org_conscrypt_NativeCrypto.cpp revision 3e46e4ee56c8e37158f46941dedd5b436d724baa
1/*
2 * Copyright (C) 2007-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * Native glue for Java class org.conscrypt.NativeCrypto
19 */
20
21#define TO_STRING1(x) #x
22#define TO_STRING(x) TO_STRING1(x)
23#ifndef JNI_JARJAR_PREFIX
24    #ifndef CONSCRYPT_NOT_UNBUNDLED
25        #define CONSCRYPT_UNBUNDLED
26    #endif
27    #define JNI_JARJAR_PREFIX
28#endif
29
30#define LOG_TAG "NativeCrypto"
31
32#include <arpa/inet.h>
33#include <fcntl.h>
34#include <pthread.h>
35#include <sys/socket.h>
36#include <unistd.h>
37
38#ifdef CONSCRYPT_UNBUNDLED
39#include <dlfcn.h>
40#endif
41
42#include <jni.h>
43
44#include <openssl/asn1t.h>
45#include <openssl/dsa.h>
46#include <openssl/engine.h>
47#include <openssl/err.h>
48#include <openssl/evp.h>
49#include <openssl/rand.h>
50#include <openssl/rsa.h>
51#include <openssl/ssl.h>
52#include <openssl/x509v3.h>
53
54#ifndef CONSCRYPT_UNBUNDLED
55/* If we're compiled unbundled from Android system image, we use the
56 * CompatibilityCloseMonitor
57 */
58#include "AsynchronousCloseMonitor.h"
59#endif
60
61#ifndef CONSCRYPT_UNBUNDLED
62#include "cutils/log.h"
63#else
64#include <android/log.h>
65#define ALOGD(...) \
66        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);
67#define ALOGE(...) \
68        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);
69#define ALOGV(...) \
70        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__);
71#endif
72
73#ifndef CONSCRYPT_UNBUNDLED
74#include "JNIHelp.h"
75#include "JniConstants.h"
76#include "JniException.h"
77#else
78#define NATIVE_METHOD(className, functionName, signature) \
79  { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
80#define REGISTER_NATIVE_METHODS(jni_class_name) \
81  RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
82#endif
83
84#include "ScopedLocalRef.h"
85#include "ScopedPrimitiveArray.h"
86#include "ScopedUtfChars.h"
87#include "UniquePtr.h"
88#include "NetFd.h"
89
90#undef WITH_JNI_TRACE
91#undef WITH_JNI_TRACE_MD
92#undef WITH_JNI_TRACE_DATA
93
94/*
95 * How to use this for debugging with Wireshark:
96 *
97 * 1. Pull lines from logcat to a file that looks like (without quotes):
98 *     "RSA Session-ID:... Master-Key:..." <CR>
99 *     "RSA Session-ID:... Master-Key:..." <CR>
100 *     <etc>
101 * 2. Start Wireshark
102 * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in
103 *    the file you put the lines in above.
104 * 4. Follow the stream that corresponds to the desired "Session-ID" in
105 *    the Server Hello.
106 */
107#undef WITH_JNI_TRACE_KEYS
108
109#ifdef WITH_JNI_TRACE
110#define JNI_TRACE(...) \
111        ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__));     \
112/*
113        ((void)printf("I/" LOG_TAG "-jni:"));         \
114        ((void)printf(__VA_ARGS__));          \
115        ((void)printf("\n"))
116*/
117#else
118#define JNI_TRACE(...) ((void)0)
119#endif
120#ifdef WITH_JNI_TRACE_MD
121#define JNI_TRACE_MD(...) \
122        ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__));
123#else
124#define JNI_TRACE_MD(...) ((void)0)
125#endif
126// don't overwhelm logcat
127#define WITH_JNI_TRACE_DATA_CHUNK_SIZE 512
128
129static JavaVM* gJavaVM;
130static jclass openSslOutputStreamClass;
131static jclass openSslNativeReferenceClass;
132
133static jclass byteArrayClass;
134static jclass calendarClass;
135static jclass objectClass;
136static jclass objectArrayClass;
137static jclass integerClass;
138static jclass inputStreamClass;
139static jclass outputStreamClass;
140static jclass stringClass;
141
142static jfieldID openSslNativeReference_context;
143
144static jmethodID calendar_setMethod;
145static jmethodID inputStream_readMethod;
146static jmethodID integer_valueOfMethod;
147static jmethodID openSslInputStream_readLineMethod;
148static jmethodID outputStream_writeMethod;
149static jmethodID outputStream_flushMethod;
150
151struct OPENSSL_Delete {
152    void operator()(void* p) const {
153        OPENSSL_free(p);
154    }
155};
156typedef UniquePtr<unsigned char, OPENSSL_Delete> Unique_OPENSSL_str;
157
158struct BIO_Delete {
159    void operator()(BIO* p) const {
160        BIO_free_all(p);
161    }
162};
163typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
164
165struct BIGNUM_Delete {
166    void operator()(BIGNUM* p) const {
167        BN_free(p);
168    }
169};
170typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
171
172struct ASN1_INTEGER_Delete {
173    void operator()(ASN1_INTEGER* p) const {
174        ASN1_INTEGER_free(p);
175    }
176};
177typedef UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> Unique_ASN1_INTEGER;
178
179struct DH_Delete {
180    void operator()(DH* p) const {
181        DH_free(p);
182    }
183};
184typedef UniquePtr<DH, DH_Delete> Unique_DH;
185
186struct DSA_Delete {
187    void operator()(DSA* p) const {
188        DSA_free(p);
189    }
190};
191typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
192
193struct EC_GROUP_Delete {
194    void operator()(EC_GROUP* p) const {
195        EC_GROUP_clear_free(p);
196    }
197};
198typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
199
200struct EC_POINT_Delete {
201    void operator()(EC_POINT* p) const {
202        EC_POINT_clear_free(p);
203    }
204};
205typedef UniquePtr<EC_POINT, EC_POINT_Delete> Unique_EC_POINT;
206
207struct EC_KEY_Delete {
208    void operator()(EC_KEY* p) const {
209        EC_KEY_free(p);
210    }
211};
212typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
213
214struct EVP_MD_CTX_Delete {
215    void operator()(EVP_MD_CTX* p) const {
216        EVP_MD_CTX_destroy(p);
217    }
218};
219typedef UniquePtr<EVP_MD_CTX, EVP_MD_CTX_Delete> Unique_EVP_MD_CTX;
220
221struct EVP_CIPHER_CTX_Delete {
222    void operator()(EVP_CIPHER_CTX* p) const {
223        EVP_CIPHER_CTX_free(p);
224    }
225};
226typedef UniquePtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Delete> Unique_EVP_CIPHER_CTX;
227
228struct EVP_PKEY_Delete {
229    void operator()(EVP_PKEY* p) const {
230        EVP_PKEY_free(p);
231    }
232};
233typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
234
235struct PKCS8_PRIV_KEY_INFO_Delete {
236    void operator()(PKCS8_PRIV_KEY_INFO* p) const {
237        PKCS8_PRIV_KEY_INFO_free(p);
238    }
239};
240typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
241
242struct RSA_Delete {
243    void operator()(RSA* p) const {
244        RSA_free(p);
245    }
246};
247typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
248
249struct ASN1_BIT_STRING_Delete {
250    void operator()(ASN1_BIT_STRING* p) const {
251        ASN1_BIT_STRING_free(p);
252    }
253};
254typedef UniquePtr<ASN1_BIT_STRING, ASN1_BIT_STRING_Delete> Unique_ASN1_BIT_STRING;
255
256struct ASN1_OBJECT_Delete {
257    void operator()(ASN1_OBJECT* p) const {
258        ASN1_OBJECT_free(p);
259    }
260};
261typedef UniquePtr<ASN1_OBJECT, ASN1_OBJECT_Delete> Unique_ASN1_OBJECT;
262
263struct ASN1_GENERALIZEDTIME_Delete {
264    void operator()(ASN1_GENERALIZEDTIME* p) const {
265        ASN1_GENERALIZEDTIME_free(p);
266    }
267};
268typedef UniquePtr<ASN1_GENERALIZEDTIME, ASN1_GENERALIZEDTIME_Delete> Unique_ASN1_GENERALIZEDTIME;
269
270struct SSL_Delete {
271    void operator()(SSL* p) const {
272        SSL_free(p);
273    }
274};
275typedef UniquePtr<SSL, SSL_Delete> Unique_SSL;
276
277struct SSL_CTX_Delete {
278    void operator()(SSL_CTX* p) const {
279        SSL_CTX_free(p);
280    }
281};
282typedef UniquePtr<SSL_CTX, SSL_CTX_Delete> Unique_SSL_CTX;
283
284struct X509_Delete {
285    void operator()(X509* p) const {
286        X509_free(p);
287    }
288};
289typedef UniquePtr<X509, X509_Delete> Unique_X509;
290
291struct X509_NAME_Delete {
292    void operator()(X509_NAME* p) const {
293        X509_NAME_free(p);
294    }
295};
296typedef UniquePtr<X509_NAME, X509_NAME_Delete> Unique_X509_NAME;
297
298struct PKCS7_Delete {
299    void operator()(PKCS7* p) const {
300        PKCS7_free(p);
301    }
302};
303typedef UniquePtr<PKCS7, PKCS7_Delete> Unique_PKCS7;
304
305struct sk_SSL_CIPHER_Delete {
306    void operator()(STACK_OF(SSL_CIPHER)* p) const {
307        // We don't own SSL_CIPHER references, so no need for pop_free
308        sk_SSL_CIPHER_free(p);
309    }
310};
311typedef UniquePtr<STACK_OF(SSL_CIPHER), sk_SSL_CIPHER_Delete> Unique_sk_SSL_CIPHER;
312
313struct sk_X509_Delete {
314    void operator()(STACK_OF(X509)* p) const {
315        sk_X509_pop_free(p, X509_free);
316    }
317};
318typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509;
319
320struct sk_X509_NAME_Delete {
321    void operator()(STACK_OF(X509_NAME)* p) const {
322        sk_X509_NAME_pop_free(p, X509_NAME_free);
323    }
324};
325typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME;
326
327struct sk_ASN1_OBJECT_Delete {
328    void operator()(STACK_OF(ASN1_OBJECT)* p) const {
329        sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free);
330    }
331};
332typedef UniquePtr<STACK_OF(ASN1_OBJECT), sk_ASN1_OBJECT_Delete> Unique_sk_ASN1_OBJECT;
333
334struct sk_GENERAL_NAME_Delete {
335    void operator()(STACK_OF(GENERAL_NAME)* p) const {
336        sk_GENERAL_NAME_pop_free(p, GENERAL_NAME_free);
337    }
338};
339typedef UniquePtr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_Delete> Unique_sk_GENERAL_NAME;
340
341/**
342 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
343 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
344 * without triggering a warning by not using the result of release().
345 */
346#define OWNERSHIP_TRANSFERRED(obj) \
347    do { typeof (obj.release()) _dummy __attribute__((unused)) = obj.release(); } while(0)
348
349/**
350 * Frees the SSL error state.
351 *
352 * OpenSSL keeps an "error stack" per thread, and given that this code
353 * can be called from arbitrary threads that we don't keep track of,
354 * we err on the side of freeing the error state promptly (instead of,
355 * say, at thread death).
356 */
357static void freeOpenSslErrorState(void) {
358    ERR_clear_error();
359    ERR_remove_state(0);
360}
361
362/**
363 * Throws a OutOfMemoryError with the given string as a message.
364 */
365static void jniThrowOutOfMemory(JNIEnv* env, const char* message) {
366    jniThrowException(env, "java/lang/OutOfMemoryError", message);
367}
368
369/**
370 * Throws a BadPaddingException with the given string as a message.
371 */
372static void throwBadPaddingException(JNIEnv* env, const char* message) {
373    JNI_TRACE("throwBadPaddingException %s", message);
374    jniThrowException(env, "javax/crypto/BadPaddingException", message);
375}
376
377/**
378 * Throws a SignatureException with the given string as a message.
379 */
380static void throwSignatureException(JNIEnv* env, const char* message) {
381    JNI_TRACE("throwSignatureException %s", message);
382    jniThrowException(env, "java/security/SignatureException", message);
383}
384
385/**
386 * Throws a InvalidKeyException with the given string as a message.
387 */
388static void throwInvalidKeyException(JNIEnv* env, const char* message) {
389    JNI_TRACE("throwInvalidKeyException %s", message);
390    jniThrowException(env, "java/security/InvalidKeyException", message);
391}
392
393/**
394 * Throws a SignatureException with the given string as a message.
395 */
396static void throwIllegalBlockSizeException(JNIEnv* env, const char* message) {
397    JNI_TRACE("throwIllegalBlockSizeException %s", message);
398    jniThrowException(env, "javax/crypto/IllegalBlockSizeException", message);
399}
400
401/**
402 * Throws a NoSuchAlgorithmException with the given string as a message.
403 */
404static void throwNoSuchAlgorithmException(JNIEnv* env, const char* message) {
405    JNI_TRACE("throwUnknownAlgorithmException %s", message);
406    jniThrowException(env, "java/security/NoSuchAlgorithmException", message);
407}
408
409static void throwForAsn1Error(JNIEnv* env, int reason, const char *message) {
410    switch (reason) {
411    case ASN1_R_UNABLE_TO_DECODE_RSA_KEY:
412    case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY:
413    case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:
414    case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:
415    case ASN1_R_WRONG_PUBLIC_KEY_TYPE:
416        throwInvalidKeyException(env, message);
417        break;
418    case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
419        throwNoSuchAlgorithmException(env, message);
420        break;
421    default:
422        jniThrowRuntimeException(env, message);
423        break;
424    }
425}
426
427static void throwForEvpError(JNIEnv* env, int reason, const char *message) {
428    switch (reason) {
429    case EVP_R_BAD_DECRYPT:
430        throwBadPaddingException(env, message);
431        break;
432    case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
433    case EVP_R_WRONG_FINAL_BLOCK_LENGTH:
434        throwIllegalBlockSizeException(env, message);
435        break;
436    case EVP_R_BAD_KEY_LENGTH:
437    case EVP_R_BN_DECODE_ERROR:
438    case EVP_R_BN_PUBKEY_ERROR:
439    case EVP_R_INVALID_KEY_LENGTH:
440    case EVP_R_MISSING_PARAMETERS:
441    case EVP_R_UNSUPPORTED_KEY_SIZE:
442    case EVP_R_UNSUPPORTED_KEYLENGTH:
443        throwInvalidKeyException(env, message);
444        break;
445    case EVP_R_WRONG_PUBLIC_KEY_TYPE:
446        throwSignatureException(env, message);
447        break;
448    case EVP_R_UNSUPPORTED_ALGORITHM:
449        throwNoSuchAlgorithmException(env, message);
450        break;
451    default:
452        jniThrowRuntimeException(env, message);
453        break;
454    }
455}
456
457static void throwForRsaError(JNIEnv* env, int reason, const char *message) {
458    switch (reason) {
459    case RSA_R_BLOCK_TYPE_IS_NOT_01:
460    case RSA_R_BLOCK_TYPE_IS_NOT_02:
461        throwBadPaddingException(env, message);
462        break;
463    case RSA_R_ALGORITHM_MISMATCH:
464    case RSA_R_BAD_SIGNATURE:
465    case RSA_R_DATA_GREATER_THAN_MOD_LEN:
466    case RSA_R_DATA_TOO_LARGE_FOR_MODULUS:
467    case RSA_R_INVALID_MESSAGE_LENGTH:
468    case RSA_R_WRONG_SIGNATURE_LENGTH:
469        throwSignatureException(env, message);
470        break;
471    case RSA_R_UNKNOWN_ALGORITHM_TYPE:
472        throwNoSuchAlgorithmException(env, message);
473        break;
474    case RSA_R_MODULUS_TOO_LARGE:
475    case RSA_R_NO_PUBLIC_EXPONENT:
476        throwInvalidKeyException(env, message);
477        break;
478    default:
479        jniThrowRuntimeException(env, message);
480        break;
481    }
482}
483
484static void throwForX509Error(JNIEnv* env, int reason, const char *message) {
485    switch (reason) {
486    case X509_R_UNSUPPORTED_ALGORITHM:
487        throwNoSuchAlgorithmException(env, message);
488        break;
489    default:
490        jniThrowRuntimeException(env, message);
491        break;
492    }
493}
494
495/*
496 * Checks this thread's OpenSSL error queue and throws a RuntimeException if
497 * necessary.
498 *
499 * @return true if an exception was thrown, false if not.
500 */
501static bool throwExceptionIfNecessary(JNIEnv* env, const char* location  __attribute__ ((unused))) {
502    const char* file;
503    int line;
504    const char* data;
505    int flags;
506    unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags);
507    int result = false;
508
509    if (error != 0) {
510        char message[256];
511        ERR_error_string_n(error, message, sizeof(message));
512        int library = ERR_GET_LIB(error);
513        int reason = ERR_GET_REASON(error);
514        JNI_TRACE("OpenSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s",
515                  location, error, library, reason, file, line, message,
516                  (flags & ERR_TXT_STRING) ? data : "(no data)");
517        switch (library) {
518        case ERR_LIB_RSA:
519            throwForRsaError(env, reason, message);
520            break;
521        case ERR_LIB_ASN1:
522            throwForAsn1Error(env, reason, message);
523            break;
524        case ERR_LIB_EVP:
525            throwForEvpError(env, reason, message);
526            break;
527        case ERR_LIB_X509:
528            throwForX509Error(env, reason, message);
529            break;
530        case ERR_LIB_DSA:
531            throwInvalidKeyException(env, message);
532            break;
533        default:
534            jniThrowRuntimeException(env, message);
535            break;
536        }
537        result = true;
538    }
539
540    freeOpenSslErrorState();
541    return result;
542}
543
544/**
545 * Throws an SocketTimeoutException with the given string as a message.
546 */
547static void throwSocketTimeoutException(JNIEnv* env, const char* message) {
548    JNI_TRACE("throwSocketTimeoutException %s", message);
549    jniThrowException(env, "java/net/SocketTimeoutException", message);
550}
551
552/**
553 * Throws a javax.net.ssl.SSLException with the given string as a message.
554 */
555static void throwSSLHandshakeExceptionStr(JNIEnv* env, const char* message) {
556    JNI_TRACE("throwSSLExceptionStr %s", message);
557    jniThrowException(env, "javax/net/ssl/SSLHandshakeException", message);
558}
559
560/**
561 * Throws a javax.net.ssl.SSLException with the given string as a message.
562 */
563static void throwSSLExceptionStr(JNIEnv* env, const char* message) {
564    JNI_TRACE("throwSSLExceptionStr %s", message);
565    jniThrowException(env, "javax/net/ssl/SSLException", message);
566}
567
568/**
569 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message.
570 */
571static void throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) {
572    JNI_TRACE("throwSSLProtocolExceptionStr %s", message);
573    jniThrowException(env, "javax/net/ssl/SSLProtocolException", message);
574}
575
576/**
577 * Throws an SSLException with a message constructed from the current
578 * SSL errors. This will also log the errors.
579 *
580 * @param env the JNI environment
581 * @param ssl the possibly NULL SSL
582 * @param sslErrorCode error code returned from SSL_get_error() or
583 * SSL_ERROR_NONE to probe with ERR_get_error
584 * @param message null-ok; general error message
585 */
586static void throwSSLExceptionWithSslErrors(JNIEnv* env, SSL* ssl, int sslErrorCode,
587        const char* message, void (*actualThrow)(JNIEnv*, const char*) = throwSSLExceptionStr) {
588
589    if (message == NULL) {
590        message = "SSL error";
591    }
592
593    // First consult the SSL error code for the general message.
594    const char* sslErrorStr = NULL;
595    switch (sslErrorCode) {
596        case SSL_ERROR_NONE:
597            if (ERR_peek_error() == 0) {
598                sslErrorStr = "OK";
599            } else {
600                sslErrorStr = "";
601            }
602            break;
603        case SSL_ERROR_SSL:
604            sslErrorStr = "Failure in SSL library, usually a protocol error";
605            break;
606        case SSL_ERROR_WANT_READ:
607            sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this.";
608            break;
609        case SSL_ERROR_WANT_WRITE:
610            sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this.";
611            break;
612        case SSL_ERROR_WANT_X509_LOOKUP:
613            sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this.";
614            break;
615        case SSL_ERROR_SYSCALL:
616            sslErrorStr = "I/O error during system call";
617            break;
618        case SSL_ERROR_ZERO_RETURN:
619            sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this.";
620            break;
621        case SSL_ERROR_WANT_CONNECT:
622            sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this.";
623            break;
624        case SSL_ERROR_WANT_ACCEPT:
625            sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this.";
626            break;
627        default:
628            sslErrorStr = "Unknown SSL error";
629    }
630
631    // Prepend either our explicit message or a default one.
632    char* str;
633    if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) {
634        // problem with asprintf, just throw argument message, log everything
635        actualThrow(env, message);
636        ALOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr);
637        freeOpenSslErrorState();
638        return;
639    }
640
641    char* allocStr = str;
642
643    // For protocol errors, SSL might have more information.
644    if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) {
645        // Append each error as an additional line to the message.
646        for (;;) {
647            char errStr[256];
648            const char* file;
649            int line;
650            const char* data;
651            int flags;
652            unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags);
653            if (err == 0) {
654                break;
655            }
656
657            ERR_error_string_n(err, errStr, sizeof(errStr));
658
659            int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
660                               (allocStr == NULL) ? "" : allocStr,
661                               errStr,
662                               file,
663                               line,
664                               (flags & ERR_TXT_STRING) ? data : "(no data)",
665                               flags);
666
667            if (ret < 0) {
668                break;
669            }
670
671            free(allocStr);
672            allocStr = str;
673        }
674    // For errors during system calls, errno might be our friend.
675    } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
676        if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
677            free(allocStr);
678            allocStr = str;
679        }
680    // If the error code is invalid, print it.
681    } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
682        if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
683            free(allocStr);
684            allocStr = str;
685        }
686    }
687
688    if (sslErrorCode == SSL_ERROR_SSL) {
689        throwSSLProtocolExceptionStr(env, allocStr);
690    } else {
691        actualThrow(env, allocStr);
692    }
693
694    ALOGV("%s", allocStr);
695    free(allocStr);
696    freeOpenSslErrorState();
697}
698
699/**
700 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
701 * If this function returns NULL and <code>throwIfNull</code> is
702 * passed as <code>true</code>, then this function will call
703 * <code>throwSSLExceptionStr</code> before returning, so in this case of
704 * NULL, a caller of this function should simply return and allow JNI
705 * to do its thing.
706 *
707 * @param env the JNI environment
708 * @param ssl_address; the ssl_address pointer as an integer
709 * @param throwIfNull whether to throw if the SSL pointer is NULL
710 * @returns the pointer, which may be NULL
711 */
712static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
713    SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
714    if ((ssl_ctx == NULL) && throwIfNull) {
715        JNI_TRACE("ssl_ctx == null");
716        jniThrowNullPointerException(env, "ssl_ctx == null");
717    }
718    return ssl_ctx;
719}
720
721static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
722    SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
723    if ((ssl == NULL) && throwIfNull) {
724        JNI_TRACE("ssl == null");
725        jniThrowNullPointerException(env, "ssl == null");
726    }
727    return ssl;
728}
729
730static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
731    SSL_SESSION* ssl_session
732        = reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
733    if ((ssl_session == NULL) && throwIfNull) {
734        JNI_TRACE("ssl_session == null");
735        jniThrowNullPointerException(env, "ssl_session == null");
736    }
737    return ssl_session;
738}
739
740static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
741    SSL_CIPHER* ssl_cipher
742        = reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
743    if ((ssl_cipher == NULL) && throwIfNull) {
744        JNI_TRACE("ssl_cipher == null");
745        jniThrowNullPointerException(env, "ssl_cipher == null");
746    }
747    return ssl_cipher;
748}
749
750template<typename T>
751static T* fromContextObject(JNIEnv* env, jobject contextObject) {
752    T* ref = reinterpret_cast<T*>(env->GetLongField(contextObject, openSslNativeReference_context));
753    if (ref == NULL) {
754        JNI_TRACE("ctx == null");
755        jniThrowNullPointerException(env, "ctx == null");
756    }
757    return ref;
758}
759
760/**
761 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
762 * allocate the BIGNUM if *dest == NULL. Returns true on success. If the
763 * return value is false, there is a pending exception.
764 */
765static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
766    JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
767    if (dest == NULL) {
768        JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
769        jniThrowNullPointerException(env, "dest == null");
770        return false;
771    }
772    JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
773
774    ScopedByteArrayRO sourceBytes(env, source);
775    if (sourceBytes.get() == NULL) {
776        JNI_TRACE("arrayToBignum(%p, %p) => NULL", source, dest);
777        return false;
778    }
779    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
780    size_t tmpSize = sourceBytes.size();
781
782    /* if the array is empty, it is zero. */
783    if (tmpSize == 0) {
784        if (*dest == NULL) {
785            *dest = BN_new();
786        }
787        BN_zero(*dest);
788        return true;
789    }
790
791    UniquePtr<unsigned char[]> twosComplement;
792    bool negative = (tmp[0] & 0x80) != 0;
793    if (negative) {
794        // Need to convert to two's complement.
795        twosComplement.reset(new unsigned char[tmpSize]);
796        unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
797        memcpy(twosBytes, tmp, tmpSize);
798        tmp = twosBytes;
799
800        bool carry = true;
801        for (ssize_t i = tmpSize - 1; i >= 0; i--) {
802            twosBytes[i] ^= 0xFF;
803            if (carry) {
804                carry = (++twosBytes[i]) == 0;
805            }
806        }
807    }
808    BIGNUM *ret = BN_bin2bn(tmp, tmpSize, *dest);
809    if (ret == NULL) {
810        jniThrowRuntimeException(env, "Conversion to BIGNUM failed");
811        JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
812        return false;
813    }
814    BN_set_negative(ret, negative ? 1 : 0);
815
816    *dest = ret;
817    JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
818    return true;
819}
820
821/**
822 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
823 */
824static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
825    JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
826
827    if (source == NULL) {
828        jniThrowNullPointerException(env, sourceName);
829        return NULL;
830    }
831
832    size_t numBytes = BN_num_bytes(source) + 1;
833    jbyteArray javaBytes = env->NewByteArray(numBytes);
834    ScopedByteArrayRW bytes(env, javaBytes);
835    if (bytes.get() == NULL) {
836        JNI_TRACE("bignumToArray(%p, %s) => NULL", source, sourceName);
837        return NULL;
838    }
839
840    unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
841    if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
842        throwExceptionIfNecessary(env, "bignumToArray");
843        return NULL;
844    }
845
846    // Set the sign and convert to two's complement if necessary for the Java code.
847    if (BN_is_negative(source)) {
848        bool carry = true;
849        for (ssize_t i = numBytes - 1; i >= 0; i--) {
850            tmp[i] ^= 0xFF;
851            if (carry) {
852                carry = (++tmp[i]) == 0;
853            }
854        }
855        *tmp |= 0x80;
856    } else {
857        *tmp = 0x00;
858    }
859
860    JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
861    return javaBytes;
862}
863
864/**
865 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
866 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
867 * from the OpenSSL ASN.1 API.
868 */
869template<typename T, int (*i2d_func)(T*, unsigned char**)>
870jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj) {
871    if (obj == NULL) {
872        jniThrowNullPointerException(env, "ASN1 input == null");
873        JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
874        return NULL;
875    }
876
877    int derLen = i2d_func(obj, NULL);
878    if (derLen < 0) {
879        throwExceptionIfNecessary(env, "ASN1ToByteArray");
880        JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
881        return NULL;
882    }
883
884    ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
885    if (byteArray.get() == NULL) {
886        JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
887        return NULL;
888    }
889
890    ScopedByteArrayRW bytes(env, byteArray.get());
891    if (bytes.get() == NULL) {
892        JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
893        return NULL;
894    }
895
896    unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
897    int ret = i2d_func(obj, &p);
898    if (ret < 0) {
899        throwExceptionIfNecessary(env, "ASN1ToByteArray");
900        JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
901        return NULL;
902    }
903
904    JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
905    return byteArray.release();
906}
907
908template<typename T, T* (*d2i_func)(T**, const unsigned char**, long)>
909T* ByteArrayToASN1(JNIEnv* env, jbyteArray byteArray) {
910    ScopedByteArrayRO bytes(env, byteArray);
911    if (bytes.get() == NULL) {
912        JNI_TRACE("ByteArrayToASN1(%p) => using byte array failed", byteArray);
913        return 0;
914    }
915
916    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
917    return d2i_func(NULL, &tmp, bytes.size());
918}
919
920/**
921 * Converts ASN.1 BIT STRING to a jbooleanArray.
922 */
923jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, ASN1_BIT_STRING* bitStr) {
924    int size = bitStr->length * 8;
925    if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
926        size -= bitStr->flags & 0x07;
927    }
928
929    ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
930    if (bitsRef.get() == NULL) {
931        return NULL;
932    }
933
934    ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
935    for (int i = 0; i < static_cast<int>(bitsArray.size()); i++) {
936        bitsArray[i] = ASN1_BIT_STRING_get_bit(bitStr, i);
937    }
938
939    return bitsRef.release();
940}
941
942/**
943 * To avoid the round-trip to ASN.1 and back in X509_dup, we just up the reference count.
944 */
945static X509* X509_dup_nocopy(X509* x509) {
946    if (x509 == NULL) {
947        return NULL;
948    }
949    CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
950    return x509;
951}
952
953/*
954 * Sets the read and write BIO for an SSL connection and removes it when it goes out of scope.
955 * We hang on to BIO with a JNI GlobalRef and we want to remove them as soon as possible.
956 */
957class ScopedSslBio {
958public:
959    ScopedSslBio(SSL *ssl, BIO* rbio, BIO* wbio) : ssl_(ssl) {
960        SSL_set_bio(ssl_, rbio, wbio);
961        CRYPTO_add(&rbio->references,1,CRYPTO_LOCK_BIO);
962        CRYPTO_add(&wbio->references,1,CRYPTO_LOCK_BIO);
963    }
964
965    ~ScopedSslBio() {
966        SSL_set_bio(ssl_, NULL, NULL);
967    }
968
969private:
970    SSL* const ssl_;
971};
972
973/**
974 * BIO for InputStream
975 */
976class BIO_Stream {
977public:
978    BIO_Stream(jobject stream) :
979            mEof(false) {
980        JNIEnv* env = getEnv();
981        mStream = env->NewGlobalRef(stream);
982    }
983
984    ~BIO_Stream() {
985        JNIEnv* env = getEnv();
986
987        env->DeleteGlobalRef(mStream);
988    }
989
990    bool isEof() const {
991        JNI_TRACE("isEof? %s", mEof ? "yes" : "no");
992        return mEof;
993    }
994
995    int flush() {
996        JNIEnv* env = getEnv();
997        if (env == NULL) {
998            return -1;
999        }
1000
1001        if (env->ExceptionCheck()) {
1002            JNI_TRACE("BIO_Stream::flush called with pending exception");
1003            return -1;
1004        }
1005
1006        env->CallVoidMethod(mStream, outputStream_flushMethod);
1007        if (env->ExceptionCheck()) {
1008            return -1;
1009        }
1010
1011        return 1;
1012    }
1013
1014protected:
1015    jobject getStream() {
1016        return mStream;
1017    }
1018
1019    void setEof(bool eof) {
1020        mEof = eof;
1021    }
1022
1023    JNIEnv* getEnv() {
1024        JNIEnv* env;
1025
1026        if (gJavaVM->AttachCurrentThread(&env, NULL) < 0) {
1027            return NULL;
1028        }
1029
1030        return env;
1031    }
1032
1033private:
1034    jobject mStream;
1035    bool mEof;
1036};
1037
1038class BIO_InputStream : public BIO_Stream {
1039public:
1040    BIO_InputStream(jobject stream) :
1041            BIO_Stream(stream) {
1042    }
1043
1044    int read(char *buf, int len) {
1045        return read_internal(buf, len, inputStream_readMethod);
1046    }
1047
1048    int gets(char *buf, int len) {
1049        if (len > PEM_LINE_LENGTH) {
1050            len = PEM_LINE_LENGTH;
1051        }
1052
1053        int read = read_internal(buf, len - 1, openSslInputStream_readLineMethod);
1054        buf[read] = '\0';
1055        JNI_TRACE("BIO::gets \"%s\"", buf);
1056        return read;
1057    }
1058
1059private:
1060    int read_internal(char *buf, int len, jmethodID method) {
1061        JNIEnv* env = getEnv();
1062        if (env == NULL) {
1063            JNI_TRACE("BIO_InputStream::read could not get JNIEnv");
1064            return -1;
1065        }
1066
1067        if (env->ExceptionCheck()) {
1068            JNI_TRACE("BIO_InputStream::read called with pending exception");
1069            return -1;
1070        }
1071
1072        ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1073        if (javaBytes.get() == NULL) {
1074            JNI_TRACE("BIO_InputStream::read failed call to NewByteArray");
1075            return -1;
1076        }
1077
1078        jint read = env->CallIntMethod(getStream(), method, javaBytes.get());
1079        if (env->ExceptionCheck()) {
1080            JNI_TRACE("BIO_InputStream::read failed call to InputStream#read");
1081            return -1;
1082        }
1083
1084        /* Java uses -1 to indicate EOF condition. */
1085        if (read == -1) {
1086            setEof(true);
1087            read = 0;
1088        } else if (read > 0) {
1089            env->GetByteArrayRegion(javaBytes.get(), 0, read, reinterpret_cast<jbyte*>(buf));
1090        }
1091
1092        return read;
1093    }
1094
1095public:
1096    /** Length of PEM-encoded line (64) plus CR plus NULL */
1097    static const int PEM_LINE_LENGTH = 66;
1098};
1099
1100class BIO_OutputStream : public BIO_Stream {
1101public:
1102    BIO_OutputStream(jobject stream) :
1103            BIO_Stream(stream) {
1104    }
1105
1106    int write(const char *buf, int len) {
1107        JNIEnv* env = getEnv();
1108        if (env == NULL) {
1109            JNI_TRACE("BIO_OutputStream::write => could not get JNIEnv");
1110            return -1;
1111        }
1112
1113        if (env->ExceptionCheck()) {
1114            JNI_TRACE("BIO_OutputStream::write => called with pending exception");
1115            return -1;
1116        }
1117
1118        ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1119        if (javaBytes.get() == NULL) {
1120            JNI_TRACE("BIO_OutputStream::write => failed call to NewByteArray");
1121            return -1;
1122        }
1123
1124        env->SetByteArrayRegion(javaBytes.get(), 0, len, reinterpret_cast<const jbyte*>(buf));
1125
1126        env->CallVoidMethod(getStream(), outputStream_writeMethod, javaBytes.get());
1127        if (env->ExceptionCheck()) {
1128            JNI_TRACE("BIO_OutputStream::write => failed call to OutputStream#write");
1129            return -1;
1130        }
1131
1132        return len;
1133    }
1134};
1135
1136static int bio_stream_create(BIO *b) {
1137    b->init = 1;
1138    b->num = 0;
1139    b->ptr = NULL;
1140    b->flags = 0;
1141    return 1;
1142}
1143
1144static int bio_stream_destroy(BIO *b) {
1145    if (b == NULL) {
1146        return 0;
1147    }
1148
1149    if (b->ptr != NULL) {
1150        delete static_cast<BIO_Stream*>(b->ptr);
1151        b->ptr = NULL;
1152    }
1153
1154    b->init = 0;
1155    b->flags = 0;
1156    return 1;
1157}
1158
1159static int bio_stream_read(BIO *b, char *buf, int len) {
1160    BIO_clear_retry_flags(b);
1161    BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
1162    int ret = stream->read(buf, len);
1163    if (ret == 0) {
1164        // EOF is indicated by -1 with a BIO flag.
1165        BIO_set_retry_read(b);
1166        return -1;
1167    }
1168    return ret;
1169}
1170
1171static int bio_stream_write(BIO *b, const char *buf, int len) {
1172    BIO_clear_retry_flags(b);
1173    BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1174    return stream->write(buf, len);
1175}
1176
1177static int bio_stream_puts(BIO *b, const char *buf) {
1178    BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1179    return stream->write(buf, strlen(buf));
1180}
1181
1182static int bio_stream_gets(BIO *b, char *buf, int len) {
1183    BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
1184    return stream->gets(buf, len);
1185}
1186
1187static void bio_stream_assign(BIO *b, BIO_Stream* stream) {
1188    b->ptr = static_cast<void*>(stream);
1189}
1190
1191static long bio_stream_ctrl(BIO *b, int cmd, long, void *) {
1192    BIO_Stream* stream = static_cast<BIO_Stream*>(b->ptr);
1193
1194    switch (cmd) {
1195    case BIO_CTRL_EOF:
1196        return stream->isEof() ? 1 : 0;
1197    case BIO_CTRL_FLUSH:
1198        return stream->flush();
1199    default:
1200        return 0;
1201    }
1202}
1203
1204static BIO_METHOD stream_bio_method = {
1205        ( 100 | 0x0400 ), /* source/sink BIO */
1206        "InputStream/OutputStream BIO",
1207        bio_stream_write, /* bio_write */
1208        bio_stream_read, /* bio_read */
1209        bio_stream_puts, /* bio_puts */
1210        bio_stream_gets, /* bio_gets */
1211        bio_stream_ctrl, /* bio_ctrl */
1212        bio_stream_create, /* bio_create */
1213        bio_stream_destroy, /* bio_free */
1214        NULL, /* no bio_callback_ctrl */
1215};
1216
1217#ifdef CONSCRYPT_UNBUNDLED
1218/*
1219 * This is a big hack; don't learn from this. Basically what happened is we do
1220 * not have an API way to insert ourselves into the AsynchronousCloseMonitor
1221 * that's compiled into the native libraries for libcore when we're unbundled.
1222 * So we try to look up the symbol from the main library to find it.
1223 */
1224typedef void (*acm_ctor_func)(void*, int);
1225typedef void (*acm_dtor_func)(void*);
1226static acm_ctor_func async_close_monitor_ctor = NULL;
1227static acm_dtor_func async_close_monitor_dtor = NULL;
1228
1229class CompatibilityCloseMonitor {
1230public:
1231    CompatibilityCloseMonitor(int fd) {
1232        if (async_close_monitor_ctor != NULL) {
1233            async_close_monitor_ctor(objBuffer, fd);
1234        }
1235    }
1236
1237    ~CompatibilityCloseMonitor() {
1238        if (async_close_monitor_dtor != NULL) {
1239            async_close_monitor_dtor(objBuffer);
1240        }
1241    }
1242private:
1243    char objBuffer[256];
1244#if 0
1245    static_assert(sizeof(objBuffer) > 2*sizeof(AsynchronousCloseMonitor),
1246                  "CompatibilityCloseMonitor must be larger than the actual object");
1247#endif
1248};
1249
1250static void findAsynchronousCloseMonitorFuncs() {
1251    void *lib = dlopen("libjavacore.so", RTLD_NOW);
1252    if (lib != NULL) {
1253        async_close_monitor_ctor = (acm_ctor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorC1Ei");
1254        async_close_monitor_dtor = (acm_dtor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorD1Ev");
1255    }
1256}
1257#endif
1258
1259/**
1260 * Copied from libnativehelper NetworkUtilites.cpp
1261 */
1262static bool setBlocking(int fd, bool blocking) {
1263    int flags = fcntl(fd, F_GETFL);
1264    if (flags == -1) {
1265        return false;
1266    }
1267
1268    if (!blocking) {
1269        flags |= O_NONBLOCK;
1270    } else {
1271        flags &= ~O_NONBLOCK;
1272    }
1273
1274    int rc = fcntl(fd, F_SETFL, flags);
1275    return (rc != -1);
1276}
1277
1278/**
1279 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
1280 * suppose there are not many other ways to do this on a Linux system (modulo
1281 * isomorphism).
1282 */
1283#define MUTEX_TYPE pthread_mutex_t
1284#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
1285#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
1286#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
1287#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
1288#define THREAD_ID pthread_self()
1289#define THROW_SSLEXCEPTION (-2)
1290#define THROW_SOCKETTIMEOUTEXCEPTION (-3)
1291#define THROWN_EXCEPTION (-4)
1292
1293static MUTEX_TYPE* mutex_buf = NULL;
1294
1295static void locking_function(int mode, int n, const char*, int) {
1296    if (mode & CRYPTO_LOCK) {
1297        MUTEX_LOCK(mutex_buf[n]);
1298    } else {
1299        MUTEX_UNLOCK(mutex_buf[n]);
1300    }
1301}
1302
1303static unsigned long id_function(void) {
1304    return ((unsigned long)THREAD_ID);
1305}
1306
1307int THREAD_setup(void) {
1308    mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
1309    if (!mutex_buf) {
1310        return 0;
1311    }
1312
1313    for (int i = 0; i < CRYPTO_num_locks(); ++i) {
1314        MUTEX_SETUP(mutex_buf[i]);
1315    }
1316
1317    CRYPTO_set_id_callback(id_function);
1318    CRYPTO_set_locking_callback(locking_function);
1319
1320    return 1;
1321}
1322
1323int THREAD_cleanup(void) {
1324    if (!mutex_buf) {
1325        return 0;
1326    }
1327
1328    CRYPTO_set_id_callback(NULL);
1329    CRYPTO_set_locking_callback(NULL);
1330
1331    for (int i = 0; i < CRYPTO_num_locks( ); i++) {
1332        MUTEX_CLEANUP(mutex_buf[i]);
1333    }
1334
1335    free(mutex_buf);
1336    mutex_buf = NULL;
1337
1338    return 1;
1339}
1340
1341/**
1342 * Initialization phase for every OpenSSL job: Loads the Error strings, the
1343 * crypto algorithms and reset the OpenSSL library
1344 */
1345static void NativeCrypto_clinit(JNIEnv*, jclass)
1346{
1347    SSL_load_error_strings();
1348    ERR_load_crypto_strings();
1349    SSL_library_init();
1350    OpenSSL_add_all_algorithms();
1351    THREAD_setup();
1352}
1353
1354static void NativeCrypto_ENGINE_load_dynamic(JNIEnv*, jclass) {
1355    JNI_TRACE("ENGINE_load_dynamic()");
1356
1357    ENGINE_load_dynamic();
1358}
1359
1360static jlong NativeCrypto_ENGINE_by_id(JNIEnv* env, jclass, jstring idJava) {
1361    JNI_TRACE("ENGINE_by_id(%p)", idJava);
1362
1363    ScopedUtfChars id(env, idJava);
1364    if (id.c_str() == NULL) {
1365        JNI_TRACE("ENGINE_by_id(%p) => id == null", idJava);
1366        return 0;
1367    }
1368    JNI_TRACE("ENGINE_by_id(\"%s\")", id.c_str());
1369
1370    ENGINE* e = ENGINE_by_id(id.c_str());
1371    if (e == NULL) {
1372        freeOpenSslErrorState();
1373    }
1374
1375    JNI_TRACE("ENGINE_by_id(\"%s\") => %p", id.c_str(), e);
1376    return reinterpret_cast<uintptr_t>(e);
1377}
1378
1379static jint NativeCrypto_ENGINE_add(JNIEnv* env, jclass, jlong engineRef) {
1380    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1381    JNI_TRACE("ENGINE_add(%p)", e);
1382
1383    if (e == NULL) {
1384        jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1385        return 0;
1386    }
1387
1388    int ret = ENGINE_add(e);
1389
1390    /*
1391     * We tolerate errors, because the most likely error is that
1392     * the ENGINE is already in the list.
1393     */
1394    freeOpenSslErrorState();
1395
1396    JNI_TRACE("ENGINE_add(%p) => %d", e, ret);
1397    return ret;
1398}
1399
1400static jint NativeCrypto_ENGINE_init(JNIEnv* env, jclass, jlong engineRef) {
1401    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1402    JNI_TRACE("ENGINE_init(%p)", e);
1403
1404    if (e == NULL) {
1405        jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1406        return 0;
1407    }
1408
1409    int ret = ENGINE_init(e);
1410    JNI_TRACE("ENGINE_init(%p) => %d", e, ret);
1411    return ret;
1412}
1413
1414static jint NativeCrypto_ENGINE_finish(JNIEnv* env, jclass, jlong engineRef) {
1415    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1416    JNI_TRACE("ENGINE_finish(%p)", e);
1417
1418    if (e == NULL) {
1419        jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1420        return 0;
1421    }
1422
1423    int ret = ENGINE_finish(e);
1424    JNI_TRACE("ENGINE_finish(%p) => %d", e, ret);
1425    return ret;
1426}
1427
1428static jint NativeCrypto_ENGINE_free(JNIEnv* env, jclass, jlong engineRef) {
1429    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1430    JNI_TRACE("ENGINE_free(%p)", e);
1431
1432    if (e == NULL) {
1433        jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1434        return 0;
1435    }
1436
1437    int ret = ENGINE_free(e);
1438    JNI_TRACE("ENGINE_free(%p) => %d", e, ret);
1439    return ret;
1440}
1441
1442static jlong NativeCrypto_ENGINE_load_private_key(JNIEnv* env, jclass, jlong engineRef,
1443        jstring idJava) {
1444    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1445    JNI_TRACE("ENGINE_load_private_key(%p, %p)", e, idJava);
1446
1447    ScopedUtfChars id(env, idJava);
1448    if (id.c_str() == NULL) {
1449        jniThrowException(env, "java/lang/IllegalArgumentException", "id == NULL");
1450        return 0;
1451    }
1452
1453    Unique_EVP_PKEY pkey(ENGINE_load_private_key(e, id.c_str(), NULL, NULL));
1454    if (pkey.get() == NULL) {
1455        throwExceptionIfNecessary(env, "ENGINE_load_private_key");
1456        return 0;
1457    }
1458
1459    JNI_TRACE("ENGINE_load_private_key(%p, %p) => %p", e, idJava, pkey.get());
1460    return reinterpret_cast<uintptr_t>(pkey.release());
1461}
1462
1463static jstring NativeCrypto_ENGINE_get_id(JNIEnv* env, jclass, jlong engineRef)
1464{
1465    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1466    JNI_TRACE("ENGINE_get_id(%p)", e);
1467
1468    if (e == NULL) {
1469        jniThrowNullPointerException(env, "engine == null");
1470        JNI_TRACE("ENGINE_get_id(%p) => engine == null", e);
1471        return NULL;
1472    }
1473
1474    const char *id = ENGINE_get_id(e);
1475    ScopedLocalRef<jstring> idJava(env, env->NewStringUTF(id));
1476
1477    JNI_TRACE("ENGINE_get_id(%p) => \"%s\"", e, id);
1478    return idJava.release();
1479}
1480
1481static jint NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv* env, jclass, jlong engineRef,
1482        jstring cmdJava, jstring argJava, jint cmd_optional)
1483{
1484    ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1485    JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d)", e, cmdJava, argJava, cmd_optional);
1486
1487    if (e == NULL) {
1488        jniThrowNullPointerException(env, "engine == null");
1489        JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d) => engine == null", e, cmdJava, argJava,
1490                cmd_optional);
1491        return 0;
1492    }
1493
1494    ScopedUtfChars cmdChars(env, cmdJava);
1495    if (cmdChars.c_str() == NULL) {
1496        return 0;
1497    }
1498
1499    UniquePtr<ScopedUtfChars> arg;
1500    const char* arg_c_str = NULL;
1501    if (argJava != NULL) {
1502        arg.reset(new ScopedUtfChars(env, argJava));
1503        arg_c_str = arg->c_str();
1504        if (arg_c_str == NULL) {
1505            return 0;
1506        }
1507    }
1508    JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d)", e, cmdChars.c_str(), arg_c_str,
1509            cmd_optional);
1510
1511    int ret = ENGINE_ctrl_cmd_string(e, cmdChars.c_str(), arg_c_str, cmd_optional);
1512    if (ret != 1) {
1513        throwExceptionIfNecessary(env, "ENGINE_ctrl_cmd_string");
1514        JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => threw error", e,
1515                cmdChars.c_str(), arg_c_str, cmd_optional);
1516        return 0;
1517    }
1518
1519    JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => %d", e, cmdChars.c_str(),
1520            arg_c_str, cmd_optional, ret);
1521    return ret;
1522}
1523
1524static jlong NativeCrypto_EVP_PKEY_new_DH(JNIEnv* env, jclass,
1525                                               jbyteArray p, jbyteArray g,
1526                                               jbyteArray pub_key, jbyteArray priv_key) {
1527    JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p)",
1528              p, g, pub_key, priv_key);
1529
1530    Unique_DH dh(DH_new());
1531    if (dh.get() == NULL) {
1532        jniThrowRuntimeException(env, "DH_new failed");
1533        return 0;
1534    }
1535
1536    if (!arrayToBignum(env, p, &dh->p)) {
1537        return 0;
1538    }
1539
1540    if (!arrayToBignum(env, g, &dh->g)) {
1541        return 0;
1542    }
1543
1544    if (pub_key != NULL && !arrayToBignum(env, pub_key, &dh->pub_key)) {
1545        return 0;
1546    }
1547
1548    if (priv_key != NULL && !arrayToBignum(env, priv_key, &dh->priv_key)) {
1549        return 0;
1550    }
1551
1552    if (dh->p == NULL || dh->g == NULL
1553            || (dh->pub_key == NULL && dh->priv_key == NULL)) {
1554        jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
1555        return 0;
1556    }
1557
1558    /* The public key can be recovered if the private key is available. */
1559    if (dh->pub_key == NULL && dh->priv_key != NULL) {
1560        if (!DH_generate_key(dh.get())) {
1561            jniThrowRuntimeException(env, "EVP_PKEY_new_DH failed during pub_key generation");
1562            return 0;
1563        }
1564    }
1565
1566    Unique_EVP_PKEY pkey(EVP_PKEY_new());
1567    if (pkey.get() == NULL) {
1568        jniThrowRuntimeException(env, "EVP_PKEY_new failed");
1569        return 0;
1570    }
1571    if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
1572        jniThrowRuntimeException(env, "EVP_PKEY_assign_DH failed");
1573        return 0;
1574    }
1575    OWNERSHIP_TRANSFERRED(dh);
1576    JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
1577              p, g, pub_key, priv_key, pkey.get());
1578    return reinterpret_cast<jlong>(pkey.release());
1579}
1580
1581/**
1582 * public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g,
1583 *                                           byte[] pub_key, byte[] priv_key);
1584 */
1585static jlong NativeCrypto_EVP_PKEY_new_DSA(JNIEnv* env, jclass,
1586                                               jbyteArray p, jbyteArray q, jbyteArray g,
1587                                               jbyteArray pub_key, jbyteArray priv_key) {
1588    JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p)",
1589              p, q, g, pub_key, priv_key);
1590
1591    Unique_DSA dsa(DSA_new());
1592    if (dsa.get() == NULL) {
1593        jniThrowRuntimeException(env, "DSA_new failed");
1594        return 0;
1595    }
1596
1597    if (!arrayToBignum(env, p, &dsa->p)) {
1598        return 0;
1599    }
1600
1601    if (!arrayToBignum(env, q, &dsa->q)) {
1602        return 0;
1603    }
1604
1605    if (!arrayToBignum(env, g, &dsa->g)) {
1606        return 0;
1607    }
1608
1609    if (pub_key != NULL && !arrayToBignum(env, pub_key, &dsa->pub_key)) {
1610        return 0;
1611    }
1612
1613    if (priv_key != NULL && !arrayToBignum(env, priv_key, &dsa->priv_key)) {
1614        return 0;
1615    }
1616
1617    if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL
1618            || (dsa->pub_key == NULL && dsa->priv_key == NULL)) {
1619        jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
1620        return 0;
1621    }
1622
1623    Unique_EVP_PKEY pkey(EVP_PKEY_new());
1624    if (pkey.get() == NULL) {
1625        jniThrowRuntimeException(env, "EVP_PKEY_new failed");
1626        return 0;
1627    }
1628    if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
1629        jniThrowRuntimeException(env, "EVP_PKEY_assign_DSA failed");
1630        return 0;
1631    }
1632    OWNERSHIP_TRANSFERRED(dsa);
1633    JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
1634              p, q, g, pub_key, priv_key, pkey.get());
1635    return reinterpret_cast<jlong>(pkey.release());
1636}
1637
1638/**
1639 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
1640 */
1641static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass,
1642                                               jbyteArray n, jbyteArray e, jbyteArray d,
1643                                               jbyteArray p, jbyteArray q,
1644                                               jbyteArray dmp1, jbyteArray dmq1,
1645                                               jbyteArray iqmp) {
1646    JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p, dmp1=%p, dmq1=%p, iqmp=%p)",
1647            n, e, d, p, q, dmp1, dmq1, iqmp);
1648
1649    Unique_RSA rsa(RSA_new());
1650    if (rsa.get() == NULL) {
1651        jniThrowRuntimeException(env, "RSA_new failed");
1652        return 0;
1653    }
1654
1655    if (e == NULL && d == NULL) {
1656        jniThrowException(env, "java/lang/IllegalArgumentException", "e == NULL && d == NULL");
1657        JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == NULL && d == NULL");
1658        return 0;
1659    }
1660
1661    if (!arrayToBignum(env, n, &rsa->n)) {
1662        return 0;
1663    }
1664
1665    if (e != NULL && !arrayToBignum(env, e, &rsa->e)) {
1666        return 0;
1667    }
1668
1669    if (d != NULL && !arrayToBignum(env, d, &rsa->d)) {
1670        return 0;
1671    }
1672
1673    if (p != NULL && !arrayToBignum(env, p, &rsa->p)) {
1674        return 0;
1675    }
1676
1677    if (q != NULL && !arrayToBignum(env, q, &rsa->q)) {
1678        return 0;
1679    }
1680
1681    if (dmp1 != NULL && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
1682        return 0;
1683    }
1684
1685    if (dmq1 != NULL && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
1686        return 0;
1687    }
1688
1689    if (iqmp != NULL && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
1690        return 0;
1691    }
1692
1693#ifdef WITH_JNI_TRACE
1694    if (p != NULL && q != NULL) {
1695        int check = RSA_check_key(rsa.get());
1696        JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
1697    }
1698#endif
1699
1700    if (rsa->n == NULL || (rsa->e == NULL && rsa->d == NULL)) {
1701        jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
1702        return 0;
1703    }
1704
1705    /*
1706     * If the private exponent is available, there is the potential to do signing
1707     * operations. If the public exponent is also available, OpenSSL will do RSA
1708     * blinding. Enable it if possible.
1709     */
1710    if (rsa->d != NULL) {
1711        if (rsa->e != NULL) {
1712            JNI_TRACE("EVP_PKEY_new_RSA(...) enabling RSA blinding => %p", rsa.get());
1713            RSA_blinding_on(rsa.get(), NULL);
1714        } else {
1715            JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
1716            RSA_blinding_off(rsa.get());
1717        }
1718    }
1719
1720    Unique_EVP_PKEY pkey(EVP_PKEY_new());
1721    if (pkey.get() == NULL) {
1722        jniThrowRuntimeException(env, "EVP_PKEY_new failed");
1723        return 0;
1724    }
1725    if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1726        jniThrowRuntimeException(env, "EVP_PKEY_new failed");
1727        return 0;
1728    }
1729    OWNERSHIP_TRANSFERRED(rsa);
1730    JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p",
1731            n, e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
1732    return reinterpret_cast<uintptr_t>(pkey.release());
1733}
1734
1735static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jlong groupRef,
1736        jlong pubkeyRef, jbyteArray keyJavaBytes) {
1737    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
1738    const EC_POINT* pubkey = reinterpret_cast<const EC_POINT*>(pubkeyRef);
1739    JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", group, pubkey, keyJavaBytes);
1740
1741    Unique_BIGNUM key(NULL);
1742    if (keyJavaBytes != NULL) {
1743        BIGNUM* keyRef = NULL;
1744        if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
1745            return 0;
1746        }
1747        key.reset(keyRef);
1748    }
1749
1750    Unique_EC_KEY eckey(EC_KEY_new());
1751    if (eckey.get() == NULL) {
1752        jniThrowRuntimeException(env, "EC_KEY_new failed");
1753        return 0;
1754    }
1755
1756    if (EC_KEY_set_group(eckey.get(), group) != 1) {
1757        JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1758                keyJavaBytes);
1759        throwExceptionIfNecessary(env, "EC_KEY_set_group");
1760        return 0;
1761    }
1762
1763    if (pubkey != NULL) {
1764        if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1765            JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1766                    pubkey, keyJavaBytes);
1767            throwExceptionIfNecessary(env, "EC_KEY_set_public_key");
1768            return 0;
1769        }
1770    }
1771
1772    if (key.get() != NULL) {
1773        if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1774            JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1775                    pubkey, keyJavaBytes);
1776            throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
1777            return 0;
1778        }
1779        if (pubkey == NULL) {
1780            Unique_EC_POINT calcPubkey(EC_POINT_new(group));
1781            if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), NULL, NULL, NULL)) {
1782                JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calulate public key", group,
1783                        pubkey, keyJavaBytes);
1784                throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
1785                return 0;
1786            }
1787            EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1788        }
1789    }
1790
1791    if (!EC_KEY_check_key(eckey.get())) {
1792        JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey, keyJavaBytes);
1793        throwExceptionIfNecessary(env, "EC_KEY_check_key");
1794        return 0;
1795    }
1796
1797    Unique_EVP_PKEY pkey(EVP_PKEY_new());
1798    if (pkey.get() == NULL) {
1799        JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1800        throwExceptionIfNecessary(env, "EVP_PKEY_new failed");
1801        return 0;
1802    }
1803    if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1804        JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1805        jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1806        return 0;
1807    }
1808    OWNERSHIP_TRANSFERRED(eckey);
1809
1810    JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1811    return reinterpret_cast<uintptr_t>(pkey.release());
1812}
1813
1814static jlong NativeCrypto_EVP_PKEY_new_mac_key(JNIEnv* env, jclass, jint pkeyType,
1815        jbyteArray keyJavaBytes)
1816{
1817    JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p)", pkeyType, keyJavaBytes);
1818
1819    ScopedByteArrayRO key(env, keyJavaBytes);
1820    if (key.get() == NULL) {
1821        return 0;
1822    }
1823
1824    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(key.get());
1825    Unique_EVP_PKEY pkey(EVP_PKEY_new_mac_key(pkeyType, (ENGINE *) NULL, tmp, key.size()));
1826    if (pkey.get() == NULL) {
1827        JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => threw error", pkeyType, keyJavaBytes);
1828        throwExceptionIfNecessary(env, "ENGINE_load_private_key");
1829        return 0;
1830    }
1831
1832    JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => %p", pkeyType, keyJavaBytes, pkey.get());
1833    return reinterpret_cast<uintptr_t>(pkey.release());
1834}
1835
1836static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jlong pkeyRef) {
1837    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1838    JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1839
1840    if (pkey == NULL) {
1841        jniThrowNullPointerException(env, NULL);
1842        return -1;
1843    }
1844
1845    int result = EVP_PKEY_type(pkey->type);
1846    JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1847    return result;
1848}
1849
1850/**
1851 * private static native int EVP_PKEY_size(int pkey);
1852 */
1853static int NativeCrypto_EVP_PKEY_size(JNIEnv* env, jclass, jlong pkeyRef) {
1854    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1855    JNI_TRACE("EVP_PKEY_size(%p)", pkey);
1856
1857    if (pkey == NULL) {
1858        jniThrowNullPointerException(env, NULL);
1859        return -1;
1860    }
1861
1862    int result = EVP_PKEY_size(pkey);
1863    JNI_TRACE("EVP_PKEY_size(%p) => %d", pkey, result);
1864    return result;
1865}
1866
1867static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jlong pkeyRef) {
1868    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1869    JNI_TRACE("EVP_PKEY_print_public(%p)", pkey);
1870
1871    if (pkey == NULL) {
1872        jniThrowNullPointerException(env, "pkey == null");
1873        return NULL;
1874    }
1875
1876    Unique_BIO buffer(BIO_new(BIO_s_mem()));
1877    if (buffer.get() == NULL) {
1878        jniThrowOutOfMemory(env, "Unable to allocate BIO");
1879        return NULL;
1880    }
1881
1882    if (EVP_PKEY_print_public(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
1883        throwExceptionIfNecessary(env, "EVP_PKEY_print_public");
1884        return NULL;
1885    }
1886    // Null terminate this
1887    BIO_write(buffer.get(), "\0", 1);
1888
1889    char *tmp;
1890    BIO_get_mem_data(buffer.get(), &tmp);
1891    jstring description = env->NewStringUTF(tmp);
1892
1893    JNI_TRACE("EVP_PKEY_print_public(%p) => \"%s\"", pkey, tmp);
1894    return description;
1895}
1896
1897static jstring NativeCrypto_EVP_PKEY_print_private(JNIEnv* env, jclass, jlong pkeyRef) {
1898    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1899    JNI_TRACE("EVP_PKEY_print_private(%p)", pkey);
1900
1901    if (pkey == NULL) {
1902        jniThrowNullPointerException(env, "pkey == null");
1903        return NULL;
1904    }
1905
1906    Unique_BIO buffer(BIO_new(BIO_s_mem()));
1907    if (buffer.get() == NULL) {
1908        jniThrowOutOfMemory(env, "Unable to allocate BIO");
1909        return NULL;
1910    }
1911
1912    if (EVP_PKEY_print_private(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
1913        throwExceptionIfNecessary(env, "EVP_PKEY_print_private");
1914        return NULL;
1915    }
1916    // Null terminate this
1917    BIO_write(buffer.get(), "\0", 1);
1918
1919    char *tmp;
1920    BIO_get_mem_data(buffer.get(), &tmp);
1921    jstring description = env->NewStringUTF(tmp);
1922
1923    JNI_TRACE("EVP_PKEY_print_private(%p) => \"%s\"", pkey, tmp);
1924    return description;
1925}
1926
1927static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, jlong pkeyRef) {
1928    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1929    JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1930
1931    if (pkey != NULL) {
1932        EVP_PKEY_free(pkey);
1933    }
1934}
1935
1936static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jlong pkey1Ref, jlong pkey2Ref) {
1937    EVP_PKEY* pkey1 = reinterpret_cast<EVP_PKEY*>(pkey1Ref);
1938    EVP_PKEY* pkey2 = reinterpret_cast<EVP_PKEY*>(pkey2Ref);
1939    JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1, pkey2);
1940
1941    if (pkey1 == NULL) {
1942        JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey1 == NULL", pkey1, pkey2);
1943        jniThrowNullPointerException(env, "pkey1 == NULL");
1944        return -1;
1945    } else if (pkey2 == NULL) {
1946        JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey2 == NULL", pkey1, pkey2);
1947        jniThrowNullPointerException(env, "pkey2 == NULL");
1948        return -1;
1949    }
1950
1951    int result = EVP_PKEY_cmp(pkey1, pkey2);
1952    JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1953    return result;
1954}
1955
1956/*
1957 * static native byte[] i2d_PKCS8_PRIV_KEY_INFO(int, byte[])
1958 */
1959static jbyteArray NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jlong pkeyRef) {
1960    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1961    JNI_TRACE("i2d_PKCS8_PRIV_KEY_INFO(%p)", pkey);
1962
1963    if (pkey == NULL) {
1964        jniThrowNullPointerException(env, NULL);
1965        return NULL;
1966    }
1967
1968    Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey));
1969    if (pkcs8.get() == NULL) {
1970        throwExceptionIfNecessary(env, "NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO");
1971        JNI_TRACE("key=%p i2d_PKCS8_PRIV_KEY_INFO => error from key to PKCS8", pkey);
1972        return NULL;
1973    }
1974
1975    return ASN1ToByteArray<PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO>(env, pkcs8.get());
1976}
1977
1978/*
1979 * static native int d2i_PKCS8_PRIV_KEY_INFO(byte[])
1980 */
1981static jlong NativeCrypto_d2i_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1982    JNI_TRACE("d2i_PKCS8_PRIV_KEY_INFO(%p)", keyJavaBytes);
1983
1984    ScopedByteArrayRO bytes(env, keyJavaBytes);
1985    if (bytes.get() == NULL) {
1986        JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => threw exception", keyJavaBytes);
1987        return 0;
1988    }
1989
1990    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
1991    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, bytes.size()));
1992    if (pkcs8.get() == NULL) {
1993        throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
1994        JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from DER to PKCS8", keyJavaBytes);
1995        return 0;
1996    }
1997
1998    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
1999    if (pkey.get() == NULL) {
2000        throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
2001        JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from PKCS8 to key", keyJavaBytes);
2002        return 0;
2003    }
2004
2005    JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => %p", keyJavaBytes, pkey.get());
2006    return reinterpret_cast<uintptr_t>(pkey.release());
2007}
2008
2009/*
2010 * static native byte[] i2d_PUBKEY(int)
2011 */
2012static jbyteArray NativeCrypto_i2d_PUBKEY(JNIEnv* env, jclass, jlong pkeyRef) {
2013    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2014    JNI_TRACE("i2d_PUBKEY(%p)", pkey);
2015    return ASN1ToByteArray<EVP_PKEY, i2d_PUBKEY>(env, pkey);
2016}
2017
2018/*
2019 * static native int d2i_PUBKEY(byte[])
2020 */
2021static jlong NativeCrypto_d2i_PUBKEY(JNIEnv* env, jclass, jbyteArray javaBytes) {
2022    JNI_TRACE("d2i_PUBKEY(%p)", javaBytes);
2023
2024    ScopedByteArrayRO bytes(env, javaBytes);
2025    if (bytes.get() == NULL) {
2026        JNI_TRACE("d2i_PUBKEY(%p) => threw error", javaBytes);
2027        return 0;
2028    }
2029
2030    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
2031    Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, bytes.size()));
2032    if (pkey.get() == NULL) {
2033        JNI_TRACE("bytes=%p d2i_PUBKEY => threw exception", javaBytes);
2034        throwExceptionIfNecessary(env, "d2i_PUBKEY");
2035        return 0;
2036    }
2037
2038    return reinterpret_cast<uintptr_t>(pkey.release());
2039}
2040
2041/*
2042 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
2043 */
2044static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
2045        jbyteArray publicExponent) {
2046    JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
2047
2048    BIGNUM* eRef = NULL;
2049    if (!arrayToBignum(env, publicExponent, &eRef)) {
2050        return 0;
2051    }
2052    Unique_BIGNUM e(eRef);
2053
2054    Unique_RSA rsa(RSA_new());
2055    if (rsa.get() == NULL) {
2056        jniThrowOutOfMemory(env, "Unable to allocate RSA key");
2057        return 0;
2058    }
2059
2060    if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), NULL) < 0) {
2061        throwExceptionIfNecessary(env, "RSA_generate_key_ex");
2062        return 0;
2063    }
2064
2065    Unique_EVP_PKEY pkey(EVP_PKEY_new());
2066    if (pkey.get() == NULL) {
2067        jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
2068        return 0;
2069    }
2070
2071    if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
2072        jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
2073        return 0;
2074    }
2075
2076    OWNERSHIP_TRANSFERRED(rsa);
2077    JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
2078    return reinterpret_cast<uintptr_t>(pkey.release());
2079}
2080
2081static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jlong pkeyRef) {
2082    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2083    JNI_TRACE("RSA_size(%p)", pkey);
2084
2085    if (pkey == NULL) {
2086        jniThrowNullPointerException(env, "pkey == null");
2087        return 0;
2088    }
2089
2090    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2091    if (rsa.get() == NULL) {
2092        jniThrowRuntimeException(env, "RSA_size failed");
2093        return 0;
2094    }
2095
2096    return static_cast<jint>(RSA_size(rsa.get()));
2097}
2098
2099typedef int RSACryptOperation(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
2100                              int padding);
2101
2102static jint RSA_crypt_operation(RSACryptOperation operation,
2103        const char* caller __attribute__ ((unused)), JNIEnv* env, jint flen,
2104        jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2105    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2106    JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
2107
2108    if (pkey == NULL) {
2109        jniThrowNullPointerException(env, "pkey == null");
2110        return -1;
2111    }
2112
2113    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2114    if (rsa.get() == NULL) {
2115        return -1;
2116    }
2117
2118    ScopedByteArrayRO from(env, fromJavaBytes);
2119    if (from.get() == NULL) {
2120        return -1;
2121    }
2122
2123    ScopedByteArrayRW to(env, toJavaBytes);
2124    if (to.get() == NULL) {
2125        return -1;
2126    }
2127
2128    int resultSize = operation(static_cast<int>(flen),
2129            reinterpret_cast<const unsigned char*>(from.get()),
2130            reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
2131    if (resultSize == -1) {
2132        JNI_TRACE("%s => failed", caller);
2133        throwExceptionIfNecessary(env, "RSA_crypt_operation");
2134        return -1;
2135    }
2136
2137    JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
2138              resultSize);
2139    return static_cast<jint>(resultSize);
2140}
2141
2142static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
2143        jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2144    return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__,
2145                               env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2146}
2147static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
2148        jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2149    return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__,
2150                               env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2151}
2152static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
2153        jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2154    return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__,
2155                               env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2156}
2157static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
2158        jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2159    return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__,
2160                               env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2161}
2162
2163/*
2164 * public static native byte[][] get_RSA_public_params(long);
2165 */
2166static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jlong pkeyRef) {
2167    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2168    JNI_TRACE("get_RSA_public_params(%p)", pkey);
2169
2170    if (pkey == NULL) {
2171        jniThrowNullPointerException(env, "pkey == null");
2172        return 0;
2173    }
2174
2175    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2176    if (rsa.get() == NULL) {
2177        throwExceptionIfNecessary(env, "get_RSA_public_params failed");
2178        return 0;
2179    }
2180
2181    jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
2182    if (joa == NULL) {
2183        return NULL;
2184    }
2185
2186    jbyteArray n = bignumToArray(env, rsa->n, "n");
2187    if (env->ExceptionCheck()) {
2188        return NULL;
2189    }
2190    env->SetObjectArrayElement(joa, 0, n);
2191
2192    jbyteArray e = bignumToArray(env, rsa->e, "e");
2193    if (env->ExceptionCheck()) {
2194        return NULL;
2195    }
2196    env->SetObjectArrayElement(joa, 1, e);
2197
2198    return joa;
2199}
2200
2201/*
2202 * public static native byte[][] get_RSA_private_params(long);
2203 */
2204static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jlong pkeyRef) {
2205    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2206    JNI_TRACE("get_RSA_public_params(%p)", pkey);
2207
2208    if (pkey == NULL) {
2209        jniThrowNullPointerException(env, "pkey == null");
2210        return 0;
2211    }
2212
2213    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2214    if (rsa.get() == NULL) {
2215        throwExceptionIfNecessary(env, "get_RSA_public_params failed");
2216        return 0;
2217    }
2218
2219    jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL);
2220    if (joa == NULL) {
2221        return NULL;
2222    }
2223
2224    jbyteArray n = bignumToArray(env, rsa->n, "n");
2225    if (env->ExceptionCheck()) {
2226        return NULL;
2227    }
2228    env->SetObjectArrayElement(joa, 0, n);
2229
2230    if (rsa->e != NULL) {
2231        jbyteArray e = bignumToArray(env, rsa->e, "e");
2232        if (env->ExceptionCheck()) {
2233            return NULL;
2234        }
2235        env->SetObjectArrayElement(joa, 1, e);
2236    }
2237
2238    if (rsa->d != NULL) {
2239        jbyteArray d = bignumToArray(env, rsa->d, "d");
2240        if (env->ExceptionCheck()) {
2241            return NULL;
2242        }
2243        env->SetObjectArrayElement(joa, 2, d);
2244    }
2245
2246    if (rsa->p != NULL) {
2247        jbyteArray p = bignumToArray(env, rsa->p, "p");
2248        if (env->ExceptionCheck()) {
2249            return NULL;
2250        }
2251        env->SetObjectArrayElement(joa, 3, p);
2252    }
2253
2254    if (rsa->q != NULL) {
2255        jbyteArray q = bignumToArray(env, rsa->q, "q");
2256        if (env->ExceptionCheck()) {
2257            return NULL;
2258        }
2259        env->SetObjectArrayElement(joa, 4, q);
2260    }
2261
2262    if (rsa->dmp1 != NULL) {
2263        jbyteArray dmp1 = bignumToArray(env, rsa->dmp1, "dmp1");
2264        if (env->ExceptionCheck()) {
2265            return NULL;
2266        }
2267        env->SetObjectArrayElement(joa, 5, dmp1);
2268    }
2269
2270    if (rsa->dmq1 != NULL) {
2271        jbyteArray dmq1 = bignumToArray(env, rsa->dmq1, "dmq1");
2272        if (env->ExceptionCheck()) {
2273            return NULL;
2274        }
2275        env->SetObjectArrayElement(joa, 6, dmq1);
2276    }
2277
2278    if (rsa->iqmp != NULL) {
2279        jbyteArray iqmp = bignumToArray(env, rsa->iqmp, "iqmp");
2280        if (env->ExceptionCheck()) {
2281            return NULL;
2282        }
2283        env->SetObjectArrayElement(joa, 7, iqmp);
2284    }
2285
2286    return joa;
2287}
2288
2289/*
2290 * public static native int DSA_generate_key(int, byte[], byte[], byte[], byte[]);
2291 */
2292static jlong NativeCrypto_DSA_generate_key(JNIEnv* env, jclass, jint primeBits,
2293        jbyteArray seedJavaBytes, jbyteArray gBytes, jbyteArray pBytes, jbyteArray qBytes) {
2294    JNI_TRACE("DSA_generate_key(%d, %p, %p, %p, %p)", primeBits, seedJavaBytes,
2295            gBytes, pBytes, qBytes);
2296
2297    UniquePtr<unsigned char[]> seedPtr;
2298    unsigned long seedSize = 0;
2299    if (seedJavaBytes != NULL) {
2300        ScopedByteArrayRO seed(env, seedJavaBytes);
2301        if (seed.get() == NULL) {
2302            return 0;
2303        }
2304
2305        seedSize = seed.size();
2306        seedPtr.reset(new unsigned char[seedSize]);
2307
2308        memcpy(seedPtr.get(), seed.get(), seedSize);
2309    }
2310
2311    Unique_DSA dsa(DSA_new());
2312    if (dsa.get() == NULL) {
2313        JNI_TRACE("DSA_generate_key failed");
2314        jniThrowOutOfMemory(env, "Unable to allocate DSA key");
2315        freeOpenSslErrorState();
2316        return 0;
2317    }
2318
2319    if (gBytes != NULL && pBytes != NULL && qBytes != NULL) {
2320        JNI_TRACE("DSA_generate_key parameters specified");
2321
2322        if (!arrayToBignum(env, gBytes, &dsa->g)) {
2323            return 0;
2324        }
2325
2326        if (!arrayToBignum(env, pBytes, &dsa->p)) {
2327            return 0;
2328        }
2329
2330        if (!arrayToBignum(env, qBytes, &dsa->q)) {
2331            return 0;
2332        }
2333    } else {
2334        JNI_TRACE("DSA_generate_key generating parameters");
2335
2336        if (!DSA_generate_parameters_ex(dsa.get(), primeBits, seedPtr.get(), seedSize, NULL, NULL, NULL)) {
2337            JNI_TRACE("DSA_generate_key => param generation failed");
2338            throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_parameters_ex failed");
2339            return 0;
2340        }
2341    }
2342
2343    if (!DSA_generate_key(dsa.get())) {
2344        JNI_TRACE("DSA_generate_key failed");
2345        throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed");
2346        return 0;
2347    }
2348
2349    Unique_EVP_PKEY pkey(EVP_PKEY_new());
2350    if (pkey.get() == NULL) {
2351        JNI_TRACE("DSA_generate_key failed");
2352        jniThrowRuntimeException(env, "NativeCrypto_DSA_generate_key failed");
2353        freeOpenSslErrorState();
2354        return 0;
2355    }
2356
2357    if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
2358        JNI_TRACE("DSA_generate_key failed");
2359        throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed");
2360        return 0;
2361    }
2362
2363    OWNERSHIP_TRANSFERRED(dsa);
2364    JNI_TRACE("DSA_generate_key(n=%d, e=%p) => %p", primeBits, seedPtr.get(), pkey.get());
2365    return reinterpret_cast<uintptr_t>(pkey.release());
2366}
2367
2368/*
2369 * public static native byte[][] get_DSA_params(long);
2370 */
2371static jobjectArray NativeCrypto_get_DSA_params(JNIEnv* env, jclass, jlong pkeyRef) {
2372    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2373    JNI_TRACE("get_DSA_params(%p)", pkey);
2374
2375    if (pkey == NULL) {
2376        jniThrowNullPointerException(env, "pkey == null");
2377        return NULL;
2378    }
2379
2380    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
2381    if (dsa.get() == NULL) {
2382        throwExceptionIfNecessary(env, "get_DSA_params failed");
2383        return 0;
2384    }
2385
2386    jobjectArray joa = env->NewObjectArray(5, byteArrayClass, NULL);
2387    if (joa == NULL) {
2388        return NULL;
2389    }
2390
2391    if (dsa->g != NULL) {
2392        jbyteArray g = bignumToArray(env, dsa->g, "g");
2393        if (env->ExceptionCheck()) {
2394            return NULL;
2395        }
2396        env->SetObjectArrayElement(joa, 0, g);
2397    }
2398
2399    if (dsa->p != NULL) {
2400        jbyteArray p = bignumToArray(env, dsa->p, "p");
2401        if (env->ExceptionCheck()) {
2402            return NULL;
2403        }
2404        env->SetObjectArrayElement(joa, 1, p);
2405    }
2406
2407    if (dsa->q != NULL) {
2408        jbyteArray q = bignumToArray(env, dsa->q, "q");
2409        if (env->ExceptionCheck()) {
2410            return NULL;
2411        }
2412        env->SetObjectArrayElement(joa, 2, q);
2413    }
2414
2415    if (dsa->pub_key != NULL) {
2416        jbyteArray pub_key = bignumToArray(env, dsa->pub_key, "pub_key");
2417        if (env->ExceptionCheck()) {
2418            return NULL;
2419        }
2420        env->SetObjectArrayElement(joa, 3, pub_key);
2421    }
2422
2423    if (dsa->priv_key != NULL) {
2424        jbyteArray priv_key = bignumToArray(env, dsa->priv_key, "priv_key");
2425        if (env->ExceptionCheck()) {
2426            return NULL;
2427        }
2428        env->SetObjectArrayElement(joa, 4, priv_key);
2429    }
2430
2431    return joa;
2432}
2433
2434static void NativeCrypto_set_DSA_flag_nonce_from_hash(JNIEnv* env, jclass, jlong pkeyRef)
2435{
2436    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2437    JNI_TRACE("set_DSA_flag_nonce_from_hash(%p)", pkey);
2438
2439    if (pkey == NULL) {
2440        jniThrowNullPointerException(env, "pkey == null");
2441        return;
2442    }
2443
2444    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
2445    if (dsa.get() == NULL) {
2446        throwExceptionIfNecessary(env, "set_DSA_flag_nonce_from_hash failed");
2447        return;
2448    }
2449
2450    dsa->flags |= DSA_FLAG_NONCE_FROM_HASH;
2451}
2452
2453static jlong NativeCrypto_DH_generate_key(JNIEnv* env, jclass, jint primeBits, jint generator) {
2454    JNI_TRACE("DH_generate_key(%d, %d)", primeBits, generator);
2455
2456    Unique_DH dh(DH_new());
2457    if (dh.get() == NULL) {
2458        JNI_TRACE("DH_generate_key failed");
2459        jniThrowOutOfMemory(env, "Unable to allocate DH key");
2460        freeOpenSslErrorState();
2461        return 0;
2462    }
2463
2464    JNI_TRACE("DH_generate_key generating parameters");
2465
2466    if (!DH_generate_parameters_ex(dh.get(), primeBits, generator, NULL)) {
2467        JNI_TRACE("DH_generate_key => param generation failed");
2468        throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_parameters_ex failed");
2469        return 0;
2470    }
2471
2472    if (!DH_generate_key(dh.get())) {
2473        JNI_TRACE("DH_generate_key failed");
2474        throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_key failed");
2475        return 0;
2476    }
2477
2478    Unique_EVP_PKEY pkey(EVP_PKEY_new());
2479    if (pkey.get() == NULL) {
2480        JNI_TRACE("DH_generate_key failed");
2481        jniThrowRuntimeException(env, "NativeCrypto_DH_generate_key failed");
2482        freeOpenSslErrorState();
2483        return 0;
2484    }
2485
2486    if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
2487        JNI_TRACE("DH_generate_key failed");
2488        throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_key failed");
2489        return 0;
2490    }
2491
2492    OWNERSHIP_TRANSFERRED(dh);
2493    JNI_TRACE("DH_generate_key(n=%d, g=%d) => %p", primeBits, generator, pkey.get());
2494    return reinterpret_cast<uintptr_t>(pkey.release());
2495}
2496
2497static jobjectArray NativeCrypto_get_DH_params(JNIEnv* env, jclass, jlong pkeyRef) {
2498    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2499    JNI_TRACE("get_DH_params(%p)", pkey);
2500
2501    if (pkey == NULL) {
2502        jniThrowNullPointerException(env, "pkey == null");
2503        return NULL;
2504    }
2505
2506    Unique_DH dh(EVP_PKEY_get1_DH(pkey));
2507    if (dh.get() == NULL) {
2508        throwExceptionIfNecessary(env, "get_DH_params failed");
2509        return 0;
2510    }
2511
2512    jobjectArray joa = env->NewObjectArray(4, byteArrayClass, NULL);
2513    if (joa == NULL) {
2514        return NULL;
2515    }
2516
2517    if (dh->p != NULL) {
2518        jbyteArray p = bignumToArray(env, dh->p, "p");
2519        if (env->ExceptionCheck()) {
2520            return NULL;
2521        }
2522        env->SetObjectArrayElement(joa, 0, p);
2523    }
2524
2525    if (dh->g != NULL) {
2526        jbyteArray g = bignumToArray(env, dh->g, "g");
2527        if (env->ExceptionCheck()) {
2528            return NULL;
2529        }
2530        env->SetObjectArrayElement(joa, 1, g);
2531    }
2532
2533    if (dh->pub_key != NULL) {
2534        jbyteArray pub_key = bignumToArray(env, dh->pub_key, "pub_key");
2535        if (env->ExceptionCheck()) {
2536            return NULL;
2537        }
2538        env->SetObjectArrayElement(joa, 2, pub_key);
2539    }
2540
2541    if (dh->priv_key != NULL) {
2542        jbyteArray priv_key = bignumToArray(env, dh->priv_key, "priv_key");
2543        if (env->ExceptionCheck()) {
2544            return NULL;
2545        }
2546        env->SetObjectArrayElement(joa, 3, priv_key);
2547    }
2548
2549    return joa;
2550}
2551
2552#define EC_CURVE_GFP 1
2553#define EC_CURVE_GF2M 2
2554
2555/**
2556 * Return group type or 0 if unknown group.
2557 * EC_GROUP_GFP or EC_GROUP_GF2M
2558 */
2559static int get_EC_GROUP_type(const EC_GROUP* group)
2560{
2561    const EC_METHOD* method = EC_GROUP_method_of(group);
2562    if (method == EC_GFp_nist_method()
2563                || method == EC_GFp_mont_method()
2564                || method == EC_GFp_simple_method()) {
2565        return EC_CURVE_GFP;
2566    } else if (method == EC_GF2m_simple_method()) {
2567        return EC_CURVE_GF2M;
2568    }
2569
2570    return 0;
2571}
2572
2573static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava)
2574{
2575    JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
2576
2577    ScopedUtfChars curveName(env, curveNameJava);
2578    if (curveName.c_str() == NULL) {
2579        return 0;
2580    }
2581    JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
2582
2583    int nid = OBJ_sn2nid(curveName.c_str());
2584    if (nid == NID_undef) {
2585        JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
2586        return 0;
2587    }
2588
2589    EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
2590    if (group == NULL) {
2591        JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
2592        freeOpenSslErrorState();
2593        return 0;
2594    }
2595
2596    JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
2597    return reinterpret_cast<uintptr_t>(group);
2598}
2599
2600static void NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv* env, jclass, jlong groupRef,
2601        jint flag)
2602{
2603    EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
2604    JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d)", group, flag);
2605
2606    if (group == NULL) {
2607        JNI_TRACE("EC_GROUP_set_asn1_flag => group == NULL");
2608        jniThrowNullPointerException(env, "group == NULL");
2609        return;
2610    }
2611
2612    EC_GROUP_set_asn1_flag(group, flag);
2613    JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d) => success", group, flag);
2614}
2615
2616static void NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv* env, jclass,
2617        jlong groupRef, jint form)
2618{
2619    EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
2620    JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d)", group, form);
2621
2622    if (group == NULL) {
2623        JNI_TRACE("EC_GROUP_set_point_conversion_form => group == NULL");
2624        jniThrowNullPointerException(env, "group == NULL");
2625        return;
2626    }
2627
2628    EC_GROUP_set_point_conversion_form(group, static_cast<point_conversion_form_t>(form));
2629    JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d) => success", group, form);
2630}
2631
2632static jlong NativeCrypto_EC_GROUP_new_curve(JNIEnv* env, jclass, jint type, jbyteArray pJava,
2633        jbyteArray aJava, jbyteArray bJava)
2634{
2635    JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p)", type, pJava, aJava, bJava);
2636
2637    BIGNUM* pRef = NULL;
2638    if (!arrayToBignum(env, pJava, &pRef)) {
2639        return 0;
2640    }
2641    Unique_BIGNUM p(pRef);
2642
2643    BIGNUM* aRef = NULL;
2644    if (!arrayToBignum(env, aJava, &aRef)) {
2645        return 0;
2646    }
2647    Unique_BIGNUM a(aRef);
2648
2649    BIGNUM* bRef = NULL;
2650    if (!arrayToBignum(env, bJava, &bRef)) {
2651        return 0;
2652    }
2653    Unique_BIGNUM b(bRef);
2654
2655    EC_GROUP* group;
2656    switch (type) {
2657    case EC_CURVE_GFP:
2658        group = EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), (BN_CTX*) NULL);
2659        break;
2660    case EC_CURVE_GF2M:
2661        group = EC_GROUP_new_curve_GF2m(p.get(), a.get(), b.get(), (BN_CTX*) NULL);
2662        break;
2663    default:
2664        jniThrowRuntimeException(env, "invalid group");
2665        return 0;
2666    }
2667
2668    if (group == NULL) {
2669        throwExceptionIfNecessary(env, "EC_GROUP_new_curve");
2670    }
2671
2672    JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p) => %p", type, pJava, aJava, bJava, group);
2673    return reinterpret_cast<uintptr_t>(group);
2674}
2675
2676static jlong NativeCrypto_EC_GROUP_dup(JNIEnv* env, jclass, jlong groupRef) {
2677    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2678    JNI_TRACE("EC_GROUP_dup(%p)", group);
2679
2680    if (group == NULL) {
2681         JNI_TRACE("EC_GROUP_dup => group == NULL");
2682         jniThrowNullPointerException(env, "group == NULL");
2683         return 0;
2684     }
2685
2686     EC_GROUP* groupDup = EC_GROUP_dup(group);
2687     JNI_TRACE("EC_GROUP_dup(%p) => %p", group, groupDup);
2688     return reinterpret_cast<uintptr_t>(groupDup);
2689}
2690
2691static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jlong groupRef) {
2692    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2693    JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
2694
2695    if (group == NULL) {
2696        JNI_TRACE("EC_GROUP_get_curve_name => group == NULL");
2697        jniThrowNullPointerException(env, "group == NULL");
2698        return 0;
2699    }
2700
2701    int nid = EC_GROUP_get_curve_name(group);
2702    if (nid == NID_undef) {
2703        JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
2704        return NULL;
2705    }
2706
2707    const char* shortName = OBJ_nid2sn(nid);
2708    JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
2709    return env->NewStringUTF(shortName);
2710}
2711
2712static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jlong groupRef)
2713{
2714    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2715    JNI_TRACE("EC_GROUP_get_curve(%p)", group);
2716
2717    Unique_BIGNUM p(BN_new());
2718    Unique_BIGNUM a(BN_new());
2719    Unique_BIGNUM b(BN_new());
2720
2721    int ret;
2722    switch (get_EC_GROUP_type(group)) {
2723    case EC_CURVE_GFP:
2724        ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), (BN_CTX*) NULL);
2725        break;
2726    case EC_CURVE_GF2M:
2727        ret = EC_GROUP_get_curve_GF2m(group, p.get(), a.get(), b.get(), (BN_CTX*)NULL);
2728        break;
2729    default:
2730        jniThrowRuntimeException(env, "invalid group");
2731        return NULL;
2732    }
2733    if (ret != 1) {
2734        throwExceptionIfNecessary(env, "EC_GROUP_get_curve");
2735        return NULL;
2736    }
2737
2738    jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL);
2739    if (joa == NULL) {
2740        return NULL;
2741    }
2742
2743    jbyteArray pArray = bignumToArray(env, p.get(), "p");
2744    if (env->ExceptionCheck()) {
2745        return NULL;
2746    }
2747    env->SetObjectArrayElement(joa, 0, pArray);
2748
2749    jbyteArray aArray = bignumToArray(env, a.get(), "a");
2750    if (env->ExceptionCheck()) {
2751        return NULL;
2752    }
2753    env->SetObjectArrayElement(joa, 1, aArray);
2754
2755    jbyteArray bArray = bignumToArray(env, b.get(), "b");
2756    if (env->ExceptionCheck()) {
2757        return NULL;
2758    }
2759    env->SetObjectArrayElement(joa, 2, bArray);
2760
2761    JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
2762    return joa;
2763}
2764
2765static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jlong groupRef)
2766{
2767    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2768    JNI_TRACE("EC_GROUP_get_order(%p)", group);
2769
2770    Unique_BIGNUM order(BN_new());
2771    if (order.get() == NULL) {
2772        JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
2773        jniThrowOutOfMemory(env, "BN_new");
2774        return NULL;
2775    }
2776
2777    if (EC_GROUP_get_order(group, order.get(), NULL) != 1) {
2778        JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
2779        throwExceptionIfNecessary(env, "EC_GROUP_get_order");
2780        return NULL;
2781    }
2782
2783    jbyteArray orderArray = bignumToArray(env, order.get(), "order");
2784    if (env->ExceptionCheck()) {
2785        return NULL;
2786    }
2787
2788    JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
2789    return orderArray;
2790}
2791
2792static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jlong groupRef)
2793{
2794    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2795    JNI_TRACE("EC_GROUP_get_degree(%p)", group);
2796
2797    jint degree = EC_GROUP_get_degree(group);
2798    if (degree == 0) {
2799      JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
2800      jniThrowRuntimeException(env, "not supported");
2801      return 0;
2802    }
2803
2804    JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
2805    return degree;
2806}
2807
2808static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jlong groupRef)
2809{
2810    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2811    JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
2812
2813    Unique_BIGNUM cofactor(BN_new());
2814    if (cofactor.get() == NULL) {
2815        JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
2816        jniThrowOutOfMemory(env, "BN_new");
2817        return NULL;
2818    }
2819
2820    if (EC_GROUP_get_cofactor(group, cofactor.get(), NULL) != 1) {
2821        JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
2822        throwExceptionIfNecessary(env, "EC_GROUP_get_cofactor");
2823        return NULL;
2824    }
2825
2826    jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
2827    if (env->ExceptionCheck()) {
2828        return NULL;
2829    }
2830
2831    JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
2832    return cofactorArray;
2833}
2834
2835static jint NativeCrypto_get_EC_GROUP_type(JNIEnv* env, jclass, jlong groupRef)
2836{
2837    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2838    JNI_TRACE("get_EC_GROUP_type(%p)", group);
2839
2840    int type = get_EC_GROUP_type(group);
2841    if (type == 0) {
2842        JNI_TRACE("get_EC_GROUP_type(%p) => curve type", group);
2843        jniThrowRuntimeException(env, "unknown curve type");
2844    } else {
2845        JNI_TRACE("get_EC_GROUP_type(%p) => %d", group, type);
2846    }
2847    return type;
2848}
2849
2850static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef)
2851{
2852    EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
2853    JNI_TRACE("EC_GROUP_clear_free(%p)", group);
2854
2855    if (group == NULL) {
2856        JNI_TRACE("EC_GROUP_clear_free => group == NULL");
2857        jniThrowNullPointerException(env, "group == NULL");
2858        return;
2859    }
2860
2861    EC_GROUP_clear_free(group);
2862    JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
2863}
2864
2865static jboolean NativeCrypto_EC_GROUP_cmp(JNIEnv* env, jclass, jlong group1Ref, jlong group2Ref)
2866{
2867    const EC_GROUP* group1 = reinterpret_cast<const EC_GROUP*>(group1Ref);
2868    const EC_GROUP* group2 = reinterpret_cast<const EC_GROUP*>(group2Ref);
2869    JNI_TRACE("EC_GROUP_cmp(%p, %p)", group1, group2);
2870
2871    if (group1 == NULL || group2 == NULL) {
2872        JNI_TRACE("EC_GROUP_cmp(%p, %p) => group1 == null || group2 == null", group1, group2);
2873        jniThrowNullPointerException(env, "group1 == null || group2 == null");
2874        return false;
2875    }
2876
2877    int ret = EC_GROUP_cmp(group1, group2, (BN_CTX*)NULL);
2878
2879    JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", group1, group2, ret);
2880    return ret == 0;
2881}
2882
2883static void NativeCrypto_EC_GROUP_set_generator(JNIEnv* env, jclass, jlong groupRef, jlong pointRef, jbyteArray njavaBytes, jbyteArray hjavaBytes)
2884{
2885    EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
2886    const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef);
2887    JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p)", group, point, njavaBytes, hjavaBytes);
2888
2889    if (group == NULL || point == NULL) {
2890        JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => group == null || point == null",
2891                group, point, njavaBytes, hjavaBytes);
2892        jniThrowNullPointerException(env, "group == null || point == null");
2893        return;
2894    }
2895
2896    BIGNUM* nRef = NULL;
2897    if (!arrayToBignum(env, njavaBytes, &nRef)) {
2898        return;
2899    }
2900    Unique_BIGNUM n(nRef);
2901
2902    BIGNUM* hRef = NULL;
2903    if (!arrayToBignum(env, hjavaBytes, &hRef)) {
2904        return;
2905    }
2906    Unique_BIGNUM h(hRef);
2907
2908    int ret = EC_GROUP_set_generator(group, point, n.get(), h.get());
2909    if (ret == 0) {
2910        throwExceptionIfNecessary(env, "EC_GROUP_set_generator");
2911    }
2912
2913    JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => %d", group, point, njavaBytes, hjavaBytes, ret);
2914}
2915
2916static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jlong groupRef)
2917{
2918    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2919    JNI_TRACE("EC_GROUP_get_generator(%p)", group);
2920
2921    if (group == NULL) {
2922        JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
2923        jniThrowNullPointerException(env, "group == null");
2924        return 0;
2925    }
2926
2927    const EC_POINT* generator = EC_GROUP_get0_generator(group);
2928
2929    Unique_EC_POINT dup(EC_POINT_dup(generator, group));
2930    if (dup.get() == NULL) {
2931        JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
2932        jniThrowOutOfMemory(env, "unable to dupe generator");
2933        return 0;
2934    }
2935
2936    JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
2937    return reinterpret_cast<uintptr_t>(dup.release());
2938}
2939
2940static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jlong groupRef)
2941{
2942    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2943    JNI_TRACE("EC_POINT_new(%p)", group);
2944
2945    if (group == NULL) {
2946        JNI_TRACE("EC_POINT_new(%p) => group == null", group);
2947        jniThrowNullPointerException(env, "group == null");
2948        return 0;
2949    }
2950
2951    EC_POINT* point = EC_POINT_new(group);
2952    if (point == NULL) {
2953        jniThrowOutOfMemory(env, "Unable create an EC_POINT");
2954        return 0;
2955    }
2956
2957    return reinterpret_cast<uintptr_t>(point);
2958}
2959
2960static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
2961    EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
2962    JNI_TRACE("EC_POINT_clear_free(%p)", group);
2963
2964    if (group == NULL) {
2965        JNI_TRACE("EC_POINT_clear_free => group == NULL");
2966        jniThrowNullPointerException(env, "group == NULL");
2967        return;
2968    }
2969
2970    EC_POINT_clear_free(group);
2971    JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
2972}
2973
2974static jboolean NativeCrypto_EC_POINT_cmp(JNIEnv* env, jclass, jlong groupRef, jlong point1Ref, jlong point2Ref)
2975{
2976    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2977    const EC_POINT* point1 = reinterpret_cast<const EC_POINT*>(point1Ref);
2978    const EC_POINT* point2 = reinterpret_cast<const EC_POINT*>(point2Ref);
2979    JNI_TRACE("EC_POINT_cmp(%p, %p, %p)", group, point1, point2);
2980
2981    if (group == NULL || point1 == NULL || point2 == NULL) {
2982        JNI_TRACE("EC_POINT_cmp(%p, %p, %p) => group == null || point1 == null || point2 == null",
2983                group, point1, point2);
2984        jniThrowNullPointerException(env, "group == null || point1 == null || point2 == null");
2985        return false;
2986    }
2987
2988    int ret = EC_POINT_cmp(group, point1, point2, (BN_CTX*)NULL);
2989
2990    JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", point1, point2, ret);
2991    return ret == 0;
2992}
2993
2994static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass,
2995        jlong groupRef, jlong pointRef, jbyteArray xjavaBytes, jbyteArray yjavaBytes)
2996{
2997    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2998    EC_POINT* point = reinterpret_cast<EC_POINT*>(pointRef);
2999    JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", group, point, xjavaBytes,
3000            yjavaBytes);
3001
3002    if (group == NULL || point == NULL) {
3003        JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => group == null || point == null",
3004                group, point, xjavaBytes, yjavaBytes);
3005        jniThrowNullPointerException(env, "group == null || point == null");
3006        return;
3007    }
3008
3009    BIGNUM* xRef = NULL;
3010    if (!arrayToBignum(env, xjavaBytes, &xRef)) {
3011        return;
3012    }
3013    Unique_BIGNUM x(xRef);
3014
3015    BIGNUM* yRef = NULL;
3016    if (!arrayToBignum(env, yjavaBytes, &yRef)) {
3017        return;
3018    }
3019    Unique_BIGNUM y(yRef);
3020
3021    int ret;
3022    switch (get_EC_GROUP_type(group)) {
3023    case EC_CURVE_GFP:
3024        ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
3025        break;
3026    case EC_CURVE_GF2M:
3027        ret = EC_POINT_set_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL);
3028        break;
3029    default:
3030        jniThrowRuntimeException(env, "invalid curve type");
3031        return;
3032    }
3033
3034    if (ret != 1) {
3035        throwExceptionIfNecessary(env, "EC_POINT_set_affine_coordinates");
3036    }
3037
3038    JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point,
3039            xjavaBytes, yjavaBytes, ret);
3040}
3041
3042static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass, jlong groupRef,
3043        jlong pointRef)
3044{
3045    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3046    const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef);
3047    JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
3048
3049    Unique_BIGNUM x(BN_new());
3050    Unique_BIGNUM y(BN_new());
3051
3052    int ret;
3053    switch (get_EC_GROUP_type(group)) {
3054    case EC_CURVE_GFP:
3055        ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
3056        break;
3057    case EC_CURVE_GF2M:
3058        ret = EC_POINT_get_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL);
3059        break;
3060    default:
3061        jniThrowRuntimeException(env, "invalid curve type");
3062        return NULL;
3063    }
3064    if (ret != 1) {
3065        JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
3066        throwExceptionIfNecessary(env, "EC_POINT_get_affine_coordinates");
3067        return NULL;
3068    }
3069
3070    jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
3071    if (joa == NULL) {
3072        return NULL;
3073    }
3074
3075    jbyteArray xBytes = bignumToArray(env, x.get(), "x");
3076    if (env->ExceptionCheck()) {
3077        return NULL;
3078    }
3079    env->SetObjectArrayElement(joa, 0, xBytes);
3080
3081    jbyteArray yBytes = bignumToArray(env, y.get(), "y");
3082    if (env->ExceptionCheck()) {
3083        return NULL;
3084    }
3085    env->SetObjectArrayElement(joa, 1, yBytes);
3086
3087    JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
3088    return joa;
3089}
3090
3091static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jlong groupRef)
3092{
3093    const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3094    JNI_TRACE("EC_KEY_generate_key(%p)", group);
3095
3096    Unique_EC_KEY eckey(EC_KEY_new());
3097    if (eckey.get() == NULL) {
3098        JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
3099        jniThrowOutOfMemory(env, "Unable to create an EC_KEY");
3100        return 0;
3101    }
3102
3103    if (EC_KEY_set_group(eckey.get(), group) != 1) {
3104        JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
3105        throwExceptionIfNecessary(env, "EC_KEY_set_group");
3106        return 0;
3107    }
3108
3109    if (EC_KEY_generate_key(eckey.get()) != 1) {
3110        JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
3111        throwExceptionIfNecessary(env, "EC_KEY_set_group");
3112        return 0;
3113    }
3114
3115    Unique_EVP_PKEY pkey(EVP_PKEY_new());
3116    if (pkey.get() == NULL) {
3117        JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
3118        throwExceptionIfNecessary(env, "EC_KEY_generate_key");
3119        return 0;
3120    }
3121    if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
3122        jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
3123        return 0;
3124    }
3125    OWNERSHIP_TRANSFERRED(eckey);
3126
3127    JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
3128    return reinterpret_cast<uintptr_t>(pkey.release());
3129}
3130
3131static jlong NativeCrypto_EC_KEY_get0_group(JNIEnv* env, jclass, jlong pkeyRef)
3132{
3133    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3134    JNI_TRACE("EC_KEY_get0_group(%p)", pkey);
3135
3136    if (pkey == NULL) {
3137        jniThrowNullPointerException(env, "pkey == null");
3138        JNI_TRACE("EC_KEY_get0_group(%p) => pkey == null", pkey);
3139        return 0;
3140    }
3141
3142    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
3143        jniThrowRuntimeException(env, "not EC key");
3144        JNI_TRACE("EC_KEY_get0_group(%p) => not EC key (type == %d)", pkey,
3145                EVP_PKEY_type(pkey->type));
3146        return 0;
3147    }
3148
3149    const EC_GROUP* group = EC_KEY_get0_group(pkey->pkey.ec);
3150    JNI_TRACE("EC_KEY_get0_group(%p) => %p", pkey, group);
3151    return reinterpret_cast<uintptr_t>(group);
3152}
3153
3154static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jlong pkeyRef)
3155{
3156    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3157    JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
3158
3159    if (pkey == NULL) {
3160        jniThrowNullPointerException(env, "pkey == null");
3161        return NULL;
3162    }
3163
3164    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3165    if (eckey.get() == NULL) {
3166        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3167        return NULL;
3168    }
3169
3170    const BIGNUM *privkey = EC_KEY_get0_private_key(eckey.get());
3171
3172    jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
3173    if (env->ExceptionCheck()) {
3174        JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
3175        return NULL;
3176    }
3177
3178    JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
3179    return privBytes;
3180}
3181
3182static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jlong pkeyRef)
3183{
3184    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3185    JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
3186
3187    if (pkey == NULL) {
3188        jniThrowNullPointerException(env, "pkey == null");
3189        return 0;
3190    }
3191
3192    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3193    if (eckey.get() == NULL) {
3194        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3195        return 0;
3196    }
3197
3198    Unique_EC_POINT dup(EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()),
3199            EC_KEY_get0_group(eckey.get())));
3200    if (dup.get() == NULL) {
3201        JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
3202        jniThrowRuntimeException(env, "EC_POINT_dup");
3203        return 0;
3204    }
3205
3206    JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
3207    return reinterpret_cast<uintptr_t>(dup.release());
3208}
3209
3210static void NativeCrypto_EC_KEY_set_nonce_from_hash(JNIEnv* env, jclass, jlong pkeyRef,
3211        jboolean enabled)
3212{
3213    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3214    JNI_TRACE("EC_KEY_set_nonce_from_hash(%p, %d)", pkey, enabled ? 1 : 0);
3215
3216    if (pkey == NULL) {
3217        jniThrowNullPointerException(env, "pkey == null");
3218        return;
3219    }
3220
3221    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3222    if (eckey.get() == NULL) {
3223        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3224        return;
3225    }
3226
3227    EC_KEY_set_nonce_from_hash(eckey.get(), enabled ? 1 : 0);
3228}
3229
3230static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass,
3231     jbyteArray outArray, jint outOffset, jlong pubkeyRef, jlong privkeyRef)
3232{
3233    EVP_PKEY* pubPkey = reinterpret_cast<EVP_PKEY*>(pubkeyRef);
3234    EVP_PKEY* privPkey = reinterpret_cast<EVP_PKEY*>(privkeyRef);
3235    JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubPkey, privPkey);
3236
3237    ScopedByteArrayRW out(env, outArray);
3238    if (out.get() == NULL) {
3239        JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer",
3240                outArray, outOffset, pubPkey, privPkey);
3241        return -1;
3242    }
3243
3244    if ((outOffset < 0) || ((size_t) outOffset >= out.size())) {
3245        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
3246        return -1;
3247    }
3248
3249    if (pubPkey == NULL) {
3250        jniThrowNullPointerException(env, "pubPkey == null");
3251        return -1;
3252    }
3253
3254    Unique_EC_KEY pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
3255    if (pubkey.get() == NULL) {
3256        JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
3257        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
3258        return -1;
3259    }
3260
3261    const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
3262    if (pubkeyPoint == NULL) {
3263        JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
3264        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
3265        return -1;
3266    }
3267
3268    if (privPkey == NULL) {
3269        jniThrowNullPointerException(env, "privPkey == null");
3270        return -1;
3271    }
3272
3273    Unique_EC_KEY privkey(EVP_PKEY_get1_EC_KEY(privPkey));
3274    if (privkey.get() == NULL) {
3275        throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY private");
3276        return -1;
3277    }
3278
3279    int outputLength = ECDH_compute_key(
3280            &out[outOffset],
3281            out.size() - outOffset,
3282            pubkeyPoint,
3283            privkey.get(),
3284            NULL // No KDF
3285            );
3286    if (outputLength == -1) {
3287        throwExceptionIfNecessary(env, "ECDH_compute_key");
3288        return -1;
3289    }
3290
3291    return outputLength;
3292}
3293
3294static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
3295    JNI_TRACE_MD("EVP_MD_CTX_create()");
3296
3297    Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
3298    if (ctx.get() == NULL) {
3299        jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX");
3300        return 0;
3301    }
3302
3303    JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
3304    return reinterpret_cast<uintptr_t>(ctx.release());
3305}
3306
3307static void NativeCrypto_EVP_MD_CTX_init(JNIEnv* env, jclass, jobject ctxRef) {
3308    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3309    JNI_TRACE_MD("EVP_MD_CTX_init(%p)", ctx);
3310
3311    if (ctx != NULL) {
3312        EVP_MD_CTX_init(ctx);
3313    }
3314}
3315
3316static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
3317    EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
3318    JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
3319
3320    if (ctx != NULL) {
3321        EVP_MD_CTX_destroy(ctx);
3322    }
3323}
3324
3325static jint NativeCrypto_EVP_MD_CTX_copy(JNIEnv* env, jclass, jobject dstCtxRef, jobject srcCtxRef) {
3326    EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
3327    const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
3328    JNI_TRACE_MD("EVP_MD_CTX_copy(%p. %p)", dst_ctx, src_ctx);
3329
3330    if (src_ctx == NULL) {
3331        return 0;
3332    } else if (dst_ctx == NULL) {
3333        return 0;
3334    }
3335
3336    int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
3337    if (result == 0) {
3338        jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX");
3339        freeOpenSslErrorState();
3340    }
3341
3342    JNI_TRACE_MD("EVP_MD_CTX_copy(%p, %p) => %d", dst_ctx, src_ctx, result);
3343    return result;
3344}
3345
3346/*
3347 * public static native int EVP_DigestFinal(long, byte[], int)
3348 */
3349static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
3350        jint offset) {
3351    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3352    JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset);
3353
3354    if (ctx == NULL) {
3355        return -1;
3356    } else if (hash == NULL) {
3357        jniThrowNullPointerException(env, "ctx == null || hash == null");
3358        return -1;
3359    }
3360
3361    ScopedByteArrayRW hashBytes(env, hash);
3362    if (hashBytes.get() == NULL) {
3363        return -1;
3364    }
3365    unsigned int bytesWritten = -1;
3366    int ok = EVP_DigestFinal_ex(ctx,
3367                             reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
3368                             &bytesWritten);
3369    if (ok == 0) {
3370        throwExceptionIfNecessary(env, "EVP_DigestFinal");
3371    }
3372
3373    JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d) => %d", ctx, hash, offset, bytesWritten);
3374    return bytesWritten;
3375}
3376
3377static jint evpInit(JNIEnv* env, jobject evpMdCtxRef, jlong evpMdRef, const char* jniName,
3378        int (*init_func)(EVP_MD_CTX*, const EVP_MD*, ENGINE*)) {
3379    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3380    const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3381    JNI_TRACE_MD("%s(%p, %p)", jniName, ctx, evp_md);
3382
3383    if (ctx == NULL) {
3384        return 0;
3385    } else if (evp_md == NULL) {
3386        jniThrowNullPointerException(env, "evp_md == null");
3387        return 0;
3388    }
3389
3390    int ok = init_func(ctx, evp_md, NULL);
3391    if (ok == 0) {
3392        bool exception = throwExceptionIfNecessary(env, jniName);
3393        if (exception) {
3394            JNI_TRACE("%s(%p) => threw exception", jniName, evp_md);
3395            return 0;
3396        }
3397    }
3398    JNI_TRACE_MD("%s(%p, %p) => %d", jniName, ctx, evp_md, ok);
3399    return ok;
3400}
3401
3402static jint NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
3403    return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_DigestInit", EVP_DigestInit_ex);
3404}
3405
3406static jint NativeCrypto_EVP_SignInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
3407    return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_SignInit", EVP_DigestInit_ex);
3408}
3409
3410static jint NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
3411    return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_VerifyInit", EVP_DigestInit_ex);
3412}
3413
3414/*
3415 * public static native int EVP_get_digestbyname(java.lang.String)
3416 */
3417static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
3418    JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
3419
3420    if (algorithm == NULL) {
3421        jniThrowNullPointerException(env, NULL);
3422        return -1;
3423    }
3424
3425    ScopedUtfChars algorithmChars(env, algorithm);
3426    if (algorithmChars.c_str() == NULL) {
3427        return 0;
3428    }
3429    JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
3430
3431    const EVP_MD* evp_md = EVP_get_digestbyname(algorithmChars.c_str());
3432    if (evp_md == NULL) {
3433        jniThrowRuntimeException(env, "Hash algorithm not found");
3434        return 0;
3435    }
3436
3437    JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => %p", algorithmChars.c_str(), evp_md);
3438    return reinterpret_cast<uintptr_t>(evp_md);
3439}
3440
3441/*
3442 * public static native int EVP_MD_size(long)
3443 */
3444static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
3445    EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
3446    JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
3447
3448    if (evp_md == NULL) {
3449        jniThrowNullPointerException(env, NULL);
3450        return -1;
3451    }
3452
3453    int result = EVP_MD_size(evp_md);
3454    JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
3455    return result;
3456}
3457
3458/*
3459 * public static int void EVP_MD_block_size(long)
3460 */
3461static jint NativeCrypto_EVP_MD_block_size(JNIEnv* env, jclass, jlong evpMdRef) {
3462    EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
3463    JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p)", evp_md);
3464
3465    if (evp_md == NULL) {
3466        jniThrowNullPointerException(env, NULL);
3467        return -1;
3468    }
3469
3470    int result = EVP_MD_block_size(evp_md);
3471    JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p) => %d", evp_md, result);
3472    return result;
3473}
3474
3475static void NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
3476        const jlong evpMdRef, jlong pkeyRef) {
3477    EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3478    const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3479    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3480    JNI_TRACE("EVP_DigestSignInit(%p, %p, %p)", mdCtx, md, pkey);
3481
3482    if (mdCtx == NULL) {
3483         return;
3484    }
3485
3486    if (md == NULL) {
3487         jniThrowNullPointerException(env, "md == null");
3488         return;
3489    }
3490
3491    if (pkey == NULL) {
3492         jniThrowNullPointerException(env, "pkey == null");
3493         return;
3494    }
3495
3496    if (EVP_DigestSignInit(mdCtx, (EVP_PKEY_CTX **) NULL, md, (ENGINE *) NULL, pkey) <= 0) {
3497        JNI_TRACE("ctx=%p EVP_DigestSignInit => threw exception", mdCtx);
3498        throwExceptionIfNecessary(env, "EVP_DigestSignInit");
3499        return;
3500    }
3501
3502    JNI_TRACE("EVP_DigestSignInit(%p, %p, %p) => success", mdCtx, md, pkey);
3503}
3504
3505static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
3506        jint inLength, const char *jniName, int (*update_func)(EVP_MD_CTX*, const void *,
3507        size_t))
3508{
3509    EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3510    JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
3511
3512    if (mdCtx == NULL) {
3513         return;
3514    }
3515
3516    ScopedByteArrayRO inBytes(env, inJavaBytes);
3517    if (inBytes.get() == NULL) {
3518        return;
3519    }
3520
3521    if (inOffset < 0 || size_t(inOffset) > inBytes.size()) {
3522        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inOffset");
3523        return;
3524    }
3525
3526    const ssize_t inEnd = inOffset + inLength;
3527    if (inLength < 0 || inEnd < 0 || size_t(inEnd) > inBytes.size()) {
3528        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inLength");
3529        return;
3530    }
3531
3532    const unsigned char *tmp = reinterpret_cast<const unsigned char *>(inBytes.get());
3533    if (!update_func(mdCtx, tmp + inOffset, inLength)) {
3534        JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
3535        throwExceptionIfNecessary(env, jniName);
3536    }
3537
3538    JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
3539}
3540
3541static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
3542        jbyteArray inJavaBytes, jint inOffset, jint inLength) {
3543    evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
3544            EVP_DigestUpdate);
3545}
3546
3547static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
3548        jbyteArray inJavaBytes, jint inOffset, jint inLength) {
3549    evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
3550            EVP_DigestUpdate);
3551}
3552
3553static void NativeCrypto_EVP_SignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
3554        jbyteArray inJavaBytes, jint inOffset, jint inLength) {
3555    evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_SignUpdate",
3556            EVP_DigestUpdate);
3557}
3558
3559static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef)
3560{
3561    EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3562    JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
3563
3564    if (mdCtx == NULL) {
3565         return NULL;
3566    }
3567
3568    const size_t expectedSize = EVP_MD_CTX_size(mdCtx);
3569    ScopedLocalRef<jbyteArray> outJavaBytes(env, env->NewByteArray(expectedSize));
3570    if (outJavaBytes.get() == NULL) {
3571        return NULL;
3572    }
3573    ScopedByteArrayRW outBytes(env, outJavaBytes.get());
3574    if (outBytes.get() == NULL) {
3575        return NULL;
3576    }
3577    unsigned char *tmp = reinterpret_cast<unsigned char*>(outBytes.get());
3578    size_t len;
3579    if (!EVP_DigestSignFinal(mdCtx, tmp, &len)) {
3580        JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
3581        throwExceptionIfNecessary(env, "EVP_DigestSignFinal");
3582        return 0;
3583    }
3584
3585    if (len != expectedSize) {
3586        jniThrowRuntimeException(env, "hash size unexpected");
3587        return 0;
3588    }
3589
3590    JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, outJavaBytes.get());
3591    return outJavaBytes.release();
3592}
3593
3594/*
3595 * public static native int EVP_SignFinal(long, byte[], int, long)
3596 */
3597static jint NativeCrypto_EVP_SignFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray signature,
3598        jint offset, jlong pkeyRef) {
3599    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3600    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3601    JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p)", ctx, signature, offset, pkey);
3602
3603    if (ctx == NULL) {
3604        return -1;
3605    } else if (pkey == NULL) {
3606        jniThrowNullPointerException(env, NULL);
3607        return -1;
3608    }
3609
3610    ScopedByteArrayRW signatureBytes(env, signature);
3611    if (signatureBytes.get() == NULL) {
3612        return -1;
3613    }
3614    unsigned int bytesWritten = -1;
3615    int ok = EVP_SignFinal(ctx,
3616                           reinterpret_cast<unsigned char*>(signatureBytes.get() + offset),
3617                           &bytesWritten,
3618                           pkey);
3619    if (ok == 0) {
3620        throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignFinal");
3621    }
3622    JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p) => %u",
3623              ctx, signature, offset, pkey, bytesWritten);
3624
3625    return bytesWritten;
3626}
3627
3628/*
3629 * public static native void EVP_VerifyUpdate(long, byte[], int, int)
3630 */
3631static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, jobject ctxRef,
3632                                          jbyteArray buffer, jint offset, jint length) {
3633    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3634    JNI_TRACE("NativeCrypto_EVP_VerifyUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length);
3635
3636    if (ctx == NULL) {
3637        return;
3638    } else if (buffer == NULL) {
3639        jniThrowNullPointerException(env, NULL);
3640        return;
3641    }
3642
3643    if (offset < 0 || length < 0) {
3644        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
3645        return;
3646    }
3647
3648    ScopedByteArrayRO bufferBytes(env, buffer);
3649    if (bufferBytes.get() == NULL) {
3650        return;
3651    }
3652    if (bufferBytes.size() < static_cast<size_t>(offset + length)) {
3653        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
3654        return;
3655    }
3656
3657    int ok = EVP_VerifyUpdate(ctx,
3658                              reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
3659                              length);
3660    if (ok == 0) {
3661        throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate");
3662    }
3663}
3664
3665/*
3666 * public static native int EVP_VerifyFinal(long, byte[], int, int, long)
3667 */
3668static jint NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray buffer,
3669                                        jint offset, jint length, jlong pkeyRef) {
3670    EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3671    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3672    JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p)",
3673              ctx, buffer, offset, length, pkey);
3674
3675    if (ctx == NULL) {
3676        return -1;
3677    } else if (buffer == NULL || pkey == NULL) {
3678        jniThrowNullPointerException(env, NULL);
3679        return -1;
3680    }
3681
3682    ScopedByteArrayRO bufferBytes(env, buffer);
3683    if (bufferBytes.get() == NULL) {
3684        return -1;
3685    }
3686    int ok = EVP_VerifyFinal(ctx,
3687                             reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
3688                             length,
3689                             pkey);
3690    if (ok < 0) {
3691        throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyFinal");
3692    }
3693
3694    /*
3695     * For DSA keys, OpenSSL appears to have a bug where it returns
3696     * errors for any result != 1. See dsa_ossl.c in dsa_do_verify
3697     */
3698    freeOpenSslErrorState();
3699
3700    JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) => %d",
3701              ctx, buffer, offset, length, pkey, ok);
3702
3703    return ok;
3704}
3705
3706static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3707    JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3708    if (algorithm == NULL) {
3709        JNI_TRACE("EVP_get_cipherbyname(%p) => threw exception algorithm == null", algorithm);
3710        jniThrowNullPointerException(env, NULL);
3711        return -1;
3712    }
3713
3714    ScopedUtfChars algorithmChars(env, algorithm);
3715    if (algorithmChars.c_str() == NULL) {
3716        return 0;
3717    }
3718    JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm = %s", algorithm, algorithmChars.c_str());
3719
3720    const EVP_CIPHER* evp_cipher = EVP_get_cipherbyname(algorithmChars.c_str());
3721    if (evp_cipher == NULL) {
3722        freeOpenSslErrorState();
3723    }
3724
3725    JNI_TRACE("EVP_get_cipherbyname(%s) => %p", algorithmChars.c_str(), evp_cipher);
3726    return reinterpret_cast<uintptr_t>(evp_cipher);
3727}
3728
3729static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jlong ctxRef, jlong evpCipherRef,
3730        jbyteArray keyArray, jbyteArray ivArray, jboolean encrypting) {
3731    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3732    const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3733    JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3734            encrypting ? 1 : 0);
3735
3736    if (ctx == NULL) {
3737        jniThrowNullPointerException(env, "ctx == null");
3738        JNI_TRACE("EVP_CipherUpdate => ctx == null");
3739        return;
3740    }
3741
3742    // The key can be null if we need to set extra parameters.
3743    UniquePtr<unsigned char[]> keyPtr;
3744    if (keyArray != NULL) {
3745        ScopedByteArrayRO keyBytes(env, keyArray);
3746        if (keyBytes.get() == NULL) {
3747            return;
3748        }
3749
3750        keyPtr.reset(new unsigned char[keyBytes.size()]);
3751        memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3752    }
3753
3754    // The IV can be null if we're using ECB.
3755    UniquePtr<unsigned char[]> ivPtr;
3756    if (ivArray != NULL) {
3757        ScopedByteArrayRO ivBytes(env, ivArray);
3758        if (ivBytes.get() == NULL) {
3759            return;
3760        }
3761
3762        ivPtr.reset(new unsigned char[ivBytes.size()]);
3763        memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3764    }
3765
3766    if (!EVP_CipherInit_ex(ctx, evpCipher, NULL, keyPtr.get(), ivPtr.get(), encrypting ? 1 : 0)) {
3767        throwExceptionIfNecessary(env, "EVP_CipherInit_ex");
3768        JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3769        return;
3770    }
3771
3772    JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3773            encrypting ? 1 : 0);
3774}
3775
3776/*
3777 *  public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3778 *          int inOffset, int inLength);
3779 */
3780static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray,
3781        jint outOffset, jbyteArray inArray, jint inOffset, jint inLength) {
3782    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3783    JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3784
3785    if (ctx == NULL) {
3786        jniThrowNullPointerException(env, "ctx == null");
3787        JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3788        return 0;
3789    }
3790
3791    ScopedByteArrayRO inBytes(env, inArray);
3792    if (inBytes.get() == NULL) {
3793        return 0;
3794    }
3795    const size_t inSize = inBytes.size();
3796    if (size_t(inOffset + inLength) > inSize) {
3797        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
3798                "in.length < (inSize + inOffset)");
3799        return 0;
3800    }
3801
3802    ScopedByteArrayRW outBytes(env, outArray);
3803    if (outBytes.get() == NULL) {
3804        return 0;
3805    }
3806    const size_t outSize = outBytes.size();
3807    if (size_t(outOffset + inLength) > outSize) {
3808        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
3809                "out.length < inSize + outOffset + blockSize - 1");
3810        return 0;
3811    }
3812
3813    JNI_TRACE("ctx=%p EVP_CipherUpdate in=%p in.length=%d inOffset=%d inLength=%d out=%p out.length=%d outOffset=%d",
3814            ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(), outOffset);
3815
3816    unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3817    const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3818
3819    int outl;
3820    if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3821        throwExceptionIfNecessary(env, "EVP_CipherUpdate");
3822        JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3823        return 0;
3824    }
3825
3826    JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3827            inOffset, outl);
3828    return outl;
3829}
3830
3831static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray,
3832        jint outOffset) {
3833    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3834    JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3835
3836    if (ctx == NULL) {
3837        jniThrowNullPointerException(env, "ctx == null");
3838        JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3839        return 0;
3840    }
3841
3842    ScopedByteArrayRW outBytes(env, outArray);
3843    if (outBytes.get() == NULL) {
3844        return 0;
3845    }
3846
3847    unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3848
3849    int outl;
3850    if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3851        throwExceptionIfNecessary(env, "EVP_CipherFinal_ex");
3852        JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3853        return 0;
3854    }
3855
3856    JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3857    return outl;
3858}
3859
3860static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3861    const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3862    JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3863
3864    if (evpCipher == NULL) {
3865        jniThrowNullPointerException(env, "evpCipher == null");
3866        JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3867        return 0;
3868    }
3869
3870    const int ivLength = EVP_CIPHER_iv_length(evpCipher);
3871    JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3872    return ivLength;
3873}
3874
3875static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3876    JNI_TRACE("EVP_CIPHER_CTX_new()");
3877
3878    Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
3879    if (ctx.get() == NULL) {
3880        jniThrowOutOfMemory(env, "Unable to allocate cipher context");
3881        JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3882        return 0;
3883    }
3884
3885    JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3886    return reinterpret_cast<uintptr_t>(ctx.release());
3887}
3888
3889static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jlong ctxRef) {
3890    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3891    JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3892
3893    if (ctx == NULL) {
3894        jniThrowNullPointerException(env, "ctx == null");
3895        JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3896        return 0;
3897    }
3898
3899    int blockSize = EVP_CIPHER_CTX_block_size(ctx);
3900    JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3901    return blockSize;
3902}
3903
3904static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jlong ctxRef) {
3905    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3906    JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3907
3908    if (ctx == NULL) {
3909        jniThrowNullPointerException(env, "ctx == null");
3910        JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3911        return 0;
3912    }
3913
3914    int buf_len = ctx->buf_len;
3915    JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3916    return buf_len;
3917}
3918
3919static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jlong ctxRef, jboolean enablePaddingBool) {
3920    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3921    jint enablePadding = enablePaddingBool ? 1 : 0;
3922    JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3923
3924    if (ctx == NULL) {
3925        jniThrowNullPointerException(env, "ctx == null");
3926        JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3927        return;
3928    }
3929
3930    EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3931    JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3932}
3933
3934static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jlong ctxRef,
3935        jint keySizeBits) {
3936    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3937    JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3938
3939    if (ctx == NULL) {
3940        jniThrowNullPointerException(env, "ctx == null");
3941        JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3942        return;
3943    }
3944
3945    if (!EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits)) {
3946        throwExceptionIfNecessary(env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3947        JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3948        return;
3949    }
3950    JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3951}
3952
3953static void NativeCrypto_EVP_CIPHER_CTX_cleanup(JNIEnv* env, jclass, jlong ctxRef) {
3954    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3955    JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p)", ctx);
3956
3957    if (ctx != NULL) {
3958        if (!EVP_CIPHER_CTX_cleanup(ctx)) {
3959            throwExceptionIfNecessary(env, "EVP_CIPHER_CTX_cleanup");
3960            JNI_TRACE("EVP_CIPHER_CTX_cleanup => threw error");
3961            return;
3962        }
3963    }
3964    JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p) => success", ctx);
3965}
3966
3967/**
3968 * public static native void RAND_seed(byte[]);
3969 */
3970static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) {
3971    JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed);
3972    ScopedByteArrayRO randseed(env, seed);
3973    if (randseed.get() == NULL) {
3974        return;
3975    }
3976    RAND_seed(randseed.get(), randseed.size());
3977}
3978
3979static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) {
3980    JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, max_bytes);
3981    ScopedUtfChars file(env, filename);
3982    if (file.c_str() == NULL) {
3983        return -1;
3984    }
3985    int result = RAND_load_file(file.c_str(), max_bytes);
3986    JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result);
3987    return result;
3988}
3989
3990static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
3991    JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
3992
3993    ScopedByteArrayRW outputBytes(env, output);
3994    if (outputBytes.get() == NULL) {
3995        return;
3996    }
3997
3998    unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
3999    if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4000        throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes");
4001        JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4002        return;
4003    }
4004
4005    JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4006}
4007
4008static jint NativeCrypto_OBJ_txt2nid(JNIEnv* env, jclass, jstring oidStr) {
4009    JNI_TRACE("OBJ_txt2nid(%p)", oidStr);
4010
4011    ScopedUtfChars oid(env, oidStr);
4012    if (oid.c_str() == NULL) {
4013        return 0;
4014    }
4015
4016    int nid = OBJ_txt2nid(oid.c_str());
4017    JNI_TRACE("OBJ_txt2nid(%s) => %d", oid.c_str(), nid);
4018    return nid;
4019}
4020
4021static jstring NativeCrypto_OBJ_txt2nid_longName(JNIEnv* env, jclass, jstring oidStr) {
4022    JNI_TRACE("OBJ_txt2nid_longName(%p)", oidStr);
4023
4024    ScopedUtfChars oid(env, oidStr);
4025    if (oid.c_str() == NULL) {
4026        return NULL;
4027    }
4028
4029    JNI_TRACE("OBJ_txt2nid_longName(%s)", oid.c_str());
4030
4031    int nid = OBJ_txt2nid(oid.c_str());
4032    if (nid == NID_undef) {
4033        JNI_TRACE("OBJ_txt2nid_longName(%s) => NID_undef", oid.c_str());
4034        freeOpenSslErrorState();
4035        return NULL;
4036    }
4037
4038    const char* longName = OBJ_nid2ln(nid);
4039    JNI_TRACE("OBJ_txt2nid_longName(%s) => %s", oid.c_str(), longName);
4040    return env->NewStringUTF(longName);
4041}
4042
4043static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, ASN1_OBJECT* obj) {
4044    /*
4045     * The OBJ_obj2txt API doesn't "measure" if you pass in NULL as the buffer.
4046     * Just make a buffer that's large enough here. The documentation recommends
4047     * 80 characters.
4048     */
4049    char output[128];
4050    int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4051    if (ret < 0) {
4052        throwExceptionIfNecessary(env, "ASN1_OBJECT_to_OID_string");
4053        return NULL;
4054    } else if (size_t(ret) >= sizeof(output)) {
4055        jniThrowRuntimeException(env, "ASN1_OBJECT_to_OID_string buffer too small");
4056        return NULL;
4057    }
4058
4059    JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4060    return env->NewStringUTF(output);
4061}
4062
4063static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj) {
4064    JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4065
4066    if (streamObj == NULL) {
4067        jniThrowNullPointerException(env, "stream == null");
4068        return 0;
4069    }
4070
4071    Unique_BIO bio(BIO_new(&stream_bio_method));
4072    if (bio.get() == NULL) {
4073        return 0;
4074    }
4075
4076    bio_stream_assign(bio.get(), new BIO_InputStream(streamObj));
4077
4078    JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4079    return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4080}
4081
4082static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4083    JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4084
4085    if (streamObj == NULL) {
4086        jniThrowNullPointerException(env, "stream == null");
4087        return 0;
4088    }
4089
4090    Unique_BIO bio(BIO_new(&stream_bio_method));
4091    if (bio.get() == NULL) {
4092        return 0;
4093    }
4094
4095    bio_stream_assign(bio.get(), new BIO_OutputStream(streamObj));
4096
4097    JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4098    return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4099}
4100
4101static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
4102    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4103    JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
4104
4105    if (outputJavaBytes == NULL) {
4106        jniThrowNullPointerException(env, "output == null");
4107        JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
4108        return 0;
4109    }
4110
4111    int outputSize = env->GetArrayLength(outputJavaBytes);
4112
4113    UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
4114    if (buffer.get() == NULL) {
4115        jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
4116        return 0;
4117    }
4118
4119    int read = BIO_read(bio, buffer.get(), outputSize);
4120    if (read <= 0) {
4121        jniThrowException(env, "java/io/IOException", "BIO_read");
4122        JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
4123        return 0;
4124    }
4125
4126    env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
4127    JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
4128    return read;
4129}
4130
4131static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
4132        jint offset, jint length) {
4133    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4134    JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
4135
4136    if (inputJavaBytes == NULL) {
4137        jniThrowNullPointerException(env, "input == null");
4138        return;
4139    }
4140
4141    if (offset < 0 || length < 0) {
4142        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "offset < 0 || length < 0");
4143        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4144        return;
4145    }
4146
4147    int inputSize = env->GetArrayLength(inputJavaBytes);
4148    if (inputSize < offset + length) {
4149        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
4150                "input.length < offset + length");
4151        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4152        return;
4153    }
4154
4155    UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
4156    if (buffer.get() == NULL) {
4157        jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
4158        return;
4159    }
4160
4161    env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
4162    if (BIO_write(bio, buffer.get(), length) != length) {
4163        freeOpenSslErrorState();
4164        jniThrowException(env, "java/io/IOException", "BIO_write");
4165        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
4166        return;
4167    }
4168
4169    JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
4170}
4171
4172static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4173    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4174    JNI_TRACE("BIO_free_all(%p)", bio);
4175
4176    if (bio == NULL) {
4177        jniThrowNullPointerException(env, "bio == null");
4178        return;
4179    }
4180
4181    BIO_free_all(bio);
4182}
4183
4184static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4185    JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4186
4187    Unique_BIO buffer(BIO_new(BIO_s_mem()));
4188    if (buffer.get() == NULL) {
4189        jniThrowOutOfMemory(env, "Unable to allocate BIO");
4190        JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4191        return NULL;
4192    }
4193
4194    /* Don't interpret the string. */
4195    flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4196
4197    /* Write in given format and null terminate. */
4198    X509_NAME_print_ex(buffer.get(), name, 0, flags);
4199    BIO_write(buffer.get(), "\0", 1);
4200
4201    char *tmp;
4202    BIO_get_mem_data(buffer.get(), &tmp);
4203    JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4204    return env->NewStringUTF(tmp);
4205}
4206
4207
4208/**
4209 * Converts GENERAL_NAME items to the output format expected in
4210 * X509Certificate#getSubjectAlternativeNames and
4211 * X509Certificate#getIssuerAlternativeNames return.
4212 */
4213static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4214    switch (gen->type) {
4215    case GEN_EMAIL:
4216    case GEN_DNS:
4217    case GEN_URI: {
4218        // This must not be a T61String and must not contain NULLs.
4219        const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
4220        ssize_t len = ASN1_STRING_length(gen->d.ia5);
4221        if ((len == static_cast<ssize_t>(strlen(data)))
4222                && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
4223            JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
4224            return env->NewStringUTF(data);
4225        } else {
4226            jniThrowException(env, "java/security/cert/CertificateParsingException",
4227                    "Invalid dNSName encoding");
4228            JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4229            return NULL;
4230        }
4231    }
4232    case GEN_DIRNAME:
4233        /* Write in RFC 2253 format */
4234        return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4235    case GEN_IPADD: {
4236        const void *ip = reinterpret_cast<const void *>(gen->d.ip->data);
4237        if (gen->d.ip->length == 4) {
4238            // IPv4
4239            UniquePtr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4240            if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != NULL) {
4241                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4242                return env->NewStringUTF(buffer.get());
4243            } else {
4244                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen, strerror(errno));
4245            }
4246        } else if (gen->d.ip->length == 16) {
4247            // IPv6
4248            UniquePtr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4249            if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != NULL) {
4250                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4251                return env->NewStringUTF(buffer.get());
4252            } else {
4253                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno));
4254            }
4255        }
4256
4257        /* Invalid IP encodings are pruned out without throwing an exception. */
4258        return NULL;
4259    }
4260    case GEN_RID:
4261        return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4262    case GEN_OTHERNAME:
4263    case GEN_X400:
4264    default:
4265        return ASN1ToByteArray<GENERAL_NAME, i2d_GENERAL_NAME>(env, gen);
4266    }
4267
4268    return NULL;
4269}
4270
4271#define GN_STACK_SUBJECT_ALT_NAME 1
4272#define GN_STACK_ISSUER_ALT_NAME 2
4273
4274static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4275        jint type) {
4276    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4277    JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4278
4279    if (x509 == NULL) {
4280        jniThrowNullPointerException(env, "x509 == null");
4281        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4282        return NULL;
4283    }
4284
4285    X509_check_ca(x509);
4286
4287    STACK_OF(GENERAL_NAME)* gn_stack;
4288    Unique_sk_GENERAL_NAME stackHolder;
4289    if (type == GN_STACK_SUBJECT_ALT_NAME) {
4290        gn_stack = x509->altname;
4291    } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4292        stackHolder.reset(
4293                static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, NID_issuer_alt_name,
4294                        NULL, NULL)));
4295        gn_stack = stackHolder.get();
4296    } else {
4297        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4298        return NULL;
4299    }
4300
4301    int count = sk_GENERAL_NAME_num(gn_stack);
4302    if (count <= 0) {
4303        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4304        return NULL;
4305    }
4306
4307    /*
4308     * Keep track of how many originally so we can ignore any invalid
4309     * values later.
4310     */
4311    const int origCount = count;
4312
4313    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
4314    for (int i = 0, j = 0; i < origCount; i++, j++) {
4315        GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
4316        ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4317        if (env->ExceptionCheck()) {
4318            JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4319                    x509, type);
4320            return NULL;
4321        }
4322
4323        /*
4324         * If it's NULL, we'll have to skip this, reduce the number of total
4325         * entries, and fix up the array later.
4326         */
4327        if (val.get() == NULL) {
4328            j--;
4329            count--;
4330            continue;
4331        }
4332
4333        ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
4334
4335        ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
4336                integer_valueOfMethod, gen->type));
4337        env->SetObjectArrayElement(item.get(), 0, type.get());
4338        env->SetObjectArrayElement(item.get(), 1, val.get());
4339
4340        env->SetObjectArrayElement(joa.get(), j, item.get());
4341    }
4342
4343    if (count == 0) {
4344        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning NULL",
4345                x509, type, origCount);
4346        joa.reset(NULL);
4347    } else if (origCount != count) {
4348        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
4349                origCount, count);
4350
4351        ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
4352                NULL));
4353
4354        for (int i = 0; i < count; i++) {
4355            ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4356            env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4357        }
4358
4359        joa.reset(joa_copy.release());
4360    }
4361
4362    JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4363    return joa.release();
4364}
4365
4366static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref) {
4367    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4368    JNI_TRACE("X509_get_notBefore(%p)", x509);
4369
4370    if (x509 == NULL) {
4371        jniThrowNullPointerException(env, "x509 == null");
4372        JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4373        return 0;
4374    }
4375
4376    ASN1_TIME* notBefore = X509_get_notBefore(x509);
4377    JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4378    return reinterpret_cast<uintptr_t>(notBefore);
4379}
4380
4381static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref) {
4382    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4383    JNI_TRACE("X509_get_notAfter(%p)", x509);
4384
4385    if (x509 == NULL) {
4386        jniThrowNullPointerException(env, "x509 == null");
4387        JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4388        return 0;
4389    }
4390
4391    ASN1_TIME* notAfter = X509_get_notAfter(x509);
4392    JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4393    return reinterpret_cast<uintptr_t>(notAfter);
4394}
4395
4396static long NativeCrypto_X509_get_version(JNIEnv*, jclass, jlong x509Ref) {
4397    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4398    JNI_TRACE("X509_get_version(%p)", x509);
4399
4400    long version = X509_get_version(x509);
4401    JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4402    return version;
4403}
4404
4405template<typename T>
4406static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type, ASN1_INTEGER* (*get_serial_func)(T*)) {
4407    JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4408
4409    if (x509Type == NULL) {
4410        jniThrowNullPointerException(env, "x509Type == null");
4411        JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4412        return NULL;
4413    }
4414
4415    ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4416    Unique_BIGNUM serialBn(ASN1_INTEGER_to_BN(serialNumber, NULL));
4417    if (serialBn.get() == NULL) {
4418        JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4419        return NULL;
4420    }
4421
4422    ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4423    if (env->ExceptionCheck()) {
4424        JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4425        return NULL;
4426    }
4427
4428    JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4429    return serialArray.release();
4430}
4431
4432/* OpenSSL includes set_serialNumber but not get. */
4433#if !defined(X509_REVOKED_get_serialNumber)
4434static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) {
4435    return x->serialNumber;
4436}
4437#endif
4438
4439static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref) {
4440    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4441    JNI_TRACE("X509_get_serialNumber(%p)", x509);
4442    return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber);
4443}
4444
4445static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass, jlong x509RevokedRef) {
4446    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4447    JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4448    return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber);
4449}
4450
4451static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref, jlong pkeyRef) {
4452    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4453    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
4454    JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4455
4456    if (x509 == NULL) {
4457        jniThrowNullPointerException(env, "x509 == null");
4458        JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4459        return;
4460    }
4461
4462    if (pkey == NULL) {
4463        jniThrowNullPointerException(env, "pkey == null");
4464        JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4465        return;
4466    }
4467
4468    if (X509_verify(x509, pkey) != 1) {
4469        throwExceptionIfNecessary(env, "X509_verify");
4470        JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4471    } else {
4472        JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4473    }
4474}
4475
4476static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref) {
4477    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4478    JNI_TRACE("get_X509_cert_info_enc(%p)", x509);
4479    return ASN1ToByteArray<X509_CINF, i2d_X509_CINF>(env, x509->cert_info);
4480}
4481
4482static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) {
4483    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4484    JNI_TRACE("get_X509_ex_flags(%p)", x509);
4485
4486    if (x509 == NULL) {
4487        jniThrowNullPointerException(env, "x509 == null");
4488        JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4489        return 0;
4490    }
4491
4492    X509_check_ca(x509);
4493
4494    return x509->ex_flags;
4495}
4496
4497static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
4498    X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4499    X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4500    JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4501
4502    int ret = X509_check_issued(x509_1, x509_2);
4503    JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4504    return ret;
4505}
4506
4507static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
4508    *signature = x509->signature;
4509}
4510
4511static void get_X509_CRL_signature(X509_CRL *crl, ASN1_BIT_STRING** signature) {
4512    *signature = crl->signature;
4513}
4514
4515template<typename T>
4516static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type, void (*get_signature_func)(T*, ASN1_BIT_STRING**)) {
4517    JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4518
4519    if (x509Type == NULL) {
4520        jniThrowNullPointerException(env, "x509Type == null");
4521        JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4522        return NULL;
4523    }
4524
4525    ASN1_BIT_STRING* signature;
4526    get_signature_func(x509Type, &signature);
4527
4528    ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length));
4529    if (env->ExceptionCheck()) {
4530        JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4531        return NULL;
4532    }
4533
4534    ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4535    if (signatureBytes.get() == NULL) {
4536        JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4537        return NULL;
4538    }
4539
4540    memcpy(signatureBytes.get(), signature->data, signature->length);
4541
4542    JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4543            signature->length);
4544    return signatureArray.release();
4545}
4546
4547static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref) {
4548    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4549    JNI_TRACE("get_X509_signature(%p)", x509);
4550    return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4551}
4552
4553static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef) {
4554    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4555    JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4556    return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4557}
4558
4559static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef, jlong x509Ref) {
4560    X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4561    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4562    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4563
4564    if (x509crl == NULL) {
4565        jniThrowNullPointerException(env, "x509crl == null");
4566        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4567        return 0;
4568    } else if (x509 == NULL) {
4569        jniThrowNullPointerException(env, "x509 == null");
4570        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4571        return 0;
4572    }
4573
4574    X509_REVOKED* revoked = NULL;
4575    int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4576    if (ret == 0) {
4577        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4578        return 0;
4579    }
4580
4581    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4582    return reinterpret_cast<uintptr_t>(revoked);
4583}
4584
4585static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef, jbyteArray serialArray) {
4586    X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4587    JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4588
4589    if (x509crl == NULL) {
4590        jniThrowNullPointerException(env, "x509crl == null");
4591        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4592        return 0;
4593    }
4594
4595    Unique_BIGNUM serialBn(BN_new());
4596    if (serialBn.get() == NULL) {
4597        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4598        return 0;
4599    }
4600
4601    BIGNUM* serialBare = serialBn.get();
4602    if (!arrayToBignum(env, serialArray, &serialBare)) {
4603        if (!env->ExceptionCheck()) {
4604            jniThrowNullPointerException(env, "serial == null");
4605        }
4606        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4607        return 0;
4608    }
4609
4610    Unique_ASN1_INTEGER serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), NULL));
4611    if (serialInteger.get() == NULL) {
4612        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4613        return 0;
4614    }
4615
4616    X509_REVOKED* revoked = NULL;
4617    int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4618    if (ret == 0) {
4619        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4620        return 0;
4621    }
4622
4623    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4624    return reinterpret_cast<uintptr_t>(revoked);
4625}
4626
4627
4628/* This appears to be missing from OpenSSL. */
4629#if !defined(X509_REVOKED_dup)
4630X509_REVOKED* X509_REVOKED_dup(X509_REVOKED* x) {
4631    return reinterpret_cast<X509_REVOKED*>(ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), x));
4632}
4633#endif
4634
4635static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef) {
4636    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4637    JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4638
4639    if (crl == NULL) {
4640        jniThrowNullPointerException(env, "crl == null");
4641        return NULL;
4642    }
4643
4644    STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4645    if (stack == NULL) {
4646        JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4647        return NULL;
4648    }
4649
4650    size_t size = sk_X509_REVOKED_num(stack);
4651
4652    ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(size));
4653    ScopedLongArrayRW revoked(env, revokedArray.get());
4654    for (size_t i = 0; i < size; i++) {
4655        X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4656        revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4657    }
4658
4659    JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%d]", stack, revokedArray.get(), size);
4660    return revokedArray.release();
4661}
4662
4663static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef) {
4664    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4665    JNI_TRACE("i2d_X509_CRL(%p)", crl);
4666    return ASN1ToByteArray<X509_CRL, i2d_X509_CRL>(env, crl);
4667}
4668
4669static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef) {
4670    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4671    JNI_TRACE("X509_CRL_free(%p)", crl);
4672
4673    if (crl == NULL) {
4674        jniThrowNullPointerException(env, "crl == null");
4675        JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4676        return;
4677    }
4678
4679    X509_CRL_free(crl);
4680}
4681
4682static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef) {
4683    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4684    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4685    JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4686
4687    if (bio == NULL) {
4688        jniThrowNullPointerException(env, "bio == null");
4689        JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4690        return;
4691    }
4692
4693    if (crl == NULL) {
4694        jniThrowNullPointerException(env, "crl == null");
4695        JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4696        return;
4697    }
4698
4699    if (!X509_CRL_print(bio, crl)) {
4700        throwExceptionIfNecessary(env, "X509_CRL_print");
4701        JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4702    } else {
4703        JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4704    }
4705}
4706
4707static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) {
4708    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4709    JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4710
4711    if (crl == NULL || crl->sig_alg == NULL) {
4712        jniThrowNullPointerException(env, "crl == NULL || crl->sig_alg == NULL");
4713        JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == NULL", crl);
4714        return NULL;
4715    }
4716
4717    return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm);
4718}
4719
4720static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef) {
4721    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4722    JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4723
4724    if (crl == NULL) {
4725        jniThrowNullPointerException(env, "crl == null");
4726        JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4727        return NULL;
4728    }
4729
4730    if (crl->sig_alg->parameter == NULL) {
4731        JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl);
4732        return NULL;
4733    }
4734
4735    return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, crl->sig_alg->parameter);
4736}
4737
4738static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef) {
4739    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4740    JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4741    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_CRL_get_issuer(crl));
4742}
4743
4744static long NativeCrypto_X509_CRL_get_version(JNIEnv*, jclass, jlong x509CrlRef) {
4745    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4746    JNI_TRACE("X509_CRL_get_version(%p)", crl);
4747
4748    long version = X509_CRL_get_version(crl);
4749    JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4750    return version;
4751}
4752
4753template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
4754        X509_EXTENSION* (*get_ext_func)(T*, int)>
4755static X509_EXTENSION *X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) {
4756    JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4757
4758    if (x509Type == NULL) {
4759        jniThrowNullPointerException(env, "x509 == null");
4760        return NULL;
4761    }
4762
4763    ScopedUtfChars oid(env, oidString);
4764    if (oid.c_str() == NULL) {
4765        return NULL;
4766    }
4767
4768    Unique_ASN1_OBJECT asn1(OBJ_txt2obj(oid.c_str(), 1));
4769    if (asn1.get() == NULL) {
4770        JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4771        freeOpenSslErrorState();
4772        return NULL;
4773    }
4774
4775    int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4776    if (extIndex == -1) {
4777        JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4778        return NULL;
4779    }
4780
4781    X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4782    JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4783    return ext;
4784}
4785
4786template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
4787        X509_EXTENSION* (*get_ext_func)(T*, int)>
4788static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) {
4789    X509_EXTENSION* ext = X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type,
4790            oidString);
4791    if (ext == NULL) {
4792        JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4793        return NULL;
4794    }
4795
4796    JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value);
4797    return ASN1ToByteArray<ASN1_OCTET_STRING, i2d_ASN1_OCTET_STRING>(env, ext->value);
4798}
4799
4800static jint NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef, jstring oid) {
4801    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4802    JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4803    X509_EXTENSION* ext = X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(
4804            env, crl, oid);
4805    JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4806    return reinterpret_cast<uintptr_t>(ext);
4807}
4808
4809static jint NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4810        jstring oid) {
4811    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4812    JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4813    X509_EXTENSION* ext = X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ,
4814            X509_REVOKED_get_ext>(env, revoked, oid);
4815    JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4816    return reinterpret_cast<uintptr_t>(ext);
4817}
4818
4819static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4820    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4821    JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4822
4823    if (revoked == NULL) {
4824        jniThrowNullPointerException(env, "revoked == null");
4825        JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4826        return 0;
4827    }
4828
4829    X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4830    JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4831    return reinterpret_cast<uintptr_t>(dup);
4832}
4833
4834static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass, jlong x509RevokedRef) {
4835    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4836    JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
4837
4838    if (revoked == NULL) {
4839        jniThrowNullPointerException(env, "revoked == null");
4840        JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
4841        return 0;
4842    }
4843
4844    JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate);
4845    return reinterpret_cast<uintptr_t>(revoked->revocationDate);
4846}
4847
4848#pragma GCC diagnostic push
4849#pragma GCC diagnostic ignored "-Wwrite-strings"
4850static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) {
4851    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4852    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4853    JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
4854
4855    if (bio == NULL) {
4856        jniThrowNullPointerException(env, "bio == null");
4857        JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
4858        return;
4859    }
4860
4861    if (revoked == NULL) {
4862        jniThrowNullPointerException(env, "revoked == null");
4863        JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
4864        return;
4865    }
4866
4867    BIO_printf(bio, "Serial Number: ");
4868    i2a_ASN1_INTEGER(bio, revoked->serialNumber);
4869    BIO_printf(bio, "\nRevocation Date: ");
4870    ASN1_TIME_print(bio, revoked->revocationDate);
4871    BIO_printf(bio, "\n");
4872    X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
4873}
4874#pragma GCC diagnostic pop
4875
4876static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) {
4877    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4878    JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
4879    return ASN1ToByteArray<X509_CRL_INFO, i2d_X509_CRL_INFO>(env, crl->crl);
4880}
4881
4882static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef, jlong pkeyRef) {
4883    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4884    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
4885    JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
4886
4887    if (crl == NULL) {
4888        jniThrowNullPointerException(env, "crl == null");
4889        JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
4890        return;
4891    }
4892
4893    if (pkey == NULL) {
4894        jniThrowNullPointerException(env, "pkey == null");
4895        JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
4896        return;
4897    }
4898
4899    if (X509_CRL_verify(crl, pkey) != 1) {
4900        throwExceptionIfNecessary(env, "X509_CRL_verify");
4901        JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
4902    } else {
4903        JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
4904    }
4905}
4906
4907static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
4908    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4909    JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
4910
4911    if (crl == NULL) {
4912        jniThrowNullPointerException(env, "crl == null");
4913        JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
4914        return 0;
4915    }
4916
4917    ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
4918    JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
4919    return reinterpret_cast<uintptr_t>(lastUpdate);
4920}
4921
4922static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
4923    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4924    JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
4925
4926    if (crl == NULL) {
4927        jniThrowNullPointerException(env, "crl == null");
4928        JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
4929        return 0;
4930    }
4931
4932    ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
4933    JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
4934    return reinterpret_cast<uintptr_t>(nextUpdate);
4935}
4936
4937static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
4938    X509_REVOKED* x509Revoked =
4939            reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4940    JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
4941    return ASN1ToByteArray<X509_REVOKED, i2d_X509_REVOKED>(env, x509Revoked);
4942}
4943
4944static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
4945    X509_EXTENSION* ext = reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
4946
4947    if (ext == NULL) {
4948        jniThrowNullPointerException(env, "ext == NULL");
4949        return 0;
4950    }
4951
4952    return X509_supported_extension(ext);
4953}
4954
4955static inline void get_ASN1_TIME_data(char **data, int* output, size_t len) {
4956    char c = **data;
4957    **data = '\0';
4958    *data -= len;
4959    *output = atoi(*data);
4960    *(*data + len) = c;
4961}
4962
4963static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef, jobject calendar) {
4964    ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
4965    JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
4966
4967    if (asn1Time == NULL) {
4968        jniThrowNullPointerException(env, "asn1Time == null");
4969        return;
4970    }
4971
4972    Unique_ASN1_GENERALIZEDTIME gen(ASN1_TIME_to_generalizedtime(asn1Time, NULL));
4973    if (gen.get() == NULL) {
4974        jniThrowNullPointerException(env, "asn1Time == null");
4975        return;
4976    }
4977
4978    if (gen->length < 14 || gen->data == NULL) {
4979        jniThrowNullPointerException(env, "gen->length < 14 || gen->data == NULL");
4980        return;
4981    }
4982
4983    int sec, min, hour, mday, mon, year;
4984
4985    char *p = (char*) &gen->data[14];
4986
4987    get_ASN1_TIME_data(&p, &sec, 2);
4988    get_ASN1_TIME_data(&p, &min, 2);
4989    get_ASN1_TIME_data(&p, &hour, 2);
4990    get_ASN1_TIME_data(&p, &mday, 2);
4991    get_ASN1_TIME_data(&p, &mon, 2);
4992    get_ASN1_TIME_data(&p, &year, 4);
4993
4994    env->CallVoidMethod(calendar, calendar_setMethod, year, mon - 1, mday, hour, min, sec);
4995}
4996
4997static jstring NativeCrypto_OBJ_txt2nid_oid(JNIEnv* env, jclass, jstring oidStr) {
4998    JNI_TRACE("OBJ_txt2nid_oid(%p)", oidStr);
4999
5000    ScopedUtfChars oid(env, oidStr);
5001    if (oid.c_str() == NULL) {
5002        return NULL;
5003    }
5004
5005    JNI_TRACE("OBJ_txt2nid_oid(%s)", oid.c_str());
5006
5007    int nid = OBJ_txt2nid(oid.c_str());
5008    if (nid == NID_undef) {
5009        JNI_TRACE("OBJ_txt2nid_oid(%s) => NID_undef", oid.c_str());
5010        freeOpenSslErrorState();
5011        return NULL;
5012    }
5013
5014    Unique_ASN1_OBJECT obj(OBJ_nid2obj(nid));
5015    if (obj.get() == NULL) {
5016        throwExceptionIfNecessary(env, "OBJ_nid2obj");
5017        return NULL;
5018    }
5019
5020    ScopedLocalRef<jstring> ouputStr(env, ASN1_OBJECT_to_OID_string(env, obj.get()));
5021    JNI_TRACE("OBJ_txt2nid_oid(%s) => %p", oid.c_str(), ouputStr.get());
5022    return ouputStr.release();
5023}
5024
5025static jstring NativeCrypto_X509_NAME_print_ex(JNIEnv* env, jclass, jlong x509NameRef, jlong jflags) {
5026    X509_NAME* x509name = reinterpret_cast<X509_NAME*>(static_cast<uintptr_t>(x509NameRef));
5027    unsigned long flags = static_cast<unsigned long>(jflags);
5028    JNI_TRACE("X509_NAME_print_ex(%p, %ld)", x509name, flags);
5029
5030    if (x509name == NULL) {
5031        jniThrowNullPointerException(env, "x509name == null");
5032        JNI_TRACE("X509_NAME_print_ex(%p, %ld) => x509name == null", x509name, flags);
5033        return NULL;
5034    }
5035
5036    return X509_NAME_to_jstring(env, x509name, flags);
5037}
5038
5039template <typename T, T* (*d2i_func)(BIO*, T**)>
5040static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5041    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5042    JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5043
5044    if (bio == NULL) {
5045        jniThrowNullPointerException(env, "bio == null");
5046        return 0;
5047    }
5048
5049    T* x = d2i_func(bio, NULL);
5050    if (x == NULL) {
5051        throwExceptionIfNecessary(env, "d2i_ASN1Object_to_jlong");
5052        return 0;
5053    }
5054
5055    return reinterpret_cast<uintptr_t>(x);
5056}
5057
5058static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5059    return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5060}
5061
5062static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5063    return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5064}
5065
5066static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5067    X509* x = ByteArrayToASN1<X509, d2i_X509>(env, certBytes);
5068    return reinterpret_cast<uintptr_t>(x);
5069}
5070
5071static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref) {
5072    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5073    JNI_TRACE("i2d_X509(%p)", x509);
5074    return ASN1ToByteArray<X509, i2d_X509>(env, x509);
5075}
5076
5077static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref) {
5078    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5079    JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5080    return ASN1ToByteArray<X509_PUBKEY, i2d_X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509));
5081}
5082
5083
5084template<typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
5085static jlong PEM_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5086    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5087    JNI_TRACE("PEM_ASN1Object_to_jlong(%p)", bio);
5088
5089    if (bio == NULL) {
5090        jniThrowNullPointerException(env, "bio == null");
5091        JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => bio == null", bio);
5092        return 0;
5093    }
5094
5095    T* x = PEM_read_func(bio, NULL, NULL, NULL);
5096    if (x == NULL) {
5097        throwExceptionIfNecessary(env, "PEM_ASN1Object_to_jlong");
5098        // Sometimes the PEM functions fail without pushing an error
5099        if (!env->ExceptionCheck()) {
5100            jniThrowRuntimeException(env, "Failure parsing PEM");
5101        }
5102        JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => threw exception", bio);
5103        return 0;
5104    }
5105
5106    JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => %p", bio, x);
5107    return reinterpret_cast<uintptr_t>(x);
5108}
5109
5110static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5111    JNI_TRACE("PEM_read_bio_X509(0x%llx)", bioRef);
5112    return PEM_ASN1Object_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5113}
5114
5115static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5116    JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", bioRef);
5117    return PEM_ASN1Object_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5118}
5119
5120static STACK_OF(X509)* PKCS7_get_certs(PKCS7* pkcs7) {
5121    if (PKCS7_type_is_signed(pkcs7)) {
5122        return pkcs7->d.sign->cert;
5123    } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5124        return pkcs7->d.signed_and_enveloped->cert;
5125    } else {
5126        JNI_TRACE("PKCS7_get_certs(%p) => unknown PKCS7 type", pkcs7);
5127        return NULL;
5128    }
5129}
5130
5131static STACK_OF(X509_CRL)* PKCS7_get_CRLs(PKCS7* pkcs7) {
5132    if (PKCS7_type_is_signed(pkcs7)) {
5133        return pkcs7->d.sign->crl;
5134    } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5135        return pkcs7->d.signed_and_enveloped->crl;
5136    } else {
5137        JNI_TRACE("PKCS7_get_CRLs(%p) => unknown PKCS7 type", pkcs7);
5138        return NULL;
5139    }
5140}
5141
5142template <typename T, typename T_stack>
5143static jlongArray PKCS7_to_ItemArray(JNIEnv* env, T_stack* stack, T* (*dup_func)(T*))
5144{
5145    if (stack == NULL) {
5146        return NULL;
5147    }
5148
5149    ScopedLocalRef<jlongArray> ref_array(env, NULL);
5150    size_t size = sk_num(reinterpret_cast<_STACK*>(stack));
5151    ref_array.reset(env->NewLongArray(size));
5152    ScopedLongArrayRW items(env, ref_array.get());
5153    for (size_t i = 0; i < size; i++) {
5154        T* item = reinterpret_cast<T*>(sk_value(reinterpret_cast<_STACK*>(stack), i));
5155        items[i] = reinterpret_cast<uintptr_t>(dup_func(item));
5156    }
5157
5158    JNI_TRACE("PKCS7_to_ItemArray(%p) => %p [size=%d]", stack, ref_array.get(), size);
5159    return ref_array.release();
5160}
5161
5162#define PKCS7_CERTS 1
5163#define PKCS7_CRLS 2
5164
5165static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5166    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5167    JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5168
5169    if (bio == NULL) {
5170        jniThrowNullPointerException(env, "bio == null");
5171        JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5172        return 0;
5173    }
5174
5175    Unique_PKCS7 pkcs7(PEM_read_bio_PKCS7(bio, NULL, NULL, NULL));
5176    if (pkcs7.get() == NULL) {
5177        throwExceptionIfNecessary(env, "PEM_read_bio_PKCS7_CRLs");
5178        JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => threw exception", bio);
5179        return 0;
5180    }
5181
5182    switch (which) {
5183    case PKCS7_CERTS:
5184        return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5185    case PKCS7_CRLS:
5186        return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5187                X509_CRL_dup);
5188    default:
5189        jniThrowRuntimeException(env, "unknown PKCS7 field");
5190        return NULL;
5191    }
5192}
5193
5194static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5195    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5196    JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5197
5198    if (bio == NULL) {
5199        jniThrowNullPointerException(env, "bio == null");
5200        JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5201        return 0;
5202    }
5203
5204    Unique_PKCS7 pkcs7(d2i_PKCS7_bio(bio, NULL));
5205    if (pkcs7.get() == NULL) {
5206        throwExceptionIfNecessary(env, "d2i_PKCS7_bio");
5207        JNI_TRACE("d2i_PKCS7_bio(%p, %d) => threw exception", bio, which);
5208        return 0;
5209    }
5210
5211    switch (which) {
5212    case PKCS7_CERTS:
5213        return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5214    case PKCS7_CRLS:
5215        return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5216                X509_CRL_dup);
5217    default:
5218        jniThrowRuntimeException(env, "unknown PKCS7 field");
5219        return NULL;
5220    }
5221}
5222
5223static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5224    JNI_TRACE("i2d_PKCS7(%p)", certsArray);
5225
5226    Unique_PKCS7 pkcs7(PKCS7_new());
5227    if (pkcs7.get() == NULL) {
5228        jniThrowNullPointerException(env, "pkcs7 == null");
5229        JNI_TRACE("i2d_PKCS7(%p) => pkcs7 == null", certsArray);
5230        return NULL;
5231    }
5232
5233    if (PKCS7_set_type(pkcs7.get(), NID_pkcs7_signed) != 1) {
5234        throwExceptionIfNecessary(env, "PKCS7_set_type");
5235        return NULL;
5236    }
5237
5238    ScopedLongArrayRO certs(env, certsArray);
5239    for (size_t i = 0; i < certs.size(); i++) {
5240        X509* item = reinterpret_cast<X509*>(certs[i]);
5241        if (PKCS7_add_certificate(pkcs7.get(), item) != 1) {
5242            throwExceptionIfNecessary(env, "i2d_PKCS7");
5243            return NULL;
5244        }
5245    }
5246
5247    JNI_TRACE("i2d_PKCS7(%p) => %d certs", certsArray, certs.size());
5248    return ASN1ToByteArray<PKCS7, i2d_PKCS7>(env, pkcs7.get());
5249}
5250
5251typedef STACK_OF(X509) PKIPATH;
5252
5253ASN1_ITEM_TEMPLATE(PKIPATH) =
5254    ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PkiPath, X509)
5255ASN1_ITEM_TEMPLATE_END(PKIPATH)
5256
5257static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5258    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5259    JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5260
5261    Unique_sk_X509 path((PKIPATH*) ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKIPATH), bio, NULL));
5262    if (path.get() == NULL) {
5263        throwExceptionIfNecessary(env, "ASN1_seq_unpack_X509_bio");
5264        return NULL;
5265    }
5266
5267    size_t size = sk_X509_num(path.get());
5268
5269    ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(size));
5270    ScopedLongArrayRW certs(env, certArray.get());
5271    for (size_t i = 0; i < size; i++) {
5272        X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5273        certs[i] = reinterpret_cast<uintptr_t>(item);
5274    }
5275
5276    JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %d items", bio, size);
5277    return certArray.release();
5278}
5279
5280static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5281    JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5282    ScopedLongArrayRO certsArray(env, certs);
5283    if (certsArray.get() == NULL) {
5284        JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5285        return NULL;
5286    }
5287
5288    Unique_sk_X509 certStack(sk_X509_new_null());
5289    if (certStack.get() == NULL) {
5290        JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to make cert stack", certs);
5291        return NULL;
5292    }
5293
5294    for (size_t i = 0; i < certsArray.size(); i++) {
5295        X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5296        sk_X509_push(certStack.get(), X509_dup_nocopy(x509));
5297    }
5298
5299    int len;
5300    Unique_OPENSSL_str encoded(ASN1_seq_pack(
5301                    reinterpret_cast<STACK_OF(OPENSSL_BLOCK)*>(
5302                            reinterpret_cast<uintptr_t>(certStack.get())),
5303                    reinterpret_cast<int (*)(void*, unsigned char**)>(i2d_X509), NULL, &len));
5304    if (encoded.get() == NULL) {
5305        JNI_TRACE("ASN1_seq_pack_X509(%p) => trouble encoding", certs);
5306        return NULL;
5307    }
5308
5309    ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
5310    if (byteArray.get() == NULL) {
5311        JNI_TRACE("ASN1_seq_pack_X509(%p) => creating byte array failed", certs);
5312        return NULL;
5313    }
5314
5315    ScopedByteArrayRW bytes(env, byteArray.get());
5316    if (bytes.get() == NULL) {
5317        JNI_TRACE("ASN1_seq_pack_X509(%p) => using byte array failed", certs);
5318        return NULL;
5319    }
5320
5321    unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
5322    memcpy(p, encoded.get(), len);
5323
5324    return byteArray.release();
5325}
5326
5327static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref) {
5328    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5329    JNI_TRACE("X509_free(%p)", x509);
5330
5331    if (x509 == NULL) {
5332        jniThrowNullPointerException(env, "x509 == null");
5333        JNI_TRACE("X509_free(%p) => x509 == null", x509);
5334        return;
5335    }
5336
5337    X509_free(x509);
5338}
5339
5340static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1, jlong x509Ref2) {
5341    X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5342    X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5343    JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5344
5345    if (x509_1 == NULL) {
5346        jniThrowNullPointerException(env, "x509_1 == null");
5347        JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5348        return -1;
5349    }
5350
5351    if (x509_2 == NULL) {
5352        jniThrowNullPointerException(env, "x509_2 == null");
5353        JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5354        return -1;
5355    }
5356
5357    int ret = X509_cmp(x509_1, x509_2);
5358    JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5359    return ret;
5360}
5361
5362static jint NativeCrypto_get_X509_hashCode(JNIEnv* env, jclass, jlong x509Ref) {
5363    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5364
5365    if (x509 == NULL) {
5366        jniThrowNullPointerException(env, "x509 == null");
5367        JNI_TRACE("get_X509_hashCode(%p) => x509 == null", x509);
5368        return 0;
5369    }
5370
5371    // Force caching extensions.
5372    X509_check_ca(x509);
5373
5374    jint hashCode = 0L;
5375    for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
5376        hashCode = 31 * hashCode + x509->sha1_hash[i];
5377    }
5378    return hashCode;
5379}
5380
5381static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5382        jlong nmflagJava, jlong certflagJava) {
5383    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5384    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5385    long nmflag = static_cast<long>(nmflagJava);
5386    long certflag = static_cast<long>(certflagJava);
5387    JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5388
5389    if (bio == NULL) {
5390        jniThrowNullPointerException(env, "bio == null");
5391        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5392        return;
5393    }
5394
5395    if (x509 == NULL) {
5396        jniThrowNullPointerException(env, "x509 == null");
5397        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5398        return;
5399    }
5400
5401    if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5402        throwExceptionIfNecessary(env, "X509_print_ex");
5403        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5404    } else {
5405        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5406    }
5407}
5408
5409static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref) {
5410    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5411    JNI_TRACE("X509_get_pubkey(%p)", x509);
5412
5413    if (x509 == NULL) {
5414        jniThrowNullPointerException(env, "x509 == null");
5415        JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
5416        return 0;
5417    }
5418
5419    Unique_EVP_PKEY pkey(X509_get_pubkey(x509));
5420    if (pkey.get() == NULL) {
5421        throwExceptionIfNecessary(env, "X509_get_pubkey");
5422        return 0;
5423    }
5424
5425    JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
5426    return reinterpret_cast<uintptr_t>(pkey.release());
5427}
5428
5429static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref) {
5430    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5431    JNI_TRACE("X509_get_issuer_name(%p)", x509);
5432    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_issuer_name(x509));
5433}
5434
5435static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref) {
5436    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5437    JNI_TRACE("X509_get_subject_name(%p)", x509);
5438    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_subject_name(x509));
5439}
5440
5441static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref) {
5442    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5443    JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
5444
5445    if (x509 == NULL) {
5446        jniThrowNullPointerException(env, "x509 == null");
5447        JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
5448        return NULL;
5449    }
5450
5451    X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
5452    return ASN1_OBJECT_to_OID_string(env, pubkey->algor->algorithm);
5453}
5454
5455static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref) {
5456    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5457    JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
5458
5459    if (x509 == NULL || x509->sig_alg == NULL) {
5460        jniThrowNullPointerException(env, "x509 == NULL || x509->sig_alg == NULL");
5461        JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == NULL", x509);
5462        return NULL;
5463    }
5464
5465    return ASN1_OBJECT_to_OID_string(env, x509->sig_alg->algorithm);
5466}
5467
5468static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref) {
5469    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5470    JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
5471
5472    if (x509 == NULL) {
5473        jniThrowNullPointerException(env, "x509 == null");
5474        JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
5475        return NULL;
5476    }
5477
5478    if (x509->sig_alg->parameter == NULL) {
5479        JNI_TRACE("get_X509_sig_alg_parameter(%p) => null", x509);
5480        return NULL;
5481    }
5482
5483    return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, x509->sig_alg->parameter);
5484}
5485
5486static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref) {
5487    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5488    JNI_TRACE("get_X509_issuerUID(%p)", x509);
5489
5490    if (x509 == NULL) {
5491        jniThrowNullPointerException(env, "x509 == null");
5492        JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
5493        return NULL;
5494    }
5495
5496    if (x509->cert_info->issuerUID == NULL) {
5497        JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
5498        return NULL;
5499    }
5500
5501    return ASN1BitStringToBooleanArray(env, x509->cert_info->issuerUID);
5502}
5503static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref) {
5504    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5505    JNI_TRACE("get_X509_subjectUID(%p)", x509);
5506
5507    if (x509 == NULL) {
5508        jniThrowNullPointerException(env, "x509 == null");
5509        JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
5510        return NULL;
5511    }
5512
5513    if (x509->cert_info->subjectUID == NULL) {
5514        JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
5515        return NULL;
5516    }
5517
5518    return ASN1BitStringToBooleanArray(env, x509->cert_info->subjectUID);
5519}
5520
5521static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref) {
5522    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5523    JNI_TRACE("get_X509_ex_kusage(%p)", x509);
5524
5525    if (x509 == NULL) {
5526        jniThrowNullPointerException(env, "x509 == null");
5527        JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
5528        return NULL;
5529    }
5530
5531    Unique_ASN1_BIT_STRING bitStr(static_cast<ASN1_BIT_STRING*>(
5532            X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL)));
5533    if (bitStr.get() == NULL) {
5534        JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
5535        return NULL;
5536    }
5537
5538    return ASN1BitStringToBooleanArray(env, bitStr.get());
5539}
5540
5541static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref) {
5542    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5543    JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
5544
5545    if (x509 == NULL) {
5546        jniThrowNullPointerException(env, "x509 == null");
5547        JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
5548        return NULL;
5549    }
5550
5551    Unique_sk_ASN1_OBJECT objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
5552            X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)));
5553    if (objArray.get() == NULL) {
5554        JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
5555        return NULL;
5556    }
5557
5558    size_t size = sk_ASN1_OBJECT_num(objArray.get());
5559    ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
5560    if (exKeyUsage.get() == NULL) {
5561        return NULL;
5562    }
5563
5564    for (size_t i = 0; i < size; i++) {
5565        ScopedLocalRef<jstring> oidStr(env, ASN1_OBJECT_to_OID_string(env,
5566                sk_ASN1_OBJECT_value(objArray.get(), i)));
5567        env->SetObjectArrayElement(exKeyUsage.get(), i, oidStr.get());
5568    }
5569
5570    JNI_TRACE("get_X509_ex_xkusage(%p) => success (%d entries)", x509, size);
5571    return exKeyUsage.release();
5572}
5573
5574static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref) {
5575    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5576    JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
5577
5578    if (x509 == NULL) {
5579        jniThrowNullPointerException(env, "x509 == null");
5580        JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
5581        return 0;
5582    }
5583
5584    /* Just need to do this to cache the ex_* values. */
5585    X509_check_ca(x509);
5586
5587    JNI_TRACE("get_X509_ex_pathlen(%p) => %ld", x509, x509->ex_pathlen);
5588    return x509->ex_pathlen;
5589}
5590
5591static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
5592        jstring oidString) {
5593    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5594    JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
5595    return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
5596}
5597
5598static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5599        jstring oidString) {
5600    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5601    JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
5602    return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
5603            oidString);
5604}
5605
5606static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
5607        jstring oidString) {
5608    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5609    JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
5610    return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5611            env, revoked, oidString);
5612}
5613
5614template<typename T, int (*get_ext_by_critical_func)(T*, int, int), X509_EXTENSION* (*get_ext_func)(T*, int)>
5615static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
5616    T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
5617    JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
5618
5619    if (x509 == NULL) {
5620        jniThrowNullPointerException(env, "x509 == null");
5621        JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
5622        return NULL;
5623    }
5624
5625    int lastPos = -1;
5626    int count = 0;
5627    while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
5628        count++;
5629    }
5630
5631    JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
5632
5633    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
5634    if (joa.get() == NULL) {
5635        JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
5636        return NULL;
5637    }
5638
5639    lastPos = -1;
5640    count = 0;
5641    while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
5642        X509_EXTENSION* ext = get_ext_func(x509, lastPos);
5643
5644        ScopedLocalRef<jstring> extOid(env, ASN1_OBJECT_to_OID_string(env, ext->object));
5645        if (extOid.get() == NULL) {
5646            JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
5647            return NULL;
5648        }
5649
5650        env->SetObjectArrayElement(joa.get(), count++, extOid.get());
5651    }
5652
5653    JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
5654    return joa.release();
5655}
5656
5657static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
5658        jint critical) {
5659    JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", x509Ref, critical);
5660    return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
5661            critical);
5662}
5663
5664static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
5665        jint critical) {
5666    JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509CrlRef, critical);
5667    return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(env,
5668            x509CrlRef, critical);
5669}
5670
5671static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass, jlong x509RevokedRef,
5672        jint critical) {
5673    JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509RevokedRef, critical);
5674    return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
5675            X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
5676}
5677
5678#ifdef WITH_JNI_TRACE
5679/**
5680 * Based on example logging call back from SSL_CTX_set_info_callback man page
5681 */
5682static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
5683{
5684    int w = where & ~SSL_ST_MASK;
5685    const char* str;
5686    if (w & SSL_ST_CONNECT) {
5687        str = "SSL_connect";
5688    } else if (w & SSL_ST_ACCEPT) {
5689        str = "SSL_accept";
5690    } else {
5691        str = "undefined";
5692    }
5693
5694    if (where & SSL_CB_LOOP) {
5695        JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
5696    } else if (where & SSL_CB_ALERT) {
5697        str = (where & SSL_CB_READ) ? "read" : "write";
5698        JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
5699                  s,
5700                  str,
5701                  SSL_alert_type_string(ret),
5702                  SSL_alert_desc_string(ret),
5703                  SSL_alert_type_string_long(ret),
5704                  SSL_alert_desc_string_long(ret));
5705    } else if (where & SSL_CB_EXIT) {
5706        if (ret == 0) {
5707            JNI_TRACE("ssl=%p %s:failed exit in %s %s",
5708                      s, str, SSL_state_string(s), SSL_state_string_long(s));
5709        } else if (ret < 0) {
5710            JNI_TRACE("ssl=%p %s:error exit in %s %s",
5711                      s, str, SSL_state_string(s), SSL_state_string_long(s));
5712        } else if (ret == 1) {
5713            JNI_TRACE("ssl=%p %s:ok exit in %s %s",
5714                      s, str, SSL_state_string(s), SSL_state_string_long(s));
5715        } else {
5716            JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
5717                      s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
5718        }
5719    } else if (where & SSL_CB_HANDSHAKE_START) {
5720        JNI_TRACE("ssl=%p handshake start in %s %s",
5721                  s, SSL_state_string(s), SSL_state_string_long(s));
5722    } else if (where & SSL_CB_HANDSHAKE_DONE) {
5723        JNI_TRACE("ssl=%p handshake done in %s %s",
5724                  s, SSL_state_string(s), SSL_state_string_long(s));
5725    } else {
5726        JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
5727                  s, str, where, SSL_state_string(s), SSL_state_string_long(s));
5728    }
5729}
5730#endif
5731
5732/**
5733 * Returns an array containing all the X509 certificate references
5734 */
5735static jlongArray getCertificateRefs(JNIEnv* env, const STACK_OF(X509)* chain)
5736{
5737    if (chain == NULL) {
5738        // Chain can be NULL if the associated cipher doesn't do certs.
5739        return NULL;
5740    }
5741    ssize_t count = sk_X509_num(chain);
5742    if (count <= 0) {
5743        return NULL;
5744    }
5745    ScopedLocalRef<jlongArray> refArray(env, env->NewLongArray(count));
5746    ScopedLongArrayRW refs(env, refArray.get());
5747    if (refs.get() == NULL) {
5748        return NULL;
5749    }
5750    for (ssize_t i = 0; i < count; i++) {
5751        refs[i] = reinterpret_cast<uintptr_t>(X509_dup_nocopy(sk_X509_value(chain, i)));
5752    }
5753    return refArray.release();
5754}
5755
5756/**
5757 * Returns an array containing all the X500 principal's bytes.
5758 */
5759static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
5760{
5761    if (names == NULL) {
5762        return NULL;
5763    }
5764
5765    int count = sk_X509_NAME_num(names);
5766    if (count <= 0) {
5767        return NULL;
5768    }
5769
5770    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
5771    if (joa.get() == NULL) {
5772        return NULL;
5773    }
5774
5775    for (int i = 0; i < count; i++) {
5776        X509_NAME* principal = sk_X509_NAME_value(names, i);
5777
5778        ScopedLocalRef<jbyteArray> byteArray(env, ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env,
5779                principal));
5780        if (byteArray.get() == NULL) {
5781            return NULL;
5782        }
5783        env->SetObjectArrayElement(joa.get(), i, byteArray.get());
5784    }
5785
5786    return joa.release();
5787}
5788
5789/**
5790 * Our additional application data needed for getting synchronization right.
5791 * This maybe warrants a bit of lengthy prose:
5792 *
5793 * (1) We use a flag to reflect whether we consider the SSL connection alive.
5794 * Any read or write attempt loops will be cancelled once this flag becomes 0.
5795 *
5796 * (2) We use an int to count the number of threads that are blocked by the
5797 * underlying socket. This may be at most two (one reader and one writer), since
5798 * the Java layer ensures that no more threads will enter the native code at the
5799 * same time.
5800 *
5801 * (3) The pipe is used primarily as a means of cancelling a blocking select()
5802 * when we want to close the connection (aka "emergency button"). It is also
5803 * necessary for dealing with a possible race condition situation: There might
5804 * be cases where both threads see an SSL_ERROR_WANT_READ or
5805 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
5806 * If one leaves the select() successfully before the other enters it, the
5807 * "success" event is already consumed and the second thread will be blocked,
5808 * possibly forever (depending on network conditions).
5809 *
5810 * The idea for solving the problem looks like this: Whenever a thread is
5811 * successful in moving around data on the network, and it knows there is
5812 * another thread stuck in a select(), it will write a byte to the pipe, waking
5813 * up the other thread. A thread that returned from select(), on the other hand,
5814 * knows whether it's been woken up by the pipe. If so, it will consume the
5815 * byte, and the original state of affairs has been restored.
5816 *
5817 * The pipe may seem like a bit of overhead, but it fits in nicely with the
5818 * other file descriptors of the select(), so there's only one condition to wait
5819 * for.
5820 *
5821 * (4) Finally, a mutex is needed to make sure that at most one thread is in
5822 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
5823 * requirement. We use the same mutex to guard the field for counting the
5824 * waiting threads.
5825 *
5826 * Note: The current implementation assumes that we don't have to deal with
5827 * problems induced by multiple cores or processors and their respective
5828 * memory caches. One possible problem is that of inconsistent views on the
5829 * "aliveAndKicking" field. This could be worked around by also enclosing all
5830 * accesses to that field inside a lock/unlock sequence of our mutex, but
5831 * currently this seems a bit like overkill. Marking volatile at the very least.
5832 *
5833 * During handshaking, additional fields are used to up-call into
5834 * Java to perform certificate verification and handshake
5835 * completion. These are also used in any renegotiation.
5836 *
5837 * (5) the JNIEnv so we can invoke the Java callback
5838 *
5839 * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
5840 *
5841 * (7) a java.io.FileDescriptor wrapper to check for socket close
5842 *
5843 * We store the NPN protocols list so we can either send it (from the server) or
5844 * select a protocol (on the client). We eagerly acquire a pointer to the array
5845 * data so the callback doesn't need to acquire resources that it cannot
5846 * release.
5847 *
5848 * Because renegotiation can be requested by the peer at any time,
5849 * care should be taken to maintain an appropriate JNIEnv on any
5850 * downcall to openssl since it could result in an upcall to Java. The
5851 * current code does try to cover these cases by conditionally setting
5852 * the JNIEnv on calls that can read and write to the SSL such as
5853 * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
5854 *
5855 * Finally, we have two emphemeral keys setup by OpenSSL callbacks:
5856 *
5857 * (8) a set of ephemeral RSA keys that is lazily generated if a peer
5858 * wants to use an exportable RSA cipher suite.
5859 *
5860 * (9) a set of ephemeral EC keys that is lazily generated if a peer
5861 * wants to use an TLS_ECDHE_* cipher suite.
5862 *
5863 */
5864class AppData {
5865  public:
5866    volatile int aliveAndKicking;
5867    int waitingThreads;
5868    int fdsEmergency[2];
5869    MUTEX_TYPE mutex;
5870    JNIEnv* env;
5871    jobject sslHandshakeCallbacks;
5872    jbyteArray npnProtocolsArray;
5873    jbyte* npnProtocolsData;
5874    size_t npnProtocolsLength;
5875    jbyteArray alpnProtocolsArray;
5876    jbyte* alpnProtocolsData;
5877    size_t alpnProtocolsLength;
5878    Unique_RSA ephemeralRsa;
5879    Unique_EC_KEY ephemeralEc;
5880
5881    /**
5882     * Creates the application data context for the SSL*.
5883     */
5884  public:
5885    static AppData* create() {
5886        UniquePtr<AppData> appData(new AppData());
5887        if (pipe(appData.get()->fdsEmergency) == -1) {
5888            ALOGE("AppData::create pipe(2) failed: %s", strerror(errno));
5889            return NULL;
5890        }
5891        if (!setBlocking(appData.get()->fdsEmergency[0], false)) {
5892            ALOGE("AppData::create fcntl(2) failed: %s", strerror(errno));
5893            return NULL;
5894        }
5895        if (MUTEX_SETUP(appData.get()->mutex) == -1) {
5896            ALOGE("pthread_mutex_init(3) failed: %s", strerror(errno));
5897            return NULL;
5898        }
5899        return appData.release();
5900    }
5901
5902    ~AppData() {
5903        aliveAndKicking = 0;
5904        if (fdsEmergency[0] != -1) {
5905            close(fdsEmergency[0]);
5906        }
5907        if (fdsEmergency[1] != -1) {
5908            close(fdsEmergency[1]);
5909        }
5910        clearCallbackState();
5911        MUTEX_CLEANUP(mutex);
5912    }
5913
5914  private:
5915    AppData() :
5916            aliveAndKicking(1),
5917            waitingThreads(0),
5918            env(NULL),
5919            sslHandshakeCallbacks(NULL),
5920            npnProtocolsArray(NULL),
5921            npnProtocolsData(NULL),
5922            npnProtocolsLength(-1),
5923            alpnProtocolsArray(NULL),
5924            alpnProtocolsData(NULL),
5925            alpnProtocolsLength(-1),
5926            ephemeralRsa(NULL),
5927            ephemeralEc(NULL) {
5928        fdsEmergency[0] = -1;
5929        fdsEmergency[1] = -1;
5930    }
5931
5932  public:
5933    /**
5934     * Used to set the SSL-to-Java callback state before each SSL_*
5935     * call that may result in a callback. It should be cleared after
5936     * the operation returns with clearCallbackState.
5937     *
5938     * @param env The JNIEnv
5939     * @param shc The SSLHandshakeCallbacks
5940     * @param fd The FileDescriptor
5941     * @param npnProtocols NPN protocols so that they may be advertised (by the
5942     *                     server) or selected (by the client). Has no effect
5943     *                     unless NPN is enabled.
5944     * @param alpnProtocols ALPN protocols so that they may be advertised (by the
5945     *                     server) or selected (by the client). Passing non-NULL
5946     *                     enables ALPN.
5947     */
5948    bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
5949            jbyteArray alpnProtocols) {
5950        UniquePtr<NetFd> netFd;
5951        if (fd != NULL) {
5952            netFd.reset(new NetFd(e, fd));
5953            if (netFd->isClosed()) {
5954                JNI_TRACE("appData=%p setCallbackState => netFd->isClosed() == true", this);
5955                return false;
5956            }
5957        }
5958        env = e;
5959        sslHandshakeCallbacks = shc;
5960        if (npnProtocols != NULL) {
5961            npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
5962            if (npnProtocolsData == NULL) {
5963                clearCallbackState();
5964                JNI_TRACE("appData=%p setCallbackState => npnProtocolsData == NULL", this);
5965                return false;
5966            }
5967            npnProtocolsArray = npnProtocols;
5968            npnProtocolsLength = e->GetArrayLength(npnProtocols);
5969        }
5970        if (alpnProtocols != NULL) {
5971            alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
5972            if (alpnProtocolsData == NULL) {
5973                clearCallbackState();
5974                JNI_TRACE("appData=%p setCallbackState => alpnProtocolsData == NULL", this);
5975                return false;
5976            }
5977            alpnProtocolsArray = alpnProtocols;
5978            alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
5979        }
5980        return true;
5981    }
5982
5983    void clearCallbackState() {
5984        sslHandshakeCallbacks = NULL;
5985        if (npnProtocolsArray != NULL) {
5986            env->ReleaseByteArrayElements(npnProtocolsArray, npnProtocolsData, JNI_ABORT);
5987            npnProtocolsArray = NULL;
5988            npnProtocolsData = NULL;
5989            npnProtocolsLength = -1;
5990        }
5991        if (alpnProtocolsArray != NULL) {
5992            env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
5993            alpnProtocolsArray = NULL;
5994            alpnProtocolsData = NULL;
5995            alpnProtocolsLength = -1;
5996        }
5997        env = NULL;
5998    }
5999
6000};
6001
6002/**
6003 * Dark magic helper function that checks, for a given SSL session, whether it
6004 * can SSL_read() or SSL_write() without blocking. Takes into account any
6005 * concurrent attempts to close the SSLSocket from the Java side. This is
6006 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6007 * while thread #2 is sitting in a blocking read or write. The type argument
6008 * specifies whether we are waiting for readability or writability. It expects
6009 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6010 * only need to wait in case one of these problems occurs.
6011 *
6012 * @param env
6013 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6014 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6015 * @param appData The application data structure with mutex info etc.
6016 * @param timeout_millis The timeout value for select call, with the special value
6017 *                0 meaning no timeout at all (wait indefinitely). Note: This is
6018 *                the Java semantics of the timeout value, not the usual
6019 *                select() semantics.
6020 * @return The result of the inner select() call,
6021 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6022 * additional errors
6023 */
6024static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout_millis) {
6025    // This loop is an expanded version of the NET_FAILURE_RETRY
6026    // macro. It cannot simply be used in this case because select
6027    // cannot be restarted without recreating the fd_sets and timeout
6028    // structure.
6029    int result;
6030    fd_set rfds;
6031    fd_set wfds;
6032    do {
6033        NetFd fd(env, fdObject);
6034        if (fd.isClosed()) {
6035            result = THROWN_EXCEPTION;
6036            break;
6037        }
6038        int intFd = fd.get();
6039        JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6040                  (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6041
6042        FD_ZERO(&rfds);
6043        FD_ZERO(&wfds);
6044
6045        if (type == SSL_ERROR_WANT_READ) {
6046            FD_SET(intFd, &rfds);
6047        } else {
6048            FD_SET(intFd, &wfds);
6049        }
6050
6051        FD_SET(appData->fdsEmergency[0], &rfds);
6052
6053        int maxFd = (intFd > appData->fdsEmergency[0]) ? intFd : appData->fdsEmergency[0];
6054
6055        // Build a struct for the timeout data if we actually want a timeout.
6056        timeval tv;
6057        timeval* ptv;
6058        if (timeout_millis > 0) {
6059            tv.tv_sec = timeout_millis / 1000;
6060            tv.tv_usec = (timeout_millis % 1000) * 1000;
6061            ptv = &tv;
6062        } else {
6063            ptv = NULL;
6064        }
6065
6066#ifndef CONSCRYPT_UNBUNDLED
6067        AsynchronousCloseMonitor monitor(intFd);
6068#else
6069        CompatibilityCloseMonitor monitor(intFd);
6070#endif
6071        result = select(maxFd + 1, &rfds, &wfds, NULL, ptv);
6072        JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6073                  (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
6074                  fd.get(), appData, timeout_millis, result);
6075        if (result == -1) {
6076            if (fd.isClosed()) {
6077                result = THROWN_EXCEPTION;
6078                break;
6079            }
6080            if (errno != EINTR) {
6081                break;
6082            }
6083        }
6084    } while (result == -1);
6085
6086    if (MUTEX_LOCK(appData->mutex) == -1) {
6087        return -1;
6088    }
6089
6090    if (result > 0) {
6091        // We have been woken up by a token in the emergency pipe. We
6092        // can't be sure the token is still in the pipe at this point
6093        // because it could have already been read by the thread that
6094        // originally wrote it if it entered sslSelect and acquired
6095        // the mutex before we did. Thus we cannot safely read from
6096        // the pipe in a blocking way (so we make the pipe
6097        // non-blocking at creation).
6098        if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
6099            char token;
6100            do {
6101                read(appData->fdsEmergency[0], &token, 1);
6102            } while (errno == EINTR);
6103        }
6104    }
6105
6106    // Tell the world that there is now one thread less waiting for the
6107    // underlying network.
6108    appData->waitingThreads--;
6109
6110    MUTEX_UNLOCK(appData->mutex);
6111
6112    return result;
6113}
6114
6115/**
6116 * Helper function that wakes up a thread blocked in select(), in case there is
6117 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6118 * before closing the connection.
6119 *
6120 * @param data The application data structure with mutex info etc.
6121 */
6122static void sslNotify(AppData* appData) {
6123    // Write a byte to the emergency pipe, so a concurrent select() can return.
6124    // Note we have to restore the errno of the original system call, since the
6125    // caller relies on it for generating error messages.
6126    int errnoBackup = errno;
6127    char token = '*';
6128    do {
6129        errno = 0;
6130        write(appData->fdsEmergency[1], &token, 1);
6131    } while (errno == EINTR);
6132    errno = errnoBackup;
6133}
6134
6135static AppData* toAppData(const SSL* ssl) {
6136    return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6137}
6138
6139/**
6140 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
6141 */
6142static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
6143{
6144    /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
6145    SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
6146            SSL_get_ex_data_X509_STORE_CTX_idx()));
6147    JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
6148
6149    AppData* appData = toAppData(ssl);
6150    JNIEnv* env = appData->env;
6151    if (env == NULL) {
6152        ALOGE("AppData->env missing in cert_verify_callback");
6153        JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6154        return 0;
6155    }
6156    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6157
6158    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6159    jmethodID methodID
6160        = env->GetMethodID(cls, "verifyCertificateChain", "(J[JLjava/lang/String;)V");
6161
6162    jlongArray refArray = getCertificateRefs(env, x509_store_ctx->untrusted);
6163
6164    const char* authMethod = SSL_authentication_method(ssl);
6165    JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
6166              ssl, authMethod);
6167    jstring authMethodString = env->NewStringUTF(authMethod);
6168    env->CallVoidMethod(sslHandshakeCallbacks, methodID,
6169            static_cast<jlong>(reinterpret_cast<uintptr_t>(SSL_get1_session(ssl))), refArray,
6170            authMethodString);
6171
6172    int result = (env->ExceptionCheck()) ? 0 : 1;
6173    JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6174    return result;
6175}
6176
6177/**
6178 * Call back to watch for handshake to be completed. This is necessary
6179 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
6180 * returns before the handshake is completed in this case.
6181 */
6182static void info_callback(const SSL* ssl, int where, int ret) {
6183    JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
6184#ifdef WITH_JNI_TRACE
6185    info_callback_LOG(ssl, where, ret);
6186#endif
6187    if (!(where & SSL_CB_HANDSHAKE_DONE) && !(where & SSL_CB_HANDSHAKE_START)) {
6188        JNI_TRACE("ssl=%p info_callback ignored", ssl);
6189        return;
6190    }
6191
6192    AppData* appData = toAppData(ssl);
6193    JNIEnv* env = appData->env;
6194    if (env == NULL) {
6195        ALOGE("AppData->env missing in info_callback");
6196        JNI_TRACE("ssl=%p info_callback env error", ssl);
6197        return;
6198    }
6199    if (env->ExceptionCheck()) {
6200        JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6201        return;
6202    }
6203
6204    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6205
6206    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6207    jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(JII)V");
6208
6209    JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6210    env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(ssl), where, ret);
6211
6212    if (env->ExceptionCheck()) {
6213        JNI_TRACE("ssl=%p info_callback exception", ssl);
6214    }
6215    JNI_TRACE("ssl=%p info_callback completed", ssl);
6216}
6217
6218/**
6219 * Call back to ask for a client certificate. There are three possible exit codes:
6220 *
6221 * 1 is success. x509Out and pkeyOut should point to the correct private key and certificate.
6222 * 0 is unable to find key. x509Out and pkeyOut should be NULL.
6223 * -1 is error and it doesn't matter what x509Out and pkeyOut are.
6224 */
6225static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
6226    JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
6227
6228    /* Clear output of key and certificate in case of early exit due to error. */
6229    *x509Out = NULL;
6230    *pkeyOut = NULL;
6231
6232    AppData* appData = toAppData(ssl);
6233    JNIEnv* env = appData->env;
6234    if (env == NULL) {
6235        ALOGE("AppData->env missing in client_cert_cb");
6236        JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
6237        return 0;
6238    }
6239    if (env->ExceptionCheck()) {
6240        JNI_TRACE("ssl=%p client_cert_cb already pending exception => 0", ssl);
6241        return -1;
6242    }
6243    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6244
6245    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6246    jmethodID methodID
6247        = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
6248
6249    // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
6250    char ssl2_ctype = SSL3_CT_RSA_SIGN;
6251    const char* ctype = NULL;
6252    int ctype_num = 0;
6253    jobjectArray issuers = NULL;
6254    switch (ssl->version) {
6255        case SSL2_VERSION:
6256            ctype = &ssl2_ctype;
6257            ctype_num = 1;
6258            break;
6259        case SSL3_VERSION:
6260        case TLS1_VERSION:
6261        case TLS1_1_VERSION:
6262        case TLS1_2_VERSION:
6263        case DTLS1_VERSION:
6264            ctype = ssl->s3->tmp.ctype;
6265            ctype_num = ssl->s3->tmp.ctype_num;
6266            issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
6267            break;
6268    }
6269#ifdef WITH_JNI_TRACE
6270    for (int i = 0; i < ctype_num; i++) {
6271        JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
6272    }
6273#endif
6274
6275    jbyteArray keyTypes = env->NewByteArray(ctype_num);
6276    if (keyTypes == NULL) {
6277        JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
6278        return 0;
6279    }
6280    env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
6281
6282    JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
6283              "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
6284    env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
6285
6286    if (env->ExceptionCheck()) {
6287        JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
6288        return -1;
6289    }
6290
6291    // Check for values set from Java
6292    X509*     certificate = SSL_get_certificate(ssl);
6293    EVP_PKEY* privatekey  = SSL_get_privatekey(ssl);
6294    int result = 0;
6295    if (certificate != NULL && privatekey != NULL) {
6296        *x509Out = certificate;
6297        *pkeyOut = privatekey;
6298        result = 1;
6299    } else {
6300        // Some error conditions return NULL, so make sure it doesn't linger.
6301        freeOpenSslErrorState();
6302    }
6303    JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
6304    return result;
6305}
6306
6307static RSA* rsaGenerateKey(int keylength) {
6308    Unique_BIGNUM bn(BN_new());
6309    if (bn.get() == NULL) {
6310        return NULL;
6311    }
6312    int setWordResult = BN_set_word(bn.get(), RSA_F4);
6313    if (setWordResult != 1) {
6314        return NULL;
6315    }
6316    Unique_RSA rsa(RSA_new());
6317    if (rsa.get() == NULL) {
6318        return NULL;
6319    }
6320    int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
6321    if (generateResult != 1) {
6322        return NULL;
6323    }
6324    return rsa.release();
6325}
6326
6327/**
6328 * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
6329 */
6330static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
6331                             int is_export __attribute__ ((unused)),
6332                             int keylength) {
6333    JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
6334
6335    AppData* appData = toAppData(ssl);
6336    if (appData->ephemeralRsa.get() == NULL) {
6337        JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
6338        appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
6339    }
6340    JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
6341    return appData->ephemeralRsa.get();
6342}
6343
6344static DH* dhGenerateParameters(int keylength) {
6345
6346    /*
6347     * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
6348     * different options for generating DH keys. One is generating the
6349     * keys using a single set of DH parameters. However, generating
6350     * DH parameters is slow enough (minutes) that they suggest doing
6351     * it once at install time. The other is to generate DH keys from
6352     * DSA parameters. Generating DSA parameters is faster than DH
6353     * parameters, but to prevent small subgroup attacks, they needed
6354     * to be regenerated for each set of DH keys. Setting the
6355     * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
6356     * for new DH parameters every type it needs to generate DH keys.
6357     */
6358#if 0
6359    // Slow path that takes minutes but could be cached
6360    Unique_DH dh(DH_new());
6361    if (!DH_generate_parameters_ex(dh.get(), keylength, 2, NULL)) {
6362        return NULL;
6363    }
6364    return dh.release();
6365#else
6366    // Faster path but must have SSL_OP_SINGLE_DH_USE set
6367    Unique_DSA dsa(DSA_new());
6368    if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
6369        return NULL;
6370    }
6371    DH* dh = DSA_dup_DH(dsa.get());
6372    return dh;
6373#endif
6374}
6375
6376/**
6377 * Call back to ask for Diffie-Hellman parameters
6378 */
6379static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
6380                           int is_export __attribute__ ((unused)),
6381                           int keylength) {
6382    JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
6383    DH* tmp_dh = dhGenerateParameters(keylength);
6384    JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
6385    return tmp_dh;
6386}
6387
6388static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
6389    // TODO selected curve based on keylength
6390    Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
6391    if (ec.get() == NULL) {
6392        return NULL;
6393    }
6394    return ec.release();
6395}
6396
6397/**
6398 * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
6399 */
6400static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
6401                                 int is_export __attribute__ ((unused)),
6402                                 int keylength) {
6403    JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
6404    AppData* appData = toAppData(ssl);
6405    if (appData->ephemeralEc.get() == NULL) {
6406        JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
6407        appData->ephemeralEc.reset(ecGenerateKey(keylength));
6408    }
6409    JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
6410    return appData->ephemeralEc.get();
6411}
6412
6413/*
6414 * public static native int SSL_CTX_new();
6415 */
6416static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
6417    Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
6418    if (sslCtx.get() == NULL) {
6419        throwExceptionIfNecessary(env, "SSL_CTX_new");
6420        return 0;
6421    }
6422    SSL_CTX_set_options(sslCtx.get(),
6423                        SSL_OP_ALL
6424                        // Note: We explicitly do not allow SSLv2 to be used.
6425                        | SSL_OP_NO_SSLv2
6426                        // We also disable session tickets for better compatibility b/2682876
6427                        | SSL_OP_NO_TICKET
6428                        // We also disable compression for better compatibility b/2710492 b/2710497
6429                        | SSL_OP_NO_COMPRESSION
6430                        // Because dhGenerateParameters uses DSA_generate_parameters_ex
6431                        | SSL_OP_SINGLE_DH_USE
6432                        // Because ecGenerateParameters uses a fixed named curve
6433                        | SSL_OP_SINGLE_ECDH_USE);
6434
6435    int mode = SSL_CTX_get_mode(sslCtx.get());
6436    /*
6437     * Turn on "partial write" mode. This means that SSL_write() will
6438     * behave like Posix write() and possibly return after only
6439     * writing a partial buffer. Note: The alternative, perhaps
6440     * surprisingly, is not that SSL_write() always does full writes
6441     * but that it will force you to retry write calls having
6442     * preserved the full state of the original call. (This is icky
6443     * and undesirable.)
6444     */
6445    mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
6446
6447    // Reuse empty buffers within the SSL_CTX to save memory
6448    mode |= SSL_MODE_RELEASE_BUFFERS;
6449
6450    SSL_CTX_set_mode(sslCtx.get(), mode);
6451
6452    SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
6453    SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
6454    SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
6455    SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
6456    SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
6457    SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
6458
6459    JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
6460    return (jlong) sslCtx.release();
6461}
6462
6463/**
6464 * public static native void SSL_CTX_free(long ssl_ctx)
6465 */
6466static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
6467        jclass, jlong ssl_ctx_address)
6468{
6469    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6470    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
6471    if (ssl_ctx == NULL) {
6472        return;
6473    }
6474    SSL_CTX_free(ssl_ctx);
6475}
6476
6477static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass,
6478                                                        jlong ssl_ctx_address, jbyteArray sid_ctx)
6479{
6480    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6481    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx, sid_ctx);
6482    if (ssl_ctx == NULL) {
6483        return;
6484    }
6485
6486    ScopedByteArrayRO buf(env, sid_ctx);
6487    if (buf.get() == NULL) {
6488        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception", ssl_ctx);
6489        return;
6490    }
6491
6492    unsigned int length = buf.size();
6493    if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
6494        jniThrowException(env, "java/lang/IllegalArgumentException",
6495                          "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
6496        JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
6497        return;
6498    }
6499    const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
6500    int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
6501    if (result == 0) {
6502        throwExceptionIfNecessary(env, "NativeCrypto_SSL_CTX_set_session_id_context");
6503        return;
6504    }
6505    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
6506}
6507
6508/**
6509 * public static native int SSL_new(long ssl_ctx) throws SSLException;
6510 */
6511static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address)
6512{
6513    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6514    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
6515    if (ssl_ctx == NULL) {
6516        return 0;
6517    }
6518    Unique_SSL ssl(SSL_new(ssl_ctx));
6519    if (ssl.get() == NULL) {
6520        throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
6521                "Unable to create SSL structure");
6522        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
6523        return 0;
6524    }
6525
6526    /*
6527     * Create our special application data.
6528     */
6529    AppData* appData = AppData::create();
6530    if (appData == NULL) {
6531        throwSSLExceptionStr(env, "Unable to create application data");
6532        freeOpenSslErrorState();
6533        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
6534        return 0;
6535    }
6536    SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
6537
6538    /*
6539     * Java code in class OpenSSLSocketImpl does the verification. Since
6540     * the callbacks do all the verification of the chain, this flag
6541     * simply controls whether to send protocol-level alerts or not.
6542     * SSL_VERIFY_NONE means don't send alerts and anything else means send
6543     * alerts.
6544     */
6545    SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
6546
6547    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
6548    return (jlong) ssl.release();
6549}
6550
6551
6552static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
6553{
6554    SSL* ssl = to_SSL(env, ssl_address, true);
6555    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_enable_tls_channel_id", ssl);
6556    if (ssl == NULL) {
6557        return;
6558    }
6559
6560    long ret = SSL_enable_tls_channel_id(ssl);
6561    if (ret != 1L) {
6562        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6563        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error enabling Channel ID");
6564        SSL_clear(ssl);
6565        JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
6566        return;
6567    }
6568}
6569
6570static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
6571{
6572    SSL* ssl = to_SSL(env, ssl_address, true);
6573    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id", ssl);
6574    if (ssl == NULL) {
6575        return NULL;
6576    }
6577
6578    // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
6579    // as a constant anywhere.
6580    jbyteArray javaBytes = env->NewByteArray(64);
6581    ScopedByteArrayRW bytes(env, javaBytes);
6582    if (bytes.get() == NULL) {
6583        JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => NULL", ssl);
6584        return NULL;
6585    }
6586
6587    unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
6588    // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
6589    // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
6590    // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
6591    long ret = SSL_get_tls_channel_id(ssl, tmp, 64);
6592    if (ret == 0) {
6593        // Channel ID either not set or did not verify
6594        JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
6595        return NULL;
6596    } else if (ret != 64) {
6597        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6598        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error getting Channel ID");
6599        SSL_clear(ssl);
6600        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %ld", ssl, ret);
6601        return NULL;
6602    }
6603
6604    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
6605    return javaBytes;
6606}
6607
6608static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
6609        jlong ssl_address, jlong pkeyRef)
6610{
6611    SSL* ssl = to_SSL(env, ssl_address, true);
6612    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
6613    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
6614    if (ssl == NULL) {
6615        return;
6616    }
6617
6618    if (pkey == NULL) {
6619        jniThrowNullPointerException(env, "pkey == null");
6620        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
6621        return;
6622    }
6623
6624    // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
6625    // Unfortunately, the default value is 1 and it's only changed to 0 just
6626    // before the handshake starts (see NativeCrypto_SSL_do_handshake).
6627    ssl->server = 0;
6628    long ret = SSL_set1_tls_channel_id(ssl, pkey);
6629
6630    if (ret != 1L) {
6631        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6632        throwSSLExceptionWithSslErrors(
6633                env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
6634        SSL_clear(ssl);
6635        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
6636        return;
6637    }
6638    // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
6639    // we have an external reference from the caller such as an OpenSSLKey,
6640    // so we manually increment the reference count here.
6641    CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
6642
6643    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
6644}
6645
6646static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
6647    SSL* ssl = to_SSL(env, ssl_address, true);
6648    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
6649    JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
6650    if (ssl == NULL) {
6651        return;
6652    }
6653
6654    if (pkey == NULL) {
6655        jniThrowNullPointerException(env, "pkey == null");
6656        JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
6657        return;
6658    }
6659
6660    int ret = SSL_use_PrivateKey(ssl, pkey);
6661    if (ret != 1) {
6662        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6663        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
6664        SSL_clear(ssl);
6665        JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
6666        return;
6667    }
6668    // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
6669    // but we have an external reference from the caller such as an
6670    // OpenSSLKey, so we manually increment the reference count here.
6671    CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
6672
6673    JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
6674}
6675
6676static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
6677                                             jlong ssl_address, jlongArray certificatesJava)
6678{
6679    SSL* ssl = to_SSL(env, ssl_address, true);
6680    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificatesJava);
6681    if (ssl == NULL) {
6682        return;
6683    }
6684
6685    if (certificatesJava == NULL) {
6686        jniThrowNullPointerException(env, "certificates == null");
6687        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
6688        return;
6689    }
6690
6691    size_t length = env->GetArrayLength(certificatesJava);
6692    if (length == 0) {
6693        jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
6694        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
6695        return;
6696    }
6697
6698    ScopedLongArrayRO certificates(env, certificatesJava);
6699    if (certificates.get() == NULL) {
6700        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
6701        return;
6702    }
6703
6704    Unique_X509 serverCert(
6705            X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[0]))));
6706    if (serverCert.get() == NULL) {
6707        // Note this shouldn't happen since we checked the number of certificates above.
6708        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
6709        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
6710        return;
6711    }
6712
6713    Unique_sk_X509 chain(sk_X509_new_null());
6714    if (chain.get() == NULL) {
6715        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
6716        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
6717        return;
6718    }
6719
6720    for (size_t i = 1; i < length; i++) {
6721        Unique_X509 cert(
6722                X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[i]))));
6723        if (cert.get() == NULL || !sk_X509_push(chain.get(), cert.get())) {
6724            ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6725            throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
6726            SSL_clear(ssl);
6727            JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
6728            return;
6729        }
6730        OWNERSHIP_TRANSFERRED(cert);
6731    }
6732
6733    int ret = SSL_use_certificate(ssl, serverCert.get());
6734    if (ret != 1) {
6735        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6736        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
6737        SSL_clear(ssl);
6738        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
6739        return;
6740    }
6741    OWNERSHIP_TRANSFERRED(serverCert);
6742
6743    int chainResult = SSL_use_certificate_chain(ssl, chain.get());
6744    if (chainResult == 0) {
6745        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
6746        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
6747                  ssl);
6748        return;
6749    }
6750    OWNERSHIP_TRANSFERRED(chain);
6751
6752    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
6753}
6754
6755static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jlong ssl_address)
6756{
6757    SSL* ssl = to_SSL(env, ssl_address, true);
6758    JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
6759    if (ssl == NULL) {
6760        return;
6761    }
6762    int ret = SSL_check_private_key(ssl);
6763    if (ret != 1) {
6764        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
6765        SSL_clear(ssl);
6766        JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
6767        return;
6768    }
6769    JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
6770}
6771
6772static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
6773                                                jlong ssl_address, jobjectArray principals)
6774{
6775    SSL* ssl = to_SSL(env, ssl_address, true);
6776    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
6777    if (ssl == NULL) {
6778        return;
6779    }
6780
6781    if (principals == NULL) {
6782        jniThrowNullPointerException(env, "principals == null");
6783        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
6784        return;
6785    }
6786
6787    int length = env->GetArrayLength(principals);
6788    if (length == 0) {
6789        jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
6790        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
6791        return;
6792    }
6793
6794    Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
6795    if (principalsStack.get() == NULL) {
6796        jniThrowOutOfMemory(env, "Unable to allocate principal stack");
6797        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
6798        return;
6799    }
6800    for (int i = 0; i < length; i++) {
6801        ScopedLocalRef<jbyteArray> principal(env,
6802                reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
6803        if (principal.get() == NULL) {
6804            jniThrowNullPointerException(env, "principals element == null");
6805            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
6806            return;
6807        }
6808
6809        ScopedByteArrayRO buf(env, principal.get());
6810        if (buf.get() == NULL) {
6811            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
6812            return;
6813        }
6814        const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
6815        Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
6816
6817        if (principalX509Name.get() == NULL) {
6818            ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
6819            throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
6820            SSL_clear(ssl);
6821            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
6822                      ssl);
6823            return;
6824        }
6825
6826        if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
6827            jniThrowOutOfMemory(env, "Unable to push principal");
6828            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
6829            return;
6830        }
6831    }
6832
6833    SSL_set_client_CA_list(ssl, principalsStack.release());
6834    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
6835}
6836
6837/**
6838 * public static native long SSL_get_mode(long ssl);
6839 */
6840static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address) {
6841    SSL* ssl = to_SSL(env, ssl_address, true);
6842    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
6843    if (ssl == NULL) {
6844      return 0;
6845    }
6846    long mode = SSL_get_mode(ssl);
6847    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
6848    return mode;
6849}
6850
6851/**
6852 * public static native long SSL_set_mode(long ssl, long mode);
6853 */
6854static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
6855        jlong ssl_address, jlong mode) {
6856    SSL* ssl = to_SSL(env, ssl_address, true);
6857    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
6858    if (ssl == NULL) {
6859      return 0;
6860    }
6861    long result = SSL_set_mode(ssl, mode);
6862    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
6863    return result;
6864}
6865
6866/**
6867 * public static native long SSL_clear_mode(long ssl, long mode);
6868 */
6869static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
6870        jlong ssl_address, jlong mode) {
6871    SSL* ssl = to_SSL(env, ssl_address, true);
6872    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
6873    if (ssl == NULL) {
6874      return 0;
6875    }
6876    long result = SSL_clear_mode(ssl, mode);
6877    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
6878    return result;
6879}
6880
6881/**
6882 * public static native long SSL_get_options(long ssl);
6883 */
6884static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
6885        jlong ssl_address) {
6886    SSL* ssl = to_SSL(env, ssl_address, true);
6887    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
6888    if (ssl == NULL) {
6889      return 0;
6890    }
6891    long options = SSL_get_options(ssl);
6892    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
6893    return options;
6894}
6895
6896/**
6897 * public static native long SSL_set_options(long ssl, long options);
6898 */
6899static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
6900        jlong ssl_address, jlong options) {
6901    SSL* ssl = to_SSL(env, ssl_address, true);
6902    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
6903    if (ssl == NULL) {
6904      return 0;
6905    }
6906    long result = SSL_set_options(ssl, options);
6907    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
6908    return result;
6909}
6910
6911/**
6912 * public static native long SSL_clear_options(long ssl, long options);
6913 */
6914static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
6915        jlong ssl_address, jlong options) {
6916    SSL* ssl = to_SSL(env, ssl_address, true);
6917    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
6918    if (ssl == NULL) {
6919      return 0;
6920    }
6921    long result = SSL_clear_options(ssl, options);
6922    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
6923    return result;
6924}
6925
6926static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address)
6927{
6928    SSL* ssl = to_SSL(env, ssl_address, true);
6929    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
6930
6931    STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
6932    int count = (cipherStack != NULL) ? sk_SSL_CIPHER_num(cipherStack) : 0;
6933    ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(count));
6934    ScopedLongArrayRW ciphers(env, ciphersArray.get());
6935    for (int i = 0; i < count; i++) {
6936        ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
6937    }
6938
6939    JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%d]", ssl, ciphersArray.get(), count);
6940    return ciphersArray.release();
6941}
6942
6943static jint NativeCrypto_get_SSL_CIPHER_algorithm_mkey(JNIEnv* env, jclass,
6944        jlong ssl_cipher_address)
6945{
6946    SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
6947    JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_mkey => %ld", cipher, cipher->algorithm_mkey);
6948    return cipher->algorithm_mkey;
6949}
6950
6951static jint NativeCrypto_get_SSL_CIPHER_algorithm_auth(JNIEnv* env, jclass,
6952        jlong ssl_cipher_address)
6953{
6954    SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
6955    JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_auth => %ld", cipher, cipher->algorithm_auth);
6956    return cipher->algorithm_auth;
6957}
6958
6959/**
6960 * Sets the ciphers suites that are enabled in the SSL
6961 */
6962static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
6963        jlong ssl_address, jobjectArray cipherSuites)
6964{
6965    SSL* ssl = to_SSL(env, ssl_address, true);
6966    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
6967    if (ssl == NULL) {
6968        return;
6969    }
6970    if (cipherSuites == NULL) {
6971        jniThrowNullPointerException(env, "cipherSuites == null");
6972        return;
6973    }
6974
6975    Unique_sk_SSL_CIPHER cipherstack(sk_SSL_CIPHER_new_null());
6976    if (cipherstack.get() == NULL) {
6977        jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
6978        return;
6979    }
6980
6981    const SSL_METHOD* ssl_method = ssl->method;
6982    int num_ciphers = ssl_method->num_ciphers();
6983
6984    int length = env->GetArrayLength(cipherSuites);
6985    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
6986    for (int i = 0; i < length; i++) {
6987        ScopedLocalRef<jstring> cipherSuite(env,
6988                reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
6989        ScopedUtfChars c(env, cipherSuite.get());
6990        if (c.c_str() == NULL) {
6991            return;
6992        }
6993        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
6994        bool found = false;
6995        for (int j = 0; j < num_ciphers; j++) {
6996            const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
6997            if ((strcmp(c.c_str(), cipher->name) == 0)
6998                    && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
6999                if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
7000                    jniThrowOutOfMemory(env, "Unable to push cipher");
7001                    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
7002                    return;
7003                }
7004                found = true;
7005            }
7006        }
7007        if (!found) {
7008            jniThrowException(env, "java/lang/IllegalArgumentException",
7009                              "Could not find cipher suite.");
7010            return;
7011        }
7012    }
7013
7014    int rc = SSL_set_cipher_lists(ssl, cipherstack.get());
7015    if (rc == 0) {
7016        freeOpenSslErrorState();
7017        jniThrowException(env, "java/lang/IllegalArgumentException",
7018                          "Illegal cipher suite strings.");
7019    } else {
7020        OWNERSHIP_TRANSFERRED(cipherstack);
7021    }
7022}
7023
7024static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong sslRef) {
7025    SSL* ssl = to_SSL(env, sslRef, true);
7026    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7027    if (ssl == NULL) {
7028      return;
7029    }
7030    SSL_set_accept_state(ssl);
7031}
7032
7033static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong sslRef) {
7034    SSL* ssl = to_SSL(env, sslRef, true);
7035    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7036    if (ssl == NULL) {
7037      return;
7038    }
7039    SSL_set_connect_state(ssl);
7040}
7041
7042/**
7043 * Sets certificate expectations, especially for server to request client auth
7044 */
7045static void NativeCrypto_SSL_set_verify(JNIEnv* env,
7046        jclass, jlong ssl_address, jint mode)
7047{
7048    SSL* ssl = to_SSL(env, ssl_address, true);
7049    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7050    if (ssl == NULL) {
7051      return;
7052    }
7053    SSL_set_verify(ssl, (int)mode, NULL);
7054}
7055
7056/**
7057 * Sets the ciphers suites that are enabled in the SSL
7058 */
7059static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
7060        jlong ssl_address, jlong ssl_session_address)
7061{
7062    SSL* ssl = to_SSL(env, ssl_address, true);
7063    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7064    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7065    if (ssl == NULL) {
7066        return;
7067    }
7068
7069    int ret = SSL_set_session(ssl, ssl_session);
7070    if (ret != 1) {
7071        /*
7072         * Translate the error, and throw if it turns out to be a real
7073         * problem.
7074         */
7075        int sslErrorCode = SSL_get_error(ssl, ret);
7076        if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7077            throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
7078            SSL_clear(ssl);
7079        }
7080    }
7081}
7082
7083/**
7084 * Sets the ciphers suites that are enabled in the SSL
7085 */
7086static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
7087        jlong ssl_address, jboolean creation_enabled)
7088{
7089    SSL* ssl = to_SSL(env, ssl_address, true);
7090    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
7091              ssl, creation_enabled);
7092    if (ssl == NULL) {
7093        return;
7094    }
7095    SSL_set_session_creation_enabled(ssl, creation_enabled);
7096}
7097
7098static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
7099        jlong ssl_address, jstring hostname)
7100{
7101    SSL* ssl = to_SSL(env, ssl_address, true);
7102    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
7103              ssl, hostname);
7104    if (ssl == NULL) {
7105        return;
7106    }
7107
7108    ScopedUtfChars hostnameChars(env, hostname);
7109    if (hostnameChars.c_str() == NULL) {
7110        return;
7111    }
7112    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s",
7113              ssl, hostnameChars.c_str());
7114
7115    int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7116    if (ret != 1) {
7117        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
7118        SSL_clear(ssl);
7119        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7120        return;
7121    }
7122    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7123}
7124
7125static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address) {
7126    SSL* ssl = to_SSL(env, ssl_address, true);
7127    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7128    if (ssl == NULL) {
7129        return NULL;
7130    }
7131    const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7132    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7133    return env->NewStringUTF(servername);
7134}
7135
7136/**
7137 * A common selection path for both NPN and ALPN since they're essentially the
7138 * same protocol. The list of protocols in "primary" is considered the order
7139 * which should take precedence.
7140 */
7141static int proto_select(SSL* ssl __attribute__ ((unused)),
7142        unsigned char **out, unsigned char *outLength,
7143        const unsigned char *primary, const unsigned int primaryLength,
7144        const unsigned char *secondary, const unsigned int secondaryLength) {
7145    if (primary != NULL) {
7146        JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
7147
7148        int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
7149                secondaryLength);
7150        switch (status) {
7151        case OPENSSL_NPN_NEGOTIATED:
7152            JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
7153            return SSL_TLSEXT_ERR_OK;
7154            break;
7155        case OPENSSL_NPN_UNSUPPORTED:
7156            JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
7157            break;
7158        case OPENSSL_NPN_NO_OVERLAP:
7159            JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
7160            break;
7161        }
7162    } else {
7163        if (out != NULL && outLength != NULL) {
7164            *out = NULL;
7165            *outLength = 0;
7166        }
7167        JNI_TRACE("protocols=NULL");
7168    }
7169    return SSL_TLSEXT_ERR_NOACK;
7170}
7171
7172/**
7173 * Callback for the server to select an ALPN protocol.
7174 */
7175static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
7176        const unsigned char *in, unsigned int inlen, void *) {
7177    JNI_TRACE("ssl=%p alpn_select_callback", ssl);
7178
7179    AppData* appData = toAppData(ssl);
7180    JNI_TRACE("AppData=%p", appData);
7181
7182    return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
7183            reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
7184            appData->alpnProtocolsLength, in, inlen);
7185}
7186
7187/**
7188 * Callback for the client to select an NPN protocol.
7189 */
7190static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
7191                                      const unsigned char* in, unsigned int inlen, void*)
7192{
7193    JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
7194
7195    AppData* appData = toAppData(ssl);
7196    JNI_TRACE("AppData=%p", appData);
7197
7198    // Enable False Start on the client if the server understands NPN
7199    // http://www.imperialviolet.org/2012/04/11/falsestart.html
7200    SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
7201
7202    return proto_select(ssl, out, outlen, in, inlen,
7203            reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
7204            appData->npnProtocolsLength);
7205}
7206
7207/**
7208 * Callback for the server to advertise available protocols.
7209 */
7210static int next_protos_advertised_callback(SSL* ssl,
7211        const unsigned char **out, unsigned int *outlen, void *)
7212{
7213    JNI_TRACE("ssl=%p next_protos_advertised_callback", ssl);
7214    AppData* appData = toAppData(ssl);
7215    unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
7216    if (npnProtocols != NULL) {
7217        *out = npnProtocols;
7218        *outlen = appData->npnProtocolsLength;
7219        return SSL_TLSEXT_ERR_OK;
7220    } else {
7221        *out = NULL;
7222        *outlen = 0;
7223        return SSL_TLSEXT_ERR_NOACK;
7224    }
7225}
7226
7227static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
7228{
7229    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7230    if (ssl_ctx == NULL) {
7231        return;
7232    }
7233    SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); // client
7234    SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_protos_advertised_callback, NULL); // server
7235}
7236
7237static void NativeCrypto_SSL_CTX_disable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
7238{
7239    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7240    if (ssl_ctx == NULL) {
7241        return;
7242    }
7243    SSL_CTX_set_next_proto_select_cb(ssl_ctx, NULL, NULL); // client
7244    SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, NULL, NULL); // server
7245}
7246
7247static jbyteArray NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv* env, jclass,
7248        jlong ssl_address)
7249{
7250    SSL* ssl = to_SSL(env, ssl_address, true);
7251    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_npn_negotiated_protocol", ssl);
7252    if (ssl == NULL) {
7253        return NULL;
7254    }
7255    const jbyte* npn;
7256    unsigned npnLength;
7257    SSL_get0_next_proto_negotiated(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
7258    if (npnLength == 0) {
7259        return NULL;
7260    }
7261    jbyteArray result = env->NewByteArray(npnLength);
7262    if (result != NULL) {
7263        env->SetByteArrayRegion(result, 0, npnLength, npn);
7264    }
7265    return result;
7266}
7267
7268static int NativeCrypto_SSL_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_address,
7269        jbyteArray protos) {
7270    SSL* ssl = to_SSL(env, ssl_address, true);
7271    if (ssl == NULL) {
7272        return 0;
7273    }
7274
7275    JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p", ssl, protos);
7276
7277    if (protos == NULL) {
7278        JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=NULL", ssl);
7279        return 1;
7280    }
7281
7282    ScopedByteArrayRO protosBytes(env, protos);
7283    if (protosBytes.get() == NULL) {
7284        JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => protosBytes == NULL", ssl,
7285                protos);
7286        return 0;
7287    }
7288
7289    const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
7290    int ret = SSL_set_alpn_protos(ssl, tmp, protosBytes.size());
7291    JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => ret=%d", ssl, protos, ret);
7292    return ret;
7293}
7294
7295static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
7296        jlong ssl_address)
7297{
7298    SSL* ssl = to_SSL(env, ssl_address, true);
7299    JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
7300    if (ssl == NULL) {
7301        return NULL;
7302    }
7303    const jbyte* npn;
7304    unsigned npnLength;
7305    SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
7306    if (npnLength == 0) {
7307        return NULL;
7308    }
7309    jbyteArray result = env->NewByteArray(npnLength);
7310    if (result != NULL) {
7311        env->SetByteArrayRegion(result, 0, npnLength, npn);
7312    }
7313    return result;
7314}
7315
7316#ifdef WITH_JNI_TRACE_KEYS
7317static inline char hex_char(unsigned char in)
7318{
7319    if (in < 10) {
7320        return '0' + in;
7321    } else if (in <= 0xF0) {
7322        return 'A' + in - 10;
7323    } else {
7324        return '?';
7325    }
7326}
7327
7328static void hex_string(char **dest, unsigned char* input, int len)
7329{
7330    *dest = (char*) malloc(len * 2 + 1);
7331    char *output = *dest;
7332    for (int i = 0; i < len; i++) {
7333        *output++ = hex_char(input[i] >> 4);
7334        *output++ = hex_char(input[i] & 0xF);
7335    }
7336    *output = '\0';
7337}
7338
7339static void debug_print_session_key(SSL_SESSION* session)
7340{
7341    char *session_id_str;
7342    char *master_key_str;
7343    const char *key_type;
7344    char *keyline;
7345
7346    hex_string(&session_id_str, session->session_id, session->session_id_length);
7347    hex_string(&master_key_str, session->master_key, session->master_key_length);
7348
7349    X509* peer = SSL_SESSION_get0_peer(session);
7350    EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
7351    switch (EVP_PKEY_type(pkey->type)) {
7352    case EVP_PKEY_RSA:
7353        key_type = "RSA";
7354        break;
7355    case EVP_PKEY_DSA:
7356        key_type = "DSA";
7357        break;
7358    case EVP_PKEY_EC:
7359        key_type = "EC";
7360        break;
7361    default:
7362        key_type = "Unknown";
7363        break;
7364    }
7365
7366    asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
7367            master_key_str);
7368    JNI_TRACE("ssl_session=%p %s", session, keyline);
7369
7370    free(session_id_str);
7371    free(master_key_str);
7372    free(keyline);
7373}
7374#endif /* WITH_JNI_TRACE_KEYS */
7375
7376/**
7377 * Perform SSL handshake
7378 */
7379static jlong NativeCrypto_SSL_do_handshake_bio(JNIEnv* env, jclass, jlong ssl_address,
7380        jlong rbioRef, jlong wbioRef, jobject shc, jboolean client_mode, jbyteArray npnProtocols,
7381        jbyteArray alpnProtocols) {
7382    SSL* ssl = to_SSL(env, ssl_address, true);
7383    BIO* rbio = reinterpret_cast<BIO*>(rbioRef);
7384    BIO* wbio = reinterpret_cast<BIO*>(wbioRef);
7385    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio rbio=%p wbio=%p shc=%p client_mode=%d npn=%p",
7386              ssl, rbio, wbio, shc, client_mode, npnProtocols);
7387    if (ssl == NULL) {
7388        return 0;
7389    }
7390    if (shc == NULL) {
7391        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
7392        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio sslHandshakeCallbacks == null => 0", ssl);
7393        return 0;
7394    }
7395
7396    if (rbio == NULL || wbio == NULL) {
7397        jniThrowNullPointerException(env, "rbio == null || wbio == null");
7398        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => rbio == null || wbio == NULL", ssl);
7399        return 0;
7400    }
7401
7402    ScopedSslBio sslBio(ssl, rbio, wbio);
7403
7404    AppData* appData = toAppData(ssl);
7405    if (appData == NULL) {
7406        throwSSLExceptionStr(env, "Unable to retrieve application data");
7407        SSL_clear(ssl);
7408        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
7409        return 0;
7410    }
7411
7412    if (!client_mode && alpnProtocols != NULL) {
7413        SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
7414    }
7415
7416    int ret = 0;
7417    errno = 0;
7418
7419    if (!appData->setCallbackState(env, shc, NULL, npnProtocols, alpnProtocols)) {
7420        SSL_clear(ssl);
7421        freeOpenSslErrorState();
7422        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio setCallbackState => 0", ssl);
7423        return 0;
7424    }
7425    ret = SSL_do_handshake(ssl);
7426    appData->clearCallbackState();
7427    // cert_verify_callback threw exception
7428    if (env->ExceptionCheck()) {
7429        SSL_clear(ssl);
7430        freeOpenSslErrorState();
7431        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio exception => 0", ssl);
7432        return 0;
7433    }
7434
7435    if (ret <= 0) { // error. See SSL_do_handshake(3SSL) man page.
7436        // error case
7437        int sslError = SSL_get_error(ssl, ret);
7438        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio ret=%d errno=%d sslError=%d",
7439                  ssl, ret, errno, sslError);
7440
7441        /*
7442         * If SSL_do_handshake doesn't succeed due to the socket being
7443         * either unreadable or unwritable, we need to exit to allow
7444         * the SSLEngine code to wrap or unwrap.
7445         */
7446        if (sslError == SSL_ERROR_NONE || (sslError == SSL_ERROR_SYSCALL && errno == 0)) {
7447            throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
7448            SSL_clear(ssl);
7449            freeOpenSslErrorState();
7450        } else if (sslError != SSL_ERROR_WANT_READ && sslError != SSL_ERROR_WANT_WRITE) {
7451            throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake terminated",
7452                    throwSSLHandshakeExceptionStr);
7453            SSL_clear(ssl);
7454            freeOpenSslErrorState();
7455        }
7456        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio error => 0", ssl);
7457        return 0;
7458    }
7459
7460    // success. handshake completed
7461    SSL_SESSION* ssl_session = SSL_get1_session(ssl);
7462    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => ssl_session=%p", ssl, ssl_session);
7463#ifdef WITH_JNI_TRACE_KEYS
7464    debug_print_session_key(ssl_session);
7465#endif
7466    return reinterpret_cast<uintptr_t>(ssl_session);
7467}
7468
7469/**
7470 * Perform SSL handshake
7471 */
7472static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
7473        jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
7474        jbyteArray alpnProtocols) {
7475    SSL* ssl = to_SSL(env, ssl_address, true);
7476    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
7477              ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
7478    if (ssl == NULL) {
7479        return 0;
7480    }
7481    if (fdObject == NULL) {
7482        jniThrowNullPointerException(env, "fd == null");
7483        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => 0", ssl);
7484        return 0;
7485    }
7486    if (shc == NULL) {
7487        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
7488        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => 0", ssl);
7489        return 0;
7490    }
7491
7492    NetFd fd(env, fdObject);
7493    if (fd.isClosed()) {
7494        // SocketException thrown by NetFd.isClosed
7495        SSL_clear(ssl);
7496        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => 0", ssl);
7497        return 0;
7498    }
7499
7500    int ret = SSL_set_fd(ssl, fd.get());
7501    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
7502
7503    if (ret != 1) {
7504        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7505                                       "Error setting the file descriptor");
7506        SSL_clear(ssl);
7507        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => 0", ssl);
7508        return 0;
7509    }
7510
7511    /*
7512     * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
7513     * forever and we can use select() to find out if the socket is ready.
7514     */
7515    if (!setBlocking(fd.get(), false)) {
7516        throwSSLExceptionStr(env, "Unable to make socket non blocking");
7517        SSL_clear(ssl);
7518        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => 0", ssl);
7519        return 0;
7520    }
7521
7522    AppData* appData = toAppData(ssl);
7523    if (appData == NULL) {
7524        throwSSLExceptionStr(env, "Unable to retrieve application data");
7525        SSL_clear(ssl);
7526        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
7527        return 0;
7528    }
7529
7530    if (client_mode) {
7531        SSL_set_connect_state(ssl);
7532    } else {
7533        SSL_set_accept_state(ssl);
7534        if (alpnProtocols != NULL) {
7535            SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
7536        }
7537    }
7538
7539    ret = 0;
7540    while (appData->aliveAndKicking) {
7541        errno = 0;
7542
7543        if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
7544            // SocketException thrown by NetFd.isClosed
7545            SSL_clear(ssl);
7546            JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
7547            return 0;
7548        }
7549        ret = SSL_do_handshake(ssl);
7550        appData->clearCallbackState();
7551        // cert_verify_callback threw exception
7552        if (env->ExceptionCheck()) {
7553            SSL_clear(ssl);
7554            JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => 0", ssl);
7555            return 0;
7556        }
7557        // success case
7558        if (ret == 1) {
7559            break;
7560        }
7561        // retry case
7562        if (errno == EINTR) {
7563            continue;
7564        }
7565        // error case
7566        int sslError = SSL_get_error(ssl, ret);
7567        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout_millis=%d",
7568                  ssl, ret, errno, sslError, timeout_millis);
7569
7570        /*
7571         * If SSL_do_handshake doesn't succeed due to the socket being
7572         * either unreadable or unwritable, we use sslSelect to
7573         * wait for it to become ready. If that doesn't happen
7574         * before the specified timeout or an error occurs, we
7575         * cancel the handshake. Otherwise we try the SSL_connect
7576         * again.
7577         */
7578        if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
7579            appData->waitingThreads++;
7580            int selectResult = sslSelect(env, sslError, fdObject, appData, timeout_millis);
7581
7582            if (selectResult == THROWN_EXCEPTION) {
7583                // SocketException thrown by NetFd.isClosed
7584                SSL_clear(ssl);
7585                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => 0", ssl);
7586                return 0;
7587            }
7588            if (selectResult == -1) {
7589                throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error",
7590                        throwSSLHandshakeExceptionStr);
7591                SSL_clear(ssl);
7592                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => 0", ssl);
7593                return 0;
7594            }
7595            if (selectResult == 0) {
7596                throwSocketTimeoutException(env, "SSL handshake timed out");
7597                SSL_clear(ssl);
7598                freeOpenSslErrorState();
7599                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => 0", ssl);
7600                return 0;
7601            }
7602        } else {
7603            // ALOGE("Unknown error %d during handshake", error);
7604            break;
7605        }
7606    }
7607
7608    // clean error. See SSL_do_handshake(3SSL) man page.
7609    if (ret == 0) {
7610        /*
7611         * The other side closed the socket before the handshake could be
7612         * completed, but everything is within the bounds of the TLS protocol.
7613         * We still might want to find out the real reason of the failure.
7614         */
7615        int sslError = SSL_get_error(ssl, ret);
7616        if (sslError == SSL_ERROR_NONE || (sslError == SSL_ERROR_SYSCALL && errno == 0)) {
7617            throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
7618        } else {
7619            throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake terminated",
7620                    throwSSLHandshakeExceptionStr);
7621        }
7622        SSL_clear(ssl);
7623        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => 0", ssl);
7624        return 0;
7625    }
7626
7627    // unclean error. See SSL_do_handshake(3SSL) man page.
7628    if (ret < 0) {
7629        /*
7630         * Translate the error and throw exception. We are sure it is an error
7631         * at this point.
7632         */
7633        int sslError = SSL_get_error(ssl, ret);
7634        throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake aborted",
7635                throwSSLHandshakeExceptionStr);
7636        SSL_clear(ssl);
7637        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => 0", ssl);
7638        return 0;
7639    }
7640    SSL_SESSION* ssl_session = SSL_get1_session(ssl);
7641    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
7642#ifdef WITH_JNI_TRACE_KEYS
7643    debug_print_session_key(ssl_session);
7644#endif
7645    return (jlong) ssl_session;
7646}
7647
7648/**
7649 * Perform SSL renegotiation
7650 */
7651static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jlong ssl_address)
7652{
7653    SSL* ssl = to_SSL(env, ssl_address, true);
7654    JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
7655    if (ssl == NULL) {
7656        return;
7657    }
7658    int result = SSL_renegotiate(ssl);
7659    if (result != 1) {
7660        throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
7661        return;
7662    }
7663    // first call asks client to perform renegotiation
7664    int ret = SSL_do_handshake(ssl);
7665    if (ret != 1) {
7666        int sslError = SSL_get_error(ssl, ret);
7667        throwSSLExceptionWithSslErrors(env, ssl, sslError,
7668                                       "Problem with SSL_do_handshake after SSL_renegotiate");
7669        return;
7670    }
7671    // if client agrees, set ssl state and perform renegotiation
7672    ssl->state = SSL_ST_ACCEPT;
7673    SSL_do_handshake(ssl);
7674    JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
7675}
7676
7677/**
7678 * public static native byte[][] SSL_get_certificate(long ssl);
7679 */
7680static jlongArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jlong ssl_address)
7681{
7682    SSL* ssl = to_SSL(env, ssl_address, true);
7683    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
7684    if (ssl == NULL) {
7685        return NULL;
7686    }
7687    X509* certificate = SSL_get_certificate(ssl);
7688    if (certificate == NULL) {
7689        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
7690        // SSL_get_certificate can return NULL during an error as well.
7691        freeOpenSslErrorState();
7692        return NULL;
7693    }
7694
7695    Unique_sk_X509 chain(sk_X509_new_null());
7696    if (chain.get() == NULL) {
7697        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
7698        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
7699        return NULL;
7700    }
7701    if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
7702        jniThrowOutOfMemory(env, "Unable to push local certificate");
7703        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
7704        return NULL;
7705    }
7706    STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
7707    for (int i=0; i<sk_X509_num(cert_chain); i++) {
7708        if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
7709            jniThrowOutOfMemory(env, "Unable to push local certificate chain");
7710            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
7711            return NULL;
7712        }
7713    }
7714
7715    jlongArray refArray = getCertificateRefs(env, chain.get());
7716    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, refArray);
7717    return refArray;
7718}
7719
7720// Fills a long[] with the peer certificates in the chain.
7721static jlongArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jlong ssl_address)
7722{
7723    SSL* ssl = to_SSL(env, ssl_address, true);
7724    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
7725    if (ssl == NULL) {
7726        return NULL;
7727    }
7728    STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
7729    Unique_sk_X509 chain_copy(NULL);
7730    if (ssl->server) {
7731        X509* x509 = SSL_get_peer_certificate(ssl);
7732        if (x509 == NULL) {
7733            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
7734            return NULL;
7735        }
7736        chain_copy.reset(sk_X509_new_null());
7737        if (chain_copy.get() == NULL) {
7738            jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
7739            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
7740            return NULL;
7741        }
7742        size_t chain_size = sk_X509_num(chain);
7743        for (size_t i = 0; i < chain_size; i++) {
7744            if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
7745                jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
7746                JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
7747                return NULL;
7748            }
7749        }
7750        if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
7751            jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
7752            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
7753            return NULL;
7754        }
7755        chain = chain_copy.get();
7756    }
7757    jlongArray refArray = getCertificateRefs(env, chain);
7758    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, refArray);
7759    return refArray;
7760}
7761
7762static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
7763                   int* sslReturnCode, int* sslErrorCode, int read_timeout_millis) {
7764    JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
7765
7766    if (len == 0) {
7767        // Don't bother doing anything in this case.
7768        return 0;
7769    }
7770
7771    BIO* rbio = SSL_get_rbio(ssl);
7772    BIO* wbio = SSL_get_wbio(ssl);
7773
7774    AppData* appData = toAppData(ssl);
7775    JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
7776    if (appData == NULL) {
7777        return THROW_SSLEXCEPTION;
7778    } else if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
7779               !SSL_renegotiate_pending(ssl)) {
7780        JNI_TRACE("ssl=%p sslRead => init is not finished (state=0x%x)", ssl, SSL_get_state(ssl));
7781        return THROW_SSLEXCEPTION;
7782    }
7783
7784    while (appData->aliveAndKicking) {
7785        errno = 0;
7786
7787        if (MUTEX_LOCK(appData->mutex) == -1) {
7788            return -1;
7789        }
7790
7791        unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
7792
7793        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
7794            MUTEX_UNLOCK(appData->mutex);
7795            return THROWN_EXCEPTION;
7796        }
7797        int result = SSL_read(ssl, buf, len);
7798        appData->clearCallbackState();
7799        // callbacks can happen if server requests renegotiation
7800        if (env->ExceptionCheck()) {
7801            SSL_clear(ssl);
7802            JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
7803            return THROWN_EXCEPTION;
7804        }
7805        int sslError = SSL_ERROR_NONE;
7806        if (result <= 0) {
7807            sslError = SSL_get_error(ssl, result);
7808            freeOpenSslErrorState();
7809        }
7810        JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError);
7811#ifdef WITH_JNI_TRACE_DATA
7812        for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
7813            int n = result - i;
7814            if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
7815                n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
7816            }
7817            JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
7818        }
7819#endif
7820
7821        // If we have been successful in moving data around, check whether it
7822        // might make sense to wake up other blocked threads, so they can give
7823        // it a try, too.
7824        if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
7825                && appData->waitingThreads > 0) {
7826            sslNotify(appData);
7827        }
7828
7829        // If we are blocked by the underlying socket, tell the world that
7830        // there will be one more waiting thread now.
7831        if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
7832            appData->waitingThreads++;
7833        }
7834
7835        MUTEX_UNLOCK(appData->mutex);
7836
7837        switch (sslError) {
7838            // Successfully read at least one byte.
7839            case SSL_ERROR_NONE: {
7840                return result;
7841            }
7842
7843            // Read zero bytes. End of stream reached.
7844            case SSL_ERROR_ZERO_RETURN: {
7845                return -1;
7846            }
7847
7848            // Need to wait for availability of underlying layer, then retry.
7849            case SSL_ERROR_WANT_READ:
7850            case SSL_ERROR_WANT_WRITE: {
7851                int selectResult = sslSelect(env, sslError, fdObject, appData, read_timeout_millis);
7852                if (selectResult == THROWN_EXCEPTION) {
7853                    return THROWN_EXCEPTION;
7854                }
7855                if (selectResult == -1) {
7856                    *sslReturnCode = -1;
7857                    *sslErrorCode = sslError;
7858                    return THROW_SSLEXCEPTION;
7859                }
7860                if (selectResult == 0) {
7861                    return THROW_SOCKETTIMEOUTEXCEPTION;
7862                }
7863
7864                break;
7865            }
7866
7867            // A problem occurred during a system call, but this is not
7868            // necessarily an error.
7869            case SSL_ERROR_SYSCALL: {
7870                // Connection closed without proper shutdown. Tell caller we
7871                // have reached end-of-stream.
7872                if (result == 0) {
7873                    return -1;
7874                }
7875
7876                // System call has been interrupted. Simply retry.
7877                if (errno == EINTR) {
7878                    break;
7879                }
7880
7881                // Note that for all other system call errors we fall through
7882                // to the default case, which results in an Exception.
7883            }
7884
7885            // Everything else is basically an error.
7886            default: {
7887                *sslReturnCode = result;
7888                *sslErrorCode = sslError;
7889                return THROW_SSLEXCEPTION;
7890            }
7891        }
7892    }
7893
7894    return -1;
7895}
7896
7897static jint NativeCrypto_SSL_read_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray destJava,
7898        jlong sourceBioRef, jlong sinkBioRef, jobject shc) {
7899    SSL* ssl = to_SSL(env, sslRef, true);
7900    BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sourceBioRef));
7901    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
7902    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO dest=%p sourceBio=%p sinkBio=%p shc=%p",
7903              ssl, destJava, rbio, wbio, shc);
7904    if (ssl == NULL) {
7905        return 0;
7906    }
7907    if (rbio == NULL || wbio == NULL) {
7908        jniThrowNullPointerException(env, "rbio == null || wbio == null");
7909        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => rbio == null || wbio == null", ssl);
7910        return -1;
7911    }
7912    if (shc == NULL) {
7913        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
7914        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => sslHandshakeCallbacks == null", ssl);
7915        return -1;
7916    }
7917
7918    ScopedByteArrayRW dest(env, destJava);
7919    if (dest.get() == NULL) {
7920        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
7921        return -1;
7922    }
7923
7924    AppData* appData = toAppData(ssl);
7925    if (appData == NULL) {
7926        throwSSLExceptionStr(env, "Unable to retrieve application data");
7927        SSL_clear(ssl);
7928        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => appData == NULL", ssl);
7929        return -1;
7930    }
7931
7932    errno = 0;
7933
7934    if (MUTEX_LOCK(appData->mutex) == -1) {
7935        return -1;
7936    }
7937
7938    if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
7939        MUTEX_UNLOCK(appData->mutex);
7940        throwSSLExceptionStr(env, "Unable to set callback state");
7941        SSL_clear(ssl);
7942        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => set callback state failed", ssl);
7943        return -1;
7944    }
7945
7946    ScopedSslBio sslBio(ssl, rbio, wbio);
7947
7948    int result = SSL_read(ssl, dest.get(), dest.size());
7949    appData->clearCallbackState();
7950    // callbacks can happen if server requests renegotiation
7951    if (env->ExceptionCheck()) {
7952        SSL_clear(ssl);
7953        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
7954        return THROWN_EXCEPTION;
7955    }
7956    int sslError = SSL_ERROR_NONE;
7957    if (result <= 0) {
7958        sslError = SSL_get_error(ssl, result);
7959    }
7960    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO SSL_read result=%d sslError=%d", ssl, result, sslError);
7961#ifdef WITH_JNI_TRACE_DATA
7962    for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
7963        int n = result - i;
7964        if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
7965            n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
7966        }
7967        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
7968    }
7969#endif
7970
7971    MUTEX_UNLOCK(appData->mutex);
7972
7973    switch (sslError) {
7974        // Successfully read at least one byte.
7975        case SSL_ERROR_NONE:
7976            break;
7977
7978        // Read zero bytes. End of stream reached.
7979        case SSL_ERROR_ZERO_RETURN:
7980            result = -1;
7981            break;
7982
7983        // Need to wait for availability of underlying layer, then retry.
7984        case SSL_ERROR_WANT_READ:
7985        case SSL_ERROR_WANT_WRITE:
7986            result = 0;
7987            break;
7988
7989        // A problem occurred during a system call, but this is not
7990        // necessarily an error.
7991        case SSL_ERROR_SYSCALL: {
7992            // Connection closed without proper shutdown. Tell caller we
7993            // have reached end-of-stream.
7994            if (result == 0) {
7995                result = -1;
7996                break;
7997            } else if (errno == EINTR) {
7998                // System call has been interrupted. Simply retry.
7999                result = 0;
8000                break;
8001            }
8002
8003            // Note that for all other system call errors we fall through
8004            // to the default case, which results in an Exception.
8005        }
8006
8007        // Everything else is basically an error.
8008        default: {
8009            throwSSLExceptionWithSslErrors(env, ssl, sslError, "Read error");
8010            return -1;
8011        }
8012    }
8013    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => %d", ssl, result);
8014    return result;
8015}
8016
8017/**
8018 * OpenSSL read function (2): read into buffer at offset n chunks.
8019 * Returns 1 (success) or value <= 0 (failure).
8020 */
8021static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8022                                  jobject shc, jbyteArray b, jint offset, jint len,
8023                                  jint read_timeout_millis)
8024{
8025    SSL* ssl = to_SSL(env, ssl_address, true);
8026    JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d read_timeout_millis=%d",
8027              ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8028    if (ssl == NULL) {
8029        return 0;
8030    }
8031    if (fdObject == NULL) {
8032        jniThrowNullPointerException(env, "fd == null");
8033        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8034        return 0;
8035    }
8036    if (shc == NULL) {
8037        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8038        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8039        return 0;
8040    }
8041
8042    ScopedByteArrayRW bytes(env, b);
8043    if (bytes.get() == NULL) {
8044        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8045        return 0;
8046    }
8047    int returnCode = 0;
8048    int sslErrorCode = SSL_ERROR_NONE;;
8049
8050    int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8051                      &returnCode, &sslErrorCode, read_timeout_millis);
8052
8053    int result;
8054    switch (ret) {
8055        case THROW_SSLEXCEPTION:
8056            // See sslRead() regarding improper failure to handle normal cases.
8057            throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Read error");
8058            result = -1;
8059            break;
8060        case THROW_SOCKETTIMEOUTEXCEPTION:
8061            throwSocketTimeoutException(env, "Read timed out");
8062            result = -1;
8063            break;
8064        case THROWN_EXCEPTION:
8065            // SocketException thrown by NetFd.isClosed
8066            // or RuntimeException thrown by callback
8067            result = -1;
8068            break;
8069        default:
8070            result = ret;
8071            break;
8072    }
8073
8074    JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8075    return result;
8076}
8077
8078static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8079                    int* sslReturnCode, int* sslErrorCode, int write_timeout_millis) {
8080    JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d",
8081              ssl, buf, len, write_timeout_millis);
8082
8083    if (len == 0) {
8084        // Don't bother doing anything in this case.
8085        return 0;
8086    }
8087
8088    BIO* rbio = SSL_get_rbio(ssl);
8089    BIO* wbio = SSL_get_wbio(ssl);
8090
8091    AppData* appData = toAppData(ssl);
8092    JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8093    if (appData == NULL) {
8094        return THROW_SSLEXCEPTION;
8095    } else if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
8096               !SSL_renegotiate_pending(ssl)) {
8097        JNI_TRACE("ssl=%p sslWrite => init is not finished (state=0x%x)", ssl, SSL_get_state(ssl));
8098        return THROW_SSLEXCEPTION;
8099    }
8100
8101    int count = len;
8102
8103    while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
8104        errno = 0;
8105
8106        if (MUTEX_LOCK(appData->mutex) == -1) {
8107            return -1;
8108        }
8109
8110        unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8111
8112        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8113            MUTEX_UNLOCK(appData->mutex);
8114            return THROWN_EXCEPTION;
8115        }
8116        JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
8117        int result = SSL_write(ssl, buf, len);
8118        appData->clearCallbackState();
8119        // callbacks can happen if server requests renegotiation
8120        if (env->ExceptionCheck()) {
8121            SSL_clear(ssl);
8122            JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8123            return THROWN_EXCEPTION;
8124        }
8125        int sslError = SSL_ERROR_NONE;
8126        if (result <= 0) {
8127            sslError = SSL_get_error(ssl, result);
8128            freeOpenSslErrorState();
8129        }
8130        JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
8131                  ssl, result, sslError, ssl->s3->wbuf.left);
8132#ifdef WITH_JNI_TRACE_DATA
8133        for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8134            int n = result - i;
8135            if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8136                n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8137            }
8138            JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
8139        }
8140#endif
8141
8142        // If we have been successful in moving data around, check whether it
8143        // might make sense to wake up other blocked threads, so they can give
8144        // it a try, too.
8145        if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
8146                && appData->waitingThreads > 0) {
8147            sslNotify(appData);
8148        }
8149
8150        // If we are blocked by the underlying socket, tell the world that
8151        // there will be one more waiting thread now.
8152        if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
8153            appData->waitingThreads++;
8154        }
8155
8156        MUTEX_UNLOCK(appData->mutex);
8157
8158        switch (sslError) {
8159            // Successfully wrote at least one byte.
8160            case SSL_ERROR_NONE: {
8161                buf += result;
8162                len -= result;
8163                break;
8164            }
8165
8166            // Wrote zero bytes. End of stream reached.
8167            case SSL_ERROR_ZERO_RETURN: {
8168                return -1;
8169            }
8170
8171            // Need to wait for availability of underlying layer, then retry.
8172            // The concept of a write timeout doesn't really make sense, and
8173            // it's also not standard Java behavior, so we wait forever here.
8174            case SSL_ERROR_WANT_READ:
8175            case SSL_ERROR_WANT_WRITE: {
8176                int selectResult = sslSelect(env, sslError, fdObject, appData, write_timeout_millis);
8177                if (selectResult == THROWN_EXCEPTION) {
8178                    return THROWN_EXCEPTION;
8179                }
8180                if (selectResult == -1) {
8181                    *sslReturnCode = -1;
8182                    *sslErrorCode = sslError;
8183                    return THROW_SSLEXCEPTION;
8184                }
8185                if (selectResult == 0) {
8186                    return THROW_SOCKETTIMEOUTEXCEPTION;
8187                }
8188
8189                break;
8190            }
8191
8192            // A problem occurred during a system call, but this is not
8193            // necessarily an error.
8194            case SSL_ERROR_SYSCALL: {
8195                // Connection closed without proper shutdown. Tell caller we
8196                // have reached end-of-stream.
8197                if (result == 0) {
8198                    return -1;
8199                }
8200
8201                // System call has been interrupted. Simply retry.
8202                if (errno == EINTR) {
8203                    break;
8204                }
8205
8206                // Note that for all other system call errors we fall through
8207                // to the default case, which results in an Exception.
8208            }
8209
8210            // Everything else is basically an error.
8211            default: {
8212                *sslReturnCode = result;
8213                *sslErrorCode = sslError;
8214                return THROW_SSLEXCEPTION;
8215            }
8216        }
8217    }
8218    JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8219
8220    return count;
8221}
8222
8223/**
8224 * OpenSSL write function (2): write into buffer at offset n chunks.
8225 */
8226static int NativeCrypto_SSL_write_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray sourceJava, jint len,
8227        jlong sinkBioRef, jobject shc) {
8228    SSL* ssl = to_SSL(env, sslRef, true);
8229    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
8230    JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO source=%p len=%d wbio=%p shc=%p",
8231              ssl, sourceJava, len, wbio, shc);
8232    if (ssl == NULL) {
8233        return -1;
8234    }
8235    if (wbio == NULL) {
8236        jniThrowNullPointerException(env, "wbio == null");
8237        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => wbio == null", ssl);
8238        return -1;
8239    }
8240    if (shc == NULL) {
8241        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8242        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => sslHandshakeCallbacks == null", ssl);
8243        return -1;
8244    }
8245
8246    AppData* appData = toAppData(ssl);
8247    if (appData == NULL) {
8248        throwSSLExceptionStr(env, "Unable to retrieve application data");
8249        SSL_clear(ssl);
8250        freeOpenSslErrorState();
8251        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO appData => NULL", ssl);
8252        return -1;
8253    }
8254
8255    errno = 0;
8256
8257    if (MUTEX_LOCK(appData->mutex) == -1) {
8258        return 0;
8259    }
8260
8261    if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
8262        MUTEX_UNLOCK(appData->mutex);
8263        throwSSLExceptionStr(env, "Unable to set appdata callback");
8264        SSL_clear(ssl);
8265        freeOpenSslErrorState();
8266        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => appData can't set callback", ssl);
8267        return -1;
8268    }
8269
8270    ScopedByteArrayRO source(env, sourceJava);
8271    if (source.get() == NULL) {
8272        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => threw exception", ssl);
8273        return -1;
8274    }
8275
8276    Unique_BIO nullBio(BIO_new(BIO_s_null()));
8277    ScopedSslBio sslBio(ssl, nullBio.get(), wbio);
8278
8279    int result = SSL_write(ssl, reinterpret_cast<const char*>(source.get()), len);
8280    appData->clearCallbackState();
8281    // callbacks can happen if server requests renegotiation
8282    if (env->ExceptionCheck()) {
8283        SSL_clear(ssl);
8284        freeOpenSslErrorState();
8285        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO exception => exception pending (reneg)", ssl);
8286        return -1;
8287    }
8288    int sslError = SSL_ERROR_NONE;
8289    if (result <= 0) {
8290        sslError = SSL_get_error(ssl, result);
8291        freeOpenSslErrorState();
8292    }
8293    JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO SSL_write result=%d sslError=%d left=%d",
8294              ssl, result, sslError, ssl->s3->wbuf.left);
8295#ifdef WITH_JNI_TRACE_DATA
8296    for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8297        int n = result - i;
8298        if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8299            n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8300        }
8301        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
8302    }
8303#endif
8304
8305    MUTEX_UNLOCK(appData->mutex);
8306
8307    switch (sslError) {
8308        case SSL_ERROR_NONE:
8309            return result;
8310
8311        // Wrote zero bytes. End of stream reached.
8312        case SSL_ERROR_ZERO_RETURN:
8313            return -1;
8314
8315        case SSL_ERROR_WANT_READ:
8316        case SSL_ERROR_WANT_WRITE:
8317            return 0;
8318
8319        case SSL_ERROR_SYSCALL: {
8320            // Connection closed without proper shutdown. Tell caller we
8321            // have reached end-of-stream.
8322            if (result == 0) {
8323                return -1;
8324            }
8325
8326            // System call has been interrupted. Simply retry.
8327            if (errno == EINTR) {
8328                return 0;
8329            }
8330
8331            // Note that for all other system call errors we fall through
8332            // to the default case, which results in an Exception.
8333        }
8334
8335        // Everything else is basically an error.
8336        default: {
8337            throwSSLExceptionWithSslErrors(env, ssl, sslError, "Write error");
8338            break;
8339        }
8340    }
8341    return -1;
8342}
8343
8344/**
8345 * OpenSSL write function (2): write into buffer at offset n chunks.
8346 */
8347static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8348                                   jobject shc, jbyteArray b, jint offset, jint len, jint write_timeout_millis)
8349{
8350    SSL* ssl = to_SSL(env, ssl_address, true);
8351    JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d write_timeout_millis=%d",
8352              ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8353    if (ssl == NULL) {
8354        return;
8355    }
8356    if (fdObject == NULL) {
8357        jniThrowNullPointerException(env, "fd == null");
8358        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8359        return;
8360    }
8361    if (shc == NULL) {
8362        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8363        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8364        return;
8365    }
8366
8367    ScopedByteArrayRO bytes(env, b);
8368    if (bytes.get() == NULL) {
8369        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8370        return;
8371    }
8372    int returnCode = 0;
8373    int sslErrorCode = SSL_ERROR_NONE;
8374    int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8375                       len, &returnCode, &sslErrorCode, write_timeout_millis);
8376
8377    switch (ret) {
8378        case THROW_SSLEXCEPTION:
8379            // See sslWrite() regarding improper failure to handle normal cases.
8380            throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
8381            break;
8382        case THROW_SOCKETTIMEOUTEXCEPTION:
8383            throwSocketTimeoutException(env, "Write timed out");
8384            break;
8385        case THROWN_EXCEPTION:
8386            // SocketException thrown by NetFd.isClosed
8387            break;
8388        default:
8389            break;
8390    }
8391}
8392
8393/**
8394 * Interrupt any pending I/O before closing the socket.
8395 */
8396static void NativeCrypto_SSL_interrupt(
8397        JNIEnv* env, jclass, jlong ssl_address) {
8398    SSL* ssl = to_SSL(env, ssl_address, false);
8399    JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
8400    if (ssl == NULL) {
8401        return;
8402    }
8403
8404    /*
8405     * Mark the connection as quasi-dead, then send something to the emergency
8406     * file descriptor, so any blocking select() calls are woken up.
8407     */
8408    AppData* appData = toAppData(ssl);
8409    if (appData != NULL) {
8410        appData->aliveAndKicking = 0;
8411
8412        // At most two threads can be waiting.
8413        sslNotify(appData);
8414        sslNotify(appData);
8415    }
8416}
8417
8418/**
8419 * OpenSSL close SSL socket function.
8420 */
8421static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
8422                                      jobject fdObject, jobject shc) {
8423    SSL* ssl = to_SSL(env, ssl_address, false);
8424    JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
8425    if (ssl == NULL) {
8426        return;
8427    }
8428    if (fdObject == NULL) {
8429        jniThrowNullPointerException(env, "fd == null");
8430        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
8431        return;
8432    }
8433    if (shc == NULL) {
8434        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8435        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
8436        return;
8437    }
8438
8439    AppData* appData = toAppData(ssl);
8440    if (appData != NULL) {
8441        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8442            // SocketException thrown by NetFd.isClosed
8443            SSL_clear(ssl);
8444            freeOpenSslErrorState();
8445            return;
8446        }
8447
8448        /*
8449         * Try to make socket blocking again. OpenSSL literature recommends this.
8450         */
8451        int fd = SSL_get_fd(ssl);
8452        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
8453        if (fd != -1) {
8454            setBlocking(fd, true);
8455        }
8456
8457        int ret = SSL_shutdown(ssl);
8458        appData->clearCallbackState();
8459        // callbacks can happen if server requests renegotiation
8460        if (env->ExceptionCheck()) {
8461            SSL_clear(ssl);
8462            JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
8463            return;
8464        }
8465        switch (ret) {
8466            case 0:
8467                /*
8468                 * Shutdown was not successful (yet), but there also
8469                 * is no error. Since we can't know whether the remote
8470                 * server is actually still there, and we don't want to
8471                 * get stuck forever in a second SSL_shutdown() call, we
8472                 * simply return. This is not security a problem as long
8473                 * as we close the underlying socket, which we actually
8474                 * do, because that's where we are just coming from.
8475                 */
8476                break;
8477            case 1:
8478                /*
8479                 * Shutdown was successful. We can safely return. Hooray!
8480                 */
8481                break;
8482            default:
8483                /*
8484                 * Everything else is a real error condition. We should
8485                 * let the Java layer know about this by throwing an
8486                 * exception.
8487                 */
8488                int sslError = SSL_get_error(ssl, ret);
8489                throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
8490                break;
8491        }
8492    }
8493
8494    SSL_clear(ssl);
8495    freeOpenSslErrorState();
8496}
8497
8498/**
8499 * OpenSSL close SSL socket function.
8500 */
8501static void NativeCrypto_SSL_shutdown_BIO(JNIEnv* env, jclass, jlong ssl_address, jlong rbioRef,
8502        jlong wbioRef, jobject shc) {
8503    SSL* ssl = to_SSL(env, ssl_address, false);
8504    BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(rbioRef));
8505    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(wbioRef));
8506    JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown rbio=%p wbio=%p shc=%p", ssl, rbio, wbio, shc);
8507    if (ssl == NULL) {
8508        return;
8509    }
8510    if (rbio == NULL || wbio == NULL) {
8511        jniThrowNullPointerException(env, "rbio == null || wbio == null");
8512        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => rbio == null || wbio == null", ssl);
8513        return;
8514    }
8515    if (shc == NULL) {
8516        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8517        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
8518        return;
8519    }
8520
8521    AppData* appData = toAppData(ssl);
8522    if (appData != NULL) {
8523        if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
8524            // SocketException thrown by NetFd.isClosed
8525            SSL_clear(ssl);
8526            freeOpenSslErrorState();
8527            return;
8528        }
8529
8530        ScopedSslBio scopedBio(ssl, rbio, wbio);
8531
8532        int ret = SSL_shutdown(ssl);
8533        appData->clearCallbackState();
8534        // callbacks can happen if server requests renegotiation
8535        if (env->ExceptionCheck()) {
8536            SSL_clear(ssl);
8537            JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
8538            return;
8539        }
8540        switch (ret) {
8541            case 0:
8542                /*
8543                 * Shutdown was not successful (yet), but there also
8544                 * is no error. Since we can't know whether the remote
8545                 * server is actually still there, and we don't want to
8546                 * get stuck forever in a second SSL_shutdown() call, we
8547                 * simply return. This is not security a problem as long
8548                 * as we close the underlying socket, which we actually
8549                 * do, because that's where we are just coming from.
8550                 */
8551                break;
8552            case 1:
8553                /*
8554                 * Shutdown was successful. We can safely return. Hooray!
8555                 */
8556                break;
8557            default:
8558                /*
8559                 * Everything else is a real error condition. We should
8560                 * let the Java layer know about this by throwing an
8561                 * exception.
8562                 */
8563                int sslError = SSL_get_error(ssl, ret);
8564                throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
8565                break;
8566        }
8567    }
8568
8569    SSL_clear(ssl);
8570    freeOpenSslErrorState();
8571}
8572
8573static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address) {
8574    const SSL* ssl = to_SSL(env, ssl_address, true);
8575    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
8576    if (ssl == NULL) {
8577        jniThrowNullPointerException(env, "ssl == null");
8578        return 0;
8579    }
8580
8581    int status = SSL_get_shutdown(ssl);
8582    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
8583    return static_cast<jint>(status);
8584}
8585
8586/**
8587 * public static native void SSL_free(long ssl);
8588 */
8589static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address)
8590{
8591    SSL* ssl = to_SSL(env, ssl_address, true);
8592    JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
8593    if (ssl == NULL) {
8594        return;
8595    }
8596
8597    AppData* appData = toAppData(ssl);
8598    SSL_set_app_data(ssl, NULL);
8599    delete appData;
8600    SSL_free(ssl);
8601}
8602
8603/**
8604 * Gets and returns in a byte array the ID of the actual SSL session.
8605 */
8606static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
8607                                                      jlong ssl_session_address) {
8608    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8609    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
8610    if (ssl_session == NULL) {
8611        return NULL;
8612    }
8613    jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
8614    if (result != NULL) {
8615        jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
8616        env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
8617    }
8618    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
8619             ssl_session, result, ssl_session->session_id_length);
8620    return result;
8621}
8622
8623/**
8624 * Gets and returns in a long integer the creation's time of the
8625 * actual SSL session.
8626 */
8627static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
8628    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8629    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
8630    if (ssl_session == NULL) {
8631        return 0;
8632    }
8633    // result must be jlong, not long or *1000 will overflow
8634    jlong result = SSL_SESSION_get_time(ssl_session);
8635    result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
8636    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
8637    return result;
8638}
8639
8640/**
8641 * Gets and returns in a string the version of the SSL protocol. If it
8642 * returns the string "unknown" it means that no connection is established.
8643 */
8644static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jlong ssl_session_address) {
8645    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8646    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
8647    if (ssl_session == NULL) {
8648        return NULL;
8649    }
8650    const char* protocol = SSL_SESSION_get_version(ssl_session);
8651    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
8652    return env->NewStringUTF(protocol);
8653}
8654
8655/**
8656 * Gets and returns in a string the cipher negotiated for the SSL session.
8657 */
8658static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
8659    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8660    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
8661    if (ssl_session == NULL) {
8662        return NULL;
8663    }
8664    const SSL_CIPHER* cipher = ssl_session->cipher;
8665    const char* name = SSL_CIPHER_get_name(cipher);
8666    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
8667    return env->NewStringUTF(name);
8668}
8669
8670/**
8671 * Frees the SSL session.
8672 */
8673static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
8674    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8675    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
8676    if (ssl_session == NULL) {
8677        return;
8678    }
8679    SSL_SESSION_free(ssl_session);
8680}
8681
8682
8683/**
8684 * Serializes the native state of the session (ID, cipher, and keys but
8685 * not certificates). Returns a byte[] containing the DER-encoded state.
8686 * See apache mod_ssl.
8687 */
8688static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
8689    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8690    JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
8691    if (ssl_session == NULL) {
8692        return NULL;
8693    }
8694    return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
8695}
8696
8697/**
8698 * Deserialize the session.
8699 */
8700static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
8701    JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
8702
8703    ScopedByteArrayRO bytes(env, javaBytes);
8704    if (bytes.get() == NULL) {
8705        JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
8706        return 0;
8707    }
8708    const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
8709    SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
8710
8711    // Initialize SSL_SESSION cipher field based on cipher_id http://b/7091840
8712    if (ssl_session != NULL) {
8713        // based on ssl_get_prev_session
8714        uint32_t cipher_id_network_order = htonl(ssl_session->cipher_id);
8715        uint8_t* cipher_id_byte_pointer = reinterpret_cast<uint8_t*>(&cipher_id_network_order);
8716        if (ssl_session->ssl_version >= SSL3_VERSION_MAJOR) {
8717            cipher_id_byte_pointer += 2; // skip first two bytes for SSL3+
8718        } else {
8719            cipher_id_byte_pointer += 1; // skip first byte for SSL2
8720        }
8721        ssl_session->cipher = SSLv23_method()->get_cipher_by_char(cipher_id_byte_pointer);
8722        JNI_TRACE("NativeCrypto_d2i_SSL_SESSION cipher_id=%lx hton=%x 0=%x 1=%x cipher=%s",
8723                  ssl_session->cipher_id, cipher_id_network_order,
8724                  cipher_id_byte_pointer[0], cipher_id_byte_pointer[1],
8725                  SSL_CIPHER_get_name(ssl_session->cipher));
8726    } else {
8727        freeOpenSslErrorState();
8728    }
8729
8730    JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
8731    return reinterpret_cast<uintptr_t>(ssl_session);
8732}
8733
8734static jlong NativeCrypto_ERR_peek_last_error(JNIEnv*, jclass) {
8735    return ERR_peek_last_error();
8736}
8737
8738#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
8739#define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
8740static JNINativeMethod sNativeCryptoMethods[] = {
8741    NATIVE_METHOD(NativeCrypto, clinit, "()V"),
8742    NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
8743    NATIVE_METHOD(NativeCrypto, ENGINE_by_id, "(Ljava/lang/String;)J"),
8744    NATIVE_METHOD(NativeCrypto, ENGINE_add, "(J)I"),
8745    NATIVE_METHOD(NativeCrypto, ENGINE_init, "(J)I"),
8746    NATIVE_METHOD(NativeCrypto, ENGINE_finish, "(J)I"),
8747    NATIVE_METHOD(NativeCrypto, ENGINE_free, "(J)I"),
8748    NATIVE_METHOD(NativeCrypto, ENGINE_load_private_key, "(JLjava/lang/String;)J"),
8749    NATIVE_METHOD(NativeCrypto, ENGINE_get_id, "(J)Ljava/lang/String;"),
8750    NATIVE_METHOD(NativeCrypto, ENGINE_ctrl_cmd_string, "(JLjava/lang/String;Ljava/lang/String;I)I"),
8751    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DH, "([B[B[B[B)J"),
8752    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)J"),
8753    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
8754    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_EC_KEY, "(JJ[B)J"),
8755    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_mac_key, "(I[B)J"),
8756    NATIVE_METHOD(NativeCrypto, EVP_PKEY_type, "(J)I"),
8757    NATIVE_METHOD(NativeCrypto, EVP_PKEY_size, "(J)I"),
8758    NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_public, "(J)Ljava/lang/String;"),
8759    NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_private, "(J)Ljava/lang/String;"),
8760    NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(J)V"),
8761    NATIVE_METHOD(NativeCrypto, EVP_PKEY_cmp, "(JJ)I"),
8762    NATIVE_METHOD(NativeCrypto, i2d_PKCS8_PRIV_KEY_INFO, "(J)[B"),
8763    NATIVE_METHOD(NativeCrypto, d2i_PKCS8_PRIV_KEY_INFO, "([B)J"),
8764    NATIVE_METHOD(NativeCrypto, i2d_PUBKEY, "(J)[B"),
8765    NATIVE_METHOD(NativeCrypto, d2i_PUBKEY, "([B)J"),
8766    NATIVE_METHOD(NativeCrypto, RSA_generate_key_ex, "(I[B)J"),
8767    NATIVE_METHOD(NativeCrypto, RSA_size, "(J)I"),
8768    NATIVE_METHOD(NativeCrypto, RSA_private_encrypt, "(I[B[BJI)I"),
8769    NATIVE_METHOD(NativeCrypto, RSA_public_decrypt, "(I[B[BJI)I"),
8770    NATIVE_METHOD(NativeCrypto, RSA_public_encrypt, "(I[B[BJI)I"),
8771    NATIVE_METHOD(NativeCrypto, RSA_private_decrypt, "(I[B[BJI)I"),
8772    NATIVE_METHOD(NativeCrypto, get_RSA_private_params, "(J)[[B"),
8773    NATIVE_METHOD(NativeCrypto, get_RSA_public_params, "(J)[[B"),
8774    NATIVE_METHOD(NativeCrypto, DSA_generate_key, "(I[B[B[B[B)J"),
8775    NATIVE_METHOD(NativeCrypto, get_DSA_params, "(J)[[B"),
8776    NATIVE_METHOD(NativeCrypto, set_DSA_flag_nonce_from_hash, "(J)V"),
8777    NATIVE_METHOD(NativeCrypto, DH_generate_key, "(II)J"),
8778    NATIVE_METHOD(NativeCrypto, get_DH_params, "(J)[[B"),
8779    NATIVE_METHOD(NativeCrypto, EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
8780    NATIVE_METHOD(NativeCrypto, EC_GROUP_new_curve, "(I[B[B[B)J"),
8781    NATIVE_METHOD(NativeCrypto, EC_GROUP_dup, "(J)J"),
8782    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_asn1_flag, "(JI)V"),
8783    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_point_conversion_form, "(JI)V"),
8784    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(J)Ljava/lang/String;"),
8785    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(J)[[B"),
8786    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(J)[B"),
8787    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(J)I"),
8788    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(J)[B"),
8789    NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
8790    NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(JJ)Z"),
8791    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_generator, "(J)J"),
8792    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_generator, "(JJ[B[B)V"),
8793    NATIVE_METHOD(NativeCrypto, get_EC_GROUP_type, "(J)I"),
8794    NATIVE_METHOD(NativeCrypto, EC_POINT_new, "(J)J"),
8795    NATIVE_METHOD(NativeCrypto, EC_POINT_clear_free, "(J)V"),
8796    NATIVE_METHOD(NativeCrypto, EC_POINT_cmp, "(JJJ)Z"),
8797    NATIVE_METHOD(NativeCrypto, EC_POINT_set_affine_coordinates, "(JJ[B[B)V"),
8798    NATIVE_METHOD(NativeCrypto, EC_POINT_get_affine_coordinates, "(JJ)[[B"),
8799    NATIVE_METHOD(NativeCrypto, EC_KEY_generate_key, "(J)J"),
8800    NATIVE_METHOD(NativeCrypto, EC_KEY_get0_group, "(J)J"),
8801    NATIVE_METHOD(NativeCrypto, EC_KEY_get_private_key, "(J)[B"),
8802    NATIVE_METHOD(NativeCrypto, EC_KEY_get_public_key, "(J)J"),
8803    NATIVE_METHOD(NativeCrypto, EC_KEY_set_nonce_from_hash, "(JZ)V"),
8804    NATIVE_METHOD(NativeCrypto, ECDH_compute_key, "([BIJJ)I"),
8805    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()J"),
8806    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_init, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)V"),
8807    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(J)V"),
8808    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_copy, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)I"),
8809    NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
8810    NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
8811    NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BI)I"),
8812    NATIVE_METHOD(NativeCrypto, EVP_get_digestbyname, "(Ljava/lang/String;)J"),
8813    NATIVE_METHOD(NativeCrypto, EVP_MD_block_size, "(J)I"),
8814    NATIVE_METHOD(NativeCrypto, EVP_MD_size, "(J)I"),
8815    NATIVE_METHOD(NativeCrypto, EVP_SignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
8816    NATIVE_METHOD(NativeCrypto, EVP_SignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
8817    NATIVE_METHOD(NativeCrypto, EVP_SignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIJ)I"),
8818    NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
8819    NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
8820    NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIIJ)I"),
8821    NATIVE_METHOD(NativeCrypto, EVP_DigestSignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;JJ)V"),
8822    NATIVE_METHOD(NativeCrypto, EVP_DigestSignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[B)V"),
8823    NATIVE_METHOD(NativeCrypto, EVP_DigestSignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)[B"),
8824    NATIVE_METHOD(NativeCrypto, EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
8825    NATIVE_METHOD(NativeCrypto, EVP_CipherInit_ex, "(JJ[B[BZ)V"),
8826    NATIVE_METHOD(NativeCrypto, EVP_CipherUpdate, "(J[BI[BII)I"),
8827    NATIVE_METHOD(NativeCrypto, EVP_CipherFinal_ex, "(J[BI)I"),
8828    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_iv_length, "(J)I"),
8829    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_new, "()J"),
8830    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_block_size, "(J)I"),
8831    NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_buf_len, "(J)I"),
8832    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_padding, "(JZ)V"),
8833    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_key_length, "(JI)V"),
8834    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_cleanup, "(J)V"),
8835    NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
8836    NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
8837    NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"),
8838    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
8839    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
8840    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
8841    NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
8842    NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
8843    NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
8844    NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
8845    NATIVE_METHOD(NativeCrypto, BIO_free_all, "(J)V"),
8846    NATIVE_METHOD(NativeCrypto, X509_NAME_print_ex, "(JJ)Ljava/lang/String;"),
8847    NATIVE_METHOD(NativeCrypto, d2i_X509_bio, "(J)J"),
8848    NATIVE_METHOD(NativeCrypto, d2i_X509, "([B)J"),
8849    NATIVE_METHOD(NativeCrypto, i2d_X509, "(J)[B"),
8850    NATIVE_METHOD(NativeCrypto, i2d_X509_PUBKEY, "(J)[B"),
8851    NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509, "(J)J"),
8852    NATIVE_METHOD(NativeCrypto, PEM_read_bio_PKCS7, "(JI)[J"),
8853    NATIVE_METHOD(NativeCrypto, d2i_PKCS7_bio, "(JI)[J"),
8854    NATIVE_METHOD(NativeCrypto, i2d_PKCS7, "([J)[B"),
8855    NATIVE_METHOD(NativeCrypto, ASN1_seq_unpack_X509_bio, "(J)[J"),
8856    NATIVE_METHOD(NativeCrypto, ASN1_seq_pack_X509, "([J)[B"),
8857    NATIVE_METHOD(NativeCrypto, X509_free, "(J)V"),
8858    NATIVE_METHOD(NativeCrypto, X509_cmp, "(JJ)I"),
8859    NATIVE_METHOD(NativeCrypto, get_X509_hashCode, "(J)I"),
8860    NATIVE_METHOD(NativeCrypto, X509_print_ex, "(JJJJ)V"),
8861    NATIVE_METHOD(NativeCrypto, X509_get_pubkey, "(J)J"),
8862    NATIVE_METHOD(NativeCrypto, X509_get_issuer_name, "(J)[B"),
8863    NATIVE_METHOD(NativeCrypto, X509_get_subject_name, "(J)[B"),
8864    NATIVE_METHOD(NativeCrypto, get_X509_pubkey_oid, "(J)Ljava/lang/String;"),
8865    NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_oid, "(J)Ljava/lang/String;"),
8866    NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_parameter, "(J)[B"),
8867    NATIVE_METHOD(NativeCrypto, get_X509_issuerUID, "(J)[Z"),
8868    NATIVE_METHOD(NativeCrypto, get_X509_subjectUID, "(J)[Z"),
8869    NATIVE_METHOD(NativeCrypto, get_X509_ex_kusage, "(J)[Z"),
8870    NATIVE_METHOD(NativeCrypto, get_X509_ex_xkusage, "(J)[Ljava/lang/String;"),
8871    NATIVE_METHOD(NativeCrypto, get_X509_ex_pathlen, "(J)I"),
8872    NATIVE_METHOD(NativeCrypto, X509_get_ext_oid, "(JLjava/lang/String;)[B"),
8873    NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext_oid, "(JLjava/lang/String;)[B"),
8874    NATIVE_METHOD(NativeCrypto, get_X509_CRL_crl_enc, "(J)[B"),
8875    NATIVE_METHOD(NativeCrypto, X509_CRL_verify, "(JJ)V"),
8876    NATIVE_METHOD(NativeCrypto, X509_CRL_get_lastUpdate, "(J)J"),
8877    NATIVE_METHOD(NativeCrypto, X509_CRL_get_nextUpdate, "(J)J"),
8878    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
8879    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_serialNumber, "(J)[B"),
8880    NATIVE_METHOD(NativeCrypto, X509_REVOKED_print, "(JJ)V"),
8881    NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_revocationDate, "(J)J"),
8882    NATIVE_METHOD(NativeCrypto, get_X509_ext_oids, "(JI)[Ljava/lang/String;"),
8883    NATIVE_METHOD(NativeCrypto, get_X509_CRL_ext_oids, "(JI)[Ljava/lang/String;"),
8884    NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
8885    NATIVE_METHOD(NativeCrypto, get_X509_GENERAL_NAME_stack, "(JI)[[Ljava/lang/Object;"),
8886    NATIVE_METHOD(NativeCrypto, X509_get_notBefore, "(J)J"),
8887    NATIVE_METHOD(NativeCrypto, X509_get_notAfter, "(J)J"),
8888    NATIVE_METHOD(NativeCrypto, X509_get_version, "(J)J"),
8889    NATIVE_METHOD(NativeCrypto, X509_get_serialNumber, "(J)[B"),
8890    NATIVE_METHOD(NativeCrypto, X509_verify, "(JJ)V"),
8891    NATIVE_METHOD(NativeCrypto, get_X509_cert_info_enc, "(J)[B"),
8892    NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
8893    NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
8894    NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
8895    NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
8896    NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
8897    NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
8898    NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
8899    NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_serial, "(J[B)J"),
8900    NATIVE_METHOD(NativeCrypto, X509_CRL_get_REVOKED, "(J)[J"),
8901    NATIVE_METHOD(NativeCrypto, i2d_X509_CRL, "(J)[B"),
8902    NATIVE_METHOD(NativeCrypto, X509_CRL_free, "(J)V"),
8903    NATIVE_METHOD(NativeCrypto, X509_CRL_print, "(JJ)V"),
8904    NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_oid, "(J)Ljava/lang/String;"),
8905    NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_parameter, "(J)[B"),
8906    NATIVE_METHOD(NativeCrypto, X509_CRL_get_issuer_name, "(J)[B"),
8907    NATIVE_METHOD(NativeCrypto, X509_CRL_get_version, "(J)J"),
8908    NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext, "(JLjava/lang/String;)J"),
8909    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
8910    NATIVE_METHOD(NativeCrypto, X509_REVOKED_dup, "(J)J"),
8911    NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
8912    NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
8913    NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
8914    NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
8915    NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
8916    NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),
8917    NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
8918    NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
8919    NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
8920    NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
8921    NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
8922    NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[J)V"),
8923    NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
8924    NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
8925    NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(J)J"),
8926    NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(JJ)J"),
8927    NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(JJ)J"),
8928    NATIVE_METHOD(NativeCrypto, SSL_get_options, "(J)J"),
8929    NATIVE_METHOD(NativeCrypto, SSL_set_options, "(JJ)J"),
8930    NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(JJ)J"),
8931    NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(J[Ljava/lang/String;)V"),
8932    NATIVE_METHOD(NativeCrypto, SSL_get_ciphers, "(J)[J"),
8933    NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_auth, "(J)I"),
8934    NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_mkey, "(J)I"),
8935    NATIVE_METHOD(NativeCrypto, SSL_set_accept_state, "(J)V"),
8936    NATIVE_METHOD(NativeCrypto, SSL_set_connect_state, "(J)V"),
8937    NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(JI)V"),
8938    NATIVE_METHOD(NativeCrypto, SSL_set_session, "(JJ)V"),
8939    NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
8940    NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
8941    NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
8942    NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)J"),
8943    NATIVE_METHOD(NativeCrypto, SSL_do_handshake_bio, "(JJJ" SSL_CALLBACKS "Z[B[B)J"),
8944    NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
8945    NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[J"),
8946    NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[J"),
8947    NATIVE_METHOD(NativeCrypto, SSL_read, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
8948    NATIVE_METHOD(NativeCrypto, SSL_read_BIO, "(J[BJJ" SSL_CALLBACKS ")I"),
8949    NATIVE_METHOD(NativeCrypto, SSL_write, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
8950    NATIVE_METHOD(NativeCrypto, SSL_write_BIO, "(J[BIJ" SSL_CALLBACKS ")I"),
8951    NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(J)V"),
8952    NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(J" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
8953    NATIVE_METHOD(NativeCrypto, SSL_shutdown_BIO, "(JJJ" SSL_CALLBACKS ")V"),
8954    NATIVE_METHOD(NativeCrypto, SSL_get_shutdown, "(J)I"),
8955    NATIVE_METHOD(NativeCrypto, SSL_free, "(J)V"),
8956    NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(J)[B"),
8957    NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(J)J"),
8958    NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
8959    NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
8960    NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(J)V"),
8961    NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(J)[B"),
8962    NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)J"),
8963    NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
8964    NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
8965    NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
8966    NATIVE_METHOD(NativeCrypto, SSL_set_alpn_protos, "(J[B)I"),
8967    NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
8968    NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
8969};
8970
8971static jclass getGlobalRefToClass(JNIEnv* env, const char* className) {
8972    ScopedLocalRef<jclass> localClass(env, env->FindClass(className));
8973    jclass globalRef = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
8974    if (globalRef == NULL) {
8975        ALOGE("failed to find class %s", className);
8976        abort();
8977    }
8978    return globalRef;
8979}
8980
8981static void initialize_conscrypt(JNIEnv* env) {
8982    jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
8983                             sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
8984
8985    openSslNativeReferenceClass = getGlobalRefToClass(env,
8986            TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLNativeReference");
8987    openSslOutputStreamClass = getGlobalRefToClass(env,
8988            TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream");
8989
8990    openSslNativeReference_context = env->GetFieldID(openSslNativeReferenceClass, "context", "J");
8991
8992    calendar_setMethod = env->GetMethodID(calendarClass, "set", "(IIIIII)V");
8993    inputStream_readMethod = env->GetMethodID(inputStreamClass, "read", "([B)I");
8994    integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
8995            "(I)Ljava/lang/Integer;");
8996    openSslInputStream_readLineMethod = env->GetMethodID(openSslOutputStreamClass, "gets",
8997            "([B)I");
8998    outputStream_writeMethod = env->GetMethodID(outputStreamClass, "write", "([B)V");
8999    outputStream_flushMethod = env->GetMethodID(outputStreamClass, "flush", "()V");
9000
9001#ifdef CONSCRYPT_UNBUNDLED
9002    findAsynchronousCloseMonitorFuncs();
9003#endif
9004}
9005
9006static jclass findClass(JNIEnv* env, const char* name) {
9007    ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
9008    jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
9009    if (result == NULL) {
9010        ALOGE("failed to find class '%s'", name);
9011        abort();
9012    }
9013    return result;
9014}
9015
9016// Use JNI_OnLoad for when we're standalone
9017int JNI_OnLoad(JavaVM *vm, void*) {
9018    JNI_TRACE("JNI_OnLoad NativeCrypto");
9019    gJavaVM = vm;
9020
9021    JNIEnv *env;
9022    if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
9023        ALOGE("Could not get JNIEnv");
9024        return JNI_ERR;
9025    }
9026
9027    byteArrayClass = findClass(env, "[B");
9028    calendarClass = findClass(env, "java/util/Calendar");
9029    inputStreamClass = findClass(env, "java/io/InputStream");
9030    integerClass = findClass(env, "java/lang/Integer");
9031    objectClass = findClass(env, "java/lang/Object");
9032    objectArrayClass = findClass(env, "[Ljava/lang/Object;");
9033    outputStreamClass = findClass(env, "java/io/OutputStream");
9034    stringClass = findClass(env, "java/lang/String");
9035
9036    initialize_conscrypt(env);
9037    return JNI_VERSION_1_6;
9038}
9039