10b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin/* 20b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * Copyright 2014 The Android Open Source Project 30b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * 40b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License"); 50b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * you may not use this file except in compliance with the License. 60b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * You may obtain a copy of the License at 70b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * 80b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 90b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * 100b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * Unless required by applicable law or agreed to in writing, software 110b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS, 120b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * See the License for the specific language governing permissions and 140b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * limitations under the License. 150b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin */ 160b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 170b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubinpackage org.conscrypt; 180b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 190b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubinimport java.lang.reflect.Method; 200b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubinimport java.net.Socket; 210b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubinimport javax.crypto.SecretKey; 220b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubinimport javax.net.ssl.SSLEngine; 230b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 240b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin/** 250b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * Reflection-based {@link PSKKeyManager} adaptor for objects which expose all the methods of the 260b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * {@code PSKKeyManager} interface but do not implement the interface. 270b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * 280b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * <p>This is expected to be useful on platforms where there are multiple instances of the 290b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * {@code PSKKeyManager} interface. 30bd1bbfb7034028c568bb40578d6b0d7ddbdc0f15Narayan Kamath * 31ae6e905323df3356e110c15808c7d4102da554c8Nathan Mittler * Visible for testing only. 32ae6e905323df3356e110c15808c7d4102da554c8Nathan Mittler * 33248a4d021e034705e53d9b7e1da4e927dd128b01Alex Klyubin * @deprecated This abstraction is deprecated because it does not work with TLS 1.3. 340b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin */ 35ae6e905323df3356e110c15808c7d4102da554c8Nathan Mittler@Deprecated 3629916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittlerfinal class DuckTypedPSKKeyManager implements PSKKeyManager { 370b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 380b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin private final Object mDelegate; 390b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 400b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin private DuckTypedPSKKeyManager(Object delegate) { 410b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin mDelegate = delegate; 420b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 430b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 440b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin /** 450b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * Gets an instance of {@code DuckTypedPSKKeyManager} which delegates all invocations of methods 460b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * of the {@link PSKKeyManager} interface to the same methods of the provided object. 470b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * 480b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * @throws NoSuchMethodException if {@code obj} does not implement a method of the 490b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin * {@code PSKKeyManager} interface. 500b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin */ 5129916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler static DuckTypedPSKKeyManager getInstance(Object obj) throws NoSuchMethodException { 520b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin Class<?> sourceClass = obj.getClass(); 530b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin for (Method targetMethod : PSKKeyManager.class.getMethods()) { 540b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin if (targetMethod.isSynthetic()) { 550b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin continue; 560b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 570b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin // Check that obj exposes the target method (same name and parameter types) 580b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin Method sourceMethod = 590b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin sourceClass.getMethod(targetMethod.getName(), targetMethod.getParameterTypes()); 600b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin // Check that the return type of obj's method matches the target method. 610b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin Class<?> sourceReturnType = sourceMethod.getReturnType(); 620b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin Class<?> targetReturnType = targetMethod.getReturnType(); 630b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin if (!targetReturnType.isAssignableFrom(sourceReturnType)) { 640b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new NoSuchMethodException(sourceMethod + " return value (" + sourceReturnType 650b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin + ") incompatible with target return value (" + targetReturnType + ")"); 660b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 670b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 680b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 690b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return new DuckTypedPSKKeyManager(obj); 700b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 710b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 720b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 730b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public String chooseServerKeyIdentityHint(Socket socket) { 740b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 750b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (String) mDelegate.getClass() 760b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("chooseServerKeyIdentityHint", Socket.class) 770b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, socket); 780b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 790b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke chooseServerKeyIdentityHint", e); 800b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 810b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 820b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 830b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 840b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public String chooseServerKeyIdentityHint(SSLEngine engine) { 850b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 860b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (String) mDelegate.getClass() 870b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("chooseServerKeyIdentityHint", SSLEngine.class) 880b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, engine); 890b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 900b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke chooseServerKeyIdentityHint", e); 910b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 920b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 930b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 940b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 950b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public String chooseClientKeyIdentity(String identityHint, Socket socket) { 960b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 970b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (String) mDelegate.getClass() 980b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("chooseClientKeyIdentity", String.class, Socket.class) 990b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, identityHint, socket); 1000b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 1010b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke chooseClientKeyIdentity", e); 1020b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1030b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1040b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 1050b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 1060b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public String chooseClientKeyIdentity(String identityHint, SSLEngine engine) { 1070b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 1080b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (String) mDelegate.getClass() 1090b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("chooseClientKeyIdentity", String.class, SSLEngine.class) 1100b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, identityHint, engine); 1110b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 1120b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke chooseClientKeyIdentity", e); 1130b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1140b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1150b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 1160b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 1170b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public SecretKey getKey(String identityHint, String identity, Socket socket) { 1180b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 1190b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (SecretKey) mDelegate.getClass() 1200b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("getKey", String.class, String.class, Socket.class) 1210b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, identityHint, identity, socket); 1220b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 1230b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke getKey", e); 1240b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1250b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1260b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin 1270b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin @Override 1280b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin public SecretKey getKey(String identityHint, String identity, SSLEngine engine) { 1290b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin try { 1300b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin return (SecretKey) mDelegate.getClass() 1310b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .getMethod("getKey", String.class, String.class, SSLEngine.class) 1320b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin .invoke(mDelegate, identityHint, identity, engine); 1330b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } catch (Exception e) { 1340b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin throw new RuntimeException("Failed to invoke getKey", e); 1350b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1360b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin } 1370b4bf3b34c15be6a7b3e02b4b4855049af183580Alex Klyubin} 138