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