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