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