blob: c6e1ae99ebed7b611a1944472f89973a59fddb22 [file] [log] [blame]
/*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conscrypt;
import java.lang.reflect.Method;
import java.net.Socket;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLEngine;
/**
* Reflection-based {@link PSKKeyManager} adaptor for objects which expose all the methods of the
* {@code PSKKeyManager} interface but do not implement the interface.
*
* <p>This is expected to be useful on platforms where there are multiple instances of the
* {@code PSKKeyManager} interface.
*
* Visible for testing only.
*
* @deprecated This abstraction is deprecated because it does not work with TLS 1.3.
*/
@Deprecated
final class DuckTypedPSKKeyManager implements PSKKeyManager {
private final Object mDelegate;
private DuckTypedPSKKeyManager(Object delegate) {
mDelegate = delegate;
}
/**
* Gets an instance of {@code DuckTypedPSKKeyManager} which delegates all invocations of methods
* of the {@link PSKKeyManager} interface to the same methods of the provided object.
*
* @throws NoSuchMethodException if {@code obj} does not implement a method of the
* {@code PSKKeyManager} interface.
*/
static DuckTypedPSKKeyManager getInstance(Object obj) throws NoSuchMethodException {
Class<?> sourceClass = obj.getClass();
for (Method targetMethod : PSKKeyManager.class.getMethods()) {
if (targetMethod.isSynthetic()) {
continue;
}
// Check that obj exposes the target method (same name and parameter types)
Method sourceMethod =
sourceClass.getMethod(targetMethod.getName(), targetMethod.getParameterTypes());
// Check that the return type of obj's method matches the target method.
Class<?> sourceReturnType = sourceMethod.getReturnType();
Class<?> targetReturnType = targetMethod.getReturnType();
if (!targetReturnType.isAssignableFrom(sourceReturnType)) {
throw new NoSuchMethodException(sourceMethod + " return value (" + sourceReturnType
+ ") incompatible with target return value (" + targetReturnType + ")");
}
}
return new DuckTypedPSKKeyManager(obj);
}
@Override
public String chooseServerKeyIdentityHint(Socket socket) {
try {
return (String) mDelegate.getClass()
.getMethod("chooseServerKeyIdentityHint", Socket.class)
.invoke(mDelegate, socket);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke chooseServerKeyIdentityHint", e);
}
}
@Override
public String chooseServerKeyIdentityHint(SSLEngine engine) {
try {
return (String) mDelegate.getClass()
.getMethod("chooseServerKeyIdentityHint", SSLEngine.class)
.invoke(mDelegate, engine);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke chooseServerKeyIdentityHint", e);
}
}
@Override
public String chooseClientKeyIdentity(String identityHint, Socket socket) {
try {
return (String) mDelegate.getClass()
.getMethod("chooseClientKeyIdentity", String.class, Socket.class)
.invoke(mDelegate, identityHint, socket);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke chooseClientKeyIdentity", e);
}
}
@Override
public String chooseClientKeyIdentity(String identityHint, SSLEngine engine) {
try {
return (String) mDelegate.getClass()
.getMethod("chooseClientKeyIdentity", String.class, SSLEngine.class)
.invoke(mDelegate, identityHint, engine);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke chooseClientKeyIdentity", e);
}
}
@Override
public SecretKey getKey(String identityHint, String identity, Socket socket) {
try {
return (SecretKey) mDelegate.getClass()
.getMethod("getKey", String.class, String.class, Socket.class)
.invoke(mDelegate, identityHint, identity, socket);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke getKey", e);
}
}
@Override
public SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
try {
return (SecretKey) mDelegate.getClass()
.getMethod("getKey", String.class, String.class, SSLEngine.class)
.invoke(mDelegate, identityHint, identity, engine);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke getKey", e);
}
}
}