1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import javax.net.ssl.SSLException;
19 import javax.net.ssl.SSLHandshakeException;
20 import javax.net.ssl.X509ExtendedKeyManager;
21 import javax.net.ssl.X509KeyManager;
22 import javax.security.auth.x500.X500Principal;
23 import java.security.PrivateKey;
24 import java.security.cert.X509Certificate;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30
31
32
33
34
35
36 final class OpenSslKeyMaterialManager {
37
38
39
40
41
42
43
44 static final String KEY_TYPE_RSA = "RSA";
45 static final String KEY_TYPE_DH_RSA = "DH_RSA";
46 static final String KEY_TYPE_EC = "EC";
47 static final String KEY_TYPE_EC_EC = "EC_EC";
48 static final String KEY_TYPE_EC_RSA = "EC_RSA";
49
50
51 private static final Map<String, String> KEY_TYPES = new HashMap<String, String>();
52 static {
53 KEY_TYPES.put("RSA", KEY_TYPE_RSA);
54 KEY_TYPES.put("DHE_RSA", KEY_TYPE_RSA);
55 KEY_TYPES.put("ECDHE_RSA", KEY_TYPE_RSA);
56 KEY_TYPES.put("ECDHE_ECDSA", KEY_TYPE_EC);
57 KEY_TYPES.put("ECDH_RSA", KEY_TYPE_EC_RSA);
58 KEY_TYPES.put("ECDH_ECDSA", KEY_TYPE_EC_EC);
59 KEY_TYPES.put("DH_RSA", KEY_TYPE_DH_RSA);
60 }
61
62 private final OpenSslKeyMaterialProvider provider;
63 private final boolean hasTmpDhKeys;
64
65 OpenSslKeyMaterialManager(OpenSslKeyMaterialProvider provider, boolean hasTmpDhKeys) {
66 this.provider = provider;
67 this.hasTmpDhKeys = hasTmpDhKeys;
68 }
69
70 void setKeyMaterialServerSide(ReferenceCountedOpenSslEngine engine) throws SSLException {
71 String[] authMethods = engine.authMethods();
72 if (authMethods.length == 0) {
73 throw new SSLHandshakeException("Unable to find key material");
74 }
75
76
77
78
79 Set<String> typeSet = new HashSet<String>(KEY_TYPES.size());
80 for (String authMethod : authMethods) {
81 String type = KEY_TYPES.get(authMethod);
82 if (type != null && typeSet.add(type)) {
83 String alias = chooseServerAlias(engine, type);
84 if (alias != null) {
85
86 setKeyMaterial(engine, alias);
87 return;
88 }
89 }
90 }
91 if (hasTmpDhKeys && authMethods.length == 1 &&
92 ("DH_anon".equals(authMethods[0]) || "ECDH_anon".equals(authMethods[0]))) {
93 return;
94 }
95 throw new SSLHandshakeException("Unable to find key material for auth method(s): "
96 + Arrays.toString(authMethods));
97 }
98
99 void setKeyMaterialClientSide(ReferenceCountedOpenSslEngine engine, String[] keyTypes,
100 X500Principal[] issuer) throws SSLException {
101 String alias = chooseClientAlias(engine, keyTypes, issuer);
102
103
104
105 if (alias != null) {
106 setKeyMaterial(engine, alias);
107 }
108 }
109
110 private void setKeyMaterial(ReferenceCountedOpenSslEngine engine, String alias) throws SSLException {
111 OpenSslKeyMaterial keyMaterial = null;
112 try {
113 keyMaterial = provider.chooseKeyMaterial(engine.alloc, alias);
114 if (keyMaterial == null) {
115 return;
116 }
117 engine.setKeyMaterial(keyMaterial);
118 } catch (SSLException e) {
119 throw e;
120 } catch (Exception e) {
121 throw new SSLException(e);
122 } finally {
123 if (keyMaterial != null) {
124 keyMaterial.release();
125 }
126 }
127 }
128 private String chooseClientAlias(ReferenceCountedOpenSslEngine engine,
129 String[] keyTypes, X500Principal[] issuer) {
130 X509KeyManager manager = provider.keyManager();
131 if (manager instanceof X509ExtendedKeyManager) {
132 return ((X509ExtendedKeyManager) manager).chooseEngineClientAlias(keyTypes, issuer, engine);
133 }
134 return manager.chooseClientAlias(keyTypes, issuer, null);
135 }
136
137 private String chooseServerAlias(ReferenceCountedOpenSslEngine engine, String type) {
138 X509KeyManager manager = provider.keyManager();
139 if (manager instanceof X509ExtendedKeyManager) {
140 return ((X509ExtendedKeyManager) manager).chooseEngineServerAlias(type, null, engine);
141 }
142 return manager.chooseServerAlias(type, null, null);
143 }
144 }