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
64 OpenSslKeyMaterialManager(OpenSslKeyMaterialProvider provider) {
65 this.provider = provider;
66 }
67
68 void setKeyMaterialServerSide(ReferenceCountedOpenSslEngine engine) throws SSLException {
69 String[] authMethods = engine.authMethods();
70 if (authMethods.length == 0) {
71 throw new SSLHandshakeException("Unable to find key material");
72 }
73
74
75
76
77 Set<String> typeSet = new HashSet<String>(KEY_TYPES.size());
78 for (String authMethod : authMethods) {
79 String type = KEY_TYPES.get(authMethod);
80 if (type != null && typeSet.add(type)) {
81 String alias = chooseServerAlias(engine, type);
82 if (alias != null) {
83
84 setKeyMaterial(engine, alias);
85 return;
86 }
87 }
88 }
89 throw new SSLHandshakeException("Unable to find key material for auth method(s): "
90 + Arrays.toString(authMethods));
91 }
92
93 void setKeyMaterialClientSide(ReferenceCountedOpenSslEngine engine, String[] keyTypes,
94 X500Principal[] issuer) throws SSLException {
95 String alias = chooseClientAlias(engine, keyTypes, issuer);
96
97
98
99 if (alias != null) {
100 setKeyMaterial(engine, alias);
101 }
102 }
103
104 private void setKeyMaterial(ReferenceCountedOpenSslEngine engine, String alias) throws SSLException {
105 OpenSslKeyMaterial keyMaterial = null;
106 try {
107 keyMaterial = provider.chooseKeyMaterial(engine.alloc, alias);
108 if (keyMaterial == null) {
109 return;
110 }
111 engine.setKeyMaterial(keyMaterial);
112 } catch (SSLException e) {
113 throw e;
114 } catch (Exception e) {
115 throw new SSLException(e);
116 } finally {
117 if (keyMaterial != null) {
118 keyMaterial.release();
119 }
120 }
121 }
122 private String chooseClientAlias(ReferenceCountedOpenSslEngine engine,
123 String[] keyTypes, X500Principal[] issuer) {
124 X509KeyManager manager = provider.keyManager();
125 if (manager instanceof X509ExtendedKeyManager) {
126 return ((X509ExtendedKeyManager) manager).chooseEngineClientAlias(keyTypes, issuer, engine);
127 }
128 return manager.chooseClientAlias(keyTypes, issuer, null);
129 }
130
131 private String chooseServerAlias(ReferenceCountedOpenSslEngine engine, String type) {
132 X509KeyManager manager = provider.keyManager();
133 if (manager instanceof X509ExtendedKeyManager) {
134 return ((X509ExtendedKeyManager) manager).chooseEngineServerAlias(type, null, engine);
135 }
136 return manager.chooseServerAlias(type, null, null);
137 }
138 }