1 module hunt.net.secure.conscrypt.NativeCrypto;
2 
3 
4 import std.array;
5 import std.concurrency : initOnce;
6 
7 version(Windows) {
8     import core.sys.windows.windef;
9     import core.sys.windows.winbase;
10     import core.sys.windows.winsock2;    
11 }
12 
13 /**
14 * A collection of callbacks from the native OpenSSL code that are
15  * related to the SSL handshake initiated by SSL_do_handshake.
16  */
17 interface SSLHandshakeCallbacks {
18     /**
19      * Verify that the certificate chain is trusted.
20      *
21      * @param certificateChain chain of X.509 certificates in their encoded form
22      * @param authMethod auth algorithm name
23      *
24      * @throws CertificateException if the certificate is untrusted
25      */
26     void verifyCertificateChain(byte[][] certificateChain, string authMethod);
27 
28     /**
29      * Called on an SSL client when the server requests (or
30      * requires a certificate). The client can respond by using
31      * SSL_use_certificate and SSL_use_PrivateKey to set a
32      * certificate if has an appropriate one available, similar to
33      * how the server provides its certificate.
34      *
35      * @param keyTypes key types supported by the server,
36      * convertible to strings with #keyType
37      * @param asn1DerEncodedX500Principals CAs known to the server
38      */
39     void clientCertificateRequested(byte[] keyTypes, byte[][] asn1DerEncodedX500Principals);
40 
41     /**
42      * Gets the key to be used in client mode for this connection in Pre-Shared Key (PSK) key
43      * exchange.
44      *
45      * @param identityHint PSK identity hint provided by the server or {@code null} if no hint
46      *        provided.
47      * @param identity buffer to be populated with PSK identity (NULL-terminated modified UTF-8)
48      *        by this method. This identity will be provided to the server.
49      * @param key buffer to be populated with key material by this method.
50      *
51      * @return number of bytes this method stored in the {@code key} buffer or {@code 0} if an
52      *         error occurred in which case the handshake will be aborted.
53      */
54     int clientPSKKeyRequested(string identityHint, byte[] identity, byte[] key);
55 
56     /**
57      * Gets the key to be used in server mode for this connection in Pre-Shared Key (PSK) key
58      * exchange.
59      *
60      * @param identityHint PSK identity hint provided by this server to the client or
61      *        {@code null} if no hint was provided.
62      * @param identity PSK identity provided by the client.
63      * @param key buffer to be populated with key material by this method.
64      *
65      * @return number of bytes this method stored in the {@code key} buffer or {@code 0} if an
66      *         error occurred in which case the handshake will be aborted.
67      */
68     int serverPSKKeyRequested(string identityHint, string identity, byte[] key);
69 
70     /**
71      * Called when SSL state changes. This could be handshake completion.
72      */
73     
74     void onSSLStateChange(int type, int val);
75 
76     /**
77      * Called when a new session has been established and may be added to the session cache.
78      * The callee is responsible for incrementing the reference count on the returned session.
79      */
80     
81     void onNewSessionEstablished(long sslSessionNativePtr);
82 
83     /**
84      * Called for servers where TLS < 1.3 (TLS 1.3 uses session tickets rather than
85      * application session caches).
86      *
87      * <p/>Looks up the session by ID in the application's session cache. If a valid session
88      * is returned, this callback is responsible for incrementing the reference count (and any
89      * required synchronization).
90      *
91      * @param id the ID of the session to find.
92      * @return the cached session or {@code 0} if no session was found matching the given ID.
93      */
94     
95     long serverSessionRequested(byte[] id);
96 }     
97 
98 
99 
100 
101 
102 // dfmt off
103 version(WITH_HUNT_SECURITY):
104 // dfmt on
105 
106 
107 import hunt.net.secure.conscrypt.ApplicationProtocolSelectorAdapter;
108 import hunt.net.secure.conscrypt.NativeConstants;
109 import hunt.net.secure.conscrypt.NativeRef;
110 
111 import deimos.openssl.evp;
112 import deimos.openssl.ssl;
113 import deimos.openssl.err;
114 import deimos.openssl.opensslv;
115 
116 
117 import hunt.collection;
118 import hunt.Exceptions;
119 import hunt.text.Common;
120 
121 import hunt.logging;
122 
123 import core.stdc.config;
124 import core.stdc.errno;
125 
126 import std.algorithm;
127 import std.array;
128 import std.conv;
129 import std.string;
130 import std.stdint;
131 
132 /**
133  * Provides the Java side of our JNI glue for OpenSSL.
134  * <p>
135  * Note: Many methods in this class take a reference to a Java object that holds a
136  * native pointer in the form of a long in addition to the long itself and don't use
137  * the Java object in the native implementation.  This is to prevent the Java object
138  * from becoming eligible for GC while the native method is executing.  See
139  * <a href="https://github.com/google/error-prone/blob/master/docs/bugpattern/UnsafeFinalization.md">this</a>
140  * for more details.
141  *
142  */
143 final class NativeCrypto {
144     // --- SSL handling --------------------------------------------------------
145 
146     enum string OBSOLETE_PROTOCOL_SSLV3 = "SSLv3";
147     enum string SUPPORTED_PROTOCOL_TLSV1 = "TLSv1";
148     enum string SUPPORTED_PROTOCOL_TLSV1_1 = "TLSv1.1";
149     enum string SUPPORTED_PROTOCOL_TLSV1_2 = "TLSv1.2";
150 
151     /** Protocols to enable by default when "TLSv1.2" is requested. */
152     enum string[] TLSV12_PROTOCOLS = [
153             SUPPORTED_PROTOCOL_TLSV1,
154             SUPPORTED_PROTOCOL_TLSV1_1,
155             SUPPORTED_PROTOCOL_TLSV1_2,
156     ];
157 
158     /** Protocols to enable by default when "TLSv1.1" is requested. */
159     enum string[] TLSV11_PROTOCOLS = TLSV12_PROTOCOLS;
160 
161     /** Protocols to enable by default when "TLSv1" is requested. */
162     enum string[] TLSV1_PROTOCOLS = TLSV11_PROTOCOLS;
163 
164     enum string[] DEFAULT_PROTOCOLS = TLSV12_PROTOCOLS;
165     private enum string[] SUPPORTED_PROTOCOLS = DEFAULT_PROTOCOLS;
166 
167     /**
168      * TLS_FALLBACK_SCSV is from
169      * https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00
170      * to indicate to the server that this is a fallback protocol
171      * request.
172      */
173     private enum string TLS_FALLBACK_SCSV = "TLS_FALLBACK_SCSV";
174 
175     private __gshared string[] SUPPORTED_CIPHER_SUITES;
176 
177     // SUPPORTED_CIPHER_SUITES_SET contains all the supported cipher suites, using their Java names.
178     __gshared Set!string SUPPORTED_CIPHER_SUITES_SET;
179 
180     // SUPPORTED_LEGACY_CIPHER_SUITES_SET contains all the supported cipher suites using the legacy
181     // OpenSSL-style names.
182     private __gshared Set!string SUPPORTED_LEGACY_CIPHER_SUITES_SET;
183 
184 
185     /**
186      * TLS_EMPTY_RENEGOTIATION_INFO_SCSV is RFC 5746's renegotiation
187      * indication signaling cipher suite value. It is not a real
188      * cipher suite. It is just an indication in the default and
189      * supported cipher suite lists indicates that the implementation
190      * supports secure renegotiation.
191      * <p>
192      * In the RI, its presence means that the SCSV is sent in the
193      * cipher suite list to indicate secure renegotiation support and
194      * its absense means to send an empty TLS renegotiation info
195      * extension instead.
196      * <p>
197      * However, OpenSSL doesn't provide an API to give this level of
198      * control, instead always sending the SCSV and always including
199      * the empty renegotiation info if TLS is used (as opposed to
200      * SSL). So we simply allow TLS_EMPTY_RENEGOTIATION_INFO_SCSV to
201      * be passed for compatibility as to provide the hint that we
202      * support secure renegotiation.
203      */
204     enum string TLS_EMPTY_RENEGOTIATION_INFO_SCSV = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
205 
206     static string cipherSuiteToJava(string cipherSuite) {
207         // For historical reasons, Java uses a different name for TLS_RSA_WITH_3DES_EDE_CBC_SHA.
208         if ("TLS_RSA_WITH_3DES_EDE_CBC_SHA" == cipherSuite) {
209             return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
210         }
211         return cipherSuite;
212     }
213 
214     static string cipherSuiteFromJava(string javaCipherSuite) {
215         if ("SSL_RSA_WITH_3DES_EDE_CBC_SHA" == javaCipherSuite) {
216             return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
217         }
218         return javaCipherSuite;
219     }
220 
221 
222     shared static this() {
223         SUPPORTED_CIPHER_SUITES_SET = new HashSet!string();
224         SUPPORTED_LEGACY_CIPHER_SUITES_SET = new HashSet!string();
225 
226         string[] allCipherSuites = get_cipher_names("ALL:!DHE");
227 
228         // trace(allCipherSuites);
229 
230         // get_cipher_names returns an array where even indices are the standard name and odd
231         // indices are the OpenSSL name.
232         int size = cast(int)allCipherSuites.length;
233         if (size % 2 != 0) {
234             throw new IllegalArgumentException("Invalid cipher list returned by get_cipher_names");
235         }
236         SUPPORTED_CIPHER_SUITES = new string[size / 2 + 2];
237         for (int i = 0; i < size; i += 2) {
238             string cipherSuite = cipherSuiteToJava(allCipherSuites[i]);
239             SUPPORTED_CIPHER_SUITES[i / 2] = cipherSuite;
240             SUPPORTED_CIPHER_SUITES_SET.add(cipherSuite);
241 
242             SUPPORTED_LEGACY_CIPHER_SUITES_SET.add(allCipherSuites[i + 1]);
243         }
244         SUPPORTED_CIPHER_SUITES[size / 2] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
245         SUPPORTED_CIPHER_SUITES[size / 2 + 1] = TLS_FALLBACK_SCSV;
246 
247         // trace(SUPPORTED_CIPHER_SUITES);
248     }
249 
250     static SSL* to_SSL(long ssl_address) {
251         return cast(SSL*)(cast(uintptr_t)ssl_address);
252     }
253 
254     static SSL_CTX* to_SSL_CTX(long ssl_ctx_address)    {
255         return cast(SSL_CTX*)(cast(uintptr_t)ssl_ctx_address);
256     }
257 
258     static BIO* to_SSL_BIO(long bio_address) {
259         return cast(BIO*)(cast(uintptr_t)bio_address);
260     }
261 
262     static SSL_SESSION* to_SSL_SESSION(long ssl_session_address)    {
263         return cast(SSL_SESSION*)(cast(uintptr_t)ssl_session_address);
264     }
265 
266     static SSL_CIPHER* to_SSL_CIPHER(long ssl_cipher_address) {
267         return cast(SSL_CIPHER*)(cast(uintptr_t)ssl_cipher_address);
268     }
269 
270     static AppData* toAppData(const SSL* ssl) {
271         return cast(AppData*)(SSL_get_app_data(ssl));
272     }
273 
274     static T* fromContextObject(T)(NativeRef.EVP_PKEY contextObject) {
275         if (contextObject is null) {
276             warning("contextObject is null");
277             return null;
278         }
279         return cast(T*)contextObject.context;
280     }
281 
282 
283     /**
284     * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
285     * which should take precedence.
286     */
287     static int selectApplicationProtocol(SSL* ssl, uint8_t** outBuffer, uint8_t* outLength,
288                                         const(uint8_t) * primary,
289                                         const uint primaryLength,
290                                         const(uint8_t) * secondary,
291                                         uint secondaryLength) {
292         tracef("primary=%s, length=%d", primary, primaryLength);
293 
294         int status = SSL_select_next_proto(outBuffer, outLength, primary, primaryLength, secondary,
295                                         secondaryLength);
296         switch (status) {
297             case OPENSSL_NPN_NEGOTIATED:
298                 tracef("ssl=%s selectApplicationProtocol ALPN negotiated", ssl);
299                 return SSL_TLSEXT_ERR_OK;
300             case OPENSSL_NPN_UNSUPPORTED:
301                 tracef("ssl=%s selectApplicationProtocol ALPN unsupported", ssl);
302                 break;
303             case OPENSSL_NPN_NO_OVERLAP:
304                 tracef("ssl=%s selectApplicationProtocol ALPN no overlap", ssl);
305                 break;
306             default:
307                 break;
308         }
309         return SSL_TLSEXT_ERR_NOACK;
310     }
311 
312     /**
313     * Calls out to an application-provided selector to choose the ALPN protocol.
314     */
315     static int selectApplicationProtocol(SSL* ssl, void* selector,
316                                         uint8_t** outBuffer,
317                                         uint8_t* outLen, const(uint8_t) * inBuffer,
318                                         uint inLen) {
319         // Copy the input array.
320         ubyte[] protocols = inBuffer[0..inLen].dup;
321 
322         ApplicationProtocolSelectorAdapter adapter = cast(ApplicationProtocolSelectorAdapter)selector;
323         int offset = 0;
324         if(adapter is null)
325             warning("Selector adapter is null");
326         else
327             offset = adapter.selectApplicationProtocol(protocols);
328 
329         if (offset < 0) {
330             tracef("ssl=%s selectApplicationProtocol selection failed", ssl);
331             return SSL_TLSEXT_ERR_NOACK;
332         }
333 
334         // Point the output to the selected protocol.
335         *outLen = *(inBuffer + offset);
336         *outBuffer = cast(uint8_t*)(inBuffer + offset + 1);
337 
338         return SSL_TLSEXT_ERR_OK;
339     }
340 
341     /**
342     * Callback for the server to select an ALPN protocol.
343     */
344     extern(C) static int alpn_select_callback(SSL* ssl, uint8_t ** outBuffer, uint8_t* outLen,
345                                 const(uint8_t) * inBuffer, uint inLen, void*) {
346         tracef("ssl=%s alpn_select_callback in=%s inLen=%d", ssl, inBuffer, inLen);
347 
348         AppData* appData = toAppData(ssl);
349         if (appData is null) {
350             warningf("ssl=%s alpn_select_callback appData => 0", ssl);
351             return SSL_TLSEXT_ERR_NOACK;
352         }
353 
354         if (inBuffer is null ||
355             (appData.applicationProtocolsData is null
356             && appData.applicationProtocolSelector is null)) {
357             if (outBuffer !is null && outLen !is null) {
358                 *outBuffer = null;
359                 *outLen = 0;
360             }
361             warningf("ssl=%s alpn_select_callback protocols => 0", ssl);
362             return SSL_TLSEXT_ERR_NOACK;
363         }
364 
365         if (appData.applicationProtocolSelector !is null) {
366             return selectApplicationProtocol(ssl, appData.applicationProtocolSelector,
367                                     outBuffer, outLen, inBuffer, inLen);
368         }
369 
370         return selectApplicationProtocol(ssl, outBuffer, outLen,
371                                 cast(uint8_t*)(appData.applicationProtocolsData),
372                                 cast(uint)(appData.applicationProtocolsLength),
373                                 inBuffer, inLen);
374     }
375 
376     /**
377      * Returns 1 if the BoringSSL believes the CPU has AES accelerated hardware
378      * instructions. Used to determine cipher suite ordering.
379      */
380     // static int EVP_has_aes_hardware();
381 
382     static long SSL_CTX_new()    {
383         // SSL_CTX* ctx = deimos.openssl.ssl.SSL_CTX_new(TLSv1_2_method());
384         // BUG: Reported defects -@zxp at 8/23/2018, 4:42:28 PM
385         // It doesn't work wiht TLS Server
386         // SSL_CTX* ctx = deimos.openssl.ssl.SSL_CTX_new(TLS_with_buffers_method());
387 
388         version(Have_boringssl) SSL_CTX* ctx = deimos.openssl.ssl.SSL_CTX_new(TLS_method());
389         version(Have_hunt_openssl) SSL_CTX* ctx = deimos.openssl.ssl.SSL_CTX_new(TLSv1_2_method());
390 
391         version(HUNT_NET_DEBUG_MORE) tracef("SSL_CTX_new => %s", ctx);
392         return cast(long)cast(void*)ctx;
393     }
394 
395 
396     // IMPLEMENTATION NOTE: The default list of cipher suites is a trade-off between what we'd like
397     // to use and what servers currently support. We strive to be secure enough by default. We thus
398     // avoid unacceptably weak suites (e.g., those with bulk cipher secret key shorter than 128
399     // bits), while maintaining the capability to connect to the majority of servers.
400     //
401     // Cipher suites are listed in preference order (favorite choice first) of the client. However,
402     // servers are not required to honor the order. The key rules governing the preference order
403     // are:
404     // * Prefer Forward Secrecy (i.e., cipher suites that use ECDHE and DHE for key agreement).
405     // * Prefer ChaCha20-Poly1305 to AES-GCM unless hardware support for AES is available.
406     // * Prefer AES-GCM to AES-CBC whose MAC-pad-then-encrypt approach leads to weaknesses (e.g.,
407     //   Lucky 13).
408     // * Prefer 128-bit bulk encryption to 256-bit one, because 128-bit is safe enough while
409     //   consuming less CPU/time/energy.
410     //
411     // NOTE: Removing cipher suites from this list needs to be done with caution, because this may
412     // prevent apps from connecting to servers they were previously able to connect to.
413 
414     /** X.509 based cipher suites enabled by default (if requested), in preference order. */
415     private enum bool HAS_AES_HARDWARE = false; // EVP_has_aes_hardware() == 1;
416     enum string[] DEFAULT_X509_CIPHER_SUITES = HAS_AES_HARDWARE ?
417             [
418                     "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
419                     "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
420                     "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
421                     "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
422                     "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
423                     "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
424                     "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
425                     "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
426                     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
427                     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
428                     "TLS_RSA_WITH_AES_128_GCM_SHA256",
429                     "TLS_RSA_WITH_AES_256_GCM_SHA384",
430                     "TLS_RSA_WITH_AES_128_CBC_SHA",
431                     "TLS_RSA_WITH_AES_256_CBC_SHA",
432             ] :
433             [
434                     "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
435                     "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
436                     "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
437                     "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
438                     "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
439                     "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
440                     "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
441                     "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
442                     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
443                     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
444                     "TLS_RSA_WITH_AES_128_GCM_SHA256",
445                     "TLS_RSA_WITH_AES_256_GCM_SHA384",
446                     "TLS_RSA_WITH_AES_128_CBC_SHA",
447                     "TLS_RSA_WITH_AES_256_CBC_SHA",
448             ];
449 
450     /** TLS-PSK cipher suites enabled by default (if requested), in preference order. */
451     enum string[] DEFAULT_PSK_CIPHER_SUITES = [
452             "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
453             "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
454             "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
455             "TLS_PSK_WITH_AES_128_CBC_SHA",
456             "TLS_PSK_WITH_AES_256_CBC_SHA",
457     ];
458 
459     static string[] getSupportedCipherSuites() {
460         return SUPPORTED_CIPHER_SUITES.dup;
461     }
462 
463     // static void SSL_CTX_free(long ssl_ctx);
464 
465     // static void SSL_CTX_set_session_id_context(long ssl_ctx, byte[] sid_ctx);
466 
467     // static long SSL_CTX_set_timeout(long ssl_ctx, long seconds);
468 
469     static long SSL_new(long ssl_ctx_address) {
470         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
471         if (ssl_ctx is null) {
472             return 0;
473         }
474         SSL* ssl = deimos.openssl.ssl.SSL_new(ssl_ctx);
475         if (ssl is null) {
476             warning("Unable to create SSL structure");
477             tracef("ssl_ctx=%s SSL_new => null", ssl_ctx);
478             return 0;
479         }
480 
481         version(HUNT_DEBUG_MORE) tracef("SSL_new => %s", ssl);
482 
483         /*
484         * Create our special application data.
485         */
486         AppData* appData = AppData.create();
487         if (appData is null) {
488             warning("Unable to create application data");
489             deimos.openssl.err.ERR_clear_error();
490             warning("ssl_ctx=%s SSL_new appData => 0", ssl_ctx);
491             return 0;
492         }
493         appData.name = "<<SSL_new>>";
494         deimos.openssl.ssl.SSL_set_app_data(ssl, cast(char*)(appData));
495 
496         version(Have_boringssl) SSL_set_custom_verify(ssl, SSL_VERIFY_PEER, &cert_verify_callback);
497 
498         version(HUNT_DEBUG_MORE) 
499             tracef("ssl_ctx=%s SSL_new => ssl=%s appData=%s", ssl_ctx, ssl, appData);
500         return cast(long)ssl;        
501     }
502 
503     // static void SSL_CTX_set_ecdh_auto(long ssl_ctx_address, bool flag=true) {
504     //     SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
505     //     if(ssl_ctx is null)
506     //         return;
507 
508     //     deimos.openssl.ssl.SSL_CTX_set_ecdh_auto(ssl_ctx, flag ? 1 : 0);
509     // }
510 
511     /**
512      * 
513      */
514     static void SSL_CTX_load_verify_locations(long ssl_ctx_address, string CAfile, string CApath) {
515         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
516         if(ssl_ctx is null) {
517             warningf("ssl is null");
518             return;
519         }
520         deimos.openssl.ssl.SSL_CTX_load_verify_locations(ssl_ctx, toStringz(CAfile), toStringz(CApath));
521     }
522 
523 
524     /**
525      * Sets certificate expectations, especially for server to request client auth
526      */
527     static void SSL_CTX_set_verify(long ssl_ctx_address, int mode) {
528         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
529         if (ssl_ctx is null) {
530             warningf("ssl is null");
531             return;
532         }
533         deimos.openssl.ssl.SSL_CTX_set_verify(ssl_ctx, mode, null);
534     }
535 
536     static void SSL_CTX_use_certificate_file(long ssl_ctx_address, string fileName) {
537         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
538         if(ssl_ctx is null)
539             return;
540         
541         int r = deimos.openssl.ssl.SSL_CTX_use_certificate_file(ssl_ctx, toStringz(fileName), SSL_FILETYPE_PEM);
542         if(r <=0)   {
543             warning("Failed to set the certificate file.");
544         }
545     }
546 
547     static void SSL_CTX_use_PrivateKey_file(long ssl_ctx_address, string fileName) {
548         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
549         if(ssl_ctx is null)
550             return;
551 
552         int r = deimos.openssl.ssl.SSL_CTX_use_PrivateKey_file(ssl_ctx, toStringz(fileName),  SSL_FILETYPE_PEM);
553         if(r <=0)   {
554             warning("Failed to set the privateKey file.");
555         }
556     }
557 
558 
559     static bool SSL_CTX_check_private_key(long ssl_ctx_address) {
560         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
561         if(ssl_ctx is null)
562             return false;
563 
564         int r = deimos.openssl.ssl.SSL_CTX_check_private_key(ssl_ctx);
565         return r == 1;
566     }
567 
568     
569 
570     static void SSL_enable_tls_channel_id(long ssl_address) {
571         SSL* ssl = to_SSL(ssl_address);
572         if (ssl is null) {
573             return;
574         }
575 
576         implementationMissing(false);
577         // NOLINTNEXTLINE(runtime/int)
578         // long ret = deimos.openssl.ssl.SSL_enable_tls_channel_id(ssl);
579         // if (ret != 1L) {
580         //     char* str = ERR_error_string(ERR_peek_error(), null);
581         //     errorf("%s", fromstringz(str));
582         //     return;
583         // }
584     }
585 
586     static byte[] SSL_get_tls_channel_id(long ssl_address) {
587         SSL* ssl = to_SSL(ssl_address);
588         if (ssl is null) {
589             return null;
590         }
591 
592         // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
593         // as a constant anywhere.
594         ubyte[] bytes = new ubyte[64];
595         
596 implementationMissing(false);
597 return null;
598 
599         // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
600         // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
601         // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
602         // size_t ret = deimos.openssl.ssl.SSL_get_tls_channel_id(ssl, bytes.ptr, 64);
603         // if (ret == 0) {
604         //     // Channel ID either not set or did not verify
605         //     tracef("SSL_get_tls_channel_id(%s) => not available", ssl);
606         //     return null;
607         // } else if (ret != 64) {
608         //     CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), null));
609         //     conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
610         //                                                     "Error getting Channel ID");
611         //     tracef("ssl=%s SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
612         //     return null;
613         // }
614 
615         // return javaBytes;        
616     }
617 
618     static void SSL_set1_tls_channel_id(long ssl_address, NativeRef.EVP_PKEY pkey) {
619         SSL* ssl = to_SSL(ssl_address);
620         if (ssl is null) {
621             return;
622         }
623 implementationMissing(false);
624         // EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
625         // if (pkey is null) {
626         //     tracef("ssl=%s SSL_set1_tls_channel_id => pkey is null", ssl);
627         //     return;
628         // }
629 
630         // // NOLINTNEXTLINE(runtime/int)
631         // long ret = SSL_set1_tls_channel_id(ssl, pkey);
632 
633         // if (ret != 1L) {
634         //     CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), null));
635         //     conscrypt::jniutil::throwSSLExceptionWithSslErrors(
636         //             env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
637         //     tracef("ssl=%s SSL_set1_tls_channel_id => error", ssl);
638         //     return;
639         // }
640 
641         // tracef("ssl=%s SSL_set1_tls_channel_id => ok", ssl);        
642     }
643 
644     // static void SSL_set_client_CA_list(long ssl_address, byte[][] asn1DerEncodedX500Principals)
645     //         ;
646 
647     static long SSL_set_mode(long ssl_address, long mode) {
648         SSL* ssl = to_SSL(ssl_address);
649         // NOLINTNEXTLINE(runtime/int)
650         if (ssl is null) {
651             return 0;
652         }
653         long result = cast(long)(deimos.openssl.ssl.SSL_set_mode(ssl, cast(uint32_t)(mode)));
654         // NOLINTNEXTLINE(runtime/int)
655         return result;        
656     }
657 
658     static long SSL_set_options(long ssl_address, long options) {
659         SSL* ssl = to_SSL(ssl_address);
660         // NOLINTNEXTLINE(runtime/int)
661         if (ssl is null) {
662             return 0;
663         }
664         long result = cast(long)(deimos.openssl.ssl.SSL_set_options(ssl, cast(uint)(options)));
665         // NOLINTNEXTLINE(runtime/int)
666         // JNI_TRACE("ssl=%s SSL_set_options => 0x%lx", ssl, (long)result);
667         return result;        
668     }
669 
670     static long SSL_clear_options(long ssl_address, long options) {
671         SSL* ssl = to_SSL(ssl_address);
672         // NOLINTNEXTLINE(runtime/int)
673         if (ssl is null) {
674             return 0;
675         }
676         long result = cast(long)(deimos.openssl.ssl.SSL_clear_options(ssl, cast(uint32_t)(options)));
677         // NOLINTNEXTLINE(runtime/int)
678         return result;        
679     }
680 
681     static int SSL_set_protocol_versions(long ssl_address, int min_version, int max_version) {
682         SSL* ssl = to_SSL(ssl_address);
683         if (ssl is null) {
684             return 0;
685         }
686         // TODO: Tasks pending completion -@zxp at 8/2/2018, 3:03:24 PM
687         // 
688         return 1;
689         // int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
690         // int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
691         // // Return failure if either call failed.
692         // int result = 1;
693         // if (!min_result || !max_result) {
694         //     result = 0;
695         //     // The only possible error is an invalid version, so we don't need the details.
696         //     ERR_clear_error();
697         // }
698         // tracef("ssl=%s SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl, min_result, max_result, result);
699         // return result;        
700     }
701 
702     static byte[] SSL_get_signed_cert_timestamp_list(long ssl_address) {
703         SSL* ssl = to_SSL(ssl_address);
704         if (ssl is null) {
705             return null;
706         }
707 implementationMissing(false);
708 return null;
709         // const uint8_t* data;
710         // size_t data_len;
711         // SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
712 
713         // if (data_len == 0) {
714         //     tracef("SSL_get_signed_cert_timestamp_list(%s) => null", ssl);
715         //     return null;
716         // }
717 
718         // jbyteArray result = env.NewByteArray(static_cast<jsize>(data_len));
719         // if (result !is null) {
720         //     env.SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
721         // }
722         // return result;        
723     }
724 
725     static void SSL_set_signed_cert_timestamp_list(long ssl_address, byte[] list) {
726         SSL* ssl = to_SSL(ssl_address);
727         if (ssl is null) {
728             return;
729         }
730         
731         implementationMissing(false);
732 
733         // if (!deimos.openssl.ssl.SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
734         //                                         listBytes.size())) {
735         //     warningf("ssl=%s SSL_set_signed_cert_timestamp_list => fail", ssl);
736         // } else {
737         //     infof("ssl=%s SSL_set_signed_cert_timestamp_list => ok", ssl);
738         // }        
739     }
740 
741     static byte[] SSL_get_ocsp_response(long ssl_address) {
742         SSL* ssl = to_SSL(ssl_address);
743         if (ssl is null) {
744             return null;
745         }
746         implementationMissing(false);
747         return null;
748 
749         // const uint8_t* data;
750         // size_t data_len;
751         // SSL_get0_ocsp_response(ssl, &data, &data_len);
752 
753         // if (data_len == 0) {
754         //     JNI_TRACE("SSL_get_ocsp_response(%s) => null", ssl);
755         //     return null;
756         // }
757 
758         // ScopedLocalRef<jbyteArray> byteArray(env, env.NewByteArray(static_cast<jsize>(data_len)));
759         // if (byteArray.get() is null) {
760         //     JNI_TRACE("SSL_get_ocsp_response(%s) => creating byte array failed", ssl);
761         //     return null;
762         // }
763 
764         // env.SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
765         // JNI_TRACE("SSL_get_ocsp_response(%s) => %s [size=%zd]", ssl, byteArray.get(),
766         //         data_len);
767 
768         // return byteArray.release();        
769     }
770 
771     static void SSL_set_ocsp_response(long ssl_address, byte[] response) {
772         SSL* ssl = to_SSL(ssl_address);
773         if (ssl is null) {
774             return;
775         }
776         implementationMissing(false);
777 
778         // ScopedByteArrayRO responseBytes(env, response);
779         // if (responseBytes.get() is null) {
780         //     JNI_TRACE("ssl=%s SSL_set_ocsp_response => response is null", ssl);
781         //     return;
782         // }
783 
784         // if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
785         //                         responseBytes.size())) {
786         //     JNI_TRACE("ssl=%s SSL_set_ocsp_response => fail", ssl);
787         // } else {
788         //     JNI_TRACE("ssl=%s SSL_set_ocsp_response => ok", ssl);
789         // }      
790     }
791 
792     // static byte[] SSL_get_tls_unique(long ssl_address);
793 
794     // static void SSL_set_token_binding_params(long ssl_address, int[] params) ;
795 
796     // static int SSL_get_token_binding_params(long ssl_address);
797 
798     // static byte[] SSL_export_keying_material(long ssl_address, byte[] label, byte[] context, int num_bytes) ;
799 
800     // static void SSL_use_psk_identity_hint(long ssl_address, string identityHint) ;
801 
802     // static void set_SSL_psk_client_callback_enabled(long ssl_address, bool enabled);
803 
804     // static void set_SSL_psk_server_callback_enabled(long ssl_address, bool enabled);
805 
806 
807     static void SSL_SESSION_free(long sslSessionNativePointer)    {
808         SSL_SESSION* ssl_session = to_SSL_SESSION(sslSessionNativePointer);
809         if(ssl_session is null)
810             return ;
811         
812         deimos.openssl.ssl.SSL_SESSION_free(ssl_session);
813     }
814 
815     static void SSL_CTX_set_session_id_context(long ssl_ctx_address, byte[] sid_ctx)    {
816         SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
817         if(ssl_ctx is null)
818         {
819             return;
820         }
821 
822         int result = deimos.openssl.ssl.SSL_CTX_set_session_id_context(ssl_ctx, 
823             cast(const(ubyte) *) sid_ctx.ptr, cast(uint)sid_ctx.length );
824         if (result == 0) {
825             error("");
826         }
827         // else
828         // {
829 
830         // }
831 
832     }
833 
834     static byte[] SSL_SESSION_session_id(long sslSessionNativePointer)    {
835         SSL_SESSION* ssl_session = to_SSL_SESSION(sslSessionNativePointer);
836         if(ssl_session is null)
837             return null;
838 
839         uint len;
840         const(ubyte)* id_ptr = deimos.openssl.ssl.SSL_SESSION_get_id(ssl_session, &len);
841         if(id_ptr is null)
842             return null;
843         else
844             return cast(byte[])id_ptr[0..len];
845     }
846 
847     static long SSL_SESSION_get_time(long sslSessionNativePointer)    {
848         SSL_SESSION* ssl_session = to_SSL_SESSION(sslSessionNativePointer);
849         if(ssl_session is null)
850             return 0;
851 
852         // result must be jlong, not long or *1000 will overflow
853         c_long result = deimos.openssl.ssl.SSL_SESSION_get_time(ssl_session);
854 
855         result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
856         return result;
857     }
858 
859 
860     static string[] get_cipher_names(string selector) {
861         if (selector.empty) {
862             warning("selector is null");
863             return null;
864         }
865 
866         version(Have_boringssl) 
867         SSL_CTX* sslCtx = deimos.openssl.ssl.SSL_CTX_new(TLS_with_buffers_method());
868 
869         version(Have_hunt_openssl)
870         SSL_CTX* sslCtx = deimos.openssl.ssl.SSL_CTX_new(TLSv1_2_method());
871 
872         scope(exit) {
873             deimos.openssl.ssl.SSL_CTX_free(sslCtx);
874         }
875 
876         SSL* ssl = deimos.openssl.ssl.SSL_new(sslCtx);
877         scope(exit) {
878             deimos.openssl.ssl.SSL_free(ssl);
879         }
880         if (!SSL_set_cipher_list(ssl, selector.toStringz())) {
881             warning("Unable to set SSL cipher list");
882             return null;
883         }
884 
885         STACK_OF!(SSL_CIPHER)* ciphers = deimos.openssl.ssl.SSL_get_ciphers(ssl);
886 
887         int size = sk_SSL_CIPHER_num(ciphers);
888         string[] cipherNamesArray = new string[size*2];
889 
890         // Return an array of standard and OpenSSL name pairs.
891         for (int i = 0; i < size; i++) {
892             const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
893             string opensslName = cast(string)fromStringz(SSL_CIPHER_get_name(cipher));
894 
895             version(Have_boringssl) {
896                 string cipherName = cast(string)fromStringz(SSL_CIPHER_standard_name(cipher));
897             } else version(Have_hunt_openssl) {
898                 static if (OPENSSL_VERSION_BEFORE(1, 1, 1)) { 
899                     string cipherName = toTlsCipherName(opensslName);
900                 } else {
901                     string cipherName = cast(string)fromStringz(SSL_CIPHER_standard_name(cipher));
902                 }
903 
904             }
905             cipherNamesArray[2 * i] = cipherName;
906             cipherNamesArray[2 * i + 1] = opensslName;
907         }
908 
909         version(HUNT_DEBUG_MORE)
910             tracef("get_cipher_names(%s) => success (%d entries)", selector, cipherNamesArray.length);
911         return cipherNamesArray;     
912         
913     }
914 
915 static if (OPENSSL_VERSION_BEFORE(1, 1, 1)) {
916 
917     static string toTlsCipherName(string cipherName) {
918         string name = cipherName;
919         string[] talbe = tls_cipher_name_translation_table;
920         for(int i=0; i<talbe.length; i+=2) {
921             if(talbe[i] == cipherName) {
922                 name = talbe[i+1].replace("-", "_");
923             }
924         }
925 
926         return name;
927     }
928 
929 }
930     // static byte[] get_ocsp_single_extension(
931     //         byte[] ocspResponse, string oid, long x509Ref, OpenSSLX509Certificate holder, long issuerX509Ref, OpenSSLX509Certificate holder2);
932 
933     /**
934      * Returns the starting address of the memory region referenced by the provided direct
935      * {@link Buffer} or {@code 0} if the provided buffer is not direct or if such access to direct
936      * buffers is not supported by the platform.
937      *
938      * <p>NOTE: This method ignores the buffer's current {@code position}.
939      */
940     // static long getDirectBufferAddress(Buffer buf) {
941     //     return cast(int)<jlong>(env.GetDirectBufferAddress(buffer));
942     // }
943 
944     static long SSL_BIO_new(long ssl_address)
945     {
946         SSL* ssl = to_SSL(ssl_address);
947         if (ssl is null) {
948             return 0;
949         }
950 
951         BIO* internal_bio;
952         BIO* network_bio;
953         if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
954             errorf("ssl=%s SSL_BIO_new => BIO_new_bio_pair exception", ssl);
955             return 0;
956         }
957 
958         version(HUNT_DEBUG_MORE) tracef("SSL_BIO_new => %s", network_bio);
959 
960         SSL_set_bio(ssl, internal_bio, internal_bio);
961 
962         return cast(long)(network_bio);
963     }
964 
965     static int SSL_get_error(long ssl_address, int ret) {
966         SSL* ssl = to_SSL(ssl_address);
967         if (ssl is null) {
968             return 0;
969         }
970         return deimos.openssl.ssl.SSL_get_error(ssl, ret);        
971     }
972 
973     static void SSL_clear_error() {
974         ERR_clear_error();
975     }
976 
977     static int SSL_pending_readable_bytes(long ssl_address) {
978         SSL* ssl = to_SSL(ssl_address);
979         if (ssl is null) {
980             return 0;
981         }
982         return SSL_pending(ssl);        
983     }
984 
985     static int SSL_pending_written_bytes_in_BIO(long bio_address)
986     {
987         BIO* bio = to_SSL_BIO(bio_address);
988         if (bio is null) {
989             return 0;
990         }
991         int r = cast(int)(BIO_ctrl_pending(bio));
992         return r;
993     }
994 
995     /**
996      * Enables ALPN for this TLS endpoint and sets the list of supported ALPN protocols in
997      * wire-format (length-prefixed 8-bit strings).
998      */
999     static void setApplicationProtocols(long ssl_address, bool client_mode, ubyte[] protocols) {
1000         SSL* ssl = to_SSL(ssl_address);
1001         if (ssl is null) {
1002             return;
1003         }
1004 
1005         AppData* appData = toAppData(ssl);
1006         if (appData is null) {
1007             error("Unable to retrieve application data");
1008             return;
1009         }
1010 
1011         if (protocols is null) 
1012             return;
1013 
1014         version(HUNT_DEBUG_MORE) tracef("protocols: %(%02X %)", protocols[0 .. $]);
1015 
1016         if (client_mode) {
1017             const(ubyte)* tmp = cast(const(ubyte)*)protocols.ptr;
1018             version(Have_boringssl) 
1019             int ret = deimos.openssl.ssl.SSL_set_alpn_protos(ssl, tmp, cast(uint)(protocols.length));
1020             version(Have_hunt_openssl) {
1021                 version(HUNT_DEBUG_MORE) implementationMissing(false);
1022                 int ret=0;
1023             }
1024             if (ret != 0) {
1025                 warning("Unable to set ALPN protocols for client");
1026                 return;
1027             }
1028         } else {
1029             // Server mode - configure the ALPN protocol selection callback.
1030             if (!appData.setApplicationProtocols(protocols)) {
1031                 warning("Unable to set ALPN protocols for server");
1032                 return;
1033             }
1034             SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
1035 
1036             version(HUNT_DEBUG_MORE) implementationMissing(false);
1037             // SSL_CTX_set_alpn_select_cb(ctx, alpn_select_callback, null);
1038         }
1039     }
1040 
1041     /**
1042      * Called for a server endpoint only. Enables ALPN and sets a BiFunction that will
1043      * be called to delegate protocol selection to the application. Calling this method overrides
1044      * {@link #setApplicationProtocols(long, NativeSsl, bool, byte[])}.
1045      */
1046     static void setApplicationProtocolSelector(long ssl_address, ApplicationProtocolSelectorAdapter selector) {
1047         SSL* ssl = to_SSL(ssl_address);
1048         if (ssl is null) {
1049             return;
1050         }
1051 
1052         AppData* appData = toAppData(ssl);
1053         if (appData is null) {
1054             warning("Unable to retrieve application data");
1055             return;
1056         }
1057 
1058         appData.setApplicationProtocolSelector(cast(void*)selector);
1059         if (selector !is null) {
1060             version(Have_boringssl) SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), &alpn_select_callback, null);
1061             // FIXME: Needing refactor or cleanup -@zxp at 8/8/2019, 4:38:40 PM
1062             // 
1063             // version(Have_hunt_openssl) implementationMissing(false);
1064         }
1065     }
1066 
1067     /**
1068      * Returns the selected ALPN protocol. If the server did not select a
1069      * protocol, {@code null} will be returned.
1070      */
1071     static byte[] getApplicationProtocol(long ssl_address) {
1072         SSL* ssl = to_SSL(ssl_address);
1073         if (ssl is null) {
1074             return null;
1075         }
1076 
1077         version(HUNT_DEBUG_MORE) implementationMissing(false);
1078         return null;
1079         // const jbyte* protocol;
1080         // unsigned int protocolLength;
1081         // SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
1082         //                     &protocolLength);
1083         // if (protocolLength == 0) {
1084         //     return null;
1085         // }
1086         // jbyteArray result = env.NewByteArray(static_cast<jsize>(protocolLength));
1087         // if (result !is null) {
1088         //     env.SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
1089         // }
1090         // return result;
1091     }
1092 
1093     /**
1094      * Variant of the {@link #SSL_do_handshake} used by {@link ConscryptEngine}. This differs
1095      * slightly from the raw BoringSSL API in that it returns the SSL error code from the
1096      * operation, rather than the return value from {@code SSL_do_handshake}. This is done in
1097      * order to allow to properly handle SSL errors and propagate useful exceptions.
1098      *
1099      * @return Returns the SSL error code for the operation when the error was {@code
1100      * SSL_ERROR_NONE}, {@code SSL_ERROR_WANT_READ}, or {@code SSL_ERROR_WANT_WRITE}.
1101      * @ when the error code is anything except those returned by this method.
1102      */
1103     static int ENGINE_SSL_do_handshake(long ssl_address, SSLHandshakeCallbacks shc) {
1104         SSL* ssl = to_SSL(ssl_address);
1105         if (ssl is null) {
1106             return 0;
1107         }
1108 
1109         if (shc is null) {
1110             warning("sslHandshakeCallbacks is null");
1111             return 0;
1112         }
1113 
1114         AppData* appData = toAppData(ssl);
1115         if (appData is null) {
1116             warning("Unable to retrieve application data");
1117             return 0;
1118         }
1119 
1120         errno = 0;
1121 
1122         if (!appData.setCallbackState(cast(void*)shc, cast(void*)null)) {
1123             warning("Unable to set appdata callback");
1124             ERR_clear_error();
1125             return 0;
1126         }
1127 
1128         int ret = deimos.openssl.ssl.SSL_do_handshake(ssl);
1129         appData.clearCallbackState();
1130 
1131         int code = SSL_ERROR_NONE;
1132         if(ret<=0)
1133             code = deimos.openssl.ssl.SSL_get_error(ssl, ret);
1134 
1135         if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
1136             // Non-exceptional case.
1137             version(HUNT_DEBUG_MORE) tracef("ssl=%s ENGINE_SSL_do_handshake => ret=%d", ssl, code);
1138             return code;
1139         }
1140 
1141         // Exceptional case...
1142         if (ret == 0) {
1143             // TODO(nmittler): Can this happen with memory BIOs?
1144             /*
1145             * Clean error. See SSL_do_handshake(3SSL) man page.
1146             * The other side closed the socket before the handshake could be
1147             * completed, but everything is within the bounds of the TLS protocol.
1148             * We still might want to find out the real reason of the failure.
1149             */
1150             if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
1151                 (code == SSL_ERROR_ZERO_RETURN)) {
1152                 warning("Connection closed by peer");
1153             } else {
1154                 warning("SSL handshake terminated");
1155             }
1156             return code;
1157         }
1158 
1159         /*
1160         * Unclean error. See SSL_do_handshake(3SSL) man page.
1161         * Translate the error and throw exception. We are sure it is an error
1162         * at this point.
1163         */
1164         warning("SSL handshake aborted");
1165         return code;        
1166     }
1167 
1168     /**
1169      * Variant of the {@link #SSL_read} for a direct {@link java.nio.ByteBuffer} used by {@link
1170      * ConscryptEngine}.
1171      *
1172      * @return if positive, represents the number of bytes read into the given buffer.
1173      * Returns {@code -SSL_ERROR_WANT_READ} if more data is needed. Returns
1174      * {@code -SSL_ERROR_WANT_WRITE} if data needs to be written out to flush the BIO.
1175      *
1176      * @throws java.io.InterruptedIOException if the read was interrupted.
1177      * @throws java.io.EOFException if the end of stream has been reached.
1178      * @throws CertificateException if the application's certificate verification callback failed.
1179      * Only occurs during handshake processing.
1180      * @ if any other error occurs.
1181      */
1182     static int ENGINE_SSL_read_direct(long ssl_address, long address, int length,
1183             SSLHandshakeCallbacks shc) {
1184         SSL* ssl = to_SSL(ssl_address);
1185         char* destPtr = cast(char*)(address);
1186         if (ssl is null) {
1187             return -1;
1188         }
1189 
1190         if (shc is null) {
1191             warning("sslHandshakeCallbacks is null");
1192             return -1;
1193         }
1194 
1195         // AppData* appData = toAppData(ssl);
1196         // if (appData is null) {
1197         //     warning("Unable to retrieve application data");
1198         //     return -1;
1199         // }
1200         // if (!appData.setCallbackState(env, shc, null)) {
1201         //     warning("Unable to set appdata callback");
1202         //     ERR_clear_error();
1203         //     return -1;
1204         // }
1205 
1206         errno = 0;
1207 
1208         int result = deimos.openssl.ssl.SSL_read(ssl, destPtr, length);
1209         // appData.clearCallbackState();
1210         // if (env.ExceptionCheck()) {
1211         //     // An exception was thrown by one of the callbacks. Just propagate that exception.
1212         //     ERR_clear_error();
1213         //     JNI_TRACE("ssl=%s ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
1214         //     return -1;
1215         // }
1216 
1217         int sslErrorCode = SSL_ERROR_NONE;
1218         if(result<=0)
1219             sslErrorCode = deimos.openssl.ssl.SSL_get_error(ssl, result);
1220 
1221         switch (sslErrorCode) {
1222             case SSL_ERROR_NONE: {
1223                 // Successfully read at least one byte. Just return the result.
1224                 break;
1225             }
1226             case SSL_ERROR_ZERO_RETURN: {
1227                 // A close_notify was received, this stream is finished.
1228                 return -SSL_ERROR_ZERO_RETURN;
1229             }
1230             case SSL_ERROR_WANT_READ:
1231             case SSL_ERROR_WANT_WRITE: {
1232                 // Return the negative of these values.
1233                 result = -result;
1234                 break;
1235             }
1236             case SSL_ERROR_SYSCALL: {
1237                 // A problem occurred during a system call, but this is not
1238                 // necessarily an error.
1239                 if (result == 0) {
1240                     // TODO(nmittler): Can this happen with memory BIOs?
1241                     // Connection closed without proper shutdown. Tell caller we
1242                     // have reached end-of-stream.
1243                     warning("EOFException: ", "Read error");
1244                     break;
1245                 }
1246 
1247                 if (errno == EINTR) {
1248                     // TODO(nmittler): Can this happen with memory BIOs?
1249                     // System call has been interrupted. Simply retry.
1250                     warning("InterruptedIOException: ", "Read error");
1251                     break;
1252                 }
1253 
1254                 // Note that for all other system call errors we fall through
1255                 // to the default case, which results in an Exception.
1256                 // FALLTHROUGH_INTENDED;
1257                 error("Read error");
1258                 break;
1259             }
1260             default: {
1261                 // Everything else is basically an error.
1262                 error("Read error");
1263                 break;
1264             }
1265         }
1266 
1267         version(HUNT_NET_DEBUG_MORE) {
1268             tracef("ssl=%s ENGINE_SSL_read_direct address=%s length=%d result=%d",
1269                     ssl, destPtr, length,  result);
1270         }
1271         version(HUNT_NET_DEBUG_MORE) {
1272             if(result>16)
1273                 tracef("%(%02X %)", cast(ubyte[])destPtr[0..16]);
1274             else
1275                 tracef("%(%02X %)", cast(ubyte[])destPtr[0..result]);
1276         }
1277         return result;
1278     }
1279 
1280     /**
1281      * Variant of the {@link #SSL_write} for a direct {@link java.nio.ByteBuffer} used by {@link
1282      * ConscryptEngine}. This version does not lock or and does no error pre-processing.
1283      */
1284     static int ENGINE_SSL_write_direct(long ssl_address, long address, int len,
1285             SSLHandshakeCallbacks shc) {
1286 
1287         SSL* ssl = to_SSL(ssl_address);
1288         const char* sourcePtr = cast(const char*)(address);
1289         if (ssl is null) {
1290             return -1;
1291         }
1292 
1293         if (shc is null) {
1294             warning("sslHandshakeCallbacks is null");
1295             return -1;
1296         }
1297 
1298         // AppData* appData = toAppData(ssl);
1299         // if (appData is null) {
1300         //     warning("Unable to retrieve application data");
1301         //     ERR_clear_error();
1302         //     return -1;
1303         // }
1304         // if (!appData.setCallbackState(env, shc, null)) {
1305         //     warning("Unable to set appdata callback");
1306         //     ERR_clear_error();
1307         //     return -1;
1308         // }
1309 
1310         errno = 0;
1311 
1312         int result = SSL_write(ssl, sourcePtr, len);
1313         // appData.clearCallbackState();
1314         version(HUNT_NET_DEBUG_MORE) tracef("ssl=%s ENGINE_SSL_write_direct address=%s length=%d shc=%s => ret=%d",
1315                 ssl, sourcePtr, len, shc, result);
1316         return result;
1317     }
1318 
1319     /**
1320      * Writes data from the given direct {@link java.nio.ByteBuffer} to the BIO.
1321      */
1322     static int ENGINE_SSL_write_BIO_direct(long ssl_address, long bioRef, long address, int len,
1323             SSLHandshakeCallbacks shc) {
1324 
1325         SSL* ssl = to_SSL(ssl_address);
1326         if (ssl is null) {
1327             return -1;
1328         }
1329         if (shc is null) {
1330             warning("sslHandshakeCallbacks is null");
1331             return -1;
1332         }
1333         BIO* bio = to_SSL_BIO(bioRef);
1334         if (bio is null) {
1335             return -1;
1336         }
1337         if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < cast(size_t)(len)) {
1338             // The network BIO couldn't handle the entire write. Don't write anything, so that we
1339             // only process one packet at a time.
1340             return 0;
1341         }
1342         const char* sourcePtr = cast(const char*)(address);
1343 
1344 // TODO: Tasks pending completion -@zxp at 8/2/2018, 9:45:01 AM
1345 // 
1346         // AppData* appData = toAppData(ssl);
1347         // if (appData is null) {
1348         //     warning("Unable to retrieve application data");
1349         //     ERR_clear_error();
1350         //     return -1;
1351         // }
1352         // if (!appData.setCallbackState(shc, null)) {
1353         //     warning("Unable to set appdata callback");
1354         //     ERR_clear_error();
1355         //     return -1;
1356         // }
1357 
1358         errno = 0;
1359 
1360         int result = deimos.openssl.ssl.BIO_write(bio, sourcePtr, len);
1361         // appData.clearCallbackState();
1362         version(HUNT_NET_DEBUG_MORE) tracef("ssl=%s ENGINE_SSL_write_BIO_direct bio=%s sourcePtr=%s len=%d => ret=%d",
1363                 ssl, bio, sourcePtr, len, result);
1364         return result;
1365     }
1366 
1367     // /**
1368     //  * Writes data from the given array to the BIO.
1369     //  */
1370     // static int ENGINE_SSL_write_BIO_heap(long ssl_address, long bioRef, byte[] sourceJava,
1371     //         int sourceOffset, int sourceLength, SSLHandshakeCallbacks shc);            
1372 
1373     /**
1374      * Reads data from the given BIO into a direct {@link java.nio.ByteBuffer}.
1375      */
1376     static int ENGINE_SSL_read_BIO_direct(long ssl_address, long bioRef, long address, int outputSize,
1377             SSLHandshakeCallbacks shc) {
1378 
1379         SSL* ssl = to_SSL(ssl_address);
1380         if (ssl is null) {
1381             return -1;
1382         }
1383         if (shc is null) {
1384             warning("sslHandshakeCallbacks is null");
1385             return -1;
1386         }
1387         BIO* bio = to_SSL_BIO(bioRef);
1388         if (bio is null) {
1389             return -1;
1390         }
1391         char* destPtr = cast(char*)(address);
1392         if (destPtr is null) {
1393             warning("destPtr is null");
1394             return -1;
1395         }
1396 
1397         AppData* appData = toAppData(ssl);
1398         if (appData is null) {
1399             warning("Unable to retrieve application data");
1400             ERR_clear_error();
1401             return -1;
1402         }
1403         if (!appData.setCallbackState(cast(void *)shc, cast(void*)null)) {
1404             warning("Unable to set appdata callback");
1405             ERR_clear_error();
1406             return -1;
1407         }
1408 
1409         errno = 0;
1410 
1411         int result = BIO_read(bio, destPtr, outputSize);
1412         appData.clearCallbackState();
1413         version(HUNT_DEBUG_MORE) tracef("ssl=%s ENGINE_SSL_read_BIO_direct bio=%s destPtr=%s outputSize=%d shc=%s => ret=%d",
1414                 ssl, bio, destPtr, outputSize, shc, result);
1415         return result;
1416     }
1417 
1418     // /**
1419     //  * Reads data from the given BIO into an array.
1420     //  */
1421     // static int ENGINE_SSL_read_BIO_heap(long ssl_address, long bioRef, byte[] destJava,
1422     //         int destOffset, int destLength, SSLHandshakeCallbacks shc);
1423 
1424     /**
1425      * Variant of the {@link #SSL_shutdown} used by {@link ConscryptEngine}. This version does not
1426      * lock.
1427      */
1428     static void ENGINE_SSL_shutdown(long ssl_address, SSLHandshakeCallbacks shc) {
1429         SSL* ssl = to_SSL(ssl_address);
1430         if (ssl is null) {
1431             return;
1432         }
1433         tracef("ssl=%s ENGINE_SSL_shutdown", ssl);
1434 
1435         if (shc is null) {
1436             warning("sslHandshakeCallbacks is null");
1437             return;
1438         }
1439 
1440         // AppData* appData = toAppData(ssl);
1441         // if (appData !is null) {
1442         //     if (!appData.setCallbackState(env, shc, null)) {
1443         //         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
1444         //         ERR_clear_error();
1445         //         tracef("ssl=%s ENGINE_SSL_shutdown => exception", ssl);
1446         //         return;
1447         //     }
1448         //     int ret = SSL_shutdown(ssl);
1449         //     appData.clearCallbackState();
1450         //     // callbacks can happen if server requests renegotiation
1451         //     if (env.ExceptionCheck()) {
1452         //         tracef("ssl=%s ENGINE_SSL_shutdown => exception", ssl);
1453         //         return;
1454         //     }
1455         //     switch (ret) {
1456         //         case 0:
1457         //             /*
1458         //             * Shutdown was not successful (yet), but there also
1459         //             * is no error. Since we can't know whether the remote
1460         //             * server is actually still there, and we don't want to
1461         //             * get stuck forever in a second SSL_shutdown() call, we
1462         //             * simply return. This is not security a problem as long
1463         //             * as we close the underlying socket, which we actually
1464         //             * do, because that's where we are just coming from.
1465         //             */
1466         //             tracef("ssl=%s ENGINE_SSL_shutdown => 0", ssl);
1467         //             break;
1468         //         case 1:
1469         //             /*
1470         //             * Shutdown was successful. We can safely return. Hooray!
1471         //             */
1472         //             tracef("ssl=%s ENGINE_SSL_shutdown => 1", ssl);
1473         //             break;
1474         //         default:
1475         //             /*
1476         //             * Everything else is a real error condition. We should
1477         //             * let the Java layer know about this by throwing an
1478         //             * exception.
1479         //             */
1480         //             int sslError = SSL_get_error(ssl, ret);
1481         //             tracef("ssl=%s ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
1482         //             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
1483         //                                                             "SSL shutdown failed");
1484         //             break;
1485         //     }
1486         // }
1487 
1488 implementationMissing(false);
1489         ERR_clear_error();        
1490     }
1491 
1492     // /**
1493     //  * Used for testing only.
1494     //  */
1495     // static int BIO_read(long bioRef, byte[] buffer);
1496     // static void BIO_write(long bioRef, byte[] buffer, int offset, int length);
1497     // static long ERR_peek_last_error();
1498     static long SSL_clear_mode(long ssl_address, long mode) {
1499         SSL* ssl = to_SSL(ssl_address);
1500         // NOLINTNEXTLINE(runtime/int)
1501         if (ssl is null) {
1502             return 0;
1503         }
1504         long result = cast(long)(deimos.openssl.ssl.SSL_clear_mode(ssl, cast(uint32_t)(mode)));
1505         // NOLINTNEXTLINE(runtime/int)
1506         return result;
1507     }
1508 
1509     static long SSL_get_mode(long ssl_address) {
1510         SSL* ssl = to_SSL(ssl_address);
1511         if (ssl is null) {
1512             return 0;
1513         }
1514         long mode = cast(long)(deimos.openssl.ssl.SSL_get_mode(ssl));
1515         // NOLINTNEXTLINE(runtime/int)
1516         return mode;        
1517     }
1518 
1519     static long SSL_get_options(long ssl_address) {
1520         SSL* ssl = to_SSL(ssl_address);
1521         if (ssl is null) {
1522             return 0;
1523         }
1524         long options = cast(long)(deimos.openssl.ssl.SSL_get_options(ssl));
1525         // NOLINTNEXTLINE(runtime/int)
1526         return options;        
1527     }
1528     // static long SSL_get1_session(long ssl_address);
1529 
1530     // --- DSA/RSA public/private key handling functions -----------------------
1531 
1532     // static long EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q,
1533     //         byte[] dmp1, byte[] dmq1, byte[] iqmp);
1534 
1535     // static int EVP_PKEY_type(NativeRef.EVP_PKEY pkey);
1536 
1537     // static string EVP_PKEY_print_public(NativeRef.EVP_PKEY pkeyRef);
1538 
1539     // static string EVP_PKEY_print_params(NativeRef.EVP_PKEY pkeyRef);
1540 
1541     static void EVP_PKEY_free(long pkeyRef) {
1542         EVP_PKEY* pkey = cast(EVP_PKEY*)(pkeyRef);
1543 
1544         if (pkey !is null) {
1545             deimos.openssl.ssl.EVP_PKEY_free(pkey);
1546         }        
1547     }
1548 
1549     // static int EVP_PKEY_cmp(NativeRef.EVP_PKEY pkey1, NativeRef.EVP_PKEY pkey2);
1550 
1551     // static byte[] EVP_marshal_private_key(NativeRef.EVP_PKEY pkey);
1552 
1553     // static byte[] EVP_marshal_public_key(NativeRef.EVP_PKEY pkey);
1554 
1555     // static long EVP_parse_public_key(byte[] data);
1556 
1557     // static long PEM_read_bio_PUBKEY(long bioCtx);
1558 
1559     // static long PEM_read_bio_PrivateKey(long bioCtx);
1560 
1561     // static long getRSAPrivateKeyWrapper(PrivateKey key, byte[] modulus);
1562 
1563     // static long getECPrivateKeyWrapper(PrivateKey key, NativeRef.EC_GROUP ecGroupRef);
1564 
1565     // static long RSA_generate_key_ex(int modulusBits, byte[] publicExponent);
1566 
1567     // static int RSA_size(NativeRef.EVP_PKEY pkey);
1568 
1569     // static int RSA_private_encrypt(
1570     //         int flen, byte[] from, byte[] to, NativeRef.EVP_PKEY pkey, int padding);
1571 
1572     // static int RSA_public_decrypt(int flen, byte[] from, byte[] to, NativeRef.EVP_PKEY pkey,
1573     //         int padding) throws BadPaddingException, SignatureException;
1574 
1575     // static int RSA_public_encrypt(
1576     //         int flen, byte[] from, byte[] to, NativeRef.EVP_PKEY pkey, int padding);
1577 
1578     // static int RSA_private_decrypt(int flen, byte[] from, byte[] to, NativeRef.EVP_PKEY pkey,
1579     //         int padding) throws BadPaddingException, SignatureException;
1580 
1581     // /**
1582     //  * @return array of {n, e}
1583     //  */
1584     // static byte[][] get_RSA_public_params(NativeRef.EVP_PKEY rsa);
1585 
1586     // /**
1587     //  * @return array of {n, e, d, p, q, dmp1, dmq1, iqmp}
1588     //  */
1589     // static byte[][] get_RSA_private_params(NativeRef.EVP_PKEY rsa);
1590 
1591     // // --- ChaCha20 -----------------------
1592 
1593     // /**
1594     //  * Returns the encrypted or decrypted version of the data.
1595     //  */
1596     // static void chacha20_encrypt_decrypt(byte[] in, int inOffset, byte[] out, int outOffset,
1597     //         int length, byte[] key, byte[] nonce, int blockCounter);
1598 
1599     // // --- EC functions --------------------------
1600 
1601     // static long EVP_PKEY_new_EC_KEY(
1602     //         NativeRef.EC_GROUP groupRef, NativeRef.EC_POINT pubkeyRef, byte[] privkey);
1603 
1604     // static long EC_GROUP_new_by_curve_name(string curveName);
1605 
1606     // static long EC_GROUP_new_arbitrary(
1607     //         byte[] p, byte[] a, byte[] b, byte[] x, byte[] y, byte[] order, int cofactor);
1608 
1609     // static string EC_GROUP_get_curve_name(NativeRef.EC_GROUP groupRef);
1610 
1611     // static byte[][] EC_GROUP_get_curve(NativeRef.EC_GROUP groupRef);
1612 
1613     // static void EC_GROUP_clear_free(long groupRef);
1614 
1615     // static long EC_GROUP_get_generator(NativeRef.EC_GROUP groupRef);
1616 
1617     // static byte[] EC_GROUP_get_order(NativeRef.EC_GROUP groupRef);
1618 
1619     // static int EC_GROUP_get_degree(NativeRef.EC_GROUP groupRef);
1620 
1621     // static byte[] EC_GROUP_get_cofactor(NativeRef.EC_GROUP groupRef);
1622 
1623     // static long EC_POINT_new(NativeRef.EC_GROUP groupRef);
1624 
1625     // static void EC_POINT_clear_free(long pointRef);
1626 
1627     // static byte[][] EC_POINT_get_affine_coordinates(
1628     //         NativeRef.EC_GROUP groupRef, NativeRef.EC_POINT pointRef);
1629 
1630     // static void EC_POINT_set_affine_coordinates(
1631     //         NativeRef.EC_GROUP groupRef, NativeRef.EC_POINT pointRef, byte[] x, byte[] y);
1632 
1633     // static long EC_KEY_generate_key(NativeRef.EC_GROUP groupRef);
1634 
1635     // static long EC_KEY_get1_group(NativeRef.EVP_PKEY pkeyRef);
1636 
1637     // static byte[] EC_KEY_get_private_key(NativeRef.EVP_PKEY keyRef);
1638 
1639     // static long EC_KEY_get_public_key(NativeRef.EVP_PKEY keyRef);
1640 
1641     // static byte[] EC_KEY_marshal_curve_name(NativeRef.EC_GROUP groupRef) throws IOException;
1642 
1643     // static long EC_KEY_parse_curve_name(byte[] encoded) throws IOException;
1644 
1645     // static int ECDH_compute_key(byte[] out, int outOffset, NativeRef.EVP_PKEY publicKeyRef,
1646     //         NativeRef.EVP_PKEY privateKeyRef) throws InvalidKeyException, IndexOutOfBoundsException;
1647 
1648     // static int ECDSA_size(NativeRef.EVP_PKEY pkey);
1649 
1650     // static int ECDSA_sign(byte[] data, byte[] sig, NativeRef.EVP_PKEY pkey);
1651 
1652     // static int ECDSA_verify(byte[] data, byte[] sig, NativeRef.EVP_PKEY pkey);
1653 
1654     // // --- Message digest functions --------------
1655 
1656     // // These return const references
1657     // static long EVP_get_digestbyname(string name);
1658 
1659     // static int EVP_MD_size(long evp_md_const);
1660 
1661     // // --- Message digest context functions --------------
1662 
1663     // static long EVP_MD_CTX_create();
1664 
1665     // static void EVP_MD_CTX_cleanup(NativeRef.EVP_MD_CTX ctx);
1666 
1667     // static void EVP_MD_CTX_destroy(long ctx);
1668 
1669     // static int EVP_MD_CTX_copy_ex(
1670     //         NativeRef.EVP_MD_CTX dst_ctx, NativeRef.EVP_MD_CTX src_ctx);
1671 
1672     // // --- Digest handling functions -------------------------------------------
1673 
1674     // static int EVP_DigestInit_ex(NativeRef.EVP_MD_CTX ctx, long evp_md);
1675 
1676     // static void EVP_DigestUpdate(
1677     //         NativeRef.EVP_MD_CTX ctx, byte[] buffer, int offset, int length);
1678 
1679     // static void EVP_DigestUpdateDirect(NativeRef.EVP_MD_CTX ctx, long ptr, int length);
1680 
1681     // static int EVP_DigestFinal_ex(NativeRef.EVP_MD_CTX ctx, byte[] hash, int offset);
1682 
1683     // // --- Signature handling functions ----------------------------------------
1684 
1685     // static long EVP_DigestSignInit(
1686     //         NativeRef.EVP_MD_CTX ctx, long evpMdRef, NativeRef.EVP_PKEY key);
1687 
1688     // static long EVP_DigestVerifyInit(
1689     //         NativeRef.EVP_MD_CTX ctx, long evpMdRef, NativeRef.EVP_PKEY key);
1690 
1691     // static void EVP_DigestSignUpdate(
1692     //         NativeRef.EVP_MD_CTX ctx, byte[] buffer, int offset, int length);
1693 
1694     // static void EVP_DigestSignUpdateDirect(NativeRef.EVP_MD_CTX ctx, long ptr, int length);
1695 
1696     // static void EVP_DigestVerifyUpdate(
1697     //         NativeRef.EVP_MD_CTX ctx, byte[] buffer, int offset, int length);
1698 
1699     // static void EVP_DigestVerifyUpdateDirect(NativeRef.EVP_MD_CTX ctx, long ptr, int length);
1700 
1701     // static byte[] EVP_DigestSignFinal(NativeRef.EVP_MD_CTX ctx);
1702 
1703     // static bool EVP_DigestVerifyFinal(NativeRef.EVP_MD_CTX ctx, byte[] signature,
1704     //         int offset, int length) throws IndexOutOfBoundsException;
1705 
1706     // static long EVP_PKEY_encrypt_init(NativeRef.EVP_PKEY pkey) throws InvalidKeyException;
1707 
1708     // static int EVP_PKEY_encrypt(NativeRef.EVP_PKEY_CTX ctx, byte[] out, int outOffset,
1709     //         byte[] input, int inOffset, int inLength)
1710     //         throws IndexOutOfBoundsException, BadPaddingException;
1711 
1712     // static long EVP_PKEY_decrypt_init(NativeRef.EVP_PKEY pkey) throws InvalidKeyException;
1713 
1714     // static int EVP_PKEY_decrypt(NativeRef.EVP_PKEY_CTX ctx, byte[] out, int outOffset,
1715     //         byte[] input, int inOffset, int inLength)
1716     //         throws IndexOutOfBoundsException, BadPaddingException;
1717 
1718     // static void EVP_PKEY_CTX_free(long pkeyCtx);
1719 
1720     // static void EVP_PKEY_CTX_set_rsa_padding(long ctx, int pad)
1721     //         throws InvalidAlgorithmParameterException;
1722 
1723     // static void EVP_PKEY_CTX_set_rsa_pss_saltlen(long ctx, int len)
1724     //         throws InvalidAlgorithmParameterException;
1725 
1726     // static void EVP_PKEY_CTX_set_rsa_mgf1_md(long ctx, long evpMdRef)
1727     //         throws InvalidAlgorithmParameterException;
1728 
1729     // static void EVP_PKEY_CTX_set_rsa_oaep_md(long ctx, long evpMdRef)
1730     //         throws InvalidAlgorithmParameterException;
1731 
1732     // static void EVP_PKEY_CTX_set_rsa_oaep_label(long ctx, byte[] label)
1733     //         throws InvalidAlgorithmParameterException;
1734 
1735     // // --- Block ciphers -------------------------------------------------------
1736 
1737     // // These return const references
1738     // static long EVP_get_cipherbyname(string string);
1739 
1740     // static void EVP_CipherInit_ex(NativeRef.EVP_CIPHER_CTX ctx, long evpCipher, byte[] key,
1741     //         byte[] iv, bool encrypting);
1742 
1743     // static int EVP_CipherUpdate(NativeRef.EVP_CIPHER_CTX ctx, byte[] out, int outOffset,
1744     //         byte[] in, int inOffset, int inLength) throws IndexOutOfBoundsException;
1745 
1746     // static int EVP_CipherFinal_ex(NativeRef.EVP_CIPHER_CTX ctx, byte[] out, int outOffset)
1747     //         throws BadPaddingException, IllegalBlockSizeException;
1748 
1749     // static int EVP_CIPHER_iv_length(long evpCipher);
1750 
1751     // static long EVP_CIPHER_CTX_new();
1752 
1753     // static int EVP_CIPHER_CTX_block_size(NativeRef.EVP_CIPHER_CTX ctx);
1754 
1755     // static int get_EVP_CIPHER_CTX_buf_len(NativeRef.EVP_CIPHER_CTX ctx);
1756 
1757     // static bool get_EVP_CIPHER_CTX_final_used(NativeRef.EVP_CIPHER_CTX ctx);
1758 
1759     // static void EVP_CIPHER_CTX_set_padding(
1760     //         NativeRef.EVP_CIPHER_CTX ctx, bool enablePadding);
1761 
1762     // static void EVP_CIPHER_CTX_set_key_length(NativeRef.EVP_CIPHER_CTX ctx, int keyBitSize);
1763 
1764     // static void EVP_CIPHER_CTX_free(long ctx);
1765 
1766     // // --- AEAD ----------------------------------------------------------------
1767     // static long EVP_aead_aes_128_gcm();
1768 
1769     // static long EVP_aead_aes_256_gcm();
1770 
1771     // static long EVP_aead_chacha20_poly1305();
1772 
1773     // static int EVP_AEAD_max_overhead(long evpAead);
1774 
1775     // static int EVP_AEAD_nonce_length(long evpAead);
1776 
1777     // static int EVP_AEAD_CTX_seal(long evpAead, byte[] key, int tagLengthInBytes, byte[] out,
1778     //         int outOffset, byte[] nonce, byte[] in, int inOffset, int inLength, byte[] ad)
1779     //         throws ShortBufferException, BadPaddingException, IndexOutOfBoundsException;
1780 
1781     // static int EVP_AEAD_CTX_open(long evpAead, byte[] key, int tagLengthInBytes, byte[] out,
1782     //         int outOffset, byte[] nonce, byte[] in, int inOffset, int inLength, byte[] ad)
1783     //         throws ShortBufferException, BadPaddingException, IndexOutOfBoundsException;
1784 
1785     // // --- HMAC functions ------------------------------------------------------
1786 
1787     // static long HMAC_CTX_new();
1788 
1789     // static void HMAC_CTX_free(long ctx);
1790 
1791     // static void HMAC_Init_ex(NativeRef.HMAC_CTX ctx, byte[] key, long evp_md);
1792 
1793     // static void HMAC_Update(NativeRef.HMAC_CTX ctx, byte[] in, int inOffset, int inLength);
1794 
1795     // static void HMAC_UpdateDirect(NativeRef.HMAC_CTX ctx, long inPtr, int inLength);
1796 
1797     // static byte[] HMAC_Final(NativeRef.HMAC_CTX ctx);
1798 
1799     // // --- RAND ----------------------------------------------------------------
1800 
1801     // static void RAND_bytes(byte[] output);
1802 
1803     // // --- X509_NAME -----------------------------------------------------------
1804 
1805     // static int X509_NAME_hash(X500Principal principal) {
1806     //     return X509_NAME_hash(principal, "SHA1");
1807     // }
1808 
1809     // public static int X509_NAME_hash_old(X500Principal principal) {
1810     //     return X509_NAME_hash(principal, "MD5");
1811     // }
1812     // private static int X509_NAME_hash(X500Principal principal, string algorithm) {
1813     //     try {
1814     //         byte[] digest = MessageDigest.getInstance(algorithm).digest(principal.getEncoded());
1815     //         int offset = 0;
1816     //         return (((digest[offset++] & 0xff) << 0) | ((digest[offset++] & 0xff) << 8)
1817     //                 | ((digest[offset++] & 0xff) << 16) | ((digest[offset] & 0xff) << 24));
1818     //     } catch (NoSuchAlgorithmException e) {
1819     //         throw new AssertionError(e);
1820     //     }
1821     // }
1822 
1823     // --- X509 ----------------------------------------------------------------
1824 
1825     /** Used to request get_X509_GENERAL_NAME_stack get the "altname" field. */
1826     enum int GN_STACK_SUBJECT_ALT_NAME = 1;
1827 
1828     /**
1829      * Used to request get_X509_GENERAL_NAME_stack get the issuerAlternativeName
1830      * extension.
1831      */
1832     enum int GN_STACK_ISSUER_ALT_NAME = 2;
1833 
1834     /**
1835      * Used to request only non-critical types in get_X509*_ext_oids.
1836      */
1837     enum int EXTENSION_TYPE_NON_CRITICAL = 0;
1838 
1839     /**
1840      * Used to request only critical types in get_X509*_ext_oids.
1841      */
1842     enum int EXTENSION_TYPE_CRITICAL = 1;
1843 
1844     // static long d2i_X509_bio(long bioCtx);
1845 
1846     // static long d2i_X509(byte[] encoded);
1847 
1848     // static long PEM_read_bio_X509(long bioCtx);
1849 
1850     // static byte[] i2d_X509(long x509ctx, OpenSSLX509Certificate holder);
1851 
1852     // /** Takes an X509 context not an X509_PUBKEY context. */
1853     // static byte[] i2d_X509_PUBKEY(long x509ctx, OpenSSLX509Certificate holder);
1854 
1855     // static byte[] ASN1_seq_pack_X509(long[] x509CertRefs);
1856 
1857     // static long[] ASN1_seq_unpack_X509_bio(long bioRef);
1858 
1859     // static void X509_free(long x509ctx, OpenSSLX509Certificate holder);
1860 
1861     // static long X509_dup(long x509ctx, OpenSSLX509Certificate holder);
1862 
1863     // static int X509_cmp(long x509ctx1, OpenSSLX509Certificate holder, long x509ctx2, OpenSSLX509Certificate holder2);
1864 
1865     // static void X509_print_ex(long bioCtx, long x509ctx, OpenSSLX509Certificate holder, long nmflag, long certflag);
1866 
1867     // static byte[] X509_get_issuer_name(long x509ctx, OpenSSLX509Certificate holder);
1868 
1869     // static byte[] X509_get_subject_name(long x509ctx, OpenSSLX509Certificate holder);
1870 
1871     // static string get_X509_sig_alg_oid(long x509ctx, OpenSSLX509Certificate holder);
1872 
1873     // static byte[] get_X509_sig_alg_parameter(long x509ctx, OpenSSLX509Certificate holder);
1874 
1875     // static bool[] get_X509_issuerUID(long x509ctx, OpenSSLX509Certificate holder);
1876 
1877     // static bool[] get_X509_subjectUID(long x509ctx, OpenSSLX509Certificate holder);
1878 
1879     // static long X509_get_pubkey(long x509ctx, OpenSSLX509Certificate holder)
1880     //         throws NoSuchAlgorithmException, InvalidKeyException;
1881 
1882     // static string get_X509_pubkey_oid(long x509ctx, OpenSSLX509Certificate holder);
1883 
1884     // static byte[] X509_get_ext_oid(long x509ctx, OpenSSLX509Certificate holder, string oid);
1885 
1886     // static string[] get_X509_ext_oids(long x509ctx, OpenSSLX509Certificate holder, int critical);
1887 
1888     // static Object[][] get_X509_GENERAL_NAME_stack(long x509ctx, OpenSSLX509Certificate holder, int type)
1889     //         throws CertificateParsingException;
1890 
1891     // static bool[] get_X509_ex_kusage(long x509ctx, OpenSSLX509Certificate holder);
1892 
1893     // static string[] get_X509_ex_xkusage(long x509ctx, OpenSSLX509Certificate holder);
1894 
1895     // static int get_X509_ex_pathlen(long x509ctx, OpenSSLX509Certificate holder);
1896 
1897     // static long X509_get_notBefore(long x509ctx, OpenSSLX509Certificate holder);
1898 
1899     // static long X509_get_notAfter(long x509ctx, OpenSSLX509Certificate holder);
1900 
1901     // static long X509_get_version(long x509ctx, OpenSSLX509Certificate holder);
1902 
1903     // static byte[] X509_get_serialNumber(long x509ctx, OpenSSLX509Certificate holder);
1904 
1905     // static void X509_verify(long x509ctx, OpenSSLX509Certificate holder, NativeRef.EVP_PKEY pkeyCtx)
1906     //         throws BadPaddingException;
1907 
1908     // static byte[] get_X509_cert_info_enc(long x509ctx, OpenSSLX509Certificate holder);
1909 
1910     // static byte[] get_X509_signature(long x509ctx, OpenSSLX509Certificate holder);
1911 
1912     // static int get_X509_ex_flags(long x509ctx, OpenSSLX509Certificate holder);
1913 
1914     // // Used by Android platform TrustedCertificateStore.
1915     // @SuppressWarnings("unused")
1916     // static int X509_check_issued(long ctx, OpenSSLX509Certificate holder, long ctx2, OpenSSLX509Certificate holder2);
1917 
1918     // --- PKCS7 ---------------------------------------------------------------
1919 
1920     /** Used as the "which" field in d2i_PKCS7_bio and PEM_read_bio_PKCS7. */
1921     enum int PKCS7_CERTS = 1;
1922 
1923     /** Used as the "which" field in d2i_PKCS7_bio and PEM_read_bio_PKCS7. */
1924     enum int PKCS7_CRLS = 2;
1925 
1926     // /** Returns an array of X509 or X509_CRL pointers. */
1927     // static long[] d2i_PKCS7_bio(long bioCtx, int which);
1928 
1929     // /** Returns an array of X509 or X509_CRL pointers. */
1930     // static byte[] i2d_PKCS7(long[] certs);
1931 
1932     // /** Returns an array of X509 or X509_CRL pointers. */
1933     // static long[] PEM_read_bio_PKCS7(long bioCtx, int which);
1934 
1935     // // --- X509_CRL ------------------------------------------------------------
1936 
1937     // static long d2i_X509_CRL_bio(long bioCtx);
1938 
1939     // static long PEM_read_bio_X509_CRL(long bioCtx);
1940 
1941     // static byte[] i2d_X509_CRL(long x509CrlCtx, OpenSSLX509CRL holder);
1942 
1943     // static void X509_CRL_free(long x509CrlCtx, OpenSSLX509CRL holder);
1944 
1945     // static void X509_CRL_print(long bioCtx, long x509CrlCtx, OpenSSLX509CRL holder);
1946 
1947     // static string get_X509_CRL_sig_alg_oid(long x509CrlCtx, OpenSSLX509CRL holder);
1948 
1949     // static byte[] get_X509_CRL_sig_alg_parameter(long x509CrlCtx, OpenSSLX509CRL holder);
1950 
1951     // static byte[] X509_CRL_get_issuer_name(long x509CrlCtx, OpenSSLX509CRL holder);
1952 
1953     // /** Returns X509_REVOKED reference that is not duplicated! */
1954     // static long X509_CRL_get0_by_cert(long x509CrlCtx, OpenSSLX509CRL holder, long x509Ctx, OpenSSLX509Certificate holder2);
1955 
1956     // /** Returns X509_REVOKED reference that is not duplicated! */
1957     // static long X509_CRL_get0_by_serial(long x509CrlCtx, OpenSSLX509CRL holder, byte[] serial);
1958 
1959     // /** Returns an array of X509_REVOKED that are owned by the caller. */
1960     // static long[] X509_CRL_get_REVOKED(long x509CrlCtx, OpenSSLX509CRL holder);
1961 
1962     // static string[] get_X509_CRL_ext_oids(long x509Crlctx, OpenSSLX509CRL holder, int critical);
1963 
1964     // static byte[] X509_CRL_get_ext_oid(long x509CrlCtx, OpenSSLX509CRL holder, string oid);
1965 
1966     // static void X509_delete_ext(long x509, OpenSSLX509Certificate holder, string oid);
1967 
1968     // static long X509_CRL_get_version(long x509CrlCtx, OpenSSLX509CRL holder);
1969 
1970     // static long X509_CRL_get_ext(long x509CrlCtx, OpenSSLX509CRL holder, string oid);
1971 
1972     // static byte[] get_X509_CRL_signature(long x509ctx, OpenSSLX509CRL holder);
1973 
1974     // static void X509_CRL_verify(long x509CrlCtx, OpenSSLX509CRL holder, NativeRef.EVP_PKEY pkeyCtx);
1975 
1976     // static byte[] get_X509_CRL_crl_enc(long x509CrlCtx, OpenSSLX509CRL holder);
1977 
1978     // static long X509_CRL_get_lastUpdate(long x509CrlCtx, OpenSSLX509CRL holder);
1979 
1980     // static long X509_CRL_get_nextUpdate(long x509CrlCtx, OpenSSLX509CRL holder);
1981 
1982     // // --- X509_REVOKED --------------------------------------------------------
1983 
1984     // static long X509_REVOKED_dup(long x509RevokedCtx);
1985 
1986     // static byte[] i2d_X509_REVOKED(long x509RevokedCtx);
1987 
1988     // static string[] get_X509_REVOKED_ext_oids(long x509ctx, int critical);
1989 
1990     // static byte[] X509_REVOKED_get_ext_oid(long x509RevokedCtx, string oid);
1991 
1992     // static byte[] X509_REVOKED_get_serialNumber(long x509RevokedCtx);
1993 
1994     // static long X509_REVOKED_get_ext(long x509RevokedCtx, string oid);
1995 
1996     // /** Returns ASN1_TIME reference. */
1997     // static long get_X509_REVOKED_revocationDate(long x509RevokedCtx);
1998 
1999     // static void X509_REVOKED_print(long bioRef, long x509RevokedCtx);
2000 
2001     // // --- X509_EXTENSION ------------------------------------------------------
2002 
2003     // static int X509_supported_extension(long x509ExtensionRef);
2004 
2005     // // --- ASN1_TIME -----------------------------------------------------------
2006 
2007     // static void ASN1_TIME_to_Calendar(long asn1TimeCtx, Calendar cal);
2008 
2009     // // --- ASN1 Encoding -------------------------------------------------------
2010 
2011     // /**
2012     //  * Allocates and returns an opaque reference to an object that can be used with other
2013     //  * asn1_read_* functions to read the ASN.1-encoded data in val.  The returned object must
2014     //  * be freed after use by calling asn1_read_free.
2015     //  */
2016     // static long asn1_read_init(byte[] val) ;
2017 
2018     // /**
2019     //  * Allocates and returns an opaque reference to an object that can be used with other
2020     //  * asn1_read_* functions to read the ASN.1 sequence pointed to by cbsRef.  The returned
2021     //  * object must be freed after use by calling asn1_read_free.
2022     //  */
2023     // static long asn1_read_sequence(long cbsRef) ;
2024 
2025     // /**
2026     //  * Returns whether the next object in the given reference is explicitly tagged with the
2027     //  * given tag number.
2028     //  */
2029     // static bool asn1_read_next_tag_is(long cbsRef, int tag) ;
2030 
2031     // /**
2032     //  * Allocates and returns an opaque reference to an object that can be used with
2033     //  * other asn1_read_* functions to read the ASN.1 data pointed to by cbsRef.  The returned
2034     //  * object must be freed after use by calling asn1_read_free.
2035     //  */
2036     // static long asn1_read_tagged(long cbsRef) ;
2037 
2038     // /**
2039     //  * Returns the contents of an ASN.1 octet string from the given reference.
2040     //  */
2041     // static byte[] asn1_read_octetstring(long cbsRef) ;
2042 
2043     // /**
2044     //  * Returns an ASN.1 integer from the given reference.  If the integer doesn't fit
2045     //  * in a uint64, this method will throw an IOException.
2046     //  */
2047     // static long asn1_read_uint64(long cbsRef) ;
2048 
2049     // /**
2050     //  * Consumes an ASN.1 NULL from the given reference.
2051     //  */
2052     // static void asn1_read_null(long cbsRef) ;
2053 
2054     // /**
2055     //  * Returns an ASN.1 OID in dotted-decimal notation (eg, "1.3.14.3.2.26" for SHA-1) from the
2056     //  * given reference.
2057     //  */
2058     // static string asn1_read_oid(long cbsRef) ;
2059 
2060     // /**
2061     //  * Returns whether or not the given reference has been read completely.
2062     //  */
2063     // static bool asn1_read_is_empty(long cbsRef);
2064 
2065     // /**
2066     //  * Frees any resources associated with the given reference.  After calling, the reference
2067     //  * must not be used again.  This may be called with a zero reference, in which case nothing
2068     //  * will be done.
2069     //  */
2070     // static void asn1_read_free(long cbsRef);
2071 
2072     // /**
2073     //  * Allocates and returns an opaque reference to an object that can be used with other
2074     //  * asn1_write_* functions to write ASN.1-encoded data.  The returned object must be finalized
2075     //  * after use by calling either asn1_write_finish or asn1_write_cleanup, and its resources
2076     //  * must be freed by calling asn1_write_free.
2077     //  */
2078     // static long asn1_write_init() ;
2079 
2080     // /**
2081     //  * Allocates and returns an opaque reference to an object that can be used with other
2082     //  * asn1_write_* functions to write an ASN.1 sequence into the given reference.  The returned
2083     //  * reference may only be used until the next call on the parent reference.  The returned
2084     //  * object must be freed after use by calling asn1_write_free.
2085     //  */
2086     // static long asn1_write_sequence(long cbbRef) ;
2087 
2088     // /**
2089     //  * Allocates and returns an opaque reference to an object that can be used with other
2090     //  * asn1_write_* functions to write a explicitly-tagged ASN.1 object with the given tag
2091     //  * into the given reference. The returned reference may only be used until the next
2092     //  * call on the parent reference.  The returned object must be freed after use by
2093     //  * calling asn1_write_free.
2094     //  */
2095     // static long asn1_write_tag(long cbbRef, int tag) ;
2096 
2097     // /**
2098     //  * Writes the given data into the given reference as an ASN.1-encoded octet string.
2099     //  */
2100     // static void asn1_write_octetstring(long cbbRef, byte[] data) ;
2101 
2102     // /**
2103     //  * Writes the given value into the given reference as an ASN.1-encoded integer.
2104     //  */
2105     // static void asn1_write_uint64(long cbbRef, long value) ;
2106 
2107     // /**
2108     //  * Writes a NULL value into the given reference.
2109     //  */
2110     // static void asn1_write_null(long cbbRef) ;
2111 
2112     // /**
2113     //  * Writes the given OID (which must be in dotted-decimal notation) into the given reference.
2114     //  */
2115     // static void asn1_write_oid(long cbbRef, string oid) ;
2116 
2117     // /**
2118     //  * Flushes the given reference, invalidating any child references and completing their
2119     //  * operations.  This must be called if the child references are to be freed before
2120     //  * asn1_write_finish is called on the ultimate parent.  The child references must still
2121     //  * be freed.
2122     //  */
2123     // static void asn1_write_flush(long cbbRef) ;
2124 
2125     // /**
2126     //  * Completes any in-progress operations and returns the ASN.1-encoded data.  Either this
2127     //  * or asn1_write_cleanup must be called on any reference returned from asn1_write_init
2128     //  * before it is freed.
2129     //  */
2130     // static byte[] asn1_write_finish(long cbbRef) ;
2131 
2132     // /**
2133     //  * Cleans up intermediate state in the given reference.  Either this or asn1_write_finish
2134     //  * must be called on any reference returned from asn1_write_init before it is freed.
2135     //  */
2136     // static void asn1_write_cleanup(long cbbRef);
2137 
2138     // /**
2139     //  * Frees resources associated with the given reference.  After calling, the reference
2140     //  * must not be used again.  This may be called with a zero reference, in which case nothing
2141     //  * will be done.
2142     //  */
2143     // static void asn1_write_free(long cbbRef);
2144 
2145     // --- BIO stream creation -------------------------------------------------
2146 
2147     // static long create_BIO_InputStream(OpenSSLBIOInputStream is, bool isFinite);
2148 
2149     // static long create_BIO_OutputStream(OutputStream os);
2150 
2151     static void BIO_free_all(long bioRef)    {
2152         BIO* bio = to_SSL_BIO(bioRef); // cast(BIO*)(cast(uintptr_t)(bioRef));
2153         if (bio is null) {
2154             warning("bio is null");
2155         }
2156         else
2157             deimos.openssl.ssl.BIO_free_all(bio);
2158     }
2159 
2160     static string[] getSupportedProtocols() {
2161         return SUPPORTED_PROTOCOLS.dup;
2162     }
2163 
2164     static void setEnabledProtocols(long ssl_address, string[] protocols) {
2165         checkEnabledProtocols(protocols);
2166         // TLS protocol negotiation only allows a min and max version
2167         // to be set, despite the Java API allowing a sparse set of
2168         // protocols to be enabled.  Use the lowest contiguous range
2169         // of protocols provided by the caller, which is what we've
2170         // done historically.
2171         string min = null;
2172         string max = null;
2173         for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) {
2174             string protocol = SUPPORTED_PROTOCOLS[i];
2175             if (protocols.contains(protocol)) {
2176                 if (min is null) {
2177                     min = protocol;
2178                 }
2179                 max = protocol;
2180             } else if (min !is null) {
2181                 break;
2182             }
2183         }
2184         if ((min is null) || (max is null)) {
2185             throw new IllegalArgumentException("No protocols enabled.");
2186         }
2187         SSL_set_protocol_versions(ssl_address, getProtocolConstant(min), getProtocolConstant(max));
2188     }
2189 
2190     private static int getProtocolConstant(string protocol) {
2191         if (protocol.equals(SUPPORTED_PROTOCOL_TLSV1)) {
2192             return NativeConstants.TLS1_VERSION;
2193         } else if (protocol.equals(SUPPORTED_PROTOCOL_TLSV1_1)) {
2194             return NativeConstants.TLS1_1_VERSION;
2195         } else if (protocol.equals(SUPPORTED_PROTOCOL_TLSV1_2)) {
2196             return NativeConstants.TLS1_2_VERSION;
2197         } else {
2198             throw new Exception("Unknown protocol encountered: " ~ protocol);
2199         }
2200     }
2201 
2202     static string[] checkEnabledProtocols(string[] protocols) {
2203         if (protocols is null) {
2204             throw new IllegalArgumentException("protocols is null");
2205         }
2206 
2207         foreach (string protocol ; protocols) {
2208             if (protocol.empty) {
2209                 throw new IllegalArgumentException("protocols contains null");
2210             }
2211             if (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1)
2212                     && !protocol.equals(SUPPORTED_PROTOCOL_TLSV1_1)
2213                     && !protocol.equals(SUPPORTED_PROTOCOL_TLSV1_2)
2214                     && !protocol.equals(OBSOLETE_PROTOCOL_SSLV3)) {
2215                 throw new IllegalArgumentException("protocol " ~ protocol ~ " is not supported");
2216             }
2217         }
2218         return protocols;
2219     }
2220 
2221     static void SSL_set_cipher_lists(long ssl_address, string[] cipherSuites) {
2222         SSL* ssl = to_SSL(ssl_address);
2223         if (ssl is null) {
2224             return;
2225         }
2226 
2227         implementationMissing(false);
2228         if (cipherSuites is null) {
2229             warning("cipherSuites is null");
2230             return;
2231         }
2232 
2233         // int length = env.GetArrayLength(cipherSuites);
2234 
2235         // /*
2236         // * Special case for empty cipher list. This is considered an error by the
2237         // * SSL_set_cipher_list API, but Java allows this silly configuration.
2238         // * However, the SSL cipher list is still set even when SSL_set_cipher_list
2239         // * returns 0 in this case. Just to make sure, we check the resulting cipher
2240         // * list to make sure it's zero length.
2241         // */
2242         // if (length == 0) {
2243         //     tracef("ssl=%s SSL_set_cipher_lists cipherSuites=empty", ssl);
2244         //     SSL_set_cipher_list(ssl, "");
2245         //     ERR_clear_error();
2246         //     if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
2247         //         tracef("ssl=%s SSL_set_cipher_lists cipherSuites=empty => error", ssl);
2248         //         conscrypt::jniutil::throwRuntimeException(
2249         //                 env, "SSL_set_cipher_list did not update ciphers!");
2250         //         ERR_clear_error();
2251         //     }
2252         //     return;
2253         // }
2254 
2255         // static const char noSSLv2[] = "!SSLv2";
2256         // size_t cipherStringLen = strlen(noSSLv2);
2257 
2258         // for (int i = 0; i < length; i++) {
2259         //     ScopedLocalRef<jstring> cipherSuite(
2260         //             env, reinterpret_cast<jstring>(env.GetObjectArrayElement(cipherSuites, i)));
2261         //     ScopedUtfChars c(env, cipherSuite.get());
2262         //     if (c.c_str() is null) {
2263         //         return;
2264         //     }
2265 
2266         //     if (cipherStringLen + 1 < cipherStringLen) {
2267         //         warning("java/lang/IllegalArgumentException",
2268         //                                             "Overflow in cipher suite strings");
2269         //         return;
2270         //     }
2271         //     cipherStringLen += 1; /* For the separating colon */
2272 
2273         //     if (cipherStringLen + c.size() < cipherStringLen) {
2274         //         warning("java/lang/IllegalArgumentException",
2275         //                                             "Overflow in cipher suite strings");
2276         //         return;
2277         //     }
2278         //     cipherStringLen += c.size();
2279         // }
2280 
2281         // if (cipherStringLen + 1 < cipherStringLen) {
2282         //     warning("java/lang/IllegalArgumentException",
2283         //                                         "Overflow in cipher suite strings");
2284         //     return;
2285         // }
2286         // cipherStringLen += 1; /* For final NUL. */
2287 
2288         // std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
2289         // if (cipherString.get() is null) {
2290         //     conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
2291         //     return;
2292         // }
2293         // memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
2294         // size_t j = strlen(noSSLv2);
2295 
2296         // for (int i = 0; i < length; i++) {
2297         //     ScopedLocalRef<jstring> cipherSuite(
2298         //             env, reinterpret_cast<jstring>(env.GetObjectArrayElement(cipherSuites, i)));
2299         //     ScopedUtfChars c(env, cipherSuite.get());
2300 
2301         //     cipherString[j++] = ':';
2302         //     memcpy(&cipherString[j], c.c_str(), c.size());
2303         //     j += c.size();
2304         // }
2305 
2306         // cipherString[j++] = 0;
2307         // if (j != cipherStringLen) {
2308         //     warning("java/lang/IllegalArgumentException",
2309         //                                         "Internal error");
2310         //     return;
2311         // }
2312 
2313         // tracef("ssl=%s SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
2314         // if (!SSL_set_cipher_list(ssl, cipherString.get())) {
2315         //     ERR_clear_error();
2316         //     warning("java/lang/IllegalArgumentException",
2317         //                                         "Illegal cipher suite strings.");
2318         //     return;
2319         // }        
2320     }
2321 
2322     /**
2323      * Gets the list of cipher suites enabled for the provided {@code SSL} instance.
2324      *
2325      * @return array of {@code SSL_CIPHER} references.
2326      */
2327     static long[] SSL_get_ciphers(long ssl_address) {
2328         SSL* ssl = to_SSL(ssl_address);
2329         if (ssl is null) {
2330             return null;
2331         }
2332         STACK_OF!(SSL_CIPHER)* cipherStack = deimos.openssl.ssl.SSL_get_ciphers(ssl);
2333         size_t count = (cipherStack !is null) ? sk_SSL_CIPHER_num(cipherStack) : 0;
2334         long[] ciphers = new long[count];
2335         for (size_t i = 0; i < count; i++) {
2336             ciphers[i] = cast(long)(sk_SSL_CIPHER_value(cipherStack, cast(int)i));
2337         }
2338         version(HUNT_NET_DEBUG) trace("ciphers: ", ciphers.length);
2339         return ciphers;        
2340     }
2341 
2342     static void setEnabledCipherSuites(long ssl_address, string[] cipherSuites) {
2343         checkEnabledCipherSuites(cipherSuites);
2344 
2345         SSL* ssl = to_SSL(ssl_address);
2346         string[] opensslSuites;
2347         for (size_t i = 0; i < cipherSuites.length; i++) {
2348             string cipherSuite = cipherSuites[i];
2349             if (cipherSuite.equals(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
2350                 continue;
2351             }
2352             if (cipherSuite.equals(TLS_FALLBACK_SCSV)) {
2353                 SSL_set_mode(ssl_address, NativeConstants.SSL_MODE_SEND_FALLBACK_SCSV);
2354                 continue;
2355             }
2356             opensslSuites ~= cipherSuiteFromJava(cipherSuite);
2357         }
2358         // trace(opensslSuites);
2359         SSL_set_cipher_lists(ssl_address, opensslSuites);
2360     }
2361 
2362     static string[] checkEnabledCipherSuites(string[] cipherSuites) {
2363         if (cipherSuites is null) {
2364             throw new IllegalArgumentException("cipherSuites is null");
2365         }
2366 
2367         // info(cipherSuites);
2368 
2369         // makes sure all suites are valid, throwing on error
2370         for (size_t i = 0; i < cipherSuites.length; i++) {
2371             if (cipherSuites[i].empty()) {
2372                 throw new IllegalArgumentException("cipherSuites[" ~ i.to!string() ~ "] is null");
2373             }
2374             if (cipherSuites[i] == TLS_EMPTY_RENEGOTIATION_INFO_SCSV
2375                     || cipherSuites[i] == TLS_FALLBACK_SCSV ) {
2376                 continue;
2377             }
2378             if (SUPPORTED_CIPHER_SUITES_SET.contains(cipherSuites[i])) {
2379                 continue;
2380             }
2381 
2382             // For backwards compatibility, it's allowed for |cipherSuite| to
2383             // be an OpenSSL-style cipher-suite name.
2384             if (SUPPORTED_LEGACY_CIPHER_SUITES_SET.contains(cipherSuites[i])) {
2385                 // TODO log warning about using backward compatability
2386                 continue;
2387             }
2388             throw new IllegalArgumentException(
2389                     "cipherSuite " ~ cipherSuites[i] ~ " is not supported.");
2390         }
2391         return cipherSuites;
2392     }
2393 
2394     static void SSL_set_accept_state(long ssl_address) {
2395         SSL* ssl = to_SSL(ssl_address);
2396         if (ssl is null) {
2397             return;
2398         }
2399         deimos.openssl.ssl.SSL_set_accept_state(ssl);        
2400     }
2401 
2402     static void SSL_set_connect_state(long ssl_address) {
2403         SSL* ssl = to_SSL(ssl_address);
2404         if (ssl is null) {
2405             warningf("ssl is null");
2406             return;
2407         }
2408         deimos.openssl.ssl.SSL_set_connect_state(ssl);
2409     }
2410 
2411     /**
2412      * Sets certificate expectations, especially for server to request client auth
2413      */
2414     static void SSL_set_verify(long ssl_address, int mode) {
2415         SSL* ssl = to_SSL(ssl_address);
2416         if (ssl is null) {
2417             warningf("ssl is null");
2418             return;
2419         }
2420         deimos.openssl.ssl.SSL_set_verify(ssl, mode, null);
2421     }
2422 
2423     static void SSL_use_certificate_file(long ssl_address, string fileName) {
2424         SSL* ssl = to_SSL(ssl_address);
2425         if (ssl is null) {
2426             warningf("ssl is null");
2427             return;
2428         }
2429 
2430         int r = deimos.openssl.ssl.SSL_use_certificate_file(ssl, toStringz(fileName), SSL_FILETYPE_PEM);
2431         if(r <=0)   {
2432             warning("Failed to set the certificate file.");
2433         }
2434     }
2435 
2436     static void SSL_use_PrivateKey_file(long ssl_address, string fileName) {
2437         SSL* ssl = to_SSL(ssl_address);
2438         if (ssl is null) {
2439             warningf("ssl is null");
2440             return;
2441         }
2442 
2443         int r = deimos.openssl.ssl.SSL_use_PrivateKey_file(ssl, toStringz(fileName),  SSL_FILETYPE_PEM);
2444         if(r <=0)   {
2445             warning("Failed to set the privateKey file.");
2446         }
2447     }
2448 
2449     // https://www.openssl.org/docs/man1.0.2/man3/SSL_check_private_key.html
2450     static bool SSL_check_private_key(long ssl_address) {
2451         SSL* ssl = to_SSL(ssl_address);
2452         if (ssl is null) {
2453             warningf("ssl is null");
2454             return false;
2455         }
2456 
2457         int r = deimos.openssl.ssl.SSL_check_private_key(ssl);
2458         return r == 1;
2459     }
2460 
2461     static long SSL_get_verify_result(long ssl_address) {
2462         SSL* ssl = to_SSL(ssl_address);
2463         if (ssl is null) {
2464             warningf("ssl is null");
2465             return -1;
2466         }
2467         return deimos.openssl.ssl.SSL_get_verify_result(ssl);
2468     }
2469 
2470     static void SSL_set_session(long ssl_address, long ssl_session_address) {
2471         SSL* ssl = to_SSL(ssl_address);
2472         if (ssl is null) {
2473             warningf("ssl=%s", ssl);
2474             return;
2475         }
2476 
2477         SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2478         if (ssl_session is null) {
2479             return;
2480         }
2481 
2482         int ret = deimos.openssl.ssl.SSL_set_session(ssl, ssl_session);
2483         if (ret != 1) {
2484             /*
2485             * Translate the error, and throw if it turns out to be a real
2486             * problem.
2487             */
2488             int sslErrorCode = deimos.openssl.ssl.SSL_get_error(ssl, ret);
2489             if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
2490                 warning("SSL session set");
2491             }
2492         }
2493         tracef("ssl=%s SSL_set_session ssl_session=%s => ret=%d", ssl, ssl_session,
2494                 ret);        
2495     }
2496 
2497     static void SSL_set_session_creation_enabled(
2498             long ssl_address, bool creation_enabled){
2499         SSL* ssl = to_SSL(ssl_address);
2500         if (ssl is null) {
2501             return;
2502         }
2503 
2504         if (creation_enabled) {
2505             deimos.openssl.ssl.SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); // SSL_MODE_NO_SESSION_CREATION
2506         } else {
2507             deimos.openssl.ssl.SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
2508         }                
2509     }
2510 
2511     // static bool SSL_session_reused(long ssl_address);
2512 
2513     static void SSL_accept_renegotiations(long ssl_address) {
2514         SSL* ssl = to_SSL(ssl_address);
2515         if (ssl is null) {
2516             return;
2517         }
2518 
2519         version(Have_boringssl)
2520         deimos.openssl.ssl.SSL_set_renegotiate_mode(ssl, ssl_renegotiate_mode_t.ssl_renegotiate_freely);        
2521     }
2522 
2523     static void SSL_set_tlsext_host_name(long ssl_address, string hostname) {
2524         SSL* ssl = to_SSL(ssl_address);
2525         if (ssl is null || hostname.empty) {
2526             return;
2527         }
2528 
2529         int ret = cast(int) deimos.openssl.ssl.SSL_set_tlsext_host_name(ssl, cast(char*) toStringz(hostname));
2530         if (ret != 1) 
2531             warning("Error setting host name");
2532         else 
2533             tracef("ssl=%s SSL_set_tlsext_host_name => ok", ssl);
2534     }
2535 
2536     static string SSL_get_servername(long ssl_address) {
2537         SSL* ssl = to_SSL(ssl_address);
2538         if (ssl is null) {
2539             return null;
2540         }
2541         const(char)* servername = deimos.openssl.ssl.SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2542         return cast(string)fromStringz(servername);        
2543     }
2544 
2545     /**
2546     * Perform SSL handshake
2547     */
2548     // static void SSL_do_handshake(long ssl_address, FileDescriptor fdObject, SSLHandshakeCallbacks shc, int timeoutMillis) {
2549     //     SSL* ssl = to_SSL(ssl_address);
2550     //     if (ssl is null) {
2551     //         return;
2552     //     }
2553     //     if (fdObject is null) {
2554     //         warning("fd is null");
2555     //         return;
2556     //     }
2557 
2558     //     if (shc is null) {
2559     //         warning("sslHandshakeCallbacks is null");
2560     //         return;
2561     //     }
2562 
2563     //     NetFd fd(env, fdObject);
2564     //     if (fd.isClosed()) {
2565     //         // SocketException thrown by NetFd.isClosed
2566     //         tracef("ssl=%s SSL_do_handshake fd.isClosed() => exception", ssl);
2567     //         return;
2568     //     }
2569 
2570     //     int ret = SSL_set_fd(ssl, fd.get());
2571     //     tracef("ssl=%s SSL_do_handshake s=%d", ssl, fd.get());
2572 
2573     //     if (ret != 1) {
2574     //         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
2575     //                                                         "Error setting the file descriptor");
2576     //         tracef("ssl=%s SSL_do_handshake SSL_set_fd => exception", ssl);
2577     //         return;
2578     //     }
2579 
2580     //     /*
2581     //     * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
2582     //     * forever and we can use select() to find out if the socket is ready.
2583     //     */
2584     //     if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
2585     //         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
2586     //         tracef("ssl=%s SSL_do_handshake setBlocking => exception", ssl);
2587     //         return;
2588     //     }
2589 
2590     //     AppData* appData = toAppData(ssl);
2591     //     if (appData is null) {
2592     //         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
2593     //         tracef("ssl=%s SSL_do_handshake appData => exception", ssl);
2594     //         return;
2595     //     }
2596 
2597     //     ret = 0;
2598     //     SslError sslError;
2599     //     while (appData.aliveAndKicking) {
2600     //         errno = 0;
2601 
2602     //         if (!appData.setCallbackState(env, shc, fdObject)) {
2603     //             // SocketException thrown by NetFd.isClosed
2604     //             tracef("ssl=%s SSL_do_handshake setCallbackState => exception", ssl);
2605     //             return;
2606     //         }
2607     //         ret = SSL_do_handshake(ssl);
2608     //         appData.clearCallbackState();
2609     //         // cert_verify_callback threw exception
2610     //         if (env.ExceptionCheck()) {
2611     //             ERR_clear_error();
2612     //             tracef("ssl=%s SSL_do_handshake exception => exception", ssl);
2613     //             return;
2614     //         }
2615     //         // success case
2616     //         if (ret == 1) {
2617     //             break;
2618     //         }
2619     //         // retry case
2620     //         if (errno == EINTR) {
2621     //             continue;
2622     //         }
2623     //         // error case
2624     //         sslError.reset(ssl, ret);
2625     //         tracef(
2626     //                 "ssl=%s SSL_do_handshake ret=%d errno=%d sslError=%d "
2627     //                 "timeout_millis=%d",
2628     //                 ssl, ret, errno, sslError.get(), timeout_millis);
2629 
2630     //         /*
2631     //         * If SSL_do_handshake doesn't succeed due to the socket being
2632     //         * either unreadable or unwritable, we use sslSelect to
2633     //         * wait for it to become ready. If that doesn't happen
2634     //         * before the specified timeout or an error occurs, we
2635     //         * cancel the handshake. Otherwise we try the SSL_connect
2636     //         * again.
2637     //         */
2638     //         if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
2639     //             appData.waitingThreads++;
2640     //             int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
2641 
2642     //             if (selectResult == THROWN_EXCEPTION) {
2643     //                 // SocketException thrown by NetFd.isClosed
2644     //                 tracef("ssl=%s SSL_do_handshake sslSelect => exception", ssl);
2645     //                 return;
2646     //             }
2647     //             if (selectResult == -1) {
2648     //                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
2649     //                         env, ssl, SSL_ERROR_SYSCALL, "handshake error",
2650     //                         conscrypt::jniutil::throwSSLHandshakeExceptionStr);
2651     //                 tracef("ssl=%s SSL_do_handshake selectResult == -1 => exception",
2652     //                         ssl);
2653     //                 return;
2654     //             }
2655     //             if (selectResult == 0) {
2656     //                 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
2657     //                 ERR_clear_error();
2658     //                 tracef("ssl=%s SSL_do_handshake selectResult == 0 => exception",
2659     //                         ssl);
2660     //                 return;
2661     //             }
2662     //         } else {
2663     //             // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
2664     //             break;
2665     //         }
2666     //     }
2667 
2668     //     // clean error. See SSL_do_handshake(3SSL) man page.
2669     //     if (ret == 0) {
2670     //         /*
2671     //         * The other side closed the socket before the handshake could be
2672     //         * completed, but everything is within the bounds of the TLS protocol.
2673     //         * We still might want to find out the real reason of the failure.
2674     //         */
2675     //         if (sslError.get() == SSL_ERROR_NONE ||
2676     //             (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
2677     //             (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
2678     //             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
2679     //         } else {
2680     //             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
2681     //                     env, ssl, sslError.release(), "SSL handshake terminated",
2682     //                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
2683     //         }
2684     //         tracef("ssl=%s SSL_do_handshake clean error => exception", ssl);
2685     //         return;
2686     //     }
2687 
2688     //     // unclean error. See SSL_do_handshake(3SSL) man page.
2689     //     if (ret < 0) {
2690     //         /*
2691     //         * Translate the error and throw exception. We are sure it is an error
2692     //         * at this point.
2693     //         */
2694     //         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
2695     //                 env, ssl, sslError.release(), "SSL handshake aborted",
2696     //                 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
2697     //         tracef("ssl=%s SSL_do_handshake unclean error => exception", ssl);
2698     //         return;
2699     //     }
2700     //     tracef("ssl=%s SSL_do_handshake => success", ssl);
2701     // }
2702 
2703     static string SSL_get_current_cipher(long ssl_address) {
2704         SSL* ssl = to_SSL(ssl_address);
2705         if (ssl is null) {
2706             return null;
2707         }
2708         const SSL_CIPHER* cipher = deimos.openssl.ssl.SSL_get_current_cipher(ssl);
2709         if (cipher is null) {
2710             tracef("ssl=%s SSL_get_current_cipher cipher => null", ssl);
2711             return null;
2712         }
2713         implementationMissing(false);
2714 return null;
2715         // const char* name = SSL_CIPHER_standard_name(cipher);
2716         // tracef("ssl=%s SSL_get_current_cipher => %s", ssl, name);
2717         // return env.NewStringUTF(name);        
2718     }
2719 
2720     static string SSL_get_version(long ssl_address) {
2721         SSL* ssl = to_SSL(ssl_address);
2722         if (ssl is null) {
2723             return null;
2724         }
2725         const char* protocol = deimos.openssl.ssl.SSL_get_version(ssl);
2726         return cast(string)fromStringz(protocol);        
2727     }
2728 
2729     // /**
2730     //  * Reads with the SSL_read function from the encrypted data stream
2731     //  * @return -1 if error or the end of the stream is reached.
2732     //  */
2733     // static int SSL_read(long ssl_address, FileDescriptor fd, SSLHandshakeCallbacks shc,
2734     //         byte[] b, int off, int len, int readTimeoutMillis) ;
2735 
2736     // /**
2737     //  * Writes with the SSL_write function to the encrypted data stream.
2738     //  */
2739     // static void SSL_write(long ssl_address, FileDescriptor fd,
2740     //         SSLHandshakeCallbacks shc, byte[] b, int off, int len, int writeTimeoutMillis)
2741     //         ;
2742 
2743     // static void SSL_interrupt(long ssl_address);
2744     // static void SSL_shutdown(
2745     //         long ssl_address, FileDescriptor fd, SSLHandshakeCallbacks shc) ;
2746 
2747     static int SSL_get_shutdown(long ssl_address) {
2748         const SSL* ssl = to_SSL(ssl_address);
2749         if (ssl is null) {
2750             return 0;
2751         }
2752 
2753         int status = deimos.openssl.ssl.SSL_get_shutdown(ssl);
2754         return status;        
2755     }
2756 
2757     static void SSL_free(long ssl_address) {
2758         SSL* ssl = to_SSL(ssl_address);
2759         if (ssl is null) {
2760             return;
2761         }
2762 
2763         // AppData* appData = toAppData(ssl);
2764         // delete appData;
2765         deimos.openssl.ssl.SSL_set_app_data(ssl, null);
2766         deimos.openssl.ssl.SSL_free(ssl);        
2767     }
2768 
2769     static long SSL_get_time(long ssl_address) {
2770         SSL* ssl = to_SSL(ssl_address);
2771         if (ssl is null) {
2772             return 0;
2773         }
2774 
2775         SSL_SESSION* ssl_session = deimos.openssl.ssl.SSL_get_session(ssl);
2776         if (ssl_session is null) {
2777             // BoringSSL does not protect against a NULL session.
2778             return 0;
2779         }
2780         // result must be long, not long or *1000 will overflow
2781         long result = deimos.openssl.ssl.SSL_SESSION_get_time(ssl_session);
2782         result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
2783         // NOLINTNEXTLINE(runtime/int)
2784         return result;        
2785     }
2786 
2787     static long SSL_set_timeout(long ssl_address, long millis) {
2788         SSL* ssl = to_SSL(ssl_address);
2789         if (ssl is null) {
2790             return 0;
2791         }
2792 
2793         SSL_SESSION* ssl_session = deimos.openssl.ssl.SSL_get_session(ssl);
2794         if (ssl_session is null) {
2795             // BoringSSL does not protect against a NULL session.
2796             return 0;
2797         }
2798 
2799         // Convert to seconds
2800         static const long INT_MAX_AS_JLONG = cast(long)(int.max);
2801         uint32_t timeout = cast(uint32_t)(
2802                 max(0, cast(int)(min(INT_MAX_AS_JLONG, millis / 1000))));
2803         return deimos.openssl.ssl.SSL_set_timeout(ssl_session, timeout);        
2804     }
2805 
2806     static long SSL_get_timeout(long ssl_address) {
2807         SSL* ssl = to_SSL(ssl_address);
2808         if (ssl is null) {
2809             return 0;
2810         }
2811 
2812         SSL_SESSION* ssl_session = SSL_get_session(ssl);
2813         if (ssl_session is null) {
2814             // BoringSSL does not protect against a NULL session.
2815             return 0;
2816         }
2817 
2818         long result = deimos.openssl.ssl.SSL_get_timeout(ssl_session);
2819         result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
2820         return result;        
2821     }
2822 
2823     static byte[] SSL_session_id(long ssl_address) {
2824         SSL* ssl = to_SSL(ssl_address);
2825         if (ssl is null) {
2826             return null;
2827         }
2828 
2829         SSL_SESSION* ssl_session = deimos.openssl.ssl.SSL_get_session(ssl);
2830         tracef("ssl_session=%s", ssl_session);
2831         if (ssl_session is null) {
2832             return null;
2833         }
2834 
2835         uint session_id_length;
2836         const(ubyte)* session_id = deimos.openssl.ssl.SSL_SESSION_get_id(ssl_session, &session_id_length);
2837         byte[] result = cast(byte[])session_id[0..session_id_length].dup;       
2838             
2839         return result;        
2840     }
2841 
2842     // static byte[] SSL_SESSION_session_id(long sslSessionNativePointer);
2843 
2844     // static long SSL_SESSION_get_time(long sslSessionNativePointer);
2845 
2846     // static long SSL_SESSION_get_timeout(long sslSessionNativePointer);
2847 
2848     // static string SSL_SESSION_get_version(long sslSessionNativePointer);
2849 
2850     // static string SSL_SESSION_cipher(long sslSessionNativePointer);
2851 
2852     // static void SSL_SESSION_up_ref(long sslSessionNativePointer);
2853 
2854     // static void SSL_SESSION_free(long sslSessionNativePointer);
2855 
2856     // static byte[] i2d_SSL_SESSION(long sslSessionNativePointer);
2857 
2858     // static long d2i_SSL_SESSION(byte[] data) ;
2859 
2860 
2861 
2862 version(Have_boringssl) {
2863 
2864     static void SSL_enable_signed_cert_timestamps(long ssl_address) {
2865         SSL* ssl = to_SSL(ssl_address);
2866         if (ssl is null) {
2867             return;
2868         }
2869         deimos.openssl.ssl.SSL_enable_signed_cert_timestamps(ssl);        
2870     }
2871 
2872     static void SSL_enable_ocsp_stapling(long ssl_address) {
2873         SSL* ssl = to_SSL(ssl_address);
2874         if (ssl is null) {
2875             return;
2876         }
2877 
2878         deimos.openssl.ssl.SSL_enable_ocsp_stapling(ssl);        
2879     }
2880 
2881     static string SSL_CIPHER_get_kx_name(long cipher_address) {
2882         const SSL_CIPHER* cipher = to_SSL_CIPHER(cipher_address);
2883         const char* kx_name = deimos.openssl.ssl.SSL_CIPHER_get_kx_name(cipher);
2884         string s = cast(string)fromStringz(kx_name);
2885         version(HUNT_NET_DEBUG) trace("cipher name: ", s);
2886         return s;        
2887     }
2888 
2889     /**
2890      * Returns the maximum overhead, in bytes, of sealing a record with SSL.
2891      */
2892     static int SSL_max_seal_overhead(long ssl_address) {
2893         SSL* ssl = to_SSL(ssl_address);
2894         if (ssl is null) {
2895             return 0;
2896         }
2897 
2898         return cast(int)deimos.openssl.ssl.SSL_max_seal_overhead(ssl);        
2899     }
2900 
2901     /**
2902      * Sets the local certificates and private key.
2903      *
2904      * @param ssl the SSL reference.
2905      * @param encodedCertificates the encoded form of the local certificate chain.
2906      * @param pkey a reference to the private key.
2907      * @ if a problem occurs setting the cert/key.
2908      */
2909     static void setLocalCertsAndPrivateKey(long ssl_address, byte[][] encodedCertificates,
2910         NativeRef.EVP_PKEY pkeyRef) {
2911 
2912         SSL* ssl = to_SSL(ssl_address);
2913         tracef("ssl=%s NativeCrypto_SSL_set_chain_and_key", ssl);
2914         if (ssl is null) {
2915             return;
2916         }
2917         
2918         size_t numCerts = encodedCertificates.length;
2919         if (numCerts == 0) {
2920             warning("certificates.length == 0");
2921             return;
2922         }
2923         if (pkeyRef is null) {
2924             warning("privateKey is null");
2925             return;
2926         }
2927 
2928         // Get the private key.
2929         EVP_PKEY* pkey = fromContextObject!EVP_PKEY(pkeyRef);
2930         if (pkey is null) {
2931             warning("pkey is null");
2932             return;
2933         }
2934 
2935         // Copy the certificates.
2936         CRYPTO_BUFFER*[] certBuffers = new CRYPTO_BUFFER*[numCerts];
2937         for (size_t i = 0; i < numCerts; ++i) {
2938             certBuffers[i] = ByteArrayToCryptoBuffer(encodedCertificates[i], null);
2939         }
2940 
2941         if (!deimos.openssl.ssl.SSL_set_chain_and_key(ssl, certBuffers.ptr, numCerts, pkey, null)) {
2942             error("Error configuring certificate");
2943             return;
2944         }
2945         tracef("ssl=%s NativeCrypto_SSL_set_chain_and_key => ok", ssl);
2946     }
2947 
2948     static long EVP_parse_private_key(byte[] data) {
2949         tracef("EVP_parse_private_key(lenght=%d)", data.length);
2950 
2951         CBS cbs;
2952         CBS_init(&cbs, cast(const(uint8_t)*)(data.ptr), data.length);
2953         EVP_PKEY* pkey = deimos.openssl.evp.EVP_parse_private_key(&cbs);
2954         // We intentionally do not check that cbs is exhausted, as JCA providers typically
2955         // allow parsing keys from buffers that are larger than the contained key structure
2956         // so we do the same for compatibility.
2957         if (!pkey) {
2958             warning("Error parsing private key");
2959             ERR_clear_error();
2960             return 0;
2961         }
2962 
2963         tracef("EVP_parse_private_key => %s", pkey);
2964         return cast(long)(pkey);        
2965     }
2966 
2967     /**
2968      * Returns the peer certificate chain.
2969      */
2970     static ubyte[][] SSL_get0_peer_certificates(long ssl_address) {
2971         SSL* ssl = to_SSL(ssl_address);
2972         if (ssl is null) {
2973             return null;
2974         }
2975         STACK_OF!(CRYPTO_BUFFER)* chain = deimos.openssl.ssl.SSL_get0_peer_certificates(ssl);
2976         if (chain is null) {
2977             return null;
2978         }
2979 
2980         // ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
2981         // if (array.get() is null) {
2982         //     return null;
2983         // }
2984 
2985         // tracef("ssl=%s SSL_get0_peer_certificates => %s", ssl, array.get());
2986         // return array.release(); 
2987         return CryptoBuffersToObjectArray(chain);  
2988     }
2989 
2990     static ubyte[] CryptoBufferToByteArray(const(CRYPTO_BUFFER)* buf) {
2991 
2992         size_t length = CRYPTO_BUFFER_len(buf);
2993 
2994         if (length > size_t.max) {
2995             tracef("buffer too large");
2996             return null;
2997         }
2998 
2999         ubyte* bufferData = CRYPTO_BUFFER_data(buf);
3000         ubyte[] ret = bufferData[0..length].dup;
3001 
3002         return ret;
3003     }
3004 
3005     static ubyte[][] CryptoBuffersToObjectArray(STACK_OF!(CRYPTO_BUFFER) * buffers) {
3006         int numBuffers = sk_CRYPTO_BUFFER_num(buffers);
3007         if (numBuffers > int.max) {
3008             error("too many buffers");
3009             return null;
3010         }
3011 
3012         ubyte[][] array = new ubyte[][numBuffers];
3013 
3014         for (int i = 0; i < numBuffers; ++i) {
3015             CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
3016             ubyte[] bArray = CryptoBufferToByteArray(buffer);
3017             array[i] = bArray;
3018         }
3019 
3020         return array;
3021     }
3022 
3023 
3024     extern(C) static ssl_verify_result_t cert_verify_callback(SSL* ssl, uint8_t* out_alert) {
3025         tracef("ssl=%s cert_verify_callback", ssl);
3026 
3027         AppData* appData = toAppData(ssl);
3028         if(appData is null)
3029         {
3030             warning("appData is null");
3031             return ssl_verify_result_t.ssl_verify_invalid;
3032 
3033         }
3034         // tracef("appData.name=%s", appData.name);
3035         // JNIEnv* env = appData.env;
3036         // if (env is null) {
3037         //     CONSCRYPT_LOG_ERROR("AppData.env missing in cert_verify_callback");
3038         //     tracef("ssl=%s cert_verify_callback => 0", ssl);
3039         //     return ssl_verify_invalid;
3040         // }
3041 
3042         // Create the byte[][] array that holds all the certs
3043         // byte[][] array;
3044         // deimos.openssl.ssl.SSL_get0_peer_certificates(ssl);
3045 
3046         // if (array is null) {
3047         //     return ssl_verify_result_t.ssl_verify_invalid;
3048         // }
3049 
3050         // jobject sslHandshakeCallbacks = appData.sslHandshakeCallbacks;
3051         // jclass cls = env.GetObjectClass(sslHandshakeCallbacks);
3052         // jmethodID methodID =
3053         //         env.GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
3054 
3055         // const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
3056         // const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
3057 
3058         // tracef("ssl=%s cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
3059         //         authMethod);
3060         // jstring authMethodString = env.NewStringUTF(authMethod);
3061         // env.CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString);
3062 
3063         // // We need to delete the local references so we not leak memory as this method is called
3064         // // via callback.
3065         // env.DeleteLocalRef(authMethodString);
3066 
3067         ssl_verify_result_t result = ssl_verify_result_t.ssl_verify_ok;
3068         // tracef("ssl=%s cert_verify_callback => %d", ssl, result);
3069         return result;
3070     }
3071 } else {
3072 
3073     extern(C) static int cert_verify_callback(int ok, X509_STORE_CTX* ctx) {
3074         tracef("ssl=%s cert_verify_callback", ctx);
3075         // tracef("ssl=%s cert_verify_callback => %d", ssl, result);
3076         warning("do nothing");
3077         return 0;
3078     }
3079 }
3080 
3081 
3082 }
3083 
3084 version(Have_boringssl)
3085 CRYPTO_BUFFER* ByteArrayToCryptoBuffer(byte[] array, CRYPTO_BUFFER_POOL* pool) {
3086     if (array is null) {
3087         warning("array is null");
3088         return null;
3089     }
3090 
3091     CRYPTO_BUFFER* ret = CRYPTO_BUFFER_new(cast(ubyte*)array.ptr, array.length, pool);
3092 
3093     if (ret is null) {
3094         warning("failed to allocate CRYPTO_BUFFER");
3095     }
3096 
3097     return ret;
3098 }
3099 
3100 
3101 struct AppData
3102 {
3103     string name;
3104     bool aliveAndKicking;
3105     int waitingThreads;
3106     version(Windows)  
3107     {
3108         HANDLE interruptEvent;
3109     }  
3110     else
3111     {
3112         int[2] fdsEmergency;
3113     }
3114 
3115     void* sslHandshakeCallbacks;
3116     char* applicationProtocolsData;
3117     size_t applicationProtocolsLength;
3118     void* applicationProtocolSelector;
3119 
3120     /**
3121      * Creates the application data context for the SSL*.
3122      */
3123     static AppData* create() {
3124         AppData* appData = new AppData();
3125         appData.initialize();
3126 
3127 version(Windows) {
3128         HANDLE interruptEvent = CreateEvent(null, FALSE, FALSE, null);
3129         if (interruptEvent is null) {
3130             infof("AppData::create WSACreateEvent failed: %d", WSAGetLastError());
3131             return null;
3132         }
3133         appData.interruptEvent = interruptEvent;
3134 } else {
3135         // if (pipe(appData.fdsEmergency) == -1) {
3136         //     CONSCRYPT_LOG_ERROR("AppData::create pipe(2) failed: %s", strerror(errno));
3137         //     return null;
3138         // }
3139         // if (!netutil::setBlocking(appData.fdsEmergency[0], false)) {
3140         //     CONSCRYPT_LOG_ERROR("AppData::create fcntl(2) failed: %s", strerror(errno));
3141         //     return null;
3142         // }
3143 }
3144         return appData;
3145     }
3146 
3147     ~this() {
3148         aliveAndKicking = false;
3149 version(Windows) {
3150         if (interruptEvent !is null) {
3151             CloseHandle(interruptEvent);
3152         }
3153 } else {
3154         if (fdsEmergency[0] != -1) {
3155             // close(fdsEmergency[0]);
3156         }
3157         if (fdsEmergency[1] != -1) {
3158             // close(fdsEmergency[1]);
3159         }
3160 }
3161         clearApplicationProtocols();
3162         clearApplicationProtocolSelector();
3163         clearCallbackState();
3164     }
3165 
3166     /**
3167      * Only called in server mode. Sets the protocols for ALPN negotiation.
3168      *
3169      * @param env The JNIEnv
3170      * @param alpnProtocols ALPN protocols so that they may be advertised (by the
3171      *                     server) or selected (by the client). Passing
3172      *                     non-null enables ALPN. This array is copied so that no
3173      *                     global reference to the Java byte array is maintained.
3174      */
3175     bool setApplicationProtocols(ubyte[] applicationProtocols) {
3176         // TODO: Tasks pending completion -@zxp at 8/8/2018, 4:07:35 PM
3177         // 
3178         clearApplicationProtocols();
3179         // if (applicationProtocolsJava !is null) {
3180             // jbyte* applicationProtocols =
3181             //     e.GetByteArrayElements(applicationProtocolsJava, null);
3182             if (applicationProtocols is null) {
3183                 clearCallbackState();
3184                 infof("appData=%s setApplicationCallbackState => applicationProtocols is null",
3185                           this);
3186                 return false;
3187             }
3188             applicationProtocolsLength = applicationProtocols.length;
3189                 // cast(size_t)(e.GetArrayLength(applicationProtocolsJava));
3190             char[] temp = cast(char[])applicationProtocols.dup;
3191             applicationProtocolsData = temp.ptr;
3192             // applicationProtocolsData = new char[applicationProtocolsLength];
3193             // applicationProtocolsData[0..applicationProtocolsLength] = applicationProtocols[0.. $];
3194             // memcpy(applicationProtocolsData, applicationProtocols, applicationProtocolsLength);
3195             // e.ReleaseByteArrayElements(applicationProtocolsJava, applicationProtocols, JNI_ABORT);
3196         // }
3197         return true;
3198     }
3199 
3200     /**
3201      * Only called in server mode. Sets the application-provided ALPN protocol selector.
3202      * This overrides the list of ALPN protocols, if set.
3203      */
3204     void setApplicationProtocolSelector(void* selector) {
3205         clearApplicationProtocolSelector();
3206         if (selector !is null) {
3207             // Need to a global reference since we keep this around beyond a single JNI
3208             // invocation.
3209             applicationProtocolSelector = selector;
3210         }
3211     }
3212 
3213     /**
3214      * Used to set the SSL-to-Java callback state before each SSL_*
3215      * call that may result in a callback. It should be cleared after
3216      * the operation returns with clearCallbackState.
3217      *
3218      * @param env The JNIEnv
3219      * @param shc The SSLHandshakeCallbacks
3220      * @param fd The FileDescriptor
3221      */
3222     bool setCallbackState(void* shc, void* fd) {
3223         // std::unique_ptr<NetFd> netFd;
3224         // if (fd !is null) {
3225         //     netFd.reset(new NetFd(e, fd));
3226         //     if (netFd.isClosed()) {
3227         //         infof("appData=%s setCallbackState => netFd.isClosed() == true", this);
3228         //         return false;
3229         //     }
3230         // }
3231         sslHandshakeCallbacks = shc;
3232         return true;
3233     }
3234 
3235     void clearCallbackState() {
3236         sslHandshakeCallbacks = null;
3237     }
3238 
3239 private:
3240 
3241     void initialize() {
3242         name = "default";
3243         aliveAndKicking = true;
3244         waitingThreads = 0;
3245         sslHandshakeCallbacks = null;
3246         applicationProtocolsData = null;
3247         applicationProtocolsLength = cast(size_t)(-1),
3248         applicationProtocolSelector = null;
3249 version(Windows) {
3250         interruptEvent = null;
3251 } else {
3252         fdsEmergency[0] = -1;
3253         fdsEmergency[1] = -1;
3254 }
3255     }
3256 
3257     void clearApplicationProtocols() {
3258         if (applicationProtocolsData !is null) {
3259             applicationProtocolsData = null;
3260             applicationProtocolsLength = cast(size_t)(-1);
3261         }
3262     }
3263 
3264     void clearApplicationProtocolSelector() {
3265         if (applicationProtocolSelector !is null) {
3266             applicationProtocolSelector = null;
3267         }
3268     }    
3269 }
3270 
3271 
3272 static if (OPENSSL_VERSION_BEFORE(1, 1, 1)) {
3273 
3274 /**
3275  * SSL/TLS Cipher suite name translation table
3276  * See_also:
3277  *  https://testssl.sh/openssl-iana.mapping.html
3278  */
3279 string[] tls_cipher_name_translation_table = [
3280     "ADH-SEED-SHA", "TLS-DH-anon-WITH-SEED-CBC-SHA",
3281     "AES128-GCM-SHA256", "TLS-RSA-WITH-AES-128-GCM-SHA256",
3282     "AES128-SHA256", "TLS-RSA-WITH-AES-128-CBC-SHA256",
3283     "AES128-SHA", "TLS-RSA-WITH-AES-128-CBC-SHA",
3284     "AES256-GCM-SHA384", "TLS-RSA-WITH-AES-256-GCM-SHA384",
3285     "AES256-SHA256", "TLS-RSA-WITH-AES-256-CBC-SHA256",
3286     "AES256-SHA", "TLS-RSA-WITH-AES-256-CBC-SHA",
3287     "CAMELLIA128-SHA256", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
3288     "CAMELLIA128-SHA", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
3289     "CAMELLIA256-SHA256", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
3290     "CAMELLIA256-SHA", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
3291     "DES-CBC3-SHA", "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
3292     "DES-CBC-SHA", "TLS-RSA-WITH-DES-CBC-SHA",
3293     "DH-DSS-SEED-SHA", "TLS-DH-DSS-WITH-SEED-CBC-SHA",
3294     "DHE-DSS-AES128-GCM-SHA256", "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
3295     "DHE-DSS-AES128-SHA256", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
3296     "DHE-DSS-AES128-SHA", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
3297     "DHE-DSS-AES256-GCM-SHA384", "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
3298     "DHE-DSS-AES256-SHA256", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
3299     "DHE-DSS-AES256-SHA", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
3300     "DHE-DSS-CAMELLIA128-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
3301     "DHE-DSS-CAMELLIA128-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
3302     "DHE-DSS-CAMELLIA256-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
3303     "DHE-DSS-CAMELLIA256-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
3304     "DHE-DSS-SEED-SHA", "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
3305     "DHE-RSA-AES128-GCM-SHA256", "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
3306     "DHE-RSA-AES128-SHA256", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
3307     "DHE-RSA-AES128-SHA", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
3308     "DHE-RSA-AES256-GCM-SHA384", "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
3309     "DHE-RSA-AES256-SHA256", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
3310     "DHE-RSA-AES256-SHA", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
3311     "DHE-RSA-CAMELLIA128-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
3312     "DHE-RSA-CAMELLIA128-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
3313     "DHE-RSA-CAMELLIA256-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
3314     "DHE-RSA-CAMELLIA256-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
3315     "DHE-RSA-CHACHA20-POLY1305", "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
3316     "DHE-RSA-SEED-SHA", "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
3317     "DH-RSA-SEED-SHA", "TLS-DH-RSA-WITH-SEED-CBC-SHA",
3318     "ECDH-ECDSA-AES128-GCM-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256",
3319     "ECDH-ECDSA-AES128-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256",
3320     "ECDH-ECDSA-AES128-SHA", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA",
3321     "ECDH-ECDSA-AES256-GCM-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384",
3322     "ECDH-ECDSA-AES256-SHA256", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA256",
3323     "ECDH-ECDSA-AES256-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384",
3324     "ECDH-ECDSA-AES256-SHA", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA",
3325     "ECDH-ECDSA-CAMELLIA128-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
3326     "ECDH-ECDSA-CAMELLIA128-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA",
3327     "ECDH-ECDSA-CAMELLIA256-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA256",
3328     "ECDH-ECDSA-CAMELLIA256-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA",
3329     "ECDH-ECDSA-DES-CBC3-SHA", "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA",
3330     "ECDH-ECDSA-DES-CBC-SHA", "TLS-ECDH-ECDSA-WITH-DES-CBC-SHA",
3331     "ECDH-ECDSA-RC4-SHA", "TLS-ECDH-ECDSA-WITH-RC4-128-SHA",
3332     "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
3333     "ECDHE-ECDSA-AES128-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
3334     "ECDHE-ECDSA-AES128-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA384",
3335     "ECDHE-ECDSA-AES128-SHA", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
3336     "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
3337     "ECDHE-ECDSA-AES256-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA256",
3338     "ECDHE-ECDSA-AES256-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
3339     "ECDHE-ECDSA-AES256-SHA", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA",
3340     "ECDHE-ECDSA-CAMELLIA128-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
3341     "ECDHE-ECDSA-CAMELLIA128-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA",
3342     "ECDHE-ECDSA-CAMELLIA256-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA256",
3343     "ECDHE-ECDSA-CAMELLIA256-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA",
3344     "ECDHE-ECDSA-CHACHA20-POLY1305", "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
3345     "ECDHE-ECDSA-DES-CBC3-SHA", "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA",
3346     "ECDHE-ECDSA-DES-CBC-SHA", "TLS-ECDHE-ECDSA-WITH-DES-CBC-SHA",
3347     "ECDHE-ECDSA-RC4-SHA", "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA",
3348     "ECDHE-RSA-AES128-GCM-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
3349     "ECDHE-RSA-AES128-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
3350     "ECDHE-RSA-AES128-SHA384", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA384",
3351     "ECDHE-RSA-AES128-SHA", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
3352     "ECDHE-RSA-AES256-GCM-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
3353     "ECDHE-RSA-AES256-SHA256", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA256",
3354     "ECDHE-RSA-AES256-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
3355     "ECDHE-RSA-AES256-SHA", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
3356     "ECDHE-RSA-CAMELLIA128-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
3357     "ECDHE-RSA-CAMELLIA128-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
3358     "ECDHE-RSA-CAMELLIA256-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
3359     "ECDHE-RSA-CAMELLIA256-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
3360     "ECDHE-RSA-CHACHA20-POLY1305", "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
3361     "ECDHE-RSA-DES-CBC3-SHA", "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
3362     "ECDHE-RSA-DES-CBC-SHA", "TLS-ECDHE-RSA-WITH-DES-CBC-SHA",
3363     "ECDHE-RSA-RC4-SHA", "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
3364     "ECDH-RSA-AES128-GCM-SHA256", "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256",
3365     "ECDH-RSA-AES128-SHA256", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256",
3366     "ECDH-RSA-AES128-SHA384", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA384",
3367     "ECDH-RSA-AES128-SHA", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA",
3368     "ECDH-RSA-AES256-GCM-SHA384", "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384",
3369     "ECDH-RSA-AES256-SHA256", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA256",
3370     "ECDH-RSA-AES256-SHA384", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384",
3371     "ECDH-RSA-AES256-SHA", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA",
3372     "ECDH-RSA-CAMELLIA128-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
3373     "ECDH-RSA-CAMELLIA128-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA",
3374     "ECDH-RSA-CAMELLIA256-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA256",
3375     "ECDH-RSA-CAMELLIA256-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA",
3376     "ECDH-RSA-DES-CBC3-SHA", "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA",
3377     "ECDH-RSA-DES-CBC-SHA", "TLS-ECDH-RSA-WITH-DES-CBC-SHA",
3378     "ECDH-RSA-RC4-SHA", "TLS-ECDH-RSA-WITH-RC4-128-SHA",
3379     "EDH-DSS-DES-CBC3-SHA", "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
3380     "EDH-DSS-DES-CBC-SHA", "TLS-DHE-DSS-WITH-DES-CBC-SHA",
3381     "EDH-RSA-DES-CBC3-SHA", "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
3382     "EDH-RSA-DES-CBC-SHA", "TLS-DHE-RSA-WITH-DES-CBC-SHA",
3383     "EXP-DES-CBC-SHA", "TLS-RSA-EXPORT-WITH-DES40-CBC-SHA",
3384     "EXP-EDH-DSS-DES-CBC-SHA", "TLS-DH-DSS-EXPORT-WITH-DES40-CBC-SHA",
3385     "EXP-EDH-RSA-DES-CBC-SHA", "TLS-DH-RSA-EXPORT-WITH-DES40-CBC-SHA",
3386     "EXP-RC2-CBC-MD5", "TLS-RSA-EXPORT-WITH-RC2-CBC-40-MD5",
3387     "EXP-RC4-MD5", "TLS-RSA-EXPORT-WITH-RC4-40-MD5",
3388     "NULL-MD5", "TLS-RSA-WITH-NULL-MD5",
3389     "NULL-SHA256", "TLS-RSA-WITH-NULL-SHA256",
3390     "NULL-SHA", "TLS-RSA-WITH-NULL-SHA",
3391     "PSK-3DES-EDE-CBC-SHA", "TLS-PSK-WITH-3DES-EDE-CBC-SHA",
3392     "PSK-AES128-CBC-SHA", "TLS-PSK-WITH-AES-128-CBC-SHA",
3393     "PSK-AES256-CBC-SHA", "TLS-PSK-WITH-AES-256-CBC-SHA",
3394     "PSK-RC4-SHA", "TLS-PSK-WITH-RC4-128-SHA",
3395     "RC4-MD5", "TLS-RSA-WITH-RC4-128-MD5",
3396     "RC4-SHA", "TLS-RSA-WITH-RC4-128-SHA",
3397     "SEED-SHA", "TLS-RSA-WITH-SEED-CBC-SHA",
3398     "SRP-DSS-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-3DES-EDE-CBC-SHA",
3399     "SRP-DSS-AES-128-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-128-CBC-SHA",
3400     "SRP-DSS-AES-256-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-256-CBC-SHA",
3401     "SRP-RSA-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA",
3402     "SRP-RSA-AES-128-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA",
3403     "SRP-RSA-AES-256-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"
3404 ];
3405 }