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