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