xref: /aosp_15_r20/external/conscrypt/common/src/jni/main/cpp/conscrypt/native_crypto.cc (revision cd0cc2e34ba52cdf454361820a14d744e4bd531d)
1 /*
2  * Copyright (C) 2007-2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <conscrypt/NetFd.h>
18 #include <conscrypt/app_data.h>
19 #include <conscrypt/bio_input_stream.h>
20 #include <conscrypt/bio_output_stream.h>
21 #include <conscrypt/bio_stream.h>
22 #include <conscrypt/compat.h>
23 #include <conscrypt/compatibility_close_monitor.h>
24 #include <conscrypt/jniutil.h>
25 #include <conscrypt/logging.h>
26 #include <conscrypt/macros.h>
27 #include <conscrypt/native_crypto.h>
28 #include <conscrypt/netutil.h>
29 #include <conscrypt/scoped_ssl_bio.h>
30 #include <conscrypt/ssl_error.h>
31 #include <limits.h>
32 #include <nativehelper/scoped_primitive_array.h>
33 #include <nativehelper/scoped_utf_chars.h>
34 #include <openssl/aead.h>
35 #include <openssl/asn1.h>
36 #include <openssl/bn.h>
37 #include <openssl/chacha.h>
38 #include <openssl/cmac.h>
39 #include <openssl/crypto.h>
40 #include <openssl/curve25519.h>
41 #include <openssl/engine.h>
42 #include <openssl/err.h>
43 #include <openssl/evp.h>
44 #include <openssl/hmac.h>
45 #include <openssl/hpke.h>
46 #include <openssl/pkcs7.h>
47 #include <openssl/pkcs8.h>
48 #include <openssl/rand.h>
49 #include <openssl/rsa.h>
50 #include <openssl/ssl.h>
51 #include <openssl/x509v3.h>
52 
53 #include <limits>
54 #include <optional>
55 #include <type_traits>
56 #include <vector>
57 
58 using conscrypt::AppData;
59 using conscrypt::BioInputStream;
60 using conscrypt::BioOutputStream;
61 using conscrypt::BioStream;
62 using conscrypt::CompatibilityCloseMonitor;
63 using conscrypt::NativeCrypto;
64 using conscrypt::SslError;
65 
66 /**
67  * Helper function that grabs the casts an ssl pointer and then checks for nullness.
68  * If this function returns nullptr and <code>throwIfNull</code> is
69  * passed as <code>true</code>, then this function will call
70  * <code>throwSSLExceptionStr</code> before returning, so in this case of
71  * nullptr, a caller of this function should simply return and allow JNI
72  * to do its thing.
73  *
74  * @param env the JNI environment
75  * @param ssl_address; the ssl_address pointer as an integer
76  * @param throwIfNull whether to throw if the SSL pointer is nullptr
77  * @returns the pointer, which may be nullptr
78  */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)79 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
80     SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
81     if ((ssl_ctx == nullptr) && throwIfNull) {
82         JNI_TRACE("ssl_ctx == null");
83         conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
84     }
85     return ssl_ctx;
86 }
87 
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)88 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
89     SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
90     if ((ssl == nullptr) && throwIfNull) {
91         JNI_TRACE("ssl == null");
92         conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
93     }
94     return ssl;
95 }
96 
to_BIO(JNIEnv * env,jlong bio_address)97 static BIO* to_BIO(JNIEnv* env, jlong bio_address) {
98     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
99     if (bio == nullptr) {
100         JNI_TRACE("bio == null");
101         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
102     }
103     return bio;
104 }
105 
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)106 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
107     SSL_SESSION* ssl_session =
108             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
109     if ((ssl_session == nullptr) && throwIfNull) {
110         JNI_TRACE("ssl_session == null");
111         conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
112     }
113     return ssl_session;
114 }
115 
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)116 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
117     SSL_CIPHER* ssl_cipher =
118             reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
119     if ((ssl_cipher == nullptr) && throwIfNull) {
120         JNI_TRACE("ssl_cipher == null");
121         conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
122     }
123     return ssl_cipher;
124 }
125 
126 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)127 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
128     if (contextObject == nullptr) {
129         JNI_TRACE("contextObject == null");
130         conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
131         return nullptr;
132     }
133     T* ref = reinterpret_cast<T*>(
134             env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
135     if (ref == nullptr) {
136         JNI_TRACE("ref == null");
137         conscrypt::jniutil::throwNullPointerException(env, "ref == null");
138         return nullptr;
139     }
140     return ref;
141 }
142 
143 /**
144  * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
145  * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
146  * return value is false, there is a pending exception.
147  */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)148 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
149     JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
150     if (dest == nullptr) {
151         JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
152         conscrypt::jniutil::throwNullPointerException(env, "dest == null");
153         return false;
154     }
155     JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
156 
157     ScopedByteArrayRO sourceBytes(env, source);
158     if (sourceBytes.get() == nullptr) {
159         JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
160         return false;
161     }
162     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
163     size_t tmpSize = sourceBytes.size();
164 
165     /* if the array is empty, it is zero. */
166     if (tmpSize == 0) {
167         if (*dest == nullptr) {
168             *dest = BN_new();
169         }
170         BN_zero(*dest);
171         return true;
172     }
173 
174     std::unique_ptr<unsigned char[]> twosComplement;
175     bool negative = (tmp[0] & 0x80) != 0;
176     if (negative) {
177         // Need to convert to two's complement.
178         twosComplement.reset(new unsigned char[tmpSize]);
179         unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
180         memcpy(twosBytes, tmp, tmpSize);
181         tmp = twosBytes;
182 
183         bool carry = true;
184         for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
185             twosBytes[i] ^= 0xFF;
186             if (carry) {
187                 carry = (++twosBytes[i]) == 0;
188             }
189         }
190     }
191     BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
192     if (ret == nullptr) {
193         conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
194         ERR_clear_error();
195         JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
196         return false;
197     }
198     BN_set_negative(ret, negative ? 1 : 0);
199 
200     *dest = ret;
201     JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
202     return true;
203 }
204 
arrayToBignum(JNIEnv * env,jbyteArray source)205 static bssl::UniquePtr<BIGNUM> arrayToBignum(JNIEnv* env, jbyteArray source) {
206     BIGNUM *bn = nullptr;
207     if (!arrayToBignum(env, source, &bn)) {
208         return nullptr;
209     }
210     return bssl::UniquePtr<BIGNUM>(bn);
211 }
212 
213 /**
214  * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
215  */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)216 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
217     JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
218 
219     if (source == nullptr) {
220         conscrypt::jniutil::throwNullPointerException(env, sourceName);
221         return nullptr;
222     }
223 
224     size_t numBytes = BN_num_bytes(source) + 1;
225     jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
226     ScopedByteArrayRW bytes(env, javaBytes);
227     if (bytes.get() == nullptr) {
228         JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
229         return nullptr;
230     }
231 
232     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
233     if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
234         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
235         return nullptr;
236     }
237 
238     // Set the sign and convert to two's complement if necessary for the Java code.
239     if (BN_is_negative(source)) {
240         bool carry = true;
241         for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
242             tmp[i] ^= 0xFF;
243             if (carry) {
244                 carry = (++tmp[i]) == 0;
245             }
246         }
247         *tmp |= 0x80;
248     } else {
249         *tmp = 0x00;
250     }
251 
252     JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
253     return javaBytes;
254 }
255 
256 /**
257  * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
258  * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
259  * from the OpenSSL ASN.1 API. Note i2d_func may take a const parameter, so we
260  * use a separate type parameter.
261  *
262  * TODO(https://crbug.com/boringssl/407): When all BoringSSL i2d functions are
263  * const, switch back to a single template parameter.
264  */
265 template <typename T, typename U>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(U *,unsigned char **))266 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(U*, unsigned char**)) {
267     // T and U should be the same type, but may differ in const.
268     static_assert(std::is_same<typename std::remove_const<T>::type,
269                                typename std::remove_const<U>::type>::value,
270                   "obj and i2d_func have incompatible types");
271 
272     if (obj == nullptr) {
273         conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
274         JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
275         return nullptr;
276     }
277 
278     int derLen = i2d_func(obj, nullptr);
279     if (derLen < 0) {
280         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
281         JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
282         return nullptr;
283     }
284 
285     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
286     if (byteArray.get() == nullptr) {
287         JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
288         return nullptr;
289     }
290 
291     ScopedByteArrayRW bytes(env, byteArray.get());
292     if (bytes.get() == nullptr) {
293         JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
294         return nullptr;
295     }
296 
297     unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
298     int ret = i2d_func(obj, &p);
299     if (ret < 0) {
300         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
301         JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
302         return nullptr;
303     }
304 
305     JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
306     return byteArray.release();
307 }
308 
309 /**
310  * Finishes a pending CBB and returns a jbyteArray with the contents.
311  */
CBBToByteArray(JNIEnv * env,CBB * cbb)312 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
313     uint8_t* data;
314     size_t len;
315     if (!CBB_finish(cbb, &data, &len)) {
316         conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
317         ERR_clear_error();
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 
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)339 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
340     if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
341         JNI_TRACE("buffer too large");
342         conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
343         return nullptr;
344     }
345 
346     int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
347     jbyteArray ret = env->NewByteArray(length);
348     if (ret == nullptr) {
349         JNI_TRACE("allocating byte array failed");
350         return nullptr;
351     }
352 
353     env->SetByteArrayRegion(ret, 0, length,
354                             reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
355     return ret;
356 }
357 
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)358 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
359                                                        CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
360     if (array == nullptr) {
361         JNI_TRACE("array was null");
362         conscrypt::jniutil::throwNullPointerException(env, "array == null");
363         return nullptr;
364     }
365 
366     ScopedByteArrayRO arrayRo(env, array);
367     if (arrayRo.get() == nullptr) {
368         JNI_TRACE("failed to get bytes");
369         return nullptr;
370     }
371 
372     bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
373             reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
374     if (!ret) {
375         JNI_TRACE("failed to allocate CRYPTO_BUFFER");
376         conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
377         return nullptr;
378     }
379 
380     return ret;
381 }
382 
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)383 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
384                                                const STACK_OF(CRYPTO_BUFFER)* buffers) {
385     size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
386     if (numBuffers > INT_MAX) {
387         JNI_TRACE("too many buffers");
388         conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
389         return nullptr;
390     }
391 
392     ScopedLocalRef<jobjectArray> array(
393             env, env->NewObjectArray(static_cast<int>(numBuffers),
394                                      conscrypt::jniutil::byteArrayClass, nullptr));
395     if (array.get() == nullptr) {
396         JNI_TRACE("failed to allocate array");
397         return nullptr;
398     }
399 
400     for (size_t i = 0; i < numBuffers; ++i) {
401         CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
402         ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
403         if (bArray.get() == nullptr) {
404             return nullptr;
405         }
406         env->SetObjectArrayElement(array.get(), i, bArray.get());
407     }
408 
409     return array.release();
410 }
411 
412 /**
413  * Converts ASN.1 BIT STRING to a jbooleanArray.
414  */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)415 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
416     int size = ASN1_STRING_length(bitStr) * 8;
417     if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
418         size -= bitStr->flags & 0x07;
419     }
420 
421     ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
422     if (bitsRef.get() == nullptr) {
423         return nullptr;
424     }
425 
426     ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
427     for (size_t i = 0; i < bitsArray.size(); i++) {
428         bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
429     }
430 
431     return bitsRef.release();
432 }
433 
bio_stream_destroy(BIO * b)434 static int bio_stream_destroy(BIO* b) {
435     if (b == nullptr) {
436         return 0;
437     }
438 
439     delete static_cast<BioStream*>(BIO_get_data(b));
440     BIO_set_data(b, nullptr);
441     BIO_set_init(b, 0);
442     return 1;
443 }
444 
bio_stream_read(BIO * b,char * buf,int len)445 static int bio_stream_read(BIO* b, char* buf, int len) {
446     BIO_clear_retry_flags(b);
447     BioInputStream* stream = static_cast<BioInputStream*>(BIO_get_data(b));
448     int ret = stream->read(buf, len);
449     if (ret == 0) {
450         if (stream->isFinite()) {
451             return 0;
452         }
453         // If the BioInputStream is not finite then EOF doesn't mean that
454         // there's nothing more coming.
455         BIO_set_retry_read(b);
456         return -1;
457     }
458     return ret;
459 }
460 
bio_stream_write(BIO * b,const char * buf,int len)461 static int bio_stream_write(BIO* b, const char* buf, int len) {
462     BIO_clear_retry_flags(b);
463     BioOutputStream* stream = static_cast<BioOutputStream*>(BIO_get_data(b));
464     return stream->write(buf, len);
465 }
466 
bio_stream_gets(BIO * b,char * buf,int len)467 static int bio_stream_gets(BIO* b, char* buf, int len) {
468     BioInputStream* stream = static_cast<BioInputStream*>(BIO_get_data(b));
469     return stream->gets(buf, len);
470 }
471 
bio_stream_assign(BIO * b,BioStream * stream)472 static void bio_stream_assign(BIO* b, BioStream* stream) {
473     BIO_set_data(b, stream);
474     BIO_set_init(b, 1);
475 }
476 
477 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)478 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
479     BioStream* stream = static_cast<BioStream*>(BIO_get_data(b));
480 
481     switch (cmd) {
482         case BIO_CTRL_EOF:
483             return stream->isEof() ? 1 : 0;
484         case BIO_CTRL_FLUSH:
485             return stream->flush();
486         default:
487             return 0;
488     }
489 }
490 
stream_bio_method()491 static const BIO_METHOD *stream_bio_method() {
492     static const BIO_METHOD* stream_method = []() -> const BIO_METHOD* {
493         BIO_METHOD* method = BIO_meth_new(0, nullptr);
494         if (!method || !BIO_meth_set_write(method, bio_stream_write) ||
495             !BIO_meth_set_read(method, bio_stream_read) ||
496             !BIO_meth_set_gets(method, bio_stream_gets) ||
497             !BIO_meth_set_ctrl(method, bio_stream_ctrl) ||
498             !BIO_meth_set_destroy(method, bio_stream_destroy)) {
499             BIO_meth_free(method);
500             return nullptr;
501         }
502         return method;
503     }();
504     return stream_method;
505 }
506 
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)507 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
508                                              size_t message_len) {
509     JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
510     if (message_len > std::numeric_limits<jsize>::max()) {
511         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
512         return nullptr;
513     }
514     ScopedLocalRef<jbyteArray> messageArray(env,
515                                             env->NewByteArray(static_cast<jsize>(message_len)));
516     if (env->ExceptionCheck()) {
517         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
518         return nullptr;
519     }
520 
521     {
522         ScopedByteArrayRW messageBytes(env, messageArray.get());
523         if (messageBytes.get() == nullptr) {
524             JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
525             return nullptr;
526         }
527 
528         memcpy(messageBytes.get(), message, message_len);
529     }
530 
531     return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
532             conscrypt::jniutil::cryptoUpcallsClass,
533             conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod, privateKey, messageArray.get()));
534 }
535 
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)536 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
537                                               const char* message, size_t message_len) {
538     if (message_len > std::numeric_limits<jsize>::max()) {
539         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
540         return nullptr;
541     }
542     ScopedLocalRef<jbyteArray> messageArray(env,
543                                             env->NewByteArray(static_cast<jsize>(message_len)));
544     if (env->ExceptionCheck()) {
545         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
546         return nullptr;
547     }
548 
549     {
550         ScopedByteArrayRW messageBytes(env, messageArray.get());
551         if (messageBytes.get() == nullptr) {
552             JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
553             return nullptr;
554         }
555 
556         memcpy(messageBytes.get(), message, message_len);
557     }
558 
559     return reinterpret_cast<jbyteArray>(
560             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
561                                         conscrypt::jniutil::cryptoUpcallsClass_rsaSignMethod,
562                                         privateKey, padding, messageArray.get()));
563 }
564 
565 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
566 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
567 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
568 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)569 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
570                                            const char* ciphertext, size_t ciphertext_len) {
571     if (ciphertext_len > std::numeric_limits<jsize>::max()) {
572         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
573         return nullptr;
574     }
575     ScopedLocalRef<jbyteArray> ciphertextArray(
576             env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
577     if (env->ExceptionCheck()) {
578         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
579         return nullptr;
580     }
581 
582     {
583         ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
584         if (ciphertextBytes.get() == nullptr) {
585             JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
586             return nullptr;
587         }
588 
589         memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
590     }
591 
592     return reinterpret_cast<jbyteArray>(
593             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
594                                         conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
595                                         privateKey, padding, ciphertextArray.get()));
596 }
597 
598 // *********************************************
599 // From keystore_openssl.cpp in Chromium source.
600 // *********************************************
601 
602 namespace {
603 
604 ENGINE* g_engine;
605 int g_rsa_exdata_index;
606 int g_ecdsa_exdata_index;
607 RSA_METHOD g_rsa_method;
608 ECDSA_METHOD g_ecdsa_method;
609 std::once_flag g_engine_once;
610 
611 void init_engine_globals();
612 
ensure_engine_globals()613 void ensure_engine_globals() {
614     std::call_once(g_engine_once, init_engine_globals);
615 }
616 
617 // KeyExData contains the data that is contained in the EX_DATA of the RSA
618 // and ECDSA objects that are created to wrap Android system keys.
619 struct KeyExData {
620     // private_key contains a reference to a Java, private-key object.
621     jobject private_key;
622 };
623 
624 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
625 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)626 int ExDataDup(CRYPTO_EX_DATA* /* to */,
627               const CRYPTO_EX_DATA* /* from */,
628               void** /* from_d */,
629               int /* index */,
630               long /* argl */ /* NOLINT(runtime/int) */,
631               void* /* argp */) {
632   return 0;
633 }
634 
635 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)636 void ExDataFree(void* /* parent */,
637                 void* ptr,
638                 CRYPTO_EX_DATA* /* ad */,
639                 int /* index */,
640                 long /* argl */ /* NOLINT(runtime/int) */,
641                 void* /* argp */) {
642     // Ensure the global JNI reference created with this wrapper is
643     // properly destroyed with it.
644     KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
645     if (ex_data != nullptr) {
646         JNIEnv* env = conscrypt::jniutil::getJNIEnv();
647         env->DeleteGlobalRef(ex_data->private_key);
648         delete ex_data;
649     }
650 }
651 
RsaGetExData(const RSA * rsa)652 KeyExData* RsaGetExData(const RSA* rsa) {
653     return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
654 }
655 
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)656 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
657                      size_t in_len, int padding) {
658     if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
659         OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
660         return 0;
661     }
662 
663     // Retrieve private key JNI reference.
664     const KeyExData* ex_data = RsaGetExData(rsa);
665     if (!ex_data || !ex_data->private_key) {
666         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
667         return 0;
668     }
669 
670     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
671     if (env == nullptr) {
672         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
673         return 0;
674     }
675 
676     // For RSA keys, this function behaves as RSA_private_encrypt with
677     // the specified padding.
678     ScopedLocalRef<jbyteArray> signature(
679             env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
680                                              reinterpret_cast<const char*>(in), in_len));
681 
682     if (signature.get() == nullptr) {
683         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
684         return 0;
685     }
686 
687     ScopedByteArrayRO result(env, signature.get());
688 
689     size_t expected_size = static_cast<size_t>(RSA_size(rsa));
690     if (result.size() > expected_size) {
691         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
692         return 0;
693     }
694 
695     if (max_out < expected_size) {
696         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
697         return 0;
698     }
699 
700     // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
701     // should pad with leading 0s, but if it doesn't, pad the result.
702     size_t zero_pad = expected_size - result.size();
703     memset(out, 0, zero_pad);
704     memcpy(out + zero_pad, &result[0], result.size());
705     *out_len = expected_size;
706 
707     return 1;
708 }
709 
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)710 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
711                      size_t in_len, int padding) {
712     // Retrieve private key JNI reference.
713     const KeyExData* ex_data = RsaGetExData(rsa);
714     if (!ex_data || !ex_data->private_key) {
715         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
716         return 0;
717     }
718 
719     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
720     if (env == nullptr) {
721         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
722         return 0;
723     }
724 
725     // This function behaves as RSA_private_decrypt.
726     ScopedLocalRef<jbyteArray> cleartext(
727             env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
728                                           reinterpret_cast<const char*>(in), in_len));
729     if (cleartext.get() == nullptr) {
730         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
731         return 0;
732     }
733 
734     ScopedByteArrayRO cleartextBytes(env, cleartext.get());
735 
736     if (max_out < cleartextBytes.size()) {
737         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
738         return 0;
739     }
740 
741     // Copy result to OpenSSL-provided buffer.
742     memcpy(out, cleartextBytes.get(), cleartextBytes.size());
743     *out_len = cleartextBytes.size();
744 
745     return 1;
746 }
747 
748 // Custom ECDSA_METHOD that uses the platform APIs.
749 // Note that for now, only signing through ECDSA_sign() is really supported.
750 // all other method pointers are either stubs returning errors, or no-ops.
751 
EcKeyGetKey(const EC_KEY * ec_key)752 jobject EcKeyGetKey(const EC_KEY* ec_key) {
753     KeyExData* ex_data =
754             reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
755     return ex_data->private_key;
756 }
757 
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)758 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
759                     EC_KEY* ec_key) {
760     // Retrieve private key JNI reference.
761     jobject private_key = EcKeyGetKey(ec_key);
762     if (!private_key) {
763         CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
764         return 0;
765     }
766 
767     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
768     if (env == nullptr) {
769         return 0;
770     }
771 
772     // Sign message with it through JNI.
773     ScopedLocalRef<jbyteArray> signature(
774             env, ecSignDigestWithPrivateKey(env, private_key,
775                                              reinterpret_cast<const char*>(digest), digest_len));
776     if (signature.get() == nullptr) {
777         CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
778         return 0;
779     }
780 
781     ScopedByteArrayRO signatureBytes(env, signature.get());
782     // Note: With ECDSA, the actual signature may be smaller than
783     // ECDSA_size().
784     size_t max_expected_size = ECDSA_size(ec_key);
785     if (signatureBytes.size() > max_expected_size) {
786         CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
787                             signatureBytes.size(), max_expected_size);
788         return 0;
789     }
790 
791     memcpy(sig, signatureBytes.get(), signatureBytes.size());
792     *sig_len = static_cast<unsigned int>(signatureBytes.size());
793     return 1;
794 }
795 
init_engine_globals()796 void init_engine_globals() {
797     g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
798                                               nullptr /* new_func */, ExDataDup, ExDataFree);
799     g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
800                                                    nullptr /* new_func */, ExDataDup, ExDataFree);
801 
802     g_rsa_method.common.is_static = 1;
803     g_rsa_method.sign_raw = RsaMethodSignRaw;
804     g_rsa_method.decrypt = RsaMethodDecrypt;
805     g_rsa_method.flags = RSA_FLAG_OPAQUE;
806 
807     g_ecdsa_method.common.is_static = 1;
808     g_ecdsa_method.sign = EcdsaMethodSign;
809     g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
810 
811     g_engine = ENGINE_new();
812     ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
813     ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
814 }
815 
816 }  // anonymous namespace
817 
818 #define THROW_SSLEXCEPTION (-2)
819 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
820 #define THROWN_EXCEPTION (-4)
821 
822 /**
823  * Initialization phase for every OpenSSL job: Loads the Error strings, the
824  * crypto algorithms and reset the OpenSSL library
825  */
NativeCrypto_clinit(JNIEnv *,jclass)826 static void NativeCrypto_clinit(JNIEnv*, jclass) {
827     CRYPTO_library_init();
828 }
829 
830 /**
831  * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
832  */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)833 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
834                                            jbyteArray d, jbyteArray p, jbyteArray q,
835                                            jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
836     CHECK_ERROR_QUEUE_ON_RETURN;
837     JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p, dmp1=%p, dmq1=%p, iqmp=%p)", n, e, d,
838               p, q, dmp1, dmq1, iqmp);
839 
840     if (e == nullptr && d == nullptr) {
841         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
842                                            "e == null && d == null");
843         JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
844         return 0;
845     }
846 
847 #if BORINGSSL_API_VERSION >= 20
848     bssl::UniquePtr<BIGNUM> nBN, eBN, dBN, pBN, qBN, dmp1BN, dmq1BN, iqmpBN;
849     nBN = arrayToBignum(env, n);
850     if (!nBN) {
851         return 0;
852     }
853     if (e != nullptr) {
854         eBN = arrayToBignum(env, e);
855         if (!eBN) {
856             return 0;
857         }
858     }
859     if (d != nullptr) {
860         dBN = arrayToBignum(env, d);
861         if (!dBN) {
862             return 0;
863         }
864     }
865     if (p != nullptr) {
866         pBN = arrayToBignum(env, p);
867         if (!pBN) {
868             return 0;
869         }
870     }
871     if (q != nullptr) {
872         qBN = arrayToBignum(env, q);
873         if (!qBN) {
874             return 0;
875         }
876     }
877     if (dmp1 != nullptr) {
878         dmp1BN = arrayToBignum(env, dmp1);
879         if (!dmp1BN) {
880             return 0;
881         }
882     }
883     if (dmq1 != nullptr) {
884         dmq1BN = arrayToBignum(env, dmq1);
885         if (!dmq1BN) {
886             return 0;
887         }
888     }
889     if (iqmp != nullptr) {
890         iqmpBN = arrayToBignum(env, iqmp);
891         if (!iqmpBN) {
892             return 0;
893         }
894     }
895 
896     // Determine what kind of key this is.
897     //
898     // TODO(davidben): The caller already knows what kind of key they expect. Ideally we would have
899     // separate APIs for the caller. However, we currently tolerate, say, an RSAPrivateCrtKeySpec
900     // where most fields are null and silently make a public key out of it. This is probably a
901     // mistake, but would need to be a breaking change.
902     bssl::UniquePtr<RSA> rsa;
903     if (!dBN) {
904         rsa.reset(RSA_new_public_key(nBN.get(), eBN.get()));
905     } else if (!eBN) {
906         rsa.reset(RSA_new_private_key_no_e(nBN.get(), dBN.get()));
907     } else if (!pBN || !qBN || !dmp1BN || !dmq1BN || !iqmpBN) {
908         rsa.reset(RSA_new_private_key_no_crt(nBN.get(), eBN.get(), dBN.get()));
909     } else {
910         rsa.reset(RSA_new_private_key(nBN.get(), eBN.get(), dBN.get(), pBN.get(), qBN.get(),
911                                       dmp1BN.get(), dmq1BN.get(), iqmpBN.get()));
912     }
913     if (rsa == nullptr) {
914         conscrypt::jniutil::throwRuntimeException(env, "Creating RSA key failed");
915         return 0;
916     }
917 #else
918     bssl::UniquePtr<RSA> rsa(RSA_new());
919     if (rsa.get() == nullptr) {
920         conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
921         return 0;
922     }
923 
924     if (!arrayToBignum(env, n, &rsa->n)) {
925         return 0;
926     }
927 
928     if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
929         return 0;
930     }
931 
932     if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
933         return 0;
934     }
935 
936     if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
937         return 0;
938     }
939 
940     if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
941         return 0;
942     }
943 
944     if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
945         return 0;
946     }
947 
948     if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
949         return 0;
950     }
951 
952     if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
953         return 0;
954     }
955 
956     if (conscrypt::trace::kWithJniTrace) {
957         if (p != nullptr && q != nullptr) {
958             int check = RSA_check_key(rsa.get());
959             JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
960         }
961     }
962 
963     if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
964         conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
965         return 0;
966     }
967 
968     /*
969      * If the private exponent is available, there is the potential to do signing
970      * operations. However, we can only do blinding if the public exponent is also
971      * available. Disable blinding if the public exponent isn't available.
972      *
973      * TODO[kroot]: We should try to recover the public exponent by trying
974      *              some common ones such 3, 17, or 65537.
975      */
976     if (rsa->d != nullptr && rsa->e == nullptr) {
977         JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
978         rsa->flags |= RSA_FLAG_NO_BLINDING;
979     }
980 #endif
981 
982     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
983     if (pkey.get() == nullptr) {
984         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
985         return 0;
986     }
987     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
988         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
989         ERR_clear_error();
990         return 0;
991     }
992     OWNERSHIP_TRANSFERRED(rsa);
993     JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
994               e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
995     return reinterpret_cast<uintptr_t>(pkey.release());
996 }
997 
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)998 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
999                                               jobject pubkeyRef, jbyteArray keyJavaBytes) {
1000     CHECK_ERROR_QUEUE_ON_RETURN;
1001     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
1002     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1003     if (group == nullptr) {
1004         return 0;
1005     }
1006     const EC_POINT* pubkey =
1007             pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
1008     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
1009 
1010     bssl::UniquePtr<BIGNUM> key(nullptr);
1011     if (keyJavaBytes != nullptr) {
1012         key = arrayToBignum(env, keyJavaBytes);
1013         if (!key) {
1014             return 0;
1015         }
1016     }
1017 
1018     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
1019     if (eckey.get() == nullptr) {
1020         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1021         return 0;
1022     }
1023 
1024     if (EC_KEY_set_group(eckey.get(), group) != 1) {
1025         JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1026                   keyJavaBytes);
1027         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1028         return 0;
1029     }
1030 
1031     if (pubkey != nullptr) {
1032         if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1033             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1034                       pubkey, keyJavaBytes);
1035             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1036             return 0;
1037         }
1038     }
1039 
1040     if (key.get() != nullptr) {
1041         if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1042             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1043                       pubkey, keyJavaBytes);
1044             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1045             return 0;
1046         }
1047         if (pubkey == nullptr) {
1048             bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1049             if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1050                 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1051                           pubkey, keyJavaBytes);
1052                 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1053                 return 0;
1054             }
1055             EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1056         }
1057     }
1058 
1059     if (!EC_KEY_check_key(eckey.get())) {
1060         JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1061                   keyJavaBytes);
1062         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1063         return 0;
1064     }
1065 
1066     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1067     if (pkey.get() == nullptr) {
1068         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1069         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1070         return 0;
1071     }
1072     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1073         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1074         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1075         ERR_clear_error();
1076         return 0;
1077     }
1078     OWNERSHIP_TRANSFERRED(eckey);
1079 
1080     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1081     return reinterpret_cast<uintptr_t>(pkey.release());
1082 }
1083 
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1084 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1085     CHECK_ERROR_QUEUE_ON_RETURN;
1086     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1087     JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1088 
1089     if (pkey == nullptr) {
1090         return -1;
1091     }
1092 
1093     int result = EVP_PKEY_id(pkey);
1094     JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1095     return result;
1096 }
1097 
1098 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1099 
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1100 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1101                               const char* debug_name) {
1102     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1103     JNI_TRACE("%s(%p)", debug_name, pkey);
1104 
1105     if (pkey == nullptr) {
1106         return nullptr;
1107     }
1108 
1109     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1110     if (buffer.get() == nullptr) {
1111         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1112         return nullptr;
1113     }
1114 
1115     if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1116         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1117         return nullptr;
1118     }
1119     // Null terminate this
1120     BIO_write(buffer.get(), "\0", 1);
1121 
1122     char* tmp;
1123     BIO_get_mem_data(buffer.get(), &tmp);
1124     jstring description = env->NewStringUTF(tmp);
1125 
1126     JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1127     return description;
1128 }
1129 
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1130 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1131     CHECK_ERROR_QUEUE_ON_RETURN;
1132     return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1133 }
1134 
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1135 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1136     CHECK_ERROR_QUEUE_ON_RETURN;
1137     return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1138 }
1139 
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1140 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1141     CHECK_ERROR_QUEUE_ON_RETURN;
1142     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1143     JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1144 
1145     if (pkey != nullptr) {
1146         EVP_PKEY_free(pkey);
1147     }
1148 }
1149 
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1150 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1151     CHECK_ERROR_QUEUE_ON_RETURN;
1152     JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1153     EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1154     if (pkey1 == nullptr) {
1155         JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1156         return 0;
1157     }
1158     EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1159     if (pkey2 == nullptr) {
1160         JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1161         return 0;
1162     }
1163     JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1164 
1165     int result = EVP_PKEY_cmp(pkey1, pkey2);
1166     JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1167     return result;
1168 }
1169 
1170 /*
1171  * static native byte[] EVP_marshal_private_key(long)
1172  */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1173 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1174     CHECK_ERROR_QUEUE_ON_RETURN;
1175     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1176     JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1177 
1178     if (pkey == nullptr) {
1179         return nullptr;
1180     }
1181 
1182     bssl::ScopedCBB cbb;
1183     if (!CBB_init(cbb.get(), 64)) {
1184         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1185         JNI_TRACE("CBB_init failed");
1186         return nullptr;
1187     }
1188 
1189     if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1190         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1191         JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1192         return nullptr;
1193     }
1194 
1195     return CBBToByteArray(env, cbb.get());
1196 }
1197 
1198 /*
1199  * static native long EVP_parse_private_key(byte[])
1200  */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1201 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1202     CHECK_ERROR_QUEUE_ON_RETURN;
1203     JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1204 
1205     ScopedByteArrayRO bytes(env, keyJavaBytes);
1206     if (bytes.get() == nullptr) {
1207         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1208         return 0;
1209     }
1210 
1211     CBS cbs;
1212     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1213     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1214     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1215     // allow parsing keys from buffers that are larger than the contained key structure
1216     // so we do the same for compatibility.
1217     if (!pkey) {
1218         conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1219         ERR_clear_error();
1220         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1221         return 0;
1222     }
1223 
1224     JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1225     return reinterpret_cast<uintptr_t>(pkey.release());
1226 }
1227 
1228 
NativeCrypto_EVP_raw_X25519_private_key(JNIEnv * env,jclass cls,jbyteArray keyJavaBytes)1229 static jbyteArray NativeCrypto_EVP_raw_X25519_private_key(
1230         JNIEnv* env, jclass cls, jbyteArray keyJavaBytes) {
1231     CHECK_ERROR_QUEUE_ON_RETURN;
1232     JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key(%p)", keyJavaBytes);
1233 
1234     jlong key_ptr = NativeCrypto_EVP_parse_private_key(env, cls, keyJavaBytes);
1235     if (key_ptr == 0) {
1236         return nullptr;
1237     }
1238     bssl::UniquePtr<EVP_PKEY> pkey(reinterpret_cast<EVP_PKEY*>(key_ptr));
1239     if (EVP_PKEY_id(pkey.get()) != EVP_PKEY_X25519) {
1240         conscrypt::jniutil::throwInvalidKeyException(env, "Invalid key type");
1241         return nullptr;
1242     }
1243 
1244     size_t key_length = X25519_PRIVATE_KEY_LEN;
1245     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(key_length)));
1246     if (byteArray.get() == nullptr) {
1247         conscrypt::jniutil::throwOutOfMemory(env, "Allocating byte[]");
1248         JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: byte array creation failed");
1249         return nullptr;
1250     }
1251 
1252     ScopedByteArrayRW bytes(env, byteArray.get());
1253     if (bytes.get() == nullptr) {
1254         conscrypt::jniutil::throwOutOfMemory(env, "Allocating scoped byte array");
1255         JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: scoped byte array failed");
1256         return nullptr;
1257     }
1258 
1259     if (EVP_PKEY_get_raw_private_key(
1260             pkey.get(), reinterpret_cast<uint8_t *>(bytes.get()), &key_length) == 0) {
1261         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_raw_private_key");
1262         return nullptr;
1263     }
1264     jbyteArray result = byteArray.release();
1265     JNI_TRACE("bytes=%p NativeCrypto_EVP_raw_X25519_private_key => %p", keyJavaBytes, result);
1266     return result;
1267 }
1268 
1269 /*
1270  * static native byte[] EVP_marshal_public_key(long)
1271  */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1272 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1273     CHECK_ERROR_QUEUE_ON_RETURN;
1274     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1275     JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1276 
1277     if (pkey == nullptr) {
1278         return nullptr;
1279     }
1280 
1281     bssl::ScopedCBB cbb;
1282     if (!CBB_init(cbb.get(), 64)) {
1283         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1284         JNI_TRACE("CBB_init failed");
1285         return nullptr;
1286     }
1287 
1288     if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1289         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1290         JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1291         return nullptr;
1292     }
1293 
1294     return CBBToByteArray(env, cbb.get());
1295 }
1296 
1297 /*
1298  * static native long EVP_parse_public_key(byte[])
1299  */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1300 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1301     CHECK_ERROR_QUEUE_ON_RETURN;
1302     JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1303 
1304     ScopedByteArrayRO bytes(env, keyJavaBytes);
1305     if (bytes.get() == nullptr) {
1306         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1307         return 0;
1308     }
1309 
1310     CBS cbs;
1311     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1312     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1313     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1314     // allow parsing keys from buffers that are larger than the contained key structure
1315     // so we do the same for compatibility.
1316     if (!pkey) {
1317         conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1318         ERR_clear_error();
1319         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1320         return 0;
1321     }
1322 
1323     JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1324     return reinterpret_cast<uintptr_t>(pkey.release());
1325 }
1326 
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1327 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1328                                                   jbyteArray modulusBytes) {
1329     CHECK_ERROR_QUEUE_ON_RETURN;
1330     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1331 
1332     ensure_engine_globals();
1333 
1334 #if BORINGSSL_API_VERSION >= 20
1335     // The PSS padding code needs access to the actual n, so set it even though we
1336     // don't set any other parts of the key
1337     bssl::UniquePtr<BIGNUM> n = arrayToBignum(env, modulusBytes);
1338     if (n == nullptr) {
1339         return 0;
1340     }
1341 
1342     // TODO(crbug.com/boringssl/602): RSA_METHOD is not the ideal abstraction to use here.
1343     bssl::UniquePtr<RSA> rsa(RSA_new_method_no_e(g_engine, n.get()));
1344     if (rsa == nullptr) {
1345         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1346         return 0;
1347     }
1348 #else
1349     bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1350     if (rsa == nullptr) {
1351         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1352         return 0;
1353     }
1354 
1355     // The PSS padding code needs access to the actual n, so set it even though we
1356     // don't set any other parts of the key
1357     if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1358         return 0;
1359     }
1360 #endif
1361 
1362     auto ex_data = new KeyExData;
1363     ex_data->private_key = env->NewGlobalRef(javaKey);
1364     RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1365 
1366     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1367     if (pkey.get() == nullptr) {
1368         JNI_TRACE("getRSAPrivateKeyWrapper failed");
1369         conscrypt::jniutil::throwRuntimeException(env,
1370                                                   "NativeCrypto_getRSAPrivateKeyWrapper failed");
1371         ERR_clear_error();
1372         return 0;
1373     }
1374 
1375     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1376         conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1377         ERR_clear_error();
1378         return 0;
1379     }
1380     OWNERSHIP_TRANSFERRED(rsa);
1381     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1382     return reinterpret_cast<uintptr_t>(pkey.release());
1383 }
1384 
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1385 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1386                                                  jobject groupRef) {
1387     CHECK_ERROR_QUEUE_ON_RETURN;
1388     EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1389     JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1390     if (group == nullptr) {
1391         return 0;
1392     }
1393 
1394     ensure_engine_globals();
1395 
1396     bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1397     if (ecKey.get() == nullptr) {
1398         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1399         return 0;
1400     }
1401 
1402     if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1403         JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1404         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1405         return 0;
1406     }
1407 
1408     auto ex_data = new KeyExData;
1409     ex_data->private_key = env->NewGlobalRef(javaKey);
1410 
1411     if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1412         env->DeleteGlobalRef(ex_data->private_key);
1413         delete ex_data;
1414         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1415         ERR_clear_error();
1416         return 0;
1417     }
1418 
1419     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1420     if (pkey.get() == nullptr) {
1421         JNI_TRACE("getECPrivateKeyWrapper failed");
1422         conscrypt::jniutil::throwRuntimeException(env,
1423                                                   "NativeCrypto_getECPrivateKeyWrapper failed");
1424         ERR_clear_error();
1425         return 0;
1426     }
1427 
1428     if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1429         conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1430         ERR_clear_error();
1431         return 0;
1432     }
1433     OWNERSHIP_TRANSFERRED(ecKey);
1434     return reinterpret_cast<uintptr_t>(pkey.release());
1435 }
1436 
1437 /*
1438  * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1439  */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1440 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1441                                               jbyteArray publicExponent) {
1442     CHECK_ERROR_QUEUE_ON_RETURN;
1443     JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1444 
1445     bssl::UniquePtr<BIGNUM> e = arrayToBignum(env, publicExponent);
1446     if (e == nullptr) {
1447         return 0;
1448     }
1449 
1450     bssl::UniquePtr<RSA> rsa(RSA_new());
1451     if (rsa.get() == nullptr) {
1452         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1453         return 0;
1454     }
1455 
1456     if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1457         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1458         return 0;
1459     }
1460 
1461     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1462     if (pkey.get() == nullptr) {
1463         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1464         return 0;
1465     }
1466 
1467     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1468         conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1469         ERR_clear_error();
1470         return 0;
1471     }
1472 
1473     OWNERSHIP_TRANSFERRED(rsa);
1474     JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1475     return reinterpret_cast<uintptr_t>(pkey.release());
1476 }
1477 
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1478 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1479     CHECK_ERROR_QUEUE_ON_RETURN;
1480     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1481     JNI_TRACE("RSA_size(%p)", pkey);
1482 
1483     if (pkey == nullptr) {
1484         return 0;
1485     }
1486 
1487     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1488     if (rsa.get() == nullptr) {
1489         conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1490         ERR_clear_error();
1491         return 0;
1492     }
1493 
1494     return static_cast<jint>(RSA_size(rsa.get()));
1495 }
1496 
1497 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1498                               int padding);
1499 
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1500 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1501                                 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1502                                 jobject pkeyRef, jint padding) {
1503     CHECK_ERROR_QUEUE_ON_RETURN;
1504     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1505     JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1506 
1507     if (pkey == nullptr) {
1508         return -1;
1509     }
1510 
1511     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1512     if (rsa.get() == nullptr) {
1513         return -1;
1514     }
1515 
1516     ScopedByteArrayRO from(env, fromJavaBytes);
1517     if (from.get() == nullptr) {
1518         return -1;
1519     }
1520 
1521     ScopedByteArrayRW to(env, toJavaBytes);
1522     if (to.get() == nullptr) {
1523         return -1;
1524     }
1525 
1526     int resultSize =
1527             operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1528                       reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1529     if (resultSize == -1) {
1530         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1531                 conscrypt::jniutil::throwBadPaddingException);
1532         JNI_TRACE("%s => threw error", caller);
1533         return -1;
1534     }
1535 
1536     JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1537               resultSize);
1538     return static_cast<jint>(resultSize);
1539 }
1540 
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1541 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1542                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1543                                              jobject pkeyRef, jint padding) {
1544     CHECK_ERROR_QUEUE_ON_RETURN;
1545     return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1546                                toJavaBytes, pkeyRef, padding);
1547 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1548 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1549                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1550                                             jobject pkeyRef, jint padding) {
1551     CHECK_ERROR_QUEUE_ON_RETURN;
1552     return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1553                                toJavaBytes, pkeyRef, padding);
1554 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1555 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1556                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1557                                             jobject pkeyRef, jint padding) {
1558     CHECK_ERROR_QUEUE_ON_RETURN;
1559     return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1560                                toJavaBytes, pkeyRef, padding);
1561 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1562 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1563                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1564                                              jobject pkeyRef, jint padding) {
1565     CHECK_ERROR_QUEUE_ON_RETURN;
1566     return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1567                                toJavaBytes, pkeyRef, padding);
1568 }
1569 
1570 /*
1571  * public static native byte[][] get_RSA_public_params(long);
1572  */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1573 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1574     CHECK_ERROR_QUEUE_ON_RETURN;
1575     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1576     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1577 
1578     if (pkey == nullptr) {
1579         return nullptr;
1580     }
1581 
1582     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1583     if (rsa.get() == nullptr) {
1584         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1585         return nullptr;
1586     }
1587 
1588     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1589     if (joa == nullptr) {
1590         return nullptr;
1591     }
1592 
1593     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1594     if (env->ExceptionCheck()) {
1595         return nullptr;
1596     }
1597     env->SetObjectArrayElement(joa, 0, n);
1598 
1599     jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1600     if (env->ExceptionCheck()) {
1601         return nullptr;
1602     }
1603     env->SetObjectArrayElement(joa, 1, e);
1604 
1605     return joa;
1606 }
1607 
1608 /*
1609  * public static native byte[][] get_RSA_private_params(long);
1610  */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1611 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1612     CHECK_ERROR_QUEUE_ON_RETURN;
1613     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1614     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1615 
1616     if (pkey == nullptr) {
1617         return nullptr;
1618     }
1619 
1620     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1621     if (rsa.get() == nullptr) {
1622         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1623         return nullptr;
1624     }
1625 
1626     jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1627     if (joa == nullptr) {
1628         return nullptr;
1629     }
1630 
1631     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1632     if (env->ExceptionCheck()) {
1633         return nullptr;
1634     }
1635     env->SetObjectArrayElement(joa, 0, n);
1636 
1637     if (RSA_get0_e(rsa.get()) != nullptr) {
1638         jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1639         if (env->ExceptionCheck()) {
1640             return nullptr;
1641         }
1642         env->SetObjectArrayElement(joa, 1, e);
1643     }
1644 
1645     if (RSA_get0_d(rsa.get()) != nullptr) {
1646         jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1647         if (env->ExceptionCheck()) {
1648             return nullptr;
1649         }
1650         env->SetObjectArrayElement(joa, 2, d);
1651     }
1652 
1653     if (RSA_get0_p(rsa.get()) != nullptr) {
1654         jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1655         if (env->ExceptionCheck()) {
1656             return nullptr;
1657         }
1658         env->SetObjectArrayElement(joa, 3, p);
1659     }
1660 
1661     if (RSA_get0_q(rsa.get()) != nullptr) {
1662         jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1663         if (env->ExceptionCheck()) {
1664             return nullptr;
1665         }
1666         env->SetObjectArrayElement(joa, 4, q);
1667     }
1668 
1669     if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1670         jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1671         if (env->ExceptionCheck()) {
1672             return nullptr;
1673         }
1674         env->SetObjectArrayElement(joa, 5, dmp1);
1675     }
1676 
1677     if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1678         jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1679         if (env->ExceptionCheck()) {
1680             return nullptr;
1681         }
1682         env->SetObjectArrayElement(joa, 6, dmq1);
1683     }
1684 
1685     if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1686         jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1687         if (env->ExceptionCheck()) {
1688             return nullptr;
1689         }
1690         env->SetObjectArrayElement(joa, 7, iqmp);
1691     }
1692 
1693     return joa;
1694 }
1695 
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1696 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1697         jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1698         jbyteArray nonceBytes, jint blockCounter) {
1699     CHECK_ERROR_QUEUE_ON_RETURN;
1700     JNI_TRACE("chacha20_encrypt_decrypt");
1701     ScopedByteArrayRO in(env, inBytes);
1702     if (in.get() == nullptr) {
1703         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1704         return;
1705     }
1706     ScopedByteArrayRW out(env, outBytes);
1707     if (out.get() == nullptr) {
1708         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1709         return;
1710     }
1711     ScopedByteArrayRO key(env, keyBytes);
1712     if (key.get() == nullptr) {
1713         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1714         return;
1715     }
1716     ScopedByteArrayRO nonce(env, nonceBytes);
1717     if (nonce.get() == nullptr) {
1718         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1719         return;
1720     }
1721 
1722     CRYPTO_chacha_20(
1723             reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1724             reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1725             length,
1726             reinterpret_cast<const unsigned char*>(key.get()),
1727             reinterpret_cast<const unsigned char*>(nonce.get()),
1728             blockCounter);
1729 }
1730 
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1731 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1732     CHECK_ERROR_QUEUE_ON_RETURN;
1733     JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1734 
1735     ScopedUtfChars curveName(env, curveNameJava);
1736     if (curveName.c_str() == nullptr) {
1737         return 0;
1738     }
1739     JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1740 
1741     int nid = OBJ_sn2nid(curveName.c_str());
1742     if (nid == NID_undef) {
1743         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1744         return 0;
1745     }
1746 
1747     EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1748     if (group == nullptr) {
1749         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1750         ERR_clear_error();
1751         return 0;
1752     }
1753 
1754     JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1755     return reinterpret_cast<uintptr_t>(group);
1756 }
1757 
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1758 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1759                                                  jbyteArray aBytes, jbyteArray bBytes,
1760                                                  jbyteArray xBytes, jbyteArray yBytes,
1761                                                  jbyteArray orderBytes, jint cofactorInt) {
1762     CHECK_ERROR_QUEUE_ON_RETURN;
1763     JNI_TRACE("EC_GROUP_new_arbitrary");
1764 
1765     if (cofactorInt < 1) {
1766         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1767                                            "cofactor < 1");
1768         return 0;
1769     }
1770 
1771     bssl::UniquePtr<BIGNUM> p = arrayToBignum(env, pBytes);
1772     if (p == nullptr) {
1773         return 0;
1774     }
1775     bssl::UniquePtr<BIGNUM> a = arrayToBignum(env, aBytes);
1776     if (a == nullptr) {
1777         return 0;
1778     }
1779     bssl::UniquePtr<BIGNUM> b = arrayToBignum(env, bBytes);
1780     if (b == nullptr) {
1781         return 0;
1782     }
1783     bssl::UniquePtr<BIGNUM> x = arrayToBignum(env, xBytes);
1784     if (x == nullptr) {
1785         return 0;
1786     }
1787     bssl::UniquePtr<BIGNUM> y = arrayToBignum(env, yBytes);
1788     if (y == nullptr) {
1789         return 0;
1790     }
1791     bssl::UniquePtr<BIGNUM> order = arrayToBignum(env, orderBytes);
1792     if (order == nullptr) {
1793         return 0;
1794     }
1795     bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1796     if (cofactor == nullptr || !BN_set_word(cofactor.get(), static_cast<uint32_t>(cofactorInt))) {
1797         return 0;
1798     }
1799 
1800     bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1801     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
1802     if (group.get() == nullptr) {
1803         JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1804         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1805         return 0;
1806     }
1807 
1808     bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1809     if (generator.get() == nullptr) {
1810         JNI_TRACE("EC_POINT_new => null");
1811         ERR_clear_error();
1812         return 0;
1813     }
1814 
1815     if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x.get(), y.get(), ctx.get())) {
1816         JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1817         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1818                                                              "EC_POINT_set_affine_coordinates_GFp");
1819         return 0;
1820     }
1821 
1822     if (!EC_GROUP_set_generator(group.get(), generator.get(), order.get(), cofactor.get())) {
1823         JNI_TRACE("EC_GROUP_set_generator => error");
1824         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1825         return 0;
1826     }
1827 
1828     JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1829     return reinterpret_cast<uintptr_t>(group.release());
1830 }
1831 
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1832 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1833     CHECK_ERROR_QUEUE_ON_RETURN;
1834     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1835     JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1836 
1837     if (group == nullptr) {
1838         JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1839         return nullptr;
1840     }
1841 
1842     int nid = EC_GROUP_get_curve_name(group);
1843     if (nid == NID_undef) {
1844         JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1845         return nullptr;
1846     }
1847 
1848     const char* shortName = OBJ_nid2sn(nid);
1849     JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1850     return env->NewStringUTF(shortName);
1851 }
1852 
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1853 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1854     CHECK_ERROR_QUEUE_ON_RETURN;
1855     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1856     JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1857     if (group == nullptr) {
1858         JNI_TRACE("EC_GROUP_get_curve => group == null");
1859         return nullptr;
1860     }
1861 
1862     bssl::UniquePtr<BIGNUM> p(BN_new());
1863     bssl::UniquePtr<BIGNUM> a(BN_new());
1864     bssl::UniquePtr<BIGNUM> b(BN_new());
1865 
1866     int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1867     if (ret != 1) {
1868         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1869         return nullptr;
1870     }
1871 
1872     jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1873     if (joa == nullptr) {
1874         return nullptr;
1875     }
1876 
1877     jbyteArray pArray = bignumToArray(env, p.get(), "p");
1878     if (env->ExceptionCheck()) {
1879         return nullptr;
1880     }
1881     env->SetObjectArrayElement(joa, 0, pArray);
1882 
1883     jbyteArray aArray = bignumToArray(env, a.get(), "a");
1884     if (env->ExceptionCheck()) {
1885         return nullptr;
1886     }
1887     env->SetObjectArrayElement(joa, 1, aArray);
1888 
1889     jbyteArray bArray = bignumToArray(env, b.get(), "b");
1890     if (env->ExceptionCheck()) {
1891         return nullptr;
1892     }
1893     env->SetObjectArrayElement(joa, 2, bArray);
1894 
1895     JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1896     return joa;
1897 }
1898 
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1899 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1900     CHECK_ERROR_QUEUE_ON_RETURN;
1901     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1902     JNI_TRACE("EC_GROUP_get_order(%p)", group);
1903     if (group == nullptr) {
1904         return nullptr;
1905     }
1906 
1907     bssl::UniquePtr<BIGNUM> order(BN_new());
1908     if (order.get() == nullptr) {
1909         JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1910         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1911         return nullptr;
1912     }
1913 
1914     if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1915         JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1916         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1917         return nullptr;
1918     }
1919 
1920     jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1921     if (env->ExceptionCheck()) {
1922         return nullptr;
1923     }
1924 
1925     JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1926     return orderArray;
1927 }
1928 
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1929 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1930     CHECK_ERROR_QUEUE_ON_RETURN;
1931     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1932     JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1933     if (group == nullptr) {
1934         return 0;
1935     }
1936 
1937     jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1938     if (degree == 0) {
1939         JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1940         conscrypt::jniutil::throwRuntimeException(env, "not supported");
1941         ERR_clear_error();
1942         return 0;
1943     }
1944 
1945     JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1946     return degree;
1947 }
1948 
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1949 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1950     CHECK_ERROR_QUEUE_ON_RETURN;
1951     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1952     JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1953     if (group == nullptr) {
1954         return nullptr;
1955     }
1956 
1957     bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1958     if (cofactor.get() == nullptr) {
1959         JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1960         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1961         return nullptr;
1962     }
1963 
1964     if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1965         JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1966         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1967         return nullptr;
1968     }
1969 
1970     jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1971     if (env->ExceptionCheck()) {
1972         return nullptr;
1973     }
1974 
1975     JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1976     return cofactorArray;
1977 }
1978 
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1979 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1980     CHECK_ERROR_QUEUE_ON_RETURN;
1981     EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1982     JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1983 
1984     if (group == nullptr) {
1985         JNI_TRACE("EC_GROUP_clear_free => group == null");
1986         conscrypt::jniutil::throwNullPointerException(env, "group == null");
1987         return;
1988     }
1989 
1990     EC_GROUP_free(group);
1991     JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1992 }
1993 
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1994 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1995     CHECK_ERROR_QUEUE_ON_RETURN;
1996     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1997     JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1998 
1999     if (group == nullptr) {
2000         JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
2001         return 0;
2002     }
2003 
2004     const EC_POINT* generator = EC_GROUP_get0_generator(group);
2005 
2006     bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
2007     if (dup.get() == nullptr) {
2008         JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
2009         conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
2010         return 0;
2011     }
2012 
2013     JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
2014     return reinterpret_cast<uintptr_t>(dup.release());
2015 }
2016 
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)2017 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
2018     CHECK_ERROR_QUEUE_ON_RETURN;
2019     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2020     JNI_TRACE("EC_POINT_new(%p)", group);
2021 
2022     if (group == nullptr) {
2023         JNI_TRACE("EC_POINT_new(%p) => group == null", group);
2024         return 0;
2025     }
2026 
2027     EC_POINT* point = EC_POINT_new(group);
2028     if (point == nullptr) {
2029         conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
2030         return 0;
2031     }
2032 
2033     return reinterpret_cast<uintptr_t>(point);
2034 }
2035 
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)2036 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
2037     CHECK_ERROR_QUEUE_ON_RETURN;
2038     EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
2039     JNI_TRACE("EC_POINT_clear_free(%p)", group);
2040 
2041     if (group == nullptr) {
2042         JNI_TRACE("EC_POINT_clear_free => group == null");
2043         conscrypt::jniutil::throwNullPointerException(env, "group == null");
2044         return;
2045     }
2046 
2047     EC_POINT_free(group);
2048     JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
2049 }
2050 
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)2051 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
2052                                                          jobject pointRef, jbyteArray xjavaBytes,
2053                                                          jbyteArray yjavaBytes) {
2054     CHECK_ERROR_QUEUE_ON_RETURN;
2055     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
2056               yjavaBytes);
2057     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2058     if (group == nullptr) {
2059         return;
2060     }
2061     EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2062     if (point == nullptr) {
2063         return;
2064     }
2065     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
2066               yjavaBytes);
2067 
2068     bssl::UniquePtr<BIGNUM> x = arrayToBignum(env, xjavaBytes);
2069     if (x == nullptr) {
2070         return;
2071     }
2072 
2073     bssl::UniquePtr<BIGNUM> y = arrayToBignum(env, yjavaBytes);
2074     if (y == nullptr) {
2075         return;
2076     }
2077 
2078     int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2079     if (ret != 1) {
2080         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2081                                                              "EC_POINT_set_affine_coordinates");
2082         return;
2083     }
2084 
2085     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2086               yjavaBytes, ret);
2087 }
2088 
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2089 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2090                                                                  jobject groupRef,
2091                                                                  jobject pointRef) {
2092     CHECK_ERROR_QUEUE_ON_RETURN;
2093     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2094     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2095     if (group == nullptr) {
2096         return nullptr;
2097     }
2098     const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2099     if (point == nullptr) {
2100         return nullptr;
2101     }
2102     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2103 
2104     bssl::UniquePtr<BIGNUM> x(BN_new());
2105     bssl::UniquePtr<BIGNUM> y(BN_new());
2106 
2107     int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2108     if (ret != 1) {
2109         JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2110         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2111                                                              "EC_POINT_get_affine_coordinates");
2112         return nullptr;
2113     }
2114 
2115     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2116     if (joa == nullptr) {
2117         return nullptr;
2118     }
2119 
2120     jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2121     if (env->ExceptionCheck()) {
2122         return nullptr;
2123     }
2124     env->SetObjectArrayElement(joa, 0, xBytes);
2125 
2126     jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2127     if (env->ExceptionCheck()) {
2128         return nullptr;
2129     }
2130     env->SetObjectArrayElement(joa, 1, yBytes);
2131 
2132     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2133     return joa;
2134 }
2135 
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2136 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2137     CHECK_ERROR_QUEUE_ON_RETURN;
2138     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2139     JNI_TRACE("EC_KEY_generate_key(%p)", group);
2140     if (group == nullptr) {
2141         return 0;
2142     }
2143 
2144     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2145     if (eckey.get() == nullptr) {
2146         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2147         conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2148         return 0;
2149     }
2150 
2151     if (EC_KEY_set_group(eckey.get(), group) != 1) {
2152         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2153         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2154         return 0;
2155     }
2156 
2157     if (EC_KEY_generate_key(eckey.get()) != 1) {
2158         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2159         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2160         return 0;
2161     }
2162 
2163     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2164     if (pkey.get() == nullptr) {
2165         JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2166         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2167         return 0;
2168     }
2169     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2170         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2171         ERR_clear_error();
2172         return 0;
2173     }
2174     OWNERSHIP_TRANSFERRED(eckey);
2175 
2176     JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2177     return reinterpret_cast<uintptr_t>(pkey.release());
2178 }
2179 
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2180 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2181     CHECK_ERROR_QUEUE_ON_RETURN;
2182     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2183     JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2184 
2185     if (pkey == nullptr) {
2186         JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2187         return 0;
2188     }
2189 
2190     if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2191         conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2192         JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2193         return 0;
2194     }
2195 
2196     EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2197     JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2198     return reinterpret_cast<uintptr_t>(group);
2199 }
2200 
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2201 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2202     CHECK_ERROR_QUEUE_ON_RETURN;
2203     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2204     JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2205 
2206     if (pkey == nullptr) {
2207         JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2208         return nullptr;
2209     }
2210 
2211     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2212     if (eckey.get() == nullptr) {
2213         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2214         return nullptr;
2215     }
2216 
2217     const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2218 
2219     jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2220     if (env->ExceptionCheck()) {
2221         JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2222         return nullptr;
2223     }
2224 
2225     JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2226     return privBytes;
2227 }
2228 
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2229 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2230     CHECK_ERROR_QUEUE_ON_RETURN;
2231     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2232     JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2233 
2234     if (pkey == nullptr) {
2235         JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2236         return 0;
2237     }
2238 
2239     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2240     if (eckey.get() == nullptr) {
2241         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2242         return 0;
2243     }
2244 
2245     bssl::UniquePtr<EC_POINT> dup(
2246             EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2247     if (dup.get() == nullptr) {
2248         JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2249         conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2250         ERR_clear_error();
2251         return 0;
2252     }
2253 
2254     JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2255     return reinterpret_cast<uintptr_t>(dup.release());
2256 }
2257 
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2258 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2259     CHECK_ERROR_QUEUE_ON_RETURN;
2260     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2261     JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2262     if (group == nullptr) {
2263         env->ExceptionClear();
2264         conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2265         JNI_TRACE("group=%p EC_KEY_marshal_curve_name => Invalid group pointer", group);
2266         return nullptr;
2267     }
2268 
2269     bssl::ScopedCBB cbb;
2270     if (!CBB_init(cbb.get(), 64)) {
2271         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2272         JNI_TRACE("CBB_init failed");
2273         return nullptr;
2274     }
2275 
2276     if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2277         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2278         ERR_clear_error();
2279         JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2280         return nullptr;
2281     }
2282 
2283     return CBBToByteArray(env, cbb.get());
2284 }
2285 
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2286 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2287     CHECK_ERROR_QUEUE_ON_RETURN;
2288     JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2289 
2290     ScopedByteArrayRO bytes(env, curveNameBytes);
2291     if (bytes.get() == nullptr) {
2292         env->ExceptionClear();
2293         conscrypt::jniutil::throwIOException(env, "Null EC curve name");
2294         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => curveNameBytes == null ", curveNameBytes);
2295         return 0;
2296     }
2297 
2298     CBS cbs;
2299     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2300     bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2301     if (!group || CBS_len(&cbs) != 0) {
2302         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2303         ERR_clear_error();
2304         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2305         return 0;
2306     }
2307 
2308     JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2309     return reinterpret_cast<uintptr_t>(group.release());
2310 }
2311 
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2312 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2313                                           jobject pubkeyRef, jobject privkeyRef) {
2314     CHECK_ERROR_QUEUE_ON_RETURN;
2315     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2316     EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2317     if (pubPkey == nullptr) {
2318         JNI_TRACE("ECDH_compute_key => pubPkey == null");
2319         return -1;
2320     }
2321     EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2322     if (privPkey == nullptr) {
2323         JNI_TRACE("ECDH_compute_key => privPkey == null");
2324         return -1;
2325     }
2326     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2327 
2328     ScopedByteArrayRW out(env, outArray);
2329     if (out.get() == nullptr) {
2330         JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2331                   pubPkey, privPkey);
2332         return -1;
2333     }
2334 
2335     if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2336         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2337                                            nullptr);
2338         return -1;
2339     }
2340 
2341     if (pubPkey == nullptr) {
2342         JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2343         conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2344         return -1;
2345     }
2346 
2347     bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2348     if (pubkey.get() == nullptr) {
2349         JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2350         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2351                                                       conscrypt::jniutil::throwInvalidKeyException);
2352         return -1;
2353     }
2354 
2355     const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2356     if (pubkeyPoint == nullptr) {
2357         JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2358         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2359                                                       conscrypt::jniutil::throwInvalidKeyException);
2360         return -1;
2361     }
2362 
2363     if (privPkey == nullptr) {
2364         JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2365         conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2366         return -1;
2367     }
2368 
2369     bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2370     if (privkey.get() == nullptr) {
2371         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2372                                                       conscrypt::jniutil::throwInvalidKeyException);
2373         return -1;
2374     }
2375 
2376     std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2377     int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2378                                         privkey.get(), nullptr /* No KDF */);
2379     if (outputLength == -1) {
2380         JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2381         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2382                                                       conscrypt::jniutil::throwInvalidKeyException);
2383         return -1;
2384     }
2385 
2386     JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2387     return outputLength;
2388 }
2389 
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2390 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2391     CHECK_ERROR_QUEUE_ON_RETURN;
2392     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2393     JNI_TRACE("ECDSA_size(%p)", pkey);
2394 
2395     if (pkey == nullptr) {
2396         return 0;
2397     }
2398 
2399     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2400     if (ec_key.get() == nullptr) {
2401         conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2402         ERR_clear_error();
2403         return 0;
2404     }
2405 
2406     size_t size = ECDSA_size(ec_key.get());
2407 
2408     JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2409     return static_cast<jint>(size);
2410 }
2411 
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2412 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2413                                     jobject pkeyRef) {
2414     CHECK_ERROR_QUEUE_ON_RETURN;
2415     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2416     JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2417 
2418     if (pkey == nullptr) {
2419         return -1;
2420     }
2421 
2422     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2423     if (ec_key.get() == nullptr) {
2424         return -1;
2425     }
2426 
2427     ScopedByteArrayRO data_array(env, data);
2428     if (data_array.get() == nullptr) {
2429         return -1;
2430     }
2431 
2432     ScopedByteArrayRW sig_array(env, sig);
2433     if (sig_array.get() == nullptr) {
2434         return -1;
2435     }
2436 
2437     unsigned int sig_size;
2438     int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2439                             data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2440                             &sig_size, ec_key.get());
2441     if (result == 0) {
2442         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2443         JNI_TRACE("ECDSA_sign => threw error");
2444         return -1;
2445     }
2446 
2447     JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2448     return static_cast<jint>(sig_size);
2449 }
2450 
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2451 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2452                                       jobject pkeyRef) {
2453     CHECK_ERROR_QUEUE_ON_RETURN;
2454     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2455     JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2456 
2457     if (pkey == nullptr) {
2458         return -1;
2459     }
2460 
2461     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2462     if (ec_key.get() == nullptr) {
2463         return -1;
2464     }
2465 
2466     ScopedByteArrayRO data_array(env, data);
2467     if (data_array.get() == nullptr) {
2468         return -1;
2469     }
2470 
2471     ScopedByteArrayRO sig_array(env, sig);
2472     if (sig_array.get() == nullptr) {
2473         return -1;
2474     }
2475 
2476     int result =
2477             ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2478                          data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2479                          sig_array.size(), ec_key.get());
2480 
2481     if (result == 0) {
2482         // NOLINTNEXTLINE(runtime/int)
2483         unsigned long error = ERR_peek_last_error();
2484         if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2485             (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2486             // This error just means the signature didn't verify, so clear the error and return
2487             // a failed verification
2488             ERR_clear_error();
2489             JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2490             return 0;
2491         }
2492         if (error != 0) {
2493             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2494             JNI_TRACE("ECDSA_verify => threw error");
2495             return -1;
2496         }
2497         return 0;
2498     }
2499 
2500     JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2501     return static_cast<jint>(result);
2502 }
2503 
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2504 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2505                                           jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2506     CHECK_ERROR_QUEUE_ON_RETURN;
2507     JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2508 
2509     ScopedByteArrayRW out(env, outArray);
2510     if (out.get() == nullptr) {
2511         JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2512         return JNI_FALSE;
2513     }
2514 
2515     ScopedByteArrayRO privkey(env, privkeyArray);
2516     if (privkey.get() == nullptr) {
2517         JNI_TRACE("X25519(%p) => privkey == null", outArray);
2518         return JNI_FALSE;
2519     }
2520 
2521     ScopedByteArrayRO pubkey(env, pubkeyArray);
2522     if (pubkey.get() == nullptr) {
2523         JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2524         return JNI_FALSE;
2525     }
2526 
2527     if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2528                reinterpret_cast<const uint8_t*>(privkey.get()),
2529                reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2530         JNI_TRACE("X25519(%p) => failure", outArray);
2531         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2532                                                       conscrypt::jniutil::throwInvalidKeyException);
2533         return JNI_FALSE;
2534     }
2535 
2536     JNI_TRACE("X25519(%p) => success", outArray);
2537     return JNI_TRUE;
2538 }
2539 
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2540 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2541     CHECK_ERROR_QUEUE_ON_RETURN;
2542     JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2543 
2544     ScopedByteArrayRW outPublic(env, outPublicArray);
2545     if (outPublic.get() == nullptr) {
2546         JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2547         return;
2548     }
2549 
2550     ScopedByteArrayRW outPrivate(env, outPrivateArray);
2551     if (outPrivate.get() == nullptr) {
2552         JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2553         return;
2554     }
2555 
2556     if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2557         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2558         return;
2559     }
2560 
2561     X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2562     JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2563 }
2564 
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2565 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2566     CHECK_ERROR_QUEUE_ON_RETURN;
2567     JNI_TRACE_MD("EVP_MD_CTX_create()");
2568 
2569     bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2570     if (ctx.get() == nullptr) {
2571         conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2572         return 0;
2573     }
2574 
2575     JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2576     return reinterpret_cast<uintptr_t>(ctx.release());
2577 }
2578 
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2579 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2580     CHECK_ERROR_QUEUE_ON_RETURN;
2581     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2582     JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2583 
2584     if (ctx != nullptr) {
2585         EVP_MD_CTX_cleanup(ctx);
2586     }
2587 }
2588 
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2589 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2590     CHECK_ERROR_QUEUE_ON_RETURN;
2591     EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2592     JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2593 
2594     if (ctx != nullptr) {
2595         EVP_MD_CTX_destroy(ctx);
2596     }
2597 }
2598 
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2599 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2600                                             jobject srcCtxRef) {
2601     CHECK_ERROR_QUEUE_ON_RETURN;
2602     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2603     EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2604     if (dst_ctx == nullptr) {
2605         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2606         return 0;
2607     }
2608     const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2609     if (src_ctx == nullptr) {
2610         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2611         return 0;
2612     }
2613     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2614 
2615     int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2616     if (result == 0) {
2617         conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2618         ERR_clear_error();
2619     }
2620 
2621     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2622     return result;
2623 }
2624 
2625 /*
2626  * public static native int EVP_DigestFinal_ex(long, byte[], int)
2627  */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2628 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2629                                             jint offset) {
2630     CHECK_ERROR_QUEUE_ON_RETURN;
2631     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2632     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2633 
2634     if (ctx == nullptr) {
2635         JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2636         return -1;
2637     } else if (hash == nullptr) {
2638         conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2639         return -1;
2640     }
2641 
2642     ScopedByteArrayRW hashBytes(env, hash);
2643     if (hashBytes.get() == nullptr) {
2644         return -1;
2645     }
2646     unsigned int bytesWritten = static_cast<unsigned int>(-1);
2647     int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2648                                 &bytesWritten);
2649     if (ok == 0) {
2650         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2651         return -1;
2652     }
2653 
2654     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2655     return static_cast<jint>(bytesWritten);
2656 }
2657 
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2658 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2659                                            jlong evpMdRef) {
2660     CHECK_ERROR_QUEUE_ON_RETURN;
2661     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2662     const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2663     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2664 
2665     if (ctx == nullptr) {
2666         JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2667         return 0;
2668     } else if (evp_md == nullptr) {
2669         conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2670         return 0;
2671     }
2672 
2673     int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2674     if (ok == 0) {
2675         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2676         JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2677         return 0;
2678     }
2679     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2680     return ok;
2681 }
2682 
2683 /*
2684  * public static native int EVP_get_digestbyname(java.lang.String)
2685  */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2686 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2687     CHECK_ERROR_QUEUE_ON_RETURN;
2688     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2689 
2690     if (algorithm == nullptr) {
2691         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2692         return -1;
2693     }
2694 
2695     ScopedUtfChars algorithmChars(env, algorithm);
2696     if (algorithmChars.c_str() == nullptr) {
2697         return 0;
2698     }
2699     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2700 
2701     const char* alg = algorithmChars.c_str();
2702     const EVP_MD* md;
2703 
2704     if (strcasecmp(alg, "md4") == 0) {
2705         md = EVP_md4();
2706     } else if (strcasecmp(alg, "md5") == 0) {
2707         md = EVP_md5();
2708     } else if (strcasecmp(alg, "sha1") == 0) {
2709         md = EVP_sha1();
2710     } else if (strcasecmp(alg, "sha224") == 0) {
2711         md = EVP_sha224();
2712     } else if (strcasecmp(alg, "sha256") == 0) {
2713         md = EVP_sha256();
2714     } else if (strcasecmp(alg, "sha384") == 0) {
2715         md = EVP_sha384();
2716     } else if (strcasecmp(alg, "sha512") == 0) {
2717         md = EVP_sha512();
2718     } else {
2719         JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2720         conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2721         return 0;
2722     }
2723 
2724     return reinterpret_cast<uintptr_t>(md);
2725 }
2726 
2727 /*
2728  * public static native int EVP_MD_size(long)
2729  */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2730 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2731     CHECK_ERROR_QUEUE_ON_RETURN;
2732     EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2733     JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2734 
2735     if (evp_md == nullptr) {
2736         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2737         return -1;
2738     }
2739 
2740     jint result = static_cast<jint>(EVP_MD_size(evp_md));
2741     JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2742     return result;
2743 }
2744 
evpDigestSignVerifyInit(JNIEnv * env,int (* init_func)(EVP_MD_CTX *,EVP_PKEY_CTX **,const EVP_MD *,ENGINE *,EVP_PKEY *),const char * jniName,jobject evpMdCtxRef,jlong evpMdRef,jobject pkeyRef)2745 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2746                                      int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2747                                                       ENGINE*, EVP_PKEY*),
2748                                      const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2749                                      jobject pkeyRef) {
2750     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2751     if (mdCtx == nullptr) {
2752         JNI_TRACE("%s => mdCtx == null", jniName);
2753         return 0;
2754     }
2755     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2756     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2757     if (pkey == nullptr) {
2758         JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2759         return 0;
2760     }
2761     JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2762 
2763     if (md == nullptr) {
2764         JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2765         conscrypt::jniutil::throwNullPointerException(env, "md == null");
2766         return 0;
2767     }
2768 
2769     EVP_PKEY_CTX* pctx = nullptr;
2770     if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2771         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2772         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2773         return 0;
2774     }
2775 
2776     JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2777     return reinterpret_cast<jlong>(pctx);
2778 }
2779 
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2780 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2781                                              const jlong evpMdRef, jobject pkeyRef) {
2782     CHECK_ERROR_QUEUE_ON_RETURN;
2783     return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2784                                    evpMdRef, pkeyRef);
2785 }
2786 
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2787 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2788                                                const jlong evpMdRef, jobject pkeyRef) {
2789     CHECK_ERROR_QUEUE_ON_RETURN;
2790     return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2791                                    evpMdRef, pkeyRef);
2792 }
2793 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2794 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2795                       const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2796     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2797     const void* p = reinterpret_cast<const void*>(inPtr);
2798     JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2799 
2800     if (mdCtx == nullptr) {
2801         return;
2802     }
2803 
2804     if (p == nullptr) {
2805         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2806         return;
2807     }
2808 
2809     if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2810         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2811         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2812         return;
2813     }
2814 
2815     JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2816 }
2817 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2818 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2819                       jint inLength, const char* jniName,
2820                       int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2821     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2822     JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2823 
2824     if (mdCtx == nullptr) {
2825         return;
2826     }
2827 
2828     if (inJavaBytes == nullptr) {
2829         conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2830         return;
2831     }
2832 
2833     size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2834     if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2835         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2836                                            "inBytes");
2837         return;
2838     }
2839     if (inLength == 0) {
2840         return;
2841     }
2842     jint in_offset = inOffset;
2843     jint in_size = inLength;
2844 
2845     int update_func_result = -1;
2846     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2847         // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2848         // avoid copying the whole array.
2849         if (in_size <= 1024) {
2850             // For small chunk, it's more efficient to use a bit more space on the stack instead of
2851             // allocating a new buffer.
2852             jbyte buf[1024];
2853             env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2854             update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2855                                              static_cast<size_t>(in_size));
2856         } else {
2857             // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2858             // through the buffer, stopping as soon as update_func fails.
2859             jint remaining = in_size;
2860             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2861             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2862             if (buf.get() == nullptr) {
2863                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2864                 return;
2865             }
2866             while (remaining > 0) {
2867                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2868                 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2869                 update_func_result =
2870                         update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2871                                     static_cast<size_t>(chunk_size));
2872                 if (!update_func_result) {
2873                     // update_func failed. This will be handled later in this method.
2874                     break;
2875                 }
2876                 in_offset += chunk_size;
2877                 remaining -= chunk_size;
2878             }
2879         }
2880     } else {
2881         // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2882         // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2883         // use GetByteArrayElements or another approach.
2884         jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2885         if (array_elements == nullptr) {
2886             conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2887             return;
2888         }
2889         const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2890         update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2891         env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2892     }
2893 
2894     if (!update_func_result) {
2895         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2896         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2897         return;
2898     }
2899 
2900     JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2901 }
2902 
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2903 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2904                                                 jlong inPtr, jint inLength) {
2905     CHECK_ERROR_QUEUE_ON_RETURN;
2906     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2907 }
2908 
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2909 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2910                                           jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2911     CHECK_ERROR_QUEUE_ON_RETURN;
2912     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2913               EVP_DigestUpdate);
2914 }
2915 
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2916 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2917                                               jbyteArray inJavaBytes, jint inOffset,
2918                                               jint inLength) {
2919     CHECK_ERROR_QUEUE_ON_RETURN;
2920     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2921             EVP_DigestSignUpdate);
2922 }
2923 
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2924 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2925         jlong inPtr, jint inLength) {
2926     CHECK_ERROR_QUEUE_ON_RETURN;
2927     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2928             EVP_DigestSignUpdate);
2929 }
2930 
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2931 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2932                                                 jbyteArray inJavaBytes, jint inOffset,
2933                                                 jint inLength) {
2934     CHECK_ERROR_QUEUE_ON_RETURN;
2935     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2936               EVP_DigestVerifyUpdate);
2937 }
2938 
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2939 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2940                                                       jlong inPtr, jint inLength) {
2941     CHECK_ERROR_QUEUE_ON_RETURN;
2942     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2943               EVP_DigestVerifyUpdate);
2944 }
2945 
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2946 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2947     CHECK_ERROR_QUEUE_ON_RETURN;
2948     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2949     JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2950 
2951     if (mdCtx == nullptr) {
2952         return nullptr;
2953     }
2954 
2955     size_t maxLen;
2956     if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2957         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2958         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2959         return nullptr;
2960     }
2961 
2962     std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2963     if (buffer.get() == nullptr) {
2964         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2965         return nullptr;
2966     }
2967     size_t actualLen(maxLen);
2968     if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2969         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2970         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2971         return nullptr;
2972     }
2973     if (actualLen > maxLen) {
2974         JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2975                   maxLen);
2976         conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2977         return nullptr;
2978     }
2979 
2980     ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2981     if (sigJavaBytes.get() == nullptr) {
2982         conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2983         return nullptr;
2984     }
2985     env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2986                             reinterpret_cast<jbyte*>(buffer.get()));
2987 
2988     JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2989     return sigJavaBytes.release();
2990 }
2991 
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2992 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2993                                                    jbyteArray signature, jint offset, jint len) {
2994     CHECK_ERROR_QUEUE_ON_RETURN;
2995     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2996     JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2997 
2998     if (mdCtx == nullptr) {
2999         return 0;
3000     }
3001 
3002     ScopedByteArrayRO sigBytes(env, signature);
3003     if (sigBytes.get() == nullptr) {
3004         return 0;
3005     }
3006 
3007     if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
3008         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3009                                            "signature");
3010         return 0;
3011     }
3012 
3013     const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3014     int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
3015     jboolean result;
3016     if (err == 1) {
3017         // Signature verified
3018         result = 1;
3019     } else if (err == 0) {
3020         // Signature did not verify
3021         result = 0;
3022     } else {
3023         // Error while verifying signature
3024         JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
3025         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
3026         return 0;
3027     }
3028 
3029     // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3030     // Clear the error queue to prevent its state from affecting future operations.
3031     ERR_clear_error();
3032 
3033     JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
3034     return result;
3035 }
3036 
evpPkeyEncryptDecrypt(JNIEnv * env,int (* encrypt_decrypt_func)(EVP_PKEY_CTX *,uint8_t *,size_t *,const uint8_t *,size_t),const char * jniName,jobject evpPkeyCtxRef,jbyteArray outJavaBytes,jint outOffset,jbyteArray inJavaBytes,jint inOffset,jint inLength)3037 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
3038                                   int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
3039                                                               const uint8_t*, size_t),
3040                                   const char* jniName, jobject evpPkeyCtxRef,
3041                                   jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
3042                                   jint inOffset, jint inLength) {
3043     EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
3044     JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
3045                  inJavaBytes, inOffset, inLength);
3046 
3047     if (pkeyCtx == nullptr) {
3048         return 0;
3049     }
3050 
3051     ScopedByteArrayRW outBytes(env, outJavaBytes);
3052     if (outBytes.get() == nullptr) {
3053         return 0;
3054     }
3055 
3056     ScopedByteArrayRO inBytes(env, inJavaBytes);
3057     if (inBytes.get() == nullptr) {
3058         return 0;
3059     }
3060 
3061     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3062         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3063                                            "outBytes");
3064         return 0;
3065     }
3066 
3067     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3068         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3069                                            "inBytes");
3070         return 0;
3071     }
3072 
3073     uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3074     const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3075     size_t outLength = outBytes.size() - outOffset;
3076     if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3077                               static_cast<size_t>(inLength))) {
3078         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3079         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3080                 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3081         return 0;
3082     }
3083 
3084     JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3085               outOffset, inJavaBytes, inOffset, inLength, outLength);
3086     return static_cast<jint>(outLength);
3087 }
3088 
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3089 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3090                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3091                                           jint inOffset, jint inLength) {
3092     CHECK_ERROR_QUEUE_ON_RETURN;
3093     return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3094                                  outOffset, inBytes, inOffset, inLength);
3095 }
3096 
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3097 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3098                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3099                                           jint inOffset, jint inLength) {
3100     CHECK_ERROR_QUEUE_ON_RETURN;
3101     return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3102                                  outOffset, inBytes, inOffset, inLength);
3103 }
3104 
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3105 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3106                                       int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3107     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3108     JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3109     if (pkey == nullptr) {
3110         JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3111         return 0;
3112     }
3113 
3114     bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3115     if (pkeyCtx.get() == nullptr) {
3116         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3117         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3118                 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3119         return 0;
3120     }
3121 
3122     if (!real_func(pkeyCtx.get())) {
3123         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3124         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3125                 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3126         return 0;
3127     }
3128 
3129     JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3130     return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3131 }
3132 
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3133 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3134     CHECK_ERROR_QUEUE_ON_RETURN;
3135     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3136 }
3137 
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3138 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3139     CHECK_ERROR_QUEUE_ON_RETURN;
3140     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3141 }
3142 
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3143 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3144     CHECK_ERROR_QUEUE_ON_RETURN;
3145     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3146     JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3147 
3148     if (pkeyCtx != nullptr) {
3149         EVP_PKEY_CTX_free(pkeyCtx);
3150     }
3151 }
3152 
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3153 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3154     CHECK_ERROR_QUEUE_ON_RETURN;
3155     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3156     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3157     if (pkeyCtx == nullptr) {
3158         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3159         return;
3160     }
3161 
3162     int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3163     if (result <= 0) {
3164         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3165         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3166                 env, "EVP_PKEY_CTX_set_rsa_padding",
3167                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3168         return;
3169     }
3170 
3171     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3172 }
3173 
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3174 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3175                                                           jint len) {
3176     CHECK_ERROR_QUEUE_ON_RETURN;
3177     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3178     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3179     if (pkeyCtx == nullptr) {
3180         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3181         return;
3182     }
3183 
3184     int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3185     if (result <= 0) {
3186         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3187         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3188                 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3189                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3190         return;
3191     }
3192 
3193     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3194 }
3195 
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3196 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3197                                int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3198     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3199     EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3200     JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3201     if (pkeyCtx == nullptr) {
3202         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3203         return;
3204     }
3205     if (md == nullptr) {
3206         conscrypt::jniutil::throwNullPointerException(env, "md == null");
3207         return;
3208     }
3209 
3210     int result = ctrl_func(pkeyCtx, md);
3211     if (result <= 0) {
3212         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3213         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3214                 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3215         return;
3216     }
3217 
3218     JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3219 }
3220 
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3221 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3222                                                       jlong mdRef) {
3223     CHECK_ERROR_QUEUE_ON_RETURN;
3224     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3225                        EVP_PKEY_CTX_set_rsa_mgf1_md);
3226 }
3227 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3228 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3229                                                       jlong mdRef) {
3230     CHECK_ERROR_QUEUE_ON_RETURN;
3231     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3232                        EVP_PKEY_CTX_set_rsa_oaep_md);
3233 }
3234 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3235 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3236                                                          jbyteArray labelJava) {
3237     CHECK_ERROR_QUEUE_ON_RETURN;
3238     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3239     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3240     if (pkeyCtx == nullptr) {
3241         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3242         return;
3243     }
3244 
3245     ScopedByteArrayRO labelBytes(env, labelJava);
3246     if (labelBytes.get() == nullptr) {
3247         return;
3248     }
3249 
3250     bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3251     memcpy(label.get(), labelBytes.get(), labelBytes.size());
3252 
3253     int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3254     if (result <= 0) {
3255         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3256         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3257                 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3258                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3259         return;
3260     }
3261     OWNERSHIP_TRANSFERRED(label);
3262 
3263     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3264 }
3265 
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3266 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3267     CHECK_ERROR_QUEUE_ON_RETURN;
3268     JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3269 
3270     if (algorithm == nullptr) {
3271         conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3272         JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3273         return -1;
3274     }
3275 
3276     ScopedUtfChars scoped_alg(env, algorithm);
3277     const char* alg = scoped_alg.c_str();
3278     const EVP_CIPHER* cipher;
3279 
3280     if (strcasecmp(alg, "rc4") == 0) {
3281         cipher = EVP_rc4();
3282     } else if (strcasecmp(alg, "des-cbc") == 0) {
3283         cipher = EVP_des_cbc();
3284     } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3285         cipher = EVP_des_ede_cbc();
3286     } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3287         cipher = EVP_des_ede3_cbc();
3288     } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3289         cipher = EVP_aes_128_ecb();
3290     } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3291         cipher = EVP_aes_128_cbc();
3292     } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3293         cipher = EVP_aes_128_ctr();
3294     } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3295         cipher = EVP_aes_128_gcm();
3296     } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3297         cipher = EVP_aes_192_ecb();
3298     } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3299         cipher = EVP_aes_192_cbc();
3300     } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3301         cipher = EVP_aes_192_ctr();
3302     } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3303         cipher = EVP_aes_192_gcm();
3304     } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3305         cipher = EVP_aes_256_ecb();
3306     } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3307         cipher = EVP_aes_256_cbc();
3308     } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3309         cipher = EVP_aes_256_ctr();
3310     } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3311         cipher = EVP_aes_256_gcm();
3312     } else {
3313         JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3314         return 0;
3315     }
3316 
3317     return reinterpret_cast<uintptr_t>(cipher);
3318 }
3319 
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3320 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3321                                            jbyteArray keyArray, jbyteArray ivArray,
3322                                            jboolean encrypting) {
3323     CHECK_ERROR_QUEUE_ON_RETURN;
3324     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3325     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3326     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3327               encrypting ? 1 : 0);
3328 
3329     if (ctx == nullptr) {
3330         JNI_TRACE("EVP_CipherUpdate => ctx == null");
3331         return;
3332     }
3333 
3334     // The key can be null if we need to set extra parameters.
3335     std::unique_ptr<unsigned char[]> keyPtr;
3336     if (keyArray != nullptr) {
3337         ScopedByteArrayRO keyBytes(env, keyArray);
3338         if (keyBytes.get() == nullptr) {
3339             return;
3340         }
3341 
3342         keyPtr.reset(new unsigned char[keyBytes.size()]);
3343         memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3344     }
3345 
3346     // The IV can be null if we're using ECB.
3347     std::unique_ptr<unsigned char[]> ivPtr;
3348     if (ivArray != nullptr) {
3349         ScopedByteArrayRO ivBytes(env, ivArray);
3350         if (ivBytes.get() == nullptr) {
3351             return;
3352         }
3353 
3354         ivPtr.reset(new unsigned char[ivBytes.size()]);
3355         memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3356     }
3357 
3358     if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3359                            encrypting ? 1 : 0)) {
3360         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3361         JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3362         return;
3363     }
3364 
3365     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3366               encrypting ? 1 : 0);
3367 }
3368 
3369 /*
3370  *  public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3371  *          int inOffset, int inLength);
3372  */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3373 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3374                                           jint outOffset, jbyteArray inArray, jint inOffset,
3375                                           jint inLength) {
3376     CHECK_ERROR_QUEUE_ON_RETURN;
3377     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3378     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3379 
3380     if (ctx == nullptr) {
3381         JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3382         return 0;
3383     }
3384 
3385     ScopedByteArrayRO inBytes(env, inArray);
3386     if (inBytes.get() == nullptr) {
3387         return 0;
3388     }
3389     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3390         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3391                                            "inBytes");
3392         return 0;
3393     }
3394 
3395     ScopedByteArrayRW outBytes(env, outArray);
3396     if (outBytes.get() == nullptr) {
3397         return 0;
3398     }
3399     if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3400         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3401                                            "outBytes");
3402         return 0;
3403     }
3404 
3405     JNI_TRACE(
3406             "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3407             "out.length=%zd outOffset=%d",
3408             ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3409             outOffset);
3410 
3411     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3412     const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3413 
3414     int outl;
3415     if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3416         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3417         JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3418         return 0;
3419     }
3420 
3421     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3422               inOffset, outl);
3423     return outl;
3424 }
3425 
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3426 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3427                                             jbyteArray outArray, jint outOffset) {
3428     CHECK_ERROR_QUEUE_ON_RETURN;
3429     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3430     JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3431 
3432     if (ctx == nullptr) {
3433         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3434         return 0;
3435     }
3436 
3437     ScopedByteArrayRW outBytes(env, outArray);
3438     if (outBytes.get() == nullptr) {
3439         return 0;
3440     }
3441 
3442     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3443 
3444     int outl;
3445     if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3446         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3447                 conscrypt::jniutil::throwBadPaddingException);
3448         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3449         return 0;
3450     }
3451 
3452     JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3453     return outl;
3454 }
3455 
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3456 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3457     CHECK_ERROR_QUEUE_ON_RETURN;
3458     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3459     JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3460 
3461     if (evpCipher == nullptr) {
3462         conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3463         JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3464         return 0;
3465     }
3466 
3467     jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3468     JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3469     return ivLength;
3470 }
3471 
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3472 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3473     CHECK_ERROR_QUEUE_ON_RETURN;
3474     JNI_TRACE("EVP_CIPHER_CTX_new()");
3475 
3476     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3477     if (ctx.get() == nullptr) {
3478         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3479         JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3480         return 0;
3481     }
3482 
3483     JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3484     return reinterpret_cast<uintptr_t>(ctx.release());
3485 }
3486 
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3487 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3488     CHECK_ERROR_QUEUE_ON_RETURN;
3489     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3490     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3491 
3492     if (ctx == nullptr) {
3493         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3494         return 0;
3495     }
3496 
3497     jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3498     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3499     return blockSize;
3500 }
3501 
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3502 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3503     CHECK_ERROR_QUEUE_ON_RETURN;
3504     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3505     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3506 
3507     if (ctx == nullptr) {
3508         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3509         return 0;
3510     }
3511 
3512     int buf_len = ctx->buf_len;
3513     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3514     return buf_len;
3515 }
3516 
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3517 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3518     CHECK_ERROR_QUEUE_ON_RETURN;
3519     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3520     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3521 
3522     if (ctx == nullptr) {
3523         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3524         return 0;
3525     }
3526 
3527     bool final_used = ctx->final_used != 0;
3528     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3529     return static_cast<jboolean>(final_used);
3530 }
3531 
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3532 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3533                                                     jboolean enablePaddingBool) {
3534     CHECK_ERROR_QUEUE_ON_RETURN;
3535     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3536     jint enablePadding = enablePaddingBool ? 1 : 0;
3537     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3538 
3539     if (ctx == nullptr) {
3540         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3541         return;
3542     }
3543 
3544     EVP_CIPHER_CTX_set_padding(ctx, enablePadding);  // Not void, but always returns 1.
3545     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3546 }
3547 
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3548 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3549                                                        jint keySizeBits) {
3550     CHECK_ERROR_QUEUE_ON_RETURN;
3551     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3552     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3553 
3554     if (ctx == nullptr) {
3555         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3556         return;
3557     }
3558 
3559     if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3560         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3561                 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3562         JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3563         return;
3564     }
3565     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3566 }
3567 
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3568 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3569     CHECK_ERROR_QUEUE_ON_RETURN;
3570     EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3571     JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3572 
3573     EVP_CIPHER_CTX_free(ctx);
3574 }
3575 
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3576 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3577     CHECK_ERROR_QUEUE_ON_RETURN;
3578     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3579     JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3580     return reinterpret_cast<jlong>(ctx);
3581 }
3582 
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3583 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3584     CHECK_ERROR_QUEUE_ON_RETURN;
3585     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3586     JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3587     return reinterpret_cast<jlong>(ctx);
3588 }
3589 
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3590 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3591     CHECK_ERROR_QUEUE_ON_RETURN;
3592     const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3593     JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3594     return reinterpret_cast<jlong>(ctx);
3595 }
3596 
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3597 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3598     CHECK_ERROR_QUEUE_ON_RETURN;
3599     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3600     JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3601     return reinterpret_cast<jlong>(ctx);
3602 }
3603 
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3604 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3605     CHECK_ERROR_QUEUE_ON_RETURN;
3606     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3607     JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3608     return reinterpret_cast<jlong>(ctx);
3609 }
3610 
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3611 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3612     CHECK_ERROR_QUEUE_ON_RETURN;
3613     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3614     JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3615     if (evpAead == nullptr) {
3616         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3617         return 0;
3618     }
3619     jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3620     JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3621     return maxOverhead;
3622 }
3623 
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3624 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3625     CHECK_ERROR_QUEUE_ON_RETURN;
3626     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3627     JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3628     if (evpAead == nullptr) {
3629         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3630         return 0;
3631     }
3632     jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3633     JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3634     return nonceLength;
3635 }
3636 
3637 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3638                                     size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3639                                     const uint8_t* in, size_t in_len, const uint8_t* ad,
3640                                     size_t ad_len);
3641 
evp_aead_ctx_op_common(JNIEnv * env,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,uint8_t * outBuf,jbyteArray nonceArray,const uint8_t * inBuf,jbyteArray aadArray,evp_aead_ctx_op_func realFunc,jobject inBuffer,jobject outBuffer,jint outRange,jint inRange)3642 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3643                                uint8_t* outBuf, jbyteArray nonceArray,
3644                                const uint8_t* inBuf, jbyteArray aadArray,
3645                                evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange)  {
3646     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3647 
3648     ScopedByteArrayRO keyBytes(env, keyArray);
3649     if (keyBytes.get() == nullptr) {
3650         return 0;
3651     }
3652 
3653     std::unique_ptr<ScopedByteArrayRO> aad;
3654     const uint8_t* aad_chars = nullptr;
3655     size_t aad_chars_size = 0;
3656     if (aadArray != nullptr) {
3657         aad.reset(new ScopedByteArrayRO(env, aadArray));
3658         aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3659         if (aad_chars == nullptr) {
3660             return 0;
3661         }
3662         aad_chars_size = aad->size();
3663     }
3664 
3665     ScopedByteArrayRO nonceBytes(env, nonceArray);
3666     if (nonceBytes.get() == nullptr) {
3667         return 0;
3668     }
3669 
3670     bssl::ScopedEVP_AEAD_CTX aeadCtx;
3671     const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3672     if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3673                            static_cast<size_t>(tagLen), nullptr)) {
3674         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3675                                                              "failure initializing AEAD context");
3676         JNI_TRACE(
3677                 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3678                 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3679                 aadArray);
3680         return 0;
3681     }
3682 
3683     const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3684     size_t actualOutLength;
3685 
3686     if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3687                   nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3688                   aad_chars, aad_chars_size)) {
3689         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3690         return 0;
3691     }
3692 
3693     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3694               evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3695               aadArray, actualOutLength);
3696     return static_cast<jint>(actualOutLength);
3697 }
3698 
evp_aead_ctx_op(JNIEnv * env,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jbyteArray outArray,jint outOffset,jbyteArray nonceArray,jbyteArray inArray,jint inOffset,jint inLength,jbyteArray aadArray,evp_aead_ctx_op_func realFunc)3699 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3700                             jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3701                             jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3702                             evp_aead_ctx_op_func realFunc) {
3703     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3704     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3705               outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3706 
3707 
3708     ScopedByteArrayRW outBytes(env, outArray);
3709     if (outBytes.get() == nullptr) {
3710         return 0;
3711     }
3712 
3713     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3714         JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3715                   evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3716                   inLength, aadArray);
3717         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3718         return 0;
3719     }
3720 
3721     ScopedByteArrayRO inBytes(env, inArray);
3722     if (inBytes.get() == nullptr) {
3723         return 0;
3724     }
3725 
3726     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3727         JNI_TRACE(
3728                 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3729                 "invalid",
3730                 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3731                 inLength, aadArray);
3732         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3733         return 0;
3734     }
3735 
3736     uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3737     const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3738 
3739     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3740                             aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3741 }
3742 
evp_aead_ctx_op_buf(JNIEnv * env,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray,evp_aead_ctx_op_func realFunc)3743 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3744                             jobject outBuffer, jbyteArray nonceArray,
3745                             jobject inBuffer, jbyteArray aadArray,
3746                             evp_aead_ctx_op_func realFunc) {
3747 
3748     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3749     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3750               outBuffer, nonceArray, inBuffer, aadArray);
3751 
3752     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3753         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3754                                            "inBuffer is not a direct ByteBuffer");
3755         return 0;
3756     }
3757 
3758     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3759         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3760                                            "outBuffer is not a direct ByteBuffer");
3761         return 0;
3762     }
3763 
3764     uint8_t* inBuf;
3765     jint in_limit;
3766     jint in_position;
3767 
3768     inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3769      // limit is the index of the first element that should not be read or written
3770     in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3771     // position is the index of the next element to be read or written
3772     in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3773 
3774     uint8_t* outBuf;
3775     jint out_limit;
3776     jint out_position;
3777     outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3778     // limit is the index of the first element that should not be read or written
3779     out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3780     // position is the index of the next element to be read or written
3781     out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3782 
3783     // Shifting over of ByteBuffer address to start at true position
3784     inBuf += in_position;
3785     outBuf += out_position;
3786 
3787     size_t inSize = in_limit - in_position;
3788     uint8_t* outBufEnd = outBuf + out_limit - out_position;
3789     uint8_t* inBufEnd = inBuf + inSize;
3790     std::unique_ptr<uint8_t[]> inCopy;
3791     if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3792       inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3793       if (inCopy.get() == nullptr) {
3794             conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3795             return 0;
3796         }
3797         memcpy(inCopy.get(), inBuf, inSize);
3798         inBuf = inCopy.get();
3799     }
3800 
3801     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3802                                inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3803 }
3804 
NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jbyteArray outArray,jint outOffset,jbyteArray nonceArray,jbyteArray inArray,jint inOffset,jint inLength,jbyteArray aadArray)3805 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3806                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3807                                            jint outOffset, jbyteArray nonceArray,
3808                                            jbyteArray inArray, jint inOffset, jint inLength,
3809                                            jbyteArray aadArray) {
3810     CHECK_ERROR_QUEUE_ON_RETURN;
3811     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3812                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3813 }
3814 
NativeCrypto_EVP_AEAD_CTX_open(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jbyteArray outArray,jint outOffset,jbyteArray nonceArray,jbyteArray inArray,jint inOffset,jint inLength,jbyteArray aadArray)3815 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3816                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3817                                            jint outOffset, jbyteArray nonceArray,
3818                                            jbyteArray inArray, jint inOffset, jint inLength,
3819                                            jbyteArray aadArray) {
3820     CHECK_ERROR_QUEUE_ON_RETURN;
3821     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3822                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3823 }
3824 
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3825 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3826                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3827                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3828     CHECK_ERROR_QUEUE_ON_RETURN;
3829     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3830                            inBuffer, aadArray, EVP_AEAD_CTX_seal);
3831 }
3832 
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3833 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3834                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3835                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3836     CHECK_ERROR_QUEUE_ON_RETURN;
3837     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3838                            inBuffer, aadArray, EVP_AEAD_CTX_open);
3839 }
3840 
NativeCrypto_EVP_HPKE_CTX_export(JNIEnv * env,jclass,jobject hpkeCtxRef,jbyteArray exporterCtxArray,jint exportedLen)3841 static jbyteArray NativeCrypto_EVP_HPKE_CTX_export(JNIEnv* env, jclass, jobject hpkeCtxRef,
3842                                                    jbyteArray exporterCtxArray, jint exportedLen) {
3843     CHECK_ERROR_QUEUE_ON_RETURN;
3844     EVP_HPKE_CTX* hpkeCtx = fromContextObject<EVP_HPKE_CTX>(env, hpkeCtxRef);
3845     JNI_TRACE("EVP_HPKE_CTX_export(%p, %p, %d)", hpkeCtx, exporterCtxArray, exportedLen);
3846 
3847     if (hpkeCtx == nullptr) {
3848         // NullPointerException thrown while calling fromContextObject
3849         return {};
3850     }
3851 
3852     std::optional<ScopedByteArrayRO> optionalExporterCtx;
3853     const uint8_t* exporterCtx = nullptr;
3854     size_t exporterCtxLen = 0;
3855     if (exporterCtxArray != nullptr) {
3856         optionalExporterCtx.emplace(env, exporterCtxArray);
3857         exporterCtx = reinterpret_cast<const uint8_t*>(optionalExporterCtx->get());
3858         if (exporterCtx == nullptr) {
3859             return {};
3860         }
3861         exporterCtxLen = optionalExporterCtx->size();
3862     }
3863 
3864     std::vector<uint8_t> exported(exportedLen);
3865     if (!EVP_HPKE_CTX_export(/* ctx= */ hpkeCtx,
3866                              /* out= */ exported.data(),
3867                              /* secret_len= */ exportedLen,
3868                              /* context= */ exporterCtx,
3869                              /* context_len= */ exporterCtxLen)) {
3870         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_export");
3871         return {};
3872     }
3873 
3874     ScopedLocalRef<jbyteArray> exportedArray(env, env->NewByteArray(static_cast<jsize>(exportedLen)));
3875     if (exportedArray.get() == nullptr) {
3876         return {};
3877     }
3878     ScopedByteArrayRW exportedBytes(env, exportedArray.get());
3879     if (exportedBytes.get() == nullptr) {
3880         return {};
3881     }
3882     memcpy(exportedBytes.get(), reinterpret_cast<const jbyte*>(exported.data()), exportedLen);
3883     return exportedArray.release();
3884 }
3885 
NativeCrypto_EVP_HPKE_CTX_free(JNIEnv * env,jclass,jlong hpkeCtxRef)3886 static void NativeCrypto_EVP_HPKE_CTX_free(JNIEnv* env, jclass, jlong hpkeCtxRef) {
3887     CHECK_ERROR_QUEUE_ON_RETURN;
3888     EVP_HPKE_CTX* ctx = reinterpret_cast<EVP_HPKE_CTX*>(hpkeCtxRef);
3889     JNI_TRACE("EVP_HPKE_CTX_free(%p)", ctx);
3890     if (ctx == nullptr) {
3891         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3892         return;
3893     }
3894     EVP_HPKE_CTX_free(ctx);
3895 }
3896 
NativeCrypto_EVP_HPKE_CTX_open(JNIEnv * env,jclass,jobject recipientHpkeCtxRef,jbyteArray ciphertextArray,jbyteArray aadArray)3897 static jbyteArray NativeCrypto_EVP_HPKE_CTX_open(JNIEnv* env, jclass, jobject recipientHpkeCtxRef,
3898                                                  jbyteArray ciphertextArray, jbyteArray aadArray) {
3899     CHECK_ERROR_QUEUE_ON_RETURN;
3900     EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, recipientHpkeCtxRef);
3901     JNI_TRACE("EVP_HPKE_CTX_open(%p, %p, %p)", ctx, ciphertextArray, aadArray);
3902 
3903     if (ctx == nullptr) {
3904         // NullPointerException thrown while calling fromContextObject
3905         return {};
3906     }
3907 
3908     if (ciphertextArray == nullptr) {
3909         conscrypt::jniutil::throwNullPointerException(env, "ciphertextArray == null");
3910         return {};
3911     }
3912 
3913     ScopedByteArrayRO ciphertext(env, ciphertextArray);
3914     if (ciphertext.get() == nullptr) {
3915         return {};
3916     }
3917 
3918     std::optional<ScopedByteArrayRO> optionalAad;
3919     const uint8_t* aad = nullptr;
3920     size_t aadLen = 0;
3921     if (aadArray != nullptr) {
3922         optionalAad.emplace(env, aadArray);
3923         aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
3924         if (aad == nullptr) {
3925             return {};
3926         }
3927         aadLen = optionalAad->size();
3928     }
3929 
3930     size_t plaintextLen;
3931     std::vector<uint8_t> plaintext(ciphertext.size());
3932     if (!EVP_HPKE_CTX_open(/* ctx= */ ctx,
3933                            /* out= */ plaintext.data(),
3934                            /* out_len= */ &plaintextLen,
3935                            /* max_out_len= */ plaintext.size(),
3936                            /* in= */ reinterpret_cast<const uint8_t*>(ciphertext.get()),
3937                            /* in_len= */ ciphertext.size(),
3938                            /* aad= */ aad,
3939                            /* aad_len= */ aadLen)) {
3940         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_open");
3941         return {};
3942     }
3943 
3944     plaintext.resize(plaintextLen);
3945     ScopedLocalRef<jbyteArray> plaintextArray(env, env->NewByteArray(static_cast<jsize>(plaintextLen)));
3946     if (plaintextArray.get() == nullptr) {
3947         return {};
3948     }
3949     ScopedByteArrayRW plaintextBytes(env, plaintextArray.get());
3950     if (plaintextBytes.get() == nullptr) {
3951         return {};
3952     }
3953     memcpy(plaintextBytes.get(), reinterpret_cast<const jbyte*>(plaintext.data()), plaintextLen);
3954     return plaintextArray.release();
3955 }
3956 
NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv * env,jclass,jobject senderHpkeCtxRef,jbyteArray plaintextArray,jbyteArray aadArray)3957 static jbyteArray NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv* env, jclass, jobject senderHpkeCtxRef,
3958                                                  jbyteArray plaintextArray, jbyteArray aadArray) {
3959     CHECK_ERROR_QUEUE_ON_RETURN;
3960     EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, senderHpkeCtxRef);
3961     JNI_TRACE("EVP_HPKE_CTX_seal(%p, %p, %p)", ctx, plaintextArray, aadArray);
3962 
3963     if (ctx == nullptr) {
3964         // NullPointerException thrown while calling fromContextObject
3965         return {};
3966     }
3967 
3968     if (plaintextArray == nullptr) {
3969         conscrypt::jniutil::throwNullPointerException(env, "plaintextArray == null");
3970         return {};
3971     }
3972 
3973     std::optional<ScopedByteArrayRO> optionalAad;
3974     const uint8_t* aad = nullptr;
3975     size_t aadLen = 0;
3976     if (aadArray != nullptr) {
3977         optionalAad.emplace(env, aadArray);
3978         aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
3979         if (aad == nullptr) {
3980             return {};
3981         }
3982         aadLen = optionalAad->size();
3983     }
3984 
3985     ScopedByteArrayRO plaintext(env, plaintextArray);
3986     std::vector<uint8_t> encrypted(env->GetArrayLength(plaintextArray) +
3987                                    EVP_HPKE_CTX_max_overhead(ctx));
3988     size_t encryptedLen;
3989     if (!EVP_HPKE_CTX_seal(/* ctx= */ ctx,
3990                            /* out= */ encrypted.data(),
3991                            /* out_len= */ &encryptedLen,
3992                            /* max_out_len= */ encrypted.size(),
3993                            /* in= */ reinterpret_cast<const uint8_t*>(plaintext.get()),
3994                            /* in_len= */ plaintext.size(),
3995                            /* aad= */ aad,
3996                            /* aad_len= */ aadLen)) {
3997         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_seal");
3998         return {};
3999     }
4000 
4001     ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(static_cast<jsize>(encryptedLen)));
4002     if (ciphertextArray.get() == nullptr) {
4003         return {};
4004     }
4005     ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
4006     if (ciphertextBytes.get() == nullptr) {
4007         return {};
4008     }
4009     memcpy(ciphertextBytes.get(), reinterpret_cast<const jbyte*>(encrypted.data()), encryptedLen);
4010     return ciphertextArray.release();
4011 }
4012 
getHpkeAead(JNIEnv * env,jint aeadValue)4013 const EVP_HPKE_AEAD* getHpkeAead(JNIEnv* env, jint aeadValue) {
4014     switch (aeadValue) {
4015         case EVP_HPKE_AES_128_GCM:
4016             return EVP_hpke_aes_128_gcm();
4017         case EVP_HPKE_AES_256_GCM:
4018             return EVP_hpke_aes_256_gcm();
4019         case EVP_HPKE_CHACHA20_POLY1305:
4020             return EVP_hpke_chacha20_poly1305();
4021         default:
4022             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4023                                                "AEAD is not supported");
4024             return nullptr;
4025     }
4026 }
4027 
getHpkeKdf(JNIEnv * env,jint kdfValue)4028 const EVP_HPKE_KDF* getHpkeKdf(JNIEnv* env, jint kdfValue) {
4029     if (kdfValue == EVP_HPKE_HKDF_SHA256) {
4030         return EVP_hpke_hkdf_sha256();
4031     } else {
4032         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4033                                            "KDF is not supported");
4034         return nullptr;
4035     }
4036 }
4037 
getHpkeKem(JNIEnv * env,jint kemValue)4038 const EVP_HPKE_KEM* getHpkeKem(JNIEnv* env, jint kemValue) {
4039     if (kemValue == EVP_HPKE_DHKEM_X25519_HKDF_SHA256) {
4040         return EVP_hpke_x25519_hkdf_sha256();
4041     } else {
4042         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4043                                            "KEM is not supported");
4044         return nullptr;
4045     }
4046 }
4047 
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray privateKeyArray,jbyteArray encArray,jbyteArray infoArray)4048 static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv* env, jclass,
4049                                                                    jint kemValue,jint kdfValue,
4050                                                                    jint aeadValue,
4051                                                                    jbyteArray privateKeyArray,
4052                                                                    jbyteArray encArray,
4053                                                                    jbyteArray infoArray) {
4054     CHECK_ERROR_QUEUE_ON_RETURN;
4055     JNI_TRACE("EVP_HPKE_CTX_setup_recipient(%d, %d, %d, %p, %p, %p)", kemValue, kdfValue, aeadValue,
4056               privateKeyArray, encArray, infoArray);
4057 
4058     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4059     if (kem == nullptr) {
4060         return nullptr;
4061     }
4062     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4063     if (kdf == nullptr) {
4064         return nullptr;
4065     }
4066     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4067     if (aead == nullptr) {
4068         return nullptr;
4069     }
4070     if (privateKeyArray == nullptr) {
4071         conscrypt::jniutil::throwNullPointerException(env, "privateKeyArray == null");
4072         return nullptr;
4073     }
4074     if (encArray == nullptr) {
4075         conscrypt::jniutil::throwNullPointerException(env, "encArray == null");
4076         return nullptr;
4077     }
4078 
4079     ScopedByteArrayRO privateKey(env, privateKeyArray);
4080 
4081     bssl::ScopedEVP_HPKE_KEY key;
4082 
4083     if (!EVP_HPKE_KEY_init(/* key= */ key.get(),
4084                            /* kem= */ kem,
4085                            /* priv_key= */ reinterpret_cast<const uint8_t*>(privateKey.get()),
4086                            /* priv_key_len= */ privateKey.size())) {
4087         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4088         return nullptr;
4089     }
4090 
4091     std::optional<ScopedByteArrayRO> optionalInfo;
4092     const uint8_t* info = nullptr;
4093     size_t infoLen = 0;
4094     if (infoArray != nullptr) {
4095         optionalInfo.emplace(env, infoArray);
4096         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4097         if (info == nullptr) {
4098             return {};
4099         }
4100         infoLen = optionalInfo->size();
4101     }
4102 
4103     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4104     ScopedByteArrayRO enc(env, encArray);
4105     if (!EVP_HPKE_CTX_setup_recipient(/* ctx= */ ctx.get(),
4106                                       /* key= */ key.get(),
4107                                       /* kdf= */ kdf,
4108                                       /* aead= */ aead,
4109                                       /* enc= */ reinterpret_cast<const uint8_t*>(enc.get()),
4110                                       /* enc_len= */ enc.size(),
4111                                       /* info= */ info,
4112                                       /* info_len= */ infoLen)) {
4113         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4114         return nullptr;
4115     }
4116 
4117     ScopedLocalRef<jobject> ctxObject(
4118                     env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4119                                         conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4120                                         reinterpret_cast<jlong>(ctx.release())));
4121     return ctxObject.release();
4122 }
4123 
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray)4124 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass,
4125                                                                      jint kemValue,jint kdfValue,
4126                                                                      jint aeadValue,
4127                                                                      jbyteArray publicKeyArray,
4128                                                                      jbyteArray infoArray) {
4129     CHECK_ERROR_QUEUE_ON_RETURN;
4130     JNI_TRACE("EVP_HPKE_CTX_setup_sender(%d, %d, %d, %p, %p)", kemValue, kdfValue, aeadValue,
4131               publicKeyArray, infoArray);
4132 
4133     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4134     if (kem == nullptr) {
4135         return nullptr;
4136     }
4137     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4138     if (kdf == nullptr) {
4139         return nullptr;
4140     }
4141     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4142     if (aead == nullptr) {
4143         return nullptr;
4144     }
4145     if (publicKeyArray == nullptr) {
4146         conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray == null");
4147         return {};
4148     }
4149 
4150     std::optional<ScopedByteArrayRO> optionalInfo;
4151     const uint8_t* info = nullptr;
4152     size_t infoLen = 0;
4153     if (infoArray != nullptr) {
4154         optionalInfo.emplace(env, infoArray);
4155         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4156         if (info == nullptr) {
4157             return {};
4158         }
4159         infoLen = optionalInfo->size();
4160     }
4161 
4162     ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4163 
4164     size_t encapsulatedSharedSecretLen;
4165     uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4166 
4167     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4168 
4169     if (!EVP_HPKE_CTX_setup_sender(/* ctx= */ ctx.get(),
4170                                    /* out_enc= */ encapsulatedSharedSecret,
4171                                    /* out_enc_len= */ &encapsulatedSharedSecretLen,
4172                                    /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4173                                    /* kem= */ kem,
4174                                    /* kdf= */ kdf,
4175                                    /* aead= */ aead,
4176                                    /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4177                                    /* peer_public_key_len= */ peer_public_key.size(),
4178                                    /* info= */ info,
4179                                    /* info_len= */ infoLen)) {
4180         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_sender");
4181         return {};
4182     }
4183 
4184     ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4185     if (encArray.get() == nullptr) {
4186         return {};
4187     }
4188     ScopedByteArrayRW encBytes(env, encArray.get());
4189     if (encBytes.get() == nullptr) {
4190         return {};
4191     }
4192     memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4193 
4194     ScopedLocalRef<jobjectArray> result(
4195             env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4196 
4197     ScopedLocalRef<jobject> ctxObject(
4198                 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4199                                     conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4200                                     reinterpret_cast<jlong>(ctx.release())));
4201 
4202     env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4203     env->SetObjectArrayElement(result.get(), 1, encArray.release());
4204 
4205     return result.release();
4206 }
4207 
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray,jbyteArray seedArray)4208 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(
4209         JNIEnv* env, jclass, jint kemValue, jint kdfValue, jint aeadValue,
4210         jbyteArray publicKeyArray, jbyteArray infoArray, jbyteArray seedArray) {
4211     CHECK_ERROR_QUEUE_ON_RETURN;
4212     JNI_TRACE("EVP_HPKE_CTX_setup_sender_with_seed_for_testing(%d, %d, %d, %p, %p, %p)", kemValue,
4213               kdfValue, aeadValue, publicKeyArray, infoArray, seedArray);
4214 
4215     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4216     if (kem == nullptr) {
4217         return nullptr;
4218     }
4219     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4220     if (kdf == nullptr) {
4221         return nullptr;
4222     }
4223     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4224     if (aead == nullptr) {
4225         return nullptr;
4226     }
4227     if (publicKeyArray == nullptr || seedArray == nullptr) {
4228         conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray or seedArray == null");
4229         return {};
4230     }
4231 
4232     std::optional<ScopedByteArrayRO> optionalInfo;
4233     const uint8_t* info = nullptr;
4234     size_t infoLen = 0;
4235     if (infoArray != nullptr) {
4236         optionalInfo.emplace(env, infoArray);
4237         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4238         if (info == nullptr) {
4239             return {};
4240         }
4241         infoLen = optionalInfo->size();
4242     }
4243 
4244     ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4245 
4246     ScopedByteArrayRO seed(env, seedArray);
4247 
4248     size_t encapsulatedSharedSecretLen;
4249     uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4250 
4251     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4252 
4253     if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
4254             /* ctx= */ ctx.get(),
4255             /* out_enc= */ encapsulatedSharedSecret,
4256             /* out_enc_len= */ &encapsulatedSharedSecretLen,
4257             /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4258             /* kem= */ kem,
4259             /* kdf= */ kdf,
4260             /* aead= */ aead,
4261             /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4262             /* peer_public_key_len= */ peer_public_key.size(),
4263             /* info= */ info,
4264             /* info_len= */ infoLen,
4265             /* seed= */ reinterpret_cast<const uint8_t*>(seed.get()),
4266             /* seed_len= */ seed.size())) {
4267         conscrypt::jniutil::throwExceptionFromBoringSSLError(
4268                 env, "EVP_HPKE_CTX_setup_sender_with_seed_for_testing");
4269         return {};
4270     }
4271 
4272     ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4273     if (encArray.get() == nullptr) {
4274         return {};
4275     }
4276     ScopedByteArrayRW encBytes(env, encArray.get());
4277     if (encBytes.get() == nullptr) {
4278         return {};
4279     }
4280     memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4281 
4282     ScopedLocalRef<jobjectArray> result(
4283             env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4284 
4285     ScopedLocalRef<jobject> ctxObject(
4286                     env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4287                                         conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4288                                         reinterpret_cast<jlong>(ctx.release())));
4289 
4290     env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4291     env->SetObjectArrayElement(result.get(), 1, encArray.release());
4292 
4293     return result.release();
4294 }
4295 
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)4296 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
4297     CHECK_ERROR_QUEUE_ON_RETURN;
4298     JNI_TRACE("CMAC_CTX_new");
4299     auto cmacCtx = CMAC_CTX_new();
4300     if (cmacCtx == nullptr) {
4301         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
4302         return 0;
4303     }
4304 
4305     return reinterpret_cast<jlong>(cmacCtx);
4306 }
4307 
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)4308 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
4309     CHECK_ERROR_QUEUE_ON_RETURN;
4310     CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
4311     JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
4312     if (cmacCtx == nullptr) {
4313         conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
4314         return;
4315     }
4316     CMAC_CTX_free(cmacCtx);
4317 }
4318 
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)4319 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
4320     CHECK_ERROR_QUEUE_ON_RETURN;
4321     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4322     JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
4323     if (cmacCtx == nullptr) {
4324         return;
4325     }
4326     ScopedByteArrayRO keyBytes(env, keyArray);
4327     if (keyBytes.get() == nullptr) {
4328         return;
4329     }
4330 
4331     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4332 
4333     const EVP_CIPHER *cipher;
4334     switch(keyBytes.size()) {
4335       case 16:
4336           cipher = EVP_aes_128_cbc();
4337           break;
4338       case 24:
4339           cipher = EVP_aes_192_cbc();
4340           break;
4341       case 32:
4342           cipher = EVP_aes_256_cbc();
4343           break;
4344       default:
4345           conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4346                                            "CMAC_Init: Unsupported key length");
4347           return;
4348     }
4349 
4350     if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
4351         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
4352         JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
4353         return;
4354     }
4355 }
4356 
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)4357 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
4358                                            int inLength) {
4359     CHECK_ERROR_QUEUE_ON_RETURN;
4360     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4361     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4362     JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
4363 
4364     if (cmacCtx == nullptr) {
4365         return;
4366     }
4367 
4368     if (p == nullptr) {
4369         conscrypt::jniutil::throwNullPointerException(env, nullptr);
4370         return;
4371     }
4372 
4373     if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
4374         JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
4375         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
4376         return;
4377     }
4378 }
4379 
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4380 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
4381                                      jint inOffset, jint inLength) {
4382     CHECK_ERROR_QUEUE_ON_RETURN;
4383     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4384     JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
4385 
4386     if (cmacCtx == nullptr) {
4387         return;
4388     }
4389 
4390     ScopedByteArrayRO inBytes(env, inArray);
4391     if (inBytes.get() == nullptr) {
4392         return;
4393     }
4394 
4395     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4396         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4397                                            "inBytes");
4398         return;
4399     }
4400 
4401     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4402 
4403     if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4404         JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
4405                   inLength);
4406         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
4407         return;
4408     }
4409 }
4410 
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)4411 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
4412     CHECK_ERROR_QUEUE_ON_RETURN;
4413     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4414     JNI_TRACE("CMAC_Final(%p)", cmacCtx);
4415 
4416     if (cmacCtx == nullptr) {
4417         return nullptr;
4418     }
4419 
4420     uint8_t result[EVP_MAX_MD_SIZE];
4421     size_t len;
4422     if (!CMAC_Final(cmacCtx, result, &len)) {
4423         JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
4424         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
4425         return nullptr;
4426     }
4427 
4428     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4429     if (resultArray.get() == nullptr) {
4430         return nullptr;
4431     }
4432     ScopedByteArrayRW resultBytes(env, resultArray.get());
4433     if (resultBytes.get() == nullptr) {
4434         return nullptr;
4435     }
4436     memcpy(resultBytes.get(), result, len);
4437     return resultArray.release();
4438 }
4439 
NativeCrypto_CMAC_Reset(JNIEnv * env,jclass,jobject cmacCtxRef)4440 static void NativeCrypto_CMAC_Reset(JNIEnv* env, jclass, jobject cmacCtxRef) {
4441     CHECK_ERROR_QUEUE_ON_RETURN;
4442     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4443     JNI_TRACE("CMAC_Reset(%p)", cmacCtx);
4444 
4445     if (cmacCtx == nullptr) {
4446         return;
4447     }
4448 
4449     if (!CMAC_Reset(cmacCtx)) {
4450         JNI_TRACE("CMAC_Reset(%p) => threw exception", cmacCtx);
4451         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Reset");
4452         return;
4453     }
4454 }
4455 
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)4456 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
4457     CHECK_ERROR_QUEUE_ON_RETURN;
4458     JNI_TRACE("HMAC_CTX_new");
4459     auto hmacCtx = HMAC_CTX_new();
4460     if (hmacCtx == nullptr) {
4461         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
4462         return 0;
4463     }
4464 
4465     return reinterpret_cast<jlong>(hmacCtx);
4466 }
4467 
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)4468 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
4469     CHECK_ERROR_QUEUE_ON_RETURN;
4470     HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
4471     JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
4472     if (hmacCtx == nullptr) {
4473         conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
4474         return;
4475     }
4476     HMAC_CTX_free(hmacCtx);
4477 }
4478 
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)4479 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
4480                                       jobject evpMdRef) {
4481     CHECK_ERROR_QUEUE_ON_RETURN;
4482     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4483     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4484     JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
4485     if (hmacCtx == nullptr) {
4486         return;
4487     }
4488     ScopedByteArrayRO keyBytes(env, keyArray);
4489     if (keyBytes.get() == nullptr) {
4490         return;
4491     }
4492 
4493     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4494     if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
4495         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4496         JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
4497         return;
4498     }
4499 }
4500 
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)4501 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
4502                                            int inLength) {
4503     CHECK_ERROR_QUEUE_ON_RETURN;
4504     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4505     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4506     JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
4507 
4508     if (hmacCtx == nullptr) {
4509         return;
4510     }
4511 
4512     if (p == nullptr) {
4513         conscrypt::jniutil::throwNullPointerException(env, nullptr);
4514         return;
4515     }
4516 
4517     if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
4518         JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
4519         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
4520         return;
4521     }
4522 }
4523 
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4524 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
4525                                      jint inOffset, jint inLength) {
4526     CHECK_ERROR_QUEUE_ON_RETURN;
4527     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4528     JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
4529 
4530     if (hmacCtx == nullptr) {
4531         return;
4532     }
4533 
4534     ScopedByteArrayRO inBytes(env, inArray);
4535     if (inBytes.get() == nullptr) {
4536         return;
4537     }
4538 
4539     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4540         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4541                                            "inBytes");
4542         return;
4543     }
4544 
4545     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4546     if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4547         JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4548                   inLength);
4549         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4550         return;
4551     }
4552 }
4553 
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4554 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4555     CHECK_ERROR_QUEUE_ON_RETURN;
4556     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4557     JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4558 
4559     if (hmacCtx == nullptr) {
4560         return nullptr;
4561     }
4562 
4563     uint8_t result[EVP_MAX_MD_SIZE];
4564     unsigned len;
4565     if (!HMAC_Final(hmacCtx, result, &len)) {
4566         JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4567         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4568         return nullptr;
4569     }
4570 
4571     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4572     if (resultArray.get() == nullptr) {
4573         return nullptr;
4574     }
4575     ScopedByteArrayRW resultBytes(env, resultArray.get());
4576     if (resultBytes.get() == nullptr) {
4577         return nullptr;
4578     }
4579     memcpy(resultBytes.get(), result, len);
4580     return resultArray.release();
4581 }
4582 
NativeCrypto_HMAC_Reset(JNIEnv * env,jclass,jobject hmacCtxRef)4583 static void NativeCrypto_HMAC_Reset(JNIEnv* env, jclass, jobject hmacCtxRef) {
4584     CHECK_ERROR_QUEUE_ON_RETURN;
4585     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4586     JNI_TRACE("HMAC_Reset(%p)", hmacCtx);
4587 
4588     if (hmacCtx == nullptr) {
4589         return;
4590     }
4591 
4592     // HMAC_Init_ex with all nulls will reuse the existing key. This is slightly
4593     // more efficient than re-initializing the context with the key again.
4594     if (!HMAC_Init_ex(hmacCtx, /*key=*/nullptr, /*key_len=*/0, /*md=*/nullptr, /*impl=*/nullptr)) {
4595         JNI_TRACE("HMAC_Reset(%p) => threw exception", hmacCtx);
4596         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4597         return;
4598     }
4599 }
4600 
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4601 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4602     CHECK_ERROR_QUEUE_ON_RETURN;
4603     JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4604 
4605     ScopedByteArrayRW outputBytes(env, output);
4606     if (outputBytes.get() == nullptr) {
4607         return;
4608     }
4609 
4610     unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4611     if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4612         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4613         JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4614         return;
4615     }
4616 
4617     JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4618 }
4619 
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4620 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4621     /*
4622      * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4623      * Just make a buffer that's large enough here. The documentation recommends
4624      * 80 characters.
4625      */
4626     char output[128];
4627     int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4628     if (ret < 0) {
4629         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4630         return nullptr;
4631     } else if (size_t(ret) >= sizeof(output)) {
4632         conscrypt::jniutil::throwRuntimeException(env,
4633                                                   "ASN1_OBJECT_to_OID_string buffer too small");
4634         return nullptr;
4635     }
4636 
4637     JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4638     return env->NewStringUTF(output);
4639 }
4640 
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4641 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4642                                                  jboolean isFinite) {
4643     CHECK_ERROR_QUEUE_ON_RETURN;
4644     JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4645 
4646     if (streamObj == nullptr) {
4647         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4648         return 0;
4649     }
4650 
4651     const BIO_METHOD *method = stream_bio_method();
4652     if (!method) {
4653         return 0;
4654     }
4655     bssl::UniquePtr<BIO> bio(BIO_new(method));
4656     if (bio.get() == nullptr) {
4657         return 0;
4658     }
4659 
4660     bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4661 
4662     JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4663     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4664 }
4665 
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4666 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4667     CHECK_ERROR_QUEUE_ON_RETURN;
4668     JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4669 
4670     if (streamObj == nullptr) {
4671         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4672         return 0;
4673     }
4674 
4675     const BIO_METHOD *method = stream_bio_method();
4676     if (!method) {
4677         return 0;
4678     }
4679     bssl::UniquePtr<BIO> bio(BIO_new(method));
4680     if (bio.get() == nullptr) {
4681         return 0;
4682     }
4683 
4684     bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4685 
4686     JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4687     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4688 }
4689 
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4690 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4691     CHECK_ERROR_QUEUE_ON_RETURN;
4692     BIO* bio = to_BIO(env, bioRef);
4693     JNI_TRACE("BIO_free_all(%p)", bio);
4694 
4695     if (bio == nullptr) {
4696         return;
4697     }
4698 
4699     BIO_free_all(bio);
4700 }
4701 
4702 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4703 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4704     JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4705 
4706     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4707     if (buffer.get() == nullptr) {
4708         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4709         JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4710         return nullptr;
4711     }
4712 
4713     /* Don't interpret the string. */
4714     flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4715 
4716     /* Write in given format and null terminate. */
4717     X509_NAME_print_ex(buffer.get(), name, 0, flags);
4718     BIO_write(buffer.get(), "\0", 1);
4719 
4720     char* tmp;
4721     BIO_get_mem_data(buffer.get(), &tmp);
4722     JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4723     return env->NewStringUTF(tmp);
4724 }
4725 
4726 /**
4727  * Converts GENERAL_NAME items to the output format expected in
4728  * X509Certificate#getSubjectAlternativeNames and
4729  * X509Certificate#getIssuerAlternativeNames return.
4730  */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4731 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4732     switch (gen->type) {
4733         case GEN_EMAIL:
4734         case GEN_DNS:
4735         case GEN_URI: {
4736             // This must be a valid IA5String and must not contain NULs.
4737             // BoringSSL does not currently enforce the former (see
4738             // https://crbug.com/boringssl/427). The latter was historically an
4739             // issue for parsers that truncate at NUL.
4740             const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4741             ssize_t len = ASN1_STRING_length(gen->d.ia5);
4742             std::vector<jchar> jchars;
4743             jchars.reserve(len);
4744             for (ssize_t i = 0; i < len; i++) {
4745                 if (data[i] == 0 || data[i] > 127) {
4746                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4747                     return nullptr;
4748                 }
4749                 // Converting ASCII to UTF-16 is the identity function.
4750                 jchars.push_back(data[i]);
4751             }
4752             JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4753             return env->NewString(jchars.data(), jchars.size());
4754         }
4755         case GEN_DIRNAME:
4756             /* Write in RFC 2253 format */
4757             return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4758         case GEN_IPADD: {
4759 #ifdef _WIN32
4760             void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4761 #else
4762             const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4763 #endif
4764             if (gen->d.ip->length == 4) {
4765                 // IPv4
4766                 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4767                 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4768                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4769                     return env->NewStringUTF(buffer.get());
4770                 } else {
4771                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4772                               strerror(errno));
4773                 }
4774             } else if (gen->d.ip->length == 16) {
4775                 // IPv6
4776                 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4777                 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4778                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4779                     return env->NewStringUTF(buffer.get());
4780                 } else {
4781                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4782                               strerror(errno));
4783                 }
4784             }
4785 
4786             /* Invalid IP encodings are pruned out without throwing an exception. */
4787             return nullptr;
4788         }
4789         case GEN_RID:
4790             return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4791         case GEN_OTHERNAME:
4792         case GEN_X400:
4793         default:
4794             return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4795     }
4796 
4797     return nullptr;
4798 }
4799 
4800 #define GN_STACK_SUBJECT_ALT_NAME 1
4801 #define GN_STACK_ISSUER_ALT_NAME 2
4802 
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4803 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4804                                                              CONSCRYPT_UNUSED jobject holder,
4805                                                              jint type) {
4806     CHECK_ERROR_QUEUE_ON_RETURN;
4807     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4808     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4809 
4810     if (x509 == nullptr) {
4811         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4812         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4813         return nullptr;
4814     }
4815 
4816     bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4817     if (type == GN_STACK_SUBJECT_ALT_NAME) {
4818         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4819                 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4820     } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4821         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4822                 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4823     } else {
4824         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4825         return nullptr;
4826     }
4827     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4828     // |ERR_clear_error|, and throw CertificateParsingException.
4829     if (gn_stack == nullptr) {
4830         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4831         ERR_clear_error();
4832         return nullptr;
4833     }
4834 
4835     int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4836     if (count <= 0) {
4837         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4838         return nullptr;
4839     }
4840 
4841     /*
4842      * Keep track of how many originally so we can ignore any invalid
4843      * values later.
4844      */
4845     const int origCount = count;
4846 
4847     ScopedLocalRef<jobjectArray> joa(
4848             env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4849     for (int i = 0, j = 0; i < origCount; i++, j++) {
4850         GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4851         ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4852         if (env->ExceptionCheck()) {
4853             JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4854                       x509, type);
4855             return nullptr;
4856         }
4857 
4858         /*
4859          * If it's nullptr, we'll have to skip this, reduce the number of total
4860          * entries, and fix up the array later.
4861          */
4862         if (val.get() == nullptr) {
4863             j--;
4864             count--;
4865             continue;
4866         }
4867 
4868         ScopedLocalRef<jobjectArray> item(
4869                 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4870 
4871         ScopedLocalRef<jobject> parsedType(
4872                 env,
4873                 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4874                                             conscrypt::jniutil::integer_valueOfMethod, gen->type));
4875         env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4876         env->SetObjectArrayElement(item.get(), 1, val.get());
4877 
4878         env->SetObjectArrayElement(joa.get(), j, item.get());
4879     }
4880 
4881     if (count == 0) {
4882         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4883                   x509, type, origCount);
4884         joa.reset(nullptr);
4885     } else if (origCount != count) {
4886         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4887                   count);
4888 
4889         ScopedLocalRef<jobjectArray> joa_copy(
4890                 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4891 
4892         for (int i = 0; i < count; i++) {
4893             ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4894             env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4895         }
4896 
4897         joa.reset(joa_copy.release());
4898     }
4899 
4900     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4901     return joa.release();
4902 }
4903 
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4904 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4905                                              CONSCRYPT_UNUSED jobject holder) {
4906     CHECK_ERROR_QUEUE_ON_RETURN;
4907     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4908     JNI_TRACE("X509_get_notBefore(%p)", x509);
4909 
4910     if (x509 == nullptr) {
4911         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4912         JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4913         return 0;
4914     }
4915 
4916     ASN1_TIME* notBefore = X509_get_notBefore(x509);
4917     JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4918     return reinterpret_cast<uintptr_t>(notBefore);
4919 }
4920 
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4921 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4922                                             CONSCRYPT_UNUSED jobject holder) {
4923     CHECK_ERROR_QUEUE_ON_RETURN;
4924     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4925     JNI_TRACE("X509_get_notAfter(%p)", x509);
4926 
4927     if (x509 == nullptr) {
4928         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4929         JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4930         return 0;
4931     }
4932 
4933     ASN1_TIME* notAfter = X509_get_notAfter(x509);
4934     JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4935     return reinterpret_cast<uintptr_t>(notAfter);
4936 }
4937 
4938 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4939 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4940                                           CONSCRYPT_UNUSED jobject holder) {
4941     CHECK_ERROR_QUEUE_ON_RETURN;
4942     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4943     JNI_TRACE("X509_get_version(%p)", x509);
4944 
4945     if (x509 == nullptr) {
4946         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4947         JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
4948         return 0;
4949     }
4950 
4951     // NOLINTNEXTLINE(runtime/int)
4952     long version = X509_get_version(x509);
4953     JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4954     return version;
4955 }
4956 
4957 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4958 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4959                                             const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4960     JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4961 
4962     if (x509Type == nullptr) {
4963         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4964         JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4965         return nullptr;
4966     }
4967 
4968     const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4969     bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4970     if (serialBn.get() == nullptr) {
4971         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4972         return nullptr;
4973     }
4974 
4975     ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4976     if (env->ExceptionCheck()) {
4977         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4978         return nullptr;
4979     }
4980 
4981     JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4982     return serialArray.release();
4983 }
4984 
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4985 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4986                                                      CONSCRYPT_UNUSED jobject holder) {
4987     CHECK_ERROR_QUEUE_ON_RETURN;
4988     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4989     JNI_TRACE("X509_get_serialNumber(%p)", x509);
4990 
4991     if (x509 == nullptr) {
4992         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4993         JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
4994         return nullptr;
4995     }
4996     return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4997 }
4998 
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4999 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
5000                                                              jlong x509RevokedRef) {
5001     CHECK_ERROR_QUEUE_ON_RETURN;
5002     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5003     JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5004 
5005     if (revoked == nullptr) {
5006         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5007         JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
5008         return 0;
5009     }
5010     return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
5011 }
5012 
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5013 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
5014                                      CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5015     CHECK_ERROR_QUEUE_ON_RETURN;
5016     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5017     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5018     JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5019 
5020     if (pkey == nullptr) {
5021         JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5022         return;
5023     }
5024 
5025     if (x509 == nullptr) {
5026         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5027         JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5028         return;
5029     }
5030 
5031     if (X509_verify(x509, pkey) != 1) {
5032         conscrypt::jniutil::throwExceptionFromBoringSSLError(
5033                 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
5034         JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5035         return;
5036     }
5037     JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5038 }
5039 
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5040 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
5041                                                  CONSCRYPT_UNUSED jobject holder) {
5042     CHECK_ERROR_QUEUE_ON_RETURN;
5043     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5044     JNI_TRACE("get_X509_tbs_cert(%p)", x509);
5045     // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
5046     return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
5047 }
5048 
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5049 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
5050                                                              CONSCRYPT_UNUSED jobject holder,
5051                                                              jstring oidString) {
5052     CHECK_ERROR_QUEUE_ON_RETURN;
5053     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5054     JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
5055 
5056     if (x509 == nullptr) {
5057         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5058         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
5059         return nullptr;
5060     }
5061 
5062     bssl::UniquePtr<X509> copy(X509_dup(x509));
5063     if (copy == nullptr) {
5064         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
5065         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
5066         return nullptr;
5067     }
5068 
5069     ScopedUtfChars oid(env, oidString);
5070     if (oid.c_str() == nullptr) {
5071         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
5072         return nullptr;
5073     }
5074 
5075     bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
5076     if (obj.get() == nullptr) {
5077         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
5078                   oid.c_str());
5079         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5080                                            "Invalid OID.");
5081         ERR_clear_error();
5082         return nullptr;
5083     }
5084 
5085     int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
5086     if (extIndex == -1) {
5087         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
5088         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5089                                            "Extension not found.");
5090         return nullptr;
5091     }
5092 
5093     // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
5094     // cached encoding.
5095     X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
5096     return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
5097 }
5098 
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5099 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
5100                                            CONSCRYPT_UNUSED jobject holder) {
5101     CHECK_ERROR_QUEUE_ON_RETURN;
5102     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5103     JNI_TRACE("get_X509_ex_flags(%p)", x509);
5104 
5105     if (x509 == nullptr) {
5106         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5107         JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5108         return 0;
5109     }
5110 
5111     uint32_t flags = X509_get_extension_flags(x509);
5112     // X509_get_extension_flags sometimes leaves values in the error queue. See
5113     // https://crbug.com/boringssl/382.
5114     //
5115     // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
5116     // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
5117     // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
5118     // this JNI call to EXFLAG_CRITICAL.
5119     ERR_clear_error();
5120     return flags;
5121 }
5122 
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5123 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
5124                                            CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5125                                            CONSCRYPT_UNUSED jobject holder2) {
5126     CHECK_ERROR_QUEUE_ON_RETURN;
5127     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5128     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5129     JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5130 
5131     if (x509_1 == nullptr) {
5132         conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
5133         JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
5134         return 0;
5135     }
5136     if (x509_2 == nullptr) {
5137         conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
5138         JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
5139         return 0;
5140     }
5141     int ret = X509_check_issued(x509_1, x509_2);
5142     JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5143     return ret;
5144 }
5145 
get_X509_signature(X509 * x509)5146 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
5147     const ASN1_BIT_STRING* signature;
5148     X509_get0_signature(&signature, nullptr, x509);
5149     return signature;
5150 }
5151 
get_X509_CRL_signature(X509_CRL * crl)5152 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
5153     const ASN1_BIT_STRING* signature;
5154     X509_CRL_get0_signature(crl, &signature, nullptr);
5155     return signature;
5156 }
5157 
5158 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))5159 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
5160                                          const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
5161     JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5162 
5163     if (x509Type == nullptr) {
5164         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5165         JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5166         return nullptr;
5167     }
5168 
5169     const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
5170 
5171     ScopedLocalRef<jbyteArray> signatureArray(env,
5172                                               env->NewByteArray(ASN1_STRING_length(signature)));
5173     if (env->ExceptionCheck()) {
5174         JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5175         return nullptr;
5176     }
5177 
5178     ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5179     if (signatureBytes.get() == nullptr) {
5180         JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5181         return nullptr;
5182     }
5183 
5184     memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
5185 
5186     JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5187               ASN1_STRING_length(signature));
5188     return signatureArray.release();
5189 }
5190 
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5191 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
5192                                                   CONSCRYPT_UNUSED jobject holder) {
5193     CHECK_ERROR_QUEUE_ON_RETURN;
5194     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5195     JNI_TRACE("get_X509_signature(%p)", x509);
5196 
5197     if (x509 == nullptr) {
5198         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5199         JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
5200         return nullptr;
5201     }
5202     return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5203 }
5204 
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5205 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
5206                                                       CONSCRYPT_UNUSED jobject holder) {
5207     CHECK_ERROR_QUEUE_ON_RETURN;
5208     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5209     JNI_TRACE("get_X509_CRL_signature(%p)", crl);
5210 
5211     if (crl == nullptr) {
5212         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5213         JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
5214         return nullptr;
5215     }
5216     return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5217 }
5218 
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)5219 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
5220                                                 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
5221                                                 CONSCRYPT_UNUSED jobject holder2) {
5222     CHECK_ERROR_QUEUE_ON_RETURN;
5223     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5224     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5225     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5226 
5227     if (x509crl == nullptr) {
5228         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5229         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5230         return 0;
5231     } else if (x509 == nullptr) {
5232         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5233         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5234         return 0;
5235     }
5236 
5237     X509_REVOKED* revoked = nullptr;
5238     int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5239     if (ret == 0) {
5240         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5241         return 0;
5242     }
5243 
5244     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5245     return reinterpret_cast<uintptr_t>(revoked);
5246 }
5247 
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)5248 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
5249                                                   CONSCRYPT_UNUSED jobject holder,
5250                                                   jbyteArray serialArray) {
5251     CHECK_ERROR_QUEUE_ON_RETURN;
5252     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5253     JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5254 
5255     if (x509crl == nullptr) {
5256         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5257         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5258         return 0;
5259     }
5260 
5261     bssl::UniquePtr<BIGNUM> serialBn = arrayToBignum(env, serialArray);
5262     if (serialBn == nullptr) {
5263         if (!env->ExceptionCheck()) {
5264             conscrypt::jniutil::throwNullPointerException(env, "serial == null");
5265         }
5266         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5267         return 0;
5268     }
5269 
5270     bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
5271     if (serialInteger.get() == nullptr) {
5272         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5273         return 0;
5274     }
5275 
5276     X509_REVOKED* revoked = nullptr;
5277     int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5278     if (ret == 0) {
5279         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5280         return 0;
5281     }
5282 
5283     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5284     return reinterpret_cast<uintptr_t>(revoked);
5285 }
5286 
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5287 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
5288                                                     CONSCRYPT_UNUSED jobject holder) {
5289     CHECK_ERROR_QUEUE_ON_RETURN;
5290     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5291     JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5292 
5293     if (crl == nullptr) {
5294         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5295         JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
5296         return nullptr;
5297     }
5298 
5299     STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5300     if (stack == nullptr) {
5301         JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5302         return nullptr;
5303     }
5304 
5305     size_t size = sk_X509_REVOKED_num(stack);
5306 
5307     ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
5308     ScopedLongArrayRW revoked(env, revokedArray.get());
5309     for (size_t i = 0; i < size; i++) {
5310         X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5311         revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5312     }
5313 
5314     JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
5315     return revokedArray.release();
5316 }
5317 
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5318 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
5319                                             CONSCRYPT_UNUSED jobject holder) {
5320     CHECK_ERROR_QUEUE_ON_RETURN;
5321     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5322     JNI_TRACE("i2d_X509_CRL(%p)", crl);
5323 
5324     if (crl == nullptr) {
5325         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5326         JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
5327         return nullptr;
5328     }
5329     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
5330 }
5331 
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5332 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
5333                                        CONSCRYPT_UNUSED jobject holder) {
5334     CHECK_ERROR_QUEUE_ON_RETURN;
5335     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5336     JNI_TRACE("X509_CRL_free(%p)", crl);
5337 
5338     if (crl == nullptr) {
5339         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5340         JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5341         return;
5342     }
5343 
5344     X509_CRL_free(crl);
5345 }
5346 
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5347 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
5348                                         CONSCRYPT_UNUSED jobject holder) {
5349     CHECK_ERROR_QUEUE_ON_RETURN;
5350     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5351     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5352     JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5353 
5354     if (bio == nullptr) {
5355         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5356         JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5357         return;
5358     }
5359 
5360     if (crl == nullptr) {
5361         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5362         JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5363         return;
5364     }
5365 
5366     if (!X509_CRL_print(bio, crl)) {
5367         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
5368         JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5369         return;
5370     }
5371     JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5372 }
5373 
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5374 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5375                                                      CONSCRYPT_UNUSED jobject holder) {
5376     CHECK_ERROR_QUEUE_ON_RETURN;
5377     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5378     JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5379 
5380     if (crl == nullptr) {
5381         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5382         JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
5383         return nullptr;
5384     }
5385 
5386     const X509_ALGOR* sig_alg;
5387     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5388     const ASN1_OBJECT* oid;
5389     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5390     return ASN1_OBJECT_to_OID_string(env, oid);
5391 }
5392 
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)5393 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
5394     int param_type;
5395     const void* param_value;
5396     X509_ALGOR_get0(nullptr, &param_type, &param_value, algor);
5397 
5398     if (param_type == V_ASN1_UNDEF) {
5399         JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
5400         return nullptr;
5401     }
5402 
5403     // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
5404     // recreate it from the returned components.
5405     bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
5406     if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
5407         conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
5408         return nullptr;
5409     }
5410 
5411     return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
5412 }
5413 
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5414 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
5415                                                               CONSCRYPT_UNUSED jobject holder) {
5416     CHECK_ERROR_QUEUE_ON_RETURN;
5417     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5418     JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5419 
5420     if (crl == nullptr) {
5421         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5422         JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5423         return nullptr;
5424     }
5425 
5426     const X509_ALGOR* sig_alg;
5427     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5428     return get_X509_ALGOR_parameter(env, sig_alg);
5429 }
5430 
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5431 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
5432                                                         CONSCRYPT_UNUSED jobject holder) {
5433     CHECK_ERROR_QUEUE_ON_RETURN;
5434     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5435 
5436     if (crl == nullptr) {
5437         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5438         JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
5439         return nullptr;
5440     }
5441     JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5442     return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
5443 }
5444 
5445 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5446 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
5447                                               CONSCRYPT_UNUSED jobject holder) {
5448     CHECK_ERROR_QUEUE_ON_RETURN;
5449     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5450     JNI_TRACE("X509_CRL_get_version(%p)", crl);
5451 
5452     if (crl == nullptr) {
5453         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5454         JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
5455         return 0;
5456     }
5457     // NOLINTNEXTLINE(runtime/int)
5458     long version = X509_CRL_get_version(crl);
5459     JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5460     return version;
5461 }
5462 
5463 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5464           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)5465 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
5466     JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5467 
5468     if (x509Type == nullptr) {
5469         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5470         return nullptr;
5471     }
5472 
5473     ScopedUtfChars oid(env, oidString);
5474     if (oid.c_str() == nullptr) {
5475         return nullptr;
5476     }
5477 
5478     bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
5479     if (asn1.get() == nullptr) {
5480         JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5481         ERR_clear_error();
5482         return nullptr;
5483     }
5484 
5485     int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5486     if (extIndex == -1) {
5487         JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5488         return nullptr;
5489     }
5490 
5491     X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5492     JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5493     return ext;
5494 }
5495 
5496 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5497           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)5498 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
5499     X509_EXTENSION* ext =
5500             X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
5501     if (ext == nullptr) {
5502         JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5503         return nullptr;
5504     }
5505 
5506     JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
5507               X509_EXTENSION_get_data(ext));
5508     return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
5509                                               i2d_ASN1_OCTET_STRING);
5510 }
5511 
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)5512 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
5513                                            CONSCRYPT_UNUSED jobject holder, jstring oid) {
5514     CHECK_ERROR_QUEUE_ON_RETURN;
5515     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5516     JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5517 
5518     if (crl == nullptr) {
5519         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5520         JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
5521         return 0;
5522     }
5523     X509_EXTENSION* ext =
5524             X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
5525     JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5526     return reinterpret_cast<uintptr_t>(ext);
5527 }
5528 
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)5529 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5530                                                jstring oid) {
5531     CHECK_ERROR_QUEUE_ON_RETURN;
5532     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5533     JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5534     X509_EXTENSION* ext =
5535             X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5536                     env, revoked, oid);
5537     JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5538     return reinterpret_cast<uintptr_t>(ext);
5539 }
5540 
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)5541 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5542     CHECK_ERROR_QUEUE_ON_RETURN;
5543     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5544     JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5545 
5546     if (revoked == nullptr) {
5547         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5548         JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5549         return 0;
5550     }
5551 
5552     X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5553     JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5554     return reinterpret_cast<uintptr_t>(dup);
5555 }
5556 
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5557 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5558                                                           jlong x509RevokedRef) {
5559     CHECK_ERROR_QUEUE_ON_RETURN;
5560     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5561     JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5562 
5563     if (revoked == nullptr) {
5564         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5565         JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5566         return 0;
5567     }
5568 
5569     JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5570               X509_REVOKED_get0_revocationDate(revoked));
5571     return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5572 }
5573 
5574 #ifdef __GNUC__
5575 #pragma GCC diagnostic push
5576 #pragma GCC diagnostic ignored "-Wwrite-strings"
5577 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5578 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5579                                             jlong x509RevokedRef) {
5580     CHECK_ERROR_QUEUE_ON_RETURN;
5581     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5582     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5583     JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5584 
5585     if (bio == nullptr) {
5586         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5587         JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5588         return;
5589     }
5590 
5591     if (revoked == nullptr) {
5592         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5593         JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5594         return;
5595     }
5596 
5597     BIO_printf(bio, "Serial Number: ");
5598     i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5599     BIO_printf(bio, "\nRevocation Date: ");
5600     ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5601     BIO_printf(bio, "\n");
5602     // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5603     // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5604     X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5605                             0);
5606 }
5607 #ifndef _WIN32
5608 #pragma GCC diagnostic pop
5609 #endif
5610 
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5611 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5612                                                     CONSCRYPT_UNUSED jobject holder) {
5613     CHECK_ERROR_QUEUE_ON_RETURN;
5614     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5615     JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5616 
5617     if (crl == nullptr) {
5618         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5619         JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5620         return nullptr;
5621     }
5622     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5623 }
5624 
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5625 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5626                                          CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5627     CHECK_ERROR_QUEUE_ON_RETURN;
5628     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5629     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5630     JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5631 
5632     if (pkey == nullptr) {
5633         JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5634         return;
5635     }
5636 
5637     if (crl == nullptr) {
5638         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5639         JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5640         return;
5641     }
5642 
5643     if (X509_CRL_verify(crl, pkey) != 1) {
5644         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5645         JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5646         return;
5647     }
5648     JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5649 }
5650 
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5651 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5652                                                   CONSCRYPT_UNUSED jobject holder) {
5653     CHECK_ERROR_QUEUE_ON_RETURN;
5654     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5655     JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5656 
5657     if (crl == nullptr) {
5658         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5659         JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5660         return 0;
5661     }
5662 
5663     ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5664     JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5665     return reinterpret_cast<uintptr_t>(lastUpdate);
5666 }
5667 
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5668 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5669                                                   CONSCRYPT_UNUSED jobject holder) {
5670     CHECK_ERROR_QUEUE_ON_RETURN;
5671     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5672     JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5673 
5674     if (crl == nullptr) {
5675         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5676         JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5677         return 0;
5678     }
5679 
5680     ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5681     JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5682     return reinterpret_cast<uintptr_t>(nextUpdate);
5683 }
5684 
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5685 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5686     CHECK_ERROR_QUEUE_ON_RETURN;
5687     X509_REVOKED* x509Revoked =
5688             reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5689     JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5690     return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5691 }
5692 
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5693 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5694     CHECK_ERROR_QUEUE_ON_RETURN;
5695     X509_EXTENSION* ext =
5696             reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5697 
5698     if (ext == nullptr) {
5699         conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5700         return 0;
5701     }
5702 
5703     return X509_supported_extension(ext);
5704 }
5705 
decimal_to_integer(const char * data,size_t len,int * out)5706 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5707     int ret = 0;
5708     for (size_t i = 0; i < len; i++) {
5709         ret *= 10;
5710         if (data[i] < '0' || data[i] > '9') {
5711             return false;
5712         }
5713         ret += data[i] - '0';
5714     }
5715     *out = ret;
5716     return true;
5717 }
5718 
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5719 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5720                                                jobject calendar) {
5721     CHECK_ERROR_QUEUE_ON_RETURN;
5722     ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5723     JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5724 
5725     if (asn1Time == nullptr) {
5726         conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5727         return;
5728     }
5729 
5730     if (!ASN1_TIME_check(asn1Time)) {
5731         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5732         return;
5733     }
5734 
5735     bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5736     if (gen.get() == nullptr) {
5737         conscrypt::jniutil::throwParsingException(env,
5738                                                   "ASN1_TIME_to_generalizedtime returned null");
5739         return;
5740     }
5741 
5742     if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5743         conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5744         return;
5745     }
5746 
5747     int year, mon, mday, hour, min, sec;
5748     const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5749     if (!decimal_to_integer(data, 4, &year) ||
5750         !decimal_to_integer(data + 4, 2, &mon) ||
5751         !decimal_to_integer(data + 6, 2, &mday) ||
5752         !decimal_to_integer(data + 8, 2, &hour) ||
5753         !decimal_to_integer(data + 10, 2, &min) ||
5754         !decimal_to_integer(data + 12, 2, &sec)) {
5755         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5756         return;
5757     }
5758 
5759     env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5760                         min, sec);
5761 }
5762 
5763 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5764 // functions so that they can be freed properly when finished.  This struct owns
5765 // all objects pointed to by its members.
5766 struct CbsHandle {
5767     // A pointer to the CBS.
5768     std::unique_ptr<CBS> cbs;
5769     // A pointer to the data held by the CBS.  If the data held by the CBS
5770     // is owned by a different CbsHandle, data will be null.
5771     std::unique_ptr<unsigned char[]> data;
5772 };
5773 
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5774 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5775     CHECK_ERROR_QUEUE_ON_RETURN;
5776     JNI_TRACE("asn1_read_init(%p)", data);
5777 
5778     ScopedByteArrayRO bytes(env, data);
5779     if (bytes.get() == nullptr) {
5780         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5781         return 0;
5782     }
5783 
5784     std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5785     cbs->data.reset(new unsigned char[bytes.size()]);
5786     memcpy(cbs->data.get(), bytes.get(), bytes.size());
5787 
5788     cbs->cbs.reset(new CBS());
5789     CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5790     JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5791     return reinterpret_cast<uintptr_t>(cbs.release());
5792 }
5793 
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5794 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5795     CHECK_ERROR_QUEUE_ON_RETURN;
5796     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5797     JNI_TRACE("asn1_read_sequence(%p)", cbs);
5798 
5799     std::unique_ptr<CbsHandle> seq(new CbsHandle());
5800     seq->cbs.reset(new CBS());
5801     if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5802         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5803         return 0;
5804     }
5805     JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5806     return reinterpret_cast<uintptr_t>(seq.release());
5807 }
5808 
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5809 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5810                                                    jlong cbsRef, jint tag) {
5811     CHECK_ERROR_QUEUE_ON_RETURN;
5812     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5813     JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5814 
5815     int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5816                                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5817     JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5818     return result ? JNI_TRUE : JNI_FALSE;
5819 }
5820 
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5821 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5822     CHECK_ERROR_QUEUE_ON_RETURN;
5823     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5824     JNI_TRACE("asn1_read_tagged(%p)", cbs);
5825 
5826     std::unique_ptr<CbsHandle> tag(new CbsHandle());
5827     tag->cbs.reset(new CBS());
5828     if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5829         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5830         return 0;
5831     }
5832     JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5833     return reinterpret_cast<uintptr_t>(tag.release());
5834 }
5835 
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5836 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5837     CHECK_ERROR_QUEUE_ON_RETURN;
5838     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5839     JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5840 
5841     std::unique_ptr<CBS> str(new CBS());
5842     if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5843         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5844         return 0;
5845     }
5846     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5847     if (out.get() == nullptr) {
5848         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5849         return 0;
5850     }
5851     ScopedByteArrayRW outBytes(env, out.get());
5852     if (outBytes.get() == nullptr) {
5853         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5854         return 0;
5855     }
5856     memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5857     JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5858     return out.release();
5859 }
5860 
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5861 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5862     CHECK_ERROR_QUEUE_ON_RETURN;
5863     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5864     JNI_TRACE("asn1_read_uint64(%p)", cbs);
5865 
5866     // NOLINTNEXTLINE(runtime/int)
5867     uint64_t value;
5868     if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5869         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5870         return 0;
5871     }
5872     return value;
5873 }
5874 
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5875 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5876     CHECK_ERROR_QUEUE_ON_RETURN;
5877     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5878     JNI_TRACE("asn1_read_null(%p)", cbs);
5879 
5880     CBS null_holder;
5881     if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5882         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5883     }
5884 }
5885 
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5886 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5887     CHECK_ERROR_QUEUE_ON_RETURN;
5888     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5889     JNI_TRACE("asn1_read_oid(%p)", cbs);
5890 
5891     CBS oid_cbs;
5892     if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5893         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5894         return nullptr;
5895     }
5896     int nid = OBJ_cbs2nid(&oid_cbs);
5897     if (nid == NID_undef) {
5898         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5899         return nullptr;
5900     }
5901     const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5902     if (obj == nullptr) {
5903         conscrypt::jniutil::throwIOException(env,
5904                                              "Error reading ASN.1 encoding: "
5905                                              "Could not find ASN1_OBJECT for NID");
5906         return nullptr;
5907     }
5908     return ASN1_OBJECT_to_OID_string(env, obj);
5909 }
5910 
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5911 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5912                                                 jlong cbsRef) {
5913     CHECK_ERROR_QUEUE_ON_RETURN;
5914     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5915     JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5916 
5917     bool empty = (CBS_len(cbs->cbs.get()) == 0);
5918     JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5919     return empty;
5920 }
5921 
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5922 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5923     CHECK_ERROR_QUEUE_ON_RETURN;
5924     if (cbsRef == 0) {
5925         JNI_TRACE("asn1_read_free(0)");
5926         return;
5927     }
5928     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5929     JNI_TRACE("asn1_read_free(%p)", cbs);
5930     delete cbs;
5931 }
5932 
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5933 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5934     CHECK_ERROR_QUEUE_ON_RETURN;
5935     JNI_TRACE("asn1_write_init");
5936     std::unique_ptr<CBB> cbb(new CBB());
5937     if (!CBB_init(cbb.get(), 128)) {
5938         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5939         return 0;
5940     }
5941     JNI_TRACE("asn1_write_init => %p", cbb.get());
5942     return reinterpret_cast<uintptr_t>(cbb.release());
5943 }
5944 
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5945 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5946     CHECK_ERROR_QUEUE_ON_RETURN;
5947     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5948     JNI_TRACE("asn1_write_sequence(%p)", cbb);
5949 
5950     std::unique_ptr<CBB> seq(new CBB());
5951     if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5952         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5953         return 0;
5954     }
5955     JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5956     return reinterpret_cast<uintptr_t>(seq.release());
5957 }
5958 
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5959 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5960     CHECK_ERROR_QUEUE_ON_RETURN;
5961     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5962     JNI_TRACE("asn1_write_tag(%p)", cbb);
5963 
5964     std::unique_ptr<CBB> tag_holder(new CBB());
5965     if (!CBB_add_asn1(cbb, tag_holder.get(),
5966                       CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5967         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5968         return 0;
5969     }
5970     JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5971     return reinterpret_cast<uintptr_t>(tag_holder.release());
5972 }
5973 
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5974 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5975                                                 jbyteArray data) {
5976     CHECK_ERROR_QUEUE_ON_RETURN;
5977     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5978     JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5979 
5980     ScopedByteArrayRO bytes(env, data);
5981     if (bytes.get() == nullptr) {
5982         JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5983         return;
5984     }
5985 
5986     std::unique_ptr<CBB> octetstring(new CBB());
5987     if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5988         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5989         return;
5990     }
5991     if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5992                        bytes.size())) {
5993         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5994         return;
5995     }
5996     if (!CBB_flush(cbb)) {
5997         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5998         return;
5999     }
6000 }
6001 
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)6002 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
6003     CHECK_ERROR_QUEUE_ON_RETURN;
6004     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6005     JNI_TRACE("asn1_write_uint64(%p)", cbb);
6006 
6007     if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
6008         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6009         return;
6010     }
6011 }
6012 
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)6013 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
6014     CHECK_ERROR_QUEUE_ON_RETURN;
6015     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6016     JNI_TRACE("asn1_write_null(%p)", cbb);
6017 
6018     CBB null_holder;
6019     if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
6020         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6021         return;
6022     }
6023     if (!CBB_flush(cbb)) {
6024         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6025         return;
6026     }
6027 }
6028 
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)6029 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
6030     CHECK_ERROR_QUEUE_ON_RETURN;
6031     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6032     JNI_TRACE("asn1_write_oid(%p)", cbb);
6033 
6034     ScopedUtfChars oid_chars(env, oid);
6035     if (oid_chars.c_str() == nullptr) {
6036         return;
6037     }
6038 
6039     int nid = OBJ_txt2nid(oid_chars.c_str());
6040     if (nid == NID_undef) {
6041         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6042         return;
6043     }
6044 
6045     if (!OBJ_nid2cbb(cbb, nid)) {
6046         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6047         return;
6048     }
6049 }
6050 
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)6051 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
6052     CHECK_ERROR_QUEUE_ON_RETURN;
6053     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6054     JNI_TRACE("asn1_write_flush(%p)", cbb);
6055 
6056     if (!CBB_flush(cbb)) {
6057         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6058         return;
6059     }
6060 }
6061 
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)6062 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
6063     CHECK_ERROR_QUEUE_ON_RETURN;
6064     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6065     JNI_TRACE("asn1_write_finish(%p)", cbb);
6066 
6067     uint8_t* data;
6068     size_t data_len;
6069     if (!CBB_finish(cbb, &data, &data_len)) {
6070         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6071         return 0;
6072     }
6073     bssl::UniquePtr<uint8_t> data_storage(data);
6074     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
6075     if (out.get() == nullptr) {
6076         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6077         return 0;
6078     }
6079     ScopedByteArrayRW outBytes(env, out.get());
6080     if (outBytes.get() == nullptr) {
6081         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6082         return 0;
6083     }
6084     memcpy(outBytes.get(), data, data_len);
6085     return out.release();
6086 }
6087 
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6088 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6089     CHECK_ERROR_QUEUE_ON_RETURN;
6090     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6091     JNI_TRACE("asn1_write_cleanup(%p)", cbb);
6092 
6093     CBB_cleanup(cbb);
6094 }
6095 
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6096 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6097     CHECK_ERROR_QUEUE_ON_RETURN;
6098     if (cbbRef == 0) {
6099         JNI_TRACE("asn1_write_free(0)");
6100         return;
6101     }
6102     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6103     JNI_TRACE("asn1_write_free(%p)", cbb);
6104     delete cbb;
6105 }
6106 
6107 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)6108 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6109     BIO* bio = to_BIO(env, bioRef);
6110     JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
6111 
6112     if (bio == nullptr) {
6113         return 0;
6114     }
6115 
6116     T* x = d2i_func(bio, nullptr);
6117     if (x == nullptr) {
6118         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
6119         return 0;
6120     }
6121 
6122     return reinterpret_cast<uintptr_t>(x);
6123 }
6124 
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)6125 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
6126     CHECK_ERROR_QUEUE_ON_RETURN;
6127     return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
6128 }
6129 
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)6130 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6131     CHECK_ERROR_QUEUE_ON_RETURN;
6132     return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
6133 }
6134 
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)6135 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
6136     CHECK_ERROR_QUEUE_ON_RETURN;
6137     ScopedByteArrayRO bytes(env, certBytes);
6138     if (bytes.get() == nullptr) {
6139         JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
6140         return 0;
6141     }
6142 
6143     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
6144     // NOLINTNEXTLINE(runtime/int)
6145     X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
6146     if (x == nullptr) {
6147         conscrypt::jniutil::throwExceptionFromBoringSSLError(
6148                 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
6149         return 0;
6150     }
6151     return reinterpret_cast<uintptr_t>(x);
6152 }
6153 
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6154 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
6155                                         CONSCRYPT_UNUSED jobject holder) {
6156     CHECK_ERROR_QUEUE_ON_RETURN;
6157     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6158     JNI_TRACE("i2d_X509(%p)", x509);
6159 
6160     if (x509 == nullptr) {
6161         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6162         JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
6163         return nullptr;
6164     }
6165     return ASN1ToByteArray<X509>(env, x509, i2d_X509);
6166 }
6167 
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6168 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
6169                                                CONSCRYPT_UNUSED jobject holder) {
6170     CHECK_ERROR_QUEUE_ON_RETURN;
6171     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6172     JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
6173 
6174     if (x509 == nullptr) {
6175         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6176         JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
6177         return nullptr;
6178     }
6179     return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
6180 }
6181 
6182 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)6183 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
6184     BIO* bio = to_BIO(env, bioRef);
6185     JNI_TRACE("PEM_to_jlong(%p)", bio);
6186 
6187     if (bio == nullptr) {
6188         JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
6189         return 0;
6190     }
6191 
6192     T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
6193     if (x == nullptr) {
6194         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
6195         JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
6196         return 0;
6197     }
6198 
6199     JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
6200     return reinterpret_cast<uintptr_t>(x);
6201 }
6202 
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)6203 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
6204     CHECK_ERROR_QUEUE_ON_RETURN;
6205     // NOLINTNEXTLINE(runtime/int)
6206     JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
6207     return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
6208 }
6209 
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)6210 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
6211     CHECK_ERROR_QUEUE_ON_RETURN;
6212     // NOLINTNEXTLINE(runtime/int)
6213     JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
6214     return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
6215 }
6216 
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)6217 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
6218     CHECK_ERROR_QUEUE_ON_RETURN;
6219     // NOLINTNEXTLINE(runtime/int)
6220     JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
6221     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
6222 }
6223 
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)6224 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
6225     CHECK_ERROR_QUEUE_ON_RETURN;
6226     // NOLINTNEXTLINE(runtime/int)
6227     JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
6228     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
6229 }
6230 
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)6231 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
6232     if (certs == nullptr) {
6233         return nullptr;
6234     }
6235 
6236     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6237     size_t size = sk_X509_num(certs);
6238     ref_array.reset(env->NewLongArray(size));
6239     ScopedLongArrayRW items(env, ref_array.get());
6240     for (size_t i = 0; i < size; i++) {
6241         X509* cert = sk_X509_value(certs, i);
6242         X509_up_ref(cert);
6243         items[i] = reinterpret_cast<uintptr_t>(cert);
6244     }
6245 
6246     JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
6247     return ref_array.release();
6248 }
6249 
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)6250 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
6251     if (crls == nullptr) {
6252         return nullptr;
6253     }
6254 
6255     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6256     size_t size = sk_X509_CRL_num(crls);
6257     ref_array.reset(env->NewLongArray(size));
6258     ScopedLongArrayRW items(env, ref_array.get());
6259     for (size_t i = 0; i < size; i++) {
6260         X509_CRL* crl = sk_X509_CRL_value(crls, i);
6261         X509_CRL_up_ref(crl);
6262         items[i] = reinterpret_cast<uintptr_t>(crl);
6263     }
6264 
6265     JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
6266     return ref_array.release();
6267 }
6268 
6269 #define PKCS7_CERTS 1
6270 #define PKCS7_CRLS 2
6271 
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)6272 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
6273     CHECK_ERROR_QUEUE_ON_RETURN;
6274     STACK_OF(X509)* stack = sk_X509_new_null();
6275 
6276     ScopedLongArrayRO certs(env, certsArray);
6277     for (size_t i = 0; i < certs.size(); i++) {
6278         X509* item = reinterpret_cast<X509*>(certs[i]);
6279         if (sk_X509_push(stack, item) == 0) {
6280             sk_X509_free(stack);
6281             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
6282             return nullptr;
6283         }
6284     }
6285 
6286     bssl::ScopedCBB out;
6287     CBB_init(out.get(), 1024 * certs.size());
6288     if (!PKCS7_bundle_certificates(out.get(), stack)) {
6289         sk_X509_free(stack);
6290         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
6291         return nullptr;
6292     }
6293 
6294     sk_X509_free(stack);
6295 
6296     return CBBToByteArray(env, out.get());
6297 }
6298 
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)6299 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
6300     CHECK_ERROR_QUEUE_ON_RETURN;
6301     BIO* bio = to_BIO(env, bioRef);
6302     JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
6303 
6304     if (bio == nullptr) {
6305         JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
6306         return nullptr;
6307     }
6308 
6309     if (which == PKCS7_CERTS) {
6310         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6311         if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
6312             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
6313             return nullptr;
6314         }
6315         return X509s_to_ItemArray(env, outCerts.get());
6316     } else if (which == PKCS7_CRLS) {
6317         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6318         if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
6319             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
6320             return nullptr;
6321         }
6322         return X509_CRLs_to_ItemArray(env, outCRLs.get());
6323     } else {
6324         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6325         return nullptr;
6326     }
6327 }
6328 
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)6329 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
6330     CHECK_ERROR_QUEUE_ON_RETURN;
6331     BIO* bio = to_BIO(env, bioRef);
6332     JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
6333 
6334     if (bio == nullptr) {
6335         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
6336         return nullptr;
6337     }
6338 
6339     uint8_t* data;
6340     size_t len;
6341     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6342         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
6343                 conscrypt::jniutil::throwParsingException);
6344         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
6345         return nullptr;
6346     }
6347     bssl::UniquePtr<uint8_t> data_storage(data);
6348 
6349     CBS cbs;
6350     CBS_init(&cbs, data, len);
6351 
6352     if (which == PKCS7_CERTS) {
6353         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6354         if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
6355             conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
6356                     "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
6357             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
6358             return nullptr;
6359         }
6360         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
6361         return X509s_to_ItemArray(env, outCerts.get());
6362     } else if (which == PKCS7_CRLS) {
6363         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6364         if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
6365             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
6366                     conscrypt::jniutil::throwParsingException);
6367             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
6368             return nullptr;
6369         }
6370         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
6371         return X509_CRLs_to_ItemArray(env, outCRLs.get());
6372     } else {
6373         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6374         return nullptr;
6375     }
6376 }
6377 
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)6378 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6379     CHECK_ERROR_QUEUE_ON_RETURN;
6380     BIO* bio = to_BIO(env, bioRef);
6381     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
6382 
6383     if (bio == nullptr) {
6384         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
6385         return nullptr;
6386     }
6387 
6388     uint8_t* data;
6389     size_t len;
6390     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6391         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
6392                 conscrypt::jniutil::throwParsingException);
6393         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
6394         return nullptr;
6395     }
6396     bssl::UniquePtr<uint8_t> data_storage(data);
6397 
6398     bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
6399     if (path.get() == nullptr) {
6400         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
6401         return nullptr;
6402     }
6403 
6404     CBS cbs, sequence;
6405     CBS_init(&cbs, data, len);
6406     if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
6407         conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6408         ERR_clear_error();
6409         return nullptr;
6410     }
6411 
6412     while (CBS_len(&sequence) > 0) {
6413         CBS child;
6414         if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
6415             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6416             ERR_clear_error();
6417             return nullptr;
6418         }
6419 
6420         const uint8_t* tmp = CBS_data(&child);
6421         // NOLINTNEXTLINE(runtime/int)
6422         bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
6423         if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
6424             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6425             ERR_clear_error();
6426             return nullptr;
6427         }
6428 
6429         if (!sk_X509_push(path.get(), cert.get())) {
6430             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
6431             return nullptr;
6432         }
6433         OWNERSHIP_TRANSFERRED(cert);
6434     }
6435 
6436     size_t size = sk_X509_num(path.get());
6437 
6438     ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
6439     ScopedLongArrayRW certs(env, certArray.get());
6440     for (size_t i = 0; i < size; i++) {
6441         X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
6442         certs[i] = reinterpret_cast<uintptr_t>(item);
6443     }
6444 
6445     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
6446     return certArray.release();
6447 }
6448 
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)6449 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
6450     CHECK_ERROR_QUEUE_ON_RETURN;
6451     JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
6452     ScopedLongArrayRO certsArray(env, certs);
6453     if (certsArray.get() == nullptr) {
6454         JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
6455         return nullptr;
6456     }
6457 
6458     bssl::ScopedCBB result;
6459     CBB seq_contents;
6460     if (!CBB_init(result.get(), 2048 * certsArray.size())) {
6461         JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
6462         return nullptr;
6463     }
6464     if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
6465         return nullptr;
6466     }
6467 
6468     for (size_t i = 0; i < certsArray.size(); i++) {
6469         X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
6470         uint8_t* buf;
6471         int len = i2d_X509(x509, nullptr);
6472 
6473         if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
6474             i2d_X509(x509, &buf) < 0) {
6475             return nullptr;
6476         }
6477     }
6478 
6479     return CBBToByteArray(env, result.get());
6480 }
6481 
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6482 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
6483                                    CONSCRYPT_UNUSED jobject holder) {
6484     CHECK_ERROR_QUEUE_ON_RETURN;
6485     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6486     JNI_TRACE("X509_free(%p)", x509);
6487 
6488     if (x509 == nullptr) {
6489         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6490         JNI_TRACE("X509_free(%p) => x509 == null", x509);
6491         return;
6492     }
6493 
6494     X509_free(x509);
6495 }
6496 
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)6497 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
6498                                   CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
6499                                   CONSCRYPT_UNUSED jobject holder2) {
6500     CHECK_ERROR_QUEUE_ON_RETURN;
6501     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
6502     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
6503     JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
6504 
6505     if (x509_1 == nullptr) {
6506         conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
6507         JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
6508         return -1;
6509     }
6510 
6511     if (x509_2 == nullptr) {
6512         conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
6513         JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
6514         return -1;
6515     }
6516 
6517     int ret = X509_cmp(x509_1, x509_2);
6518     JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6519     return ret;
6520 }
6521 
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)6522 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6523                                        CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
6524                                        jlong certflagJava) {
6525     CHECK_ERROR_QUEUE_ON_RETURN;
6526     BIO* bio = to_BIO(env, bioRef);
6527     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6528     // NOLINTNEXTLINE(runtime/int)
6529     unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
6530     // NOLINTNEXTLINE(runtime/int)
6531     unsigned long certflag = static_cast<unsigned long>(certflagJava);
6532     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6533 
6534     if (bio == nullptr) {
6535         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6536         return;
6537     }
6538 
6539     if (x509 == nullptr) {
6540         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6541         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6542         return;
6543     }
6544 
6545     if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6546         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
6547         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6548         return;
6549     }
6550     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6551 }
6552 
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6553 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
6554                                           CONSCRYPT_UNUSED jobject holder) {
6555     CHECK_ERROR_QUEUE_ON_RETURN;
6556     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6557     JNI_TRACE("X509_get_pubkey(%p)", x509);
6558 
6559     if (x509 == nullptr) {
6560         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6561         JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6562         return 0;
6563     }
6564 
6565     bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6566     if (pkey.get() == nullptr) {
6567         const uint32_t last_error = ERR_peek_last_error();
6568         const uint32_t first_error = ERR_peek_error();
6569         if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6570              ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6571             (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6572              ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6573             ERR_clear_error();
6574             conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6575             return 0;
6576         }
6577 
6578         conscrypt::jniutil::throwExceptionFromBoringSSLError(
6579                 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6580         return 0;
6581     }
6582 
6583     JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6584     return reinterpret_cast<uintptr_t>(pkey.release());
6585 }
6586 
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6587 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6588                                                     CONSCRYPT_UNUSED jobject holder) {
6589     CHECK_ERROR_QUEUE_ON_RETURN;
6590     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6591     JNI_TRACE("X509_get_issuer_name(%p)", x509);
6592 
6593     if (x509 == nullptr) {
6594         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6595         JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6596         return nullptr;
6597     }
6598     return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6599 }
6600 
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6601 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6602                                                      CONSCRYPT_UNUSED jobject holder) {
6603     CHECK_ERROR_QUEUE_ON_RETURN;
6604     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6605     JNI_TRACE("X509_get_subject_name(%p)", x509);
6606 
6607     if (x509 == nullptr) {
6608         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6609         JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6610         return nullptr;
6611     }
6612     return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6613 }
6614 
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6615 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6616                                                 CONSCRYPT_UNUSED jobject holder) {
6617     CHECK_ERROR_QUEUE_ON_RETURN;
6618     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6619     JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6620 
6621     if (x509 == nullptr) {
6622         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6623         JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6624         return nullptr;
6625     }
6626 
6627     X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6628     ASN1_OBJECT* algorithm;
6629     X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6630     return ASN1_OBJECT_to_OID_string(env, algorithm);
6631 }
6632 
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6633 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6634                                                  CONSCRYPT_UNUSED jobject holder) {
6635     CHECK_ERROR_QUEUE_ON_RETURN;
6636     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6637     JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6638 
6639     if (x509 == nullptr) {
6640         conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6641         JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6642         return nullptr;
6643     }
6644 
6645     const X509_ALGOR* sig_alg;
6646     X509_get0_signature(nullptr, &sig_alg, x509);
6647     const ASN1_OBJECT* oid;
6648     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6649     return ASN1_OBJECT_to_OID_string(env, oid);
6650 }
6651 
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6652 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6653                                                           CONSCRYPT_UNUSED jobject holder) {
6654     CHECK_ERROR_QUEUE_ON_RETURN;
6655     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6656     JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6657 
6658     if (x509 == nullptr) {
6659         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6660         JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6661         return nullptr;
6662     }
6663 
6664     const X509_ALGOR* sig_alg;
6665     X509_get0_signature(nullptr, &sig_alg, x509);
6666     return get_X509_ALGOR_parameter(env, sig_alg);
6667 }
6668 
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6669 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6670                                                      CONSCRYPT_UNUSED jobject holder) {
6671     CHECK_ERROR_QUEUE_ON_RETURN;
6672     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6673     JNI_TRACE("get_X509_issuerUID(%p)", x509);
6674 
6675     if (x509 == nullptr) {
6676         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6677         JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6678         return nullptr;
6679     }
6680 
6681     const ASN1_BIT_STRING* issuer_uid;
6682     X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6683     if (issuer_uid == nullptr) {
6684         JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6685         return nullptr;
6686     }
6687 
6688     return ASN1BitStringToBooleanArray(env, issuer_uid);
6689 }
6690 
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6691 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6692                                                       CONSCRYPT_UNUSED jobject holder) {
6693     CHECK_ERROR_QUEUE_ON_RETURN;
6694     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6695     JNI_TRACE("get_X509_subjectUID(%p)", x509);
6696 
6697     if (x509 == nullptr) {
6698         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6699         JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6700         return nullptr;
6701     }
6702 
6703     const ASN1_BIT_STRING* subject_uid;
6704     X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6705     if (subject_uid == nullptr) {
6706         JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6707         return nullptr;
6708     }
6709 
6710     return ASN1BitStringToBooleanArray(env, subject_uid);
6711 }
6712 
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6713 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6714                                                      CONSCRYPT_UNUSED jobject holder) {
6715     CHECK_ERROR_QUEUE_ON_RETURN;
6716     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6717     JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6718 
6719     if (x509 == nullptr) {
6720         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6721         JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6722         return nullptr;
6723     }
6724 
6725     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6726     // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6727     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6728     bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6729             static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6730     if (bitStr.get() == nullptr) {
6731         JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6732         ERR_clear_error();
6733         return nullptr;
6734     }
6735 
6736     return ASN1BitStringToBooleanArray(env, bitStr.get());
6737 }
6738 
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6739 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6740                                                      CONSCRYPT_UNUSED jobject holder) {
6741     CHECK_ERROR_QUEUE_ON_RETURN;
6742     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6743     JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6744 
6745     if (x509 == nullptr) {
6746         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6747         JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6748         return nullptr;
6749     }
6750 
6751     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6752     // |ERR_clear_error|, and throw CertificateParsingException.
6753     bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6754             X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6755     if (objArray.get() == nullptr) {
6756         JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6757         ERR_clear_error();
6758         return nullptr;
6759     }
6760 
6761     size_t size = sk_ASN1_OBJECT_num(objArray.get());
6762     ScopedLocalRef<jobjectArray> exKeyUsage(
6763             env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6764                                      nullptr));
6765     if (exKeyUsage.get() == nullptr) {
6766         return nullptr;
6767     }
6768 
6769     for (size_t i = 0; i < size; i++) {
6770         ScopedLocalRef<jstring> oidStr(
6771                 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6772         env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6773     }
6774 
6775     JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6776     return exKeyUsage.release();
6777 }
6778 
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6779 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6780                                              CONSCRYPT_UNUSED jobject holder) {
6781     CHECK_ERROR_QUEUE_ON_RETURN;
6782     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6783     JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6784 
6785     if (x509 == nullptr) {
6786         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6787         JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6788         return 0;
6789     }
6790 
6791     // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6792     // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6793     // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6794     // the constructor even if |EXFLAG_INVALID| is set.
6795     //
6796     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6797     // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6798     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6799     bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6800             X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6801     if (basic_constraints == nullptr) {
6802         JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6803         ERR_clear_error();
6804         return -1;
6805     }
6806 
6807     if (basic_constraints->pathlen == nullptr) {
6808         JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6809         return -1;
6810     }
6811 
6812     if (!basic_constraints->ca) {
6813         // Path length constraints are only valid for CA certificates.
6814         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6815         JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6816         return -1;
6817     }
6818 
6819     if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6820         // Path length constraints may not be negative.
6821         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6822         JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6823         return -1;
6824     }
6825 
6826     long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6827     if (pathlen == -1 || pathlen > INT_MAX) {
6828         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6829         // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6830         // constraint is plausible, but Chromium rejects all values above 255.
6831         JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6832         return -1;
6833     }
6834 
6835     JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6836     return pathlen;
6837 }
6838 
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6839 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6840                                                 CONSCRYPT_UNUSED jobject holder,
6841                                                 jstring oidString) {
6842     CHECK_ERROR_QUEUE_ON_RETURN;
6843     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6844     JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6845     return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6846 }
6847 
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6848 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6849                                                     CONSCRYPT_UNUSED jobject holder,
6850                                                     jstring oidString) {
6851     CHECK_ERROR_QUEUE_ON_RETURN;
6852     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6853     JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6854 
6855     if (crl == nullptr) {
6856         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
6857         JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
6858         return nullptr;
6859     }
6860     return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6861                                                                                      oidString);
6862 }
6863 
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6864 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6865                                                         jstring oidString) {
6866     CHECK_ERROR_QUEUE_ON_RETURN;
6867     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6868     JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6869 
6870     if (revoked == nullptr) {
6871         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
6872         JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
6873         return nullptr;
6874     }
6875     return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6876             env, revoked, oidString);
6877 }
6878 
6879 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6880           X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6881 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6882     T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6883     JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6884 
6885     if (x509 == nullptr) {
6886         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6887         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6888         return nullptr;
6889     }
6890 
6891     int lastPos = -1;
6892     int count = 0;
6893     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6894         count++;
6895     }
6896 
6897     JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6898 
6899     ScopedLocalRef<jobjectArray> joa(
6900             env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6901     if (joa.get() == nullptr) {
6902         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6903         return nullptr;
6904     }
6905 
6906     lastPos = -1;
6907     count = 0;
6908     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6909         X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6910 
6911         ScopedLocalRef<jstring> extOid(
6912                 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6913         if (extOid.get() == nullptr) {
6914             JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6915             return nullptr;
6916         }
6917 
6918         env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6919     }
6920 
6921     JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6922     return joa.release();
6923 }
6924 
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6925 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6926                                                    CONSCRYPT_UNUSED jobject holder, jint critical) {
6927     CHECK_ERROR_QUEUE_ON_RETURN;
6928     // NOLINTNEXTLINE(runtime/int)
6929     JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6930     return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6931                                                                                critical);
6932 }
6933 
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6934 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6935                                                        CONSCRYPT_UNUSED jobject holder,
6936                                                        jint critical) {
6937     CHECK_ERROR_QUEUE_ON_RETURN;
6938     // NOLINTNEXTLINE(runtime/int)
6939     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6940     return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6941             env, x509CrlRef, critical);
6942 }
6943 
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6944 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6945                                                            jlong x509RevokedRef, jint critical) {
6946     CHECK_ERROR_QUEUE_ON_RETURN;
6947     // NOLINTNEXTLINE(runtime/int)
6948     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6949     return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6950                                  X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6951 }
6952 
6953 /**
6954  * Based on example logging call back from SSL_CTX_set_info_callback man page
6955  */
info_callback_LOG(const SSL * s,int where,int ret)6956 static void info_callback_LOG(const SSL* s, int where, int ret) {
6957     int w = where & ~SSL_ST_MASK;
6958     const char* str;
6959     if (w & SSL_ST_CONNECT) {
6960         str = "SSL_connect";
6961     } else if (w & SSL_ST_ACCEPT) {
6962         str = "SSL_accept";
6963     } else {
6964         str = "undefined";
6965     }
6966 
6967     if (where & SSL_CB_LOOP) {
6968         JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6969     } else if (where & SSL_CB_ALERT) {
6970         str = (where & SSL_CB_READ) ? "read" : "write";
6971         JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6972                   SSL_alert_desc_string_long(ret));
6973     } else if (where & SSL_CB_EXIT) {
6974         if (ret == 0) {
6975             JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6976                       SSL_state_string_long(s));
6977         } else if (ret < 0) {
6978             JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6979                       SSL_state_string_long(s));
6980         } else if (ret == 1) {
6981             JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6982                       SSL_state_string_long(s));
6983         } else {
6984             JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6985                       SSL_state_string_long(s));
6986         }
6987     } else if (where & SSL_CB_HANDSHAKE_START) {
6988         JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6989                   SSL_state_string_long(s));
6990     } else if (where & SSL_CB_HANDSHAKE_DONE) {
6991         JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6992                   SSL_state_string_long(s));
6993     } else {
6994         JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6995                   SSL_state_string_long(s));
6996     }
6997 }
6998 
6999 #ifdef _WIN32
7000 
7001 /**
7002  * Dark magic helper function that checks, for a given SSL session, whether it
7003  * can SSL_read() or SSL_write() without blocking. Takes into account any
7004  * concurrent attempts to close the SSLSocket from the Java side. This is
7005  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7006  * while thread #2 is sitting in a blocking read or write. The type argument
7007  * specifies whether we are waiting for readability or writability. It expects
7008  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7009  * only need to wait in case one of these problems occurs.
7010  *
7011  * @param env
7012  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7013  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
7014  * @param appData The application data structure with mutex info etc.
7015  * @param timeout_millis The timeout value for select call, with the special value
7016  *                0 meaning no timeout at all (wait indefinitely). Note: This is
7017  *                the Java semantics of the timeout value, not the usual
7018  *                select() semantics.
7019  * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
7020  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7021 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7022                      int timeout_millis) {
7023     int result = -1;
7024 
7025     NetFd fd(env, fdObject);
7026     do {
7027         if (fd.isClosed()) {
7028             result = THROWN_EXCEPTION;
7029             break;
7030         }
7031 
7032         WSAEVENT events[2];
7033         events[0] = appData->interruptEvent;
7034         events[1] = WSACreateEvent();
7035         if (events[1] == WSA_INVALID_EVENT) {
7036             JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
7037             break;
7038         }
7039 
7040         if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
7041                                                         FD_CLOSE) == SOCKET_ERROR) {
7042             JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
7043             break;
7044         }
7045 
7046         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7047                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7048                   timeout_millis);
7049 
7050         int rc = WSAWaitForMultipleEvents(
7051                 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
7052         if (rc == WSA_WAIT_FAILED) {
7053             JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
7054             result = -1;
7055         } else if (rc == WSA_WAIT_TIMEOUT) {
7056             result = 0;
7057         } else {
7058             result = 1;
7059         }
7060         WSACloseEvent(events[1]);
7061     } while (0);
7062 
7063     JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
7064               (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
7065               result);
7066 
7067     std::lock_guard<std::mutex> appDataLock(appData->mutex);
7068     appData->waitingThreads--;
7069 
7070     return result;
7071 }
7072 
7073 #else   // !defined(_WIN32)
7074 
7075 /**
7076  * Dark magic helper function that checks, for a given SSL session, whether it
7077  * can SSL_read() or SSL_write() without blocking. Takes into account any
7078  * concurrent attempts to close the SSLSocket from the Java side. This is
7079  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7080  * while thread #2 is sitting in a blocking read or write. The type argument
7081  * specifies whether we are waiting for readability or writability. It expects
7082  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7083  * only need to wait in case one of these problems occurs.
7084  *
7085  * @param env
7086  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7087  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
7088  * @param appData The application data structure with mutex info etc.
7089  * @param timeout_millis The timeout value for poll call, with the special value
7090  *                0 meaning no timeout at all (wait indefinitely). Note: This is
7091  *                the Java semantics of the timeout value, not the usual
7092  *                poll() semantics.
7093  * @return The result of the inner poll() call,
7094  * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
7095  * additional errors
7096  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7097 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7098                      int timeout_millis) {
7099     // This loop is an expanded version of the NET_FAILURE_RETRY
7100     // macro. It cannot simply be used in this case because poll
7101     // cannot be restarted without recreating the pollfd structure.
7102     int result;
7103     struct pollfd fds[2];
7104     do {
7105         NetFd fd(env, fdObject);
7106         if (fd.isClosed()) {
7107             result = THROWN_EXCEPTION;
7108             break;
7109         }
7110         int intFd = fd.get();
7111         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7112                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
7113 
7114         memset(&fds, 0, sizeof(fds));
7115         fds[0].fd = intFd;
7116         if (type == SSL_ERROR_WANT_READ) {
7117             fds[0].events = POLLIN | POLLPRI;
7118         } else {
7119             fds[0].events = POLLOUT | POLLPRI;
7120         }
7121 
7122         fds[1].fd = appData->fdsEmergency[0];
7123         fds[1].events = POLLIN | POLLPRI;
7124 
7125         // Converting from Java semantics to Posix semantics.
7126         if (timeout_millis <= 0) {
7127             timeout_millis = -1;
7128         }
7129 
7130         CompatibilityCloseMonitor monitor(intFd);
7131 
7132         result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
7133         JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
7134                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7135                   timeout_millis, result);
7136         if (result == -1) {
7137             if (fd.isClosed()) {
7138                 result = THROWN_EXCEPTION;
7139                 break;
7140             }
7141             if (errno != EINTR) {
7142                 break;
7143             }
7144         }
7145     } while (result == -1);
7146 
7147     std::lock_guard<std::mutex> appDataLock(appData->mutex);
7148 
7149     if (result > 0) {
7150         // We have been woken up by a token in the emergency pipe. We
7151         // can't be sure the token is still in the pipe at this point
7152         // because it could have already been read by the thread that
7153         // originally wrote it if it entered sslSelect and acquired
7154         // the mutex before we did. Thus we cannot safely read from
7155         // the pipe in a blocking way (so we make the pipe
7156         // non-blocking at creation).
7157         if (fds[1].revents & POLLIN) {
7158             char token;
7159             do {
7160                 (void)read(appData->fdsEmergency[0], &token, 1);
7161             } while (errno == EINTR);
7162         }
7163     }
7164 
7165     // Tell the world that there is now one thread less waiting for the
7166     // underlying network.
7167     appData->waitingThreads--;
7168 
7169     return result;
7170 }
7171 #endif  // !defined(_WIN32)
7172 
7173 /**
7174  * Helper function that wakes up a thread blocked in select(), in case there is
7175  * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
7176  * before closing the connection.
7177  *
7178  * @param data The application data structure with mutex info etc.
7179  */
sslNotify(AppData * appData)7180 static void sslNotify(AppData* appData) {
7181 #ifdef _WIN32
7182     SetEvent(appData->interruptEvent);
7183 #else
7184     // Write a byte to the emergency pipe, so a concurrent select() can return.
7185     // Note we have to restore the errno of the original system call, since the
7186     // caller relies on it for generating error messages.
7187     int errnoBackup = errno;
7188     char token = '*';
7189     do {
7190         errno = 0;
7191         (void)write(appData->fdsEmergency[1], &token, 1);
7192     } while (errno == EINTR);
7193     errno = errnoBackup;
7194 #endif
7195 }
7196 
toAppData(const SSL * ssl)7197 static AppData* toAppData(const SSL* ssl) {
7198     return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
7199 }
7200 
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)7201 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
7202     JNI_TRACE("ssl=%p cert_verify_callback", ssl);
7203 
7204     AppData* appData = toAppData(ssl);
7205     JNIEnv* env = appData->env;
7206     if (env == nullptr) {
7207         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
7208         JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
7209         return ssl_verify_invalid;
7210     }
7211 
7212     // Create the byte[][] array that holds all the certs
7213     ScopedLocalRef<jobjectArray> array(
7214             env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
7215     if (array.get() == nullptr) {
7216         return ssl_verify_invalid;
7217     }
7218 
7219     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7220     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
7221 
7222     const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
7223     const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
7224 
7225     JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
7226               authMethod);
7227     ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
7228     env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
7229 
7230     ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
7231     JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
7232     return result;
7233 }
7234 
7235 /**
7236  * Call back to watch for handshake to be completed. This is necessary for
7237  * False Start support, since SSL_do_handshake returns before the handshake is
7238  * completed in this case.
7239  */
info_callback(const SSL * ssl,int type,int value)7240 static void info_callback(const SSL* ssl, int type, int value) {
7241     JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
7242     if (conscrypt::trace::kWithJniTrace) {
7243         info_callback_LOG(ssl, type, value);
7244     }
7245     if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
7246         JNI_TRACE("ssl=%p info_callback ignored", ssl);
7247         return;
7248     }
7249 
7250     AppData* appData = toAppData(ssl);
7251     JNIEnv* env = appData->env;
7252     if (env == nullptr) {
7253         CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
7254         JNI_TRACE("ssl=%p info_callback env error", ssl);
7255         return;
7256     }
7257     if (env->ExceptionCheck()) {
7258         JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
7259         return;
7260     }
7261 
7262     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7263 
7264     JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
7265     env->CallVoidMethod(sslHandshakeCallbacks,
7266                         conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
7267 
7268     if (env->ExceptionCheck()) {
7269         JNI_TRACE("ssl=%p info_callback exception", ssl);
7270     }
7271     JNI_TRACE("ssl=%p info_callback completed", ssl);
7272 }
7273 
7274 /**
7275  * Call back to ask for a certificate. There are three possible exit codes:
7276  *
7277  * 1 is success.
7278  * 0 is error.
7279  * -1 is to pause the handshake to continue from the same place later.
7280  */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)7281 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
7282     JNI_TRACE("ssl=%p cert_cb", ssl);
7283 
7284     // cert_cb is called for both clients and servers, but we are only
7285     // interested in client certificates.
7286     if (SSL_is_server(ssl)) {
7287         JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
7288         return 1;
7289     }
7290 
7291     AppData* appData = toAppData(ssl);
7292     JNIEnv* env = appData->env;
7293     if (env == nullptr) {
7294         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
7295         JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
7296         return 0;
7297     }
7298     if (env->ExceptionCheck()) {
7299         JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
7300         return 0;
7301     }
7302     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7303 
7304     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
7305 
7306     // Call Java callback which can reconfigure the client certificate.
7307     const uint8_t* ctype = nullptr;
7308     size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
7309     const uint16_t* sigalgs = nullptr;
7310     size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
7311     ScopedLocalRef<jobjectArray> issuers(
7312             env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
7313     if (issuers.get() == nullptr) {
7314         return 0;
7315     }
7316 
7317     if (conscrypt::trace::kWithJniTrace) {
7318         for (size_t i = 0; i < ctype_num; i++) {
7319             JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
7320         }
7321         for (size_t i = 0; i < sigalgs_num; i++) {
7322             JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
7323         }
7324     }
7325 
7326     jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
7327     if (keyTypes == nullptr) {
7328         JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
7329         return 0;
7330     }
7331     env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
7332                             reinterpret_cast<const jbyte*>(ctype));
7333 
7334     jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
7335     if (signatureAlgs == nullptr) {
7336         JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
7337         return 0;
7338     }
7339     {
7340         ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
7341         for (size_t i = 0; i < sigalgs_num; i++) {
7342             sigAlgsRW[i] = sigalgs[i];
7343         }
7344     }
7345 
7346     JNI_TRACE(
7347             "ssl=%p clientCertificateRequested calling clientCertificateRequested "
7348             "keyTypes=%p signatureAlgs=%p issuers=%p",
7349             ssl, keyTypes, signatureAlgs, issuers.get());
7350     env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
7351 
7352     if (env->ExceptionCheck()) {
7353         JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
7354         return 0;
7355     }
7356 
7357     JNI_TRACE("ssl=%p cert_cb => 1", ssl);
7358     return 1;
7359 }
7360 
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)7361 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
7362     SSL* ssl = client_hello->ssl;
7363     JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
7364 
7365     AppData* appData = toAppData(ssl);
7366     JNIEnv* env = appData->env;
7367     if (env == nullptr) {
7368         CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
7369         JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
7370         return ssl_select_cert_error;
7371     }
7372     if (env->ExceptionCheck()) {
7373         JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
7374         return ssl_select_cert_error;
7375     }
7376 
7377     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7378     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
7379 
7380     JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
7381     env->CallVoidMethod(sslHandshakeCallbacks, methodID);
7382 
7383     if (env->ExceptionCheck()) {
7384         JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
7385         return ssl_select_cert_error;
7386     }
7387     JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
7388     return ssl_select_cert_success;
7389 }
7390 
7391 /**
7392  * Pre-Shared Key (PSK) client callback.
7393  */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)7394 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
7395                                         unsigned int max_identity_len, unsigned char* psk,
7396                                         unsigned int max_psk_len) {
7397     JNI_TRACE("ssl=%p psk_client_callback", ssl);
7398 
7399     AppData* appData = toAppData(ssl);
7400     JNIEnv* env = appData->env;
7401     if (env == nullptr) {
7402         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
7403         JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
7404         return 0;
7405     }
7406     if (env->ExceptionCheck()) {
7407         JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
7408         return 0;
7409     }
7410 
7411     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7412     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
7413     JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
7414     ScopedLocalRef<jstring> identityHintJava(env,
7415                                              (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
7416     ScopedLocalRef<jbyteArray> identityJava(
7417             env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
7418     if (identityJava.get() == nullptr) {
7419         JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
7420         return 0;
7421     }
7422     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7423     if (keyJava.get() == nullptr) {
7424         JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
7425         return 0;
7426     }
7427     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7428                                      identityJava.get(), keyJava.get());
7429     if (env->ExceptionCheck()) {
7430         JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
7431         return 0;
7432     }
7433     if (keyLen <= 0) {
7434         JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
7435         return 0;
7436     } else if ((unsigned int)keyLen > max_psk_len) {
7437         JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
7438         return 0;
7439     }
7440     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7441     if (keyJavaRo.get() == nullptr) {
7442         JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7443         return 0;
7444     }
7445     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7446 
7447     ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7448     if (identityJavaRo.get() == nullptr) {
7449         JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7450         return 0;
7451     }
7452     memcpy(identity, identityJavaRo.get(), max_identity_len);
7453 
7454     JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7455     return static_cast<unsigned int>(keyLen);
7456 }
7457 
7458 /**
7459  * Pre-Shared Key (PSK) server callback.
7460  */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)7461 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
7462                                         unsigned int max_psk_len) {
7463     JNI_TRACE("ssl=%p psk_server_callback", ssl);
7464 
7465     AppData* appData = toAppData(ssl);
7466     JNIEnv* env = appData->env;
7467     if (env == nullptr) {
7468         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
7469         JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7470         return 0;
7471     }
7472     if (env->ExceptionCheck()) {
7473         JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7474         return 0;
7475     }
7476 
7477     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7478     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
7479     JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7480     const char* identityHint = SSL_get_psk_identity_hint(ssl);
7481     ScopedLocalRef<jstring> identityHintJava(
7482             env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
7483     ScopedLocalRef<jstring> identityJava(
7484             env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
7485     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7486     if (keyJava.get() == nullptr) {
7487         JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7488         return 0;
7489     }
7490     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7491                                      identityJava.get(), keyJava.get());
7492     if (env->ExceptionCheck()) {
7493         JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7494         return 0;
7495     }
7496     if (keyLen <= 0) {
7497         JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7498         return 0;
7499     } else if ((unsigned int)keyLen > max_psk_len) {
7500         JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7501         return 0;
7502     }
7503     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7504     if (keyJavaRo.get() == nullptr) {
7505         JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7506         return 0;
7507     }
7508     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7509 
7510     JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7511     return static_cast<unsigned int>(keyLen);
7512 }
7513 
new_session_callback(SSL * ssl,SSL_SESSION * session)7514 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
7515     JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
7516 
7517     AppData* appData = toAppData(ssl);
7518     JNIEnv* env = appData->env;
7519     if (env == nullptr) {
7520         CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
7521         JNI_TRACE("ssl=%p new_session_callback env error", ssl);
7522         return 0;
7523     }
7524     if (env->ExceptionCheck()) {
7525         JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
7526         return 0;
7527     }
7528 
7529     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7530     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
7531     JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
7532     env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
7533     if (env->ExceptionCheck()) {
7534         JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
7535         env->ExceptionClear();
7536     }
7537     JNI_TRACE("ssl=%p new_session_callback completed", ssl);
7538 
7539     // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
7540     // the reference count.
7541     return 0;
7542 }
7543 
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)7544 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
7545                                                       int* out_copy) {
7546     JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
7547 
7548     // Always set to out_copy to zero. The Java callback will be responsible for incrementing
7549     // the reference count (and any required synchronization).
7550     *out_copy = 0;
7551 
7552     AppData* appData = toAppData(ssl);
7553     JNIEnv* env = appData->env;
7554     if (env == nullptr) {
7555         CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7556         JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7557         return 0;
7558     }
7559     if (env->ExceptionCheck()) {
7560         JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7561         return 0;
7562     }
7563 
7564     // Copy the ID to a byte[].
7565     jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7566     if (id_array == nullptr) {
7567         JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7568         return 0;
7569     }
7570     env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7571                             reinterpret_cast<const jbyte*>(id));
7572 
7573     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7574     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7575     JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7576     jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7577     if (env->ExceptionCheck()) {
7578         JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7579         env->ExceptionClear();
7580     }
7581     SSL_SESSION* ssl_session_ptr =
7582             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7583     JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7584     return ssl_session_ptr;
7585 }
7586 
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7587 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7588     CHECK_ERROR_QUEUE_ON_RETURN;
7589     int ret = 0;
7590     ret = EVP_has_aes_hardware();
7591     JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7592     return ret;
7593 }
7594 
debug_print_session_key(const SSL * ssl,const char * line)7595 static void debug_print_session_key(const SSL* ssl, const char* line) {
7596     JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7597 }
7598 
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7599 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7600     static constexpr size_t kDataWidth = 16;
7601 
7602     struct timeval tv;
7603     if (gettimeofday(&tv, NULL)) {
7604         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7605                       "debug_print_packet_data: could not get time of day");
7606         return;
7607     }
7608 
7609     // Packet preamble for text2pcap
7610     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7611                   static_cast<long>(tv.tv_sec),
7612                   static_cast<long>(tv.tv_usec));  // NOLINT(runtime/int)
7613 
7614     char out[kDataWidth * 3 + 1];
7615     for (size_t i = 0; i < len; i += kDataWidth) {
7616         size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7617 
7618         for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7619             int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7620             if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7621                 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7622                               "debug_print_packet_data failed to output %d", ret);
7623                 return;
7624             }
7625         }
7626 
7627         // Print out packet data in format understood by text2pcap
7628         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7629     }
7630 
7631     // Conclude the packet data
7632     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7633 }
7634 
7635 /*
7636  * public static native int SSL_CTX_new();
7637  */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7638 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7639     CHECK_ERROR_QUEUE_ON_RETURN;
7640     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7641     if (sslCtx.get() == nullptr) {
7642         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7643         return 0;
7644     }
7645     SSL_CTX_set_options(
7646             sslCtx.get(),
7647             SSL_OP_ALL
7648                     // We also disable session tickets for better compatibility b/2682876
7649                     | SSL_OP_NO_TICKET
7650                     // We also disable compression for better compatibility b/2710492 b/2710497
7651                     | SSL_OP_NO_COMPRESSION
7652                     // Generate a fresh ECDH keypair for each key exchange.
7653                     | SSL_OP_SINGLE_ECDH_USE);
7654     SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7655     SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7656 
7657     uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7658     /*
7659      * Turn on "partial write" mode. This means that SSL_write() will
7660      * behave like Posix write() and possibly return after only
7661      * writing a partial buffer. Note: The alternative, perhaps
7662      * surprisingly, is not that SSL_write() always does full writes
7663      * but that it will force you to retry write calls having
7664      * preserved the full state of the original call. (This is icky
7665      * and undesirable.)
7666      */
7667     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7668 
7669     // Reuse empty buffers within the SSL_CTX to save memory
7670     mode |= SSL_MODE_RELEASE_BUFFERS;
7671 
7672     // Enable False Start.
7673     mode |= SSL_MODE_ENABLE_FALSE_START;
7674 
7675     // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7676     // between
7677     // calls to wrap(...).
7678     // See https://github.com/netty/netty-tcnative/issues/100
7679     mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7680 
7681     SSL_CTX_set_mode(sslCtx.get(), mode);
7682 
7683     SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7684     SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7685     SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7686     if (conscrypt::trace::kWithJniTraceKeys) {
7687         SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7688     }
7689 
7690     // By default BoringSSL will cache in server mode, but we want to get
7691     // notified of new sessions being created in client mode. We set
7692     // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7693     // ignore it in server mode in favor of the internal cache.
7694     SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7695     SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7696     SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7697 
7698     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7699     return (jlong)sslCtx.release();
7700 }
7701 
7702 /**
7703  * public static native void SSL_CTX_free(long ssl_ctx)
7704  */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7705 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7706                                       CONSCRYPT_UNUSED jobject holder) {
7707     CHECK_ERROR_QUEUE_ON_RETURN;
7708     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7709     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7710     if (ssl_ctx == nullptr) {
7711         return;
7712     }
7713     SSL_CTX_free(ssl_ctx);
7714 }
7715 
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7716 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7717                                                         CONSCRYPT_UNUSED jobject holder,
7718                                                         jbyteArray sid_ctx) {
7719     CHECK_ERROR_QUEUE_ON_RETURN;
7720     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7721     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7722               sid_ctx);
7723     if (ssl_ctx == nullptr) {
7724         return;
7725     }
7726 
7727     ScopedByteArrayRO buf(env, sid_ctx);
7728     if (buf.get() == nullptr) {
7729         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7730                   ssl_ctx);
7731         return;
7732     }
7733 
7734     unsigned int length = static_cast<unsigned int>(buf.size());
7735     if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7736         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7737                                            "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7738         JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7739         return;
7740     }
7741     const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7742     int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7743     if (result == 0) {
7744         conscrypt::jniutil::throwExceptionFromBoringSSLError(
7745                 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7746         return;
7747     }
7748     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7749 }
7750 
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7751 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7752                                               CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7753     CHECK_ERROR_QUEUE_ON_RETURN;
7754     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7755     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7756     if (ssl_ctx == nullptr) {
7757         return 0L;
7758     }
7759 
7760     return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7761 }
7762 
7763 /**
7764  * public static native int SSL_new(long ssl_ctx) throws SSLException;
7765  */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7766 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7767                                   CONSCRYPT_UNUSED jobject holder) {
7768     CHECK_ERROR_QUEUE_ON_RETURN;
7769     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7770     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7771     if (ssl_ctx == nullptr) {
7772         return 0;
7773     }
7774     bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7775     if (ssl.get() == nullptr) {
7776         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7777                                                            "Unable to create SSL structure");
7778         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7779         return 0;
7780     }
7781 
7782     /*
7783      * Create our special application data.
7784      */
7785     AppData* appData = AppData::create();
7786     if (appData == nullptr) {
7787         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7788         ERR_clear_error();
7789         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7790         return 0;
7791     }
7792     SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7793 
7794     SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7795 
7796     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7797     return (jlong)ssl.release();
7798 }
7799 
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7800 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7801                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
7802     CHECK_ERROR_QUEUE_ON_RETURN;
7803     SSL* ssl = to_SSL(env, ssl_address, true);
7804     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7805     if (ssl == nullptr) {
7806         return;
7807     }
7808 
7809     // NOLINTNEXTLINE(runtime/int)
7810     long ret = SSL_enable_tls_channel_id(ssl);
7811     if (ret != 1L) {
7812         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7813         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7814                                                            "Error enabling Channel ID");
7815         JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7816         return;
7817     }
7818 }
7819 
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7820 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7821                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
7822     CHECK_ERROR_QUEUE_ON_RETURN;
7823     SSL* ssl = to_SSL(env, ssl_address, true);
7824     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7825     if (ssl == nullptr) {
7826         return nullptr;
7827     }
7828 
7829     // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7830     // as a constant anywhere.
7831     jbyteArray javaBytes = env->NewByteArray(64);
7832     ScopedByteArrayRW bytes(env, javaBytes);
7833     if (bytes.get() == nullptr) {
7834         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7835         return nullptr;
7836     }
7837 
7838     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7839     // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7840     // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7841     // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7842     size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7843     if (ret == 0) {
7844         // Channel ID either not set or did not verify
7845         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7846         return nullptr;
7847     } else if (ret != 64) {
7848         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7849         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7850                                                            "Error getting Channel ID");
7851         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7852         return nullptr;
7853     }
7854 
7855     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7856     return javaBytes;
7857 }
7858 
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7859 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7860                                                  CONSCRYPT_UNUSED jobject ssl_holder,
7861                                                  jobject pkeyRef) {
7862     CHECK_ERROR_QUEUE_ON_RETURN;
7863     SSL* ssl = to_SSL(env, ssl_address, true);
7864     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7865     if (ssl == nullptr) {
7866         return;
7867     }
7868 
7869     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7870     if (pkey == nullptr) {
7871         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7872         return;
7873     }
7874 
7875     // NOLINTNEXTLINE(runtime/int)
7876     long ret = SSL_set1_tls_channel_id(ssl, pkey);
7877 
7878     if (ret != 1L) {
7879         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7880         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7881                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7882         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7883         return;
7884     }
7885 
7886     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7887 }
7888 
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7889 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7890                                                     CONSCRYPT_UNUSED jobject ssl_holder,
7891                                                     jobjectArray encodedCertificatesJava,
7892                                                     jobject pkeyRef) {
7893     CHECK_ERROR_QUEUE_ON_RETURN;
7894     SSL* ssl = to_SSL(env, ssl_address, true);
7895     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7896               encodedCertificatesJava, pkeyRef);
7897     if (ssl == nullptr) {
7898         return;
7899     }
7900     if (encodedCertificatesJava == nullptr) {
7901         conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7902         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7903         return;
7904     }
7905     size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7906     if (numCerts == 0) {
7907         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7908                                            "certificates.length == 0");
7909         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7910         return;
7911     }
7912     if (pkeyRef == nullptr) {
7913         conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7914         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7915         return;
7916     }
7917 
7918     // Get the private key.
7919     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7920     if (pkey == nullptr) {
7921         conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7922         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7923         return;
7924     }
7925 
7926     // Copy the certificates.
7927     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7928     std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7929     for (size_t i = 0; i < numCerts; ++i) {
7930         ScopedLocalRef<jbyteArray> certArray(
7931                 env, reinterpret_cast<jbyteArray>(
7932                              env->GetObjectArrayElement(encodedCertificatesJava, i)));
7933         certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7934         if (!certBufferRefs[i]) {
7935             return;
7936         }
7937         certBuffers[i] = certBufferRefs[i].get();
7938     }
7939 
7940     if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7941         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7942                                                            "Error configuring certificate");
7943         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7944         return;
7945     }
7946     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7947 }
7948 
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7949 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7950                                                 CONSCRYPT_UNUSED jobject ssl_holder,
7951                                                 jobjectArray principals) {
7952     CHECK_ERROR_QUEUE_ON_RETURN;
7953     SSL* ssl = to_SSL(env, ssl_address, true);
7954     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7955     if (ssl == nullptr) {
7956         return;
7957     }
7958 
7959     if (principals == nullptr) {
7960         conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7961         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7962         return;
7963     }
7964 
7965     int length = env->GetArrayLength(principals);
7966     if (length == 0) {
7967         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7968                                            "principals.length == 0");
7969         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7970         return;
7971     }
7972 
7973     bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7974     if (principalsStack.get() == nullptr) {
7975         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7976         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7977         return;
7978     }
7979     for (int i = 0; i < length; i++) {
7980         ScopedLocalRef<jbyteArray> principal(
7981                 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7982         bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7983         if (!buf) {
7984             return;
7985         }
7986         if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7987             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7988             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7989             return;
7990         }
7991         OWNERSHIP_TRANSFERRED(buf);
7992     }
7993 
7994     SSL_set0_client_CAs(ssl, principalsStack.release());
7995     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7996 }
7997 
7998 /**
7999  * public static native long SSL_set_mode(long ssl, long mode);
8000  */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)8001 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
8002                                        CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
8003     CHECK_ERROR_QUEUE_ON_RETURN;
8004     SSL* ssl = to_SSL(env, ssl_address, true);
8005     // NOLINTNEXTLINE(runtime/int)
8006     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
8007     if (ssl == nullptr) {
8008         return 0;
8009     }
8010     jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
8011     // NOLINTNEXTLINE(runtime/int)
8012     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
8013     return result;
8014 }
8015 
8016 /**
8017  * public static native long SSL_set_options(long ssl, long options);
8018  */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8019 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
8020                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8021     CHECK_ERROR_QUEUE_ON_RETURN;
8022     SSL* ssl = to_SSL(env, ssl_address, true);
8023     // NOLINTNEXTLINE(runtime/int)
8024     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
8025     if (ssl == nullptr) {
8026         return 0;
8027     }
8028     jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
8029     // NOLINTNEXTLINE(runtime/int)
8030     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
8031     return result;
8032 }
8033 
8034 /**
8035  * public static native long SSL_clear_options(long ssl, long options);
8036  */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8037 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
8038                                             CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8039     CHECK_ERROR_QUEUE_ON_RETURN;
8040     SSL* ssl = to_SSL(env, ssl_address, true);
8041     // NOLINTNEXTLINE(runtime/int)
8042     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
8043     if (ssl == nullptr) {
8044         return 0;
8045     }
8046     jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
8047     // NOLINTNEXTLINE(runtime/int)
8048     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
8049     return result;
8050 }
8051 
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)8052 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
8053                                                    CONSCRYPT_UNUSED jobject ssl_holder,
8054                                                    jint min_version, jint max_version) {
8055     CHECK_ERROR_QUEUE_ON_RETURN;
8056     SSL* ssl = to_SSL(env, ssl_address, true);
8057     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
8058               max_version);
8059     if (ssl == nullptr) {
8060         return 0;
8061     }
8062     int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
8063     int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
8064     // Return failure if either call failed.
8065     int result = 1;
8066     if (!min_result || !max_result) {
8067         result = 0;
8068         // The only possible error is an invalid version, so we don't need the details.
8069         ERR_clear_error();
8070     }
8071     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
8072               min_result, max_result, result);
8073     return result;
8074 }
8075 
8076 /**
8077  * public static native void SSL_enable_signed_cert_timestamps(long ssl);
8078  */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8079 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
8080                                                            CONSCRYPT_UNUSED jobject ssl_holder) {
8081     CHECK_ERROR_QUEUE_ON_RETURN;
8082     SSL* ssl = to_SSL(env, ssl_address, true);
8083     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
8084     if (ssl == nullptr) {
8085         return;
8086     }
8087 
8088     SSL_enable_signed_cert_timestamps(ssl);
8089 }
8090 
8091 /**
8092  * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
8093  */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8094 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
8095         JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
8096     CHECK_ERROR_QUEUE_ON_RETURN;
8097     SSL* ssl = to_SSL(env, ssl_address, true);
8098     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
8099     if (ssl == nullptr) {
8100         return nullptr;
8101     }
8102 
8103     const uint8_t* data;
8104     size_t data_len;
8105     SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
8106 
8107     if (data_len == 0) {
8108         JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
8109         return nullptr;
8110     }
8111 
8112     jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
8113     if (result != nullptr) {
8114         env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
8115     }
8116     return result;
8117 }
8118 
8119 /*
8120  * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
8121  */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)8122 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
8123                                                             CONSCRYPT_UNUSED jobject ssl_holder,
8124                                                             jbyteArray list) {
8125     CHECK_ERROR_QUEUE_ON_RETURN;
8126     SSL* ssl = to_SSL(env, ssl_address, true);
8127     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
8128     if (ssl == nullptr) {
8129         return;
8130     }
8131 
8132     ScopedByteArrayRO listBytes(env, list);
8133     if (listBytes.get() == nullptr) {
8134         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
8135         return;
8136     }
8137 
8138     if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
8139                                             listBytes.size())) {
8140         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
8141     } else {
8142         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
8143     }
8144 }
8145 
8146 /*
8147  * public static native void SSL_enable_ocsp_stapling(long ssl);
8148  */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8149 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
8150                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
8151     CHECK_ERROR_QUEUE_ON_RETURN;
8152     SSL* ssl = to_SSL(env, ssl_address, true);
8153     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
8154     if (ssl == nullptr) {
8155         return;
8156     }
8157 
8158     SSL_enable_ocsp_stapling(ssl);
8159 }
8160 
8161 /*
8162  * public static native byte[] SSL_get_ocsp_response(long ssl);
8163  */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8164 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8165                                                      CONSCRYPT_UNUSED jobject ssl_holder) {
8166     CHECK_ERROR_QUEUE_ON_RETURN;
8167     SSL* ssl = to_SSL(env, ssl_address, true);
8168     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
8169     if (ssl == nullptr) {
8170         return nullptr;
8171     }
8172 
8173     const uint8_t* data;
8174     size_t data_len;
8175     SSL_get0_ocsp_response(ssl, &data, &data_len);
8176 
8177     if (data_len == 0) {
8178         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
8179         return nullptr;
8180     }
8181 
8182     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8183     if (byteArray.get() == nullptr) {
8184         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
8185         return nullptr;
8186     }
8187 
8188     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8189     JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
8190               data_len);
8191 
8192     return byteArray.release();
8193 }
8194 
8195 /*
8196  * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
8197  */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)8198 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8199                                                CONSCRYPT_UNUSED jobject ssl_holder,
8200                                                jbyteArray response) {
8201     CHECK_ERROR_QUEUE_ON_RETURN;
8202     SSL* ssl = to_SSL(env, ssl_address, true);
8203     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
8204     if (ssl == nullptr) {
8205         return;
8206     }
8207 
8208     ScopedByteArrayRO responseBytes(env, response);
8209     if (responseBytes.get() == nullptr) {
8210         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
8211         return;
8212     }
8213 
8214     if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
8215                                responseBytes.size())) {
8216         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
8217     } else {
8218         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
8219     }
8220 }
8221 
8222 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
8223 // to customize the length of their verify_data (with a default of 12 bytes).  We accept
8224 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
8225 // tests and update this value if necessary.
8226 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
8227 
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8228 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
8229                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
8230     CHECK_ERROR_QUEUE_ON_RETURN;
8231     SSL* ssl = to_SSL(env, ssl_address, true);
8232     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
8233     if (ssl == nullptr) {
8234         return nullptr;
8235     }
8236 
8237     uint8_t data[MAX_TLS_UNIQUE_LENGTH];
8238     size_t data_len;
8239     int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
8240 
8241     if (!ret || data_len == 0) {
8242         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
8243         return nullptr;
8244     }
8245 
8246     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8247     if (byteArray.get() == nullptr) {
8248         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
8249         return nullptr;
8250     }
8251 
8252     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8253     JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
8254               data_len);
8255 
8256     return byteArray.release();
8257 }
8258 
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)8259 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
8260                                                           CONSCRYPT_UNUSED jobject ssl_holder,
8261                                                           jbyteArray label, jbyteArray context,
8262                                                           jint num_bytes) {
8263     CHECK_ERROR_QUEUE_ON_RETURN;
8264     SSL* ssl = to_SSL(env, ssl_address, true);
8265     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
8266     if (ssl == nullptr) {
8267         return nullptr;
8268     }
8269     ScopedByteArrayRO labelBytes(env, label);
8270     if (labelBytes.get() == nullptr) {
8271         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
8272         return nullptr;
8273     }
8274     std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
8275     int ret;
8276     if (context == nullptr) {
8277         ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
8278                         reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
8279                         nullptr, 0, 0);
8280     } else {
8281         ScopedByteArrayRO contextBytes(env, context);
8282         if (contextBytes.get() == nullptr) {
8283             JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
8284                       ssl);
8285             return nullptr;
8286         }
8287         ret = SSL_export_keying_material(
8288                 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
8289                 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
8290                 contextBytes.size(), 1);
8291     }
8292     if (!ret) {
8293         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
8294                 conscrypt::jniutil::throwSSLExceptionStr);
8295         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
8296         return nullptr;
8297     }
8298     jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
8299     if (result == nullptr) {
8300         conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
8301         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
8302         return nullptr;
8303     }
8304     const jbyte* src = reinterpret_cast<jbyte*>(out.get());
8305     env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
8306     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
8307     return result;
8308 }
8309 
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)8310 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
8311                                                    CONSCRYPT_UNUSED jobject ssl_holder,
8312                                                    jstring identityHintJava) {
8313     CHECK_ERROR_QUEUE_ON_RETURN;
8314     SSL* ssl = to_SSL(env, ssl_address, true);
8315     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
8316               identityHintJava);
8317     if (ssl == nullptr) {
8318         return;
8319     }
8320 
8321     int ret;
8322     if (identityHintJava == nullptr) {
8323         ret = SSL_use_psk_identity_hint(ssl, nullptr);
8324     } else {
8325         ScopedUtfChars identityHint(env, identityHintJava);
8326         if (identityHint.c_str() == nullptr) {
8327             conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
8328             return;
8329         }
8330         ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
8331     }
8332 
8333     if (ret != 1) {
8334         int sslErrorCode = SSL_get_error(ssl, ret);
8335         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8336                                                            "Failed to set PSK identity hint");
8337     }
8338 }
8339 
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8340 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8341                                                              CONSCRYPT_UNUSED jobject ssl_holder,
8342                                                              jboolean enabled) {
8343     CHECK_ERROR_QUEUE_ON_RETURN;
8344     SSL* ssl = to_SSL(env, ssl_address, true);
8345     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
8346     if (ssl == nullptr) {
8347         return;
8348     }
8349 
8350     SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
8351 }
8352 
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8353 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8354                                                              CONSCRYPT_UNUSED jobject ssl_holder,
8355                                                              jboolean enabled) {
8356     CHECK_ERROR_QUEUE_ON_RETURN;
8357     SSL* ssl = to_SSL(env, ssl_address, true);
8358     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
8359     if (ssl == nullptr) {
8360         return;
8361     }
8362 
8363     SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
8364 }
8365 
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8366 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
8367                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8368     CHECK_ERROR_QUEUE_ON_RETURN;
8369     SSL* ssl = to_SSL(env, ssl_address, true);
8370     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
8371     if (ssl == nullptr) {
8372         return nullptr;
8373     }
8374 
8375     STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
8376     size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
8377     ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
8378     ScopedLongArrayRW ciphers(env, ciphersArray.get());
8379     for (size_t i = 0; i < count; i++) {
8380         ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
8381     }
8382 
8383     JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
8384     return ciphersArray.release();
8385 }
8386 
8387 /**
8388  * Sets the ciphers suites that are enabled in the SSL
8389  */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)8390 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
8391                                               CONSCRYPT_UNUSED jobject ssl_holder,
8392                                               jobjectArray cipherSuites) {
8393     CHECK_ERROR_QUEUE_ON_RETURN;
8394     SSL* ssl = to_SSL(env, ssl_address, true);
8395     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
8396     if (ssl == nullptr) {
8397         return;
8398     }
8399     if (cipherSuites == nullptr) {
8400         conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
8401         return;
8402     }
8403 
8404     int length = env->GetArrayLength(cipherSuites);
8405 
8406     /*
8407      * Special case for empty cipher list. This is considered an error by the
8408      * SSL_set_cipher_list API, but Java allows this silly configuration.
8409      * However, the SSL cipher list is still set even when SSL_set_cipher_list
8410      * returns 0 in this case. Just to make sure, we check the resulting cipher
8411      * list to make sure it's zero length.
8412      */
8413     if (length == 0) {
8414         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
8415         SSL_set_cipher_list(ssl, "");
8416         ERR_clear_error();
8417         if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
8418             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
8419             conscrypt::jniutil::throwRuntimeException(
8420                     env, "SSL_set_cipher_list did not update ciphers!");
8421             ERR_clear_error();
8422         }
8423         return;
8424     }
8425 
8426     static const char noSSLv2[] = "!SSLv2";
8427     size_t cipherStringLen = strlen(noSSLv2);
8428 
8429     for (int i = 0; i < length; i++) {
8430         ScopedLocalRef<jstring> cipherSuite(
8431                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8432         ScopedUtfChars c(env, cipherSuite.get());
8433         if (c.c_str() == nullptr) {
8434             return;
8435         }
8436 
8437         if (cipherStringLen + 1 < cipherStringLen) {
8438             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8439                                                "Overflow in cipher suite strings");
8440             return;
8441         }
8442         cipherStringLen += 1; /* For the separating colon */
8443 
8444         if (cipherStringLen + c.size() < cipherStringLen) {
8445             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8446                                                "Overflow in cipher suite strings");
8447             return;
8448         }
8449         cipherStringLen += c.size();
8450     }
8451 
8452     if (cipherStringLen + 1 < cipherStringLen) {
8453         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8454                                            "Overflow in cipher suite strings");
8455         return;
8456     }
8457     cipherStringLen += 1; /* For final NUL. */
8458 
8459     std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
8460     if (cipherString.get() == nullptr) {
8461         conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
8462         return;
8463     }
8464     memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
8465     size_t j = strlen(noSSLv2);
8466 
8467     for (int i = 0; i < length; i++) {
8468         ScopedLocalRef<jstring> cipherSuite(
8469                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8470         ScopedUtfChars c(env, cipherSuite.get());
8471 
8472         cipherString[j++] = ':';
8473         memcpy(&cipherString[j], c.c_str(), c.size());
8474         j += c.size();
8475     }
8476 
8477     cipherString[j++] = 0;
8478     if (j != cipherStringLen) {
8479         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8480                                            "Internal error");
8481         return;
8482     }
8483 
8484     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
8485     if (!SSL_set_cipher_list(ssl, cipherString.get())) {
8486         ERR_clear_error();
8487         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8488                                            "Illegal cipher suite strings.");
8489         return;
8490     }
8491 }
8492 
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8493 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
8494                                               CONSCRYPT_UNUSED jobject ssl_holder) {
8495     CHECK_ERROR_QUEUE_ON_RETURN;
8496     SSL* ssl = to_SSL(env, ssl_address, true);
8497     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
8498     if (ssl == nullptr) {
8499         return;
8500     }
8501     SSL_set_accept_state(ssl);
8502 }
8503 
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8504 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
8505                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8506     CHECK_ERROR_QUEUE_ON_RETURN;
8507     SSL* ssl = to_SSL(env, ssl_address, true);
8508     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
8509     if (ssl == nullptr) {
8510         return;
8511     }
8512     SSL_set_connect_state(ssl);
8513 }
8514 
8515 /**
8516  * Sets certificate expectations, especially for server to request client auth
8517  */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)8518 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
8519                                         CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
8520     CHECK_ERROR_QUEUE_ON_RETURN;
8521     SSL* ssl = to_SSL(env, ssl_address, true);
8522     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
8523     if (ssl == nullptr) {
8524         return;
8525     }
8526     SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
8527 }
8528 
8529 /**
8530  * Sets the ciphers suites that are enabled in the SSL
8531  */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)8532 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
8533                                          CONSCRYPT_UNUSED jobject ssl_holder,
8534                                          jlong ssl_session_address) {
8535     CHECK_ERROR_QUEUE_ON_RETURN;
8536     SSL* ssl = to_SSL(env, ssl_address, true);
8537     if (ssl == nullptr) {
8538         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
8539         return;
8540     }
8541 
8542     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
8543     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
8544     if (ssl_session == nullptr) {
8545         return;
8546     }
8547 
8548     int ret = SSL_set_session(ssl, ssl_session);
8549     if (ret != 1) {
8550         /*
8551          * Translate the error, and throw if it turns out to be a real
8552          * problem.
8553          */
8554         int sslErrorCode = SSL_get_error(ssl, ret);
8555         if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8556             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8557                                                                "SSL session set");
8558         }
8559     }
8560     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8561               ret);
8562 }
8563 
8564 /**
8565  * Sets the ciphers suites that are enabled in the SSL
8566  */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8567 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8568                                                           CONSCRYPT_UNUSED jobject ssl_holder,
8569                                                           jboolean creation_enabled) {
8570     CHECK_ERROR_QUEUE_ON_RETURN;
8571     SSL* ssl = to_SSL(env, ssl_address, true);
8572     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8573               creation_enabled);
8574     if (ssl == nullptr) {
8575         return;
8576     }
8577 
8578     if (creation_enabled) {
8579         SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8580     } else {
8581         SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8582     }
8583 }
8584 
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8585 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8586                                                 CONSCRYPT_UNUSED jobject ssl_holder) {
8587     CHECK_ERROR_QUEUE_ON_RETURN;
8588     SSL* ssl = to_SSL(env, ssl_address, true);
8589     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8590     if (ssl == nullptr) {
8591         return JNI_FALSE;
8592     }
8593 
8594     int reused = SSL_session_reused(ssl);
8595     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8596     return static_cast<jboolean>(reused);
8597 }
8598 
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8599 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8600                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
8601     CHECK_ERROR_QUEUE_ON_RETURN;
8602     SSL* ssl = to_SSL(env, ssl_address, true);
8603     JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8604     if (ssl == nullptr) {
8605         return;
8606     }
8607 
8608     SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8609 }
8610 
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8611 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8612                                                   CONSCRYPT_UNUSED jobject ssl_holder,
8613                                                   jstring hostname) {
8614     CHECK_ERROR_QUEUE_ON_RETURN;
8615     SSL* ssl = to_SSL(env, ssl_address, true);
8616     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8617     if (ssl == nullptr) {
8618         return;
8619     }
8620 
8621     ScopedUtfChars hostnameChars(env, hostname);
8622     if (hostnameChars.c_str() == nullptr) {
8623         return;
8624     }
8625     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8626               hostnameChars.c_str());
8627 
8628     int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8629     if (ret != 1) {
8630         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8631                                                            "Error setting host name");
8632         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8633         return;
8634     }
8635     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8636 }
8637 
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8638 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8639                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8640     CHECK_ERROR_QUEUE_ON_RETURN;
8641     SSL* ssl = to_SSL(env, ssl_address, true);
8642     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8643     if (ssl == nullptr) {
8644         return nullptr;
8645     }
8646     const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8647     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8648     return env->NewStringUTF(servername);
8649 }
8650 
8651 /**
8652  * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8653  * which should take precedence.
8654  */
selectApplicationProtocol(SSL * ssl,unsigned char ** out,unsigned char * outLength,const unsigned char * primary,const unsigned int primaryLength,const unsigned char * secondary,const unsigned int secondaryLength)8655 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8656                                      const unsigned char* primary,
8657                                      const unsigned int primaryLength,
8658                                      const unsigned char* secondary,
8659                                      const unsigned int secondaryLength) {
8660     JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8661 
8662     int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8663                                        secondaryLength);
8664     switch (status) {
8665         case OPENSSL_NPN_NEGOTIATED:
8666             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8667             return SSL_TLSEXT_ERR_OK;
8668             break;
8669         case OPENSSL_NPN_UNSUPPORTED:
8670             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8671             break;
8672         case OPENSSL_NPN_NO_OVERLAP:
8673             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8674             break;
8675     }
8676     return SSL_TLSEXT_ERR_NOACK;
8677 }
8678 
8679 /**
8680  * Calls out to an application-provided selector to choose the ALPN protocol.
8681  */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8682 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8683                                      unsigned char** out,
8684                                      unsigned char* outLen, const unsigned char* in,
8685                                      const unsigned int inLen) {
8686     // Copy the input array.
8687     ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8688     if (protocols.get() == nullptr) {
8689         JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8690         return SSL_TLSEXT_ERR_NOACK;
8691     }
8692     env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8693                             reinterpret_cast<const jbyte*>(in));
8694 
8695     // Invoke the selection method.
8696     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8697     jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8698 
8699     if (offset < 0) {
8700         JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8701         return SSL_TLSEXT_ERR_NOACK;
8702     }
8703 
8704     // Point the output to the selected protocol.
8705     *outLen = *(in + offset);
8706     *out = const_cast<unsigned char*>(in + offset + 1);
8707 
8708     return SSL_TLSEXT_ERR_OK;
8709 }
8710 
8711 /**
8712  * Callback for the server to select an ALPN protocol.
8713  */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8714 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8715                                 const unsigned char* in, unsigned int inLen, void*) {
8716     JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8717 
8718     AppData* appData = toAppData(ssl);
8719     if (appData == nullptr) {
8720         JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8721         return SSL_TLSEXT_ERR_NOACK;
8722     }
8723     JNIEnv* env = appData->env;
8724     if (env == nullptr) {
8725         CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8726         JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8727         return SSL_TLSEXT_ERR_NOACK;
8728     }
8729 
8730     if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8731                           !appData->hasApplicationProtocolSelector)) {
8732         if (out != nullptr && outLen != nullptr) {
8733             *out = nullptr;
8734             *outLen = 0;
8735         }
8736         JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8737         return SSL_TLSEXT_ERR_NOACK;
8738     }
8739 
8740     if (appData->hasApplicationProtocolSelector) {
8741         return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8742                                          const_cast<unsigned char**>(out), outLen, in, inLen);
8743     }
8744 
8745     return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8746                               reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8747                               static_cast<unsigned int>(appData->applicationProtocolsLength),
8748                               in, inLen);
8749 }
8750 
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8751 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8752                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
8753     CHECK_ERROR_QUEUE_ON_RETURN;
8754     SSL* ssl = to_SSL(env, ssl_address, true);
8755     JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8756     if (ssl == nullptr) {
8757         return nullptr;
8758     }
8759     const jbyte* protocol;
8760     unsigned int protocolLength;
8761     SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8762                            &protocolLength);
8763     if (protocolLength == 0) {
8764         return nullptr;
8765     }
8766     jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8767     if (result != nullptr) {
8768         env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8769     }
8770     return result;
8771 }
8772 
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8773 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8774                                                  CONSCRYPT_UNUSED jobject ssl_holder,
8775                                                  jboolean client_mode, jbyteArray protocols) {
8776     CHECK_ERROR_QUEUE_ON_RETURN;
8777     SSL* ssl = to_SSL(env, ssl_address, true);
8778     if (ssl == nullptr) {
8779         return;
8780     }
8781     AppData* appData = toAppData(ssl);
8782     if (appData == nullptr) {
8783         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8784         JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8785         return;
8786     }
8787 
8788     if (protocols != nullptr) {
8789         if (client_mode) {
8790             ScopedByteArrayRO protosBytes(env, protocols);
8791             if (protosBytes.get() == nullptr) {
8792                 JNI_TRACE(
8793                         "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8794                         "protosBytes == null",
8795                         ssl, protocols);
8796                 return;
8797             }
8798 
8799             const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8800             int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8801             if (ret != 0) {
8802                 conscrypt::jniutil::throwSSLExceptionStr(env,
8803                                                          "Unable to set ALPN protocols for client");
8804                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8805                 return;
8806             }
8807         } else {
8808             // Server mode - configure the ALPN protocol selection callback.
8809             if (!appData->setApplicationProtocols(env, protocols)) {
8810                 conscrypt::jniutil::throwSSLExceptionStr(env,
8811                                                          "Unable to set ALPN protocols for server");
8812                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8813                 return;
8814             }
8815             SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8816         }
8817     }
8818 }
8819 
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8820 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8821                                                            CONSCRYPT_UNUSED jobject ssl_holder,
8822                                                            jboolean hasSelector) {
8823     CHECK_ERROR_QUEUE_ON_RETURN;
8824     SSL* ssl = to_SSL(env, ssl_address, true);
8825     JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8826               hasSelector);
8827     if (ssl == nullptr) {
8828         return;
8829     }
8830     AppData* appData = toAppData(ssl);
8831     if (appData == nullptr) {
8832         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8833         JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8834         return;
8835     }
8836 
8837     appData->hasApplicationProtocolSelector = hasSelector;
8838     if (hasSelector) {
8839         SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8840     }
8841 }
8842 
8843 /**
8844  * Perform SSL handshake
8845  */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8846 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8847                                           CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8848                                           jobject shc, jint timeout_millis) {
8849     CHECK_ERROR_QUEUE_ON_RETURN;
8850     SSL* ssl = to_SSL(env, ssl_address, true);
8851     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8852               shc, timeout_millis);
8853     if (ssl == nullptr) {
8854         return;
8855     }
8856     if (fdObject == nullptr) {
8857         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8858         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8859         return;
8860     }
8861     if (shc == nullptr) {
8862         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8863         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8864                   ssl);
8865         return;
8866     }
8867 
8868     NetFd fd(env, fdObject);
8869     if (fd.isClosed()) {
8870         // SocketException thrown by NetFd.isClosed
8871         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8872         return;
8873     }
8874 
8875     int ret = SSL_set_fd(ssl, fd.get());
8876     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8877 
8878     if (ret != 1) {
8879         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8880                                                            "Error setting the file descriptor");
8881         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8882         return;
8883     }
8884 
8885     /*
8886      * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8887      * forever and we can use select() to find out if the socket is ready.
8888      */
8889     if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8890         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8891         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8892         return;
8893     }
8894 
8895     AppData* appData = toAppData(ssl);
8896     if (appData == nullptr) {
8897         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8898         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8899         return;
8900     }
8901 
8902     ret = 0;
8903     SslError sslError;
8904     while (appData->aliveAndKicking) {
8905         errno = 0;
8906 
8907         if (!appData->setCallbackState(env, shc, fdObject)) {
8908             // SocketException thrown by NetFd.isClosed
8909             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8910             return;
8911         }
8912         ret = SSL_do_handshake(ssl);
8913         appData->clearCallbackState();
8914         // cert_verify_callback threw exception
8915         if (env->ExceptionCheck()) {
8916             ERR_clear_error();
8917             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8918             return;
8919         }
8920         // success case
8921         if (ret == 1) {
8922             break;
8923         }
8924         // retry case
8925         if (errno == EINTR) {
8926             continue;
8927         }
8928         // error case
8929         sslError.reset(ssl, ret);
8930         JNI_TRACE(
8931                 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8932                 "timeout_millis=%d",
8933                 ssl, ret, errno, sslError.get(), timeout_millis);
8934 
8935         /*
8936          * If SSL_do_handshake doesn't succeed due to the socket being
8937          * either unreadable or unwritable, we use sslSelect to
8938          * wait for it to become ready. If that doesn't happen
8939          * before the specified timeout or an error occurs, we
8940          * cancel the handshake. Otherwise we try the SSL_connect
8941          * again.
8942          */
8943         if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8944             appData->waitingThreads++;
8945             int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8946 
8947             if (selectResult == THROWN_EXCEPTION) {
8948                 // SocketException thrown by NetFd.isClosed
8949                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8950                 return;
8951             }
8952             if (selectResult == -1) {
8953                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8954                         env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8955                         conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8956                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8957                           ssl);
8958                 return;
8959             }
8960             if (selectResult == 0) {
8961                 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8962                 ERR_clear_error();
8963                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8964                           ssl);
8965                 return;
8966             }
8967         } else {
8968             // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8969             break;
8970         }
8971     }
8972 
8973     // clean error. See SSL_do_handshake(3SSL) man page.
8974     if (ret == 0) {
8975         /*
8976          * The other side closed the socket before the handshake could be
8977          * completed, but everything is within the bounds of the TLS protocol.
8978          * We still might want to find out the real reason of the failure.
8979          */
8980         if (sslError.get() == SSL_ERROR_NONE ||
8981             (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8982             (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8983             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8984         } else {
8985             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8986                     env, ssl, sslError.release(), "SSL handshake terminated",
8987                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8988         }
8989         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8990         return;
8991     }
8992 
8993     // unclean error. See SSL_do_handshake(3SSL) man page.
8994     if (ret < 0) {
8995         /*
8996          * Translate the error and throw exception. We are sure it is an error
8997          * at this point.
8998          */
8999         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9000                 env, ssl, sslError.release(), "SSL handshake aborted",
9001                 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9002         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9003         return;
9004     }
9005     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
9006 }
9007 
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9008 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
9009                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
9010     CHECK_ERROR_QUEUE_ON_RETURN;
9011     SSL* ssl = to_SSL(env, ssl_address, true);
9012     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
9013     if (ssl == nullptr) {
9014         return nullptr;
9015     }
9016     const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
9017     if (cipher == nullptr) {
9018         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
9019         return nullptr;
9020     }
9021     const char* name = SSL_CIPHER_standard_name(cipher);
9022     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
9023     return env->NewStringUTF(name);
9024 }
9025 
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9026 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
9027                                             CONSCRYPT_UNUSED jobject ssl_holder) {
9028     CHECK_ERROR_QUEUE_ON_RETURN;
9029     SSL* ssl = to_SSL(env, ssl_address, true);
9030     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
9031     if (ssl == nullptr) {
9032         return nullptr;
9033     }
9034     const char* protocol = SSL_get_version(ssl);
9035     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
9036     return env->NewStringUTF(protocol);
9037 }
9038 
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9039 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
9040                                                             CONSCRYPT_UNUSED jobject ssl_holder) {
9041     CHECK_ERROR_QUEUE_ON_RETURN;
9042     SSL* ssl = to_SSL(env, ssl_address, true);
9043     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
9044     if (ssl == nullptr) {
9045         return nullptr;
9046     }
9047 
9048     const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
9049     if (chain == nullptr) {
9050         return nullptr;
9051     }
9052 
9053     ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
9054     if (array.get() == nullptr) {
9055         return nullptr;
9056     }
9057 
9058     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
9059     return array.release();
9060 }
9061 
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)9062 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
9063                    SslError* sslError, int read_timeout_millis) {
9064     JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
9065 
9066     if (len == 0) {
9067         // Don't bother doing anything in this case.
9068         return 0;
9069     }
9070 
9071     BIO* rbio = SSL_get_rbio(ssl);
9072     BIO* wbio = SSL_get_wbio(ssl);
9073 
9074     AppData* appData = toAppData(ssl);
9075     JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
9076     if (appData == nullptr) {
9077         return THROW_SSLEXCEPTION;
9078     }
9079 
9080     while (appData->aliveAndKicking) {
9081         errno = 0;
9082 
9083         std::unique_lock<std::mutex> appDataLock(appData->mutex);
9084 
9085         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9086             !SSL_renegotiate_pending(ssl)) {
9087             JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
9088                       SSL_state_string_long(ssl));
9089             return THROW_SSLEXCEPTION;
9090         }
9091 
9092         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9093 
9094         if (!appData->setCallbackState(env, shc, fdObject)) {
9095             return THROWN_EXCEPTION;
9096         }
9097         int result = SSL_read(ssl, buf, len);
9098         appData->clearCallbackState();
9099         // callbacks can happen if server requests renegotiation
9100         if (env->ExceptionCheck()) {
9101             JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
9102             return THROWN_EXCEPTION;
9103         }
9104         sslError->reset(ssl, result);
9105 
9106         JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
9107         if (conscrypt::trace::kWithJniTraceData) {
9108             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9109                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9110                 size_t n = result - i;
9111                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9112                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
9113                 }
9114                 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9115             }
9116         }
9117 
9118         // If we have been successful in moving data around, check whether it
9119         // might make sense to wake up other blocked threads, so they can give
9120         // it a try, too.
9121         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9122             appData->waitingThreads > 0) {
9123             sslNotify(appData);
9124         }
9125 
9126         // If we are blocked by the underlying socket, tell the world that
9127         // there will be one more waiting thread now.
9128         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9129             appData->waitingThreads++;
9130         }
9131 
9132         appDataLock.unlock();
9133 
9134         switch (sslError->get()) {
9135             // Successfully read at least one byte.
9136             case SSL_ERROR_NONE: {
9137                 return result;
9138             }
9139 
9140             // Read zero bytes. End of stream reached.
9141             case SSL_ERROR_ZERO_RETURN: {
9142                 return -1;
9143             }
9144 
9145             // Need to wait for availability of underlying layer, then retry.
9146             case SSL_ERROR_WANT_READ:
9147             case SSL_ERROR_WANT_WRITE: {
9148                 int selectResult =
9149                         sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
9150                 if (selectResult == THROWN_EXCEPTION) {
9151                     return THROWN_EXCEPTION;
9152                 }
9153                 if (selectResult == -1) {
9154                     return THROW_SSLEXCEPTION;
9155                 }
9156                 if (selectResult == 0) {
9157                     return THROW_SOCKETTIMEOUTEXCEPTION;
9158                 }
9159 
9160                 break;
9161             }
9162 
9163             // A problem occurred during a system call, but this is not
9164             // necessarily an error.
9165             case SSL_ERROR_SYSCALL: {
9166                 // Connection closed without proper shutdown. Tell caller we
9167                 // have reached end-of-stream.
9168                 if (result == 0) {
9169                     return -1;
9170                 }
9171 
9172                 // System call has been interrupted. Simply retry.
9173                 if (errno == EINTR) {
9174                     break;
9175                 }
9176 
9177                 // Note that for all other system call errors we fall through
9178                 // to the default case, which results in an Exception.
9179                 FALLTHROUGH_INTENDED;
9180             }
9181 
9182             // Everything else is basically an error.
9183             default: { return THROW_SSLEXCEPTION; }
9184         }
9185     }
9186 
9187     return -1;
9188 }
9189 
9190 /**
9191  * OpenSSL read function (2): read into buffer at offset n chunks.
9192  * Returns the number of bytes read (success) or value <= 0 (failure).
9193  */
NativeCrypto_SSL_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jbyteArray b,jint offset,jint len,jint read_timeout_millis)9194 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
9195                                   CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9196                                   jobject shc, jbyteArray b, jint offset, jint len,
9197                                   jint read_timeout_millis) {
9198     CHECK_ERROR_QUEUE_ON_RETURN;
9199     SSL* ssl = to_SSL(env, ssl_address, true);
9200     JNI_TRACE(
9201             "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
9202             "read_timeout_millis=%d",
9203             ssl, fdObject, shc, b, offset, len, read_timeout_millis);
9204     if (ssl == nullptr) {
9205         return 0;
9206     }
9207     if (fdObject == nullptr) {
9208         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9209         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
9210         return 0;
9211     }
9212     if (shc == nullptr) {
9213         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9214         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
9215         return 0;
9216     }
9217     if (b == nullptr) {
9218         conscrypt::jniutil::throwNullPointerException(env, "b == null");
9219         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
9220         return 0;
9221     }
9222 
9223     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9224     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9225         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9226         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
9227         return 0;
9228     }
9229 
9230     SslError sslError;
9231     int ret;
9232     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9233         if (len <= 1024) {
9234             // Allocate small buffers on the stack for performance.
9235             jbyte buf[1024];
9236             ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
9237                           read_timeout_millis);
9238             if (ret > 0) {
9239                 // Don't bother applying changes if issues were encountered.
9240                 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
9241             }
9242         } else {
9243             // Allocate larger buffers on the heap.
9244             // ARRAY_CHUNK_INVALID above ensures that len >= 0.
9245             jint remaining = len;
9246             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9247             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9248             // TODO(flooey): Use new(std::nothrow).
9249             if (buf.get() == nullptr) {
9250                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9251                 return 0;
9252             }
9253             // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
9254             // by the number of internal calls to sslRead() below.
9255             ret = 0;
9256             while (remaining > 0) {
9257                 jint temp_ret;
9258                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9259                 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
9260                                    chunk_size, &sslError, read_timeout_millis);
9261                 if (temp_ret < 0) {
9262                     if (ret > 0) {
9263                         // We've already read some bytes; attempt to preserve them if this is an
9264                         // "expected" error.
9265                         if (temp_ret == -1) {
9266                             // EOF
9267                             break;
9268                         } else if (temp_ret == THROWN_EXCEPTION) {
9269                             // FD closed. Subsequent calls to sslRead should reproduce the
9270                             // exception.
9271                             env->ExceptionClear();
9272                             break;
9273                         }
9274                     }
9275                     // An error was encountered. Handle below.
9276                     ret = temp_ret;
9277                     break;
9278                 }
9279                 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
9280                 if (env->ExceptionCheck()) {
9281                     // Error committing changes to JVM.
9282                     return -1;
9283                 }
9284                 // Accumulate bytes read.
9285                 ret += temp_ret;
9286                 offset += temp_ret;
9287                 remaining -= temp_ret;
9288                 if (temp_ret < chunk_size) {
9289                     // sslRead isn't able to fulfill our request right now.
9290                     break;
9291                 }
9292             }
9293         }
9294     } else {
9295         ScopedByteArrayRW bytes(env, b);
9296         if (bytes.get() == nullptr) {
9297             JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
9298             return 0;
9299         }
9300 
9301         ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
9302                       &sslError, read_timeout_millis);
9303     }
9304 
9305     int result;
9306     switch (ret) {
9307         case THROW_SSLEXCEPTION:
9308             // See sslRead() regarding improper failure to handle normal cases.
9309             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9310                                                                "Read error");
9311             result = -1;
9312             break;
9313         case THROW_SOCKETTIMEOUTEXCEPTION:
9314             conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
9315             result = -1;
9316             break;
9317         case THROWN_EXCEPTION:
9318             // SocketException thrown by NetFd.isClosed
9319             // or RuntimeException thrown by callback
9320             result = -1;
9321             break;
9322         default:
9323             result = ret;
9324             break;
9325     }
9326 
9327     JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
9328     return result;
9329 }
9330 
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)9331 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
9332                     SslError* sslError, int write_timeout_millis) {
9333     JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
9334               write_timeout_millis);
9335 
9336     if (len == 0) {
9337         // Don't bother doing anything in this case.
9338         return 0;
9339     }
9340 
9341     BIO* rbio = SSL_get_rbio(ssl);
9342     BIO* wbio = SSL_get_wbio(ssl);
9343 
9344     AppData* appData = toAppData(ssl);
9345     JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
9346     if (appData == nullptr) {
9347         return THROW_SSLEXCEPTION;
9348     }
9349 
9350     int count = len;
9351 
9352     while (appData->aliveAndKicking && len > 0) {
9353         errno = 0;
9354 
9355         std::unique_lock<std::mutex> appDataLock(appData->mutex);
9356 
9357         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9358             !SSL_renegotiate_pending(ssl)) {
9359             JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
9360                       SSL_state_string_long(ssl));
9361             return THROW_SSLEXCEPTION;
9362         }
9363 
9364         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9365 
9366         if (!appData->setCallbackState(env, shc, fdObject)) {
9367             return THROWN_EXCEPTION;
9368         }
9369         JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
9370         int result = SSL_write(ssl, buf, len);
9371         appData->clearCallbackState();
9372         // callbacks can happen if server requests renegotiation
9373         if (env->ExceptionCheck()) {
9374             JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
9375             return THROWN_EXCEPTION;
9376         }
9377         sslError->reset(ssl, result);
9378 
9379         JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
9380         if (conscrypt::trace::kWithJniTraceData) {
9381             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9382                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9383                 size_t n = result - i;
9384                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9385                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
9386                 }
9387                 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9388             }
9389         }
9390 
9391         // If we have been successful in moving data around, check whether it
9392         // might make sense to wake up other blocked threads, so they can give
9393         // it a try, too.
9394         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9395             appData->waitingThreads > 0) {
9396             sslNotify(appData);
9397         }
9398 
9399         // If we are blocked by the underlying socket, tell the world that
9400         // there will be one more waiting thread now.
9401         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9402             appData->waitingThreads++;
9403         }
9404 
9405         appDataLock.unlock();
9406 
9407         switch (sslError->get()) {
9408             // Successfully wrote at least one byte.
9409             case SSL_ERROR_NONE: {
9410                 buf += result;
9411                 len -= result;
9412                 break;
9413             }
9414 
9415             // Wrote zero bytes. End of stream reached.
9416             case SSL_ERROR_ZERO_RETURN: {
9417                 return -1;
9418             }
9419 
9420             // Need to wait for availability of underlying layer, then retry.
9421             // The concept of a write timeout doesn't really make sense, and
9422             // it's also not standard Java behavior, so we wait forever here.
9423             case SSL_ERROR_WANT_READ:
9424             case SSL_ERROR_WANT_WRITE: {
9425                 int selectResult =
9426                         sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
9427                 if (selectResult == THROWN_EXCEPTION) {
9428                     return THROWN_EXCEPTION;
9429                 }
9430                 if (selectResult == -1) {
9431                     return THROW_SSLEXCEPTION;
9432                 }
9433                 if (selectResult == 0) {
9434                     return THROW_SOCKETTIMEOUTEXCEPTION;
9435                 }
9436 
9437                 break;
9438             }
9439 
9440             // A problem occurred during a system call, but this is not
9441             // necessarily an error.
9442             case SSL_ERROR_SYSCALL: {
9443                 // Connection closed without proper shutdown. Tell caller we
9444                 // have reached end-of-stream.
9445                 if (result == 0) {
9446                     return -1;
9447                 }
9448 
9449                 // System call has been interrupted. Simply retry.
9450                 if (errno == EINTR) {
9451                     break;
9452                 }
9453 
9454                 // Note that for all other system call errors we fall through
9455                 // to the default case, which results in an Exception.
9456                 FALLTHROUGH_INTENDED;
9457             }
9458 
9459             // Everything else is basically an error.
9460             default: { return THROW_SSLEXCEPTION; }
9461         }
9462     }
9463     JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9464 
9465     return count;
9466 }
9467 
9468 /**
9469  * OpenSSL write function (2): write into buffer at offset n chunks.
9470  */
NativeCrypto_SSL_write(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jbyteArray b,jint offset,jint len,jint write_timeout_millis)9471 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
9472                                    CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9473                                    jobject shc, jbyteArray b, jint offset, jint len,
9474                                    jint write_timeout_millis) {
9475     CHECK_ERROR_QUEUE_ON_RETURN;
9476     SSL* ssl = to_SSL(env, ssl_address, true);
9477     JNI_TRACE(
9478             "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
9479             "write_timeout_millis=%d",
9480             ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9481     if (ssl == nullptr) {
9482         return;
9483     }
9484     if (fdObject == nullptr) {
9485         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9486         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9487         return;
9488     }
9489     if (shc == nullptr) {
9490         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9491         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9492         return;
9493     }
9494     if (b == nullptr) {
9495         conscrypt::jniutil::throwNullPointerException(env, "b == null");
9496         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
9497         return;
9498     }
9499 
9500     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9501     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9502         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9503         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
9504         return;
9505     }
9506 
9507     SslError sslError;
9508     int ret;
9509     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9510         if (len <= 1024) {
9511             jbyte buf[1024];
9512             env->GetByteArrayRegion(b, offset, len, buf);
9513             ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
9514                            &sslError, write_timeout_millis);
9515         } else {
9516             // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
9517             jint remaining = len;
9518             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9519             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9520             if (buf.get() == nullptr) {
9521                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9522                 return;
9523             }
9524             while (remaining > 0) {
9525                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9526                 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
9527                 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
9528                                chunk_size, &sslError, write_timeout_millis);
9529                 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
9530                     ret == THROWN_EXCEPTION) {
9531                     // Encountered an error. Terminate early and handle below.
9532                     break;
9533                 }
9534                 offset += ret;
9535                 remaining -= ret;
9536             }
9537         }
9538     } else {
9539         ScopedByteArrayRO bytes(env, b);
9540         if (bytes.get() == nullptr) {
9541             JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9542             return;
9543         }
9544         ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9545                        len, &sslError, write_timeout_millis);
9546     }
9547 
9548     switch (ret) {
9549         case THROW_SSLEXCEPTION:
9550             // See sslWrite() regarding improper failure to handle normal cases.
9551             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9552                                                                "Write error");
9553             break;
9554         case THROW_SOCKETTIMEOUTEXCEPTION:
9555             conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9556             break;
9557         case THROWN_EXCEPTION:
9558             // SocketException thrown by NetFd.isClosed
9559             break;
9560         default:
9561             break;
9562     }
9563 }
9564 
9565 /**
9566  * Interrupt any pending I/O before closing the socket.
9567  */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9568 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9569                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9570     CHECK_ERROR_QUEUE_ON_RETURN;
9571     SSL* ssl = to_SSL(env, ssl_address, false);
9572     JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9573     if (ssl == nullptr) {
9574         return;
9575     }
9576 
9577     /*
9578      * Mark the connection as quasi-dead, then send something to the emergency
9579      * file descriptor, so any blocking select() calls are woken up.
9580      */
9581     AppData* appData = toAppData(ssl);
9582     if (appData != nullptr) {
9583         appData->aliveAndKicking = false;
9584 
9585         // At most two threads can be waiting.
9586         sslNotify(appData);
9587         sslNotify(appData);
9588     }
9589 }
9590 
9591 /**
9592  * OpenSSL close SSL socket function.
9593  */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9594 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9595                                       CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9596                                       jobject shc) {
9597     CHECK_ERROR_QUEUE_ON_RETURN;
9598     SSL* ssl = to_SSL(env, ssl_address, false);
9599     JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9600     if (ssl == nullptr) {
9601         return;
9602     }
9603     if (fdObject == nullptr) {
9604         return;
9605     }
9606     if (shc == nullptr) {
9607         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9608         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9609         return;
9610     }
9611 
9612     AppData* appData = toAppData(ssl);
9613     if (appData != nullptr) {
9614         if (!appData->setCallbackState(env, shc, fdObject)) {
9615             // SocketException thrown by NetFd.isClosed
9616             ERR_clear_error();
9617             return;
9618         }
9619 
9620         /*
9621          * Try to make socket blocking again. OpenSSL literature recommends this.
9622          */
9623         int fd = SSL_get_fd(ssl);
9624         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9625 #ifndef _WIN32
9626         if (fd != -1) {
9627             conscrypt::netutil::setBlocking(fd, true);
9628         }
9629 #endif
9630 
9631         int ret = SSL_shutdown(ssl);
9632         appData->clearCallbackState();
9633         // callbacks can happen if server requests renegotiation
9634         if (env->ExceptionCheck()) {
9635             JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9636             return;
9637         }
9638         switch (ret) {
9639             case 0:
9640                 /*
9641                  * Shutdown was not successful (yet), but there also
9642                  * is no error. Since we can't know whether the remote
9643                  * server is actually still there, and we don't want to
9644                  * get stuck forever in a second SSL_shutdown() call, we
9645                  * simply return. This is not security a problem as long
9646                  * as we close the underlying socket, which we actually
9647                  * do, because that's where we are just coming from.
9648                  */
9649                 break;
9650             case 1:
9651                 /*
9652                  * Shutdown was successful. We can safely return. Hooray!
9653                  */
9654                 break;
9655             default:
9656                 /*
9657                  * Everything else is a real error condition. We should
9658                  * let the Java layer know about this by throwing an
9659                  * exception.
9660                  */
9661                 int sslError = SSL_get_error(ssl, ret);
9662                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9663                                                                    "SSL shutdown failed");
9664                 break;
9665         }
9666     }
9667 
9668     ERR_clear_error();
9669 }
9670 
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9671 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9672                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9673     CHECK_ERROR_QUEUE_ON_RETURN;
9674     const SSL* ssl = to_SSL(env, ssl_address, true);
9675     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9676     if (ssl == nullptr) {
9677         return 0;
9678     }
9679 
9680     int status = SSL_get_shutdown(ssl);
9681     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9682     return static_cast<jint>(status);
9683 }
9684 
9685 /**
9686  * public static native void SSL_free(long ssl);
9687  */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9688 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9689                                   CONSCRYPT_UNUSED jobject ssl_holder) {
9690     CHECK_ERROR_QUEUE_ON_RETURN;
9691     SSL* ssl = to_SSL(env, ssl_address, true);
9692     JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9693     if (ssl == nullptr) {
9694         return;
9695     }
9696 
9697     AppData* appData = toAppData(ssl);
9698     SSL_set_app_data(ssl, nullptr);
9699     delete appData;
9700     SSL_free(ssl);
9701 }
9702 
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9703 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9704     unsigned int length;
9705     const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9706     JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9707     if (id && length > 0) {
9708         jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9709         if (result != nullptr) {
9710             const jbyte* src = reinterpret_cast<const jbyte*>(id);
9711             env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9712         }
9713         return result;
9714     }
9715     return nullptr;
9716 }
9717 
9718 /**
9719  * Gets and returns in a byte array the ID of the actual SSL session.
9720  */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9721 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9722                                                       jlong ssl_session_address) {
9723     CHECK_ERROR_QUEUE_ON_RETURN;
9724     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9725     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9726     if (ssl_session == nullptr) {
9727         return nullptr;
9728     }
9729     jbyteArray result = get_session_id(env, ssl_session);
9730     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9731     return result;
9732 }
9733 
9734 /**
9735  * Gets and returns in a long integer the creation's time of the
9736  * actual SSL session.
9737  */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9738 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9739     CHECK_ERROR_QUEUE_ON_RETURN;
9740     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9741     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9742     if (ssl_session == nullptr) {
9743         return 0;
9744     }
9745     // result must be jlong, not long or *1000 will overflow
9746     jlong result = SSL_SESSION_get_time(ssl_session);
9747     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9748     // NOLINTNEXTLINE(runtime/int)
9749     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9750               (long long)result);  // NOLINT(runtime/int)
9751     return result;
9752 }
9753 
9754 /**
9755  * Gets and returns in a long integer the creation's time of the
9756  * actual SSL session.
9757  */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9758 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9759                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9760     CHECK_ERROR_QUEUE_ON_RETURN;
9761     SSL* ssl = to_SSL(env, ssl_address, true);
9762     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9763     if (ssl == nullptr) {
9764         return 0;
9765     }
9766 
9767     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9768     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9769     if (ssl_session == nullptr) {
9770         // BoringSSL does not protect against a NULL session.
9771         return 0;
9772     }
9773     // result must be jlong, not long or *1000 will overflow
9774     jlong result = SSL_SESSION_get_time(ssl_session);
9775     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9776     // NOLINTNEXTLINE(runtime/int)
9777     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9778     return result;
9779 }
9780 
9781 /**
9782  * Sets the timeout on the SSL session.
9783  */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9784 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9785                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9786     CHECK_ERROR_QUEUE_ON_RETURN;
9787     SSL* ssl = to_SSL(env, ssl_address, true);
9788     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9789     if (ssl == nullptr) {
9790         return 0;
9791     }
9792 
9793     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9794     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9795     if (ssl_session == nullptr) {
9796         // BoringSSL does not protect against a NULL session.
9797         return 0;
9798     }
9799 
9800     // Convert to seconds
9801     static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9802     uint32_t timeout = static_cast<uint32_t>(
9803             std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9804     return SSL_set_timeout(ssl_session, timeout);
9805 }
9806 
9807 /**
9808  * Gets the timeout for the SSL session.
9809  */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9810 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9811                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9812     CHECK_ERROR_QUEUE_ON_RETURN;
9813     SSL* ssl = to_SSL(env, ssl_address, true);
9814     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9815     if (ssl == nullptr) {
9816         return 0;
9817     }
9818 
9819     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9820     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9821     if (ssl_session == nullptr) {
9822         // BoringSSL does not protect against a NULL session.
9823         return 0;
9824     }
9825 
9826     jlong result = SSL_get_timeout(ssl_session);
9827     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9828     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9829               (long long)result)  // NOLINT(runtime/int);
9830     return result;
9831 }
9832 
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9833 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9834                                                               jint signatureAlg) {
9835     CHECK_ERROR_QUEUE_ON_RETURN;
9836     return SSL_get_signature_algorithm_key_type(signatureAlg);
9837 }
9838 
9839 /**
9840  * Gets the timeout for the SSL session.
9841  */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9842 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9843     CHECK_ERROR_QUEUE_ON_RETURN;
9844     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9845     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9846     if (ssl_session == nullptr) {
9847         return 0;
9848     }
9849 
9850     return SSL_get_timeout(ssl_session);
9851 }
9852 
9853 /**
9854  * Gets the ID for the SSL session, or null if no session is currently available.
9855  */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9856 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9857                                               CONSCRYPT_UNUSED jobject ssl_holder) {
9858     CHECK_ERROR_QUEUE_ON_RETURN;
9859     SSL* ssl = to_SSL(env, ssl_address, true);
9860     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9861     if (ssl == nullptr) {
9862         return nullptr;
9863     }
9864 
9865     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9866     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9867     if (ssl_session == nullptr) {
9868         return nullptr;
9869     }
9870     jbyteArray result = get_session_id(env, ssl_session);
9871     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9872     return result;
9873 }
9874 
9875 /**
9876  * Gets and returns in a string the version of the SSL protocol. If it
9877  * returns the string "unknown" it means that no connection is established.
9878  */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9879 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9880                                                     jlong ssl_session_address) {
9881     CHECK_ERROR_QUEUE_ON_RETURN;
9882     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9883     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9884     if (ssl_session == nullptr) {
9885         return nullptr;
9886     }
9887     const char* protocol = SSL_SESSION_get_version(ssl_session);
9888     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9889     return env->NewStringUTF(protocol);
9890 }
9891 
9892 /**
9893  * Gets and returns in a string the cipher negotiated for the SSL session.
9894  */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9895 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9896     CHECK_ERROR_QUEUE_ON_RETURN;
9897     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9898     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9899     if (ssl_session == nullptr) {
9900         return nullptr;
9901     }
9902     const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9903     const char* name = SSL_CIPHER_standard_name(cipher);
9904     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9905     return env->NewStringUTF(name);
9906 }
9907 
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9908 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9909                                                               jlong ssl_session_address) {
9910     CHECK_ERROR_QUEUE_ON_RETURN;
9911     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9912     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9913     if (ssl_session == nullptr) {
9914         return JNI_FALSE;
9915     }
9916     int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9917     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9918               single_use);
9919     return single_use ? JNI_TRUE : JNI_FALSE;
9920 }
9921 
9922 /**
9923  * Increments the reference count of the session.
9924  */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9925 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9926     CHECK_ERROR_QUEUE_ON_RETURN;
9927     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9928     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9929     if (ssl_session == nullptr) {
9930         return;
9931     }
9932     SSL_SESSION_up_ref(ssl_session);
9933 }
9934 
9935 /**
9936  * Frees the SSL session.
9937  */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9938 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9939     CHECK_ERROR_QUEUE_ON_RETURN;
9940     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9941     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9942     if (ssl_session == nullptr) {
9943         return;
9944     }
9945     SSL_SESSION_free(ssl_session);
9946 }
9947 
9948 /**
9949  * Serializes the native state of the session (ID, cipher, and keys but
9950  * not certificates). Returns a byte[] containing the DER-encoded state.
9951  * See apache mod_ssl.
9952  */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9953 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9954     CHECK_ERROR_QUEUE_ON_RETURN;
9955     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9956     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9957     if (ssl_session == nullptr) {
9958         return nullptr;
9959     }
9960     return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9961 }
9962 
9963 /**
9964  * Deserialize the session.
9965  */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9966 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9967     CHECK_ERROR_QUEUE_ON_RETURN;
9968     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9969 
9970     ScopedByteArrayRO bytes(env, javaBytes);
9971     if (bytes.get() == nullptr) {
9972         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9973         return 0;
9974     }
9975     const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9976     // NOLINTNEXTLINE(runtime/int)
9977     SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9978 
9979     if (ssl_session == nullptr ||
9980         ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9981         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9982                                                              conscrypt::jniutil::throwIOException);
9983         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9984         return 0L;
9985     }
9986 
9987     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9988     return reinterpret_cast<uintptr_t>(ssl_session);
9989 }
9990 
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9991 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9992     CHECK_ERROR_QUEUE_ON_RETURN;
9993     const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
9994     if (cipher == nullptr) {
9995         return nullptr;
9996     }
9997 
9998     const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
9999     return env->NewStringUTF(kx_name);
10000 }
10001 
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)10002 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
10003     CHECK_ERROR_QUEUE_ON_RETURN;
10004     ScopedUtfChars selector(env, selectorJava);
10005     if (selector.c_str() == nullptr) {
10006         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10007                                            "selector == null");
10008         return nullptr;
10009     }
10010 
10011     JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
10012 
10013     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
10014     bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
10015 
10016     if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
10017         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10018                                            "Unable to set SSL cipher list");
10019         return nullptr;
10020     }
10021     STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
10022 
10023     size_t size = sk_SSL_CIPHER_num(ciphers);
10024     ScopedLocalRef<jobjectArray> cipherNamesArray(
10025             env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
10026                                      nullptr));
10027     if (cipherNamesArray.get() == nullptr) {
10028         return nullptr;
10029     }
10030 
10031     // Return an array of standard and OpenSSL name pairs.
10032     for (size_t i = 0; i < size; i++) {
10033         const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
10034         ScopedLocalRef<jstring> cipherName(env,
10035                                            env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
10036         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
10037                                    cipherName.get());
10038 
10039         ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
10040         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
10041                                    opensslName.get());
10042     }
10043 
10044     JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
10045               2 * size);
10046     return cipherNamesArray.release();
10047 }
10048 
10049 /**
10050  * Compare the given CertID with a certificate and it's issuer.
10051  * True is returned if the CertID matches.
10052  */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)10053 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
10054     // Get the hash algorithm used by this CertID
10055     CBS hash_algorithm, hash;
10056     if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
10057         !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
10058         return false;
10059     }
10060 
10061     // Get the issuer's name hash from the CertID
10062     CBS issuer_name_hash;
10063     if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
10064         return false;
10065     }
10066 
10067     // Get the issuer's key hash from the CertID
10068     CBS issuer_key_hash;
10069     if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
10070         return false;
10071     }
10072 
10073     // Get the serial number from the CertID
10074     CBS serial;
10075     if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
10076         return false;
10077     }
10078 
10079     // Compare the certificate's serial number with the one from the Cert ID
10080     const uint8_t* p = CBS_data(&serial);
10081     bssl::UniquePtr<ASN1_INTEGER> serial_number(
10082             c2i_ASN1_INTEGER(nullptr, &p,
10083                              static_cast<long>(CBS_len(&serial))));  // NOLINT(runtime/int)
10084     const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
10085     if (serial_number.get() == nullptr ||
10086         ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
10087         return false;
10088     }
10089 
10090     // Find the hash algorithm to be used
10091     const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
10092     if (digest == nullptr) {
10093         return false;
10094     }
10095 
10096     // Hash the issuer's name and compare the hash with the one from the Cert ID
10097     uint8_t md[EVP_MAX_MD_SIZE];
10098     const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
10099     if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
10100         !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
10101         return false;
10102     }
10103 
10104     // Same thing with the issuer's key
10105     const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
10106     if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
10107                     static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
10108                     nullptr) ||
10109         !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
10110         return false;
10111     }
10112 
10113     return true;
10114 }
10115 
10116 /**
10117  * Get a SingleResponse whose CertID matches the given certificate and issuer from a
10118  * SEQUENCE OF SingleResponse.
10119  *
10120  * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
10121  * error occured or no response matches the certificate, false is returned and |out_single_response|
10122  * is unchanged.
10123  */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)10124 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
10125                                       CBS* out_single_response) {
10126     // Iterate over all the SingleResponses, until one matches the certificate
10127     while (CBS_len(responses) > 0) {
10128         // Get the next available SingleResponse from the sequence
10129         CBS single_response;
10130         if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
10131             return false;
10132         }
10133 
10134         // Make a copy of the stream so we pass it back to the caller
10135         CBS single_response_original = single_response;
10136 
10137         // Get the SingleResponse's CertID
10138         // If this fails ignore the current response and move to the next one
10139         CBS cert_id;
10140         if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
10141             continue;
10142         }
10143 
10144         // Compare the CertID with the given certificate and issuer
10145         if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
10146             *out_single_response = single_response_original;
10147             return true;
10148         }
10149     }
10150 
10151     return false;
10152 }
10153 
10154 /**
10155  * Get the BasicOCSPResponse from an OCSPResponse.
10156  * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
10157  * returned.
10158  */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)10159 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
10160     CBS tagged_response_bytes, response_bytes, response_type, response;
10161 
10162     // Get the ResponseBytes out of the OCSPResponse
10163     if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
10164         !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
10165                       CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10166         !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
10167         return false;
10168     }
10169 
10170     // Parse the response type and data out of the ResponseBytes
10171     if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
10172         !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
10173         return false;
10174     }
10175 
10176     // Only basic OCSP responses are supported
10177     if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
10178         return false;
10179     }
10180 
10181     // Parse the octet string as a BasicOCSPResponse
10182     return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
10183 }
10184 
10185 /**
10186  * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
10187  * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
10188  * true is returned.
10189  */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)10190 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
10191     // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
10192     CBS response_data;
10193     if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
10194         return false;
10195     }
10196 
10197     // Skip the version, responderID and producedAt fields
10198     if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
10199                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10200         !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
10201         !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
10202         return false;
10203     }
10204 
10205     // Extract the list of SingleResponse.
10206     return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
10207 }
10208 
10209 /**
10210  * Get the SEQUENCE OF Extension from a SingleResponse.
10211  * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
10212  * returned.
10213  */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)10214 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
10215     // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
10216     if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
10217         !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
10218         !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
10219         !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
10220                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
10221         return false;
10222     }
10223 
10224     // Get the list of Extension
10225     return CBS_get_asn1(single_response, extensions,
10226                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
10227 }
10228 
10229 /*
10230     public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
10231                                                           long x509Ref, long issuerX509Ref);
10232 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)10233 static jbyteArray NativeCrypto_get_ocsp_single_extension(
10234         JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
10235         CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
10236     CHECK_ERROR_QUEUE_ON_RETURN;
10237     ScopedByteArrayRO ocspData(env, ocspDataBytes);
10238     if (ocspData.get() == nullptr) {
10239         return nullptr;
10240     }
10241 
10242     CBS cbs;
10243     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
10244 
10245     // Start parsing the OCSPResponse
10246     CBS ocsp_response;
10247     if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
10248         return nullptr;
10249     }
10250 
10251     // Get the BasicOCSPResponse from the OCSP Response
10252     CBS basic_response;
10253     if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
10254         return nullptr;
10255     }
10256 
10257     // Get the list of SingleResponses from the BasicOCSPResponse
10258     CBS responses;
10259     if (!get_ocsp_single_responses(&basic_response, &responses)) {
10260         return nullptr;
10261     }
10262 
10263     // Find the response matching the certificate
10264     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
10265     X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
10266     CBS single_response;
10267     if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
10268         return nullptr;
10269     }
10270 
10271     // Get the extensions from the SingleResponse
10272     CBS extensions;
10273     if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
10274         return nullptr;
10275     }
10276 
10277     const uint8_t* ptr = CBS_data(&extensions);
10278     bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
10279             d2i_X509_EXTENSIONS(nullptr, &ptr,
10280                                 static_cast<long>(CBS_len(&extensions))));  // NOLINT(runtime/int)
10281     if (x509_exts.get() == nullptr) {
10282         return nullptr;
10283     }
10284 
10285     return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
10286             env, x509_exts.get(), oid);
10287 }
10288 
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)10289 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
10290     // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
10291     // no throwing if the buffer is null or not a direct ByteBuffer.
10292     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
10293         return 0;
10294     }
10295     return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
10296 }
10297 
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)10298 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
10299                                        CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
10300     CHECK_ERROR_QUEUE_ON_RETURN;
10301     SSL* ssl = to_SSL(env, ssl_address, true);
10302     if (ssl == nullptr) {
10303         return 0;
10304     }
10305     return SSL_get_error(ssl, ret);
10306 }
10307 
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)10308 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
10309     ERR_clear_error();
10310 }
10311 
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10312 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
10313                                                     CONSCRYPT_UNUSED jobject ssl_holder) {
10314     CHECK_ERROR_QUEUE_ON_RETURN;
10315     SSL* ssl = to_SSL(env, ssl_address, true);
10316     if (ssl == nullptr) {
10317         return 0;
10318     }
10319     return SSL_pending(ssl);
10320 }
10321 
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)10322 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
10323     CHECK_ERROR_QUEUE_ON_RETURN;
10324     BIO* bio = to_BIO(env, bio_address);
10325     if (bio == nullptr) {
10326         return 0;
10327     }
10328     return static_cast<jint>(BIO_ctrl_pending(bio));
10329 }
10330 
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10331 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
10332                                                CONSCRYPT_UNUSED jobject ssl_holder) {
10333     CHECK_ERROR_QUEUE_ON_RETURN;
10334     SSL* ssl = to_SSL(env, ssl_address, true);
10335     if (ssl == nullptr) {
10336         return 0;
10337     }
10338     return (jint)SSL_max_seal_overhead(ssl);
10339 }
10340 
10341 /**
10342  * public static native int SSL_new_BIO(long ssl) throws SSLException;
10343  */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10344 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
10345                                       CONSCRYPT_UNUSED jobject ssl_holder) {
10346     CHECK_ERROR_QUEUE_ON_RETURN;
10347     SSL* ssl = to_SSL(env, ssl_address, true);
10348     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
10349     if (ssl == nullptr) {
10350         return 0;
10351     }
10352 
10353     BIO* internal_bio;
10354     BIO* network_bio;
10355     if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
10356         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
10357                                                            "BIO_new_bio_pair failed");
10358         JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
10359         return 0;
10360     }
10361 
10362     SSL_set_bio(ssl, internal_bio, internal_bio);
10363 
10364     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
10365     return reinterpret_cast<uintptr_t>(network_bio);
10366 }
10367 
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10368 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
10369                                                  CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10370     CHECK_ERROR_QUEUE_ON_RETURN;
10371     SSL* ssl = to_SSL(env, ssl_address, true);
10372     if (ssl == nullptr) {
10373         return 0;
10374     }
10375     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
10376 
10377     if (shc == nullptr) {
10378         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10379         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
10380                   ssl);
10381         return 0;
10382     }
10383 
10384     AppData* appData = toAppData(ssl);
10385     if (appData == nullptr) {
10386         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10387         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
10388         return 0;
10389     }
10390 
10391     errno = 0;
10392 
10393     if (!appData->setCallbackState(env, shc, nullptr)) {
10394         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10395         ERR_clear_error();
10396         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10397         return 0;
10398     }
10399 
10400     int ret = SSL_do_handshake(ssl);
10401     appData->clearCallbackState();
10402     if (env->ExceptionCheck()) {
10403         // cert_verify_callback threw exception
10404         ERR_clear_error();
10405         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10406         return 0;
10407     }
10408 
10409     SslError sslError(ssl, ret);
10410     int code = sslError.get();
10411 
10412     if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
10413         // Non-exceptional case.
10414         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
10415         return code;
10416     }
10417 
10418     // Exceptional case...
10419     if (ret == 0) {
10420         // TODO(nmittler): Can this happen with memory BIOs?
10421         /*
10422          * Clean error. See SSL_do_handshake(3SSL) man page.
10423          * The other side closed the socket before the handshake could be
10424          * completed, but everything is within the bounds of the TLS protocol.
10425          * We still might want to find out the real reason of the failure.
10426          */
10427         if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
10428             (code == SSL_ERROR_ZERO_RETURN)) {
10429             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
10430         } else {
10431             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10432                     env, ssl, sslError.release(), "SSL handshake terminated",
10433                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10434         }
10435         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
10436         return code;
10437     }
10438 
10439     /*
10440      * Unclean error. See SSL_do_handshake(3SSL) man page.
10441      * Translate the error and throw exception. We are sure it is an error
10442      * at this point.
10443      */
10444     conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10445             env, ssl, sslError.release(), "SSL handshake aborted",
10446             conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10447     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
10448     return code;
10449 }
10450 
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10451 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
10452                                              CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10453     CHECK_ERROR_QUEUE_ON_RETURN;
10454     SSL* ssl = to_SSL(env, ssl_address, false);
10455     if (ssl == nullptr) {
10456         return;
10457     }
10458     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
10459 
10460     if (shc == nullptr) {
10461         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10462         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10463         return;
10464     }
10465 
10466     AppData* appData = toAppData(ssl);
10467     if (appData != nullptr) {
10468         if (!appData->setCallbackState(env, shc, nullptr)) {
10469             conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10470             ERR_clear_error();
10471             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10472             return;
10473         }
10474         int ret = SSL_shutdown(ssl);
10475         appData->clearCallbackState();
10476         // callbacks can happen if server requests renegotiation
10477         if (env->ExceptionCheck()) {
10478             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10479             return;
10480         }
10481         switch (ret) {
10482             case 0:
10483                 /*
10484                  * Shutdown was not successful (yet), but there also
10485                  * is no error. Since we can't know whether the remote
10486                  * server is actually still there, and we don't want to
10487                  * get stuck forever in a second SSL_shutdown() call, we
10488                  * simply return. This is not security a problem as long
10489                  * as we close the underlying socket, which we actually
10490                  * do, because that's where we are just coming from.
10491                  */
10492                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
10493                 break;
10494             case 1:
10495                 /*
10496                  * Shutdown was successful. We can safely return. Hooray!
10497                  */
10498                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
10499                 break;
10500             default:
10501                 /*
10502                  * Everything else is a real error condition. We should
10503                  * let the Java layer know about this by throwing an
10504                  * exception.
10505                  */
10506                 int sslError = SSL_get_error(ssl, ret);
10507                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
10508                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
10509                                                                    "SSL shutdown failed");
10510                 break;
10511         }
10512     }
10513 
10514     ERR_clear_error();
10515 }
10516 
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)10517 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
10518                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10519                                                 jint length, jobject shc) {
10520     CHECK_ERROR_QUEUE_ON_RETURN;
10521     SSL* ssl = to_SSL(env, ssl_address, true);
10522     char* destPtr = reinterpret_cast<char*>(address);
10523     if (ssl == nullptr) {
10524         return -1;
10525     }
10526     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
10527               destPtr, length, shc);
10528 
10529     if (shc == nullptr) {
10530         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10531         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
10532                   ssl);
10533         return -1;
10534     }
10535     AppData* appData = toAppData(ssl);
10536     if (appData == nullptr) {
10537         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10538         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
10539         return -1;
10540     }
10541     if (!appData->setCallbackState(env, shc, nullptr)) {
10542         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10543         ERR_clear_error();
10544         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
10545         return -1;
10546     }
10547 
10548     errno = 0;
10549 
10550     int result = SSL_read(ssl, destPtr, length);
10551     appData->clearCallbackState();
10552     if (env->ExceptionCheck()) {
10553         // An exception was thrown by one of the callbacks. Just propagate that exception.
10554         ERR_clear_error();
10555         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10556         return -1;
10557     }
10558 
10559     SslError sslError(ssl, result);
10560     switch (sslError.get()) {
10561         case SSL_ERROR_NONE: {
10562             // Successfully read at least one byte. Just return the result.
10563             break;
10564         }
10565         case SSL_ERROR_ZERO_RETURN: {
10566             // A close_notify was received, this stream is finished.
10567             return -SSL_ERROR_ZERO_RETURN;
10568         }
10569         case SSL_ERROR_WANT_READ:
10570         case SSL_ERROR_WANT_WRITE: {
10571             // Return the negative of these values.
10572             result = -sslError.get();
10573             break;
10574         }
10575         case SSL_ERROR_SYSCALL: {
10576             // A problem occurred during a system call, but this is not
10577             // necessarily an error.
10578             if (result == 0) {
10579                 // TODO(nmittler): Can this happen with memory BIOs?
10580                 // Connection closed without proper shutdown. Tell caller we
10581                 // have reached end-of-stream.
10582                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10583                 break;
10584             }
10585 
10586             if (errno == EINTR) {
10587                 // TODO(nmittler): Can this happen with memory BIOs?
10588                 // System call has been interrupted. Simply retry.
10589                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10590                                                    "Read error");
10591                 break;
10592             }
10593 
10594             // Note that for all other system call errors we fall through
10595             // to the default case, which results in an Exception.
10596             FALLTHROUGH_INTENDED;
10597         }
10598         default: {
10599             // Everything else is basically an error.
10600             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10601                                                                "Read error");
10602             break;
10603         }
10604     }
10605 
10606     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10607               ssl, destPtr, length, shc, result);
10608     return result;
10609 }
10610 
NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong bioRef,jlong address,jint len,jobject shc)10611 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10612                                                     CONSCRYPT_UNUSED jobject ssl_holder,
10613                                                     jlong bioRef, jlong address, jint len,
10614                                                     jobject shc) {
10615     CHECK_ERROR_QUEUE_ON_RETURN;
10616     SSL* ssl = to_SSL(env, ssl_address, true);
10617     if (ssl == nullptr) {
10618         return -1;
10619     }
10620     if (shc == nullptr) {
10621         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10622         JNI_TRACE(
10623                 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10624                 "sslHandshakeCallbacks == null",
10625                 ssl);
10626         return -1;
10627     }
10628     BIO* bio = to_BIO(env, bioRef);
10629     if (bio == nullptr) {
10630         return -1;
10631     }
10632     if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10633         // The network BIO couldn't handle the entire write. Don't write anything, so that we
10634         // only process one packet at a time.
10635         return 0;
10636     }
10637     const char* sourcePtr = reinterpret_cast<const char*>(address);
10638 
10639     AppData* appData = toAppData(ssl);
10640     if (appData == nullptr) {
10641         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10642         ERR_clear_error();
10643         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10644         return -1;
10645     }
10646     if (!appData->setCallbackState(env, shc, nullptr)) {
10647         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10648         ERR_clear_error();
10649         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10650         return -1;
10651     }
10652 
10653     errno = 0;
10654 
10655     int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10656     appData->clearCallbackState();
10657     JNI_TRACE(
10658             "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10659             "ret=%d",
10660             ssl, bio, sourcePtr, len, shc, result);
10661     JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10662                           static_cast<size_t>(result));
10663     return result;
10664 }
10665 
NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong bioRef,jlong address,jint outputSize,jobject shc)10666 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10667                                                    CONSCRYPT_UNUSED jobject ssl_holder,
10668                                                    jlong bioRef, jlong address, jint outputSize,
10669                                                    jobject shc) {
10670     CHECK_ERROR_QUEUE_ON_RETURN;
10671     SSL* ssl = to_SSL(env, ssl_address, true);
10672     if (ssl == nullptr) {
10673         return -1;
10674     }
10675     if (shc == nullptr) {
10676         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10677         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10678                   ssl);
10679         return -1;
10680     }
10681     BIO* bio = to_BIO(env, bioRef);
10682     if (bio == nullptr) {
10683         return -1;
10684     }
10685     char* destPtr = reinterpret_cast<char*>(address);
10686     if (destPtr == nullptr) {
10687         conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10688         return -1;
10689     }
10690 
10691     AppData* appData = toAppData(ssl);
10692     if (appData == nullptr) {
10693         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10694         ERR_clear_error();
10695         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10696         return -1;
10697     }
10698     if (!appData->setCallbackState(env, shc, nullptr)) {
10699         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10700         ERR_clear_error();
10701         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10702         return -1;
10703     }
10704 
10705     errno = 0;
10706 
10707     int result = BIO_read(bio, destPtr, outputSize);
10708     appData->clearCallbackState();
10709     JNI_TRACE(
10710             "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10711             "=> ret=%d",
10712             ssl, bio, destPtr, outputSize, shc, result);
10713     JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10714     return result;
10715 }
10716 
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10717 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10718                                                CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10719     CHECK_ERROR_QUEUE_ON_RETURN;
10720     SSL* ssl = to_SSL(env, ssl_address, true);
10721     if (ssl == nullptr) {
10722         return;
10723     }
10724     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10725     if (shc == nullptr) {
10726         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10727         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10728                   ssl);
10729         return;
10730     }
10731     AppData* appData = toAppData(ssl);
10732     if (appData == nullptr) {
10733         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10734         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10735         return;
10736     }
10737     if (!appData->setCallbackState(env, shc, nullptr)) {
10738         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10739         ERR_clear_error();
10740         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10741         return;
10742     }
10743     char c;
10744     int result = SSL_peek(ssl, &c, 1);
10745     appData->clearCallbackState();
10746     if (env->ExceptionCheck()) {
10747         // An exception was thrown by one of the callbacks. Just propagate that exception.
10748         ERR_clear_error();
10749         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10750         return;
10751     }
10752 
10753     SslError sslError(ssl, result);
10754     switch (sslError.get()) {
10755         case SSL_ERROR_NONE:
10756         case SSL_ERROR_ZERO_RETURN:
10757         case SSL_ERROR_WANT_READ:
10758         case SSL_ERROR_WANT_WRITE: {
10759             // The call succeeded, lacked data, or the SSL is closed.  All is well.
10760             break;
10761         }
10762         case SSL_ERROR_SYSCALL: {
10763             // A problem occurred during a system call, but this is not
10764             // necessarily an error.
10765             if (result == 0) {
10766                 // TODO(nmittler): Can this happen with memory BIOs?
10767                 // Connection closed without proper shutdown. Tell caller we
10768                 // have reached end-of-stream.
10769                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10770                 break;
10771             }
10772 
10773             if (errno == EINTR) {
10774                 // TODO(nmittler): Can this happen with memory BIOs?
10775                 // System call has been interrupted. Simply retry.
10776                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10777                                                    "Read error");
10778                 break;
10779             }
10780 
10781             // Note that for all other system call errors we fall through
10782             // to the default case, which results in an Exception.
10783             FALLTHROUGH_INTENDED;
10784         }
10785         default: {
10786             // Everything else is basically an error.
10787             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10788                                                                "Read error");
10789             break;
10790         }
10791     }
10792 
10793     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10794 }
10795 
10796 /**
10797  * OpenSSL write function (2): write into buffer at offset n chunks.
10798  */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10799 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10800                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10801                                                 jint len, jobject shc) {
10802     CHECK_ERROR_QUEUE_ON_RETURN;
10803     SSL* ssl = to_SSL(env, ssl_address, true);
10804     const char* sourcePtr = reinterpret_cast<const char*>(address);
10805     if (ssl == nullptr) {
10806         return -1;
10807     }
10808     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10809               sourcePtr, len, shc);
10810     if (shc == nullptr) {
10811         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10812         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10813                   ssl);
10814         return -1;
10815     }
10816 
10817     AppData* appData = toAppData(ssl);
10818     if (appData == nullptr) {
10819         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10820         ERR_clear_error();
10821         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10822         return -1;
10823     }
10824     if (!appData->setCallbackState(env, shc, nullptr)) {
10825         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10826         ERR_clear_error();
10827         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10828         return -1;
10829     }
10830 
10831     errno = 0;
10832 
10833     int result = SSL_write(ssl, sourcePtr, len);
10834     appData->clearCallbackState();
10835     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10836               ssl, sourcePtr, len, shc, result);
10837     return result;
10838 }
10839 
10840 /**
10841  * public static native bool usesBoringSsl_FIPS_mode();
10842  */
NativeCrypto_usesBoringSsl_FIPS_mode()10843 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
10844     return FIPS_mode();
10845 }
10846 
10847 /**
10848  * Scrypt support
10849  */
10850 
NativeCrypto_Scrypt_generate_key(JNIEnv * env,jclass,jbyteArray password,jbyteArray salt,jint n,jint r,jint p,jint key_len)10851 static jbyteArray NativeCrypto_Scrypt_generate_key(JNIEnv* env, jclass, jbyteArray password, jbyteArray salt,
10852                                                    jint n, jint r, jint p, jint key_len) {
10853     CHECK_ERROR_QUEUE_ON_RETURN;
10854     JNI_TRACE("Scrypt_generate_key(%p, %p, %d, %d, %d, %d)", password, salt, n, r, p, key_len);
10855 
10856     if (password == nullptr) {
10857         conscrypt::jniutil::throwNullPointerException(env, "password == null");
10858         JNI_TRACE("Scrypt_generate_key() => password == null");
10859         return nullptr;
10860     }
10861     if (salt == nullptr) {
10862         conscrypt::jniutil::throwNullPointerException(env, "salt == null");
10863         JNI_TRACE("Scrypt_generate_key() => salt == null");
10864         return nullptr;
10865     }
10866 
10867     jbyteArray key_bytes = env->NewByteArray(static_cast<jsize>(key_len));
10868     ScopedByteArrayRW out_key(env, key_bytes);
10869     if (out_key.get() == nullptr) {
10870         conscrypt::jniutil::throwNullPointerException(env, "out_key == null");
10871         JNI_TRACE("Scrypt_generate_key() => out_key == null");
10872         return nullptr;
10873     }
10874 
10875     size_t memory_limit = 1u << 29;
10876     ScopedByteArrayRO password_bytes(env, password);
10877     ScopedByteArrayRO salt_bytes(env, salt);
10878 
10879     int result = EVP_PBE_scrypt(reinterpret_cast<const char*>(password_bytes.get()), password_bytes.size(),
10880                                 reinterpret_cast<const uint8_t*>(salt_bytes.get()), salt_bytes.size(),
10881                                 n, r, p, memory_limit,
10882                                 reinterpret_cast<uint8_t*>(out_key.get()), key_len);
10883 
10884     if (result <= 0) {
10885         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Scrypt_generate_key");
10886         return nullptr;
10887     }
10888     return key_bytes;
10889 }
10890 
10891 // TESTING METHODS BEGIN
10892 
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10893 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10894     CHECK_ERROR_QUEUE_ON_RETURN;
10895     BIO* bio = to_BIO(env, bioRef);
10896     JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10897 
10898     if (bio == nullptr) {
10899         JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10900         return 0;
10901     }
10902 
10903     if (outputJavaBytes == nullptr) {
10904         conscrypt::jniutil::throwNullPointerException(env, "output == null");
10905         JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10906         return 0;
10907     }
10908 
10909     jsize outputSize = env->GetArrayLength(outputJavaBytes);
10910 
10911     std::unique_ptr<unsigned char[]> buffer(
10912             new unsigned char[static_cast<unsigned int>(outputSize)]);
10913     if (buffer.get() == nullptr) {
10914         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10915         return 0;
10916     }
10917 
10918     int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10919     if (read <= 0) {
10920         conscrypt::jniutil::throwIOException(env, "BIO_read");
10921         JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10922         return 0;
10923     }
10924 
10925     env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10926     JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10927     return read;
10928 }
10929 
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10930 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10931                                    jint offset, jint length) {
10932     CHECK_ERROR_QUEUE_ON_RETURN;
10933     BIO* bio = to_BIO(env, bioRef);
10934     JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10935 
10936     if (bio == nullptr) {
10937         return;
10938     }
10939 
10940     if (inputJavaBytes == nullptr) {
10941         conscrypt::jniutil::throwNullPointerException(env, "input == null");
10942         return;
10943     }
10944 
10945     int inputSize = env->GetArrayLength(inputJavaBytes);
10946     if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10947         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10948                                            "inputJavaBytes");
10949         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10950         return;
10951     }
10952 
10953     std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10954     if (buffer.get() == nullptr) {
10955         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10956         return;
10957     }
10958 
10959     env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10960     if (BIO_write(bio, buffer.get(), length) != length) {
10961         ERR_clear_error();
10962         conscrypt::jniutil::throwIOException(env, "BIO_write");
10963         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10964         return;
10965     }
10966 
10967     JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10968 }
10969 
10970 /**
10971  * public static native long SSL_clear_mode(long ssl, long mode);
10972  */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10973 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10974                                          CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10975     CHECK_ERROR_QUEUE_ON_RETURN;
10976     SSL* ssl = to_SSL(env, ssl_address, true);
10977     // NOLINTNEXTLINE(runtime/int)
10978     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10979     if (ssl == nullptr) {
10980         return 0;
10981     }
10982     jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10983     // NOLINTNEXTLINE(runtime/int)
10984     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10985     return result;
10986 }
10987 
10988 /**
10989  * public static native long SSL_get_mode(long ssl);
10990  */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10991 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10992                                        CONSCRYPT_UNUSED jobject ssl_holder) {
10993     CHECK_ERROR_QUEUE_ON_RETURN;
10994     SSL* ssl = to_SSL(env, ssl_address, true);
10995     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10996     if (ssl == nullptr) {
10997         return 0;
10998     }
10999     jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
11000     // NOLINTNEXTLINE(runtime/int)
11001     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
11002     return mode;
11003 }
11004 
11005 /**
11006  * public static native long SSL_get_options(long ssl);
11007  */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11008 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
11009                                           CONSCRYPT_UNUSED jobject ssl_holder) {
11010     CHECK_ERROR_QUEUE_ON_RETURN;
11011     SSL* ssl = to_SSL(env, ssl_address, true);
11012     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
11013     if (ssl == nullptr) {
11014         return 0;
11015     }
11016     jlong options = static_cast<jlong>(SSL_get_options(ssl));
11017     // NOLINTNEXTLINE(runtime/int)
11018     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
11019     return options;
11020 }
11021 
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11022 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
11023                                            CONSCRYPT_UNUSED jobject ssl_holder) {
11024     CHECK_ERROR_QUEUE_ON_RETURN;
11025     SSL* ssl = to_SSL(env, ssl_address, true);
11026     if (ssl == nullptr) {
11027         return 0;
11028     }
11029     return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
11030 }
11031 
11032 // TESTING METHODS END
11033 
11034 #define CONSCRYPT_NATIVE_METHOD(functionName, signature)             \
11035     {                                                                \
11036         /* NOLINTNEXTLINE */                                         \
11037         (char*)#functionName, (char*)(signature),                    \
11038                 reinterpret_cast<void*>(NativeCrypto_##functionName) \
11039     }
11040 
11041 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
11042 #define SSL_CALLBACKS \
11043     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
11044 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
11045 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
11046 #define REF_EVP_CIPHER_CTX \
11047     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
11048 #define REF_EVP_HPKE_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_CTX;"
11049 #define REF_EVP_HPKE_KEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_KEY;"
11050 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
11051 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
11052 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
11053 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
11054 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
11055 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
11056 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
11057 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
11058 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
11059 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
11060 static JNINativeMethod sNativeCryptoMethods[] = {
11061         CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
11062         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
11063         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
11064         CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
11065         CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
11066         CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
11067         CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
11068         CONSCRYPT_NATIVE_METHOD(CMAC_Reset, "(" REF_CMAC_CTX ")V"),
11069         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
11070         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
11071         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
11072         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11073         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11074         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
11075         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11076         CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
11077         CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
11078         CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"),
11079         CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
11080         CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
11081         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
11082         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
11083         CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
11084         CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
11085                                 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
11086         CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
11087         CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
11088         CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11089         CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11090         CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11091         CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11092         CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
11093         CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
11094         CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
11095         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
11096         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
11097         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
11098         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
11099         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
11100         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
11101         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
11102         CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
11103         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
11104         CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
11105         CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
11106         CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
11107                                 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
11108         CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
11109                                 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
11110         CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
11111         CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
11112         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
11113         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
11114         CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
11115         CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
11116         CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11117         CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
11118         CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
11119         CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
11120         CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
11121         CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
11122         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
11123         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
11124         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
11125         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
11126         CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
11127         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11128         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11129         CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
11130         CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
11131         CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
11132         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11133         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11134         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11135         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
11136         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11137         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11138         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11139         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
11140         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
11141         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11142         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
11143         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11144         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
11145         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
11146         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
11147         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
11148         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
11149         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
11150         CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
11151         CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
11152         CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
11153         CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
11154         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
11155         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
11156         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
11157         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
11158         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
11159         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
11160         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
11161         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
11162         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
11163         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
11164         CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
11165         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
11166         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
11167         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
11168         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
11169         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
11170         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
11171         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf,
11172                                 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11173         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf,
11174                                 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11175         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_export, "(" REF_EVP_HPKE_CTX "[BI)[B"),
11176         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_free, "(J)V"),
11177         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_open, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11178         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_seal, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11179         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_recipient, "(III[B[B[B)Ljava/lang/Object;"),
11180         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender, "(III[B[B)[Ljava/lang/Object;"),
11181         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing,
11182                                 "(III[B[B[B)[Ljava/lang/Object;"),
11183         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
11184         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
11185         CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
11186         CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
11187         CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
11188         CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
11189         CONSCRYPT_NATIVE_METHOD(HMAC_Reset, "(" REF_HMAC_CTX ")V"),
11190         CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
11191         CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
11192         CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
11193         CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
11194         CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
11195         CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
11196         CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
11197         CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
11198         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
11199         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
11200         CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
11201         CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
11202         CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
11203         CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
11204         CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
11205         CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
11206         CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
11207         CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
11208         CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
11209         CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
11210         CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11211         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11212         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
11213         CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
11214         CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
11215         CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
11216         CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
11217         CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
11218         CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
11219         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
11220         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
11221         CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
11222         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
11223         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
11224         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
11225         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
11226         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
11227         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
11228         CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
11229         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
11230         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
11231         CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
11232                                 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
11233         CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
11234         CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
11235         CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
11236         CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
11237         CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
11238         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
11239         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext,
11240                                 "(J" REF_X509 "Ljava/lang/String;)[B"),
11241         CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
11242         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
11243         CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
11244         CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
11245         CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
11246         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
11247         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
11248         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
11249         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
11250         CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
11251         CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
11252         CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
11253         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
11254         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
11255         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
11256         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
11257         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
11258         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
11259         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
11260         CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
11261         CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
11262         CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
11263         CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
11264         CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
11265         CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
11266         CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
11267         CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
11268         CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
11269         CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
11270         CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
11271         CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
11272         CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
11273         CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
11274         CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
11275         CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
11276         CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
11277         CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
11278         CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
11279         CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
11280         CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
11281         CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
11282         CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
11283         CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
11284         CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
11285         CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
11286         CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
11287         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
11288         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
11289         CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
11290         CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
11291         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
11292         CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
11293         CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
11294         CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
11295         CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
11296         CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
11297         CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
11298         CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
11299         CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
11300         CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
11301         CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
11302         CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
11303         CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
11304         CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
11305         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
11306         CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
11307         CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
11308         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
11309         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
11310         CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
11311         CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
11312         CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
11313         CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
11314         CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
11315         CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
11316         CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
11317         CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
11318         CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
11319         CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
11320         CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
11321         CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
11322         CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
11323         CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
11324         CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
11325         CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
11326         CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
11327         CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
11328         CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
11329         CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
11330         CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
11331         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
11332         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
11333         CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
11334         CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
11335         CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
11336         CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
11337         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
11338         CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
11339         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
11340         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
11341         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
11342         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
11343         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
11344         CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
11345         CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
11346         CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
11347         CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
11348         CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
11349         CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
11350         CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
11351         CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
11352                                 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
11353         CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
11354         CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
11355         CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
11356         CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
11357         CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
11358         CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
11359         CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
11360         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
11361         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11362         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11363         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11364         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11365         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
11366         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
11367         CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
11368         CONSCRYPT_NATIVE_METHOD(Scrypt_generate_key, "([B[BIIII)[B"),
11369 
11370         // Used for testing only.
11371         CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
11372         CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
11373         CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
11374         CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
11375         CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
11376         CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
11377 };
11378 
registerNativeMethods(JNIEnv * env)11379 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
11380     conscrypt::jniutil::jniRegisterNativeMethods(
11381             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
11382             NELEM(sNativeCryptoMethods));
11383 }
11384 
11385 /* Local Variables: */
11386 /* mode: c++ */
11387 /* tab-width: 4 */
11388 /* indent-tabs-mode: nil */
11389 /* c-basic-offset: 4 */
11390 /* End: */
11391 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
11392