1 module hunt.net.secure.conscrypt.AbstractConscryptSSLContextFactory;
2 
3 // dfmt off
4 version(WITH_HUNT_SECURITY):
5 // dfmt on
6 
7 import hunt.net.secure.ProtocolSelector;
8 import hunt.net.secure.conscrypt.ConscryptALPNSelector;
9 import hunt.net.secure.SSLContextFactory;
10 import hunt.net.ssl;
11 
12 import hunt.Exceptions;
13 import hunt.stream.ByteArrayInputStream;
14 import hunt.stream.Common;
15 import hunt.logging;
16 import hunt.net.KeyCertOptions;
17 // import hunt.security.cert.X509Certificate;
18 import hunt.util.DateTime;
19 import hunt.util.TypeUtils;
20 
21 import std.array;
22 import std.datetime : Clock;
23 import std.datetime.stopwatch;
24 import std.typecons;
25 
26 
27 /**
28  * 
29  */
30 abstract class AbstractConscryptSSLContextFactory : SSLContextFactory {
31 
32     private enum string provideName = "Conscrypt";
33     private string[] supportedProtocols;
34 
35     // static this() {
36     //     // Provider provider = Conscrypt.newProvider();
37     //     // provideName = provider.getName();
38     //     // Security.addProvider(provider);
39     //     // provideName = "Conscrypt";
40     //     infof("add Conscrypt security provider");
41     // }
42 
43     // static string getProvideName() {
44     //     return provideName;
45     // }
46 
47     SSLContext getSSLContextWithManager() { // KeyManager[] km, TrustManager[] tm
48         version(HUNT_NET_DEBUG) long start = Clock.currStdTime;
49 
50         SSLContext sslContext = SSLContext.getInstance(null, "TLSv1.2");
51         // sslContext.init(km, tm); // TODO:
52 
53         version(HUNT_NET_DEBUG) {
54             long end = Clock.currStdTime;
55             long d = convert!(TimeUnit.HectoNanosecond, TimeUnit.Millisecond)(end - start);
56             tracef("creating Conscrypt SSL context spends %d ms", d);
57         }
58         return sslContext;
59     }
60 
61     // SSLContext getSSLContext(InputStream inputStream, string keystorePassword, string keyPassword) {
62     //     return getSSLContext(inputStream, keystorePassword, keyPassword, null, null, null);
63     // }
64 
65     // SSLContext getSSLContext(InputStream inputStream, string keystorePassword, string keyPassword,
66     //             string keyManagerFactoryType, string trustManagerFactoryType, string sslProtocol) {
67     //     version(HUNT_NET_DEBUG) StopWatch sw = StopWatch(AutoStart.yes);
68     //     SSLContext sslContext;
69 
70     //     // KeyStore ks = KeyStore.getInstance("JKS");
71     //     // ks.load(inputStream, keystorePassword !is null ? keystorePassword.toCharArray() : null);
72 
73     //     // // PKIX,SunX509
74     //     // KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryType is null ? "SunX509" : keyManagerFactoryType);
75     //     // kmf.init(ks, keyPassword !is null ? keyPassword.toCharArray() : null);
76 
77     //     // TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustManagerFactoryType is null ? "SunX509" : trustManagerFactoryType);
78     //     // tmf.init(ks);
79 
80     //     // TLSv1 TLSv1.2
81     //     sslContext = SSLContext.getInstance(sslProtocol.empty ? "TLSv1.2" : sslProtocol, provideName);
82     //     // sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
83 
84     //     version(HUNT_NET_DEBUG) {
85     //         sw.stop();
86     //         infof("creating Conscrypt SSL context spends %s ms", sw.peek.total!"msecs");
87     //     }
88 
89     //     implementationMissing(false);
90     //     return sslContext;
91     // }
92 
93     void initializeSslContext() {
94         implementationMissing(false);
95     }
96 
97     SSLContext getSSLContext(KeyCertOptions options, string sslProtocol) {
98         version(HUNT_NET_DEBUG) {
99             StopWatch sw = StopWatch(AutoStart.yes);
100         }
101 
102         SSLContext sslContext;
103 
104         // // PKIX,SunX509
105         // KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryType is null ? "SunX509" : keyManagerFactoryType);
106         // kmf.init(ks, keyPassword !is null ? keyPassword.toCharArray() : null);
107 
108         // TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustManagerFactoryType is null ? "SunX509" : trustManagerFactoryType);
109         // tmf.init(ks);
110 
111         // TLSv1 TLSv1.2
112         // sslContext = SSLContext.getInstance(options.getCertFile(), options.getKeyFile(), 
113         //     sslProtocol.empty ? "TLSv1.2" : sslProtocol, provideName);
114         sslContext = SSLContext.getInstance(options, sslProtocol.empty ? "TLSv1.2" : sslProtocol);
115         // sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
116         sslContext.initialize(options);
117 
118         version(HUNT_NET_DEBUG) {
119             infof("creating Conscrypt SSL context spends %s ms", sw.peek.total!"msecs");
120             sw.stop();
121         }
122         return sslContext;
123     }
124 
125     SSLContext getSSLContext() {
126         throw new NotImplementedException();
127     }
128 
129 
130     Pair!(SSLEngine, ProtocolSelector) createSSLEngine(bool clientMode) {
131         SSLEngine sslEngine = getSSLContext().createSSLEngine(clientMode);
132         // sslEngine.setUseClientMode(clientMode);
133         return makePair(sslEngine, cast(ProtocolSelector)new ConscryptALPNSelector(sslEngine, supportedProtocols));
134     }
135 
136     Pair!(SSLEngine, ProtocolSelector) createSSLEngine(bool clientMode, string peerHost, int peerPort) {
137         SSLEngine sslEngine = getSSLContext().createSSLEngine(clientMode, peerHost, peerPort);
138         // sslEngine.setUseClientMode(clientMode);
139         return makePair(sslEngine, cast(ProtocolSelector)new ConscryptALPNSelector(sslEngine, supportedProtocols));
140     }
141 
142     string[] getSupportedProtocols() {
143         return supportedProtocols;
144     }
145 
146     void setSupportedProtocols(string[] supportedProtocols) {
147         this.supportedProtocols = supportedProtocols;
148     }
149 }
150 
151 /**
152  * 
153  */
154 class NoCheckConscryptSSLContextFactory : AbstractConscryptSSLContextFactory {
155 
156     override SSLContext getSSLContext() {
157         try {
158             return getSSLContextWithManager();
159         } catch (Exception e) {
160             errorf("get SSL context error: %s", e.msg);
161             version(HUNT_DEBUG) error(e);
162             return null;
163         }
164     }
165     
166     alias getSSLContext = AbstractConscryptSSLContextFactory.getSSLContext;
167 }
168 
169 /**
170  * 
171  */
172 class FileCredentialConscryptSSLContextFactory : AbstractConscryptSSLContextFactory {
173 
174     private KeyCertOptions _options;
175 
176     this(KeyCertOptions options) {
177         this._options = options;
178     }
179 
180     override SSLContext getSSLContext() {
181         try {
182             return getSSLContext(_options, "TLSv1.2");
183         } catch (Exception e) {
184             errorf("get SSL context error: %s", e.msg);
185             version(HUNT_DEBUG) error(e);
186             return null;
187         }
188     }
189 
190     alias getSSLContext = AbstractConscryptSSLContextFactory.getSSLContext;
191 }