1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.javax.net.ssl;
18
19import java.lang.reflect.InvocationHandler;
20import java.lang.reflect.Method;
21import java.lang.reflect.Proxy;
22import java.net.Socket;
23import javax.crypto.SecretKey;
24import javax.net.ssl.KeyManager;
25import javax.net.ssl.SSLEngine;
26
27/**
28 * Reflection-based implementation of {@code PSKKeyManager} from Conscrypt on which these tests
29 * cannot depend directly.
30 */
31class PSKKeyManagerProxy implements InvocationHandler {
32
33    static KeyManager getConscryptPSKKeyManager(PSKKeyManagerProxy delegate) {
34        Class<?> pskKeyManagerInterface;
35        try {
36            pskKeyManagerInterface = Class.forName("com.android.org.conscrypt.PSKKeyManager");
37        } catch (ClassNotFoundException e) {
38            throw new RuntimeException(e);
39        }
40        return (KeyManager) Proxy.newProxyInstance(
41                PSKKeyManagerProxy.class.getClassLoader(),
42                new Class[] {pskKeyManagerInterface},
43                delegate);
44    }
45
46    @SuppressWarnings("unused")
47    protected SecretKey getKey(String identityHint, String identity, Socket socket) {
48        return null;
49    }
50
51    @SuppressWarnings("unused")
52    protected SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
53        return null;
54    }
55
56    @SuppressWarnings("unused")
57    protected String chooseServerKeyIdentityHint(Socket socket) {
58        return null;
59    }
60
61    @SuppressWarnings("unused")
62    protected String chooseServerKeyIdentityHint(SSLEngine engine) {
63        return null;
64    }
65
66    @SuppressWarnings("unused")
67    protected String chooseClientKeyIdentity(String identityHint, Socket socket) {
68        return null;
69    }
70
71    @SuppressWarnings("unused")
72    protected String chooseClientKeyIdentity(String identityHint, SSLEngine engine) {
73        return null;
74    }
75
76    @Override
77    public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
78        String methodName = method.getName();
79        Class<?>[] parameterTypes = method.getParameterTypes();
80        boolean sslEngineVariant = (parameterTypes.length > 0)
81                && (SSLEngine.class.equals(parameterTypes[parameterTypes.length - 1]));
82        if ("getKey".equals(methodName)) {
83            if (sslEngineVariant) {
84                return getKey((String) args[0], (String) args[1], (SSLEngine) args[2]);
85            } else {
86                return getKey((String) args[0], (String) args[1], (Socket) args[2]);
87            }
88        } else if ("chooseServerKeyIdentityHint".equals(methodName)) {
89            if (sslEngineVariant) {
90                return chooseServerKeyIdentityHint((SSLEngine) args[0]);
91            } else {
92                return chooseServerKeyIdentityHint((Socket) args[0]);
93            }
94        } else if ("chooseClientKeyIdentity".equals(methodName)) {
95            if (sslEngineVariant) {
96                return chooseClientKeyIdentity((String) args[0], (SSLEngine) args[1]);
97            } else {
98                return chooseClientKeyIdentity((String) args[0], (Socket) args[1]);
99            }
100        } else {
101            throw new IllegalArgumentException("Unexpected method: " + method);
102        }
103    }
104}