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