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_free(JNIEnv*, jclass, jlong ctxRef) {
4586    EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4587    JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
4588
4589    EVP_CIPHER_CTX_free(ctx);
4590}
4591
4592/**
4593 * public static native void RAND_seed(byte[]);
4594 */
4595static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) {
4596    JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed);
4597    ScopedByteArrayRO randseed(env, seed);
4598    if (randseed.get() == NULL) {
4599        return;
4600    }
4601    RAND_seed(randseed.get(), randseed.size());
4602}
4603
4604static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) {
4605    JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, max_bytes);
4606    ScopedUtfChars file(env, filename);
4607    if (file.c_str() == NULL) {
4608        return -1;
4609    }
4610    int result = RAND_load_file(file.c_str(), max_bytes);
4611    JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result);
4612    return result;
4613}
4614
4615static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4616    JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4617
4618    ScopedByteArrayRW outputBytes(env, output);
4619    if (outputBytes.get() == NULL) {
4620        return;
4621    }
4622
4623    unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4624    if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4625        throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes");
4626        JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4627        return;
4628    }
4629
4630    JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4631}
4632
4633static jint NativeCrypto_OBJ_txt2nid(JNIEnv* env, jclass, jstring oidStr) {
4634    JNI_TRACE("OBJ_txt2nid(%p)", oidStr);
4635
4636    ScopedUtfChars oid(env, oidStr);
4637    if (oid.c_str() == NULL) {
4638        return 0;
4639    }
4640
4641    int nid = OBJ_txt2nid(oid.c_str());
4642    JNI_TRACE("OBJ_txt2nid(%s) => %d", oid.c_str(), nid);
4643    return nid;
4644}
4645
4646static jstring NativeCrypto_OBJ_txt2nid_longName(JNIEnv* env, jclass, jstring oidStr) {
4647    JNI_TRACE("OBJ_txt2nid_longName(%p)", oidStr);
4648
4649    ScopedUtfChars oid(env, oidStr);
4650    if (oid.c_str() == NULL) {
4651        return NULL;
4652    }
4653
4654    JNI_TRACE("OBJ_txt2nid_longName(%s)", oid.c_str());
4655
4656    int nid = OBJ_txt2nid(oid.c_str());
4657    if (nid == NID_undef) {
4658        JNI_TRACE("OBJ_txt2nid_longName(%s) => NID_undef", oid.c_str());
4659        freeOpenSslErrorState();
4660        return NULL;
4661    }
4662
4663    const char* longName = OBJ_nid2ln(nid);
4664    JNI_TRACE("OBJ_txt2nid_longName(%s) => %s", oid.c_str(), longName);
4665    return env->NewStringUTF(longName);
4666}
4667
4668static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, ASN1_OBJECT* obj) {
4669    /*
4670     * The OBJ_obj2txt API doesn't "measure" if you pass in NULL as the buffer.
4671     * Just make a buffer that's large enough here. The documentation recommends
4672     * 80 characters.
4673     */
4674    char output[128];
4675    int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4676    if (ret < 0) {
4677        throwExceptionIfNecessary(env, "ASN1_OBJECT_to_OID_string");
4678        return NULL;
4679    } else if (size_t(ret) >= sizeof(output)) {
4680        jniThrowRuntimeException(env, "ASN1_OBJECT_to_OID_string buffer too small");
4681        return NULL;
4682    }
4683
4684    JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4685    return env->NewStringUTF(output);
4686}
4687
4688static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj) {
4689    JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4690
4691    if (streamObj == NULL) {
4692        jniThrowNullPointerException(env, "stream == null");
4693        return 0;
4694    }
4695
4696    Unique_BIO bio(BIO_new(&stream_bio_method));
4697    if (bio.get() == NULL) {
4698        return 0;
4699    }
4700
4701    bio_stream_assign(bio.get(), new BIO_InputStream(streamObj));
4702
4703    JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4704    return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4705}
4706
4707static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4708    JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4709
4710    if (streamObj == NULL) {
4711        jniThrowNullPointerException(env, "stream == null");
4712        return 0;
4713    }
4714
4715    Unique_BIO bio(BIO_new(&stream_bio_method));
4716    if (bio.get() == NULL) {
4717        return 0;
4718    }
4719
4720    bio_stream_assign(bio.get(), new BIO_OutputStream(streamObj));
4721
4722    JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4723    return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4724}
4725
4726static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
4727    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4728    JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
4729
4730    if (outputJavaBytes == NULL) {
4731        jniThrowNullPointerException(env, "output == null");
4732        JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
4733        return 0;
4734    }
4735
4736    int outputSize = env->GetArrayLength(outputJavaBytes);
4737
4738    UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
4739    if (buffer.get() == NULL) {
4740        jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
4741        return 0;
4742    }
4743
4744    int read = BIO_read(bio, buffer.get(), outputSize);
4745    if (read <= 0) {
4746        jniThrowException(env, "java/io/IOException", "BIO_read");
4747        JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
4748        return 0;
4749    }
4750
4751    env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
4752    JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
4753    return read;
4754}
4755
4756static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
4757        jint offset, jint length) {
4758    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4759    JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
4760
4761    if (inputJavaBytes == NULL) {
4762        jniThrowNullPointerException(env, "input == null");
4763        return;
4764    }
4765
4766    if (offset < 0 || length < 0) {
4767        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "offset < 0 || length < 0");
4768        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4769        return;
4770    }
4771
4772    int inputSize = env->GetArrayLength(inputJavaBytes);
4773    if (inputSize < offset + length) {
4774        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
4775                "input.length < offset + length");
4776        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4777        return;
4778    }
4779
4780    UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
4781    if (buffer.get() == NULL) {
4782        jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
4783        return;
4784    }
4785
4786    env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
4787    if (BIO_write(bio, buffer.get(), length) != length) {
4788        freeOpenSslErrorState();
4789        jniThrowException(env, "java/io/IOException", "BIO_write");
4790        JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
4791        return;
4792    }
4793
4794    JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
4795}
4796
4797static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4798    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4799    JNI_TRACE("BIO_free_all(%p)", bio);
4800
4801    if (bio == NULL) {
4802        jniThrowNullPointerException(env, "bio == null");
4803        return;
4804    }
4805
4806    BIO_free_all(bio);
4807}
4808
4809static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4810    JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4811
4812    Unique_BIO buffer(BIO_new(BIO_s_mem()));
4813    if (buffer.get() == NULL) {
4814        jniThrowOutOfMemory(env, "Unable to allocate BIO");
4815        JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4816        return NULL;
4817    }
4818
4819    /* Don't interpret the string. */
4820    flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4821
4822    /* Write in given format and null terminate. */
4823    X509_NAME_print_ex(buffer.get(), name, 0, flags);
4824    BIO_write(buffer.get(), "\0", 1);
4825
4826    char *tmp;
4827    BIO_get_mem_data(buffer.get(), &tmp);
4828    JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4829    return env->NewStringUTF(tmp);
4830}
4831
4832
4833/**
4834 * Converts GENERAL_NAME items to the output format expected in
4835 * X509Certificate#getSubjectAlternativeNames and
4836 * X509Certificate#getIssuerAlternativeNames return.
4837 */
4838static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4839    switch (gen->type) {
4840    case GEN_EMAIL:
4841    case GEN_DNS:
4842    case GEN_URI: {
4843        // This must not be a T61String and must not contain NULLs.
4844        const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
4845        ssize_t len = ASN1_STRING_length(gen->d.ia5);
4846        if ((len == static_cast<ssize_t>(strlen(data)))
4847                && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
4848            JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
4849            return env->NewStringUTF(data);
4850        } else {
4851            jniThrowException(env, "java/security/cert/CertificateParsingException",
4852                    "Invalid dNSName encoding");
4853            JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4854            return NULL;
4855        }
4856    }
4857    case GEN_DIRNAME:
4858        /* Write in RFC 2253 format */
4859        return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4860    case GEN_IPADD: {
4861        const void *ip = reinterpret_cast<const void *>(gen->d.ip->data);
4862        if (gen->d.ip->length == 4) {
4863            // IPv4
4864            UniquePtr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4865            if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != NULL) {
4866                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4867                return env->NewStringUTF(buffer.get());
4868            } else {
4869                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen, strerror(errno));
4870            }
4871        } else if (gen->d.ip->length == 16) {
4872            // IPv6
4873            UniquePtr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4874            if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != NULL) {
4875                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4876                return env->NewStringUTF(buffer.get());
4877            } else {
4878                JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno));
4879            }
4880        }
4881
4882        /* Invalid IP encodings are pruned out without throwing an exception. */
4883        return NULL;
4884    }
4885    case GEN_RID:
4886        return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4887    case GEN_OTHERNAME:
4888    case GEN_X400:
4889    default:
4890        return ASN1ToByteArray<GENERAL_NAME, i2d_GENERAL_NAME>(env, gen);
4891    }
4892
4893    return NULL;
4894}
4895
4896#define GN_STACK_SUBJECT_ALT_NAME 1
4897#define GN_STACK_ISSUER_ALT_NAME 2
4898
4899static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4900        jint type) {
4901    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4902    JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4903
4904    if (x509 == NULL) {
4905        jniThrowNullPointerException(env, "x509 == null");
4906        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4907        return NULL;
4908    }
4909
4910    X509_check_ca(x509);
4911
4912    STACK_OF(GENERAL_NAME)* gn_stack;
4913    Unique_sk_GENERAL_NAME stackHolder;
4914    if (type == GN_STACK_SUBJECT_ALT_NAME) {
4915        gn_stack = x509->altname;
4916    } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4917        stackHolder.reset(
4918                static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, NID_issuer_alt_name,
4919                        NULL, NULL)));
4920        gn_stack = stackHolder.get();
4921    } else {
4922        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4923        return NULL;
4924    }
4925
4926    int count = sk_GENERAL_NAME_num(gn_stack);
4927    if (count <= 0) {
4928        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4929        return NULL;
4930    }
4931
4932    /*
4933     * Keep track of how many originally so we can ignore any invalid
4934     * values later.
4935     */
4936    const int origCount = count;
4937
4938    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
4939    for (int i = 0, j = 0; i < origCount; i++, j++) {
4940        GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
4941        ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4942        if (env->ExceptionCheck()) {
4943            JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4944                    x509, type);
4945            return NULL;
4946        }
4947
4948        /*
4949         * If it's NULL, we'll have to skip this, reduce the number of total
4950         * entries, and fix up the array later.
4951         */
4952        if (val.get() == NULL) {
4953            j--;
4954            count--;
4955            continue;
4956        }
4957
4958        ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
4959
4960        ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
4961                integer_valueOfMethod, gen->type));
4962        env->SetObjectArrayElement(item.get(), 0, type.get());
4963        env->SetObjectArrayElement(item.get(), 1, val.get());
4964
4965        env->SetObjectArrayElement(joa.get(), j, item.get());
4966    }
4967
4968    if (count == 0) {
4969        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning NULL",
4970                x509, type, origCount);
4971        joa.reset(NULL);
4972    } else if (origCount != count) {
4973        JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
4974                origCount, count);
4975
4976        ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
4977                NULL));
4978
4979        for (int i = 0; i < count; i++) {
4980            ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4981            env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4982        }
4983
4984        joa.reset(joa_copy.release());
4985    }
4986
4987    JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4988    return joa.release();
4989}
4990
4991static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref) {
4992    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4993    JNI_TRACE("X509_get_notBefore(%p)", x509);
4994
4995    if (x509 == NULL) {
4996        jniThrowNullPointerException(env, "x509 == null");
4997        JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4998        return 0;
4999    }
5000
5001    ASN1_TIME* notBefore = X509_get_notBefore(x509);
5002    JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
5003    return reinterpret_cast<uintptr_t>(notBefore);
5004}
5005
5006static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref) {
5007    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5008    JNI_TRACE("X509_get_notAfter(%p)", x509);
5009
5010    if (x509 == NULL) {
5011        jniThrowNullPointerException(env, "x509 == null");
5012        JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
5013        return 0;
5014    }
5015
5016    ASN1_TIME* notAfter = X509_get_notAfter(x509);
5017    JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
5018    return reinterpret_cast<uintptr_t>(notAfter);
5019}
5020
5021static long NativeCrypto_X509_get_version(JNIEnv*, jclass, jlong x509Ref) {
5022    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5023    JNI_TRACE("X509_get_version(%p)", x509);
5024
5025    long version = X509_get_version(x509);
5026    JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
5027    return version;
5028}
5029
5030template<typename T>
5031static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type, ASN1_INTEGER* (*get_serial_func)(T*)) {
5032    JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
5033
5034    if (x509Type == NULL) {
5035        jniThrowNullPointerException(env, "x509Type == null");
5036        JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
5037        return NULL;
5038    }
5039
5040    ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
5041    Unique_BIGNUM serialBn(ASN1_INTEGER_to_BN(serialNumber, NULL));
5042    if (serialBn.get() == NULL) {
5043        JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5044        return NULL;
5045    }
5046
5047    ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
5048    if (env->ExceptionCheck()) {
5049        JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5050        return NULL;
5051    }
5052
5053    JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
5054    return serialArray.release();
5055}
5056
5057/* OpenSSL includes set_serialNumber but not get. */
5058#if !defined(X509_REVOKED_get_serialNumber)
5059static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) {
5060    return x->serialNumber;
5061}
5062#endif
5063
5064static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref) {
5065    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5066    JNI_TRACE("X509_get_serialNumber(%p)", x509);
5067    return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber);
5068}
5069
5070static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass, jlong x509RevokedRef) {
5071    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5072    JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5073    return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber);
5074}
5075
5076static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref, jlong pkeyRef) {
5077    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5078    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
5079    JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5080
5081    if (x509 == NULL) {
5082        jniThrowNullPointerException(env, "x509 == null");
5083        JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5084        return;
5085    }
5086
5087    if (pkey == NULL) {
5088        jniThrowNullPointerException(env, "pkey == null");
5089        JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5090        return;
5091    }
5092
5093    if (X509_verify(x509, pkey) != 1) {
5094        throwExceptionIfNecessary(env, "X509_verify");
5095        JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5096    } else {
5097        JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5098    }
5099}
5100
5101static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref) {
5102    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5103    JNI_TRACE("get_X509_cert_info_enc(%p)", x509);
5104    return ASN1ToByteArray<X509_CINF, i2d_X509_CINF>(env, x509->cert_info);
5105}
5106
5107static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) {
5108    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5109    JNI_TRACE("get_X509_ex_flags(%p)", x509);
5110
5111    if (x509 == NULL) {
5112        jniThrowNullPointerException(env, "x509 == null");
5113        JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5114        return 0;
5115    }
5116
5117    X509_check_ca(x509);
5118
5119    return x509->ex_flags;
5120}
5121
5122static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
5123    X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5124    X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5125    JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5126
5127    int ret = X509_check_issued(x509_1, x509_2);
5128    JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5129    return ret;
5130}
5131
5132static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
5133    *signature = x509->signature;
5134}
5135
5136static void get_X509_CRL_signature(X509_CRL *crl, ASN1_BIT_STRING** signature) {
5137    *signature = crl->signature;
5138}
5139
5140template<typename T>
5141static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type, void (*get_signature_func)(T*, ASN1_BIT_STRING**)) {
5142    JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5143
5144    if (x509Type == NULL) {
5145        jniThrowNullPointerException(env, "x509Type == null");
5146        JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5147        return NULL;
5148    }
5149
5150    ASN1_BIT_STRING* signature;
5151    get_signature_func(x509Type, &signature);
5152
5153    ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length));
5154    if (env->ExceptionCheck()) {
5155        JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5156        return NULL;
5157    }
5158
5159    ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5160    if (signatureBytes.get() == NULL) {
5161        JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5162        return NULL;
5163    }
5164
5165    memcpy(signatureBytes.get(), signature->data, signature->length);
5166
5167    JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5168            signature->length);
5169    return signatureArray.release();
5170}
5171
5172static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref) {
5173    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5174    JNI_TRACE("get_X509_signature(%p)", x509);
5175    return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5176}
5177
5178static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef) {
5179    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5180    JNI_TRACE("get_X509_CRL_signature(%p)", crl);
5181    return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5182}
5183
5184static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef, jlong x509Ref) {
5185    X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5186    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5187    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5188
5189    if (x509crl == NULL) {
5190        jniThrowNullPointerException(env, "x509crl == null");
5191        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5192        return 0;
5193    } else if (x509 == NULL) {
5194        jniThrowNullPointerException(env, "x509 == null");
5195        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5196        return 0;
5197    }
5198
5199    X509_REVOKED* revoked = NULL;
5200    int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5201    if (ret == 0) {
5202        JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5203        return 0;
5204    }
5205
5206    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5207    return reinterpret_cast<uintptr_t>(revoked);
5208}
5209
5210static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef, jbyteArray serialArray) {
5211    X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5212    JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5213
5214    if (x509crl == NULL) {
5215        jniThrowNullPointerException(env, "x509crl == null");
5216        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5217        return 0;
5218    }
5219
5220    Unique_BIGNUM serialBn(BN_new());
5221    if (serialBn.get() == NULL) {
5222        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
5223        return 0;
5224    }
5225
5226    BIGNUM* serialBare = serialBn.get();
5227    if (!arrayToBignum(env, serialArray, &serialBare)) {
5228        if (!env->ExceptionCheck()) {
5229            jniThrowNullPointerException(env, "serial == null");
5230        }
5231        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5232        return 0;
5233    }
5234
5235    Unique_ASN1_INTEGER serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), NULL));
5236    if (serialInteger.get() == NULL) {
5237        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5238        return 0;
5239    }
5240
5241    X509_REVOKED* revoked = NULL;
5242    int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5243    if (ret == 0) {
5244        JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5245        return 0;
5246    }
5247
5248    JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5249    return reinterpret_cast<uintptr_t>(revoked);
5250}
5251
5252
5253/* This appears to be missing from OpenSSL. */
5254#if !defined(X509_REVOKED_dup)
5255X509_REVOKED* X509_REVOKED_dup(X509_REVOKED* x) {
5256    return reinterpret_cast<X509_REVOKED*>(ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), x));
5257}
5258#endif
5259
5260static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef) {
5261    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5262    JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5263
5264    if (crl == NULL) {
5265        jniThrowNullPointerException(env, "crl == null");
5266        return NULL;
5267    }
5268
5269    STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5270    if (stack == NULL) {
5271        JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5272        return NULL;
5273    }
5274
5275    size_t size = sk_X509_REVOKED_num(stack);
5276
5277    ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(size));
5278    ScopedLongArrayRW revoked(env, revokedArray.get());
5279    for (size_t i = 0; i < size; i++) {
5280        X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5281        revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5282    }
5283
5284    JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%d]", stack, revokedArray.get(), size);
5285    return revokedArray.release();
5286}
5287
5288static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef) {
5289    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5290    JNI_TRACE("i2d_X509_CRL(%p)", crl);
5291    return ASN1ToByteArray<X509_CRL, i2d_X509_CRL>(env, crl);
5292}
5293
5294static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef) {
5295    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5296    JNI_TRACE("X509_CRL_free(%p)", crl);
5297
5298    if (crl == NULL) {
5299        jniThrowNullPointerException(env, "crl == null");
5300        JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5301        return;
5302    }
5303
5304    X509_CRL_free(crl);
5305}
5306
5307static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef) {
5308    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5309    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5310    JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5311
5312    if (bio == NULL) {
5313        jniThrowNullPointerException(env, "bio == null");
5314        JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5315        return;
5316    }
5317
5318    if (crl == NULL) {
5319        jniThrowNullPointerException(env, "crl == null");
5320        JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5321        return;
5322    }
5323
5324    if (!X509_CRL_print(bio, crl)) {
5325        throwExceptionIfNecessary(env, "X509_CRL_print");
5326        JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5327    } else {
5328        JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5329    }
5330}
5331
5332static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) {
5333    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5334    JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5335
5336    if (crl == NULL || crl->sig_alg == NULL) {
5337        jniThrowNullPointerException(env, "crl == NULL || crl->sig_alg == NULL");
5338        JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == NULL", crl);
5339        return NULL;
5340    }
5341
5342    return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm);
5343}
5344
5345static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef) {
5346    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5347    JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5348
5349    if (crl == NULL) {
5350        jniThrowNullPointerException(env, "crl == null");
5351        JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5352        return NULL;
5353    }
5354
5355    if (crl->sig_alg->parameter == NULL) {
5356        JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl);
5357        return NULL;
5358    }
5359
5360    return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, crl->sig_alg->parameter);
5361}
5362
5363static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef) {
5364    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5365    JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5366    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_CRL_get_issuer(crl));
5367}
5368
5369static long NativeCrypto_X509_CRL_get_version(JNIEnv*, jclass, jlong x509CrlRef) {
5370    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5371    JNI_TRACE("X509_CRL_get_version(%p)", crl);
5372
5373    long version = X509_CRL_get_version(crl);
5374    JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5375    return version;
5376}
5377
5378template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
5379        X509_EXTENSION* (*get_ext_func)(T*, int)>
5380static X509_EXTENSION *X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) {
5381    JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5382
5383    if (x509Type == NULL) {
5384        jniThrowNullPointerException(env, "x509 == null");
5385        return NULL;
5386    }
5387
5388    ScopedUtfChars oid(env, oidString);
5389    if (oid.c_str() == NULL) {
5390        return NULL;
5391    }
5392
5393    Unique_ASN1_OBJECT asn1(OBJ_txt2obj(oid.c_str(), 1));
5394    if (asn1.get() == NULL) {
5395        JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5396        freeOpenSslErrorState();
5397        return NULL;
5398    }
5399
5400    int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5401    if (extIndex == -1) {
5402        JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5403        return NULL;
5404    }
5405
5406    X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5407    JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5408    return ext;
5409}
5410
5411template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
5412        X509_EXTENSION* (*get_ext_func)(T*, int)>
5413static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) {
5414    X509_EXTENSION* ext = X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type,
5415            oidString);
5416    if (ext == NULL) {
5417        JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5418        return NULL;
5419    }
5420
5421    JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value);
5422    return ASN1ToByteArray<ASN1_OCTET_STRING, i2d_ASN1_OCTET_STRING>(env, ext->value);
5423}
5424
5425static jint NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef, jstring oid) {
5426    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5427    JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5428    X509_EXTENSION* ext = X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(
5429            env, crl, oid);
5430    JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5431    return reinterpret_cast<uintptr_t>(ext);
5432}
5433
5434static jint NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5435        jstring oid) {
5436    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5437    JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5438    X509_EXTENSION* ext = X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ,
5439            X509_REVOKED_get_ext>(env, revoked, oid);
5440    JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5441    return reinterpret_cast<uintptr_t>(ext);
5442}
5443
5444static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5445    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5446    JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5447
5448    if (revoked == NULL) {
5449        jniThrowNullPointerException(env, "revoked == null");
5450        JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5451        return 0;
5452    }
5453
5454    X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5455    JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5456    return reinterpret_cast<uintptr_t>(dup);
5457}
5458
5459static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass, jlong x509RevokedRef) {
5460    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5461    JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5462
5463    if (revoked == NULL) {
5464        jniThrowNullPointerException(env, "revoked == null");
5465        JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5466        return 0;
5467    }
5468
5469    JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate);
5470    return reinterpret_cast<uintptr_t>(revoked->revocationDate);
5471}
5472
5473#pragma GCC diagnostic push
5474#pragma GCC diagnostic ignored "-Wwrite-strings"
5475static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) {
5476    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5477    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5478    JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5479
5480    if (bio == NULL) {
5481        jniThrowNullPointerException(env, "bio == null");
5482        JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5483        return;
5484    }
5485
5486    if (revoked == NULL) {
5487        jniThrowNullPointerException(env, "revoked == null");
5488        JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5489        return;
5490    }
5491
5492    BIO_printf(bio, "Serial Number: ");
5493    i2a_ASN1_INTEGER(bio, revoked->serialNumber);
5494    BIO_printf(bio, "\nRevocation Date: ");
5495    ASN1_TIME_print(bio, revoked->revocationDate);
5496    BIO_printf(bio, "\n");
5497    X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
5498}
5499#pragma GCC diagnostic pop
5500
5501static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) {
5502    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5503    JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5504    return ASN1ToByteArray<X509_CRL_INFO, i2d_X509_CRL_INFO>(env, crl->crl);
5505}
5506
5507static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef, jlong pkeyRef) {
5508    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5509    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
5510    JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5511
5512    if (crl == NULL) {
5513        jniThrowNullPointerException(env, "crl == null");
5514        JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5515        return;
5516    }
5517
5518    if (pkey == NULL) {
5519        jniThrowNullPointerException(env, "pkey == null");
5520        JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5521        return;
5522    }
5523
5524    if (X509_CRL_verify(crl, pkey) != 1) {
5525        throwExceptionIfNecessary(env, "X509_CRL_verify");
5526        JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5527    } else {
5528        JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5529    }
5530}
5531
5532static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
5533    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5534    JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5535
5536    if (crl == NULL) {
5537        jniThrowNullPointerException(env, "crl == null");
5538        JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5539        return 0;
5540    }
5541
5542    ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5543    JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5544    return reinterpret_cast<uintptr_t>(lastUpdate);
5545}
5546
5547static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
5548    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5549    JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5550
5551    if (crl == NULL) {
5552        jniThrowNullPointerException(env, "crl == null");
5553        JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5554        return 0;
5555    }
5556
5557    ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5558    JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5559    return reinterpret_cast<uintptr_t>(nextUpdate);
5560}
5561
5562static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5563    X509_REVOKED* x509Revoked =
5564            reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5565    JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5566    return ASN1ToByteArray<X509_REVOKED, i2d_X509_REVOKED>(env, x509Revoked);
5567}
5568
5569static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5570    X509_EXTENSION* ext = reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5571
5572    if (ext == NULL) {
5573        jniThrowNullPointerException(env, "ext == NULL");
5574        return 0;
5575    }
5576
5577    return X509_supported_extension(ext);
5578}
5579
5580static inline void get_ASN1_TIME_data(char **data, int* output, size_t len) {
5581    char c = **data;
5582    **data = '\0';
5583    *data -= len;
5584    *output = atoi(*data);
5585    *(*data + len) = c;
5586}
5587
5588static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef, jobject calendar) {
5589    ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5590    JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5591
5592    if (asn1Time == NULL) {
5593        jniThrowNullPointerException(env, "asn1Time == null");
5594        return;
5595    }
5596
5597    Unique_ASN1_GENERALIZEDTIME gen(ASN1_TIME_to_generalizedtime(asn1Time, NULL));
5598    if (gen.get() == NULL) {
5599        jniThrowNullPointerException(env, "asn1Time == null");
5600        return;
5601    }
5602
5603    if (gen->length < 14 || gen->data == NULL) {
5604        jniThrowNullPointerException(env, "gen->length < 14 || gen->data == NULL");
5605        return;
5606    }
5607
5608    int sec, min, hour, mday, mon, year;
5609
5610    char *p = (char*) &gen->data[14];
5611
5612    get_ASN1_TIME_data(&p, &sec, 2);
5613    get_ASN1_TIME_data(&p, &min, 2);
5614    get_ASN1_TIME_data(&p, &hour, 2);
5615    get_ASN1_TIME_data(&p, &mday, 2);
5616    get_ASN1_TIME_data(&p, &mon, 2);
5617    get_ASN1_TIME_data(&p, &year, 4);
5618
5619    env->CallVoidMethod(calendar, calendar_setMethod, year, mon - 1, mday, hour, min, sec);
5620}
5621
5622static jstring NativeCrypto_OBJ_txt2nid_oid(JNIEnv* env, jclass, jstring oidStr) {
5623    JNI_TRACE("OBJ_txt2nid_oid(%p)", oidStr);
5624
5625    ScopedUtfChars oid(env, oidStr);
5626    if (oid.c_str() == NULL) {
5627        return NULL;
5628    }
5629
5630    JNI_TRACE("OBJ_txt2nid_oid(%s)", oid.c_str());
5631
5632    int nid = OBJ_txt2nid(oid.c_str());
5633    if (nid == NID_undef) {
5634        JNI_TRACE("OBJ_txt2nid_oid(%s) => NID_undef", oid.c_str());
5635        freeOpenSslErrorState();
5636        return NULL;
5637    }
5638
5639    Unique_ASN1_OBJECT obj(OBJ_nid2obj(nid));
5640    if (obj.get() == NULL) {
5641        throwExceptionIfNecessary(env, "OBJ_nid2obj");
5642        return NULL;
5643    }
5644
5645    ScopedLocalRef<jstring> ouputStr(env, ASN1_OBJECT_to_OID_string(env, obj.get()));
5646    JNI_TRACE("OBJ_txt2nid_oid(%s) => %p", oid.c_str(), ouputStr.get());
5647    return ouputStr.release();
5648}
5649
5650static jstring NativeCrypto_X509_NAME_print_ex(JNIEnv* env, jclass, jlong x509NameRef, jlong jflags) {
5651    X509_NAME* x509name = reinterpret_cast<X509_NAME*>(static_cast<uintptr_t>(x509NameRef));
5652    unsigned long flags = static_cast<unsigned long>(jflags);
5653    JNI_TRACE("X509_NAME_print_ex(%p, %ld)", x509name, flags);
5654
5655    if (x509name == NULL) {
5656        jniThrowNullPointerException(env, "x509name == null");
5657        JNI_TRACE("X509_NAME_print_ex(%p, %ld) => x509name == null", x509name, flags);
5658        return NULL;
5659    }
5660
5661    return X509_NAME_to_jstring(env, x509name, flags);
5662}
5663
5664template <typename T, T* (*d2i_func)(BIO*, T**)>
5665static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5666    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5667    JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5668
5669    if (bio == NULL) {
5670        jniThrowNullPointerException(env, "bio == null");
5671        return 0;
5672    }
5673
5674    T* x = d2i_func(bio, NULL);
5675    if (x == NULL) {
5676        throwExceptionIfNecessary(env, "d2i_ASN1Object_to_jlong");
5677        return 0;
5678    }
5679
5680    return reinterpret_cast<uintptr_t>(x);
5681}
5682
5683static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5684    return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5685}
5686
5687static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5688    return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5689}
5690
5691static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5692    X509* x = ByteArrayToASN1<X509, d2i_X509>(env, certBytes);
5693    return reinterpret_cast<uintptr_t>(x);
5694}
5695
5696static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref) {
5697    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5698    JNI_TRACE("i2d_X509(%p)", x509);
5699    return ASN1ToByteArray<X509, i2d_X509>(env, x509);
5700}
5701
5702static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref) {
5703    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5704    JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5705    return ASN1ToByteArray<X509_PUBKEY, i2d_X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509));
5706}
5707
5708
5709template<typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
5710static jlong PEM_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5711    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5712    JNI_TRACE("PEM_ASN1Object_to_jlong(%p)", bio);
5713
5714    if (bio == NULL) {
5715        jniThrowNullPointerException(env, "bio == null");
5716        JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => bio == null", bio);
5717        return 0;
5718    }
5719
5720    T* x = PEM_read_func(bio, NULL, NULL, NULL);
5721    if (x == NULL) {
5722        throwExceptionIfNecessary(env, "PEM_ASN1Object_to_jlong");
5723        // Sometimes the PEM functions fail without pushing an error
5724        if (!env->ExceptionCheck()) {
5725            jniThrowRuntimeException(env, "Failure parsing PEM");
5726        }
5727        JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => threw exception", bio);
5728        return 0;
5729    }
5730
5731    JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => %p", bio, x);
5732    return reinterpret_cast<uintptr_t>(x);
5733}
5734
5735static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5736    JNI_TRACE("PEM_read_bio_X509(0x%llx)", bioRef);
5737    return PEM_ASN1Object_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5738}
5739
5740static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5741    JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", bioRef);
5742    return PEM_ASN1Object_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5743}
5744
5745static STACK_OF(X509)* PKCS7_get_certs(PKCS7* pkcs7) {
5746    if (PKCS7_type_is_signed(pkcs7)) {
5747        return pkcs7->d.sign->cert;
5748    } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5749        return pkcs7->d.signed_and_enveloped->cert;
5750    } else {
5751        JNI_TRACE("PKCS7_get_certs(%p) => unknown PKCS7 type", pkcs7);
5752        return NULL;
5753    }
5754}
5755
5756static STACK_OF(X509_CRL)* PKCS7_get_CRLs(PKCS7* pkcs7) {
5757    if (PKCS7_type_is_signed(pkcs7)) {
5758        return pkcs7->d.sign->crl;
5759    } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5760        return pkcs7->d.signed_and_enveloped->crl;
5761    } else {
5762        JNI_TRACE("PKCS7_get_CRLs(%p) => unknown PKCS7 type", pkcs7);
5763        return NULL;
5764    }
5765}
5766
5767template <typename T, typename T_stack>
5768static jlongArray PKCS7_to_ItemArray(JNIEnv* env, T_stack* stack, T* (*dup_func)(T*))
5769{
5770    if (stack == NULL) {
5771        return NULL;
5772    }
5773
5774    ScopedLocalRef<jlongArray> ref_array(env, NULL);
5775    size_t size = sk_num(reinterpret_cast<_STACK*>(stack));
5776    ref_array.reset(env->NewLongArray(size));
5777    ScopedLongArrayRW items(env, ref_array.get());
5778    for (size_t i = 0; i < size; i++) {
5779        T* item = reinterpret_cast<T*>(sk_value(reinterpret_cast<_STACK*>(stack), i));
5780        items[i] = reinterpret_cast<uintptr_t>(dup_func(item));
5781    }
5782
5783    JNI_TRACE("PKCS7_to_ItemArray(%p) => %p [size=%d]", stack, ref_array.get(), size);
5784    return ref_array.release();
5785}
5786
5787#define PKCS7_CERTS 1
5788#define PKCS7_CRLS 2
5789
5790static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5791    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5792    JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5793
5794    if (bio == NULL) {
5795        jniThrowNullPointerException(env, "bio == null");
5796        JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5797        return 0;
5798    }
5799
5800    Unique_PKCS7 pkcs7(PEM_read_bio_PKCS7(bio, NULL, NULL, NULL));
5801    if (pkcs7.get() == NULL) {
5802        throwExceptionIfNecessary(env, "PEM_read_bio_PKCS7_CRLs");
5803        JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => threw exception", bio);
5804        return 0;
5805    }
5806
5807    switch (which) {
5808    case PKCS7_CERTS:
5809        return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5810    case PKCS7_CRLS:
5811        return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5812                X509_CRL_dup);
5813    default:
5814        jniThrowRuntimeException(env, "unknown PKCS7 field");
5815        return NULL;
5816    }
5817}
5818
5819static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5820    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5821    JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5822
5823    if (bio == NULL) {
5824        jniThrowNullPointerException(env, "bio == null");
5825        JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5826        return 0;
5827    }
5828
5829    Unique_PKCS7 pkcs7(d2i_PKCS7_bio(bio, NULL));
5830    if (pkcs7.get() == NULL) {
5831        throwExceptionIfNecessary(env, "d2i_PKCS7_bio");
5832        JNI_TRACE("d2i_PKCS7_bio(%p, %d) => threw exception", bio, which);
5833        return 0;
5834    }
5835
5836    switch (which) {
5837    case PKCS7_CERTS:
5838        return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5839    case PKCS7_CRLS:
5840        return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5841                X509_CRL_dup);
5842    default:
5843        jniThrowRuntimeException(env, "unknown PKCS7 field");
5844        return NULL;
5845    }
5846}
5847
5848static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5849    JNI_TRACE("i2d_PKCS7(%p)", certsArray);
5850
5851    Unique_PKCS7 pkcs7(PKCS7_new());
5852    if (pkcs7.get() == NULL) {
5853        jniThrowNullPointerException(env, "pkcs7 == null");
5854        JNI_TRACE("i2d_PKCS7(%p) => pkcs7 == null", certsArray);
5855        return NULL;
5856    }
5857
5858    if (PKCS7_set_type(pkcs7.get(), NID_pkcs7_signed) != 1) {
5859        throwExceptionIfNecessary(env, "PKCS7_set_type");
5860        return NULL;
5861    }
5862
5863    // The EncapsulatedContentInfo must be present in the output, but OpenSSL
5864    // will fill in a zero-length OID if you don't call PKCS7_set_content on the
5865    // outer PKCS7 container. So we construct an empty PKCS7 data container and
5866    // set it as the content.
5867    Unique_PKCS7 pkcs7Data(PKCS7_new());
5868    if (PKCS7_set_type(pkcs7Data.get(), NID_pkcs7_data) != 1) {
5869        throwExceptionIfNecessary(env, "PKCS7_set_type data");
5870        return NULL;
5871    }
5872
5873    if (PKCS7_set_content(pkcs7.get(), pkcs7Data.get()) != 1) {
5874        throwExceptionIfNecessary(env, "PKCS7_set_content");
5875        return NULL;
5876    }
5877    OWNERSHIP_TRANSFERRED(pkcs7Data);
5878
5879    ScopedLongArrayRO certs(env, certsArray);
5880    for (size_t i = 0; i < certs.size(); i++) {
5881        X509* item = reinterpret_cast<X509*>(certs[i]);
5882        if (PKCS7_add_certificate(pkcs7.get(), item) != 1) {
5883            throwExceptionIfNecessary(env, "i2d_PKCS7");
5884            return NULL;
5885        }
5886    }
5887
5888    JNI_TRACE("i2d_PKCS7(%p) => %d certs", certsArray, certs.size());
5889    return ASN1ToByteArray<PKCS7, i2d_PKCS7>(env, pkcs7.get());
5890}
5891
5892typedef STACK_OF(X509) PKIPATH;
5893
5894ASN1_ITEM_TEMPLATE(PKIPATH) =
5895    ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PkiPath, X509)
5896ASN1_ITEM_TEMPLATE_END(PKIPATH)
5897
5898static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5899    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5900    JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5901
5902    Unique_sk_X509 path((PKIPATH*) ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKIPATH), bio, NULL));
5903    if (path.get() == NULL) {
5904        throwExceptionIfNecessary(env, "ASN1_seq_unpack_X509_bio");
5905        return NULL;
5906    }
5907
5908    size_t size = sk_X509_num(path.get());
5909
5910    ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(size));
5911    ScopedLongArrayRW certs(env, certArray.get());
5912    for (size_t i = 0; i < size; i++) {
5913        X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5914        certs[i] = reinterpret_cast<uintptr_t>(item);
5915    }
5916
5917    JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %d items", bio, size);
5918    return certArray.release();
5919}
5920
5921static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5922    JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5923    ScopedLongArrayRO certsArray(env, certs);
5924    if (certsArray.get() == NULL) {
5925        JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5926        return NULL;
5927    }
5928
5929    Unique_sk_X509 certStack(sk_X509_new_null());
5930    if (certStack.get() == NULL) {
5931        JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to make cert stack", certs);
5932        return NULL;
5933    }
5934
5935    for (size_t i = 0; i < certsArray.size(); i++) {
5936        X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5937        sk_X509_push(certStack.get(), X509_dup_nocopy(x509));
5938    }
5939
5940    int len;
5941    Unique_OPENSSL_str encoded(ASN1_seq_pack(
5942                    reinterpret_cast<STACK_OF(OPENSSL_BLOCK)*>(
5943                            reinterpret_cast<uintptr_t>(certStack.get())),
5944                    reinterpret_cast<int (*)(void*, unsigned char**)>(i2d_X509), NULL, &len));
5945    if (encoded.get() == NULL) {
5946        JNI_TRACE("ASN1_seq_pack_X509(%p) => trouble encoding", certs);
5947        return NULL;
5948    }
5949
5950    ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
5951    if (byteArray.get() == NULL) {
5952        JNI_TRACE("ASN1_seq_pack_X509(%p) => creating byte array failed", certs);
5953        return NULL;
5954    }
5955
5956    ScopedByteArrayRW bytes(env, byteArray.get());
5957    if (bytes.get() == NULL) {
5958        JNI_TRACE("ASN1_seq_pack_X509(%p) => using byte array failed", certs);
5959        return NULL;
5960    }
5961
5962    unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
5963    memcpy(p, encoded.get(), len);
5964
5965    return byteArray.release();
5966}
5967
5968static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref) {
5969    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5970    JNI_TRACE("X509_free(%p)", x509);
5971
5972    if (x509 == NULL) {
5973        jniThrowNullPointerException(env, "x509 == null");
5974        JNI_TRACE("X509_free(%p) => x509 == null", x509);
5975        return;
5976    }
5977
5978    X509_free(x509);
5979}
5980
5981static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1, jlong x509Ref2) {
5982    X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5983    X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5984    JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5985
5986    if (x509_1 == NULL) {
5987        jniThrowNullPointerException(env, "x509_1 == null");
5988        JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5989        return -1;
5990    }
5991
5992    if (x509_2 == NULL) {
5993        jniThrowNullPointerException(env, "x509_2 == null");
5994        JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5995        return -1;
5996    }
5997
5998    int ret = X509_cmp(x509_1, x509_2);
5999    JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6000    return ret;
6001}
6002
6003static jint NativeCrypto_get_X509_hashCode(JNIEnv* env, jclass, jlong x509Ref) {
6004    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6005
6006    if (x509 == NULL) {
6007        jniThrowNullPointerException(env, "x509 == null");
6008        JNI_TRACE("get_X509_hashCode(%p) => x509 == null", x509);
6009        return 0;
6010    }
6011
6012    // Force caching extensions.
6013    X509_check_ca(x509);
6014
6015    jint hashCode = 0L;
6016    for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
6017        hashCode = 31 * hashCode + x509->sha1_hash[i];
6018    }
6019    return hashCode;
6020}
6021
6022static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6023        jlong nmflagJava, jlong certflagJava) {
6024    BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6025    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6026    long nmflag = static_cast<long>(nmflagJava);
6027    long certflag = static_cast<long>(certflagJava);
6028    JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6029
6030    if (bio == NULL) {
6031        jniThrowNullPointerException(env, "bio == null");
6032        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6033        return;
6034    }
6035
6036    if (x509 == NULL) {
6037        jniThrowNullPointerException(env, "x509 == null");
6038        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6039        return;
6040    }
6041
6042    if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6043        throwExceptionIfNecessary(env, "X509_print_ex");
6044        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6045    } else {
6046        JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6047    }
6048}
6049
6050static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref) {
6051    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6052    JNI_TRACE("X509_get_pubkey(%p)", x509);
6053
6054    if (x509 == NULL) {
6055        jniThrowNullPointerException(env, "x509 == null");
6056        JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6057        return 0;
6058    }
6059
6060    Unique_EVP_PKEY pkey(X509_get_pubkey(x509));
6061    if (pkey.get() == NULL) {
6062        throwExceptionIfNecessary(env, "X509_get_pubkey");
6063        return 0;
6064    }
6065
6066    JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6067    return reinterpret_cast<uintptr_t>(pkey.release());
6068}
6069
6070static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref) {
6071    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6072    JNI_TRACE("X509_get_issuer_name(%p)", x509);
6073    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_issuer_name(x509));
6074}
6075
6076static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref) {
6077    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6078    JNI_TRACE("X509_get_subject_name(%p)", x509);
6079    return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_subject_name(x509));
6080}
6081
6082static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref) {
6083    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6084    JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6085
6086    if (x509 == NULL) {
6087        jniThrowNullPointerException(env, "x509 == null");
6088        JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6089        return NULL;
6090    }
6091
6092    X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6093    return ASN1_OBJECT_to_OID_string(env, pubkey->algor->algorithm);
6094}
6095
6096static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref) {
6097    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6098    JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6099
6100    if (x509 == NULL || x509->sig_alg == NULL) {
6101        jniThrowNullPointerException(env, "x509 == NULL || x509->sig_alg == NULL");
6102        JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == NULL", x509);
6103        return NULL;
6104    }
6105
6106    return ASN1_OBJECT_to_OID_string(env, x509->sig_alg->algorithm);
6107}
6108
6109static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref) {
6110    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6111    JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6112
6113    if (x509 == NULL) {
6114        jniThrowNullPointerException(env, "x509 == null");
6115        JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6116        return NULL;
6117    }
6118
6119    if (x509->sig_alg->parameter == NULL) {
6120        JNI_TRACE("get_X509_sig_alg_parameter(%p) => null", x509);
6121        return NULL;
6122    }
6123
6124    return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, x509->sig_alg->parameter);
6125}
6126
6127static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref) {
6128    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6129    JNI_TRACE("get_X509_issuerUID(%p)", x509);
6130
6131    if (x509 == NULL) {
6132        jniThrowNullPointerException(env, "x509 == null");
6133        JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6134        return NULL;
6135    }
6136
6137    if (x509->cert_info->issuerUID == NULL) {
6138        JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6139        return NULL;
6140    }
6141
6142    return ASN1BitStringToBooleanArray(env, x509->cert_info->issuerUID);
6143}
6144static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref) {
6145    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6146    JNI_TRACE("get_X509_subjectUID(%p)", x509);
6147
6148    if (x509 == NULL) {
6149        jniThrowNullPointerException(env, "x509 == null");
6150        JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6151        return NULL;
6152    }
6153
6154    if (x509->cert_info->subjectUID == NULL) {
6155        JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6156        return NULL;
6157    }
6158
6159    return ASN1BitStringToBooleanArray(env, x509->cert_info->subjectUID);
6160}
6161
6162static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref) {
6163    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6164    JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6165
6166    if (x509 == NULL) {
6167        jniThrowNullPointerException(env, "x509 == null");
6168        JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6169        return NULL;
6170    }
6171
6172    Unique_ASN1_BIT_STRING bitStr(static_cast<ASN1_BIT_STRING*>(
6173            X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL)));
6174    if (bitStr.get() == NULL) {
6175        JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6176        return NULL;
6177    }
6178
6179    return ASN1BitStringToBooleanArray(env, bitStr.get());
6180}
6181
6182static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref) {
6183    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6184    JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6185
6186    if (x509 == NULL) {
6187        jniThrowNullPointerException(env, "x509 == null");
6188        JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6189        return NULL;
6190    }
6191
6192    Unique_sk_ASN1_OBJECT objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6193            X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)));
6194    if (objArray.get() == NULL) {
6195        JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6196        return NULL;
6197    }
6198
6199    size_t size = sk_ASN1_OBJECT_num(objArray.get());
6200    ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
6201    if (exKeyUsage.get() == NULL) {
6202        return NULL;
6203    }
6204
6205    for (size_t i = 0; i < size; i++) {
6206        ScopedLocalRef<jstring> oidStr(env, ASN1_OBJECT_to_OID_string(env,
6207                sk_ASN1_OBJECT_value(objArray.get(), i)));
6208        env->SetObjectArrayElement(exKeyUsage.get(), i, oidStr.get());
6209    }
6210
6211    JNI_TRACE("get_X509_ex_xkusage(%p) => success (%d entries)", x509, size);
6212    return exKeyUsage.release();
6213}
6214
6215static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref) {
6216    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6217    JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6218
6219    if (x509 == NULL) {
6220        jniThrowNullPointerException(env, "x509 == null");
6221        JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6222        return 0;
6223    }
6224
6225    /* Just need to do this to cache the ex_* values. */
6226    X509_check_ca(x509);
6227
6228    JNI_TRACE("get_X509_ex_pathlen(%p) => %ld", x509, x509->ex_pathlen);
6229    return x509->ex_pathlen;
6230}
6231
6232static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6233        jstring oidString) {
6234    X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6235    JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6236    return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6237}
6238
6239static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6240        jstring oidString) {
6241    X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6242    JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6243    return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6244            oidString);
6245}
6246
6247static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6248        jstring oidString) {
6249    X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6250    JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6251    return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6252            env, revoked, oidString);
6253}
6254
6255template<typename T, int (*get_ext_by_critical_func)(T*, int, int), X509_EXTENSION* (*get_ext_func)(T*, int)>
6256static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6257    T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6258    JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6259
6260    if (x509 == NULL) {
6261        jniThrowNullPointerException(env, "x509 == null");
6262        JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6263        return NULL;
6264    }
6265
6266    int lastPos = -1;
6267    int count = 0;
6268    while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6269        count++;
6270    }
6271
6272    JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6273
6274    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
6275    if (joa.get() == NULL) {
6276        JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6277        return NULL;
6278    }
6279
6280    lastPos = -1;
6281    count = 0;
6282    while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6283        X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6284
6285        ScopedLocalRef<jstring> extOid(env, ASN1_OBJECT_to_OID_string(env, ext->object));
6286        if (extOid.get() == NULL) {
6287            JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6288            return NULL;
6289        }
6290
6291        env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6292    }
6293
6294    JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6295    return joa.release();
6296}
6297
6298static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6299        jint critical) {
6300    JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", x509Ref, critical);
6301    return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6302            critical);
6303}
6304
6305static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6306        jint critical) {
6307    JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509CrlRef, critical);
6308    return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(env,
6309            x509CrlRef, critical);
6310}
6311
6312static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass, jlong x509RevokedRef,
6313        jint critical) {
6314    JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509RevokedRef, critical);
6315    return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6316            X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6317}
6318
6319#ifdef WITH_JNI_TRACE
6320/**
6321 * Based on example logging call back from SSL_CTX_set_info_callback man page
6322 */
6323static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
6324{
6325    int w = where & ~SSL_ST_MASK;
6326    const char* str;
6327    if (w & SSL_ST_CONNECT) {
6328        str = "SSL_connect";
6329    } else if (w & SSL_ST_ACCEPT) {
6330        str = "SSL_accept";
6331    } else {
6332        str = "undefined";
6333    }
6334
6335    if (where & SSL_CB_LOOP) {
6336        JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6337    } else if (where & SSL_CB_ALERT) {
6338        str = (where & SSL_CB_READ) ? "read" : "write";
6339        JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
6340                  s,
6341                  str,
6342                  SSL_alert_type_string(ret),
6343                  SSL_alert_desc_string(ret),
6344                  SSL_alert_type_string_long(ret),
6345                  SSL_alert_desc_string_long(ret));
6346    } else if (where & SSL_CB_EXIT) {
6347        if (ret == 0) {
6348            JNI_TRACE("ssl=%p %s:failed exit in %s %s",
6349                      s, str, SSL_state_string(s), SSL_state_string_long(s));
6350        } else if (ret < 0) {
6351            JNI_TRACE("ssl=%p %s:error exit in %s %s",
6352                      s, str, SSL_state_string(s), SSL_state_string_long(s));
6353        } else if (ret == 1) {
6354            JNI_TRACE("ssl=%p %s:ok exit in %s %s",
6355                      s, str, SSL_state_string(s), SSL_state_string_long(s));
6356        } else {
6357            JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
6358                      s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
6359        }
6360    } else if (where & SSL_CB_HANDSHAKE_START) {
6361        JNI_TRACE("ssl=%p handshake start in %s %s",
6362                  s, SSL_state_string(s), SSL_state_string_long(s));
6363    } else if (where & SSL_CB_HANDSHAKE_DONE) {
6364        JNI_TRACE("ssl=%p handshake done in %s %s",
6365                  s, SSL_state_string(s), SSL_state_string_long(s));
6366    } else {
6367        JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
6368                  s, str, where, SSL_state_string(s), SSL_state_string_long(s));
6369    }
6370}
6371#endif
6372
6373/**
6374 * Returns an array containing all the X509 certificate references
6375 */
6376static jlongArray getCertificateRefs(JNIEnv* env, const STACK_OF(X509)* chain)
6377{
6378    if (chain == NULL) {
6379        // Chain can be NULL if the associated cipher doesn't do certs.
6380        return NULL;
6381    }
6382    ssize_t count = sk_X509_num(chain);
6383    if (count <= 0) {
6384        return NULL;
6385    }
6386    ScopedLocalRef<jlongArray> refArray(env, env->NewLongArray(count));
6387    ScopedLongArrayRW refs(env, refArray.get());
6388    if (refs.get() == NULL) {
6389        return NULL;
6390    }
6391    for (ssize_t i = 0; i < count; i++) {
6392        refs[i] = reinterpret_cast<uintptr_t>(X509_dup_nocopy(sk_X509_value(chain, i)));
6393    }
6394    return refArray.release();
6395}
6396
6397/**
6398 * Returns an array containing all the X500 principal's bytes.
6399 */
6400static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
6401{
6402    if (names == NULL) {
6403        return NULL;
6404    }
6405
6406    int count = sk_X509_NAME_num(names);
6407    if (count <= 0) {
6408        return NULL;
6409    }
6410
6411    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
6412    if (joa.get() == NULL) {
6413        return NULL;
6414    }
6415
6416    for (int i = 0; i < count; i++) {
6417        X509_NAME* principal = sk_X509_NAME_value(names, i);
6418
6419        ScopedLocalRef<jbyteArray> byteArray(env, ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env,
6420                principal));
6421        if (byteArray.get() == NULL) {
6422            return NULL;
6423        }
6424        env->SetObjectArrayElement(joa.get(), i, byteArray.get());
6425    }
6426
6427    return joa.release();
6428}
6429
6430/**
6431 * Our additional application data needed for getting synchronization right.
6432 * This maybe warrants a bit of lengthy prose:
6433 *
6434 * (1) We use a flag to reflect whether we consider the SSL connection alive.
6435 * Any read or write attempt loops will be cancelled once this flag becomes 0.
6436 *
6437 * (2) We use an int to count the number of threads that are blocked by the
6438 * underlying socket. This may be at most two (one reader and one writer), since
6439 * the Java layer ensures that no more threads will enter the native code at the
6440 * same time.
6441 *
6442 * (3) The pipe is used primarily as a means of cancelling a blocking select()
6443 * when we want to close the connection (aka "emergency button"). It is also
6444 * necessary for dealing with a possible race condition situation: There might
6445 * be cases where both threads see an SSL_ERROR_WANT_READ or
6446 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
6447 * If one leaves the select() successfully before the other enters it, the
6448 * "success" event is already consumed and the second thread will be blocked,
6449 * possibly forever (depending on network conditions).
6450 *
6451 * The idea for solving the problem looks like this: Whenever a thread is
6452 * successful in moving around data on the network, and it knows there is
6453 * another thread stuck in a select(), it will write a byte to the pipe, waking
6454 * up the other thread. A thread that returned from select(), on the other hand,
6455 * knows whether it's been woken up by the pipe. If so, it will consume the
6456 * byte, and the original state of affairs has been restored.
6457 *
6458 * The pipe may seem like a bit of overhead, but it fits in nicely with the
6459 * other file descriptors of the select(), so there's only one condition to wait
6460 * for.
6461 *
6462 * (4) Finally, a mutex is needed to make sure that at most one thread is in
6463 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
6464 * requirement. We use the same mutex to guard the field for counting the
6465 * waiting threads.
6466 *
6467 * Note: The current implementation assumes that we don't have to deal with
6468 * problems induced by multiple cores or processors and their respective
6469 * memory caches. One possible problem is that of inconsistent views on the
6470 * "aliveAndKicking" field. This could be worked around by also enclosing all
6471 * accesses to that field inside a lock/unlock sequence of our mutex, but
6472 * currently this seems a bit like overkill. Marking volatile at the very least.
6473 *
6474 * During handshaking, additional fields are used to up-call into
6475 * Java to perform certificate verification and handshake
6476 * completion. These are also used in any renegotiation.
6477 *
6478 * (5) the JNIEnv so we can invoke the Java callback
6479 *
6480 * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
6481 *
6482 * (7) a java.io.FileDescriptor wrapper to check for socket close
6483 *
6484 * We store the NPN protocols list so we can either send it (from the server) or
6485 * select a protocol (on the client). We eagerly acquire a pointer to the array
6486 * data so the callback doesn't need to acquire resources that it cannot
6487 * release.
6488 *
6489 * Because renegotiation can be requested by the peer at any time,
6490 * care should be taken to maintain an appropriate JNIEnv on any
6491 * downcall to openssl since it could result in an upcall to Java. The
6492 * current code does try to cover these cases by conditionally setting
6493 * the JNIEnv on calls that can read and write to the SSL such as
6494 * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
6495 *
6496 * Finally, we have two emphemeral keys setup by OpenSSL callbacks:
6497 *
6498 * (8) a set of ephemeral RSA keys that is lazily generated if a peer
6499 * wants to use an exportable RSA cipher suite.
6500 *
6501 * (9) a set of ephemeral EC keys that is lazily generated if a peer
6502 * wants to use an TLS_ECDHE_* cipher suite.
6503 *
6504 */
6505class AppData {
6506  public:
6507    volatile int aliveAndKicking;
6508    int waitingThreads;
6509    int fdsEmergency[2];
6510    MUTEX_TYPE mutex;
6511    JNIEnv* env;
6512    jobject sslHandshakeCallbacks;
6513    jbyteArray npnProtocolsArray;
6514    jbyte* npnProtocolsData;
6515    size_t npnProtocolsLength;
6516    jbyteArray alpnProtocolsArray;
6517    jbyte* alpnProtocolsData;
6518    size_t alpnProtocolsLength;
6519    Unique_RSA ephemeralRsa;
6520    Unique_EC_KEY ephemeralEc;
6521
6522    /**
6523     * Creates the application data context for the SSL*.
6524     */
6525  public:
6526    static AppData* create() {
6527        UniquePtr<AppData> appData(new AppData());
6528        if (pipe(appData.get()->fdsEmergency) == -1) {
6529            ALOGE("AppData::create pipe(2) failed: %s", strerror(errno));
6530            return NULL;
6531        }
6532        if (!setBlocking(appData.get()->fdsEmergency[0], false)) {
6533            ALOGE("AppData::create fcntl(2) failed: %s", strerror(errno));
6534            return NULL;
6535        }
6536        if (MUTEX_SETUP(appData.get()->mutex) == -1) {
6537            ALOGE("pthread_mutex_init(3) failed: %s", strerror(errno));
6538            return NULL;
6539        }
6540        return appData.release();
6541    }
6542
6543    ~AppData() {
6544        aliveAndKicking = 0;
6545        if (fdsEmergency[0] != -1) {
6546            close(fdsEmergency[0]);
6547        }
6548        if (fdsEmergency[1] != -1) {
6549            close(fdsEmergency[1]);
6550        }
6551        clearCallbackState();
6552        MUTEX_CLEANUP(mutex);
6553    }
6554
6555  private:
6556    AppData() :
6557            aliveAndKicking(1),
6558            waitingThreads(0),
6559            env(NULL),
6560            sslHandshakeCallbacks(NULL),
6561            npnProtocolsArray(NULL),
6562            npnProtocolsData(NULL),
6563            npnProtocolsLength(-1),
6564            alpnProtocolsArray(NULL),
6565            alpnProtocolsData(NULL),
6566            alpnProtocolsLength(-1),
6567            ephemeralRsa(NULL),
6568            ephemeralEc(NULL) {
6569        fdsEmergency[0] = -1;
6570        fdsEmergency[1] = -1;
6571    }
6572
6573  public:
6574    /**
6575     * Used to set the SSL-to-Java callback state before each SSL_*
6576     * call that may result in a callback. It should be cleared after
6577     * the operation returns with clearCallbackState.
6578     *
6579     * @param env The JNIEnv
6580     * @param shc The SSLHandshakeCallbacks
6581     * @param fd The FileDescriptor
6582     * @param npnProtocols NPN protocols so that they may be advertised (by the
6583     *                     server) or selected (by the client). Has no effect
6584     *                     unless NPN is enabled.
6585     * @param alpnProtocols ALPN protocols so that they may be advertised (by the
6586     *                     server) or selected (by the client). Passing non-NULL
6587     *                     enables ALPN.
6588     */
6589    bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
6590            jbyteArray alpnProtocols) {
6591        UniquePtr<NetFd> netFd;
6592        if (fd != NULL) {
6593            netFd.reset(new NetFd(e, fd));
6594            if (netFd->isClosed()) {
6595                JNI_TRACE("appData=%p setCallbackState => netFd->isClosed() == true", this);
6596                return false;
6597            }
6598        }
6599        env = e;
6600        sslHandshakeCallbacks = shc;
6601        if (npnProtocols != NULL) {
6602            npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
6603            if (npnProtocolsData == NULL) {
6604                clearCallbackState();
6605                JNI_TRACE("appData=%p setCallbackState => npnProtocolsData == NULL", this);
6606                return false;
6607            }
6608            npnProtocolsArray = npnProtocols;
6609            npnProtocolsLength = e->GetArrayLength(npnProtocols);
6610        }
6611        if (alpnProtocols != NULL) {
6612            alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
6613            if (alpnProtocolsData == NULL) {
6614                clearCallbackState();
6615                JNI_TRACE("appData=%p setCallbackState => alpnProtocolsData == NULL", this);
6616                return false;
6617            }
6618            alpnProtocolsArray = alpnProtocols;
6619            alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
6620        }
6621        return true;
6622    }
6623
6624    void clearCallbackState() {
6625        sslHandshakeCallbacks = NULL;
6626        if (npnProtocolsArray != NULL) {
6627            env->ReleaseByteArrayElements(npnProtocolsArray, npnProtocolsData, JNI_ABORT);
6628            npnProtocolsArray = NULL;
6629            npnProtocolsData = NULL;
6630            npnProtocolsLength = -1;
6631        }
6632        if (alpnProtocolsArray != NULL) {
6633            env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
6634            alpnProtocolsArray = NULL;
6635            alpnProtocolsData = NULL;
6636            alpnProtocolsLength = -1;
6637        }
6638        env = NULL;
6639    }
6640
6641};
6642
6643/**
6644 * Dark magic helper function that checks, for a given SSL session, whether it
6645 * can SSL_read() or SSL_write() without blocking. Takes into account any
6646 * concurrent attempts to close the SSLSocket from the Java side. This is
6647 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6648 * while thread #2 is sitting in a blocking read or write. The type argument
6649 * specifies whether we are waiting for readability or writability. It expects
6650 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6651 * only need to wait in case one of these problems occurs.
6652 *
6653 * @param env
6654 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6655 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6656 * @param appData The application data structure with mutex info etc.
6657 * @param timeout_millis The timeout value for select call, with the special value
6658 *                0 meaning no timeout at all (wait indefinitely). Note: This is
6659 *                the Java semantics of the timeout value, not the usual
6660 *                select() semantics.
6661 * @return The result of the inner select() call,
6662 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6663 * additional errors
6664 */
6665static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout_millis) {
6666    // This loop is an expanded version of the NET_FAILURE_RETRY
6667    // macro. It cannot simply be used in this case because select
6668    // cannot be restarted without recreating the fd_sets and timeout
6669    // structure.
6670    int result;
6671    fd_set rfds;
6672    fd_set wfds;
6673    do {
6674        NetFd fd(env, fdObject);
6675        if (fd.isClosed()) {
6676            result = THROWN_EXCEPTION;
6677            break;
6678        }
6679        int intFd = fd.get();
6680        JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6681                  (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6682
6683        FD_ZERO(&rfds);
6684        FD_ZERO(&wfds);
6685
6686        if (type == SSL_ERROR_WANT_READ) {
6687            FD_SET(intFd, &rfds);
6688        } else {
6689            FD_SET(intFd, &wfds);
6690        }
6691
6692        FD_SET(appData->fdsEmergency[0], &rfds);
6693
6694        int maxFd = (intFd > appData->fdsEmergency[0]) ? intFd : appData->fdsEmergency[0];
6695
6696        // Build a struct for the timeout data if we actually want a timeout.
6697        timeval tv;
6698        timeval* ptv;
6699        if (timeout_millis > 0) {
6700            tv.tv_sec = timeout_millis / 1000;
6701            tv.tv_usec = (timeout_millis % 1000) * 1000;
6702            ptv = &tv;
6703        } else {
6704            ptv = NULL;
6705        }
6706
6707#ifndef CONSCRYPT_UNBUNDLED
6708        AsynchronousCloseMonitor monitor(intFd);
6709#else
6710        CompatibilityCloseMonitor monitor(intFd);
6711#endif
6712        result = select(maxFd + 1, &rfds, &wfds, NULL, ptv);
6713        JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6714                  (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
6715                  fd.get(), appData, timeout_millis, result);
6716        if (result == -1) {
6717            if (fd.isClosed()) {
6718                result = THROWN_EXCEPTION;
6719                break;
6720            }
6721            if (errno != EINTR) {
6722                break;
6723            }
6724        }
6725    } while (result == -1);
6726
6727    if (MUTEX_LOCK(appData->mutex) == -1) {
6728        return -1;
6729    }
6730
6731    if (result > 0) {
6732        // We have been woken up by a token in the emergency pipe. We
6733        // can't be sure the token is still in the pipe at this point
6734        // because it could have already been read by the thread that
6735        // originally wrote it if it entered sslSelect and acquired
6736        // the mutex before we did. Thus we cannot safely read from
6737        // the pipe in a blocking way (so we make the pipe
6738        // non-blocking at creation).
6739        if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
6740            char token;
6741            do {
6742                read(appData->fdsEmergency[0], &token, 1);
6743            } while (errno == EINTR);
6744        }
6745    }
6746
6747    // Tell the world that there is now one thread less waiting for the
6748    // underlying network.
6749    appData->waitingThreads--;
6750
6751    MUTEX_UNLOCK(appData->mutex);
6752
6753    return result;
6754}
6755
6756/**
6757 * Helper function that wakes up a thread blocked in select(), in case there is
6758 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6759 * before closing the connection.
6760 *
6761 * @param data The application data structure with mutex info etc.
6762 */
6763static void sslNotify(AppData* appData) {
6764    // Write a byte to the emergency pipe, so a concurrent select() can return.
6765    // Note we have to restore the errno of the original system call, since the
6766    // caller relies on it for generating error messages.
6767    int errnoBackup = errno;
6768    char token = '*';
6769    do {
6770        errno = 0;
6771        write(appData->fdsEmergency[1], &token, 1);
6772    } while (errno == EINTR);
6773    errno = errnoBackup;
6774}
6775
6776static AppData* toAppData(const SSL* ssl) {
6777    return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6778}
6779
6780/**
6781 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
6782 */
6783static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
6784{
6785    /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
6786    SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
6787            SSL_get_ex_data_X509_STORE_CTX_idx()));
6788    JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
6789
6790    AppData* appData = toAppData(ssl);
6791    JNIEnv* env = appData->env;
6792    if (env == NULL) {
6793        ALOGE("AppData->env missing in cert_verify_callback");
6794        JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6795        return 0;
6796    }
6797    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6798
6799    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6800    jmethodID methodID
6801        = env->GetMethodID(cls, "verifyCertificateChain", "(J[JLjava/lang/String;)V");
6802
6803    jlongArray refArray = getCertificateRefs(env, x509_store_ctx->untrusted);
6804
6805    const char* authMethod = SSL_authentication_method(ssl);
6806    JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
6807              ssl, authMethod);
6808    jstring authMethodString = env->NewStringUTF(authMethod);
6809    env->CallVoidMethod(sslHandshakeCallbacks, methodID,
6810            static_cast<jlong>(reinterpret_cast<uintptr_t>(SSL_get1_session(ssl))), refArray,
6811            authMethodString);
6812
6813    int result = (env->ExceptionCheck()) ? 0 : 1;
6814    JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6815    return result;
6816}
6817
6818/**
6819 * Call back to watch for handshake to be completed. This is necessary
6820 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
6821 * returns before the handshake is completed in this case.
6822 */
6823static void info_callback(const SSL* ssl, int where, int ret) {
6824    JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
6825#ifdef WITH_JNI_TRACE
6826    info_callback_LOG(ssl, where, ret);
6827#endif
6828    if (!(where & SSL_CB_HANDSHAKE_DONE) && !(where & SSL_CB_HANDSHAKE_START)) {
6829        JNI_TRACE("ssl=%p info_callback ignored", ssl);
6830        return;
6831    }
6832
6833    AppData* appData = toAppData(ssl);
6834    JNIEnv* env = appData->env;
6835    if (env == NULL) {
6836        ALOGE("AppData->env missing in info_callback");
6837        JNI_TRACE("ssl=%p info_callback env error", ssl);
6838        return;
6839    }
6840    if (env->ExceptionCheck()) {
6841        JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6842        return;
6843    }
6844
6845    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6846
6847    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6848    jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(JII)V");
6849
6850    JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6851    env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(ssl), where, ret);
6852
6853    if (env->ExceptionCheck()) {
6854        JNI_TRACE("ssl=%p info_callback exception", ssl);
6855    }
6856    JNI_TRACE("ssl=%p info_callback completed", ssl);
6857}
6858
6859/**
6860 * Call back to ask for a client certificate. There are three possible exit codes:
6861 *
6862 * 1 is success. x509Out and pkeyOut should point to the correct private key and certificate.
6863 * 0 is unable to find key. x509Out and pkeyOut should be NULL.
6864 * -1 is error and it doesn't matter what x509Out and pkeyOut are.
6865 */
6866static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
6867    JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
6868
6869    /* Clear output of key and certificate in case of early exit due to error. */
6870    *x509Out = NULL;
6871    *pkeyOut = NULL;
6872
6873    AppData* appData = toAppData(ssl);
6874    JNIEnv* env = appData->env;
6875    if (env == NULL) {
6876        ALOGE("AppData->env missing in client_cert_cb");
6877        JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
6878        return 0;
6879    }
6880    if (env->ExceptionCheck()) {
6881        JNI_TRACE("ssl=%p client_cert_cb already pending exception => 0", ssl);
6882        return -1;
6883    }
6884    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6885
6886    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6887    jmethodID methodID
6888        = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
6889
6890    // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
6891    char ssl2_ctype = SSL3_CT_RSA_SIGN;
6892    const char* ctype = NULL;
6893    int ctype_num = 0;
6894    jobjectArray issuers = NULL;
6895    switch (ssl->version) {
6896        case SSL2_VERSION:
6897            ctype = &ssl2_ctype;
6898            ctype_num = 1;
6899            break;
6900        case SSL3_VERSION:
6901        case TLS1_VERSION:
6902        case TLS1_1_VERSION:
6903        case TLS1_2_VERSION:
6904        case DTLS1_VERSION:
6905            ctype = ssl->s3->tmp.ctype;
6906            ctype_num = ssl->s3->tmp.ctype_num;
6907            issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
6908            break;
6909    }
6910#ifdef WITH_JNI_TRACE
6911    for (int i = 0; i < ctype_num; i++) {
6912        JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
6913    }
6914#endif
6915
6916    jbyteArray keyTypes = env->NewByteArray(ctype_num);
6917    if (keyTypes == NULL) {
6918        JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
6919        return 0;
6920    }
6921    env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
6922
6923    JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
6924              "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
6925    env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
6926
6927    if (env->ExceptionCheck()) {
6928        JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
6929        return -1;
6930    }
6931
6932    // Check for values set from Java
6933    X509*     certificate = SSL_get_certificate(ssl);
6934    EVP_PKEY* privatekey  = SSL_get_privatekey(ssl);
6935    int result = 0;
6936    if (certificate != NULL && privatekey != NULL) {
6937        *x509Out = certificate;
6938        *pkeyOut = privatekey;
6939        result = 1;
6940    } else {
6941        // Some error conditions return NULL, so make sure it doesn't linger.
6942        freeOpenSslErrorState();
6943    }
6944    JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
6945    return result;
6946}
6947
6948/**
6949 * Pre-Shared Key (PSK) client callback.
6950 */
6951static unsigned int psk_client_callback(SSL* ssl, const char *hint,
6952        char *identity, unsigned int max_identity_len,
6953        unsigned char *psk, unsigned int max_psk_len) {
6954    JNI_TRACE("ssl=%p psk_client_callback", ssl);
6955
6956    AppData* appData = toAppData(ssl);
6957    JNIEnv* env = appData->env;
6958    if (env == NULL) {
6959        ALOGE("AppData->env missing in psk_client_callback");
6960        JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6961        return 0;
6962    }
6963    if (env->ExceptionCheck()) {
6964        JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6965        return 0;
6966    }
6967
6968    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6969    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6970    jmethodID methodID =
6971            env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
6972    JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6973    ScopedLocalRef<jstring> identityHintJava(
6974            env,
6975            (hint != NULL) ? env->NewStringUTF(hint) : NULL);
6976    ScopedLocalRef<jbyteArray> identityJava(env, env->NewByteArray(max_identity_len));
6977    if (identityJava.get() == NULL) {
6978        JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6979        return 0;
6980    }
6981    ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
6982    if (keyJava.get() == NULL) {
6983        JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6984        return 0;
6985    }
6986    jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
6987            identityHintJava.get(), identityJava.get(), keyJava.get());
6988    if (env->ExceptionCheck()) {
6989        JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6990        return 0;
6991    }
6992    if (keyLen <= 0) {
6993        JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6994        return 0;
6995    } else if ((unsigned int) keyLen > max_psk_len) {
6996        JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6997        return 0;
6998    }
6999    ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7000    if (keyJavaRo.get() == NULL) {
7001        JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7002        return 0;
7003    }
7004    memcpy(psk, keyJavaRo.get(), keyLen);
7005
7006    ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7007    if (identityJavaRo.get() == NULL) {
7008        JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7009        return 0;
7010    }
7011    memcpy(identity, identityJavaRo.get(), max_identity_len);
7012
7013    JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7014    return keyLen;
7015}
7016
7017/**
7018 * Pre-Shared Key (PSK) server callback.
7019 */
7020static unsigned int psk_server_callback(SSL* ssl, const char *identity,
7021        unsigned char *psk, unsigned int max_psk_len) {
7022    JNI_TRACE("ssl=%p psk_server_callback", ssl);
7023
7024    AppData* appData = toAppData(ssl);
7025    JNIEnv* env = appData->env;
7026    if (env == NULL) {
7027        ALOGE("AppData->env missing in psk_server_callback");
7028        JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7029        return 0;
7030    }
7031    if (env->ExceptionCheck()) {
7032        JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7033        return 0;
7034    }
7035
7036    jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7037    jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7038    jmethodID methodID = env->GetMethodID(
7039            cls, "serverPSKKeyRequested", "(Ljava/lang/String;Ljava/lang/String;[B)I");
7040    JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7041    const char* identityHint = SSL_get_psk_identity_hint(ssl);
7042    // identityHint = NULL;
7043    // identity = NULL;
7044    ScopedLocalRef<jstring> identityHintJava(
7045            env,
7046            (identityHint != NULL) ? env->NewStringUTF(identityHint) : NULL);
7047    ScopedLocalRef<jstring> identityJava(
7048            env,
7049            (identity != NULL) ? env->NewStringUTF(identity) : NULL);
7050    ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
7051    if (keyJava.get() == NULL) {
7052        JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7053        return 0;
7054    }
7055    jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
7056            identityHintJava.get(), identityJava.get(), keyJava.get());
7057    if (env->ExceptionCheck()) {
7058        JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7059        return 0;
7060    }
7061    if (keyLen <= 0) {
7062        JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7063        return 0;
7064    } else if ((unsigned int) keyLen > max_psk_len) {
7065        JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7066        return 0;
7067    }
7068    ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7069    if (keyJavaRo.get() == NULL) {
7070        JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7071        return 0;
7072    }
7073    memcpy(psk, keyJavaRo.get(), keyLen);
7074
7075    JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7076    return keyLen;
7077}
7078
7079static RSA* rsaGenerateKey(int keylength) {
7080    Unique_BIGNUM bn(BN_new());
7081    if (bn.get() == NULL) {
7082        return NULL;
7083    }
7084    int setWordResult = BN_set_word(bn.get(), RSA_F4);
7085    if (setWordResult != 1) {
7086        return NULL;
7087    }
7088    Unique_RSA rsa(RSA_new());
7089    if (rsa.get() == NULL) {
7090        return NULL;
7091    }
7092    int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
7093    if (generateResult != 1) {
7094        return NULL;
7095    }
7096    return rsa.release();
7097}
7098
7099/**
7100 * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
7101 */
7102static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
7103                             int is_export __attribute__ ((unused)),
7104                             int keylength) {
7105    JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7106
7107    AppData* appData = toAppData(ssl);
7108    if (appData->ephemeralRsa.get() == NULL) {
7109        JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
7110        appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
7111    }
7112    JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
7113    return appData->ephemeralRsa.get();
7114}
7115
7116static DH* dhGenerateParameters(int keylength) {
7117
7118    /*
7119     * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
7120     * different options for generating DH keys. One is generating the
7121     * keys using a single set of DH parameters. However, generating
7122     * DH parameters is slow enough (minutes) that they suggest doing
7123     * it once at install time. The other is to generate DH keys from
7124     * DSA parameters. Generating DSA parameters is faster than DH
7125     * parameters, but to prevent small subgroup attacks, they needed
7126     * to be regenerated for each set of DH keys. Setting the
7127     * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
7128     * for new DH parameters every type it needs to generate DH keys.
7129     */
7130#if 0
7131    // Slow path that takes minutes but could be cached
7132    Unique_DH dh(DH_new());
7133    if (!DH_generate_parameters_ex(dh.get(), keylength, 2, NULL)) {
7134        return NULL;
7135    }
7136    return dh.release();
7137#else
7138    // Faster path but must have SSL_OP_SINGLE_DH_USE set
7139    Unique_DSA dsa(DSA_new());
7140    if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
7141        return NULL;
7142    }
7143    DH* dh = DSA_dup_DH(dsa.get());
7144    return dh;
7145#endif
7146}
7147
7148/**
7149 * Call back to ask for Diffie-Hellman parameters
7150 */
7151static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
7152                           int is_export __attribute__ ((unused)),
7153                           int keylength) {
7154    JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7155    DH* tmp_dh = dhGenerateParameters(keylength);
7156    JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
7157    return tmp_dh;
7158}
7159
7160static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
7161    // TODO selected curve based on keylength
7162    Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
7163    if (ec.get() == NULL) {
7164        return NULL;
7165    }
7166    return ec.release();
7167}
7168
7169/**
7170 * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
7171 */
7172static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
7173                                 int is_export __attribute__ ((unused)),
7174                                 int keylength) {
7175    JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7176    AppData* appData = toAppData(ssl);
7177    if (appData->ephemeralEc.get() == NULL) {
7178        JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
7179        appData->ephemeralEc.reset(ecGenerateKey(keylength));
7180    }
7181    JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
7182    return appData->ephemeralEc.get();
7183}
7184
7185/*
7186 * public static native int SSL_CTX_new();
7187 */
7188static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7189    Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
7190    if (sslCtx.get() == NULL) {
7191        throwExceptionIfNecessary(env, "SSL_CTX_new");
7192        return 0;
7193    }
7194    SSL_CTX_set_options(sslCtx.get(),
7195                        SSL_OP_ALL
7196                        // Note: We explicitly do not allow SSLv2 to be used.
7197                        | SSL_OP_NO_SSLv2
7198                        // We also disable session tickets for better compatibility b/2682876
7199                        | SSL_OP_NO_TICKET
7200                        // We also disable compression for better compatibility b/2710492 b/2710497
7201                        | SSL_OP_NO_COMPRESSION
7202                        // Because dhGenerateParameters uses DSA_generate_parameters_ex
7203                        | SSL_OP_SINGLE_DH_USE
7204                        // Because ecGenerateParameters uses a fixed named curve
7205                        | SSL_OP_SINGLE_ECDH_USE);
7206
7207    int mode = SSL_CTX_get_mode(sslCtx.get());
7208    /*
7209     * Turn on "partial write" mode. This means that SSL_write() will
7210     * behave like Posix write() and possibly return after only
7211     * writing a partial buffer. Note: The alternative, perhaps
7212     * surprisingly, is not that SSL_write() always does full writes
7213     * but that it will force you to retry write calls having
7214     * preserved the full state of the original call. (This is icky
7215     * and undesirable.)
7216     */
7217    mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7218
7219    // Reuse empty buffers within the SSL_CTX to save memory
7220    mode |= SSL_MODE_RELEASE_BUFFERS;
7221
7222    SSL_CTX_set_mode(sslCtx.get(), mode);
7223
7224    SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
7225    SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7226    SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
7227    SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
7228    SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
7229    SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
7230
7231    // When TLS Channel ID extension is used, use the new version of it.
7232    sslCtx.get()->tlsext_channel_id_enabled_new = 1;
7233
7234    JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7235    return (jlong) sslCtx.release();
7236}
7237
7238/**
7239 * public static native void SSL_CTX_free(long ssl_ctx)
7240 */
7241static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
7242        jclass, jlong ssl_ctx_address)
7243{
7244    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7245    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7246    if (ssl_ctx == NULL) {
7247        return;
7248    }
7249    SSL_CTX_free(ssl_ctx);
7250}
7251
7252static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass,
7253                                                        jlong ssl_ctx_address, jbyteArray sid_ctx)
7254{
7255    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7256    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx, sid_ctx);
7257    if (ssl_ctx == NULL) {
7258        return;
7259    }
7260
7261    ScopedByteArrayRO buf(env, sid_ctx);
7262    if (buf.get() == NULL) {
7263        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception", ssl_ctx);
7264        return;
7265    }
7266
7267    unsigned int length = buf.size();
7268    if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7269        jniThrowException(env, "java/lang/IllegalArgumentException",
7270                          "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7271        JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7272        return;
7273    }
7274    const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7275    int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7276    if (result == 0) {
7277        throwExceptionIfNecessary(env, "NativeCrypto_SSL_CTX_set_session_id_context");
7278        return;
7279    }
7280    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7281}
7282
7283/**
7284 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7285 */
7286static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address)
7287{
7288    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7289    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7290    if (ssl_ctx == NULL) {
7291        return 0;
7292    }
7293    Unique_SSL ssl(SSL_new(ssl_ctx));
7294    if (ssl.get() == NULL) {
7295        throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
7296                "Unable to create SSL structure");
7297        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
7298        return 0;
7299    }
7300
7301    /*
7302     * Create our special application data.
7303     */
7304    AppData* appData = AppData::create();
7305    if (appData == NULL) {
7306        throwSSLExceptionStr(env, "Unable to create application data");
7307        freeOpenSslErrorState();
7308        JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7309        return 0;
7310    }
7311    SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7312
7313    /*
7314     * Java code in class OpenSSLSocketImpl does the verification. Since
7315     * the callbacks do all the verification of the chain, this flag
7316     * simply controls whether to send protocol-level alerts or not.
7317     * SSL_VERIFY_NONE means don't send alerts and anything else means send
7318     * alerts.
7319     */
7320    SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
7321
7322    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7323    return (jlong) ssl.release();
7324}
7325
7326
7327static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
7328{
7329    SSL* ssl = to_SSL(env, ssl_address, true);
7330    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_enable_tls_channel_id", ssl);
7331    if (ssl == NULL) {
7332        return;
7333    }
7334
7335    long ret = SSL_enable_tls_channel_id(ssl);
7336    if (ret != 1L) {
7337        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7338        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error enabling Channel ID");
7339        safeSslClear(ssl);
7340        JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7341        return;
7342    }
7343}
7344
7345static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
7346{
7347    SSL* ssl = to_SSL(env, ssl_address, true);
7348    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id", ssl);
7349    if (ssl == NULL) {
7350        return NULL;
7351    }
7352
7353    // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7354    // as a constant anywhere.
7355    jbyteArray javaBytes = env->NewByteArray(64);
7356    ScopedByteArrayRW bytes(env, javaBytes);
7357    if (bytes.get() == NULL) {
7358        JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => NULL", ssl);
7359        return NULL;
7360    }
7361
7362    unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7363    // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7364    // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7365    // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7366    long ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7367    if (ret == 0) {
7368        // Channel ID either not set or did not verify
7369        JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7370        return NULL;
7371    } else if (ret != 64) {
7372        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7373        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error getting Channel ID");
7374        safeSslClear(ssl);
7375        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %ld", ssl, ret);
7376        return NULL;
7377    }
7378
7379    JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7380    return javaBytes;
7381}
7382
7383static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
7384        jlong ssl_address, jlong pkeyRef)
7385{
7386    SSL* ssl = to_SSL(env, ssl_address, true);
7387    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
7388    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
7389    if (ssl == NULL) {
7390        return;
7391    }
7392
7393    if (pkey == NULL) {
7394        jniThrowNullPointerException(env, "pkey == null");
7395        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7396        return;
7397    }
7398
7399    // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
7400    // Unfortunately, the default value is 1 and it's only changed to 0 just
7401    // before the handshake starts (see NativeCrypto_SSL_do_handshake).
7402    ssl->server = 0;
7403    long ret = SSL_set1_tls_channel_id(ssl, pkey);
7404
7405    if (ret != 1L) {
7406        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7407        throwSSLExceptionWithSslErrors(
7408                env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7409        safeSslClear(ssl);
7410        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7411        return;
7412    }
7413    // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
7414    // we have an external reference from the caller such as an OpenSSLKey,
7415    // so we manually increment the reference count here.
7416    CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
7417
7418    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7419}
7420
7421static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
7422    SSL* ssl = to_SSL(env, ssl_address, true);
7423    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
7424    JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
7425    if (ssl == NULL) {
7426        return;
7427    }
7428
7429    if (pkey == NULL) {
7430        jniThrowNullPointerException(env, "pkey == null");
7431        JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
7432        return;
7433    }
7434
7435    int ret = SSL_use_PrivateKey(ssl, pkey);
7436    if (ret != 1) {
7437        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7438        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
7439        safeSslClear(ssl);
7440        JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
7441        return;
7442    }
7443    // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
7444    // but we have an external reference from the caller such as an
7445    // OpenSSLKey, so we manually increment the reference count here.
7446    CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
7447
7448    JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
7449}
7450
7451static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
7452                                             jlong ssl_address, jlongArray certificatesJava)
7453{
7454    SSL* ssl = to_SSL(env, ssl_address, true);
7455    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificatesJava);
7456    if (ssl == NULL) {
7457        return;
7458    }
7459
7460    if (certificatesJava == NULL) {
7461        jniThrowNullPointerException(env, "certificates == null");
7462        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
7463        return;
7464    }
7465
7466    size_t length = env->GetArrayLength(certificatesJava);
7467    if (length == 0) {
7468        jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
7469        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
7470        return;
7471    }
7472
7473    ScopedLongArrayRO certificates(env, certificatesJava);
7474    if (certificates.get() == NULL) {
7475        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
7476        return;
7477    }
7478
7479    Unique_X509 serverCert(
7480            X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[0]))));
7481    if (serverCert.get() == NULL) {
7482        // Note this shouldn't happen since we checked the number of certificates above.
7483        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
7484        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
7485        return;
7486    }
7487
7488    Unique_sk_X509 chain(sk_X509_new_null());
7489    if (chain.get() == NULL) {
7490        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
7491        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
7492        return;
7493    }
7494
7495    for (size_t i = 1; i < length; i++) {
7496        Unique_X509 cert(
7497                X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[i]))));
7498        if (cert.get() == NULL || !sk_X509_push(chain.get(), cert.get())) {
7499            ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7500            throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
7501            safeSslClear(ssl);
7502            JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
7503            return;
7504        }
7505        OWNERSHIP_TRANSFERRED(cert);
7506    }
7507
7508    int ret = SSL_use_certificate(ssl, serverCert.get());
7509    if (ret != 1) {
7510        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7511        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
7512        safeSslClear(ssl);
7513        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
7514        return;
7515    }
7516    OWNERSHIP_TRANSFERRED(serverCert);
7517
7518    int chainResult = SSL_use_certificate_chain(ssl, chain.get());
7519    if (chainResult == 0) {
7520        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
7521        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
7522                  ssl);
7523        return;
7524    }
7525    OWNERSHIP_TRANSFERRED(chain);
7526
7527    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
7528}
7529
7530static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jlong ssl_address)
7531{
7532    SSL* ssl = to_SSL(env, ssl_address, true);
7533    JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
7534    if (ssl == NULL) {
7535        return;
7536    }
7537    int ret = SSL_check_private_key(ssl);
7538    if (ret != 1) {
7539        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
7540        safeSslClear(ssl);
7541        JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
7542        return;
7543    }
7544    JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
7545}
7546
7547static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
7548                                                jlong ssl_address, jobjectArray principals)
7549{
7550    SSL* ssl = to_SSL(env, ssl_address, true);
7551    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7552    if (ssl == NULL) {
7553        return;
7554    }
7555
7556    if (principals == NULL) {
7557        jniThrowNullPointerException(env, "principals == null");
7558        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7559        return;
7560    }
7561
7562    int length = env->GetArrayLength(principals);
7563    if (length == 0) {
7564        jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
7565        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7566        return;
7567    }
7568
7569    Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
7570    if (principalsStack.get() == NULL) {
7571        jniThrowOutOfMemory(env, "Unable to allocate principal stack");
7572        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7573        return;
7574    }
7575    for (int i = 0; i < length; i++) {
7576        ScopedLocalRef<jbyteArray> principal(env,
7577                reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7578        if (principal.get() == NULL) {
7579            jniThrowNullPointerException(env, "principals element == null");
7580            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
7581            return;
7582        }
7583
7584        ScopedByteArrayRO buf(env, principal.get());
7585        if (buf.get() == NULL) {
7586            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
7587            return;
7588        }
7589        const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
7590        Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
7591
7592        if (principalX509Name.get() == NULL) {
7593            ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7594            throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
7595            safeSslClear(ssl);
7596            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
7597                      ssl);
7598            return;
7599        }
7600
7601        if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
7602            jniThrowOutOfMemory(env, "Unable to push principal");
7603            JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7604            return;
7605        }
7606    }
7607
7608    SSL_set_client_CA_list(ssl, principalsStack.release());
7609    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7610}
7611
7612/**
7613 * public static native long SSL_get_mode(long ssl);
7614 */
7615static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address) {
7616    SSL* ssl = to_SSL(env, ssl_address, true);
7617    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
7618    if (ssl == NULL) {
7619      return 0;
7620    }
7621    long mode = SSL_get_mode(ssl);
7622    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
7623    return mode;
7624}
7625
7626/**
7627 * public static native long SSL_set_mode(long ssl, long mode);
7628 */
7629static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
7630        jlong ssl_address, jlong mode) {
7631    SSL* ssl = to_SSL(env, ssl_address, true);
7632    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
7633    if (ssl == NULL) {
7634      return 0;
7635    }
7636    long result = SSL_set_mode(ssl, mode);
7637    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
7638    return result;
7639}
7640
7641/**
7642 * public static native long SSL_clear_mode(long ssl, long mode);
7643 */
7644static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
7645        jlong ssl_address, jlong mode) {
7646    SSL* ssl = to_SSL(env, ssl_address, true);
7647    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
7648    if (ssl == NULL) {
7649      return 0;
7650    }
7651    long result = SSL_clear_mode(ssl, mode);
7652    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
7653    return result;
7654}
7655
7656/**
7657 * public static native long SSL_get_options(long ssl);
7658 */
7659static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
7660        jlong ssl_address) {
7661    SSL* ssl = to_SSL(env, ssl_address, true);
7662    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
7663    if (ssl == NULL) {
7664      return 0;
7665    }
7666    long options = SSL_get_options(ssl);
7667    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
7668    return options;
7669}
7670
7671/**
7672 * public static native long SSL_set_options(long ssl, long options);
7673 */
7674static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
7675        jlong ssl_address, jlong options) {
7676    SSL* ssl = to_SSL(env, ssl_address, true);
7677    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
7678    if (ssl == NULL) {
7679      return 0;
7680    }
7681    long result = SSL_set_options(ssl, options);
7682    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
7683    return result;
7684}
7685
7686/**
7687 * public static native long SSL_clear_options(long ssl, long options);
7688 */
7689static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
7690        jlong ssl_address, jlong options) {
7691    SSL* ssl = to_SSL(env, ssl_address, true);
7692    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
7693    if (ssl == NULL) {
7694      return 0;
7695    }
7696    long result = SSL_clear_options(ssl, options);
7697    JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
7698    return result;
7699}
7700
7701
7702static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass,
7703        jlong ssl_address, jstring identityHintJava)
7704{
7705    SSL* ssl = to_SSL(env, ssl_address, true);
7706    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p",
7707            ssl, identityHintJava);
7708    if (ssl == NULL)  {
7709        return;
7710    }
7711
7712    int ret;
7713    if (identityHintJava == NULL) {
7714        ret = SSL_use_psk_identity_hint(ssl, NULL);
7715    } else {
7716        ScopedUtfChars identityHint(env, identityHintJava);
7717        if (identityHint.c_str() == NULL) {
7718            throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7719            return;
7720        }
7721        ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7722    }
7723
7724    if (ret != 1) {
7725        int sslErrorCode = SSL_get_error(ssl, ret);
7726        throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Failed to set PSK identity hint");
7727        safeSslClear(ssl);
7728    }
7729}
7730
7731static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass,
7732        jlong ssl_address, jboolean enabled)
7733{
7734    SSL* ssl = to_SSL(env, ssl_address, true);
7735    JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)",
7736            ssl, enabled);
7737    if (ssl == NULL)  {
7738        return;
7739    }
7740
7741    SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : NULL);
7742}
7743
7744static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass,
7745        jlong ssl_address, jboolean enabled)
7746{
7747    SSL* ssl = to_SSL(env, ssl_address, true);
7748    JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)",
7749            ssl, enabled);
7750    if (ssl == NULL)  {
7751        return;
7752    }
7753
7754    SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : NULL);
7755}
7756
7757static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address)
7758{
7759    SSL* ssl = to_SSL(env, ssl_address, true);
7760    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7761
7762    STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7763    int count = (cipherStack != NULL) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7764    ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(count));
7765    ScopedLongArrayRW ciphers(env, ciphersArray.get());
7766    for (int i = 0; i < count; i++) {
7767        ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7768    }
7769
7770    JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%d]", ssl, ciphersArray.get(), count);
7771    return ciphersArray.release();
7772}
7773
7774static jint NativeCrypto_get_SSL_CIPHER_algorithm_mkey(JNIEnv* env, jclass,
7775        jlong ssl_cipher_address)
7776{
7777    SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
7778    JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_mkey => %ld", cipher, cipher->algorithm_mkey);
7779    return cipher->algorithm_mkey;
7780}
7781
7782static jint NativeCrypto_get_SSL_CIPHER_algorithm_auth(JNIEnv* env, jclass,
7783        jlong ssl_cipher_address)
7784{
7785    SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
7786    JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_auth => %ld", cipher, cipher->algorithm_auth);
7787    return cipher->algorithm_auth;
7788}
7789
7790/**
7791 * Sets the ciphers suites that are enabled in the SSL
7792 */
7793static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
7794        jlong ssl_address, jobjectArray cipherSuites)
7795{
7796    SSL* ssl = to_SSL(env, ssl_address, true);
7797    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7798    if (ssl == NULL) {
7799        return;
7800    }
7801    if (cipherSuites == NULL) {
7802        jniThrowNullPointerException(env, "cipherSuites == null");
7803        return;
7804    }
7805
7806    Unique_sk_SSL_CIPHER cipherstack(sk_SSL_CIPHER_new_null());
7807    if (cipherstack.get() == NULL) {
7808        jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
7809        return;
7810    }
7811
7812    const SSL_METHOD* ssl_method = ssl->method;
7813    int num_ciphers = ssl_method->num_ciphers();
7814
7815    int length = env->GetArrayLength(cipherSuites);
7816    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
7817    for (int i = 0; i < length; i++) {
7818        ScopedLocalRef<jstring> cipherSuite(env,
7819                reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7820        ScopedUtfChars c(env, cipherSuite.get());
7821        if (c.c_str() == NULL) {
7822            return;
7823        }
7824        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
7825        bool found = false;
7826        for (int j = 0; j < num_ciphers; j++) {
7827            const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
7828            if ((strcmp(c.c_str(), cipher->name) == 0)
7829                    && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
7830                if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
7831                    jniThrowOutOfMemory(env, "Unable to push cipher");
7832                    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
7833                    return;
7834                }
7835                found = true;
7836            }
7837        }
7838        if (!found) {
7839            jniThrowException(env, "java/lang/IllegalArgumentException",
7840                              "Could not find cipher suite.");
7841            return;
7842        }
7843    }
7844
7845    int rc = SSL_set_cipher_lists(ssl, cipherstack.get());
7846    if (rc == 0) {
7847        freeOpenSslErrorState();
7848        jniThrowException(env, "java/lang/IllegalArgumentException",
7849                          "Illegal cipher suite strings.");
7850    } else {
7851        OWNERSHIP_TRANSFERRED(cipherstack);
7852    }
7853}
7854
7855static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong sslRef) {
7856    SSL* ssl = to_SSL(env, sslRef, true);
7857    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7858    if (ssl == NULL) {
7859      return;
7860    }
7861    SSL_set_accept_state(ssl);
7862}
7863
7864static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong sslRef) {
7865    SSL* ssl = to_SSL(env, sslRef, true);
7866    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7867    if (ssl == NULL) {
7868      return;
7869    }
7870    SSL_set_connect_state(ssl);
7871}
7872
7873/**
7874 * Sets certificate expectations, especially for server to request client auth
7875 */
7876static void NativeCrypto_SSL_set_verify(JNIEnv* env,
7877        jclass, jlong ssl_address, jint mode)
7878{
7879    SSL* ssl = to_SSL(env, ssl_address, true);
7880    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7881    if (ssl == NULL) {
7882      return;
7883    }
7884    SSL_set_verify(ssl, (int)mode, NULL);
7885}
7886
7887/**
7888 * Sets the ciphers suites that are enabled in the SSL
7889 */
7890static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
7891        jlong ssl_address, jlong ssl_session_address)
7892{
7893    SSL* ssl = to_SSL(env, ssl_address, true);
7894    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7895    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7896    if (ssl == NULL) {
7897        return;
7898    }
7899
7900    int ret = SSL_set_session(ssl, ssl_session);
7901    if (ret != 1) {
7902        /*
7903         * Translate the error, and throw if it turns out to be a real
7904         * problem.
7905         */
7906        int sslErrorCode = SSL_get_error(ssl, ret);
7907        if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7908            throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
7909            safeSslClear(ssl);
7910        }
7911    }
7912}
7913
7914/**
7915 * Sets the ciphers suites that are enabled in the SSL
7916 */
7917static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
7918        jlong ssl_address, jboolean creation_enabled)
7919{
7920    SSL* ssl = to_SSL(env, ssl_address, true);
7921    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
7922              ssl, creation_enabled);
7923    if (ssl == NULL) {
7924        return;
7925    }
7926    SSL_set_session_creation_enabled(ssl, creation_enabled);
7927}
7928
7929static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
7930        jlong ssl_address, jstring hostname)
7931{
7932    SSL* ssl = to_SSL(env, ssl_address, true);
7933    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
7934              ssl, hostname);
7935    if (ssl == NULL) {
7936        return;
7937    }
7938
7939    ScopedUtfChars hostnameChars(env, hostname);
7940    if (hostnameChars.c_str() == NULL) {
7941        return;
7942    }
7943    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s",
7944              ssl, hostnameChars.c_str());
7945
7946    int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7947    if (ret != 1) {
7948        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
7949        safeSslClear(ssl);
7950        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7951        return;
7952    }
7953    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7954}
7955
7956static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address) {
7957    SSL* ssl = to_SSL(env, ssl_address, true);
7958    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7959    if (ssl == NULL) {
7960        return NULL;
7961    }
7962    const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7963    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7964    return env->NewStringUTF(servername);
7965}
7966
7967/**
7968 * A common selection path for both NPN and ALPN since they're essentially the
7969 * same protocol. The list of protocols in "primary" is considered the order
7970 * which should take precedence.
7971 */
7972static int proto_select(SSL* ssl __attribute__ ((unused)),
7973        unsigned char **out, unsigned char *outLength,
7974        const unsigned char *primary, const unsigned int primaryLength,
7975        const unsigned char *secondary, const unsigned int secondaryLength) {
7976    if (primary != NULL && secondary != NULL) {
7977        JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
7978
7979        int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
7980                secondaryLength);
7981        switch (status) {
7982        case OPENSSL_NPN_NEGOTIATED:
7983            JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
7984            return SSL_TLSEXT_ERR_OK;
7985            break;
7986        case OPENSSL_NPN_UNSUPPORTED:
7987            JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
7988            break;
7989        case OPENSSL_NPN_NO_OVERLAP:
7990            JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
7991            break;
7992        }
7993    } else {
7994        if (out != NULL && outLength != NULL) {
7995            *out = NULL;
7996            *outLength = 0;
7997        }
7998        JNI_TRACE("protocols=NULL");
7999    }
8000    return SSL_TLSEXT_ERR_NOACK;
8001}
8002
8003/**
8004 * Callback for the server to select an ALPN protocol.
8005 */
8006static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
8007        const unsigned char *in, unsigned int inlen, void *) {
8008    JNI_TRACE("ssl=%p alpn_select_callback", ssl);
8009
8010    AppData* appData = toAppData(ssl);
8011    JNI_TRACE("AppData=%p", appData);
8012
8013    return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
8014            reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
8015            appData->alpnProtocolsLength, in, inlen);
8016}
8017
8018/**
8019 * Callback for the client to select an NPN protocol.
8020 */
8021static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
8022                                      const unsigned char* in, unsigned int inlen, void*)
8023{
8024    JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
8025
8026    AppData* appData = toAppData(ssl);
8027    JNI_TRACE("AppData=%p", appData);
8028
8029    // Enable False Start on the client if the server understands NPN
8030    // http://www.imperialviolet.org/2012/04/11/falsestart.html
8031    SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
8032
8033    return proto_select(ssl, out, outlen, in, inlen,
8034            reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
8035            appData->npnProtocolsLength);
8036}
8037
8038/**
8039 * Callback for the server to advertise available protocols.
8040 */
8041static int next_protos_advertised_callback(SSL* ssl,
8042        const unsigned char **out, unsigned int *outlen, void *)
8043{
8044    JNI_TRACE("ssl=%p next_protos_advertised_callback", ssl);
8045    AppData* appData = toAppData(ssl);
8046    unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
8047    if (npnProtocols != NULL) {
8048        *out = npnProtocols;
8049        *outlen = appData->npnProtocolsLength;
8050        return SSL_TLSEXT_ERR_OK;
8051    } else {
8052        *out = NULL;
8053        *outlen = 0;
8054        return SSL_TLSEXT_ERR_NOACK;
8055    }
8056}
8057
8058static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
8059{
8060    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8061    if (ssl_ctx == NULL) {
8062        return;
8063    }
8064    SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); // client
8065    SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_protos_advertised_callback, NULL); // server
8066}
8067
8068static void NativeCrypto_SSL_CTX_disable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
8069{
8070    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8071    if (ssl_ctx == NULL) {
8072        return;
8073    }
8074    SSL_CTX_set_next_proto_select_cb(ssl_ctx, NULL, NULL); // client
8075    SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, NULL, NULL); // server
8076}
8077
8078static jbyteArray NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv* env, jclass,
8079        jlong ssl_address)
8080{
8081    SSL* ssl = to_SSL(env, ssl_address, true);
8082    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_npn_negotiated_protocol", ssl);
8083    if (ssl == NULL) {
8084        return NULL;
8085    }
8086    const jbyte* npn;
8087    unsigned npnLength;
8088    SSL_get0_next_proto_negotiated(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
8089    if (npnLength == 0) {
8090        return NULL;
8091    }
8092    jbyteArray result = env->NewByteArray(npnLength);
8093    if (result != NULL) {
8094        env->SetByteArrayRegion(result, 0, npnLength, npn);
8095    }
8096    return result;
8097}
8098
8099static int NativeCrypto_SSL_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_address,
8100        jbyteArray protos) {
8101    SSL* ssl = to_SSL(env, ssl_address, true);
8102    if (ssl == NULL) {
8103        return 0;
8104    }
8105
8106    JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p", ssl, protos);
8107
8108    if (protos == NULL) {
8109        JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=NULL", ssl);
8110        return 1;
8111    }
8112
8113    ScopedByteArrayRO protosBytes(env, protos);
8114    if (protosBytes.get() == NULL) {
8115        JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => protosBytes == NULL", ssl,
8116                protos);
8117        return 0;
8118    }
8119
8120    const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8121    int ret = SSL_set_alpn_protos(ssl, tmp, protosBytes.size());
8122    JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => ret=%d", ssl, protos, ret);
8123    return ret;
8124}
8125
8126static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
8127        jlong ssl_address)
8128{
8129    SSL* ssl = to_SSL(env, ssl_address, true);
8130    JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
8131    if (ssl == NULL) {
8132        return NULL;
8133    }
8134    const jbyte* npn;
8135    unsigned npnLength;
8136    SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
8137    if (npnLength == 0) {
8138        return NULL;
8139    }
8140    jbyteArray result = env->NewByteArray(npnLength);
8141    if (result != NULL) {
8142        env->SetByteArrayRegion(result, 0, npnLength, npn);
8143    }
8144    return result;
8145}
8146
8147#ifdef WITH_JNI_TRACE_KEYS
8148static inline char hex_char(unsigned char in)
8149{
8150    if (in < 10) {
8151        return '0' + in;
8152    } else if (in <= 0xF0) {
8153        return 'A' + in - 10;
8154    } else {
8155        return '?';
8156    }
8157}
8158
8159static void hex_string(char **dest, unsigned char* input, int len)
8160{
8161    *dest = (char*) malloc(len * 2 + 1);
8162    char *output = *dest;
8163    for (int i = 0; i < len; i++) {
8164        *output++ = hex_char(input[i] >> 4);
8165        *output++ = hex_char(input[i] & 0xF);
8166    }
8167    *output = '\0';
8168}
8169
8170static void debug_print_session_key(SSL_SESSION* session)
8171{
8172    char *session_id_str;
8173    char *master_key_str;
8174    const char *key_type;
8175    char *keyline;
8176
8177    hex_string(&session_id_str, session->session_id, session->session_id_length);
8178    hex_string(&master_key_str, session->master_key, session->master_key_length);
8179
8180    X509* peer = SSL_SESSION_get0_peer(session);
8181    EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
8182    switch (EVP_PKEY_type(pkey->type)) {
8183    case EVP_PKEY_RSA:
8184        key_type = "RSA";
8185        break;
8186    case EVP_PKEY_DSA:
8187        key_type = "DSA";
8188        break;
8189    case EVP_PKEY_EC:
8190        key_type = "EC";
8191        break;
8192    default:
8193        key_type = "Unknown";
8194        break;
8195    }
8196
8197    asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
8198            master_key_str);
8199    JNI_TRACE("ssl_session=%p %s", session, keyline);
8200
8201    free(session_id_str);
8202    free(master_key_str);
8203    free(keyline);
8204}
8205#endif /* WITH_JNI_TRACE_KEYS */
8206
8207/**
8208 * Perform SSL handshake
8209 */
8210static jlong NativeCrypto_SSL_do_handshake_bio(JNIEnv* env, jclass, jlong ssl_address,
8211        jlong rbioRef, jlong wbioRef, jobject shc, jboolean client_mode, jbyteArray npnProtocols,
8212        jbyteArray alpnProtocols) {
8213    SSL* ssl = to_SSL(env, ssl_address, true);
8214    BIO* rbio = reinterpret_cast<BIO*>(rbioRef);
8215    BIO* wbio = reinterpret_cast<BIO*>(wbioRef);
8216    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio rbio=%p wbio=%p shc=%p client_mode=%d npn=%p",
8217              ssl, rbio, wbio, shc, client_mode, npnProtocols);
8218    if (ssl == NULL) {
8219        return 0;
8220    }
8221    if (shc == NULL) {
8222        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8223        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio sslHandshakeCallbacks == null => 0", ssl);
8224        return 0;
8225    }
8226
8227    if (rbio == NULL || wbio == NULL) {
8228        jniThrowNullPointerException(env, "rbio == null || wbio == null");
8229        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => rbio == null || wbio == NULL", ssl);
8230        return 0;
8231    }
8232
8233    ScopedSslBio sslBio(ssl, rbio, wbio);
8234
8235    AppData* appData = toAppData(ssl);
8236    if (appData == NULL) {
8237        throwSSLExceptionStr(env, "Unable to retrieve application data");
8238        safeSslClear(ssl);
8239        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
8240        return 0;
8241    }
8242
8243    if (!client_mode && alpnProtocols != NULL) {
8244        SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
8245    }
8246
8247    int ret = 0;
8248    errno = 0;
8249
8250    if (!appData->setCallbackState(env, shc, NULL, npnProtocols, alpnProtocols)) {
8251        freeOpenSslErrorState();
8252        safeSslClear(ssl);
8253        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio setCallbackState => 0", ssl);
8254        return 0;
8255    }
8256    ret = SSL_do_handshake(ssl);
8257    appData->clearCallbackState();
8258    // cert_verify_callback threw exception
8259    if (env->ExceptionCheck()) {
8260        freeOpenSslErrorState();
8261        safeSslClear(ssl);
8262        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio exception => 0", ssl);
8263        return 0;
8264    }
8265
8266    if (ret <= 0) { // error. See SSL_do_handshake(3SSL) man page.
8267        // error case
8268        OpenSslError sslError(ssl, ret);
8269        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio ret=%d errno=%d sslError=%d",
8270                  ssl, ret, errno, sslError.get());
8271
8272        /*
8273         * If SSL_do_handshake doesn't succeed due to the socket being
8274         * either unreadable or unwritable, we need to exit to allow
8275         * the SSLEngine code to wrap or unwrap.
8276         */
8277        if (sslError.get() == SSL_ERROR_NONE ||
8278                (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8279                (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8280            throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8281            safeSslClear(ssl);
8282        } else if (sslError.get() != SSL_ERROR_WANT_READ &&
8283                sslError.get() != SSL_ERROR_WANT_WRITE) {
8284            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8285                    "SSL handshake terminated", throwSSLHandshakeExceptionStr);
8286            safeSslClear(ssl);
8287        }
8288        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio error => 0", ssl);
8289        return 0;
8290    }
8291
8292    // success. handshake completed
8293    SSL_SESSION* ssl_session = SSL_get1_session(ssl);
8294    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => ssl_session=%p", ssl, ssl_session);
8295#ifdef WITH_JNI_TRACE_KEYS
8296    debug_print_session_key(ssl_session);
8297#endif
8298    return reinterpret_cast<uintptr_t>(ssl_session);
8299}
8300
8301/**
8302 * Perform SSL handshake
8303 */
8304static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8305        jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
8306        jbyteArray alpnProtocols) {
8307    SSL* ssl = to_SSL(env, ssl_address, true);
8308    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
8309              ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
8310    if (ssl == NULL) {
8311        return 0;
8312    }
8313    if (fdObject == NULL) {
8314        jniThrowNullPointerException(env, "fd == null");
8315        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => 0", ssl);
8316        return 0;
8317    }
8318    if (shc == NULL) {
8319        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8320        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => 0", ssl);
8321        return 0;
8322    }
8323
8324    NetFd fd(env, fdObject);
8325    if (fd.isClosed()) {
8326        // SocketException thrown by NetFd.isClosed
8327        safeSslClear(ssl);
8328        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => 0", ssl);
8329        return 0;
8330    }
8331
8332    int ret = SSL_set_fd(ssl, fd.get());
8333    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8334
8335    if (ret != 1) {
8336        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8337                                       "Error setting the file descriptor");
8338        safeSslClear(ssl);
8339        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => 0", ssl);
8340        return 0;
8341    }
8342
8343    /*
8344     * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8345     * forever and we can use select() to find out if the socket is ready.
8346     */
8347    if (!setBlocking(fd.get(), false)) {
8348        throwSSLExceptionStr(env, "Unable to make socket non blocking");
8349        safeSslClear(ssl);
8350        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => 0", ssl);
8351        return 0;
8352    }
8353
8354    AppData* appData = toAppData(ssl);
8355    if (appData == NULL) {
8356        throwSSLExceptionStr(env, "Unable to retrieve application data");
8357        safeSslClear(ssl);
8358        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
8359        return 0;
8360    }
8361
8362    if (client_mode) {
8363        SSL_set_connect_state(ssl);
8364    } else {
8365        SSL_set_accept_state(ssl);
8366        if (alpnProtocols != NULL) {
8367            SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
8368        }
8369    }
8370
8371    ret = 0;
8372    OpenSslError sslError;
8373    while (appData->aliveAndKicking) {
8374        errno = 0;
8375
8376        if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
8377            // SocketException thrown by NetFd.isClosed
8378            safeSslClear(ssl);
8379            JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
8380            return 0;
8381        }
8382        ret = SSL_do_handshake(ssl);
8383        appData->clearCallbackState();
8384        // cert_verify_callback threw exception
8385        if (env->ExceptionCheck()) {
8386            freeOpenSslErrorState();
8387            safeSslClear(ssl);
8388            JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => 0", ssl);
8389            return 0;
8390        }
8391        // success case
8392        if (ret == 1) {
8393            break;
8394        }
8395        // retry case
8396        if (errno == EINTR) {
8397            continue;
8398        }
8399        // error case
8400        sslError.reset(ssl, ret);
8401        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout_millis=%d",
8402                  ssl, ret, errno, sslError.get(), timeout_millis);
8403
8404        /*
8405         * If SSL_do_handshake doesn't succeed due to the socket being
8406         * either unreadable or unwritable, we use sslSelect to
8407         * wait for it to become ready. If that doesn't happen
8408         * before the specified timeout or an error occurs, we
8409         * cancel the handshake. Otherwise we try the SSL_connect
8410         * again.
8411         */
8412        if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8413            appData->waitingThreads++;
8414            int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8415
8416            if (selectResult == THROWN_EXCEPTION) {
8417                // SocketException thrown by NetFd.isClosed
8418                safeSslClear(ssl);
8419                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => 0", ssl);
8420                return 0;
8421            }
8422            if (selectResult == -1) {
8423                throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8424                        throwSSLHandshakeExceptionStr);
8425                safeSslClear(ssl);
8426                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => 0", ssl);
8427                return 0;
8428            }
8429            if (selectResult == 0) {
8430                throwSocketTimeoutException(env, "SSL handshake timed out");
8431                freeOpenSslErrorState();
8432                safeSslClear(ssl);
8433                JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => 0", ssl);
8434                return 0;
8435            }
8436        } else {
8437            // ALOGE("Unknown error %d during handshake", error);
8438            break;
8439        }
8440    }
8441
8442    // clean error. See SSL_do_handshake(3SSL) man page.
8443    if (ret == 0) {
8444        /*
8445         * The other side closed the socket before the handshake could be
8446         * completed, but everything is within the bounds of the TLS protocol.
8447         * We still might want to find out the real reason of the failure.
8448         */
8449        if (sslError.get() == SSL_ERROR_NONE ||
8450                (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8451                (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8452            throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8453        } else {
8454            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8455                    "SSL handshake terminated", throwSSLHandshakeExceptionStr);
8456        }
8457        safeSslClear(ssl);
8458        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => 0", ssl);
8459        return 0;
8460    }
8461
8462    // unclean error. See SSL_do_handshake(3SSL) man page.
8463    if (ret < 0) {
8464        /*
8465         * Translate the error and throw exception. We are sure it is an error
8466         * at this point.
8467         */
8468        throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "SSL handshake aborted",
8469                throwSSLHandshakeExceptionStr);
8470        safeSslClear(ssl);
8471        JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => 0", ssl);
8472        return 0;
8473    }
8474    SSL_SESSION* ssl_session = SSL_get1_session(ssl);
8475    JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
8476#ifdef WITH_JNI_TRACE_KEYS
8477    debug_print_session_key(ssl_session);
8478#endif
8479    return (jlong) ssl_session;
8480}
8481
8482/**
8483 * Perform SSL renegotiation
8484 */
8485static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jlong ssl_address)
8486{
8487    SSL* ssl = to_SSL(env, ssl_address, true);
8488    JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
8489    if (ssl == NULL) {
8490        return;
8491    }
8492    int result = SSL_renegotiate(ssl);
8493    if (result != 1) {
8494        throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
8495        return;
8496    }
8497    // first call asks client to perform renegotiation
8498    int ret = SSL_do_handshake(ssl);
8499    if (ret != 1) {
8500        OpenSslError sslError(ssl, ret);
8501        throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8502                                       "Problem with SSL_do_handshake after SSL_renegotiate");
8503        return;
8504    }
8505    // if client agrees, set ssl state and perform renegotiation
8506    ssl->state = SSL_ST_ACCEPT;
8507    SSL_do_handshake(ssl);
8508    JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
8509}
8510
8511/**
8512 * public static native byte[][] SSL_get_certificate(long ssl);
8513 */
8514static jlongArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jlong ssl_address)
8515{
8516    SSL* ssl = to_SSL(env, ssl_address, true);
8517    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
8518    if (ssl == NULL) {
8519        return NULL;
8520    }
8521    X509* certificate = SSL_get_certificate(ssl);
8522    if (certificate == NULL) {
8523        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8524        // SSL_get_certificate can return NULL during an error as well.
8525        freeOpenSslErrorState();
8526        return NULL;
8527    }
8528
8529    Unique_sk_X509 chain(sk_X509_new_null());
8530    if (chain.get() == NULL) {
8531        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
8532        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
8533        return NULL;
8534    }
8535    if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
8536        jniThrowOutOfMemory(env, "Unable to push local certificate");
8537        JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8538        return NULL;
8539    }
8540    STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
8541    for (int i=0; i<sk_X509_num(cert_chain); i++) {
8542        if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
8543            jniThrowOutOfMemory(env, "Unable to push local certificate chain");
8544            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8545            return NULL;
8546        }
8547    }
8548
8549    jlongArray refArray = getCertificateRefs(env, chain.get());
8550    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, refArray);
8551    return refArray;
8552}
8553
8554// Fills a long[] with the peer certificates in the chain.
8555static jlongArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jlong ssl_address)
8556{
8557    SSL* ssl = to_SSL(env, ssl_address, true);
8558    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
8559    if (ssl == NULL) {
8560        return NULL;
8561    }
8562    STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
8563    Unique_sk_X509 chain_copy(NULL);
8564    if (ssl->server) {
8565        X509* x509 = SSL_get_peer_certificate(ssl);
8566        if (x509 == NULL) {
8567            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
8568            return NULL;
8569        }
8570        chain_copy.reset(sk_X509_new_null());
8571        if (chain_copy.get() == NULL) {
8572            jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
8573            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
8574            return NULL;
8575        }
8576        size_t chain_size = sk_X509_num(chain);
8577        for (size_t i = 0; i < chain_size; i++) {
8578            if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
8579                jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
8580                JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
8581                return NULL;
8582            }
8583        }
8584        if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
8585            jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
8586            JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
8587            return NULL;
8588        }
8589        chain = chain_copy.get();
8590    }
8591    jlongArray refArray = getCertificateRefs(env, chain);
8592    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, refArray);
8593    return refArray;
8594}
8595
8596static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8597                   OpenSslError& sslError, int read_timeout_millis) {
8598    JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8599
8600    if (len == 0) {
8601        // Don't bother doing anything in this case.
8602        return 0;
8603    }
8604
8605    BIO* rbio = SSL_get_rbio(ssl);
8606    BIO* wbio = SSL_get_wbio(ssl);
8607
8608    AppData* appData = toAppData(ssl);
8609    JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8610    if (appData == NULL) {
8611        return THROW_SSLEXCEPTION;
8612    }
8613
8614    while (appData->aliveAndKicking) {
8615        errno = 0;
8616
8617        if (MUTEX_LOCK(appData->mutex) == -1) {
8618            return -1;
8619        }
8620
8621        if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
8622               !SSL_renegotiate_pending(ssl)) {
8623            JNI_TRACE("ssl=%p sslRead => init is not finished (state=0x%x)", ssl,
8624                    SSL_get_state(ssl));
8625            MUTEX_UNLOCK(appData->mutex);
8626            return THROW_SSLEXCEPTION;
8627        }
8628
8629        unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8630
8631        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8632            MUTEX_UNLOCK(appData->mutex);
8633            return THROWN_EXCEPTION;
8634        }
8635        int result = SSL_read(ssl, buf, len);
8636        appData->clearCallbackState();
8637        // callbacks can happen if server requests renegotiation
8638        if (env->ExceptionCheck()) {
8639            safeSslClear(ssl);
8640            JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8641            return THROWN_EXCEPTION;
8642        }
8643        sslError.reset(ssl, result);
8644        JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError.get());
8645#ifdef WITH_JNI_TRACE_DATA
8646        for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8647            int n = result - i;
8648            if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8649                n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8650            }
8651            JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
8652        }
8653#endif
8654
8655        // If we have been successful in moving data around, check whether it
8656        // might make sense to wake up other blocked threads, so they can give
8657        // it a try, too.
8658        if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
8659                && appData->waitingThreads > 0) {
8660            sslNotify(appData);
8661        }
8662
8663        // If we are blocked by the underlying socket, tell the world that
8664        // there will be one more waiting thread now.
8665        if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8666            appData->waitingThreads++;
8667        }
8668
8669        MUTEX_UNLOCK(appData->mutex);
8670
8671        switch (sslError.get()) {
8672            // Successfully read at least one byte.
8673            case SSL_ERROR_NONE: {
8674                return result;
8675            }
8676
8677            // Read zero bytes. End of stream reached.
8678            case SSL_ERROR_ZERO_RETURN: {
8679                return -1;
8680            }
8681
8682            // Need to wait for availability of underlying layer, then retry.
8683            case SSL_ERROR_WANT_READ:
8684            case SSL_ERROR_WANT_WRITE: {
8685                int selectResult = sslSelect(env, sslError.get(), fdObject, appData, read_timeout_millis);
8686                if (selectResult == THROWN_EXCEPTION) {
8687                    return THROWN_EXCEPTION;
8688                }
8689                if (selectResult == -1) {
8690                    return THROW_SSLEXCEPTION;
8691                }
8692                if (selectResult == 0) {
8693                    return THROW_SOCKETTIMEOUTEXCEPTION;
8694                }
8695
8696                break;
8697            }
8698
8699            // A problem occurred during a system call, but this is not
8700            // necessarily an error.
8701            case SSL_ERROR_SYSCALL: {
8702                // Connection closed without proper shutdown. Tell caller we
8703                // have reached end-of-stream.
8704                if (result == 0) {
8705                    return -1;
8706                }
8707
8708                // System call has been interrupted. Simply retry.
8709                if (errno == EINTR) {
8710                    break;
8711                }
8712
8713                // Note that for all other system call errors we fall through
8714                // to the default case, which results in an Exception.
8715            }
8716
8717            // Everything else is basically an error.
8718            default: {
8719                return THROW_SSLEXCEPTION;
8720            }
8721        }
8722    }
8723
8724    return -1;
8725}
8726
8727static jint NativeCrypto_SSL_read_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray destJava,
8728        jint destOffset, jint destLength, jlong sourceBioRef, jlong sinkBioRef, jobject shc) {
8729    SSL* ssl = to_SSL(env, sslRef, true);
8730    BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sourceBioRef));
8731    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
8732    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO dest=%p sourceBio=%p sinkBio=%p shc=%p",
8733              ssl, destJava, rbio, wbio, shc);
8734    if (ssl == NULL) {
8735        return 0;
8736    }
8737    if (rbio == NULL || wbio == NULL) {
8738        jniThrowNullPointerException(env, "rbio == null || wbio == null");
8739        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => rbio == null || wbio == null", ssl);
8740        return -1;
8741    }
8742    if (shc == NULL) {
8743        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8744        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => sslHandshakeCallbacks == null", ssl);
8745        return -1;
8746    }
8747
8748    ScopedByteArrayRW dest(env, destJava);
8749    if (dest.get() == NULL) {
8750        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
8751        return -1;
8752    }
8753    if (destOffset < 0 || destOffset > ssize_t(dest.size()) || destLength < 0
8754            || destLength > (ssize_t) dest.size() - destOffset) {
8755        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => destOffset=%d, destLength=%d, size=%zd",
8756                  destOffset, destLength, dest.size());
8757        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
8758        return -1;
8759    }
8760
8761    AppData* appData = toAppData(ssl);
8762    if (appData == NULL) {
8763        throwSSLExceptionStr(env, "Unable to retrieve application data");
8764        safeSslClear(ssl);
8765        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => appData == NULL", ssl);
8766        return -1;
8767    }
8768
8769    errno = 0;
8770
8771    if (MUTEX_LOCK(appData->mutex) == -1) {
8772        return -1;
8773    }
8774
8775    if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
8776        MUTEX_UNLOCK(appData->mutex);
8777        throwSSLExceptionStr(env, "Unable to set callback state");
8778        safeSslClear(ssl);
8779        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => set callback state failed", ssl);
8780        return -1;
8781    }
8782
8783    ScopedSslBio sslBio(ssl, rbio, wbio);
8784
8785    int result = SSL_read(ssl, dest.get() + destOffset, destLength);
8786    appData->clearCallbackState();
8787    // callbacks can happen if server requests renegotiation
8788    if (env->ExceptionCheck()) {
8789        safeSslClear(ssl);
8790        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
8791        return THROWN_EXCEPTION;
8792    }
8793    OpenSslError sslError(ssl, result);
8794    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO SSL_read result=%d sslError=%d", ssl, result,
8795              sslError.get());
8796#ifdef WITH_JNI_TRACE_DATA
8797    for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8798        int n = result - i;
8799        if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8800            n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8801        }
8802        JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
8803    }
8804#endif
8805
8806    MUTEX_UNLOCK(appData->mutex);
8807
8808    switch (sslError.get()) {
8809        // Successfully read at least one byte.
8810        case SSL_ERROR_NONE:
8811            break;
8812
8813        // Read zero bytes. End of stream reached.
8814        case SSL_ERROR_ZERO_RETURN:
8815            result = -1;
8816            break;
8817
8818        // Need to wait for availability of underlying layer, then retry.
8819        case SSL_ERROR_WANT_READ:
8820        case SSL_ERROR_WANT_WRITE:
8821            result = 0;
8822            break;
8823
8824        // A problem occurred during a system call, but this is not
8825        // necessarily an error.
8826        case SSL_ERROR_SYSCALL: {
8827            // Connection closed without proper shutdown. Tell caller we
8828            // have reached end-of-stream.
8829            if (result == 0) {
8830                result = -1;
8831                break;
8832            } else if (errno == EINTR) {
8833                // System call has been interrupted. Simply retry.
8834                result = 0;
8835                break;
8836            }
8837
8838            // Note that for all other system call errors we fall through
8839            // to the default case, which results in an Exception.
8840        }
8841
8842        // Everything else is basically an error.
8843        default: {
8844            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
8845            return -1;
8846        }
8847    }
8848    JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => %d", ssl, result);
8849    return result;
8850}
8851
8852/**
8853 * OpenSSL read function (2): read into buffer at offset n chunks.
8854 * Returns 1 (success) or value <= 0 (failure).
8855 */
8856static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8857                                  jobject shc, jbyteArray b, jint offset, jint len,
8858                                  jint read_timeout_millis)
8859{
8860    SSL* ssl = to_SSL(env, ssl_address, true);
8861    JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d read_timeout_millis=%d",
8862              ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8863    if (ssl == NULL) {
8864        return 0;
8865    }
8866    if (fdObject == NULL) {
8867        jniThrowNullPointerException(env, "fd == null");
8868        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8869        return 0;
8870    }
8871    if (shc == NULL) {
8872        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8873        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8874        return 0;
8875    }
8876
8877    ScopedByteArrayRW bytes(env, b);
8878    if (bytes.get() == NULL) {
8879        JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8880        return 0;
8881    }
8882
8883    OpenSslError sslError;
8884    int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8885                      sslError, read_timeout_millis);
8886
8887    int result;
8888    switch (ret) {
8889        case THROW_SSLEXCEPTION:
8890            // See sslRead() regarding improper failure to handle normal cases.
8891            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
8892            result = -1;
8893            break;
8894        case THROW_SOCKETTIMEOUTEXCEPTION:
8895            throwSocketTimeoutException(env, "Read timed out");
8896            result = -1;
8897            break;
8898        case THROWN_EXCEPTION:
8899            // SocketException thrown by NetFd.isClosed
8900            // or RuntimeException thrown by callback
8901            result = -1;
8902            break;
8903        default:
8904            result = ret;
8905            break;
8906    }
8907
8908    JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8909    return result;
8910}
8911
8912static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8913                    OpenSslError& sslError, int write_timeout_millis) {
8914    JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d",
8915              ssl, buf, len, write_timeout_millis);
8916
8917    if (len == 0) {
8918        // Don't bother doing anything in this case.
8919        return 0;
8920    }
8921
8922    BIO* rbio = SSL_get_rbio(ssl);
8923    BIO* wbio = SSL_get_wbio(ssl);
8924
8925    AppData* appData = toAppData(ssl);
8926    JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8927    if (appData == NULL) {
8928        return THROW_SSLEXCEPTION;
8929    }
8930
8931    int count = len;
8932
8933    while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
8934        errno = 0;
8935
8936        if (MUTEX_LOCK(appData->mutex) == -1) {
8937            return -1;
8938        }
8939
8940        if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
8941               !SSL_renegotiate_pending(ssl)) {
8942            JNI_TRACE("ssl=%p sslWrite => init is not finished (state=0x%x)", ssl,
8943                    SSL_get_state(ssl));
8944            MUTEX_UNLOCK(appData->mutex);
8945            return THROW_SSLEXCEPTION;
8946        }
8947
8948        unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8949
8950        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8951            MUTEX_UNLOCK(appData->mutex);
8952            return THROWN_EXCEPTION;
8953        }
8954        JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
8955        int result = SSL_write(ssl, buf, len);
8956        appData->clearCallbackState();
8957        // callbacks can happen if server requests renegotiation
8958        if (env->ExceptionCheck()) {
8959            safeSslClear(ssl);
8960            JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8961            return THROWN_EXCEPTION;
8962        }
8963        sslError.reset(ssl, result);
8964        JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
8965                  ssl, result, sslError.get(), ssl->s3->wbuf.left);
8966#ifdef WITH_JNI_TRACE_DATA
8967        for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8968            int n = result - i;
8969            if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8970                n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8971            }
8972            JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
8973        }
8974#endif
8975
8976        // If we have been successful in moving data around, check whether it
8977        // might make sense to wake up other blocked threads, so they can give
8978        // it a try, too.
8979        if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
8980                && appData->waitingThreads > 0) {
8981            sslNotify(appData);
8982        }
8983
8984        // If we are blocked by the underlying socket, tell the world that
8985        // there will be one more waiting thread now.
8986        if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8987            appData->waitingThreads++;
8988        }
8989
8990        MUTEX_UNLOCK(appData->mutex);
8991
8992        switch (sslError.get()) {
8993            // Successfully wrote at least one byte.
8994            case SSL_ERROR_NONE: {
8995                buf += result;
8996                len -= result;
8997                break;
8998            }
8999
9000            // Wrote zero bytes. End of stream reached.
9001            case SSL_ERROR_ZERO_RETURN: {
9002                return -1;
9003            }
9004
9005            // Need to wait for availability of underlying layer, then retry.
9006            // The concept of a write timeout doesn't really make sense, and
9007            // it's also not standard Java behavior, so we wait forever here.
9008            case SSL_ERROR_WANT_READ:
9009            case SSL_ERROR_WANT_WRITE: {
9010                int selectResult = sslSelect(env, sslError.get(), fdObject, appData,
9011                                             write_timeout_millis);
9012                if (selectResult == THROWN_EXCEPTION) {
9013                    return THROWN_EXCEPTION;
9014                }
9015                if (selectResult == -1) {
9016                    return THROW_SSLEXCEPTION;
9017                }
9018                if (selectResult == 0) {
9019                    return THROW_SOCKETTIMEOUTEXCEPTION;
9020                }
9021
9022                break;
9023            }
9024
9025            // A problem occurred during a system call, but this is not
9026            // necessarily an error.
9027            case SSL_ERROR_SYSCALL: {
9028                // Connection closed without proper shutdown. Tell caller we
9029                // have reached end-of-stream.
9030                if (result == 0) {
9031                    return -1;
9032                }
9033
9034                // System call has been interrupted. Simply retry.
9035                if (errno == EINTR) {
9036                    break;
9037                }
9038
9039                // Note that for all other system call errors we fall through
9040                // to the default case, which results in an Exception.
9041            }
9042
9043            // Everything else is basically an error.
9044            default: {
9045                return THROW_SSLEXCEPTION;
9046            }
9047        }
9048    }
9049    JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9050
9051    return count;
9052}
9053
9054/**
9055 * OpenSSL write function (2): write into buffer at offset n chunks.
9056 */
9057static int NativeCrypto_SSL_write_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray sourceJava, jint len,
9058        jlong sinkBioRef, jobject shc) {
9059    SSL* ssl = to_SSL(env, sslRef, true);
9060    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
9061    JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO source=%p len=%d wbio=%p shc=%p",
9062              ssl, sourceJava, len, wbio, shc);
9063    if (ssl == NULL) {
9064        return -1;
9065    }
9066    if (wbio == NULL) {
9067        jniThrowNullPointerException(env, "wbio == null");
9068        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => wbio == null", ssl);
9069        return -1;
9070    }
9071    if (shc == NULL) {
9072        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9073        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => sslHandshakeCallbacks == null", ssl);
9074        return -1;
9075    }
9076
9077    AppData* appData = toAppData(ssl);
9078    if (appData == NULL) {
9079        throwSSLExceptionStr(env, "Unable to retrieve application data");
9080        safeSslClear(ssl);
9081        freeOpenSslErrorState();
9082        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO appData => NULL", ssl);
9083        return -1;
9084    }
9085
9086    errno = 0;
9087
9088    if (MUTEX_LOCK(appData->mutex) == -1) {
9089        return 0;
9090    }
9091
9092    if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
9093        MUTEX_UNLOCK(appData->mutex);
9094        throwSSLExceptionStr(env, "Unable to set appdata callback");
9095        freeOpenSslErrorState();
9096        safeSslClear(ssl);
9097        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => appData can't set callback", ssl);
9098        return -1;
9099    }
9100
9101    ScopedByteArrayRO source(env, sourceJava);
9102    if (source.get() == NULL) {
9103        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => threw exception", ssl);
9104        return -1;
9105    }
9106
9107    Unique_BIO nullBio(BIO_new(BIO_s_null()));
9108    ScopedSslBio sslBio(ssl, nullBio.get(), wbio);
9109
9110    int result = SSL_write(ssl, reinterpret_cast<const char*>(source.get()), len);
9111    appData->clearCallbackState();
9112    // callbacks can happen if server requests renegotiation
9113    if (env->ExceptionCheck()) {
9114        freeOpenSslErrorState();
9115        safeSslClear(ssl);
9116        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO exception => exception pending (reneg)", ssl);
9117        return -1;
9118    }
9119    OpenSslError sslError(ssl, result);
9120    JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO SSL_write result=%d sslError=%d left=%d",
9121              ssl, result, sslError.get(), ssl->s3->wbuf.left);
9122#ifdef WITH_JNI_TRACE_DATA
9123    for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9124        int n = result - i;
9125        if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9126            n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
9127        }
9128        JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
9129    }
9130#endif
9131
9132    MUTEX_UNLOCK(appData->mutex);
9133
9134    switch (sslError.get()) {
9135        case SSL_ERROR_NONE:
9136            return result;
9137
9138        // Wrote zero bytes. End of stream reached.
9139        case SSL_ERROR_ZERO_RETURN:
9140            return -1;
9141
9142        case SSL_ERROR_WANT_READ:
9143        case SSL_ERROR_WANT_WRITE:
9144            return 0;
9145
9146        case SSL_ERROR_SYSCALL: {
9147            // Connection closed without proper shutdown. Tell caller we
9148            // have reached end-of-stream.
9149            if (result == 0) {
9150                return -1;
9151            }
9152
9153            // System call has been interrupted. Simply retry.
9154            if (errno == EINTR) {
9155                return 0;
9156            }
9157
9158            // Note that for all other system call errors we fall through
9159            // to the default case, which results in an Exception.
9160        }
9161
9162        // Everything else is basically an error.
9163        default: {
9164            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
9165            break;
9166        }
9167    }
9168    return -1;
9169}
9170
9171/**
9172 * OpenSSL write function (2): write into buffer at offset n chunks.
9173 */
9174static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
9175                                   jobject shc, jbyteArray b, jint offset, jint len, jint write_timeout_millis)
9176{
9177    SSL* ssl = to_SSL(env, ssl_address, true);
9178    JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d write_timeout_millis=%d",
9179              ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9180    if (ssl == NULL) {
9181        return;
9182    }
9183    if (fdObject == NULL) {
9184        jniThrowNullPointerException(env, "fd == null");
9185        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9186        return;
9187    }
9188    if (shc == NULL) {
9189        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9190        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9191        return;
9192    }
9193
9194    ScopedByteArrayRO bytes(env, b);
9195    if (bytes.get() == NULL) {
9196        JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9197        return;
9198    }
9199    OpenSslError sslError;
9200    int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9201                       len, sslError, write_timeout_millis);
9202
9203    switch (ret) {
9204        case THROW_SSLEXCEPTION:
9205            // See sslWrite() regarding improper failure to handle normal cases.
9206            throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
9207            break;
9208        case THROW_SOCKETTIMEOUTEXCEPTION:
9209            throwSocketTimeoutException(env, "Write timed out");
9210            break;
9211        case THROWN_EXCEPTION:
9212            // SocketException thrown by NetFd.isClosed
9213            break;
9214        default:
9215            break;
9216    }
9217}
9218
9219/**
9220 * Interrupt any pending I/O before closing the socket.
9221 */
9222static void NativeCrypto_SSL_interrupt(
9223        JNIEnv* env, jclass, jlong ssl_address) {
9224    SSL* ssl = to_SSL(env, ssl_address, false);
9225    JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9226    if (ssl == NULL) {
9227        return;
9228    }
9229
9230    /*
9231     * Mark the connection as quasi-dead, then send something to the emergency
9232     * file descriptor, so any blocking select() calls are woken up.
9233     */
9234    AppData* appData = toAppData(ssl);
9235    if (appData != NULL) {
9236        appData->aliveAndKicking = 0;
9237
9238        // At most two threads can be waiting.
9239        sslNotify(appData);
9240        sslNotify(appData);
9241    }
9242}
9243
9244/**
9245 * OpenSSL close SSL socket function.
9246 */
9247static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9248                                      jobject fdObject, jobject shc) {
9249    SSL* ssl = to_SSL(env, ssl_address, false);
9250    JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9251    if (ssl == NULL) {
9252        return;
9253    }
9254    if (fdObject == NULL) {
9255        jniThrowNullPointerException(env, "fd == null");
9256        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
9257        return;
9258    }
9259    if (shc == NULL) {
9260        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9261        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9262        return;
9263    }
9264
9265    AppData* appData = toAppData(ssl);
9266    if (appData != NULL) {
9267        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
9268            // SocketException thrown by NetFd.isClosed
9269            freeOpenSslErrorState();
9270            safeSslClear(ssl);
9271            return;
9272        }
9273
9274        /*
9275         * Try to make socket blocking again. OpenSSL literature recommends this.
9276         */
9277        int fd = SSL_get_fd(ssl);
9278        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9279        if (fd != -1) {
9280            setBlocking(fd, true);
9281        }
9282
9283        int ret = SSL_shutdown(ssl);
9284        appData->clearCallbackState();
9285        // callbacks can happen if server requests renegotiation
9286        if (env->ExceptionCheck()) {
9287            safeSslClear(ssl);
9288            JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9289            return;
9290        }
9291        switch (ret) {
9292            case 0:
9293                /*
9294                 * Shutdown was not successful (yet), but there also
9295                 * is no error. Since we can't know whether the remote
9296                 * server is actually still there, and we don't want to
9297                 * get stuck forever in a second SSL_shutdown() call, we
9298                 * simply return. This is not security a problem as long
9299                 * as we close the underlying socket, which we actually
9300                 * do, because that's where we are just coming from.
9301                 */
9302                break;
9303            case 1:
9304                /*
9305                 * Shutdown was successful. We can safely return. Hooray!
9306                 */
9307                break;
9308            default:
9309                /*
9310                 * Everything else is a real error condition. We should
9311                 * let the Java layer know about this by throwing an
9312                 * exception.
9313                 */
9314                int sslError = SSL_get_error(ssl, ret);
9315                throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
9316                break;
9317        }
9318    }
9319
9320    freeOpenSslErrorState();
9321    safeSslClear(ssl);
9322}
9323
9324/**
9325 * OpenSSL close SSL socket function.
9326 */
9327static void NativeCrypto_SSL_shutdown_BIO(JNIEnv* env, jclass, jlong ssl_address, jlong rbioRef,
9328        jlong wbioRef, jobject shc) {
9329    SSL* ssl = to_SSL(env, ssl_address, false);
9330    BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(rbioRef));
9331    BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(wbioRef));
9332    JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown rbio=%p wbio=%p shc=%p", ssl, rbio, wbio, shc);
9333    if (ssl == NULL) {
9334        return;
9335    }
9336    if (rbio == NULL || wbio == NULL) {
9337        jniThrowNullPointerException(env, "rbio == null || wbio == null");
9338        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => rbio == null || wbio == null", ssl);
9339        return;
9340    }
9341    if (shc == NULL) {
9342        jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9343        JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9344        return;
9345    }
9346
9347    AppData* appData = toAppData(ssl);
9348    if (appData != NULL) {
9349        if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
9350            // SocketException thrown by NetFd.isClosed
9351            freeOpenSslErrorState();
9352            safeSslClear(ssl);
9353            return;
9354        }
9355
9356        ScopedSslBio scopedBio(ssl, rbio, wbio);
9357
9358        int ret = SSL_shutdown(ssl);
9359        appData->clearCallbackState();
9360        // callbacks can happen if server requests renegotiation
9361        if (env->ExceptionCheck()) {
9362            safeSslClear(ssl);
9363            JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9364            return;
9365        }
9366        switch (ret) {
9367            case 0:
9368                /*
9369                 * Shutdown was not successful (yet), but there also
9370                 * is no error. Since we can't know whether the remote
9371                 * server is actually still there, and we don't want to
9372                 * get stuck forever in a second SSL_shutdown() call, we
9373                 * simply return. This is not security a problem as long
9374                 * as we close the underlying socket, which we actually
9375                 * do, because that's where we are just coming from.
9376                 */
9377                break;
9378            case 1:
9379                /*
9380                 * Shutdown was successful. We can safely return. Hooray!
9381                 */
9382                break;
9383            default:
9384                /*
9385                 * Everything else is a real error condition. We should
9386                 * let the Java layer know about this by throwing an
9387                 * exception.
9388                 */
9389                int sslError = SSL_get_error(ssl, ret);
9390                throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
9391                break;
9392        }
9393    }
9394
9395    freeOpenSslErrorState();
9396    safeSslClear(ssl);
9397}
9398
9399static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address) {
9400    const SSL* ssl = to_SSL(env, ssl_address, true);
9401    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9402    if (ssl == NULL) {
9403        jniThrowNullPointerException(env, "ssl == null");
9404        return 0;
9405    }
9406
9407    int status = SSL_get_shutdown(ssl);
9408    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9409    return static_cast<jint>(status);
9410}
9411
9412/**
9413 * public static native void SSL_free(long ssl);
9414 */
9415static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address)
9416{
9417    SSL* ssl = to_SSL(env, ssl_address, true);
9418    JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9419    if (ssl == NULL) {
9420        return;
9421    }
9422
9423    AppData* appData = toAppData(ssl);
9424    SSL_set_app_data(ssl, NULL);
9425    delete appData;
9426    SSL_free(ssl);
9427}
9428
9429/**
9430 * Gets and returns in a byte array the ID of the actual SSL session.
9431 */
9432static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9433                                                      jlong ssl_session_address) {
9434    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9435    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9436    if (ssl_session == NULL) {
9437        return NULL;
9438    }
9439    jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
9440    if (result != NULL) {
9441        jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
9442        env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
9443    }
9444    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
9445             ssl_session, result, ssl_session->session_id_length);
9446    return result;
9447}
9448
9449/**
9450 * Gets and returns in a long integer the creation's time of the
9451 * actual SSL session.
9452 */
9453static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9454    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9455    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9456    if (ssl_session == NULL) {
9457        return 0;
9458    }
9459    // result must be jlong, not long or *1000 will overflow
9460    jlong result = SSL_SESSION_get_time(ssl_session);
9461    result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9462    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
9463    return result;
9464}
9465
9466/**
9467 * Gets and returns in a string the version of the SSL protocol. If it
9468 * returns the string "unknown" it means that no connection is established.
9469 */
9470static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jlong ssl_session_address) {
9471    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9472    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9473    if (ssl_session == NULL) {
9474        return NULL;
9475    }
9476    const char* protocol = SSL_SESSION_get_version(ssl_session);
9477    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9478    return env->NewStringUTF(protocol);
9479}
9480
9481/**
9482 * Gets and returns in a string the cipher negotiated for the SSL session.
9483 */
9484static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9485    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9486    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9487    if (ssl_session == NULL) {
9488        return NULL;
9489    }
9490    const SSL_CIPHER* cipher = ssl_session->cipher;
9491    const char* name = SSL_CIPHER_get_name(cipher);
9492    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9493    return env->NewStringUTF(name);
9494}
9495
9496/**
9497 * Frees the SSL session.
9498 */
9499static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9500    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9501    JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9502    if (ssl_session == NULL) {
9503        return;
9504    }
9505    SSL_SESSION_free(ssl_session);
9506}
9507
9508
9509/**
9510 * Serializes the native state of the session (ID, cipher, and keys but
9511 * not certificates). Returns a byte[] containing the DER-encoded state.
9512 * See apache mod_ssl.
9513 */
9514static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9515    SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9516    JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9517    if (ssl_session == NULL) {
9518        return NULL;
9519    }
9520    return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
9521}
9522
9523/**
9524 * Deserialize the session.
9525 */
9526static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9527    JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9528
9529    ScopedByteArrayRO bytes(env, javaBytes);
9530    if (bytes.get() == NULL) {
9531        JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9532        return 0;
9533    }
9534    const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9535    SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
9536
9537    // Initialize SSL_SESSION cipher field based on cipher_id http://b/7091840
9538    if (ssl_session != NULL) {
9539        // based on ssl_get_prev_session
9540        uint32_t cipher_id_network_order = htonl(ssl_session->cipher_id);
9541        uint8_t* cipher_id_byte_pointer = reinterpret_cast<uint8_t*>(&cipher_id_network_order);
9542        if (ssl_session->ssl_version >= SSL3_VERSION_MAJOR) {
9543            cipher_id_byte_pointer += 2; // skip first two bytes for SSL3+
9544        } else {
9545            cipher_id_byte_pointer += 1; // skip first byte for SSL2
9546        }
9547        ssl_session->cipher = SSLv23_method()->get_cipher_by_char(cipher_id_byte_pointer);
9548        JNI_TRACE("NativeCrypto_d2i_SSL_SESSION cipher_id=%lx hton=%x 0=%x 1=%x cipher=%s",
9549                  ssl_session->cipher_id, cipher_id_network_order,
9550                  cipher_id_byte_pointer[0], cipher_id_byte_pointer[1],
9551                  SSL_CIPHER_get_name(ssl_session->cipher));
9552    } else {
9553        freeOpenSslErrorState();
9554    }
9555
9556    JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9557    return reinterpret_cast<uintptr_t>(ssl_session);
9558}
9559
9560static jlong NativeCrypto_ERR_peek_last_error(JNIEnv*, jclass) {
9561    return ERR_peek_last_error();
9562}
9563
9564#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
9565#define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
9566static JNINativeMethod sNativeCryptoMethods[] = {
9567    NATIVE_METHOD(NativeCrypto, clinit, "()V"),
9568    NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
9569    NATIVE_METHOD(NativeCrypto, ENGINE_by_id, "(Ljava/lang/String;)J"),
9570    NATIVE_METHOD(NativeCrypto, ENGINE_add, "(J)I"),
9571    NATIVE_METHOD(NativeCrypto, ENGINE_init, "(J)I"),
9572    NATIVE_METHOD(NativeCrypto, ENGINE_finish, "(J)I"),
9573    NATIVE_METHOD(NativeCrypto, ENGINE_free, "(J)I"),
9574    NATIVE_METHOD(NativeCrypto, ENGINE_load_private_key, "(JLjava/lang/String;)J"),
9575    NATIVE_METHOD(NativeCrypto, ENGINE_get_id, "(J)Ljava/lang/String;"),
9576    NATIVE_METHOD(NativeCrypto, ENGINE_ctrl_cmd_string, "(JLjava/lang/String;Ljava/lang/String;I)I"),
9577    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DH, "([B[B[B[B)J"),
9578    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)J"),
9579    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
9580    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_EC_KEY, "(JJ[B)J"),
9581    NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_mac_key, "(I[B)J"),
9582    NATIVE_METHOD(NativeCrypto, EVP_PKEY_type, "(J)I"),
9583    NATIVE_METHOD(NativeCrypto, EVP_PKEY_size, "(J)I"),
9584    NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_public, "(J)Ljava/lang/String;"),
9585    NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_private, "(J)Ljava/lang/String;"),
9586    NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(J)V"),
9587    NATIVE_METHOD(NativeCrypto, EVP_PKEY_cmp, "(JJ)I"),
9588    NATIVE_METHOD(NativeCrypto, i2d_PKCS8_PRIV_KEY_INFO, "(J)[B"),
9589    NATIVE_METHOD(NativeCrypto, d2i_PKCS8_PRIV_KEY_INFO, "([B)J"),
9590    NATIVE_METHOD(NativeCrypto, i2d_PUBKEY, "(J)[B"),
9591    NATIVE_METHOD(NativeCrypto, d2i_PUBKEY, "([B)J"),
9592    NATIVE_METHOD(NativeCrypto, getRSAPrivateKeyWrapper, "(Ljava/security/interfaces/RSAPrivateKey;[B)J"),
9593    NATIVE_METHOD(NativeCrypto, getDSAPrivateKeyWrapper, "(Ljava/security/interfaces/DSAPrivateKey;)J"),
9594    NATIVE_METHOD(NativeCrypto, getECPrivateKeyWrapper, "(Ljava/security/interfaces/ECPrivateKey;J)J"),
9595    NATIVE_METHOD(NativeCrypto, RSA_generate_key_ex, "(I[B)J"),
9596    NATIVE_METHOD(NativeCrypto, RSA_size, "(J)I"),
9597    NATIVE_METHOD(NativeCrypto, RSA_private_encrypt, "(I[B[BJI)I"),
9598    NATIVE_METHOD(NativeCrypto, RSA_public_decrypt, "(I[B[BJI)I"),
9599    NATIVE_METHOD(NativeCrypto, RSA_public_encrypt, "(I[B[BJI)I"),
9600    NATIVE_METHOD(NativeCrypto, RSA_private_decrypt, "(I[B[BJI)I"),
9601    NATIVE_METHOD(NativeCrypto, get_RSA_private_params, "(J)[[B"),
9602    NATIVE_METHOD(NativeCrypto, get_RSA_public_params, "(J)[[B"),
9603    NATIVE_METHOD(NativeCrypto, DSA_generate_key, "(I[B[B[B[B)J"),
9604    NATIVE_METHOD(NativeCrypto, get_DSA_params, "(J)[[B"),
9605    NATIVE_METHOD(NativeCrypto, set_DSA_flag_nonce_from_hash, "(J)V"),
9606    NATIVE_METHOD(NativeCrypto, DH_generate_parameters_ex, "(IJ)J"),
9607    NATIVE_METHOD(NativeCrypto, DH_generate_key, "(J)V"),
9608    NATIVE_METHOD(NativeCrypto, get_DH_params, "(J)[[B"),
9609    NATIVE_METHOD(NativeCrypto, EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
9610    NATIVE_METHOD(NativeCrypto, EC_GROUP_new_curve, "(I[B[B[B)J"),
9611    NATIVE_METHOD(NativeCrypto, EC_GROUP_dup, "(J)J"),
9612    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_asn1_flag, "(JI)V"),
9613    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_point_conversion_form, "(JI)V"),
9614    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(J)Ljava/lang/String;"),
9615    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(J)[[B"),
9616    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(J)[B"),
9617    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(J)I"),
9618    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(J)[B"),
9619    NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
9620    NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(JJ)Z"),
9621    NATIVE_METHOD(NativeCrypto, EC_GROUP_get_generator, "(J)J"),
9622    NATIVE_METHOD(NativeCrypto, EC_GROUP_set_generator, "(JJ[B[B)V"),
9623    NATIVE_METHOD(NativeCrypto, get_EC_GROUP_type, "(J)I"),
9624    NATIVE_METHOD(NativeCrypto, EC_POINT_new, "(J)J"),
9625    NATIVE_METHOD(NativeCrypto, EC_POINT_clear_free, "(J)V"),
9626    NATIVE_METHOD(NativeCrypto, EC_POINT_cmp, "(JJJ)Z"),
9627    NATIVE_METHOD(NativeCrypto, EC_POINT_set_affine_coordinates, "(JJ[B[B)V"),
9628    NATIVE_METHOD(NativeCrypto, EC_POINT_get_affine_coordinates, "(JJ)[[B"),
9629    NATIVE_METHOD(NativeCrypto, EC_KEY_generate_key, "(J)J"),
9630    NATIVE_METHOD(NativeCrypto, EC_KEY_get0_group, "(J)J"),
9631    NATIVE_METHOD(NativeCrypto, EC_KEY_get_private_key, "(J)[B"),
9632    NATIVE_METHOD(NativeCrypto, EC_KEY_get_public_key, "(J)J"),
9633    NATIVE_METHOD(NativeCrypto, EC_KEY_set_nonce_from_hash, "(JZ)V"),
9634    NATIVE_METHOD(NativeCrypto, ECDH_compute_key, "([BIJJ)I"),
9635    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()J"),
9636    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_init, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)V"),
9637    NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(J)V"),
9638    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"),
9639    NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9640    NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9641    NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BI)I"),
9642    NATIVE_METHOD(NativeCrypto, EVP_get_digestbyname, "(Ljava/lang/String;)J"),
9643    NATIVE_METHOD(NativeCrypto, EVP_MD_block_size, "(J)I"),
9644    NATIVE_METHOD(NativeCrypto, EVP_MD_size, "(J)I"),
9645    NATIVE_METHOD(NativeCrypto, EVP_SignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9646    NATIVE_METHOD(NativeCrypto, EVP_SignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9647    NATIVE_METHOD(NativeCrypto, EVP_SignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIJ)I"),
9648    NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9649    NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9650    NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIIJ)I"),
9651    NATIVE_METHOD(NativeCrypto, EVP_DigestSignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;JJ)V"),
9652    NATIVE_METHOD(NativeCrypto, EVP_DigestSignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[B)V"),
9653    NATIVE_METHOD(NativeCrypto, EVP_DigestSignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)[B"),
9654    NATIVE_METHOD(NativeCrypto, EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
9655    NATIVE_METHOD(NativeCrypto, EVP_CipherInit_ex, "(JJ[B[BZ)V"),
9656    NATIVE_METHOD(NativeCrypto, EVP_CipherUpdate, "(J[BI[BII)I"),
9657    NATIVE_METHOD(NativeCrypto, EVP_CipherFinal_ex, "(J[BI)I"),
9658    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_iv_length, "(J)I"),
9659    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_new, "()J"),
9660    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_block_size, "(J)I"),
9661    NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_buf_len, "(J)I"),
9662    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_padding, "(JZ)V"),
9663    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_key_length, "(JI)V"),
9664    NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_free, "(J)V"),
9665    NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
9666    NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
9667    NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"),
9668    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
9669    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
9670    NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
9671    NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
9672    NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
9673    NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
9674    NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
9675    NATIVE_METHOD(NativeCrypto, BIO_free_all, "(J)V"),
9676    NATIVE_METHOD(NativeCrypto, X509_NAME_print_ex, "(JJ)Ljava/lang/String;"),
9677    NATIVE_METHOD(NativeCrypto, d2i_X509_bio, "(J)J"),
9678    NATIVE_METHOD(NativeCrypto, d2i_X509, "([B)J"),
9679    NATIVE_METHOD(NativeCrypto, i2d_X509, "(J)[B"),
9680    NATIVE_METHOD(NativeCrypto, i2d_X509_PUBKEY, "(J)[B"),
9681    NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509, "(J)J"),
9682    NATIVE_METHOD(NativeCrypto, PEM_read_bio_PKCS7, "(JI)[J"),
9683    NATIVE_METHOD(NativeCrypto, d2i_PKCS7_bio, "(JI)[J"),
9684    NATIVE_METHOD(NativeCrypto, i2d_PKCS7, "([J)[B"),
9685    NATIVE_METHOD(NativeCrypto, ASN1_seq_unpack_X509_bio, "(J)[J"),
9686    NATIVE_METHOD(NativeCrypto, ASN1_seq_pack_X509, "([J)[B"),
9687    NATIVE_METHOD(NativeCrypto, X509_free, "(J)V"),
9688    NATIVE_METHOD(NativeCrypto, X509_cmp, "(JJ)I"),
9689    NATIVE_METHOD(NativeCrypto, get_X509_hashCode, "(J)I"),
9690    NATIVE_METHOD(NativeCrypto, X509_print_ex, "(JJJJ)V"),
9691    NATIVE_METHOD(NativeCrypto, X509_get_pubkey, "(J)J"),
9692    NATIVE_METHOD(NativeCrypto, X509_get_issuer_name, "(J)[B"),
9693    NATIVE_METHOD(NativeCrypto, X509_get_subject_name, "(J)[B"),
9694    NATIVE_METHOD(NativeCrypto, get_X509_pubkey_oid, "(J)Ljava/lang/String;"),
9695    NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_oid, "(J)Ljava/lang/String;"),
9696    NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_parameter, "(J)[B"),
9697    NATIVE_METHOD(NativeCrypto, get_X509_issuerUID, "(J)[Z"),
9698    NATIVE_METHOD(NativeCrypto, get_X509_subjectUID, "(J)[Z"),
9699    NATIVE_METHOD(NativeCrypto, get_X509_ex_kusage, "(J)[Z"),
9700    NATIVE_METHOD(NativeCrypto, get_X509_ex_xkusage, "(J)[Ljava/lang/String;"),
9701    NATIVE_METHOD(NativeCrypto, get_X509_ex_pathlen, "(J)I"),
9702    NATIVE_METHOD(NativeCrypto, X509_get_ext_oid, "(JLjava/lang/String;)[B"),
9703    NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext_oid, "(JLjava/lang/String;)[B"),
9704    NATIVE_METHOD(NativeCrypto, get_X509_CRL_crl_enc, "(J)[B"),
9705    NATIVE_METHOD(NativeCrypto, X509_CRL_verify, "(JJ)V"),
9706    NATIVE_METHOD(NativeCrypto, X509_CRL_get_lastUpdate, "(J)J"),
9707    NATIVE_METHOD(NativeCrypto, X509_CRL_get_nextUpdate, "(J)J"),
9708    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
9709    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_serialNumber, "(J)[B"),
9710    NATIVE_METHOD(NativeCrypto, X509_REVOKED_print, "(JJ)V"),
9711    NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_revocationDate, "(J)J"),
9712    NATIVE_METHOD(NativeCrypto, get_X509_ext_oids, "(JI)[Ljava/lang/String;"),
9713    NATIVE_METHOD(NativeCrypto, get_X509_CRL_ext_oids, "(JI)[Ljava/lang/String;"),
9714    NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
9715    NATIVE_METHOD(NativeCrypto, get_X509_GENERAL_NAME_stack, "(JI)[[Ljava/lang/Object;"),
9716    NATIVE_METHOD(NativeCrypto, X509_get_notBefore, "(J)J"),
9717    NATIVE_METHOD(NativeCrypto, X509_get_notAfter, "(J)J"),
9718    NATIVE_METHOD(NativeCrypto, X509_get_version, "(J)J"),
9719    NATIVE_METHOD(NativeCrypto, X509_get_serialNumber, "(J)[B"),
9720    NATIVE_METHOD(NativeCrypto, X509_verify, "(JJ)V"),
9721    NATIVE_METHOD(NativeCrypto, get_X509_cert_info_enc, "(J)[B"),
9722    NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
9723    NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
9724    NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
9725    NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
9726    NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
9727    NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
9728    NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
9729    NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_serial, "(J[B)J"),
9730    NATIVE_METHOD(NativeCrypto, X509_CRL_get_REVOKED, "(J)[J"),
9731    NATIVE_METHOD(NativeCrypto, i2d_X509_CRL, "(J)[B"),
9732    NATIVE_METHOD(NativeCrypto, X509_CRL_free, "(J)V"),
9733    NATIVE_METHOD(NativeCrypto, X509_CRL_print, "(JJ)V"),
9734    NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_oid, "(J)Ljava/lang/String;"),
9735    NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_parameter, "(J)[B"),
9736    NATIVE_METHOD(NativeCrypto, X509_CRL_get_issuer_name, "(J)[B"),
9737    NATIVE_METHOD(NativeCrypto, X509_CRL_get_version, "(J)J"),
9738    NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext, "(JLjava/lang/String;)J"),
9739    NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
9740    NATIVE_METHOD(NativeCrypto, X509_REVOKED_dup, "(J)J"),
9741    NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
9742    NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
9743    NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
9744    NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
9745    NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
9746    NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),
9747    NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
9748    NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
9749    NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
9750    NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
9751    NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
9752    NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[J)V"),
9753    NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
9754    NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
9755    NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(J)J"),
9756    NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(JJ)J"),
9757    NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(JJ)J"),
9758    NATIVE_METHOD(NativeCrypto, SSL_get_options, "(J)J"),
9759    NATIVE_METHOD(NativeCrypto, SSL_set_options, "(JJ)J"),
9760    NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(JJ)J"),
9761    NATIVE_METHOD(NativeCrypto, SSL_use_psk_identity_hint, "(JLjava/lang/String;)V"),
9762    NATIVE_METHOD(NativeCrypto, set_SSL_psk_client_callback_enabled, "(JZ)V"),
9763    NATIVE_METHOD(NativeCrypto, set_SSL_psk_server_callback_enabled, "(JZ)V"),
9764    NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(J[Ljava/lang/String;)V"),
9765    NATIVE_METHOD(NativeCrypto, SSL_get_ciphers, "(J)[J"),
9766    NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_auth, "(J)I"),
9767    NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_mkey, "(J)I"),
9768    NATIVE_METHOD(NativeCrypto, SSL_set_accept_state, "(J)V"),
9769    NATIVE_METHOD(NativeCrypto, SSL_set_connect_state, "(J)V"),
9770    NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(JI)V"),
9771    NATIVE_METHOD(NativeCrypto, SSL_set_session, "(JJ)V"),
9772    NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
9773    NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
9774    NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
9775    NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)J"),
9776    NATIVE_METHOD(NativeCrypto, SSL_do_handshake_bio, "(JJJ" SSL_CALLBACKS "Z[B[B)J"),
9777    NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
9778    NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[J"),
9779    NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[J"),
9780    NATIVE_METHOD(NativeCrypto, SSL_read, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
9781    NATIVE_METHOD(NativeCrypto, SSL_read_BIO, "(J[BIIJJ" SSL_CALLBACKS ")I"),
9782    NATIVE_METHOD(NativeCrypto, SSL_write, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
9783    NATIVE_METHOD(NativeCrypto, SSL_write_BIO, "(J[BIJ" SSL_CALLBACKS ")I"),
9784    NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(J)V"),
9785    NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(J" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
9786    NATIVE_METHOD(NativeCrypto, SSL_shutdown_BIO, "(JJJ" SSL_CALLBACKS ")V"),
9787    NATIVE_METHOD(NativeCrypto, SSL_get_shutdown, "(J)I"),
9788    NATIVE_METHOD(NativeCrypto, SSL_free, "(J)V"),
9789    NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(J)[B"),
9790    NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(J)J"),
9791    NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
9792    NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
9793    NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(J)V"),
9794    NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(J)[B"),
9795    NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)J"),
9796    NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
9797    NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
9798    NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
9799    NATIVE_METHOD(NativeCrypto, SSL_set_alpn_protos, "(J[B)I"),
9800    NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
9801    NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
9802};
9803
9804static jclass getGlobalRefToClass(JNIEnv* env, const char* className) {
9805    ScopedLocalRef<jclass> localClass(env, env->FindClass(className));
9806    jclass globalRef = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
9807    if (globalRef == NULL) {
9808        ALOGE("failed to find class %s", className);
9809        abort();
9810    }
9811    return globalRef;
9812}
9813
9814static jmethodID getStaticMethodRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9815    jmethodID localMethod = env->GetStaticMethodID(clazz, name, sig);
9816    if (localMethod == NULL) {
9817        ALOGE("could not find static method %s", name);
9818        abort();
9819    }
9820    return localMethod;
9821}
9822
9823static jmethodID getMethodRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9824    jmethodID localMethod = env->GetMethodID(clazz, name, sig);
9825    if (localMethod == NULL) {
9826        ALOGE("could not find method %s", name);
9827        abort();
9828    }
9829    return localMethod;
9830}
9831
9832static jfieldID getFieldRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9833    jfieldID localField = env->GetFieldID(clazz, name, sig);
9834    if (localField == NULL) {
9835        ALOGE("could not find field %s", name);
9836        abort();
9837    }
9838    return localField;
9839}
9840
9841static void initialize_conscrypt(JNIEnv* env) {
9842    jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
9843                             sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
9844
9845    cryptoUpcallsClass = getGlobalRefToClass(env,
9846            TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/CryptoUpcalls");
9847    openSslNativeReferenceClass = getGlobalRefToClass(env,
9848            TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLNativeReference");
9849    openSslInputStreamClass = getGlobalRefToClass(env,
9850            TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream");
9851
9852    openSslNativeReference_context = getFieldRef(env, openSslNativeReferenceClass, "context", "J");
9853
9854    calendar_setMethod = getMethodRef(env, calendarClass, "set", "(IIIIII)V");
9855    inputStream_readMethod = getMethodRef(env, inputStreamClass, "read", "([B)I");
9856    integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
9857            "(I)Ljava/lang/Integer;");
9858    openSslInputStream_readLineMethod = getMethodRef(env, openSslInputStreamClass, "gets",
9859            "([B)I");
9860    outputStream_writeMethod = getMethodRef(env, outputStreamClass, "write", "([B)V");
9861    outputStream_flushMethod = getMethodRef(env, outputStreamClass, "flush", "()V");
9862
9863#ifdef CONSCRYPT_UNBUNDLED
9864    findAsynchronousCloseMonitorFuncs();
9865#endif
9866}
9867
9868static jclass findClass(JNIEnv* env, const char* name) {
9869    ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
9870    jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
9871    if (result == NULL) {
9872        ALOGE("failed to find class '%s'", name);
9873        abort();
9874    }
9875    return result;
9876}
9877
9878#ifdef STATIC_LIB
9879// Give client libs everything they need to initialize our JNI
9880int libconscrypt_JNI_OnLoad(JavaVM *vm, void*) {
9881#else
9882// Use JNI_OnLoad for when we're standalone
9883int JNI_OnLoad(JavaVM *vm, void*) {
9884    JNI_TRACE("JNI_OnLoad NativeCrypto");
9885#endif
9886    gJavaVM = vm;
9887
9888    JNIEnv *env;
9889    if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
9890        ALOGE("Could not get JNIEnv");
9891        return JNI_ERR;
9892    }
9893
9894    byteArrayClass = findClass(env, "[B");
9895    calendarClass = findClass(env, "java/util/Calendar");
9896    inputStreamClass = findClass(env, "java/io/InputStream");
9897    integerClass = findClass(env, "java/lang/Integer");
9898    objectClass = findClass(env, "java/lang/Object");
9899    objectArrayClass = findClass(env, "[Ljava/lang/Object;");
9900    outputStreamClass = findClass(env, "java/io/OutputStream");
9901    stringClass = findClass(env, "java/lang/String");
9902
9903    initialize_conscrypt(env);
9904    return JNI_VERSION_1_6;
9905}
9906