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