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         clearCallbackState();
   5623         MUTEX_CLEANUP(mutex);
   5624     }
   5625 
   5626   private:
   5627     AppData() :
   5628             aliveAndKicking(1),
   5629             waitingThreads(0),
   5630             env(NULL),
   5631             sslHandshakeCallbacks(NULL),
   5632             npnProtocolsArray(NULL),
   5633             npnProtocolsData(NULL),
   5634             npnProtocolsLength(-1),
   5635             alpnProtocolsArray(NULL),
   5636             alpnProtocolsData(NULL),
   5637             alpnProtocolsLength(-1),
   5638             ephemeralRsa(NULL),
   5639             ephemeralEc(NULL) {
   5640         fdsEmergency[0] = -1;
   5641         fdsEmergency[1] = -1;
   5642     }
   5643 
   5644   public:
   5645     /**
   5646      * Used to set the SSL-to-Java callback state before each SSL_*
   5647      * call that may result in a callback. It should be cleared after
   5648      * the operation returns with clearCallbackState.
   5649      *
   5650      * @param env The JNIEnv
   5651      * @param shc The SSLHandshakeCallbacks
   5652      * @param fd The FileDescriptor
   5653      * @param npnProtocols NPN protocols so that they may be advertised (by the
   5654      *                     server) or selected (by the client). Has no effect
   5655      *                     unless NPN is enabled.
   5656      * @param alpnProtocols ALPN protocols so that they may be advertised (by the
   5657      *                     server) or selected (by the client). Passing non-NULL
   5658      *                     enables ALPN.
   5659      */
   5660     bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
   5661             jbyteArray alpnProtocols) {
   5662         NetFd netFd(e, fd);
   5663         if (netFd.isClosed()) {
   5664             return false;
   5665         }
   5666         env = e;
   5667         sslHandshakeCallbacks = shc;
   5668         fileDescriptor = fd;
   5669         if (npnProtocols != NULL) {
   5670             npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
   5671             if (npnProtocolsData == NULL) {
   5672                 clearCallbackState();
   5673                 return false;
   5674             }
   5675             npnProtocolsArray = npnProtocols;
   5676             npnProtocolsLength = e->GetArrayLength(npnProtocols);
   5677         }
   5678         if (alpnProtocols != NULL) {
   5679             alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
   5680             if (alpnProtocolsData == NULL) {
   5681                 clearCallbackState();
   5682                 return false;
   5683             }
   5684             alpnProtocolsArray = alpnProtocols;
   5685             alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
   5686         }
   5687         return true;
   5688     }
   5689 
   5690     void clearCallbackState() {
   5691         sslHandshakeCallbacks = NULL;
   5692         fileDescriptor = NULL;
   5693         if (npnProtocolsArray != NULL) {
   5694             env->ReleaseByteArrayElements(npnProtocolsArray, npnProtocolsData, JNI_ABORT);
   5695             npnProtocolsArray = NULL;
   5696             npnProtocolsData = NULL;
   5697             npnProtocolsLength = -1;
   5698         }
   5699         if (alpnProtocolsArray != NULL) {
   5700             env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
   5701             alpnProtocolsArray = NULL;
   5702             alpnProtocolsData = NULL;
   5703             alpnProtocolsLength = -1;
   5704         }
   5705         env = NULL;
   5706     }
   5707 
   5708 };
   5709 
   5710 /**
   5711  * Dark magic helper function that checks, for a given SSL session, whether it
   5712  * can SSL_read() or SSL_write() without blocking. Takes into account any
   5713  * concurrent attempts to close the SSLSocket from the Java side. This is
   5714  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
   5715  * while thread #2 is sitting in a blocking read or write. The type argument
   5716  * specifies whether we are waiting for readability or writability. It expects
   5717  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
   5718  * only need to wait in case one of these problems occurs.
   5719  *
   5720  * @param env
   5721  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
   5722  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
   5723  * @param appData The application data structure with mutex info etc.
   5724  * @param timeout_millis The timeout value for select call, with the special value
   5725  *                0 meaning no timeout at all (wait indefinitely). Note: This is
   5726  *                the Java semantics of the timeout value, not the usual
   5727  *                select() semantics.
   5728  * @return The result of the inner select() call,
   5729  * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
   5730  * additional errors
   5731  */
   5732 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout_millis) {
   5733     // This loop is an expanded version of the NET_FAILURE_RETRY
   5734     // macro. It cannot simply be used in this case because select
   5735     // cannot be restarted without recreating the fd_sets and timeout
   5736     // structure.
   5737     int result;
   5738     fd_set rfds;
   5739     fd_set wfds;
   5740     do {
   5741         NetFd fd(env, fdObject);
   5742         if (fd.isClosed()) {
   5743             result = THROWN_EXCEPTION;
   5744             break;
   5745         }
   5746         int intFd = fd.get();
   5747         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
   5748                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
   5749 
   5750         FD_ZERO(&rfds);
   5751         FD_ZERO(&wfds);
   5752 
   5753         if (type == SSL_ERROR_WANT_READ) {
   5754             FD_SET(intFd, &rfds);
   5755         } else {
   5756             FD_SET(intFd, &wfds);
   5757         }
   5758 
   5759         FD_SET(appData->fdsEmergency[0], &rfds);
   5760 
   5761         int maxFd = (intFd > appData->fdsEmergency[0]) ? intFd : appData->fdsEmergency[0];
   5762 
   5763         // Build a struct for the timeout data if we actually want a timeout.
   5764         timeval tv;
   5765         timeval* ptv;
   5766         if (timeout_millis > 0) {
   5767             tv.tv_sec = timeout_millis / 1000;
   5768             tv.tv_usec = (timeout_millis % 1000) * 1000;
   5769             ptv = &tv;
   5770         } else {
   5771             ptv = NULL;
   5772         }
   5773 
   5774         AsynchronousSocketCloseMonitor monitor(intFd);
   5775         result = select(maxFd + 1, &rfds, &wfds, NULL, ptv);
   5776         JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
   5777                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
   5778                   fd.get(), appData, timeout_millis, result);
   5779         if (result == -1) {
   5780             if (fd.isClosed()) {
   5781                 result = THROWN_EXCEPTION;
   5782                 break;
   5783             }
   5784             if (errno != EINTR) {
   5785                 break;
   5786             }
   5787         }
   5788     } while (result == -1);
   5789 
   5790     if (MUTEX_LOCK(appData->mutex) == -1) {
   5791         return -1;
   5792     }
   5793 
   5794     if (result > 0) {
   5795         // We have been woken up by a token in the emergency pipe. We
   5796         // can't be sure the token is still in the pipe at this point
   5797         // because it could have already been read by the thread that
   5798         // originally wrote it if it entered sslSelect and acquired
   5799         // the mutex before we did. Thus we cannot safely read from
   5800         // the pipe in a blocking way (so we make the pipe
   5801         // non-blocking at creation).
   5802         if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
   5803             char token;
   5804             do {
   5805                 read(appData->fdsEmergency[0], &token, 1);
   5806             } while (errno == EINTR);
   5807         }
   5808     }
   5809 
   5810     // Tell the world that there is now one thread less waiting for the
   5811     // underlying network.
   5812     appData->waitingThreads--;
   5813 
   5814     MUTEX_UNLOCK(appData->mutex);
   5815 
   5816     return result;
   5817 }
   5818 
   5819 /**
   5820  * Helper function that wakes up a thread blocked in select(), in case there is
   5821  * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
   5822  * before closing the connection.
   5823  *
   5824  * @param data The application data structure with mutex info etc.
   5825  */
   5826 static void sslNotify(AppData* appData) {
   5827     // Write a byte to the emergency pipe, so a concurrent select() can return.
   5828     // Note we have to restore the errno of the original system call, since the
   5829     // caller relies on it for generating error messages.
   5830     int errnoBackup = errno;
   5831     char token = '*';
   5832     do {
   5833         errno = 0;
   5834         write(appData->fdsEmergency[1], &token, 1);
   5835     } while (errno == EINTR);
   5836     errno = errnoBackup;
   5837 }
   5838 
   5839 static AppData* toAppData(const SSL* ssl) {
   5840     return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
   5841 }
   5842 
   5843 /**
   5844  * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
   5845  */
   5846 static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
   5847 {
   5848     /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
   5849     SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
   5850             SSL_get_ex_data_X509_STORE_CTX_idx()));
   5851     JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
   5852 
   5853     AppData* appData = toAppData(ssl);
   5854     JNIEnv* env = appData->env;
   5855     if (env == NULL) {
   5856         ALOGE("AppData->env missing in cert_verify_callback");
   5857         JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
   5858         return 0;
   5859     }
   5860     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
   5861 
   5862     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
   5863     jmethodID methodID
   5864         = env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
   5865 
   5866     jobjectArray objectArray = getCertificateBytes(env, x509_store_ctx->untrusted);
   5867 
   5868     const char* authMethod = SSL_authentication_method(ssl);
   5869     JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
   5870               ssl, authMethod);
   5871     jstring authMethodString = env->NewStringUTF(authMethod);
   5872     env->CallVoidMethod(sslHandshakeCallbacks, methodID, objectArray, authMethodString);
   5873 
   5874     int result = (env->ExceptionCheck()) ? 0 : 1;
   5875     JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
   5876     return result;
   5877 }
   5878 
   5879 /**
   5880  * Call back to watch for handshake to be completed. This is necessary
   5881  * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
   5882  * returns before the handshake is completed in this case.
   5883  */
   5884 static void info_callback(const SSL* ssl, int where, int ret __attribute__ ((unused))) {
   5885     JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
   5886 #ifdef WITH_JNI_TRACE
   5887     info_callback_LOG(ssl, where, ret);
   5888 #endif
   5889     if (!(where & SSL_CB_HANDSHAKE_DONE)) {
   5890         JNI_TRACE("ssl=%p info_callback ignored", ssl);
   5891         return;
   5892     }
   5893 
   5894     AppData* appData = toAppData(ssl);
   5895     JNIEnv* env = appData->env;
   5896     if (env == NULL) {
   5897         ALOGE("AppData->env missing in info_callback");
   5898         JNI_TRACE("ssl=%p info_callback env error", ssl);
   5899         return;
   5900     }
   5901     if (env->ExceptionCheck()) {
   5902         JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
   5903         return;
   5904     }
   5905 
   5906     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
   5907 
   5908     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
   5909     jmethodID methodID = env->GetMethodID(cls, "handshakeCompleted", "()V");
   5910 
   5911     JNI_TRACE("ssl=%p info_callback calling handshakeCompleted", ssl);
   5912     env->CallVoidMethod(sslHandshakeCallbacks, methodID);
   5913 
   5914     if (env->ExceptionCheck()) {
   5915         JNI_TRACE("ssl=%p info_callback exception", ssl);
   5916     }
   5917     JNI_TRACE("ssl=%p info_callback completed", ssl);
   5918 }
   5919 
   5920 /**
   5921  * Call back to ask for a client certificate. There are three possible exit codes:
   5922  *
   5923  * 1 is success. x509Out and pkeyOut should point to the correct private key and certificate.
   5924  * 0 is unable to find key. x509Out and pkeyOut should be NULL.
   5925  * -1 is error and it doesn't matter what x509Out and pkeyOut are.
   5926  */
   5927 static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
   5928     JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
   5929 
   5930     /* Clear output of key and certificate in case of early exit due to error. */
   5931     *x509Out = NULL;
   5932     *pkeyOut = NULL;
   5933 
   5934     AppData* appData = toAppData(ssl);
   5935     JNIEnv* env = appData->env;
   5936     if (env == NULL) {
   5937         ALOGE("AppData->env missing in client_cert_cb");
   5938         JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
   5939         return 0;
   5940     }
   5941     if (env->ExceptionCheck()) {
   5942         JNI_TRACE("ssl=%p client_cert_cb already pending exception => 0", ssl);
   5943         return -1;
   5944     }
   5945     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
   5946 
   5947     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
   5948     jmethodID methodID
   5949         = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
   5950 
   5951     // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
   5952     char ssl2_ctype = SSL3_CT_RSA_SIGN;
   5953     const char* ctype = NULL;
   5954     int ctype_num = 0;
   5955     jobjectArray issuers = NULL;
   5956     switch (ssl->version) {
   5957         case SSL2_VERSION:
   5958             ctype = &ssl2_ctype;
   5959             ctype_num = 1;
   5960             break;
   5961         case SSL3_VERSION:
   5962         case TLS1_VERSION:
   5963         case TLS1_1_VERSION:
   5964         case TLS1_2_VERSION:
   5965         case DTLS1_VERSION:
   5966             ctype = ssl->s3->tmp.ctype;
   5967             ctype_num = ssl->s3->tmp.ctype_num;
   5968             issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
   5969             break;
   5970     }
   5971 #ifdef WITH_JNI_TRACE
   5972     for (int i = 0; i < ctype_num; i++) {
   5973         JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
   5974     }
   5975 #endif
   5976 
   5977     jbyteArray keyTypes = env->NewByteArray(ctype_num);
   5978     if (keyTypes == NULL) {
   5979         JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
   5980         return 0;
   5981     }
   5982     env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
   5983 
   5984     JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
   5985               "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
   5986     env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
   5987 
   5988     if (env->ExceptionCheck()) {
   5989         JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
   5990         return -1;
   5991     }
   5992 
   5993     // Check for values set from Java
   5994     X509*     certificate = SSL_get_certificate(ssl);
   5995     EVP_PKEY* privatekey  = SSL_get_privatekey(ssl);
   5996     int result = 0;
   5997     if (certificate != NULL && privatekey != NULL) {
   5998         *x509Out = certificate;
   5999         *pkeyOut = privatekey;
   6000         result = 1;
   6001     } else {
   6002         // Some error conditions return NULL, so make sure it doesn't linger.
   6003         freeOpenSslErrorState();
   6004     }
   6005     JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
   6006     return result;
   6007 }
   6008 
   6009 static RSA* rsaGenerateKey(int keylength) {
   6010     Unique_BIGNUM bn(BN_new());
   6011     if (bn.get() == NULL) {
   6012         return NULL;
   6013     }
   6014     int setWordResult = BN_set_word(bn.get(), RSA_F4);
   6015     if (setWordResult != 1) {
   6016         return NULL;
   6017     }
   6018     Unique_RSA rsa(RSA_new());
   6019     if (rsa.get() == NULL) {
   6020         return NULL;
   6021     }
   6022     int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
   6023     if (generateResult != 1) {
   6024         return NULL;
   6025     }
   6026     return rsa.release();
   6027 }
   6028 
   6029 /**
   6030  * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
   6031  */
   6032 static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
   6033                              int is_export __attribute__ ((unused)),
   6034                              int keylength) {
   6035     JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
   6036 
   6037     AppData* appData = toAppData(ssl);
   6038     if (appData->ephemeralRsa.get() == NULL) {
   6039         JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
   6040         appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
   6041     }
   6042     JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
   6043     return appData->ephemeralRsa.get();
   6044 }
   6045 
   6046 static DH* dhGenerateParameters(int keylength) {
   6047 
   6048     /*
   6049      * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
   6050      * different options for generating DH keys. One is generating the
   6051      * keys using a single set of DH parameters. However, generating
   6052      * DH parameters is slow enough (minutes) that they suggest doing
   6053      * it once at install time. The other is to generate DH keys from
   6054      * DSA parameters. Generating DSA parameters is faster than DH
   6055      * parameters, but to prevent small subgroup attacks, they needed
   6056      * to be regenerated for each set of DH keys. Setting the
   6057      * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
   6058      * for new DH parameters every type it needs to generate DH keys.
   6059      */
   6060 #if 0
   6061     // Slow path that takes minutes but could be cached
   6062     Unique_DH dh(DH_new());
   6063     if (!DH_generate_parameters_ex(dh.get(), keylength, 2, NULL)) {
   6064         return NULL;
   6065     }
   6066     return dh.release();
   6067 #else
   6068     // Faster path but must have SSL_OP_SINGLE_DH_USE set
   6069     Unique_DSA dsa(DSA_new());
   6070     if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
   6071         return NULL;
   6072     }
   6073     DH* dh = DSA_dup_DH(dsa.get());
   6074     return dh;
   6075 #endif
   6076 }
   6077 
   6078 /**
   6079  * Call back to ask for Diffie-Hellman parameters
   6080  */
   6081 static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
   6082                            int is_export __attribute__ ((unused)),
   6083                            int keylength) {
   6084     JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
   6085     DH* tmp_dh = dhGenerateParameters(keylength);
   6086     JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
   6087     return tmp_dh;
   6088 }
   6089 
   6090 static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
   6091     // TODO selected curve based on keylength
   6092     Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
   6093     if (ec.get() == NULL) {
   6094         return NULL;
   6095     }
   6096     return ec.release();
   6097 }
   6098 
   6099 /**
   6100  * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
   6101  */
   6102 static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
   6103                                  int is_export __attribute__ ((unused)),
   6104                                  int keylength) {
   6105     JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
   6106     AppData* appData = toAppData(ssl);
   6107     if (appData->ephemeralEc.get() == NULL) {
   6108         JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
   6109         appData->ephemeralEc.reset(ecGenerateKey(keylength));
   6110     }
   6111     JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
   6112     return appData->ephemeralEc.get();
   6113 }
   6114 
   6115 /*
   6116  * public static native int SSL_CTX_new();
   6117  */
   6118 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
   6119     Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
   6120     if (sslCtx.get() == NULL) {
   6121         throwExceptionIfNecessary(env, "SSL_CTX_new");
   6122         return 0;
   6123     }
   6124     SSL_CTX_set_options(sslCtx.get(),
   6125                         SSL_OP_ALL
   6126                         // Note: We explicitly do not allow SSLv2 to be used.
   6127                         | SSL_OP_NO_SSLv2
   6128                         // We also disable session tickets for better compatibility b/2682876
   6129                         | SSL_OP_NO_TICKET
   6130                         // We also disable compression for better compatibility b/2710492 b/2710497
   6131                         | SSL_OP_NO_COMPRESSION
   6132                         // Because dhGenerateParameters uses DSA_generate_parameters_ex
   6133                         | SSL_OP_SINGLE_DH_USE
   6134                         // Because ecGenerateParameters uses a fixed named curve
   6135                         | SSL_OP_SINGLE_ECDH_USE);
   6136 
   6137     int mode = SSL_CTX_get_mode(sslCtx.get());
   6138     /*
   6139      * Turn on "partial write" mode. This means that SSL_write() will
   6140      * behave like Posix write() and possibly return after only
   6141      * writing a partial buffer. Note: The alternative, perhaps
   6142      * surprisingly, is not that SSL_write() always does full writes
   6143      * but that it will force you to retry write calls having
   6144      * preserved the full state of the original call. (This is icky
   6145      * and undesirable.)
   6146      */
   6147     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
   6148 
   6149     // Reuse empty buffers within the SSL_CTX to save memory
   6150     mode |= SSL_MODE_RELEASE_BUFFERS;
   6151 
   6152     SSL_CTX_set_mode(sslCtx.get(), mode);
   6153 
   6154     SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
   6155     SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
   6156     SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
   6157     SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
   6158     SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
   6159     SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
   6160 
   6161     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
   6162     return (jlong) sslCtx.release();
   6163 }
   6164 
   6165 /**
   6166  * public static native void SSL_CTX_free(int ssl_ctx)
   6167  */
   6168 static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
   6169         jclass, jlong ssl_ctx_address)
   6170 {
   6171     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6172     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
   6173     if (ssl_ctx == NULL) {
   6174         return;
   6175     }
   6176     SSL_CTX_free(ssl_ctx);
   6177 }
   6178 
   6179 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass,
   6180                                                         jlong ssl_ctx_address, jbyteArray sid_ctx)
   6181 {
   6182     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6183     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx, sid_ctx);
   6184     if (ssl_ctx == NULL) {
   6185         return;
   6186     }
   6187 
   6188     ScopedByteArrayRO buf(env, sid_ctx);
   6189     if (buf.get() == NULL) {
   6190         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception", ssl_ctx);
   6191         return;
   6192     }
   6193 
   6194     unsigned int length = buf.size();
   6195     if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
   6196         jniThrowException(env, "java/lang/IllegalArgumentException",
   6197                           "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
   6198         JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
   6199         return;
   6200     }
   6201     const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
   6202     int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
   6203     if (result == 0) {
   6204         throwExceptionIfNecessary(env, "NativeCrypto_SSL_CTX_set_session_id_context");
   6205         return;
   6206     }
   6207     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
   6208 }
   6209 
   6210 /**
   6211  * public static native int SSL_new(int ssl_ctx) throws SSLException;
   6212  */
   6213 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address)
   6214 {
   6215     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6216     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
   6217     if (ssl_ctx == NULL) {
   6218         return 0;
   6219     }
   6220     Unique_SSL ssl(SSL_new(ssl_ctx));
   6221     if (ssl.get() == NULL) {
   6222         throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
   6223                 "Unable to create SSL structure");
   6224         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
   6225         return 0;
   6226     }
   6227 
   6228     /* Java code in class OpenSSLSocketImpl does the verification. Meaning of
   6229      * SSL_VERIFY_NONE flag in client mode: if not using an anonymous cipher
   6230      * (by default disabled), the server will send a certificate which will
   6231      * be checked. The result of the certificate verification process can be
   6232      * checked after the TLS/SSL handshake using the SSL_get_verify_result(3)
   6233      * function. The handshake will be continued regardless of the
   6234      * verification result.
   6235      */
   6236     SSL_set_verify(ssl.get(), SSL_VERIFY_NONE, NULL);
   6237 
   6238     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p", ssl_ctx, ssl.get());
   6239     return (jlong) ssl.release();
   6240 }
   6241 
   6242 
   6243 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
   6244 {
   6245     SSL* ssl = to_SSL(env, ssl_address, true);
   6246     JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_enable_tls_channel_id", ssl);
   6247     if (ssl == NULL) {
   6248         return;
   6249     }
   6250 
   6251     long ret = SSL_enable_tls_channel_id(ssl);
   6252     if (ret != 1L) {
   6253         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6254         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error enabling Channel ID");
   6255         SSL_clear(ssl);
   6256         JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
   6257         return;
   6258     }
   6259 }
   6260 
   6261 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
   6262 {
   6263     SSL* ssl = to_SSL(env, ssl_address, true);
   6264     JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id", ssl);
   6265     if (ssl == NULL) {
   6266         return NULL;
   6267     }
   6268 
   6269     // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
   6270     // as a constant anywhere.
   6271     jbyteArray javaBytes = env->NewByteArray(64);
   6272     ScopedByteArrayRW bytes(env, javaBytes);
   6273     if (bytes.get() == NULL) {
   6274         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => NULL", ssl);
   6275         return NULL;
   6276     }
   6277 
   6278     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
   6279     // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
   6280     // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
   6281     // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
   6282     long ret = SSL_get_tls_channel_id(ssl, tmp, 64);
   6283     if (ret == 0) {
   6284         // Channel ID either not set or did not verify
   6285         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
   6286         return NULL;
   6287     } else if (ret != 64) {
   6288         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6289         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error getting Channel ID");
   6290         SSL_clear(ssl);
   6291         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %ld", ssl, ret);
   6292         return NULL;
   6293     }
   6294 
   6295     JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
   6296     return javaBytes;
   6297 }
   6298 
   6299 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
   6300         jlong ssl_address, jlong pkeyRef)
   6301 {
   6302     SSL* ssl = to_SSL(env, ssl_address, true);
   6303     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
   6304     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
   6305     if (ssl == NULL) {
   6306         return;
   6307     }
   6308 
   6309     if (pkey == NULL) {
   6310         jniThrowNullPointerException(env, "pkey == null");
   6311         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
   6312         return;
   6313     }
   6314 
   6315     // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
   6316     // Unfortunately, the default value is 1 and it's only changed to 0 just
   6317     // before the handshake starts (see NativeCrypto_SSL_do_handshake).
   6318     ssl->server = 0;
   6319     long ret = SSL_set1_tls_channel_id(ssl, pkey);
   6320 
   6321     if (ret != 1L) {
   6322         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6323         throwSSLExceptionWithSslErrors(
   6324                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
   6325         SSL_clear(ssl);
   6326         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
   6327         return;
   6328     }
   6329     // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
   6330     // we have an external reference from the caller such as an OpenSSLKey,
   6331     // so we manually increment the reference count here.
   6332     CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
   6333 
   6334     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
   6335 }
   6336 
   6337 static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
   6338     SSL* ssl = to_SSL(env, ssl_address, true);
   6339     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
   6340     JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
   6341     if (ssl == NULL) {
   6342         return;
   6343     }
   6344 
   6345     if (pkey == NULL) {
   6346         jniThrowNullPointerException(env, "pkey == null");
   6347         JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
   6348         return;
   6349     }
   6350 
   6351     int ret = SSL_use_PrivateKey(ssl, pkey);
   6352     if (ret != 1) {
   6353         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6354         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
   6355         SSL_clear(ssl);
   6356         JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
   6357         return;
   6358     }
   6359     // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
   6360     // but we have an external reference from the caller such as an
   6361     // OpenSSLKey, so we manually increment the reference count here.
   6362     CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
   6363 
   6364     JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
   6365 }
   6366 
   6367 static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
   6368                                              jlong ssl_address, jobjectArray certificates)
   6369 {
   6370     SSL* ssl = to_SSL(env, ssl_address, true);
   6371     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificates);
   6372     if (ssl == NULL) {
   6373         return;
   6374     }
   6375 
   6376     if (certificates == NULL) {
   6377         jniThrowNullPointerException(env, "certificates == null");
   6378         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
   6379         return;
   6380     }
   6381 
   6382     int length = env->GetArrayLength(certificates);
   6383     if (length == 0) {
   6384         jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
   6385         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
   6386         return;
   6387     }
   6388 
   6389     X509Chain certificatesX509(length);
   6390     for (int i = 0; i < length; i++) {
   6391         ScopedLocalRef<jbyteArray> certificate(env,
   6392                 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(certificates, i)));
   6393         if (certificate.get() == NULL) {
   6394             jniThrowNullPointerException(env, "certificates element == null");
   6395             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates element null", ssl);
   6396             return;
   6397         }
   6398 
   6399         ScopedByteArrayRO buf(env, certificate.get());
   6400         if (buf.get() == NULL) {
   6401             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => threw exception", ssl);
   6402             return;
   6403         }
   6404         const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
   6405         certificatesX509[i] = d2i_X509(NULL, &tmp, buf.size());
   6406 
   6407         if (certificatesX509[i] == NULL) {
   6408             ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6409             throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
   6410             SSL_clear(ssl);
   6411             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
   6412             return;
   6413         }
   6414     }
   6415 
   6416     int ret = SSL_use_certificate(ssl, certificatesX509[0]);
   6417     if (ret == 1) {
   6418         certificatesX509.release(0);
   6419     } else {
   6420         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6421         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
   6422         SSL_clear(ssl);
   6423         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
   6424         return;
   6425     }
   6426 
   6427     Unique_sk_X509 chain(sk_X509_new_null());
   6428     if (chain.get() == NULL) {
   6429         jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
   6430         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
   6431         return;
   6432     }
   6433     for (int i = 1; i < length; i++) {
   6434         if (!sk_X509_push(chain.get(), certificatesX509.release(i))) {
   6435             jniThrowOutOfMemory(env, "Unable to push certificate");
   6436             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
   6437             return;
   6438         }
   6439     }
   6440     int chainResult = SSL_use_certificate_chain(ssl, chain.get());
   6441     if (chainResult == 0) {
   6442         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
   6443         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
   6444                   ssl);
   6445         return;
   6446     } else {
   6447         OWNERSHIP_TRANSFERRED(chain);
   6448     }
   6449 
   6450     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
   6451 }
   6452 
   6453 static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jlong ssl_address)
   6454 {
   6455     SSL* ssl = to_SSL(env, ssl_address, true);
   6456     JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
   6457     if (ssl == NULL) {
   6458         return;
   6459     }
   6460     int ret = SSL_check_private_key(ssl);
   6461     if (ret != 1) {
   6462         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
   6463         SSL_clear(ssl);
   6464         JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
   6465         return;
   6466     }
   6467     JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
   6468 }
   6469 
   6470 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
   6471                                                 jlong ssl_address, jobjectArray principals)
   6472 {
   6473     SSL* ssl = to_SSL(env, ssl_address, true);
   6474     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
   6475     if (ssl == NULL) {
   6476         return;
   6477     }
   6478 
   6479     if (principals == NULL) {
   6480         jniThrowNullPointerException(env, "principals == null");
   6481         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
   6482         return;
   6483     }
   6484 
   6485     int length = env->GetArrayLength(principals);
   6486     if (length == 0) {
   6487         jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
   6488         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
   6489         return;
   6490     }
   6491 
   6492     Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
   6493     if (principalsStack.get() == NULL) {
   6494         jniThrowOutOfMemory(env, "Unable to allocate principal stack");
   6495         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
   6496         return;
   6497     }
   6498     for (int i = 0; i < length; i++) {
   6499         ScopedLocalRef<jbyteArray> principal(env,
   6500                 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
   6501         if (principal.get() == NULL) {
   6502             jniThrowNullPointerException(env, "principals element == null");
   6503             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
   6504             return;
   6505         }
   6506 
   6507         ScopedByteArrayRO buf(env, principal.get());
   6508         if (buf.get() == NULL) {
   6509             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
   6510             return;
   6511         }
   6512         const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
   6513         Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
   6514 
   6515         if (principalX509Name.get() == NULL) {
   6516             ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
   6517             throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
   6518             SSL_clear(ssl);
   6519             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
   6520                       ssl);
   6521             return;
   6522         }
   6523 
   6524         if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
   6525             jniThrowOutOfMemory(env, "Unable to push principal");
   6526             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
   6527             return;
   6528         }
   6529     }
   6530 
   6531     SSL_set_client_CA_list(ssl, principalsStack.release());
   6532     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
   6533 }
   6534 
   6535 /**
   6536  * public static native long SSL_get_mode(int ssl);
   6537  */
   6538 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address) {
   6539     SSL* ssl = to_SSL(env, ssl_address, true);
   6540     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
   6541     if (ssl == NULL) {
   6542       return 0;
   6543     }
   6544     long mode = SSL_get_mode(ssl);
   6545     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
   6546     return mode;
   6547 }
   6548 
   6549 /**
   6550  * public static native long SSL_set_mode(int ssl, long mode);
   6551  */
   6552 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
   6553         jlong ssl_address, jlong mode) {
   6554     SSL* ssl = to_SSL(env, ssl_address, true);
   6555     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
   6556     if (ssl == NULL) {
   6557       return 0;
   6558     }
   6559     long result = SSL_set_mode(ssl, mode);
   6560     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
   6561     return result;
   6562 }
   6563 
   6564 /**
   6565  * public static native long SSL_clear_mode(int ssl, long mode);
   6566  */
   6567 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
   6568         jlong ssl_address, jlong mode) {
   6569     SSL* ssl = to_SSL(env, ssl_address, true);
   6570     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
   6571     if (ssl == NULL) {
   6572       return 0;
   6573     }
   6574     long result = SSL_clear_mode(ssl, mode);
   6575     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
   6576     return result;
   6577 }
   6578 
   6579 /**
   6580  * public static native long SSL_get_options(int ssl);
   6581  */
   6582 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
   6583         jlong ssl_address) {
   6584     SSL* ssl = to_SSL(env, ssl_address, true);
   6585     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
   6586     if (ssl == NULL) {
   6587       return 0;
   6588     }
   6589     long options = SSL_get_options(ssl);
   6590     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
   6591     return options;
   6592 }
   6593 
   6594 /**
   6595  * public static native long SSL_set_options(int ssl, long options);
   6596  */
   6597 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
   6598         jlong ssl_address, jlong options) {
   6599     SSL* ssl = to_SSL(env, ssl_address, true);
   6600     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
   6601     if (ssl == NULL) {
   6602       return 0;
   6603     }
   6604     long result = SSL_set_options(ssl, options);
   6605     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
   6606     return result;
   6607 }
   6608 
   6609 /**
   6610  * public static native long SSL_clear_options(int ssl, long options);
   6611  */
   6612 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
   6613         jlong ssl_address, jlong options) {
   6614     SSL* ssl = to_SSL(env, ssl_address, true);
   6615     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
   6616     if (ssl == NULL) {
   6617       return 0;
   6618     }
   6619     long result = SSL_clear_options(ssl, options);
   6620     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
   6621     return result;
   6622 }
   6623 
   6624 /**
   6625  * Sets the ciphers suites that are enabled in the SSL
   6626  */
   6627 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
   6628         jlong ssl_address, jobjectArray cipherSuites)
   6629 {
   6630     SSL* ssl = to_SSL(env, ssl_address, true);
   6631     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
   6632     if (ssl == NULL) {
   6633         return;
   6634     }
   6635     if (cipherSuites == NULL) {
   6636         jniThrowNullPointerException(env, "cipherSuites == null");
   6637         return;
   6638     }
   6639 
   6640     Unique_sk_SSL_CIPHER cipherstack(sk_SSL_CIPHER_new_null());
   6641     if (cipherstack.get() == NULL) {
   6642         jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
   6643         return;
   6644     }
   6645 
   6646     const SSL_METHOD* ssl_method = ssl->method;
   6647     int num_ciphers = ssl_method->num_ciphers();
   6648 
   6649     int length = env->GetArrayLength(cipherSuites);
   6650     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
   6651     for (int i = 0; i < length; i++) {
   6652         ScopedLocalRef<jstring> cipherSuite(env,
   6653                 reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
   6654         ScopedUtfChars c(env, cipherSuite.get());
   6655         if (c.c_str() == NULL) {
   6656             return;
   6657         }
   6658         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
   6659         bool found = false;
   6660         for (int j = 0; j < num_ciphers; j++) {
   6661             const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
   6662             if ((strcmp(c.c_str(), cipher->name) == 0)
   6663                     && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
   6664                 if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
   6665                     jniThrowOutOfMemory(env, "Unable to push cipher");
   6666                     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
   6667                     return;
   6668                 }
   6669                 found = true;
   6670             }
   6671         }
   6672         if (!found) {
   6673             jniThrowException(env, "java/lang/IllegalArgumentException",
   6674                               "Could not find cipher suite.");
   6675             return;
   6676         }
   6677     }
   6678 
   6679     int rc = SSL_set_cipher_lists(ssl, cipherstack.get());
   6680     if (rc == 0) {
   6681         freeOpenSslErrorState();
   6682         jniThrowException(env, "java/lang/IllegalArgumentException",
   6683                           "Illegal cipher suite strings.");
   6684     } else {
   6685         OWNERSHIP_TRANSFERRED(cipherstack);
   6686     }
   6687 }
   6688 
   6689 /**
   6690  * Sets certificate expectations, especially for server to request client auth
   6691  */
   6692 static void NativeCrypto_SSL_set_verify(JNIEnv* env,
   6693         jclass, jlong ssl_address, jint mode)
   6694 {
   6695     SSL* ssl = to_SSL(env, ssl_address, true);
   6696     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
   6697     if (ssl == NULL) {
   6698       return;
   6699     }
   6700     SSL_set_verify(ssl, (int)mode, NULL);
   6701 }
   6702 
   6703 /**
   6704  * Sets the ciphers suites that are enabled in the SSL
   6705  */
   6706 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
   6707         jlong ssl_address, jlong ssl_session_address)
   6708 {
   6709     SSL* ssl = to_SSL(env, ssl_address, true);
   6710     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
   6711     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
   6712     if (ssl == NULL) {
   6713         return;
   6714     }
   6715 
   6716     int ret = SSL_set_session(ssl, ssl_session);
   6717     if (ret != 1) {
   6718         /*
   6719          * Translate the error, and throw if it turns out to be a real
   6720          * problem.
   6721          */
   6722         int sslErrorCode = SSL_get_error(ssl, ret);
   6723         if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
   6724             throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
   6725             SSL_clear(ssl);
   6726         }
   6727     }
   6728 }
   6729 
   6730 /**
   6731  * Sets the ciphers suites that are enabled in the SSL
   6732  */
   6733 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
   6734         jlong ssl_address, jboolean creation_enabled)
   6735 {
   6736     SSL* ssl = to_SSL(env, ssl_address, true);
   6737     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
   6738               ssl, creation_enabled);
   6739     if (ssl == NULL) {
   6740         return;
   6741     }
   6742     SSL_set_session_creation_enabled(ssl, creation_enabled);
   6743 }
   6744 
   6745 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
   6746         jlong ssl_address, jstring hostname)
   6747 {
   6748     SSL* ssl = to_SSL(env, ssl_address, true);
   6749     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
   6750               ssl, hostname);
   6751     if (ssl == NULL) {
   6752         return;
   6753     }
   6754 
   6755     ScopedUtfChars hostnameChars(env, hostname);
   6756     if (hostnameChars.c_str() == NULL) {
   6757         return;
   6758     }
   6759     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s",
   6760               ssl, hostnameChars.c_str());
   6761 
   6762     int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
   6763     if (ret != 1) {
   6764         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
   6765         SSL_clear(ssl);
   6766         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
   6767         return;
   6768     }
   6769     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
   6770 }
   6771 
   6772 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address) {
   6773     SSL* ssl = to_SSL(env, ssl_address, true);
   6774     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
   6775     if (ssl == NULL) {
   6776         return NULL;
   6777     }
   6778     const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
   6779     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
   6780     return env->NewStringUTF(servername);
   6781 }
   6782 
   6783 /**
   6784  * A common selection path for both NPN and ALPN since they're essentially the
   6785  * same protocol. The list of protocols in "primary" is considered the order
   6786  * which should take precedence.
   6787  */
   6788 static int proto_select(SSL* ssl __attribute__ ((unused)),
   6789         unsigned char **out, unsigned char *outLength,
   6790         const unsigned char *primary, const unsigned int primaryLength,
   6791         const unsigned char *secondary, const unsigned int secondaryLength) {
   6792     if (primary != NULL) {
   6793         JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
   6794 
   6795         int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
   6796                 secondaryLength);
   6797         switch (status) {
   6798         case OPENSSL_NPN_NEGOTIATED:
   6799             JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
   6800             return SSL_TLSEXT_ERR_OK;
   6801             break;
   6802         case OPENSSL_NPN_UNSUPPORTED:
   6803             JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
   6804             break;
   6805         case OPENSSL_NPN_NO_OVERLAP:
   6806             JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
   6807             break;
   6808         }
   6809     } else {
   6810         if (out != NULL && outLength != NULL) {
   6811             *out = NULL;
   6812             *outLength = 0;
   6813         }
   6814         JNI_TRACE("protocols=NULL");
   6815     }
   6816     return SSL_TLSEXT_ERR_NOACK;
   6817 }
   6818 
   6819 /**
   6820  * Callback for the server to select an ALPN protocol.
   6821  */
   6822 static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
   6823         const unsigned char *in, unsigned int inlen, void *) {
   6824     JNI_TRACE("ssl=%p alpn_select_callback", ssl);
   6825 
   6826     AppData* appData = toAppData(ssl);
   6827     JNI_TRACE("AppData=%p", appData);
   6828 
   6829     return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
   6830             reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
   6831             appData->alpnProtocolsLength, in, inlen);
   6832 }
   6833 
   6834 /**
   6835  * Callback for the client to select an NPN protocol.
   6836  */
   6837 static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
   6838                                       const unsigned char* in, unsigned int inlen, void*)
   6839 {
   6840     JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
   6841 
   6842     AppData* appData = toAppData(ssl);
   6843     JNI_TRACE("AppData=%p", appData);
   6844 
   6845     // Enable False Start on the client if the server understands NPN
   6846     // http://www.imperialviolet.org/2012/04/11/falsestart.html
   6847     SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
   6848 
   6849     return proto_select(ssl, out, outlen, in, inlen,
   6850             reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
   6851             appData->npnProtocolsLength);
   6852 }
   6853 
   6854 /**
   6855  * Callback for the server to advertise available protocols.
   6856  */
   6857 static int next_protos_advertised_callback(SSL* ssl,
   6858         const unsigned char **out, unsigned int *outlen, void *)
   6859 {
   6860     JNI_TRACE("ssl=%p next_protos_advertised_callback", ssl);
   6861     AppData* appData = toAppData(ssl);
   6862     unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
   6863     if (npnProtocols != NULL) {
   6864         *out = npnProtocols;
   6865         *outlen = appData->npnProtocolsLength;
   6866         return SSL_TLSEXT_ERR_OK;
   6867     } else {
   6868         *out = NULL;
   6869         *outlen = 0;
   6870         return SSL_TLSEXT_ERR_NOACK;
   6871     }
   6872 }
   6873 
   6874 static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
   6875 {
   6876     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6877     if (ssl_ctx == NULL) {
   6878         return;
   6879     }
   6880     SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); // client
   6881     SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_protos_advertised_callback, NULL); // server
   6882 }
   6883 
   6884 static void NativeCrypto_SSL_CTX_disable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
   6885 {
   6886     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6887     if (ssl_ctx == NULL) {
   6888         return;
   6889     }
   6890     SSL_CTX_set_next_proto_select_cb(ssl_ctx, NULL, NULL); // client
   6891     SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, NULL, NULL); // server
   6892 }
   6893 
   6894 static jbyteArray NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv* env, jclass,
   6895         jlong ssl_address)
   6896 {
   6897     SSL* ssl = to_SSL(env, ssl_address, true);
   6898     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_npn_negotiated_protocol", ssl);
   6899     if (ssl == NULL) {
   6900         return NULL;
   6901     }
   6902     const jbyte* npn;
   6903     unsigned npnLength;
   6904     SSL_get0_next_proto_negotiated(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
   6905     if (npnLength == 0) {
   6906         return NULL;
   6907     }
   6908     jbyteArray result = env->NewByteArray(npnLength);
   6909     if (result != NULL) {
   6910         env->SetByteArrayRegion(result, 0, npnLength, npn);
   6911     }
   6912     return result;
   6913 }
   6914 
   6915 static int NativeCrypto_SSL_CTX_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_ctx_address,
   6916         jbyteArray protos) {
   6917     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
   6918     if (ssl_ctx == NULL) {
   6919         return 0;
   6920     }
   6921 
   6922     JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p", ssl_ctx, protos);
   6923 
   6924     if (protos == NULL) {
   6925         JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=NULL", ssl_ctx);
   6926         return 1;
   6927     }
   6928 
   6929     ScopedByteArrayRO protosBytes(env, protos);
   6930     if (protosBytes.get() == NULL) {
   6931         JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => protosBytes == NULL", ssl_ctx,
   6932                 protos);
   6933         return 0;
   6934     }
   6935 
   6936     const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
   6937     int ret = SSL_CTX_set_alpn_protos(ssl_ctx, tmp, protosBytes.size());
   6938     JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => ret=%d", ssl_ctx, protos, ret);
   6939     return ret;
   6940 }
   6941 
   6942 static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
   6943         jlong ssl_address)
   6944 {
   6945     SSL* ssl = to_SSL(env, ssl_address, true);
   6946     JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
   6947     if (ssl == NULL) {
   6948         return NULL;
   6949     }
   6950     const jbyte* npn;
   6951     unsigned npnLength;
   6952     SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
   6953     if (npnLength == 0) {
   6954         return NULL;
   6955     }
   6956     jbyteArray result = env->NewByteArray(npnLength);
   6957     if (result != NULL) {
   6958         env->SetByteArrayRegion(result, 0, npnLength, npn);
   6959     }
   6960     return result;
   6961 }
   6962 
   6963 #ifdef WITH_JNI_TRACE_KEYS
   6964 static inline char hex_char(unsigned char in)
   6965 {
   6966     if (in < 10) {
   6967         return '0' + in;
   6968     } else if (in <= 0xF0) {
   6969         return 'A' + in - 10;
   6970     } else {
   6971         return '?';
   6972     }
   6973 }
   6974 
   6975 static void hex_string(char **dest, unsigned char* input, int len)
   6976 {
   6977     *dest = (char*) malloc(len * 2 + 1);
   6978     char *output = *dest;
   6979     for (int i = 0; i < len; i++) {
   6980         *output++ = hex_char(input[i] >> 4);
   6981         *output++ = hex_char(input[i] & 0xF);
   6982     }
   6983     *output = '\0';
   6984 }
   6985 
   6986 static void debug_print_session_key(SSL_SESSION* session)
   6987 {
   6988     char *session_id_str;
   6989     char *master_key_str;
   6990     const char *key_type;
   6991     char *keyline;
   6992 
   6993     hex_string(&session_id_str, session->session_id, session->session_id_length);
   6994     hex_string(&master_key_str, session->master_key, session->master_key_length);
   6995 
   6996     X509* peer = SSL_SESSION_get0_peer(session);
   6997     EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
   6998     switch (EVP_PKEY_type(pkey->type)) {
   6999     case EVP_PKEY_RSA:
   7000         key_type = "RSA";
   7001         break;
   7002     case EVP_PKEY_DSA:
   7003         key_type = "DSA";
   7004         break;
   7005     case EVP_PKEY_EC:
   7006         key_type = "EC";
   7007         break;
   7008     default:
   7009         key_type = "Unknown";
   7010         break;
   7011     }
   7012 
   7013     asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
   7014             master_key_str);
   7015     JNI_TRACE("ssl_session=%p %s", session, keyline);
   7016 
   7017     free(session_id_str);
   7018     free(master_key_str);
   7019     free(keyline);
   7020 }
   7021 #endif /* WITH_JNI_TRACE_KEYS */
   7022 
   7023 /**
   7024  * Perform SSL handshake
   7025  */
   7026 static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
   7027         jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
   7028         jbyteArray alpnProtocols) {
   7029     SSL* ssl = to_SSL(env, ssl_address, true);
   7030     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
   7031               ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
   7032     if (ssl == NULL) {
   7033       return 0;
   7034     }
   7035     if (fdObject == NULL) {
   7036         jniThrowNullPointerException(env, "fd == null");
   7037         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => 0", ssl);
   7038         return 0;
   7039     }
   7040     if (shc == NULL) {
   7041         jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
   7042         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => 0", ssl);
   7043         return 0;
   7044     }
   7045 
   7046     NetFd fd(env, fdObject);
   7047     if (fd.isClosed()) {
   7048         // SocketException thrown by NetFd.isClosed
   7049         SSL_clear(ssl);
   7050         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => 0", ssl);
   7051         return 0;
   7052     }
   7053 
   7054     int ret = SSL_set_fd(ssl, fd.get());
   7055     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
   7056 
   7057     if (ret != 1) {
   7058         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
   7059                                        "Error setting the file descriptor");
   7060         SSL_clear(ssl);
   7061         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => 0", ssl);
   7062         return 0;
   7063     }
   7064 
   7065     /*
   7066      * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
   7067      * forever and we can use select() to find out if the socket is ready.
   7068      */
   7069     if (!setBlocking(fd.get(), false)) {
   7070         throwSSLExceptionStr(env, "Unable to make socket non blocking");
   7071         SSL_clear(ssl);
   7072         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => 0", ssl);
   7073         return 0;
   7074     }
   7075 
   7076     /*
   7077      * Create our special application data.
   7078      */
   7079     AppData* appData = AppData::create();
   7080     if (appData == NULL) {
   7081         throwSSLExceptionStr(env, "Unable to create application data");
   7082         SSL_clear(ssl);
   7083         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
   7084         return 0;
   7085     }
   7086 
   7087     SSL_set_app_data(ssl, reinterpret_cast<char*>(appData));
   7088     JNI_TRACE("ssl=%p AppData::create => %p", ssl, appData);
   7089 
   7090     if (client_mode) {
   7091         SSL_set_connect_state(ssl);
   7092     } else {
   7093         SSL_set_accept_state(ssl);
   7094         if (alpnProtocols != NULL) {
   7095             SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
   7096         }
   7097     }
   7098 
   7099     ret = 0;
   7100     while (appData->aliveAndKicking) {
   7101         errno = 0;
   7102 
   7103         if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
   7104             // SocketException thrown by NetFd.isClosed
   7105             SSL_clear(ssl);
   7106             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
   7107             return 0;
   7108         }
   7109         ret = SSL_do_handshake(ssl);
   7110         appData->clearCallbackState();
   7111         // cert_verify_callback threw exception
   7112         if (env->ExceptionCheck()) {
   7113             SSL_clear(ssl);
   7114             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => 0", ssl);
   7115             return 0;
   7116         }
   7117         // success case
   7118         if (ret == 1) {
   7119             break;
   7120         }
   7121         // retry case
   7122         if (errno == EINTR) {
   7123             continue;
   7124         }
   7125         // error case
   7126         int sslError = SSL_get_error(ssl, ret);
   7127         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout_millis=%d",
   7128                   ssl, ret, errno, sslError, timeout_millis);
   7129 
   7130         /*
   7131          * If SSL_do_handshake doesn't succeed due to the socket being
   7132          * either unreadable or unwritable, we use sslSelect to
   7133          * wait for it to become ready. If that doesn't happen
   7134          * before the specified timeout or an error occurs, we
   7135          * cancel the handshake. Otherwise we try the SSL_connect
   7136          * again.
   7137          */
   7138         if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
   7139             appData->waitingThreads++;
   7140             int selectResult = sslSelect(env, sslError, fdObject, appData, timeout_millis);
   7141 
   7142             if (selectResult == THROWN_EXCEPTION) {
   7143                 // SocketException thrown by NetFd.isClosed
   7144                 SSL_clear(ssl);
   7145                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => 0", ssl);
   7146                 return 0;
   7147             }
   7148             if (selectResult == -1) {
   7149                 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error");
   7150                 SSL_clear(ssl);
   7151                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => 0", ssl);
   7152                 return 0;
   7153             }
   7154             if (selectResult == 0) {
   7155                 throwSocketTimeoutException(env, "SSL handshake timed out");
   7156                 SSL_clear(ssl);
   7157                 freeOpenSslErrorState();
   7158                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => 0", ssl);
   7159                 return 0;
   7160             }
   7161         } else {
   7162             // ALOGE("Unknown error %d during handshake", error);
   7163             break;
   7164         }
   7165     }
   7166 
   7167     // clean error. See SSL_do_handshake(3SSL) man page.
   7168     if (ret == 0) {
   7169         /*
   7170          * The other side closed the socket before the handshake could be
   7171          * completed, but everything is within the bounds of the TLS protocol.
   7172          * We still might want to find out the real reason of the failure.
   7173          */
   7174         int sslError = SSL_get_error(ssl, ret);
   7175         if (sslError == SSL_ERROR_NONE || (sslError == SSL_ERROR_SYSCALL && errno == 0)) {
   7176             throwSSLExceptionStr(env, "Connection closed by peer");
   7177         } else {
   7178             throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake terminated");
   7179         }
   7180         SSL_clear(ssl);
   7181         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => 0", ssl);
   7182         return 0;
   7183     }
   7184 
   7185     // unclean error. See SSL_do_handshake(3SSL) man page.
   7186     if (ret < 0) {
   7187         /*
   7188          * Translate the error and throw exception. We are sure it is an error
   7189          * at this point.
   7190          */
   7191         int sslError = SSL_get_error(ssl, ret);
   7192         throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake aborted");
   7193         SSL_clear(ssl);
   7194         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => 0", ssl);
   7195         return 0;
   7196     }
   7197     SSL_SESSION* ssl_session = SSL_get1_session(ssl);
   7198     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
   7199 #ifdef WITH_JNI_TRACE_KEYS
   7200     debug_print_session_key(ssl_session);
   7201 #endif
   7202     return (jlong) ssl_session;
   7203 }
   7204 
   7205 /**
   7206  * Perform SSL renegotiation
   7207  */
   7208 static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jlong ssl_address)
   7209 {
   7210     SSL* ssl = to_SSL(env, ssl_address, true);
   7211     JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
   7212     if (ssl == NULL) {
   7213         return;
   7214     }
   7215     int result = SSL_renegotiate(ssl);
   7216     if (result != 1) {
   7217         throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
   7218         return;
   7219     }
   7220     // first call asks client to perform renegotiation
   7221     int ret = SSL_do_handshake(ssl);
   7222     if (ret != 1) {
   7223         int sslError = SSL_get_error(ssl, ret);
   7224         throwSSLExceptionWithSslErrors(env, ssl, sslError,
   7225                                        "Problem with SSL_do_handshake after SSL_renegotiate");
   7226         return;
   7227     }
   7228     // if client agrees, set ssl state and perform renegotiation
   7229     ssl->state = SSL_ST_ACCEPT;
   7230     SSL_do_handshake(ssl);
   7231     JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
   7232 }
   7233 
   7234 /**
   7235  * public static native byte[][] SSL_get_certificate(int ssl);
   7236  */
   7237 static jobjectArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jlong ssl_address)
   7238 {
   7239     SSL* ssl = to_SSL(env, ssl_address, true);
   7240     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
   7241     if (ssl == NULL) {
   7242         return NULL;
   7243     }
   7244     X509* certificate = SSL_get_certificate(ssl);
   7245     if (certificate == NULL) {
   7246         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
   7247         // SSL_get_certificate can return NULL during an error as well.
   7248         freeOpenSslErrorState();
   7249         return NULL;
   7250     }
   7251 
   7252     Unique_sk_X509 chain(sk_X509_new_null());
   7253     if (chain.get() == NULL) {
   7254         jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
   7255         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
   7256         return NULL;
   7257     }
   7258     if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
   7259         jniThrowOutOfMemory(env, "Unable to push local certificate");
   7260         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
   7261         return NULL;
   7262     }
   7263     STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
   7264     for (int i=0; i<sk_X509_num(cert_chain); i++) {
   7265         if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
   7266             jniThrowOutOfMemory(env, "Unable to push local certificate chain");
   7267             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
   7268             return NULL;
   7269         }
   7270     }
   7271 
   7272     jobjectArray objectArray = getCertificateBytes(env, chain.get());
   7273     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, objectArray);
   7274     return objectArray;
   7275 }
   7276 
   7277 // Fills a byte[][] with the peer certificates in the chain.
   7278 static jobjectArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jlong ssl_address)
   7279 {
   7280     SSL* ssl = to_SSL(env, ssl_address, true);
   7281     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
   7282     if (ssl == NULL) {
   7283         return NULL;
   7284     }
   7285     STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
   7286     Unique_sk_X509 chain_copy(NULL);
   7287     if (ssl->server) {
   7288         X509* x509 = SSL_get_peer_certificate(ssl);
   7289         if (x509 == NULL) {
   7290             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
   7291             return NULL;
   7292         }
   7293         chain_copy.reset(sk_X509_new_null());
   7294         if (chain_copy.get() == NULL) {
   7295             jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
   7296             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
   7297             return NULL;
   7298         }
   7299         size_t chain_size = sk_X509_num(chain);
   7300         for (size_t i = 0; i < chain_size; i++) {
   7301             if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
   7302                 jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
   7303                 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
   7304                 return NULL;
   7305             }
   7306         }
   7307         if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
   7308             jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
   7309             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
   7310             return NULL;
   7311         }
   7312         chain = chain_copy.get();
   7313     }
   7314     jobjectArray objectArray = getCertificateBytes(env, chain);
   7315     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, objectArray);
   7316     return objectArray;
   7317 }
   7318 
   7319 /**
   7320  * Helper function which does the actual reading. The Java layer guarantees that
   7321  * at most one thread will enter this function at any given time.
   7322  *
   7323  * @param ssl non-null; the SSL context
   7324  * @param buf non-null; buffer to read into
   7325  * @param len length of the buffer, in bytes
   7326  * @param sslReturnCode original SSL return code
   7327  * @param sslErrorCode filled in with the SSL error code in case of error
   7328  * @return number of bytes read on success, -1 if the connection was
   7329  * cleanly shut down, or THROW_SSLEXCEPTION if an exception should be thrown.
   7330  */
   7331 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
   7332                    int* sslReturnCode, int* sslErrorCode, int read_timeout_millis) {
   7333     JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
   7334 
   7335     if (len == 0) {
   7336         // Don't bother doing anything in this case.
   7337         return 0;
   7338     }
   7339 
   7340     BIO* bio = SSL_get_rbio(ssl);
   7341 
   7342     AppData* appData = toAppData(ssl);
   7343     if (appData == NULL) {
   7344         return THROW_SSLEXCEPTION;
   7345     }
   7346 
   7347     while (appData->aliveAndKicking) {
   7348         errno = 0;
   7349 
   7350         if (MUTEX_LOCK(appData->mutex) == -1) {
   7351             return -1;
   7352         }
   7353 
   7354         unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
   7355 
   7356         if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
   7357             MUTEX_UNLOCK(appData->mutex);
   7358             return THROWN_EXCEPTION;
   7359         }
   7360         int result = SSL_read(ssl, buf, len);
   7361         appData->clearCallbackState();
   7362         // callbacks can happen if server requests renegotiation
   7363         if (env->ExceptionCheck()) {
   7364             SSL_clear(ssl);
   7365             JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
   7366             return THROWN_EXCEPTION;
   7367         }
   7368         int sslError = SSL_ERROR_NONE;
   7369         if (result <= 0) {
   7370             sslError = SSL_get_error(ssl, result);
   7371             freeOpenSslErrorState();
   7372         }
   7373         JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError);
   7374 #ifdef WITH_JNI_TRACE_DATA
   7375         for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
   7376             int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
   7377             JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
   7378         }
   7379 #endif
   7380 
   7381         // If we have been successful in moving data around, check whether it
   7382         // might make sense to wake up other blocked threads, so they can give
   7383         // it a try, too.
   7384         if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved
   7385                 && appData->waitingThreads > 0) {
   7386             sslNotify(appData);
   7387         }
   7388 
   7389         // If we are blocked by the underlying socket, tell the world that
   7390         // there will be one more waiting thread now.
   7391         if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
   7392             appData->waitingThreads++;
   7393         }
   7394 
   7395         MUTEX_UNLOCK(appData->mutex);
   7396 
   7397         switch (sslError) {
   7398             // Successfully read at least one byte.
   7399             case SSL_ERROR_NONE: {
   7400                 return result;
   7401             }
   7402 
   7403             // Read zero bytes. End of stream reached.
   7404             case SSL_ERROR_ZERO_RETURN: {
   7405                 return -1;
   7406             }
   7407 
   7408             // Need to wait for availability of underlying layer, then retry.
   7409             case SSL_ERROR_WANT_READ:
   7410             case SSL_ERROR_WANT_WRITE: {
   7411                 int selectResult = sslSelect(env, sslError, fdObject, appData, read_timeout_millis);
   7412                 if (selectResult == THROWN_EXCEPTION) {
   7413                     return THROWN_EXCEPTION;
   7414                 }
   7415                 if (selectResult == -1) {
   7416                     *sslReturnCode = -1;
   7417                     *sslErrorCode = sslError;
   7418                     return THROW_SSLEXCEPTION;
   7419                 }
   7420                 if (selectResult == 0) {
   7421                     return THROW_SOCKETTIMEOUTEXCEPTION;
   7422                 }
   7423 
   7424                 break;
   7425             }
   7426 
   7427             // A problem occurred during a system call, but this is not
   7428             // necessarily an error.
   7429             case SSL_ERROR_SYSCALL: {
   7430                 // Connection closed without proper shutdown. Tell caller we
   7431                 // have reached end-of-stream.
   7432                 if (result == 0) {
   7433                     return -1;
   7434                 }
   7435 
   7436                 // System call has been interrupted. Simply retry.
   7437                 if (errno == EINTR) {
   7438                     break;
   7439                 }
   7440 
   7441                 // Note that for all other system call errors we fall through
   7442                 // to the default case, which results in an Exception.
   7443             }
   7444 
   7445             // Everything else is basically an error.
   7446             default: {
   7447                 *sslReturnCode = result;
   7448                 *sslErrorCode = sslError;
   7449                 return THROW_SSLEXCEPTION;
   7450             }
   7451         }
   7452     }
   7453 
   7454     return -1;
   7455 }
   7456 
   7457 /**
   7458  * OpenSSL read function (2): read into buffer at offset n chunks.
   7459  * Returns 1 (success) or value <= 0 (failure).
   7460  */
   7461 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
   7462                                   jobject shc, jbyteArray b, jint offset, jint len,
   7463                                   jint read_timeout_millis)
   7464 {
   7465     SSL* ssl = to_SSL(env, ssl_address, true);
   7466     JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d read_timeout_millis=%d",
   7467               ssl, fdObject, shc, b, offset, len, read_timeout_millis);
   7468     if (ssl == NULL) {
   7469         return 0;
   7470     }
   7471     if (fdObject == NULL) {
   7472         jniThrowNullPointerException(env, "fd == null");
   7473         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
   7474         return 0;
   7475     }
   7476     if (shc == NULL) {
   7477         jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
   7478         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
   7479         return 0;
   7480     }
   7481 
   7482     ScopedByteArrayRW bytes(env, b);
   7483     if (bytes.get() == NULL) {
   7484         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
   7485         return 0;
   7486     }
   7487     int returnCode = 0;
   7488     int sslErrorCode = SSL_ERROR_NONE;;
   7489 
   7490     int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
   7491                       &returnCode, &sslErrorCode, read_timeout_millis);
   7492 
   7493     int result;
   7494     switch (ret) {
   7495         case THROW_SSLEXCEPTION:
   7496             // See sslRead() regarding improper failure to handle normal cases.
   7497             throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Read error");
   7498             result = -1;
   7499             break;
   7500         case THROW_SOCKETTIMEOUTEXCEPTION:
   7501             throwSocketTimeoutException(env, "Read timed out");
   7502             result = -1;
   7503             break;
   7504         case THROWN_EXCEPTION:
   7505             // SocketException thrown by NetFd.isClosed
   7506             // or RuntimeException thrown by callback
   7507             result = -1;
   7508             break;
   7509         default:
   7510             result = ret;
   7511             break;
   7512     }
   7513 
   7514     JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
   7515     return result;
   7516 }
   7517 
   7518 /**
   7519  * Helper function which does the actual writing. The Java layer guarantees that
   7520  * at most one thread will enter this function at any given time.
   7521  *
   7522  * @param ssl non-null; the SSL context
   7523  * @param buf non-null; buffer to write
   7524  * @param len length of the buffer, in bytes
   7525  * @param sslReturnCode original SSL return code
   7526  * @param sslErrorCode filled in with the SSL error code in case of error
   7527  * @return number of bytes read on success, -1 if the connection was
   7528  * cleanly shut down, or THROW_SSLEXCEPTION if an exception should be thrown.
   7529  */
   7530 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
   7531                     int* sslReturnCode, int* sslErrorCode, int write_timeout_millis) {
   7532     JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d",
   7533               ssl, buf, len, write_timeout_millis);
   7534 
   7535     if (len == 0) {
   7536         // Don't bother doing anything in this case.
   7537         return 0;
   7538     }
   7539 
   7540     BIO* bio = SSL_get_wbio(ssl);
   7541 
   7542     AppData* appData = toAppData(ssl);
   7543     if (appData == NULL) {
   7544         return THROW_SSLEXCEPTION;
   7545     }
   7546 
   7547     int count = len;
   7548 
   7549     while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
   7550         errno = 0;
   7551 
   7552         if (MUTEX_LOCK(appData->mutex) == -1) {
   7553             return -1;
   7554         }
   7555 
   7556         unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
   7557 
   7558         if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
   7559             MUTEX_UNLOCK(appData->mutex);
   7560             return THROWN_EXCEPTION;
   7561         }
   7562         JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
   7563         int result = SSL_write(ssl, buf, len);
   7564         appData->clearCallbackState();
   7565         // callbacks can happen if server requests renegotiation
   7566         if (env->ExceptionCheck()) {
   7567             SSL_clear(ssl);
   7568             JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
   7569             return THROWN_EXCEPTION;
   7570         }
   7571         int sslError = SSL_ERROR_NONE;
   7572         if (result <= 0) {
   7573             sslError = SSL_get_error(ssl, result);
   7574             freeOpenSslErrorState();
   7575         }
   7576         JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
   7577                   ssl, result, sslError, ssl->s3->wbuf.left);
   7578 #ifdef WITH_JNI_TRACE_DATA
   7579         for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
   7580             int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
   7581             JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
   7582         }
   7583 #endif
   7584 
   7585         // If we have been successful in moving data around, check whether it
   7586         // might make sense to wake up other blocked threads, so they can give
   7587         // it a try, too.
   7588         if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved
   7589                 && appData->waitingThreads > 0) {
   7590             sslNotify(appData);
   7591         }
   7592 
   7593         // If we are blocked by the underlying socket, tell the world that
   7594         // there will be one more waiting thread now.
   7595         if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
   7596             appData->waitingThreads++;
   7597         }
   7598 
   7599         MUTEX_UNLOCK(appData->mutex);
   7600 
   7601         switch (sslError) {
   7602             // Successfully wrote at least one byte.
   7603             case SSL_ERROR_NONE: {
   7604                 buf += result;
   7605                 len -= result;
   7606                 break;
   7607             }
   7608 
   7609             // Wrote zero bytes. End of stream reached.
   7610             case SSL_ERROR_ZERO_RETURN: {
   7611                 return -1;
   7612             }
   7613 
   7614             // Need to wait for availability of underlying layer, then retry.
   7615             // The concept of a write timeout doesn't really make sense, and
   7616             // it's also not standard Java behavior, so we wait forever here.
   7617             case SSL_ERROR_WANT_READ:
   7618             case SSL_ERROR_WANT_WRITE: {
   7619                 int selectResult = sslSelect(env, sslError, fdObject, appData, write_timeout_millis);
   7620                 if (selectResult == THROWN_EXCEPTION) {
   7621                     return THROWN_EXCEPTION;
   7622                 }
   7623                 if (selectResult == -1) {
   7624                     *sslReturnCode = -1;
   7625                     *sslErrorCode = sslError;
   7626                     return THROW_SSLEXCEPTION;
   7627                 }
   7628                 if (selectResult == 0) {
   7629                     return THROW_SOCKETTIMEOUTEXCEPTION;
   7630                 }
   7631 
   7632                 break;
   7633             }
   7634 
   7635             // A problem occurred during a system call, but this is not
   7636             // necessarily an error.
   7637             case SSL_ERROR_SYSCALL: {
   7638                 // Connection closed without proper shutdown. Tell caller we
   7639                 // have reached end-of-stream.
   7640                 if (result == 0) {
   7641                     return -1;
   7642                 }
   7643 
   7644                 // System call has been interrupted. Simply retry.
   7645                 if (errno == EINTR) {
   7646                     break;
   7647                 }
   7648 
   7649                 // Note that for all other system call errors we fall through
   7650                 // to the default case, which results in an Exception.
   7651             }
   7652 
   7653             // Everything else is basically an error.
   7654             default: {
   7655                 *sslReturnCode = result;
   7656                 *sslErrorCode = sslError;
   7657                 return THROW_SSLEXCEPTION;
   7658             }
   7659         }
   7660     }
   7661     JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
   7662 
   7663     return count;
   7664 }
   7665 
   7666 /**
   7667  * OpenSSL write function (2): write into buffer at offset n chunks.
   7668  */
   7669 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
   7670                                    jobject shc, jbyteArray b, jint offset, jint len, jint write_timeout_millis)
   7671 {
   7672     SSL* ssl = to_SSL(env, ssl_address, true);
   7673     JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d write_timeout_millis=%d",
   7674               ssl, fdObject, shc, b, offset, len, write_timeout_millis);
   7675     if (ssl == NULL) {
   7676         return;
   7677     }
   7678     if (fdObject == NULL) {
   7679         jniThrowNullPointerException(env, "fd == null");
   7680         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
   7681         return;
   7682     }
   7683     if (shc == NULL) {
   7684         jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
   7685         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
   7686         return;
   7687     }
   7688 
   7689     ScopedByteArrayRO bytes(env, b);
   7690     if (bytes.get() == NULL) {
   7691         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
   7692         return;
   7693     }
   7694     int returnCode = 0;
   7695     int sslErrorCode = SSL_ERROR_NONE;
   7696     int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
   7697                        len, &returnCode, &sslErrorCode, write_timeout_millis);
   7698 
   7699     switch (ret) {
   7700         case THROW_SSLEXCEPTION:
   7701             // See sslWrite() regarding improper failure to handle normal cases.
   7702             throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
   7703             break;
   7704         case THROW_SOCKETTIMEOUTEXCEPTION:
   7705             throwSocketTimeoutException(env, "Write timed out");
   7706             break;
   7707         case THROWN_EXCEPTION:
   7708             // SocketException thrown by NetFd.isClosed
   7709             break;
   7710         default:
   7711             break;
   7712     }
   7713 }
   7714 
   7715 /**
   7716  * Interrupt any pending I/O before closing the socket.
   7717  */
   7718 static void NativeCrypto_SSL_interrupt(
   7719         JNIEnv* env, jclass, jlong ssl_address) {
   7720     SSL* ssl = to_SSL(env, ssl_address, false);
   7721     JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
   7722     if (ssl == NULL) {
   7723         return;
   7724     }
   7725 
   7726     /*
   7727      * Mark the connection as quasi-dead, then send something to the emergency
   7728      * file descriptor, so any blocking select() calls are woken up.
   7729      */
   7730     AppData* appData = toAppData(ssl);
   7731     if (appData != NULL) {
   7732         appData->aliveAndKicking = 0;
   7733 
   7734         // At most two threads can be waiting.
   7735         sslNotify(appData);
   7736         sslNotify(appData);
   7737     }
   7738 }
   7739 
   7740 /**
   7741  * OpenSSL close SSL socket function.
   7742  */
   7743 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
   7744                                       jobject fdObject, jobject shc) {
   7745     SSL* ssl = to_SSL(env, ssl_address, false);
   7746     JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
   7747     if (ssl == NULL) {
   7748         return;
   7749     }
   7750     if (fdObject == NULL) {
   7751         jniThrowNullPointerException(env, "fd == null");
   7752         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
   7753         return;
   7754     }
   7755     if (shc == NULL) {
   7756         jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
   7757         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
   7758         return;
   7759     }
   7760 
   7761     AppData* appData = toAppData(ssl);
   7762     if (appData != NULL) {
   7763         if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
   7764             // SocketException thrown by NetFd.isClosed
   7765             SSL_clear(ssl);
   7766             freeOpenSslErrorState();
   7767             return;
   7768         }
   7769 
   7770         /*
   7771          * Try to make socket blocking again. OpenSSL literature recommends this.
   7772          */
   7773         int fd = SSL_get_fd(ssl);
   7774         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
   7775         if (fd != -1) {
   7776             setBlocking(fd, true);
   7777         }
   7778 
   7779         int ret = SSL_shutdown(ssl);
   7780         appData->clearCallbackState();
   7781         // callbacks can happen if server requests renegotiation
   7782         if (env->ExceptionCheck()) {
   7783             SSL_clear(ssl);
   7784             JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
   7785             return;
   7786         }
   7787         switch (ret) {
   7788             case 0:
   7789                 /*
   7790                  * Shutdown was not successful (yet), but there also
   7791                  * is no error. Since we can't know whether the remote
   7792                  * server is actually still there, and we don't want to
   7793                  * get stuck forever in a second SSL_shutdown() call, we
   7794                  * simply return. This is not security a problem as long
   7795                  * as we close the underlying socket, which we actually
   7796                  * do, because that's where we are just coming from.
   7797                  */
   7798                 break;
   7799             case 1:
   7800                 /*
   7801                  * Shutdown was successful. We can safely return. Hooray!
   7802                  */
   7803                 break;
   7804             default:
   7805                 /*
   7806                  * Everything else is a real error condition. We should
   7807                  * let the Java layer know about this by throwing an
   7808                  * exception.
   7809                  */
   7810                 int sslError = SSL_get_error(ssl, ret);
   7811                 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
   7812                 break;
   7813         }
   7814     }
   7815 
   7816     SSL_clear(ssl);
   7817     freeOpenSslErrorState();
   7818 }
   7819 
   7820 /**
   7821  * public static native void SSL_free(int ssl);
   7822  */
   7823 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address)
   7824 {
   7825     SSL* ssl = to_SSL(env, ssl_address, true);
   7826     JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
   7827     if (ssl == NULL) {
   7828         return;
   7829     }
   7830 
   7831     AppData* appData = toAppData(ssl);
   7832     SSL_set_app_data(ssl, NULL);
   7833     delete appData;
   7834     SSL_free(ssl);
   7835 }
   7836 
   7837 /**
   7838  * Gets and returns in a byte array the ID of the actual SSL session.
   7839  */
   7840 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
   7841                                                       jlong ssl_session_address) {
   7842     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7843     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
   7844     if (ssl_session == NULL) {
   7845         return NULL;
   7846     }
   7847     jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
   7848     if (result != NULL) {
   7849         jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
   7850         env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
   7851     }
   7852     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
   7853              ssl_session, result, ssl_session->session_id_length);
   7854     return result;
   7855 }
   7856 
   7857 /**
   7858  * Gets and returns in a long integer the creation's time of the
   7859  * actual SSL session.
   7860  */
   7861 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
   7862     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7863     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
   7864     if (ssl_session == NULL) {
   7865         return 0;
   7866     }
   7867     // result must be jlong, not long or *1000 will overflow
   7868     jlong result = SSL_SESSION_get_time(ssl_session);
   7869     result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
   7870     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
   7871     return result;
   7872 }
   7873 
   7874 /**
   7875  * Gets and returns in a string the version of the SSL protocol. If it
   7876  * returns the string "unknown" it means that no connection is established.
   7877  */
   7878 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jlong ssl_session_address) {
   7879     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7880     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
   7881     if (ssl_session == NULL) {
   7882         return NULL;
   7883     }
   7884     const char* protocol = SSL_SESSION_get_version(ssl_session);
   7885     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
   7886     return env->NewStringUTF(protocol);
   7887 }
   7888 
   7889 /**
   7890  * Gets and returns in a string the cipher negotiated for the SSL session.
   7891  */
   7892 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
   7893     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7894     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
   7895     if (ssl_session == NULL) {
   7896         return NULL;
   7897     }
   7898     const SSL_CIPHER* cipher = ssl_session->cipher;
   7899     const char* name = SSL_CIPHER_get_name(cipher);
   7900     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
   7901     return env->NewStringUTF(name);
   7902 }
   7903 
   7904 /**
   7905  * Frees the SSL session.
   7906  */
   7907 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
   7908     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7909     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
   7910     if (ssl_session == NULL) {
   7911         return;
   7912     }
   7913     SSL_SESSION_free(ssl_session);
   7914 }
   7915 
   7916 
   7917 /**
   7918  * Serializes the native state of the session (ID, cipher, and keys but
   7919  * not certificates). Returns a byte[] containing the DER-encoded state.
   7920  * See apache mod_ssl.
   7921  */
   7922 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
   7923     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
   7924     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
   7925     if (ssl_session == NULL) {
   7926         return NULL;
   7927     }
   7928     return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
   7929 }
   7930 
   7931 /**
   7932  * Deserialize the session.
   7933  */
   7934 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
   7935     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
   7936 
   7937     ScopedByteArrayRO bytes(env, javaBytes);
   7938     if (bytes.get() == NULL) {
   7939         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
   7940         return 0;
   7941     }
   7942     const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
   7943     SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
   7944 
   7945     // Initialize SSL_SESSION cipher field based on cipher_id http://b/7091840
   7946     if (ssl_session != NULL) {
   7947         // based on ssl_get_prev_session
   7948         uint32_t cipher_id_network_order = htonl(ssl_session->cipher_id);
   7949         uint8_t* cipher_id_byte_pointer = reinterpret_cast<uint8_t*>(&cipher_id_network_order);
   7950         if (ssl_session->ssl_version >= SSL3_VERSION_MAJOR) {
   7951             cipher_id_byte_pointer += 2; // skip first two bytes for SSL3+
   7952         } else {
   7953             cipher_id_byte_pointer += 1; // skip first byte for SSL2
   7954         }
   7955         ssl_session->cipher = SSLv23_method()->get_cipher_by_char(cipher_id_byte_pointer);
   7956         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION cipher_id=%lx hton=%x 0=%x 1=%x cipher=%s",
   7957                   ssl_session->cipher_id, cipher_id_network_order,
   7958                   cipher_id_byte_pointer[0], cipher_id_byte_pointer[1],
   7959                   SSL_CIPHER_get_name(ssl_session->cipher));
   7960     } else {
   7961         freeOpenSslErrorState();
   7962     }
   7963 
   7964     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
   7965     return reinterpret_cast<uintptr_t>(ssl_session);
   7966 }
   7967 
   7968 static jlong NativeCrypto_ERR_peek_last_error(JNIEnv*, jclass) {
   7969     return ERR_peek_last_error();
   7970 }
   7971 
   7972 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
   7973 #define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
   7974 static JNINativeMethod sNativeCryptoMethods[] = {
   7975     NATIVE_METHOD(NativeCrypto, clinit, "()V"),
   7976     NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
   7977     NATIVE_METHOD(NativeCrypto, ENGINE_by_id, "(Ljava/lang/String;)J"),
   7978     NATIVE_METHOD(NativeCrypto, ENGINE_add, "(J)I"),
   7979     NATIVE_METHOD(NativeCrypto, ENGINE_init, "(J)I"),
   7980     NATIVE_METHOD(NativeCrypto, ENGINE_finish, "(J)I"),
   7981     NATIVE_METHOD(NativeCrypto, ENGINE_free, "(J)I"),
   7982     NATIVE_METHOD(NativeCrypto, ENGINE_load_private_key, "(JLjava/lang/String;)J"),
   7983     NATIVE_METHOD(NativeCrypto, ENGINE_get_id, "(J)Ljava/lang/String;"),
   7984     NATIVE_METHOD(NativeCrypto, ENGINE_ctrl_cmd_string, "(JLjava/lang/String;Ljava/lang/String;I)I"),
   7985     NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)J"),
   7986     NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
   7987     NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_EC_KEY, "(JJ[B)J"),
   7988     NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_mac_key, "(I[B)J"),
   7989     NATIVE_METHOD(NativeCrypto, EVP_PKEY_type, "(J)I"),
   7990     NATIVE_METHOD(NativeCrypto, EVP_PKEY_size, "(J)I"),
   7991     NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_public, "(J)Ljava/lang/String;"),
   7992     NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_private, "(J)Ljava/lang/String;"),
   7993     NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(J)V"),
   7994     NATIVE_METHOD(NativeCrypto, EVP_PKEY_cmp, "(JJ)I"),
   7995     NATIVE_METHOD(NativeCrypto, i2d_PKCS8_PRIV_KEY_INFO, "(J)[B"),
   7996     NATIVE_METHOD(NativeCrypto, d2i_PKCS8_PRIV_KEY_INFO, "([B)J"),
   7997     NATIVE_METHOD(NativeCrypto, i2d_PUBKEY, "(J)[B"),
   7998     NATIVE_METHOD(NativeCrypto, d2i_PUBKEY, "([B)J"),
   7999     NATIVE_METHOD(NativeCrypto, RSA_generate_key_ex, "(I[B)J"),
   8000     NATIVE_METHOD(NativeCrypto, RSA_size, "(J)I"),
   8001     NATIVE_METHOD(NativeCrypto, RSA_private_encrypt, "(I[B[BJI)I"),
   8002     NATIVE_METHOD(NativeCrypto, RSA_public_decrypt, "(I[B[BJI)I"),
   8003     NATIVE_METHOD(NativeCrypto, RSA_public_encrypt, "(I[B[BJI)I"),
   8004     NATIVE_METHOD(NativeCrypto, RSA_private_decrypt, "(I[B[BJI)I"),
   8005     NATIVE_METHOD(NativeCrypto, get_RSA_private_params, "(J)[[B"),
   8006     NATIVE_METHOD(NativeCrypto, get_RSA_public_params, "(J)[[B"),
   8007     NATIVE_METHOD(NativeCrypto, DSA_generate_key, "(I[B[B[B[B)J"),
   8008     NATIVE_METHOD(NativeCrypto, get_DSA_params, "(J)[[B"),
   8009     NATIVE_METHOD(NativeCrypto, EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
   8010     NATIVE_METHOD(NativeCrypto, EC_GROUP_new_curve, "(I[B[B[B)J"),
   8011     NATIVE_METHOD(NativeCrypto, EC_GROUP_dup, "(J)J"),
   8012     NATIVE_METHOD(NativeCrypto, EC_GROUP_set_asn1_flag, "(JI)V"),
   8013     NATIVE_METHOD(NativeCrypto, EC_GROUP_set_point_conversion_form, "(JI)V"),
   8014     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(J)Ljava/lang/String;"),
   8015     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(J)[[B"),
   8016     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(J)[B"),
   8017     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(J)I"),
   8018     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(J)[B"),
   8019     NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
   8020     NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(JJ)Z"),
   8021     NATIVE_METHOD(NativeCrypto, EC_GROUP_get_generator, "(J)J"),
   8022     NATIVE_METHOD(NativeCrypto, EC_GROUP_set_generator, "(JJ[B[B)V"),
   8023     NATIVE_METHOD(NativeCrypto, get_EC_GROUP_type, "(J)I"),
   8024     NATIVE_METHOD(NativeCrypto, EC_POINT_new, "(J)J"),
   8025     NATIVE_METHOD(NativeCrypto, EC_POINT_clear_free, "(J)V"),
   8026     NATIVE_METHOD(NativeCrypto, EC_POINT_cmp, "(JJJ)Z"),
   8027     NATIVE_METHOD(NativeCrypto, EC_POINT_set_affine_coordinates, "(JJ[B[B)V"),
   8028     NATIVE_METHOD(NativeCrypto, EC_POINT_get_affine_coordinates, "(JJ)[[B"),
   8029     NATIVE_METHOD(NativeCrypto, EC_KEY_generate_key, "(J)J"),
   8030     NATIVE_METHOD(NativeCrypto, EC_KEY_get0_group, "(J)J"),
   8031     NATIVE_METHOD(NativeCrypto, EC_KEY_get_private_key, "(J)[B"),
   8032     NATIVE_METHOD(NativeCrypto, EC_KEY_get_public_key, "(J)J"),
   8033     NATIVE_METHOD(NativeCrypto, ECDH_compute_key, "([BIJJ)I"),
   8034     NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()J"),
   8035     NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_init, "(J)V"),
   8036     NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(J)V"),
   8037     NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_copy, "(J)J"),
   8038     NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(J[BI)I"),
   8039     NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(J)J"),
   8040     NATIVE_METHOD(NativeCrypto, EVP_get_digestbyname, "(Ljava/lang/String;)J"),
   8041     NATIVE_METHOD(NativeCrypto, EVP_MD_block_size, "(J)I"),
   8042     NATIVE_METHOD(NativeCrypto, EVP_MD_size, "(J)I"),
   8043     NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(J[BII)V"),
   8044     NATIVE_METHOD(NativeCrypto, EVP_SignInit, "(Ljava/lang/String;)J"),
   8045     NATIVE_METHOD(NativeCrypto, EVP_SignUpdate, "(J[BII)V"),
   8046     NATIVE_METHOD(NativeCrypto, EVP_SignFinal, "(J[BIJ)I"),
   8047     NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(Ljava/lang/String;)J"),
   8048     NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(J[BII)V"),
   8049     NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(J[BIIJ)I"),
   8050     NATIVE_METHOD(NativeCrypto, EVP_DigestSignInit, "(JJJ)V"),
   8051     NATIVE_METHOD(NativeCrypto, EVP_DigestSignUpdate, "(J[B)V"),
   8052     NATIVE_METHOD(NativeCrypto, EVP_DigestSignFinal, "(J)[B"),
   8053     NATIVE_METHOD(NativeCrypto, EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
   8054     NATIVE_METHOD(NativeCrypto, EVP_CipherInit_ex, "(JJ[B[BZ)V"),
   8055     NATIVE_METHOD(NativeCrypto, EVP_CipherUpdate, "(J[BI[BII)I"),
   8056     NATIVE_METHOD(NativeCrypto, EVP_CipherFinal_ex, "(J[BI)I"),
   8057     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_iv_length, "(J)I"),
   8058     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_new, "()J"),
   8059     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_block_size, "(J)I"),
   8060     NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_buf_len, "(J)I"),
   8061     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_padding, "(JZ)V"),
   8062     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_key_length, "(JI)V"),
   8063     NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_cleanup, "(J)V"),
   8064     NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
   8065     NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
   8066     NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"),
   8067     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
   8068     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
   8069     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
   8070     NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
   8071     NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
   8072     NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
   8073     NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
   8074     NATIVE_METHOD(NativeCrypto, BIO_free, "(J)V"),
   8075     NATIVE_METHOD(NativeCrypto, X509_NAME_print_ex, "(JJ)Ljava/lang/String;"),
   8076     NATIVE_METHOD(NativeCrypto, d2i_X509_bio, "(J)J"),
   8077     NATIVE_METHOD(NativeCrypto, d2i_X509, "([B)J"),
   8078     NATIVE_METHOD(NativeCrypto, i2d_X509, "(J)[B"),
   8079     NATIVE_METHOD(NativeCrypto, i2d_X509_PUBKEY, "(J)[B"),
   8080     NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509, "(J)J"),
   8081     NATIVE_METHOD(NativeCrypto, PEM_read_bio_PKCS7, "(JI)[J"),
   8082     NATIVE_METHOD(NativeCrypto, d2i_PKCS7_bio, "(JI)[J"),
   8083     NATIVE_METHOD(NativeCrypto, i2d_PKCS7, "([J)[B"),
   8084     NATIVE_METHOD(NativeCrypto, ASN1_seq_unpack_X509_bio, "(J)[J"),
   8085     NATIVE_METHOD(NativeCrypto, ASN1_seq_pack_X509, "([J)[B"),
   8086     NATIVE_METHOD(NativeCrypto, X509_free, "(J)V"),
   8087     NATIVE_METHOD(NativeCrypto, X509_cmp, "(JJ)I"),
   8088     NATIVE_METHOD(NativeCrypto, get_X509_hashCode, "(J)I"),
   8089     NATIVE_METHOD(NativeCrypto, X509_print_ex, "(JJJJ)V"),
   8090     NATIVE_METHOD(NativeCrypto, X509_get_pubkey, "(J)J"),
   8091     NATIVE_METHOD(NativeCrypto, X509_get_issuer_name, "(J)[B"),
   8092     NATIVE_METHOD(NativeCrypto, X509_get_subject_name, "(J)[B"),
   8093     NATIVE_METHOD(NativeCrypto, get_X509_pubkey_oid, "(J)Ljava/lang/String;"),
   8094     NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_oid, "(J)Ljava/lang/String;"),
   8095     NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_parameter, "(J)[B"),
   8096     NATIVE_METHOD(NativeCrypto, get_X509_issuerUID, "(J)[Z"),
   8097     NATIVE_METHOD(NativeCrypto, get_X509_subjectUID, "(J)[Z"),
   8098     NATIVE_METHOD(NativeCrypto, get_X509_ex_kusage, "(J)[Z"),
   8099     NATIVE_METHOD(NativeCrypto, get_X509_ex_xkusage, "(J)[Ljava/lang/String;"),
   8100     NATIVE_METHOD(NativeCrypto, get_X509_ex_pathlen, "(J)I"),
   8101     NATIVE_METHOD(NativeCrypto, X509_get_ext_oid, "(JLjava/lang/String;)[B"),
   8102     NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext_oid, "(JLjava/lang/String;)[B"),
   8103     NATIVE_METHOD(NativeCrypto, get_X509_CRL_crl_enc, "(J)[B"),
   8104     NATIVE_METHOD(NativeCrypto, X509_CRL_verify, "(JJ)V"),
   8105     NATIVE_METHOD(NativeCrypto, X509_CRL_get_lastUpdate, "(J)J"),
   8106     NATIVE_METHOD(NativeCrypto, X509_CRL_get_nextUpdate, "(J)J"),
   8107     NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
   8108     NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_serialNumber, "(J)[B"),
   8109     NATIVE_METHOD(NativeCrypto, X509_REVOKED_print, "(JJ)V"),
   8110     NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_revocationDate, "(J)J"),
   8111     NATIVE_METHOD(NativeCrypto, get_X509_ext_oids, "(JI)[Ljava/lang/String;"),
   8112     NATIVE_METHOD(NativeCrypto, get_X509_CRL_ext_oids, "(JI)[Ljava/lang/String;"),
   8113     NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
   8114     NATIVE_METHOD(NativeCrypto, get_X509_GENERAL_NAME_stack, "(JI)[[Ljava/lang/Object;"),
   8115     NATIVE_METHOD(NativeCrypto, X509_get_notBefore, "(J)J"),
   8116     NATIVE_METHOD(NativeCrypto, X509_get_notAfter, "(J)J"),
   8117     NATIVE_METHOD(NativeCrypto, X509_get_version, "(J)J"),
   8118     NATIVE_METHOD(NativeCrypto, X509_get_serialNumber, "(J)[B"),
   8119     NATIVE_METHOD(NativeCrypto, X509_verify, "(JJ)V"),
   8120     NATIVE_METHOD(NativeCrypto, get_X509_cert_info_enc, "(J)[B"),
   8121     NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
   8122     NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
   8123     NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
   8124     NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
   8125     NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
   8126     NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
   8127     NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
   8128     NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_serial, "(J[B)J"),
   8129     NATIVE_METHOD(NativeCrypto, X509_CRL_get_REVOKED, "(J)[J"),
   8130     NATIVE_METHOD(NativeCrypto, i2d_X509_CRL, "(J)[B"),
   8131     NATIVE_METHOD(NativeCrypto, X509_CRL_free, "(J)V"),
   8132     NATIVE_METHOD(NativeCrypto, X509_CRL_print, "(JJ)V"),
   8133     NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_oid, "(J)Ljava/lang/String;"),
   8134     NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_parameter, "(J)[B"),
   8135     NATIVE_METHOD(NativeCrypto, X509_CRL_get_issuer_name, "(J)[B"),
   8136     NATIVE_METHOD(NativeCrypto, X509_CRL_get_version, "(J)J"),
   8137     NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext, "(JLjava/lang/String;)J"),
   8138     NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
   8139     NATIVE_METHOD(NativeCrypto, X509_REVOKED_dup, "(J)J"),
   8140     NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
   8141     NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
   8142     NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
   8143     NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
   8144     NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
   8145     NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),
   8146     NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
   8147     NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
   8148     NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
   8149     NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
   8150     NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
   8151     NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[[B)V"),
   8152     NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
   8153     NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
   8154     NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(J)J"),
   8155     NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(JJ)J"),
   8156     NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(JJ)J"),
   8157     NATIVE_METHOD(NativeCrypto, SSL_get_options, "(J)J"),
   8158     NATIVE_METHOD(NativeCrypto, SSL_set_options, "(JJ)J"),
   8159     NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(JJ)J"),
   8160     NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(J[Ljava/lang/String;)V"),
   8161     NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(JI)V"),
   8162     NATIVE_METHOD(NativeCrypto, SSL_set_session, "(JJ)V"),
   8163     NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
   8164     NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
   8165     NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
   8166     NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)I"),
   8167     NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
   8168     NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[[B"),
   8169     NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[[B"),
   8170     NATIVE_METHOD(NativeCrypto, SSL_read, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
   8171     NATIVE_METHOD(NativeCrypto, SSL_write, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
   8172     NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(J)V"),
   8173     NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(J" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
   8174     NATIVE_METHOD(NativeCrypto, SSL_free, "(J)V"),
   8175     NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(J)[B"),
   8176     NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(J)J"),
   8177     NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
   8178     NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
   8179     NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(J)V"),
   8180     NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(J)[B"),
   8181     NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)J"),
   8182     NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
   8183     NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
   8184     NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
   8185     NATIVE_METHOD(NativeCrypto, SSL_CTX_set_alpn_protos, "(J[B)I"),
   8186     NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
   8187     NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
   8188 };
   8189 
   8190 static void initialize_conscrypt(JNIEnv* env) {
   8191     jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
   8192                              sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
   8193 
   8194     ScopedLocalRef<jclass> localClass(env,
   8195             env->FindClass(TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream"));
   8196     openSslOutputStreamClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
   8197     if (openSslOutputStreamClass == NULL) {
   8198         ALOGE("failed to find class OpenSSLBIOInputStream");
   8199         abort();
   8200     }
   8201 
   8202     calendar_setMethod = env->GetMethodID(calendarClass, "set", "(IIIIII)V");
   8203     inputStream_readMethod = env->GetMethodID(inputStreamClass, "read", "([B)I");
   8204     integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
   8205             "(I)Ljava/lang/Integer;");
   8206     openSslInputStream_readLineMethod = env->GetMethodID(openSslOutputStreamClass, "gets",
   8207             "([B)I");
   8208     outputStream_writeMethod = env->GetMethodID(outputStreamClass, "write", "([B)V");
   8209     outputStream_flushMethod = env->GetMethodID(outputStreamClass, "flush", "()V");
   8210 }
   8211 
   8212 static jclass findClass(JNIEnv* env, const char* name) {
   8213     ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
   8214     jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
   8215     if (result == NULL) {
   8216         ALOGE("failed to find class '%s'", name);
   8217         abort();
   8218     }
   8219     return result;
   8220 }
   8221 
   8222 // Use JNI_OnLoad for when we're standalone
   8223 int JNI_OnLoad(JavaVM *vm, void*) {
   8224     JNI_TRACE("JNI_OnLoad NativeCrypto");
   8225     gJavaVM = vm;
   8226 
   8227     JNIEnv *env;
   8228     if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
   8229         ALOGE("Could not get JNIEnv");
   8230         return JNI_ERR;
   8231     }
   8232 
   8233     byteArrayClass = findClass(env, "[B");
   8234     calendarClass = findClass(env, "java/util/Calendar");
   8235     inputStreamClass = findClass(env, "java/io/InputStream");
   8236     integerClass = findClass(env, "java/lang/Integer");
   8237     objectClass = findClass(env, "java/lang/Object");
   8238     objectArrayClass = findClass(env, "[Ljava/lang/Object;");
   8239     outputStreamClass = findClass(env, "java/io/OutputStream");
   8240     stringClass = findClass(env, "java/lang/String");
   8241 
   8242     initialize_conscrypt(env);
   8243     return JNI_VERSION_1_6;
   8244 }
   8245