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