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