• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ED25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2565 static void NativeCrypto_ED25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray,
2566                                          jbyteArray outPrivateArray) {
2567     CHECK_ERROR_QUEUE_ON_RETURN;
2568     JNI_TRACE("ED25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2569 
2570     ScopedByteArrayRW outPublic(env, outPublicArray);
2571     if (outPublic.get() == nullptr) {
2572         JNI_TRACE("ED25519_keypair(%p, %p) can't get output public key buffer", outPublicArray,
2573                   outPrivateArray);
2574         return;
2575     }
2576 
2577     ScopedByteArrayRW outPrivate(env, outPrivateArray);
2578     if (outPrivate.get() == nullptr) {
2579         JNI_TRACE("ED25519_keypair(%p, %p) can't get output private key buffer", outPublicArray,
2580                   outPrivateArray);
2581         return;
2582     }
2583 
2584     if (outPublic.size() != ED25519_PUBLIC_KEY_LEN) {
2585         conscrypt::jniutil::throwIllegalArgumentException(env,
2586                                                           "Output public key array length != 32");
2587         return;
2588     }
2589 
2590     if (outPrivate.size() != ED25519_PRIVATE_KEY_LEN) {
2591         conscrypt::jniutil::throwIllegalArgumentException(env,
2592                                                           "Output private key array length != 64");
2593         return;
2594     }
2595 
2596     ED25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()),
2597                     reinterpret_cast<uint8_t*>(outPrivate.get()));
2598     JNI_TRACE("ED25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2599 }
2600 
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2601 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2602     CHECK_ERROR_QUEUE_ON_RETURN;
2603     JNI_TRACE_MD("EVP_MD_CTX_create()");
2604 
2605     bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2606     if (ctx.get() == nullptr) {
2607         conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2608         return 0;
2609     }
2610 
2611     JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2612     return reinterpret_cast<uintptr_t>(ctx.release());
2613 }
2614 
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2615 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2616     CHECK_ERROR_QUEUE_ON_RETURN;
2617     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2618     JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2619 
2620     if (ctx != nullptr) {
2621         EVP_MD_CTX_cleanup(ctx);
2622     }
2623 }
2624 
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2625 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2626     CHECK_ERROR_QUEUE_ON_RETURN;
2627     EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2628     JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2629 
2630     if (ctx != nullptr) {
2631         EVP_MD_CTX_destroy(ctx);
2632     }
2633 }
2634 
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2635 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2636                                             jobject srcCtxRef) {
2637     CHECK_ERROR_QUEUE_ON_RETURN;
2638     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2639     EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2640     if (dst_ctx == nullptr) {
2641         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2642         return 0;
2643     }
2644     const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2645     if (src_ctx == nullptr) {
2646         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2647         return 0;
2648     }
2649     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2650 
2651     int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2652     if (result == 0) {
2653         conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2654         ERR_clear_error();
2655     }
2656 
2657     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2658     return result;
2659 }
2660 
2661 /*
2662  * public static native int EVP_DigestFinal_ex(long, byte[], int)
2663  */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2664 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2665                                             jint offset) {
2666     CHECK_ERROR_QUEUE_ON_RETURN;
2667     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2668     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2669 
2670     if (ctx == nullptr) {
2671         JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2672         return -1;
2673     } else if (hash == nullptr) {
2674         conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2675         return -1;
2676     }
2677 
2678     ScopedByteArrayRW hashBytes(env, hash);
2679     if (hashBytes.get() == nullptr) {
2680         return -1;
2681     }
2682     unsigned int bytesWritten = static_cast<unsigned int>(-1);
2683     int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2684                                 &bytesWritten);
2685     if (ok == 0) {
2686         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2687         return -1;
2688     }
2689 
2690     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2691     return static_cast<jint>(bytesWritten);
2692 }
2693 
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2694 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2695                                            jlong evpMdRef) {
2696     CHECK_ERROR_QUEUE_ON_RETURN;
2697     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2698     const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2699     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2700 
2701     if (ctx == nullptr) {
2702         JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2703         return 0;
2704     } else if (evp_md == nullptr) {
2705         conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2706         return 0;
2707     }
2708 
2709     int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2710     if (ok == 0) {
2711         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2712         JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2713         return 0;
2714     }
2715     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2716     return ok;
2717 }
2718 
2719 /*
2720  * public static native int EVP_get_digestbyname(java.lang.String)
2721  */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2722 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2723     CHECK_ERROR_QUEUE_ON_RETURN;
2724     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2725 
2726     if (algorithm == nullptr) {
2727         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2728         return -1;
2729     }
2730 
2731     ScopedUtfChars algorithmChars(env, algorithm);
2732     if (algorithmChars.c_str() == nullptr) {
2733         return 0;
2734     }
2735     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2736 
2737     const char* alg = algorithmChars.c_str();
2738     const EVP_MD* md;
2739 
2740     if (strcasecmp(alg, "md4") == 0) {
2741         md = EVP_md4();
2742     } else if (strcasecmp(alg, "md5") == 0) {
2743         md = EVP_md5();
2744     } else if (strcasecmp(alg, "sha1") == 0) {
2745         md = EVP_sha1();
2746     } else if (strcasecmp(alg, "sha224") == 0) {
2747         md = EVP_sha224();
2748     } else if (strcasecmp(alg, "sha256") == 0) {
2749         md = EVP_sha256();
2750     } else if (strcasecmp(alg, "sha384") == 0) {
2751         md = EVP_sha384();
2752     } else if (strcasecmp(alg, "sha512") == 0) {
2753         md = EVP_sha512();
2754     } else {
2755         JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2756         conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2757         return 0;
2758     }
2759 
2760     return reinterpret_cast<uintptr_t>(md);
2761 }
2762 
2763 /*
2764  * public static native int EVP_MD_size(long)
2765  */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2766 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2767     CHECK_ERROR_QUEUE_ON_RETURN;
2768     EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2769     JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2770 
2771     if (evp_md == nullptr) {
2772         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2773         return -1;
2774     }
2775 
2776     jint result = static_cast<jint>(EVP_MD_size(evp_md));
2777     JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2778     return result;
2779 }
2780 
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)2781 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2782                                      int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2783                                                       ENGINE*, EVP_PKEY*),
2784                                      const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2785                                      jobject pkeyRef) {
2786     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2787     if (mdCtx == nullptr) {
2788         JNI_TRACE("%s => mdCtx == null", jniName);
2789         return 0;
2790     }
2791     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2792     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2793     if (pkey == nullptr) {
2794         JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2795         return 0;
2796     }
2797     JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2798 
2799     // For ED25519, md must be null, see
2800     // https://github.com/google/boringssl/blob/master/include/openssl/evp.h
2801     if (md == nullptr && (EVP_PKEY_id(pkey) != EVP_PKEY_ED25519)) {
2802         JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2803         conscrypt::jniutil::throwNullPointerException(env, "md == null");
2804         return 0;
2805     }
2806 
2807     EVP_PKEY_CTX* pctx = nullptr;
2808     if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2809         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2810         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2811         return 0;
2812     }
2813 
2814     JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2815     return reinterpret_cast<jlong>(pctx);
2816 }
2817 
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2818 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2819                                              const jlong evpMdRef, jobject pkeyRef) {
2820     CHECK_ERROR_QUEUE_ON_RETURN;
2821     return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2822                                    evpMdRef, pkeyRef);
2823 }
2824 
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2825 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2826                                                const jlong evpMdRef, jobject pkeyRef) {
2827     CHECK_ERROR_QUEUE_ON_RETURN;
2828     return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2829                                    evpMdRef, pkeyRef);
2830 }
2831 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2832 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2833                       const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2834     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2835     const void* p = reinterpret_cast<const void*>(inPtr);
2836     JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2837 
2838     if (mdCtx == nullptr) {
2839         return;
2840     }
2841 
2842     if (p == nullptr) {
2843         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2844         return;
2845     }
2846 
2847     if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2848         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2849         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2850         return;
2851     }
2852 
2853     JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2854 }
2855 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2856 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2857                       jint inLength, const char* jniName,
2858                       int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2859     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2860     JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2861 
2862     if (mdCtx == nullptr) {
2863         return;
2864     }
2865 
2866     if (inJavaBytes == nullptr) {
2867         conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2868         return;
2869     }
2870 
2871     size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2872     if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2873         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2874                                            "inBytes");
2875         return;
2876     }
2877     if (inLength == 0) {
2878         return;
2879     }
2880     jint in_offset = inOffset;
2881     jint in_size = inLength;
2882 
2883     int update_func_result = -1;
2884     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2885         // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2886         // avoid copying the whole array.
2887         if (in_size <= 1024) {
2888             // For small chunk, it's more efficient to use a bit more space on the stack instead of
2889             // allocating a new buffer.
2890             jbyte buf[1024];
2891             env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2892             update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2893                                              static_cast<size_t>(in_size));
2894         } else {
2895             // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2896             // through the buffer, stopping as soon as update_func fails.
2897             jint remaining = in_size;
2898             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2899             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2900             if (buf.get() == nullptr) {
2901                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2902                 return;
2903             }
2904             while (remaining > 0) {
2905                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2906                 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2907                 update_func_result =
2908                         update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2909                                     static_cast<size_t>(chunk_size));
2910                 if (!update_func_result) {
2911                     // update_func failed. This will be handled later in this method.
2912                     break;
2913                 }
2914                 in_offset += chunk_size;
2915                 remaining -= chunk_size;
2916             }
2917         }
2918     } else {
2919         // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2920         // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2921         // use GetByteArrayElements or another approach.
2922         jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2923         if (array_elements == nullptr) {
2924             conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2925             return;
2926         }
2927         const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2928         update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2929         env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2930     }
2931 
2932     if (!update_func_result) {
2933         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2934         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2935         return;
2936     }
2937 
2938     JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2939 }
2940 
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2941 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2942                                                 jlong inPtr, jint inLength) {
2943     CHECK_ERROR_QUEUE_ON_RETURN;
2944     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2945 }
2946 
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2947 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2948                                           jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2949     CHECK_ERROR_QUEUE_ON_RETURN;
2950     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2951               EVP_DigestUpdate);
2952 }
2953 
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2954 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2955                                               jbyteArray inJavaBytes, jint inOffset,
2956                                               jint inLength) {
2957     CHECK_ERROR_QUEUE_ON_RETURN;
2958     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2959             EVP_DigestSignUpdate);
2960 }
2961 
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2962 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2963         jlong inPtr, jint inLength) {
2964     CHECK_ERROR_QUEUE_ON_RETURN;
2965     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2966             EVP_DigestSignUpdate);
2967 }
2968 
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2969 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2970                                                 jbyteArray inJavaBytes, jint inOffset,
2971                                                 jint inLength) {
2972     CHECK_ERROR_QUEUE_ON_RETURN;
2973     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2974               EVP_DigestVerifyUpdate);
2975 }
2976 
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2977 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2978                                                       jlong inPtr, jint inLength) {
2979     CHECK_ERROR_QUEUE_ON_RETURN;
2980     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2981               EVP_DigestVerifyUpdate);
2982 }
2983 
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2984 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2985     CHECK_ERROR_QUEUE_ON_RETURN;
2986     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2987     JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2988 
2989     if (mdCtx == nullptr) {
2990         return nullptr;
2991     }
2992 
2993     size_t maxLen;
2994     if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2995         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2996         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2997         return nullptr;
2998     }
2999 
3000     std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
3001     if (buffer.get() == nullptr) {
3002         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
3003         return nullptr;
3004     }
3005     size_t actualLen(maxLen);
3006     if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
3007         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
3008         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
3009         return nullptr;
3010     }
3011     if (actualLen > maxLen) {
3012         JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
3013                   maxLen);
3014         conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
3015         return nullptr;
3016     }
3017 
3018     ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
3019     if (sigJavaBytes.get() == nullptr) {
3020         conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
3021         return nullptr;
3022     }
3023     env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
3024                             reinterpret_cast<jbyte*>(buffer.get()));
3025 
3026     JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
3027     return sigJavaBytes.release();
3028 }
3029 
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)3030 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
3031                                                    jbyteArray signature, jint offset, jint len) {
3032     CHECK_ERROR_QUEUE_ON_RETURN;
3033     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3034     JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
3035 
3036     if (mdCtx == nullptr) {
3037         return 0;
3038     }
3039 
3040     ScopedByteArrayRO sigBytes(env, signature);
3041     if (sigBytes.get() == nullptr) {
3042         return 0;
3043     }
3044 
3045     if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
3046         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3047                                            "signature");
3048         return 0;
3049     }
3050 
3051     const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3052     int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
3053     jboolean result;
3054     if (err == 1) {
3055         // Signature verified
3056         result = 1;
3057     } else if (err == 0) {
3058         // Signature did not verify
3059         result = 0;
3060     } else {
3061         // Error while verifying signature
3062         JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
3063         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
3064         return 0;
3065     }
3066 
3067     // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3068     // Clear the error queue to prevent its state from affecting future operations.
3069     ERR_clear_error();
3070 
3071     JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
3072     return result;
3073 }
3074 
NativeCrypto_EVP_DigestSign(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)3075 static jbyteArray NativeCrypto_EVP_DigestSign(JNIEnv* env, jclass, jobject evpMdCtxRef,
3076                                               jbyteArray inJavaBytes, jint inOffset,
3077                                               jint inLength) {
3078     CHECK_ERROR_QUEUE_ON_RETURN;
3079 
3080     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3081     JNI_TRACE_MD("%s(%p, %p, %d, %d)", "EVP_DigestSign", mdCtx, inJavaBytes, inOffset, inLength);
3082 
3083     if (mdCtx == nullptr) {
3084         return nullptr;
3085     }
3086 
3087     if (inJavaBytes == nullptr) {
3088         conscrypt::jniutil::throwNullPointerException(env, "inBytes");
3089         return nullptr;
3090     }
3091 
3092     size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
3093     if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
3094         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3095                                            "inBytes");
3096         return nullptr;
3097     }
3098 
3099     jint in_offset = inOffset;
3100     jint in_size = inLength;
3101 
3102     jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
3103     if (array_elements == nullptr) {
3104         conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
3105         return nullptr;
3106     }
3107     const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
3108     const unsigned char* inStart = buf + in_offset;
3109     size_t inLen = static_cast<size_t>(in_size);
3110 
3111     size_t maxLen;
3112     if (EVP_DigestSign(mdCtx, nullptr, &maxLen, inStart, inLen) != 1) {
3113         JNI_TRACE("ctx=%p EVP_DigestSign => threw exception", mdCtx);
3114         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSign");
3115         return nullptr;
3116     }
3117 
3118     std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
3119     if (buffer.get() == nullptr) {
3120         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
3121         return nullptr;
3122     }
3123     size_t actualLen(maxLen);
3124     if (EVP_DigestSign(mdCtx, buffer.get(), &actualLen, inStart, inLen) != 1) {
3125         JNI_TRACE("ctx=%p EVP_DigestSign => threw exception", mdCtx);
3126         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSign");
3127         return nullptr;
3128     }
3129     if (actualLen > maxLen) {
3130         JNI_TRACE("ctx=%p EVP_DigestSign => signature too long: %zd vs %zd", mdCtx, actualLen,
3131                   maxLen);
3132         conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSign signature too long");
3133         return nullptr;
3134     }
3135 
3136     ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
3137     if (sigJavaBytes.get() == nullptr) {
3138         conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
3139         return nullptr;
3140     }
3141     env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
3142                             reinterpret_cast<jbyte*>(buffer.get()));
3143 
3144     JNI_TRACE("EVP_DigestSign(%p) => %p", mdCtx, sigJavaBytes.get());
3145     return sigJavaBytes.release();
3146 }
3147 
NativeCrypto_EVP_DigestVerify(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint sigOffset,jint sigLen,jbyteArray data,jint dataOffset,jint dataLen)3148 static jboolean NativeCrypto_EVP_DigestVerify(JNIEnv* env, jclass, jobject evpMdCtxRef,
3149                                               jbyteArray signature, jint sigOffset, jint sigLen,
3150                                               jbyteArray data, jint dataOffset, jint dataLen) {
3151     CHECK_ERROR_QUEUE_ON_RETURN;
3152     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3153     JNI_TRACE("EVP_DigestVerify(%p)", mdCtx);
3154 
3155     if (mdCtx == nullptr) {
3156         return 0;
3157     }
3158 
3159     ScopedByteArrayRO sigBytes(env, signature);
3160     if (sigBytes.get() == nullptr) {
3161         return 0;
3162     }
3163 
3164     if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, sigOffset, sigLen)) {
3165         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3166                                            "signature");
3167         return 0;
3168     }
3169 
3170     ScopedByteArrayRO dataBytes(env, data);
3171     if (dataBytes.get() == nullptr) {
3172         return 0;
3173     }
3174 
3175     if (ARRAY_OFFSET_LENGTH_INVALID(dataBytes, dataOffset, dataLen)) {
3176         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "data");
3177         return 0;
3178     }
3179 
3180     const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3181     const unsigned char* dataBuf = reinterpret_cast<const unsigned char*>(dataBytes.get());
3182     int err = EVP_DigestVerify(mdCtx, sigBuf + sigOffset, static_cast<size_t>(sigLen),
3183                                dataBuf + dataOffset, static_cast<size_t>(dataLen));
3184     jboolean result;
3185     if (err == 1) {
3186         // Signature verified
3187         result = 1;
3188     } else if (err == 0) {
3189         // Signature did not verify
3190         result = 0;
3191     } else {
3192         // Error while verifying signature
3193         JNI_TRACE("ctx=%p EVP_DigestVerify => threw exception", mdCtx);
3194         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerify");
3195         return 0;
3196     }
3197 
3198     // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3199     // Clear the error queue to prevent its state from affecting future operations.
3200     ERR_clear_error();
3201 
3202     JNI_TRACE("EVP_DigestVerify(%p) => %d", mdCtx, result);
3203     return result;
3204 }
3205 
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)3206 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
3207                                   int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
3208                                                               const uint8_t*, size_t),
3209                                   const char* jniName, jobject evpPkeyCtxRef,
3210                                   jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
3211                                   jint inOffset, jint inLength) {
3212     EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
3213     JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
3214                  inJavaBytes, inOffset, inLength);
3215 
3216     if (pkeyCtx == nullptr) {
3217         return 0;
3218     }
3219 
3220     ScopedByteArrayRW outBytes(env, outJavaBytes);
3221     if (outBytes.get() == nullptr) {
3222         return 0;
3223     }
3224 
3225     ScopedByteArrayRO inBytes(env, inJavaBytes);
3226     if (inBytes.get() == nullptr) {
3227         return 0;
3228     }
3229 
3230     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3231         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3232                                            "outBytes");
3233         return 0;
3234     }
3235 
3236     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3237         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3238                                            "inBytes");
3239         return 0;
3240     }
3241 
3242     uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3243     const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3244     size_t outLength = outBytes.size() - outOffset;
3245     if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3246                               static_cast<size_t>(inLength))) {
3247         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3248         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3249                 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3250         return 0;
3251     }
3252 
3253     JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3254               outOffset, inJavaBytes, inOffset, inLength, outLength);
3255     return static_cast<jint>(outLength);
3256 }
3257 
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3258 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3259                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3260                                           jint inOffset, jint inLength) {
3261     CHECK_ERROR_QUEUE_ON_RETURN;
3262     return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3263                                  outOffset, inBytes, inOffset, inLength);
3264 }
3265 
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3266 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3267                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3268                                           jint inOffset, jint inLength) {
3269     CHECK_ERROR_QUEUE_ON_RETURN;
3270     return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3271                                  outOffset, inBytes, inOffset, inLength);
3272 }
3273 
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3274 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3275                                       int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3276     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3277     JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3278     if (pkey == nullptr) {
3279         JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3280         return 0;
3281     }
3282 
3283     bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3284     if (pkeyCtx.get() == nullptr) {
3285         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3286         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3287                 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3288         return 0;
3289     }
3290 
3291     if (!real_func(pkeyCtx.get())) {
3292         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3293         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3294                 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3295         return 0;
3296     }
3297 
3298     JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3299     return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3300 }
3301 
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3302 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3303     CHECK_ERROR_QUEUE_ON_RETURN;
3304     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3305 }
3306 
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3307 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3308     CHECK_ERROR_QUEUE_ON_RETURN;
3309     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3310 }
3311 
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3312 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3313     CHECK_ERROR_QUEUE_ON_RETURN;
3314     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3315     JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3316 
3317     if (pkeyCtx != nullptr) {
3318         EVP_PKEY_CTX_free(pkeyCtx);
3319     }
3320 }
3321 
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3322 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3323     CHECK_ERROR_QUEUE_ON_RETURN;
3324     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3325     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3326     if (pkeyCtx == nullptr) {
3327         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3328         return;
3329     }
3330 
3331     int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3332     if (result <= 0) {
3333         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3334         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3335                 env, "EVP_PKEY_CTX_set_rsa_padding",
3336                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3337         return;
3338     }
3339 
3340     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3341 }
3342 
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3343 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3344                                                           jint len) {
3345     CHECK_ERROR_QUEUE_ON_RETURN;
3346     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3347     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3348     if (pkeyCtx == nullptr) {
3349         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3350         return;
3351     }
3352 
3353     int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3354     if (result <= 0) {
3355         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3356         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3357                 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3358                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3359         return;
3360     }
3361 
3362     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3363 }
3364 
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3365 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3366                                int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3367     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3368     EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3369     JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3370     if (pkeyCtx == nullptr) {
3371         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3372         return;
3373     }
3374     if (md == nullptr) {
3375         conscrypt::jniutil::throwNullPointerException(env, "md == null");
3376         return;
3377     }
3378 
3379     int result = ctrl_func(pkeyCtx, md);
3380     if (result <= 0) {
3381         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3382         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3383                 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3384         return;
3385     }
3386 
3387     JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3388 }
3389 
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3390 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3391                                                       jlong mdRef) {
3392     CHECK_ERROR_QUEUE_ON_RETURN;
3393     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3394                        EVP_PKEY_CTX_set_rsa_mgf1_md);
3395 }
3396 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3397 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3398                                                       jlong mdRef) {
3399     CHECK_ERROR_QUEUE_ON_RETURN;
3400     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3401                        EVP_PKEY_CTX_set_rsa_oaep_md);
3402 }
3403 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3404 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3405                                                          jbyteArray labelJava) {
3406     CHECK_ERROR_QUEUE_ON_RETURN;
3407     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3408     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3409     if (pkeyCtx == nullptr) {
3410         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3411         return;
3412     }
3413 
3414     ScopedByteArrayRO labelBytes(env, labelJava);
3415     if (labelBytes.get() == nullptr) {
3416         return;
3417     }
3418 
3419     bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3420     memcpy(label.get(), labelBytes.get(), labelBytes.size());
3421 
3422     int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3423     if (result <= 0) {
3424         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3425         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3426                 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3427                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3428         return;
3429     }
3430     OWNERSHIP_TRANSFERRED(label);
3431 
3432     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3433 }
3434 
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3435 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3436     CHECK_ERROR_QUEUE_ON_RETURN;
3437     JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3438 
3439     if (algorithm == nullptr) {
3440         conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3441         JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3442         return -1;
3443     }
3444 
3445     ScopedUtfChars scoped_alg(env, algorithm);
3446     const char* alg = scoped_alg.c_str();
3447     const EVP_CIPHER* cipher;
3448 
3449     if (strcasecmp(alg, "rc4") == 0) {
3450         cipher = EVP_rc4();
3451     } else if (strcasecmp(alg, "des-cbc") == 0) {
3452         cipher = EVP_des_cbc();
3453     } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3454         cipher = EVP_des_ede_cbc();
3455     } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3456         cipher = EVP_des_ede3_cbc();
3457     } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3458         cipher = EVP_aes_128_ecb();
3459     } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3460         cipher = EVP_aes_128_cbc();
3461     } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3462         cipher = EVP_aes_128_ctr();
3463     } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3464         cipher = EVP_aes_128_gcm();
3465     } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3466         cipher = EVP_aes_192_ecb();
3467     } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3468         cipher = EVP_aes_192_cbc();
3469     } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3470         cipher = EVP_aes_192_ctr();
3471     } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3472         cipher = EVP_aes_192_gcm();
3473     } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3474         cipher = EVP_aes_256_ecb();
3475     } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3476         cipher = EVP_aes_256_cbc();
3477     } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3478         cipher = EVP_aes_256_ctr();
3479     } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3480         cipher = EVP_aes_256_gcm();
3481     } else {
3482         JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3483         return 0;
3484     }
3485 
3486     return reinterpret_cast<uintptr_t>(cipher);
3487 }
3488 
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3489 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3490                                            jbyteArray keyArray, jbyteArray ivArray,
3491                                            jboolean encrypting) {
3492     CHECK_ERROR_QUEUE_ON_RETURN;
3493     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3494     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3495     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3496               encrypting ? 1 : 0);
3497 
3498     if (ctx == nullptr) {
3499         JNI_TRACE("EVP_CipherUpdate => ctx == null");
3500         return;
3501     }
3502 
3503     // The key can be null if we need to set extra parameters.
3504     std::unique_ptr<unsigned char[]> keyPtr;
3505     if (keyArray != nullptr) {
3506         ScopedByteArrayRO keyBytes(env, keyArray);
3507         if (keyBytes.get() == nullptr) {
3508             return;
3509         }
3510 
3511         keyPtr.reset(new unsigned char[keyBytes.size()]);
3512         memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3513     }
3514 
3515     // The IV can be null if we're using ECB.
3516     std::unique_ptr<unsigned char[]> ivPtr;
3517     if (ivArray != nullptr) {
3518         ScopedByteArrayRO ivBytes(env, ivArray);
3519         if (ivBytes.get() == nullptr) {
3520             return;
3521         }
3522 
3523         ivPtr.reset(new unsigned char[ivBytes.size()]);
3524         memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3525     }
3526 
3527     if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3528                            encrypting ? 1 : 0)) {
3529         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3530         JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3531         return;
3532     }
3533 
3534     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3535               encrypting ? 1 : 0);
3536 }
3537 
3538 /*
3539  *  public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3540  *          int inOffset, int inLength);
3541  */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3542 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3543                                           jint outOffset, jbyteArray inArray, jint inOffset,
3544                                           jint inLength) {
3545     CHECK_ERROR_QUEUE_ON_RETURN;
3546     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3547     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3548 
3549     if (ctx == nullptr) {
3550         JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3551         return 0;
3552     }
3553 
3554     ScopedByteArrayRO inBytes(env, inArray);
3555     if (inBytes.get() == nullptr) {
3556         return 0;
3557     }
3558     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3559         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3560                                            "inBytes");
3561         return 0;
3562     }
3563 
3564     ScopedByteArrayRW outBytes(env, outArray);
3565     if (outBytes.get() == nullptr) {
3566         return 0;
3567     }
3568     if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3569         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3570                                            "outBytes");
3571         return 0;
3572     }
3573 
3574     JNI_TRACE(
3575             "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3576             "out.length=%zd outOffset=%d",
3577             ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3578             outOffset);
3579 
3580     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3581     const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3582 
3583     int outl;
3584     if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3585         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3586         JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3587         return 0;
3588     }
3589 
3590     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3591               inOffset, outl);
3592     return outl;
3593 }
3594 
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3595 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3596                                             jbyteArray outArray, jint outOffset) {
3597     CHECK_ERROR_QUEUE_ON_RETURN;
3598     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3599     JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3600 
3601     if (ctx == nullptr) {
3602         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3603         return 0;
3604     }
3605 
3606     ScopedByteArrayRW outBytes(env, outArray);
3607     if (outBytes.get() == nullptr) {
3608         return 0;
3609     }
3610 
3611     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3612 
3613     int outl;
3614     if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3615         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3616                 conscrypt::jniutil::throwBadPaddingException);
3617         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3618         return 0;
3619     }
3620 
3621     JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3622     return outl;
3623 }
3624 
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3625 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3626     CHECK_ERROR_QUEUE_ON_RETURN;
3627     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3628     JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3629 
3630     if (evpCipher == nullptr) {
3631         conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3632         JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3633         return 0;
3634     }
3635 
3636     jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3637     JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3638     return ivLength;
3639 }
3640 
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3641 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3642     CHECK_ERROR_QUEUE_ON_RETURN;
3643     JNI_TRACE("EVP_CIPHER_CTX_new()");
3644 
3645     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3646     if (ctx.get() == nullptr) {
3647         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3648         JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3649         return 0;
3650     }
3651 
3652     JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3653     return reinterpret_cast<uintptr_t>(ctx.release());
3654 }
3655 
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3656 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3657     CHECK_ERROR_QUEUE_ON_RETURN;
3658     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3659     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3660 
3661     if (ctx == nullptr) {
3662         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3663         return 0;
3664     }
3665 
3666     jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3667     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3668     return blockSize;
3669 }
3670 
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3671 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3672     CHECK_ERROR_QUEUE_ON_RETURN;
3673     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3674     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3675 
3676     if (ctx == nullptr) {
3677         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3678         return 0;
3679     }
3680 
3681     int buf_len = ctx->buf_len;
3682     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3683     return buf_len;
3684 }
3685 
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3686 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3687     CHECK_ERROR_QUEUE_ON_RETURN;
3688     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3689     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3690 
3691     if (ctx == nullptr) {
3692         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3693         return 0;
3694     }
3695 
3696     bool final_used = ctx->final_used != 0;
3697     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3698     return static_cast<jboolean>(final_used);
3699 }
3700 
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3701 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3702                                                     jboolean enablePaddingBool) {
3703     CHECK_ERROR_QUEUE_ON_RETURN;
3704     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3705     jint enablePadding = enablePaddingBool ? 1 : 0;
3706     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3707 
3708     if (ctx == nullptr) {
3709         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3710         return;
3711     }
3712 
3713     EVP_CIPHER_CTX_set_padding(ctx, enablePadding);  // Not void, but always returns 1.
3714     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3715 }
3716 
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3717 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3718                                                        jint keySizeBits) {
3719     CHECK_ERROR_QUEUE_ON_RETURN;
3720     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3721     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3722 
3723     if (ctx == nullptr) {
3724         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3725         return;
3726     }
3727 
3728     if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3729         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3730                 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3731         JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3732         return;
3733     }
3734     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3735 }
3736 
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3737 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3738     CHECK_ERROR_QUEUE_ON_RETURN;
3739     EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3740     JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3741 
3742     EVP_CIPHER_CTX_free(ctx);
3743 }
3744 
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3745 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3746     CHECK_ERROR_QUEUE_ON_RETURN;
3747     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3748     JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3749     return reinterpret_cast<jlong>(ctx);
3750 }
3751 
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3752 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3753     CHECK_ERROR_QUEUE_ON_RETURN;
3754     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3755     JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3756     return reinterpret_cast<jlong>(ctx);
3757 }
3758 
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3759 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3760     CHECK_ERROR_QUEUE_ON_RETURN;
3761     const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3762     JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3763     return reinterpret_cast<jlong>(ctx);
3764 }
3765 
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3766 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3767     CHECK_ERROR_QUEUE_ON_RETURN;
3768     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3769     JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3770     return reinterpret_cast<jlong>(ctx);
3771 }
3772 
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3773 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3774     CHECK_ERROR_QUEUE_ON_RETURN;
3775     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3776     JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3777     return reinterpret_cast<jlong>(ctx);
3778 }
3779 
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3780 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3781     CHECK_ERROR_QUEUE_ON_RETURN;
3782     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3783     JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3784     if (evpAead == nullptr) {
3785         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3786         return 0;
3787     }
3788     jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3789     JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3790     return maxOverhead;
3791 }
3792 
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3793 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3794     CHECK_ERROR_QUEUE_ON_RETURN;
3795     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3796     JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3797     if (evpAead == nullptr) {
3798         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3799         return 0;
3800     }
3801     jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3802     JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3803     return nonceLength;
3804 }
3805 
3806 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3807                                     size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3808                                     const uint8_t* in, size_t in_len, const uint8_t* ad,
3809                                     size_t ad_len);
3810 
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)3811 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3812                                uint8_t* outBuf, jbyteArray nonceArray,
3813                                const uint8_t* inBuf, jbyteArray aadArray,
3814                                evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange)  {
3815     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3816 
3817     ScopedByteArrayRO keyBytes(env, keyArray);
3818     if (keyBytes.get() == nullptr) {
3819         return 0;
3820     }
3821 
3822     std::unique_ptr<ScopedByteArrayRO> aad;
3823     const uint8_t* aad_chars = nullptr;
3824     size_t aad_chars_size = 0;
3825     if (aadArray != nullptr) {
3826         aad.reset(new ScopedByteArrayRO(env, aadArray));
3827         aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3828         if (aad_chars == nullptr) {
3829             return 0;
3830         }
3831         aad_chars_size = aad->size();
3832     }
3833 
3834     ScopedByteArrayRO nonceBytes(env, nonceArray);
3835     if (nonceBytes.get() == nullptr) {
3836         return 0;
3837     }
3838 
3839     bssl::ScopedEVP_AEAD_CTX aeadCtx;
3840     const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3841     if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3842                            static_cast<size_t>(tagLen), nullptr)) {
3843         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3844                                                              "failure initializing AEAD context");
3845         JNI_TRACE(
3846                 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3847                 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3848                 aadArray);
3849         return 0;
3850     }
3851 
3852     const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3853     size_t actualOutLength;
3854 
3855     if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3856                   nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3857                   aad_chars, aad_chars_size)) {
3858         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3859         return 0;
3860     }
3861 
3862     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3863               evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3864               aadArray, actualOutLength);
3865     return static_cast<jint>(actualOutLength);
3866 }
3867 
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)3868 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3869                             jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3870                             jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3871                             evp_aead_ctx_op_func realFunc) {
3872     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3873     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3874               outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3875 
3876 
3877     ScopedByteArrayRW outBytes(env, outArray);
3878     if (outBytes.get() == nullptr) {
3879         return 0;
3880     }
3881 
3882     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3883         JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3884                   evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3885                   inLength, aadArray);
3886         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3887         return 0;
3888     }
3889 
3890     ScopedByteArrayRO inBytes(env, inArray);
3891     if (inBytes.get() == nullptr) {
3892         return 0;
3893     }
3894 
3895     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3896         JNI_TRACE(
3897                 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3898                 "invalid",
3899                 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3900                 inLength, aadArray);
3901         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3902         return 0;
3903     }
3904 
3905     uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3906     const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3907 
3908     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3909                             aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3910 }
3911 
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)3912 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3913                             jobject outBuffer, jbyteArray nonceArray,
3914                             jobject inBuffer, jbyteArray aadArray,
3915                             evp_aead_ctx_op_func realFunc) {
3916 
3917     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3918     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3919               outBuffer, nonceArray, inBuffer, aadArray);
3920 
3921     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3922         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3923                                            "inBuffer is not a direct ByteBuffer");
3924         return 0;
3925     }
3926 
3927     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3928         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3929                                            "outBuffer is not a direct ByteBuffer");
3930         return 0;
3931     }
3932 
3933     uint8_t* inBuf;
3934     jint in_limit;
3935     jint in_position;
3936 
3937     inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3938      // limit is the index of the first element that should not be read or written
3939     in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3940     // position is the index of the next element to be read or written
3941     in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3942 
3943     uint8_t* outBuf;
3944     jint out_limit;
3945     jint out_position;
3946     outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3947     // limit is the index of the first element that should not be read or written
3948     out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3949     // position is the index of the next element to be read or written
3950     out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3951 
3952     // Shifting over of ByteBuffer address to start at true position
3953     inBuf += in_position;
3954     outBuf += out_position;
3955 
3956     size_t inSize = in_limit - in_position;
3957     uint8_t* outBufEnd = outBuf + out_limit - out_position;
3958     uint8_t* inBufEnd = inBuf + inSize;
3959     std::unique_ptr<uint8_t[]> inCopy;
3960     if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3961       inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3962       if (inCopy.get() == nullptr) {
3963             conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3964             return 0;
3965         }
3966         memcpy(inCopy.get(), inBuf, inSize);
3967         inBuf = inCopy.get();
3968     }
3969 
3970     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3971                                inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3972 }
3973 
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)3974 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3975                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3976                                            jint outOffset, jbyteArray nonceArray,
3977                                            jbyteArray inArray, jint inOffset, jint inLength,
3978                                            jbyteArray aadArray) {
3979     CHECK_ERROR_QUEUE_ON_RETURN;
3980     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3981                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3982 }
3983 
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)3984 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3985                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3986                                            jint outOffset, jbyteArray nonceArray,
3987                                            jbyteArray inArray, jint inOffset, jint inLength,
3988                                            jbyteArray aadArray) {
3989     CHECK_ERROR_QUEUE_ON_RETURN;
3990     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3991                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3992 }
3993 
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3994 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3995                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3996                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3997     CHECK_ERROR_QUEUE_ON_RETURN;
3998     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3999                            inBuffer, aadArray, EVP_AEAD_CTX_seal);
4000 }
4001 
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)4002 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
4003                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
4004                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
4005     CHECK_ERROR_QUEUE_ON_RETURN;
4006     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
4007                            inBuffer, aadArray, EVP_AEAD_CTX_open);
4008 }
4009 
NativeCrypto_EVP_HPKE_CTX_export(JNIEnv * env,jclass,jobject hpkeCtxRef,jbyteArray exporterCtxArray,jint exportedLen)4010 static jbyteArray NativeCrypto_EVP_HPKE_CTX_export(JNIEnv* env, jclass, jobject hpkeCtxRef,
4011                                                    jbyteArray exporterCtxArray, jint exportedLen) {
4012     CHECK_ERROR_QUEUE_ON_RETURN;
4013     EVP_HPKE_CTX* hpkeCtx = fromContextObject<EVP_HPKE_CTX>(env, hpkeCtxRef);
4014     JNI_TRACE("EVP_HPKE_CTX_export(%p, %p, %d)", hpkeCtx, exporterCtxArray, exportedLen);
4015 
4016     if (hpkeCtx == nullptr) {
4017         // NullPointerException thrown while calling fromContextObject
4018         return {};
4019     }
4020 
4021     std::optional<ScopedByteArrayRO> optionalExporterCtx;
4022     const uint8_t* exporterCtx = nullptr;
4023     size_t exporterCtxLen = 0;
4024     if (exporterCtxArray != nullptr) {
4025         optionalExporterCtx.emplace(env, exporterCtxArray);
4026         exporterCtx = reinterpret_cast<const uint8_t*>(optionalExporterCtx->get());
4027         if (exporterCtx == nullptr) {
4028             return {};
4029         }
4030         exporterCtxLen = optionalExporterCtx->size();
4031     }
4032 
4033     std::vector<uint8_t> exported(exportedLen);
4034     if (!EVP_HPKE_CTX_export(/* ctx= */ hpkeCtx,
4035                              /* out= */ exported.data(),
4036                              /* secret_len= */ exportedLen,
4037                              /* context= */ exporterCtx,
4038                              /* context_len= */ exporterCtxLen)) {
4039         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_export");
4040         return {};
4041     }
4042 
4043     ScopedLocalRef<jbyteArray> exportedArray(env, env->NewByteArray(static_cast<jsize>(exportedLen)));
4044     if (exportedArray.get() == nullptr) {
4045         return {};
4046     }
4047     ScopedByteArrayRW exportedBytes(env, exportedArray.get());
4048     if (exportedBytes.get() == nullptr) {
4049         return {};
4050     }
4051     memcpy(exportedBytes.get(), reinterpret_cast<const jbyte*>(exported.data()), exportedLen);
4052     return exportedArray.release();
4053 }
4054 
NativeCrypto_EVP_HPKE_CTX_free(JNIEnv * env,jclass,jlong hpkeCtxRef)4055 static void NativeCrypto_EVP_HPKE_CTX_free(JNIEnv* env, jclass, jlong hpkeCtxRef) {
4056     CHECK_ERROR_QUEUE_ON_RETURN;
4057     EVP_HPKE_CTX* ctx = reinterpret_cast<EVP_HPKE_CTX*>(hpkeCtxRef);
4058     JNI_TRACE("EVP_HPKE_CTX_free(%p)", ctx);
4059     if (ctx == nullptr) {
4060         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
4061         return;
4062     }
4063     EVP_HPKE_CTX_free(ctx);
4064 }
4065 
NativeCrypto_EVP_HPKE_CTX_open(JNIEnv * env,jclass,jobject recipientHpkeCtxRef,jbyteArray ciphertextArray,jbyteArray aadArray)4066 static jbyteArray NativeCrypto_EVP_HPKE_CTX_open(JNIEnv* env, jclass, jobject recipientHpkeCtxRef,
4067                                                  jbyteArray ciphertextArray, jbyteArray aadArray) {
4068     CHECK_ERROR_QUEUE_ON_RETURN;
4069     EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, recipientHpkeCtxRef);
4070     JNI_TRACE("EVP_HPKE_CTX_open(%p, %p, %p)", ctx, ciphertextArray, aadArray);
4071 
4072     if (ctx == nullptr) {
4073         // NullPointerException thrown while calling fromContextObject
4074         return {};
4075     }
4076 
4077     if (ciphertextArray == nullptr) {
4078         conscrypt::jniutil::throwNullPointerException(env, "ciphertextArray == null");
4079         return {};
4080     }
4081 
4082     ScopedByteArrayRO ciphertext(env, ciphertextArray);
4083     if (ciphertext.get() == nullptr) {
4084         return {};
4085     }
4086 
4087     std::optional<ScopedByteArrayRO> optionalAad;
4088     const uint8_t* aad = nullptr;
4089     size_t aadLen = 0;
4090     if (aadArray != nullptr) {
4091         optionalAad.emplace(env, aadArray);
4092         aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
4093         if (aad == nullptr) {
4094             return {};
4095         }
4096         aadLen = optionalAad->size();
4097     }
4098 
4099     size_t plaintextLen;
4100     std::vector<uint8_t> plaintext(ciphertext.size());
4101     if (!EVP_HPKE_CTX_open(/* ctx= */ ctx,
4102                            /* out= */ plaintext.data(),
4103                            /* out_len= */ &plaintextLen,
4104                            /* max_out_len= */ plaintext.size(),
4105                            /* in= */ reinterpret_cast<const uint8_t*>(ciphertext.get()),
4106                            /* in_len= */ ciphertext.size(),
4107                            /* aad= */ aad,
4108                            /* aad_len= */ aadLen)) {
4109         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_open");
4110         return {};
4111     }
4112 
4113     plaintext.resize(plaintextLen);
4114     ScopedLocalRef<jbyteArray> plaintextArray(env, env->NewByteArray(static_cast<jsize>(plaintextLen)));
4115     if (plaintextArray.get() == nullptr) {
4116         return {};
4117     }
4118     ScopedByteArrayRW plaintextBytes(env, plaintextArray.get());
4119     if (plaintextBytes.get() == nullptr) {
4120         return {};
4121     }
4122     memcpy(plaintextBytes.get(), reinterpret_cast<const jbyte*>(plaintext.data()), plaintextLen);
4123     return plaintextArray.release();
4124 }
4125 
NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv * env,jclass,jobject senderHpkeCtxRef,jbyteArray plaintextArray,jbyteArray aadArray)4126 static jbyteArray NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv* env, jclass, jobject senderHpkeCtxRef,
4127                                                  jbyteArray plaintextArray, jbyteArray aadArray) {
4128     CHECK_ERROR_QUEUE_ON_RETURN;
4129     EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, senderHpkeCtxRef);
4130     JNI_TRACE("EVP_HPKE_CTX_seal(%p, %p, %p)", ctx, plaintextArray, aadArray);
4131 
4132     if (ctx == nullptr) {
4133         // NullPointerException thrown while calling fromContextObject
4134         return {};
4135     }
4136 
4137     if (plaintextArray == nullptr) {
4138         conscrypt::jniutil::throwNullPointerException(env, "plaintextArray == null");
4139         return {};
4140     }
4141 
4142     std::optional<ScopedByteArrayRO> optionalAad;
4143     const uint8_t* aad = nullptr;
4144     size_t aadLen = 0;
4145     if (aadArray != nullptr) {
4146         optionalAad.emplace(env, aadArray);
4147         aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
4148         if (aad == nullptr) {
4149             return {};
4150         }
4151         aadLen = optionalAad->size();
4152     }
4153 
4154     ScopedByteArrayRO plaintext(env, plaintextArray);
4155     std::vector<uint8_t> encrypted(env->GetArrayLength(plaintextArray) +
4156                                    EVP_HPKE_CTX_max_overhead(ctx));
4157     size_t encryptedLen;
4158     if (!EVP_HPKE_CTX_seal(/* ctx= */ ctx,
4159                            /* out= */ encrypted.data(),
4160                            /* out_len= */ &encryptedLen,
4161                            /* max_out_len= */ encrypted.size(),
4162                            /* in= */ reinterpret_cast<const uint8_t*>(plaintext.get()),
4163                            /* in_len= */ plaintext.size(),
4164                            /* aad= */ aad,
4165                            /* aad_len= */ aadLen)) {
4166         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_seal");
4167         return {};
4168     }
4169 
4170     ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(static_cast<jsize>(encryptedLen)));
4171     if (ciphertextArray.get() == nullptr) {
4172         return {};
4173     }
4174     ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
4175     if (ciphertextBytes.get() == nullptr) {
4176         return {};
4177     }
4178     memcpy(ciphertextBytes.get(), reinterpret_cast<const jbyte*>(encrypted.data()), encryptedLen);
4179     return ciphertextArray.release();
4180 }
4181 
getHpkeAead(JNIEnv * env,jint aeadValue)4182 const EVP_HPKE_AEAD* getHpkeAead(JNIEnv* env, jint aeadValue) {
4183     switch (aeadValue) {
4184         case EVP_HPKE_AES_128_GCM:
4185             return EVP_hpke_aes_128_gcm();
4186         case EVP_HPKE_AES_256_GCM:
4187             return EVP_hpke_aes_256_gcm();
4188         case EVP_HPKE_CHACHA20_POLY1305:
4189             return EVP_hpke_chacha20_poly1305();
4190         default:
4191             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4192                                                "AEAD is not supported");
4193             return nullptr;
4194     }
4195 }
4196 
getHpkeKdf(JNIEnv * env,jint kdfValue)4197 const EVP_HPKE_KDF* getHpkeKdf(JNIEnv* env, jint kdfValue) {
4198     if (kdfValue == EVP_HPKE_HKDF_SHA256) {
4199         return EVP_hpke_hkdf_sha256();
4200     } else {
4201         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4202                                            "KDF is not supported");
4203         return nullptr;
4204     }
4205 }
4206 
getHpkeKem(JNIEnv * env,jint kemValue)4207 const EVP_HPKE_KEM* getHpkeKem(JNIEnv* env, jint kemValue) {
4208     if (kemValue == EVP_HPKE_DHKEM_X25519_HKDF_SHA256) {
4209         return EVP_hpke_x25519_hkdf_sha256();
4210     } else {
4211         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4212                                            "KEM is not supported");
4213         return nullptr;
4214     }
4215 }
4216 
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray privateKeyArray,jbyteArray encArray,jbyteArray infoArray)4217 static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv* env, jclass,
4218                                                                    jint kemValue,jint kdfValue,
4219                                                                    jint aeadValue,
4220                                                                    jbyteArray privateKeyArray,
4221                                                                    jbyteArray encArray,
4222                                                                    jbyteArray infoArray) {
4223     CHECK_ERROR_QUEUE_ON_RETURN;
4224     JNI_TRACE("EVP_HPKE_CTX_setup_recipient(%d, %d, %d, %p, %p, %p)", kemValue, kdfValue, aeadValue,
4225               privateKeyArray, encArray, infoArray);
4226 
4227     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4228     if (kem == nullptr) {
4229         return nullptr;
4230     }
4231     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4232     if (kdf == nullptr) {
4233         return nullptr;
4234     }
4235     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4236     if (aead == nullptr) {
4237         return nullptr;
4238     }
4239     if (privateKeyArray == nullptr) {
4240         conscrypt::jniutil::throwNullPointerException(env, "privateKeyArray == null");
4241         return nullptr;
4242     }
4243     if (encArray == nullptr) {
4244         conscrypt::jniutil::throwNullPointerException(env, "encArray == null");
4245         return nullptr;
4246     }
4247 
4248     ScopedByteArrayRO privateKey(env, privateKeyArray);
4249 
4250     bssl::ScopedEVP_HPKE_KEY key;
4251 
4252     if (!EVP_HPKE_KEY_init(/* key= */ key.get(),
4253                            /* kem= */ kem,
4254                            /* priv_key= */ reinterpret_cast<const uint8_t*>(privateKey.get()),
4255                            /* priv_key_len= */ privateKey.size())) {
4256         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4257         return nullptr;
4258     }
4259 
4260     std::optional<ScopedByteArrayRO> optionalInfo;
4261     const uint8_t* info = nullptr;
4262     size_t infoLen = 0;
4263     if (infoArray != nullptr) {
4264         optionalInfo.emplace(env, infoArray);
4265         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4266         if (info == nullptr) {
4267             return {};
4268         }
4269         infoLen = optionalInfo->size();
4270     }
4271 
4272     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4273     ScopedByteArrayRO enc(env, encArray);
4274     if (!EVP_HPKE_CTX_setup_recipient(/* ctx= */ ctx.get(),
4275                                       /* key= */ key.get(),
4276                                       /* kdf= */ kdf,
4277                                       /* aead= */ aead,
4278                                       /* enc= */ reinterpret_cast<const uint8_t*>(enc.get()),
4279                                       /* enc_len= */ enc.size(),
4280                                       /* info= */ info,
4281                                       /* info_len= */ infoLen)) {
4282         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4283         return nullptr;
4284     }
4285 
4286     ScopedLocalRef<jobject> ctxObject(
4287                     env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4288                                         conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4289                                         reinterpret_cast<jlong>(ctx.release())));
4290     return ctxObject.release();
4291 }
4292 
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray)4293 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass,
4294                                                                      jint kemValue,jint kdfValue,
4295                                                                      jint aeadValue,
4296                                                                      jbyteArray publicKeyArray,
4297                                                                      jbyteArray infoArray) {
4298     CHECK_ERROR_QUEUE_ON_RETURN;
4299     JNI_TRACE("EVP_HPKE_CTX_setup_sender(%d, %d, %d, %p, %p)", kemValue, kdfValue, aeadValue,
4300               publicKeyArray, infoArray);
4301 
4302     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4303     if (kem == nullptr) {
4304         return nullptr;
4305     }
4306     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4307     if (kdf == nullptr) {
4308         return nullptr;
4309     }
4310     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4311     if (aead == nullptr) {
4312         return nullptr;
4313     }
4314     if (publicKeyArray == nullptr) {
4315         conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray == null");
4316         return {};
4317     }
4318 
4319     std::optional<ScopedByteArrayRO> optionalInfo;
4320     const uint8_t* info = nullptr;
4321     size_t infoLen = 0;
4322     if (infoArray != nullptr) {
4323         optionalInfo.emplace(env, infoArray);
4324         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4325         if (info == nullptr) {
4326             return {};
4327         }
4328         infoLen = optionalInfo->size();
4329     }
4330 
4331     ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4332 
4333     size_t encapsulatedSharedSecretLen;
4334     uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4335 
4336     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4337 
4338     if (!EVP_HPKE_CTX_setup_sender(/* ctx= */ ctx.get(),
4339                                    /* out_enc= */ encapsulatedSharedSecret,
4340                                    /* out_enc_len= */ &encapsulatedSharedSecretLen,
4341                                    /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4342                                    /* kem= */ kem,
4343                                    /* kdf= */ kdf,
4344                                    /* aead= */ aead,
4345                                    /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4346                                    /* peer_public_key_len= */ peer_public_key.size(),
4347                                    /* info= */ info,
4348                                    /* info_len= */ infoLen)) {
4349         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_sender");
4350         return {};
4351     }
4352 
4353     ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4354     if (encArray.get() == nullptr) {
4355         return {};
4356     }
4357     ScopedByteArrayRW encBytes(env, encArray.get());
4358     if (encBytes.get() == nullptr) {
4359         return {};
4360     }
4361     memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4362 
4363     ScopedLocalRef<jobjectArray> result(
4364             env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4365 
4366     ScopedLocalRef<jobject> ctxObject(
4367                 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4368                                     conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4369                                     reinterpret_cast<jlong>(ctx.release())));
4370 
4371     env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4372     env->SetObjectArrayElement(result.get(), 1, encArray.release());
4373 
4374     return result.release();
4375 }
4376 
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)4377 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(
4378         JNIEnv* env, jclass, jint kemValue, jint kdfValue, jint aeadValue,
4379         jbyteArray publicKeyArray, jbyteArray infoArray, jbyteArray seedArray) {
4380     CHECK_ERROR_QUEUE_ON_RETURN;
4381     JNI_TRACE("EVP_HPKE_CTX_setup_sender_with_seed_for_testing(%d, %d, %d, %p, %p, %p)", kemValue,
4382               kdfValue, aeadValue, publicKeyArray, infoArray, seedArray);
4383 
4384     const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4385     if (kem == nullptr) {
4386         return nullptr;
4387     }
4388     const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4389     if (kdf == nullptr) {
4390         return nullptr;
4391     }
4392     const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4393     if (aead == nullptr) {
4394         return nullptr;
4395     }
4396     if (publicKeyArray == nullptr || seedArray == nullptr) {
4397         conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray or seedArray == null");
4398         return {};
4399     }
4400 
4401     std::optional<ScopedByteArrayRO> optionalInfo;
4402     const uint8_t* info = nullptr;
4403     size_t infoLen = 0;
4404     if (infoArray != nullptr) {
4405         optionalInfo.emplace(env, infoArray);
4406         info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4407         if (info == nullptr) {
4408             return {};
4409         }
4410         infoLen = optionalInfo->size();
4411     }
4412 
4413     ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4414 
4415     ScopedByteArrayRO seed(env, seedArray);
4416 
4417     size_t encapsulatedSharedSecretLen;
4418     uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4419 
4420     bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4421 
4422     if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
4423             /* ctx= */ ctx.get(),
4424             /* out_enc= */ encapsulatedSharedSecret,
4425             /* out_enc_len= */ &encapsulatedSharedSecretLen,
4426             /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4427             /* kem= */ kem,
4428             /* kdf= */ kdf,
4429             /* aead= */ aead,
4430             /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4431             /* peer_public_key_len= */ peer_public_key.size(),
4432             /* info= */ info,
4433             /* info_len= */ infoLen,
4434             /* seed= */ reinterpret_cast<const uint8_t*>(seed.get()),
4435             /* seed_len= */ seed.size())) {
4436         conscrypt::jniutil::throwExceptionFromBoringSSLError(
4437                 env, "EVP_HPKE_CTX_setup_sender_with_seed_for_testing");
4438         return {};
4439     }
4440 
4441     ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4442     if (encArray.get() == nullptr) {
4443         return {};
4444     }
4445     ScopedByteArrayRW encBytes(env, encArray.get());
4446     if (encBytes.get() == nullptr) {
4447         return {};
4448     }
4449     memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4450 
4451     ScopedLocalRef<jobjectArray> result(
4452             env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4453 
4454     ScopedLocalRef<jobject> ctxObject(
4455                     env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4456                                         conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4457                                         reinterpret_cast<jlong>(ctx.release())));
4458 
4459     env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4460     env->SetObjectArrayElement(result.get(), 1, encArray.release());
4461 
4462     return result.release();
4463 }
4464 
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)4465 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
4466     CHECK_ERROR_QUEUE_ON_RETURN;
4467     JNI_TRACE("CMAC_CTX_new");
4468     auto cmacCtx = CMAC_CTX_new();
4469     if (cmacCtx == nullptr) {
4470         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
4471         return 0;
4472     }
4473 
4474     return reinterpret_cast<jlong>(cmacCtx);
4475 }
4476 
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)4477 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
4478     CHECK_ERROR_QUEUE_ON_RETURN;
4479     CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
4480     JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
4481     if (cmacCtx == nullptr) {
4482         conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
4483         return;
4484     }
4485     CMAC_CTX_free(cmacCtx);
4486 }
4487 
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)4488 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
4489     CHECK_ERROR_QUEUE_ON_RETURN;
4490     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4491     JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
4492     if (cmacCtx == nullptr) {
4493         return;
4494     }
4495     ScopedByteArrayRO keyBytes(env, keyArray);
4496     if (keyBytes.get() == nullptr) {
4497         return;
4498     }
4499 
4500     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4501 
4502     const EVP_CIPHER *cipher;
4503     switch(keyBytes.size()) {
4504       case 16:
4505           cipher = EVP_aes_128_cbc();
4506           break;
4507       case 24:
4508           cipher = EVP_aes_192_cbc();
4509           break;
4510       case 32:
4511           cipher = EVP_aes_256_cbc();
4512           break;
4513       default:
4514           conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4515                                            "CMAC_Init: Unsupported key length");
4516           return;
4517     }
4518 
4519     if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
4520         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
4521         JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
4522         return;
4523     }
4524 }
4525 
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)4526 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
4527                                            int inLength) {
4528     CHECK_ERROR_QUEUE_ON_RETURN;
4529     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4530     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4531     JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
4532 
4533     if (cmacCtx == nullptr) {
4534         return;
4535     }
4536 
4537     if (p == nullptr) {
4538         conscrypt::jniutil::throwNullPointerException(env, nullptr);
4539         return;
4540     }
4541 
4542     if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
4543         JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
4544         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
4545         return;
4546     }
4547 }
4548 
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4549 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
4550                                      jint inOffset, jint inLength) {
4551     CHECK_ERROR_QUEUE_ON_RETURN;
4552     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4553     JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
4554 
4555     if (cmacCtx == nullptr) {
4556         return;
4557     }
4558 
4559     ScopedByteArrayRO inBytes(env, inArray);
4560     if (inBytes.get() == nullptr) {
4561         return;
4562     }
4563 
4564     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4565         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4566                                            "inBytes");
4567         return;
4568     }
4569 
4570     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4571 
4572     if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4573         JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
4574                   inLength);
4575         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
4576         return;
4577     }
4578 }
4579 
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)4580 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
4581     CHECK_ERROR_QUEUE_ON_RETURN;
4582     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4583     JNI_TRACE("CMAC_Final(%p)", cmacCtx);
4584 
4585     if (cmacCtx == nullptr) {
4586         return nullptr;
4587     }
4588 
4589     uint8_t result[EVP_MAX_MD_SIZE];
4590     size_t len;
4591     if (!CMAC_Final(cmacCtx, result, &len)) {
4592         JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
4593         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
4594         return nullptr;
4595     }
4596 
4597     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4598     if (resultArray.get() == nullptr) {
4599         return nullptr;
4600     }
4601     ScopedByteArrayRW resultBytes(env, resultArray.get());
4602     if (resultBytes.get() == nullptr) {
4603         return nullptr;
4604     }
4605     memcpy(resultBytes.get(), result, len);
4606     return resultArray.release();
4607 }
4608 
NativeCrypto_CMAC_Reset(JNIEnv * env,jclass,jobject cmacCtxRef)4609 static void NativeCrypto_CMAC_Reset(JNIEnv* env, jclass, jobject cmacCtxRef) {
4610     CHECK_ERROR_QUEUE_ON_RETURN;
4611     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4612     JNI_TRACE("CMAC_Reset(%p)", cmacCtx);
4613 
4614     if (cmacCtx == nullptr) {
4615         return;
4616     }
4617 
4618     if (!CMAC_Reset(cmacCtx)) {
4619         JNI_TRACE("CMAC_Reset(%p) => threw exception", cmacCtx);
4620         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Reset");
4621         return;
4622     }
4623 }
4624 
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)4625 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
4626     CHECK_ERROR_QUEUE_ON_RETURN;
4627     JNI_TRACE("HMAC_CTX_new");
4628     auto hmacCtx = HMAC_CTX_new();
4629     if (hmacCtx == nullptr) {
4630         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
4631         return 0;
4632     }
4633 
4634     return reinterpret_cast<jlong>(hmacCtx);
4635 }
4636 
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)4637 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
4638     CHECK_ERROR_QUEUE_ON_RETURN;
4639     HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
4640     JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
4641     if (hmacCtx == nullptr) {
4642         conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
4643         return;
4644     }
4645     HMAC_CTX_free(hmacCtx);
4646 }
4647 
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)4648 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
4649                                       jobject evpMdRef) {
4650     CHECK_ERROR_QUEUE_ON_RETURN;
4651     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4652     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4653     JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
4654     if (hmacCtx == nullptr) {
4655         return;
4656     }
4657     ScopedByteArrayRO keyBytes(env, keyArray);
4658     if (keyBytes.get() == nullptr) {
4659         return;
4660     }
4661 
4662     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4663     if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
4664         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4665         JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
4666         return;
4667     }
4668 }
4669 
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)4670 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
4671                                            int inLength) {
4672     CHECK_ERROR_QUEUE_ON_RETURN;
4673     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4674     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4675     JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
4676 
4677     if (hmacCtx == nullptr) {
4678         return;
4679     }
4680 
4681     if (p == nullptr) {
4682         conscrypt::jniutil::throwNullPointerException(env, nullptr);
4683         return;
4684     }
4685 
4686     if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
4687         JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
4688         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
4689         return;
4690     }
4691 }
4692 
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4693 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
4694                                      jint inOffset, jint inLength) {
4695     CHECK_ERROR_QUEUE_ON_RETURN;
4696     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4697     JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
4698 
4699     if (hmacCtx == nullptr) {
4700         return;
4701     }
4702 
4703     ScopedByteArrayRO inBytes(env, inArray);
4704     if (inBytes.get() == nullptr) {
4705         return;
4706     }
4707 
4708     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4709         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4710                                            "inBytes");
4711         return;
4712     }
4713 
4714     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4715     if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4716         JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4717                   inLength);
4718         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4719         return;
4720     }
4721 }
4722 
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4723 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4724     CHECK_ERROR_QUEUE_ON_RETURN;
4725     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4726     JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4727 
4728     if (hmacCtx == nullptr) {
4729         return nullptr;
4730     }
4731 
4732     uint8_t result[EVP_MAX_MD_SIZE];
4733     unsigned len;
4734     if (!HMAC_Final(hmacCtx, result, &len)) {
4735         JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4736         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4737         return nullptr;
4738     }
4739 
4740     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4741     if (resultArray.get() == nullptr) {
4742         return nullptr;
4743     }
4744     ScopedByteArrayRW resultBytes(env, resultArray.get());
4745     if (resultBytes.get() == nullptr) {
4746         return nullptr;
4747     }
4748     memcpy(resultBytes.get(), result, len);
4749     return resultArray.release();
4750 }
4751 
NativeCrypto_HMAC_Reset(JNIEnv * env,jclass,jobject hmacCtxRef)4752 static void NativeCrypto_HMAC_Reset(JNIEnv* env, jclass, jobject hmacCtxRef) {
4753     CHECK_ERROR_QUEUE_ON_RETURN;
4754     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4755     JNI_TRACE("HMAC_Reset(%p)", hmacCtx);
4756 
4757     if (hmacCtx == nullptr) {
4758         return;
4759     }
4760 
4761     // HMAC_Init_ex with all nulls will reuse the existing key. This is slightly
4762     // more efficient than re-initializing the context with the key again.
4763     if (!HMAC_Init_ex(hmacCtx, /*key=*/nullptr, /*key_len=*/0, /*md=*/nullptr, /*impl=*/nullptr)) {
4764         JNI_TRACE("HMAC_Reset(%p) => threw exception", hmacCtx);
4765         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4766         return;
4767     }
4768 }
4769 
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4770 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4771     CHECK_ERROR_QUEUE_ON_RETURN;
4772     JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4773 
4774     ScopedByteArrayRW outputBytes(env, output);
4775     if (outputBytes.get() == nullptr) {
4776         return;
4777     }
4778 
4779     unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4780     if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4781         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4782         JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4783         return;
4784     }
4785 
4786     JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4787 }
4788 
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4789 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4790     /*
4791      * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4792      * Just make a buffer that's large enough here. The documentation recommends
4793      * 80 characters.
4794      */
4795     char output[128];
4796     int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4797     if (ret < 0) {
4798         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4799         return nullptr;
4800     } else if (size_t(ret) >= sizeof(output)) {
4801         conscrypt::jniutil::throwRuntimeException(env,
4802                                                   "ASN1_OBJECT_to_OID_string buffer too small");
4803         return nullptr;
4804     }
4805 
4806     JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4807     return env->NewStringUTF(output);
4808 }
4809 
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4810 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4811                                                  jboolean isFinite) {
4812     CHECK_ERROR_QUEUE_ON_RETURN;
4813     JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4814 
4815     if (streamObj == nullptr) {
4816         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4817         return 0;
4818     }
4819 
4820     const BIO_METHOD *method = stream_bio_method();
4821     if (!method) {
4822         return 0;
4823     }
4824     bssl::UniquePtr<BIO> bio(BIO_new(method));
4825     if (bio.get() == nullptr) {
4826         return 0;
4827     }
4828 
4829     bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4830 
4831     JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4832     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4833 }
4834 
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4835 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4836     CHECK_ERROR_QUEUE_ON_RETURN;
4837     JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4838 
4839     if (streamObj == nullptr) {
4840         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4841         return 0;
4842     }
4843 
4844     const BIO_METHOD *method = stream_bio_method();
4845     if (!method) {
4846         return 0;
4847     }
4848     bssl::UniquePtr<BIO> bio(BIO_new(method));
4849     if (bio.get() == nullptr) {
4850         return 0;
4851     }
4852 
4853     bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4854 
4855     JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4856     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4857 }
4858 
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4859 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4860     CHECK_ERROR_QUEUE_ON_RETURN;
4861     BIO* bio = to_BIO(env, bioRef);
4862     JNI_TRACE("BIO_free_all(%p)", bio);
4863 
4864     if (bio == nullptr) {
4865         return;
4866     }
4867 
4868     BIO_free_all(bio);
4869 }
4870 
4871 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4872 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4873     JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4874 
4875     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4876     if (buffer.get() == nullptr) {
4877         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4878         JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4879         return nullptr;
4880     }
4881 
4882     /* Don't interpret the string. */
4883     flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4884 
4885     /* Write in given format and null terminate. */
4886     X509_NAME_print_ex(buffer.get(), name, 0, flags);
4887     BIO_write(buffer.get(), "\0", 1);
4888 
4889     char* tmp;
4890     BIO_get_mem_data(buffer.get(), &tmp);
4891     JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4892     return env->NewStringUTF(tmp);
4893 }
4894 
4895 /**
4896  * Converts GENERAL_NAME items to the output format expected in
4897  * X509Certificate#getSubjectAlternativeNames and
4898  * X509Certificate#getIssuerAlternativeNames return.
4899  */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4900 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4901     switch (gen->type) {
4902         case GEN_EMAIL:
4903         case GEN_DNS:
4904         case GEN_URI: {
4905             // This must be a valid IA5String and must not contain NULs.
4906             // BoringSSL does not currently enforce the former (see
4907             // https://crbug.com/boringssl/427). The latter was historically an
4908             // issue for parsers that truncate at NUL.
4909             const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4910             ssize_t len = ASN1_STRING_length(gen->d.ia5);
4911             std::vector<jchar> jchars;
4912             jchars.reserve(len);
4913             for (ssize_t i = 0; i < len; i++) {
4914                 if (data[i] == 0 || data[i] > 127) {
4915                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4916                     return nullptr;
4917                 }
4918                 // Converting ASCII to UTF-16 is the identity function.
4919                 jchars.push_back(data[i]);
4920             }
4921             JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4922             return env->NewString(jchars.data(), jchars.size());
4923         }
4924         case GEN_DIRNAME:
4925             /* Write in RFC 2253 format */
4926             return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4927         case GEN_IPADD: {
4928 #ifdef _WIN32
4929             void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4930 #else
4931             const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4932 #endif
4933             if (gen->d.ip->length == 4) {
4934                 // IPv4
4935                 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4936                 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4937                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4938                     return env->NewStringUTF(buffer.get());
4939                 } else {
4940                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4941                               strerror(errno));
4942                 }
4943             } else if (gen->d.ip->length == 16) {
4944                 // IPv6
4945                 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4946                 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4947                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4948                     return env->NewStringUTF(buffer.get());
4949                 } else {
4950                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4951                               strerror(errno));
4952                 }
4953             }
4954 
4955             /* Invalid IP encodings are pruned out without throwing an exception. */
4956             return nullptr;
4957         }
4958         case GEN_RID:
4959             return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4960         case GEN_OTHERNAME:
4961         case GEN_X400:
4962         default:
4963             return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4964     }
4965 
4966     return nullptr;
4967 }
4968 
4969 #define GN_STACK_SUBJECT_ALT_NAME 1
4970 #define GN_STACK_ISSUER_ALT_NAME 2
4971 
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4972 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4973                                                              CONSCRYPT_UNUSED jobject holder,
4974                                                              jint type) {
4975     CHECK_ERROR_QUEUE_ON_RETURN;
4976     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4977     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4978 
4979     if (x509 == nullptr) {
4980         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4981         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4982         return nullptr;
4983     }
4984 
4985     bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4986     if (type == GN_STACK_SUBJECT_ALT_NAME) {
4987         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4988                 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4989     } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4990         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4991                 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4992     } else {
4993         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4994         return nullptr;
4995     }
4996     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4997     // |ERR_clear_error|, and throw CertificateParsingException.
4998     if (gn_stack == nullptr) {
4999         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
5000         ERR_clear_error();
5001         return nullptr;
5002     }
5003 
5004     int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
5005     if (count <= 0) {
5006         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
5007         return nullptr;
5008     }
5009 
5010     /*
5011      * Keep track of how many originally so we can ignore any invalid
5012      * values later.
5013      */
5014     const int origCount = count;
5015 
5016     ScopedLocalRef<jobjectArray> joa(
5017             env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
5018     for (int i = 0, j = 0; i < origCount; i++, j++) {
5019         GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
5020         ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
5021         if (env->ExceptionCheck()) {
5022             JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
5023                       x509, type);
5024             return nullptr;
5025         }
5026 
5027         /*
5028          * If it's nullptr, we'll have to skip this, reduce the number of total
5029          * entries, and fix up the array later.
5030          */
5031         if (val.get() == nullptr) {
5032             j--;
5033             count--;
5034             continue;
5035         }
5036 
5037         ScopedLocalRef<jobjectArray> item(
5038                 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
5039 
5040         ScopedLocalRef<jobject> parsedType(
5041                 env,
5042                 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
5043                                             conscrypt::jniutil::integer_valueOfMethod, gen->type));
5044         env->SetObjectArrayElement(item.get(), 0, parsedType.get());
5045         env->SetObjectArrayElement(item.get(), 1, val.get());
5046 
5047         env->SetObjectArrayElement(joa.get(), j, item.get());
5048     }
5049 
5050     if (count == 0) {
5051         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
5052                   x509, type, origCount);
5053         joa.reset(nullptr);
5054     } else if (origCount != count) {
5055         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
5056                   count);
5057 
5058         ScopedLocalRef<jobjectArray> joa_copy(
5059                 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
5060 
5061         for (int i = 0; i < count; i++) {
5062             ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
5063             env->SetObjectArrayElement(joa_copy.get(), i, item.get());
5064         }
5065 
5066         joa.reset(joa_copy.release());
5067     }
5068 
5069     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
5070     return joa.release();
5071 }
5072 
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5073 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
5074                                              CONSCRYPT_UNUSED jobject holder) {
5075     CHECK_ERROR_QUEUE_ON_RETURN;
5076     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5077     JNI_TRACE("X509_get_notBefore(%p)", x509);
5078 
5079     if (x509 == nullptr) {
5080         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5081         JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
5082         return 0;
5083     }
5084 
5085     ASN1_TIME* notBefore = X509_get_notBefore(x509);
5086     JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
5087     return reinterpret_cast<uintptr_t>(notBefore);
5088 }
5089 
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5090 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
5091                                             CONSCRYPT_UNUSED jobject holder) {
5092     CHECK_ERROR_QUEUE_ON_RETURN;
5093     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5094     JNI_TRACE("X509_get_notAfter(%p)", x509);
5095 
5096     if (x509 == nullptr) {
5097         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5098         JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
5099         return 0;
5100     }
5101 
5102     ASN1_TIME* notAfter = X509_get_notAfter(x509);
5103     JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
5104     return reinterpret_cast<uintptr_t>(notAfter);
5105 }
5106 
5107 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5108 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
5109                                           CONSCRYPT_UNUSED jobject holder) {
5110     CHECK_ERROR_QUEUE_ON_RETURN;
5111     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5112     JNI_TRACE("X509_get_version(%p)", x509);
5113 
5114     if (x509 == nullptr) {
5115         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5116         JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
5117         return 0;
5118     }
5119 
5120     // NOLINTNEXTLINE(runtime/int)
5121     long version = X509_get_version(x509);
5122     JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
5123     return version;
5124 }
5125 
5126 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))5127 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
5128                                             const ASN1_INTEGER* (*get_serial_func)(const T*)) {
5129     JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
5130 
5131     if (x509Type == nullptr) {
5132         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5133         JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
5134         return nullptr;
5135     }
5136 
5137     const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
5138     bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
5139     if (serialBn.get() == nullptr) {
5140         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5141         return nullptr;
5142     }
5143 
5144     ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
5145     if (env->ExceptionCheck()) {
5146         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5147         return nullptr;
5148     }
5149 
5150     JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
5151     return serialArray.release();
5152 }
5153 
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5154 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
5155                                                      CONSCRYPT_UNUSED jobject holder) {
5156     CHECK_ERROR_QUEUE_ON_RETURN;
5157     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5158     JNI_TRACE("X509_get_serialNumber(%p)", x509);
5159 
5160     if (x509 == nullptr) {
5161         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5162         JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
5163         return nullptr;
5164     }
5165     return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
5166 }
5167 
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)5168 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
5169                                                              jlong x509RevokedRef) {
5170     CHECK_ERROR_QUEUE_ON_RETURN;
5171     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5172     JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5173 
5174     if (revoked == nullptr) {
5175         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5176         JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
5177         return 0;
5178     }
5179     return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
5180 }
5181 
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5182 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
5183                                      CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5184     CHECK_ERROR_QUEUE_ON_RETURN;
5185     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5186     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5187     JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5188 
5189     if (pkey == nullptr) {
5190         JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5191         return;
5192     }
5193 
5194     if (x509 == nullptr) {
5195         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5196         JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5197         return;
5198     }
5199 
5200     if (X509_verify(x509, pkey) != 1) {
5201         conscrypt::jniutil::throwExceptionFromBoringSSLError(
5202                 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
5203         JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5204         return;
5205     }
5206     JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5207 }
5208 
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5209 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
5210                                                  CONSCRYPT_UNUSED jobject holder) {
5211     CHECK_ERROR_QUEUE_ON_RETURN;
5212     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5213     JNI_TRACE("get_X509_tbs_cert(%p)", x509);
5214     // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
5215     return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
5216 }
5217 
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5218 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
5219                                                              CONSCRYPT_UNUSED jobject holder,
5220                                                              jstring oidString) {
5221     CHECK_ERROR_QUEUE_ON_RETURN;
5222     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5223     JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
5224 
5225     if (x509 == nullptr) {
5226         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5227         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
5228         return nullptr;
5229     }
5230 
5231     bssl::UniquePtr<X509> copy(X509_dup(x509));
5232     if (copy == nullptr) {
5233         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
5234         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
5235         return nullptr;
5236     }
5237 
5238     ScopedUtfChars oid(env, oidString);
5239     if (oid.c_str() == nullptr) {
5240         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
5241         return nullptr;
5242     }
5243 
5244     bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
5245     if (obj.get() == nullptr) {
5246         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
5247                   oid.c_str());
5248         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5249                                            "Invalid OID.");
5250         ERR_clear_error();
5251         return nullptr;
5252     }
5253 
5254     int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
5255     if (extIndex == -1) {
5256         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
5257         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5258                                            "Extension not found.");
5259         return nullptr;
5260     }
5261 
5262     // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
5263     // cached encoding.
5264     X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
5265     return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
5266 }
5267 
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5268 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
5269                                            CONSCRYPT_UNUSED jobject holder) {
5270     CHECK_ERROR_QUEUE_ON_RETURN;
5271     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5272     JNI_TRACE("get_X509_ex_flags(%p)", x509);
5273 
5274     if (x509 == nullptr) {
5275         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5276         JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5277         return 0;
5278     }
5279 
5280     uint32_t flags = X509_get_extension_flags(x509);
5281     // X509_get_extension_flags sometimes leaves values in the error queue. See
5282     // https://crbug.com/boringssl/382.
5283     //
5284     // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
5285     // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
5286     // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
5287     // this JNI call to EXFLAG_CRITICAL.
5288     ERR_clear_error();
5289     return flags;
5290 }
5291 
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5292 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
5293                                            CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5294                                            CONSCRYPT_UNUSED jobject holder2) {
5295     CHECK_ERROR_QUEUE_ON_RETURN;
5296     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5297     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5298     JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5299 
5300     if (x509_1 == nullptr) {
5301         conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
5302         JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
5303         return 0;
5304     }
5305     if (x509_2 == nullptr) {
5306         conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
5307         JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
5308         return 0;
5309     }
5310     int ret = X509_check_issued(x509_1, x509_2);
5311     JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5312     return ret;
5313 }
5314 
get_X509_signature(X509 * x509)5315 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
5316     const ASN1_BIT_STRING* signature;
5317     X509_get0_signature(&signature, nullptr, x509);
5318     return signature;
5319 }
5320 
get_X509_CRL_signature(X509_CRL * crl)5321 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
5322     const ASN1_BIT_STRING* signature;
5323     X509_CRL_get0_signature(crl, &signature, nullptr);
5324     return signature;
5325 }
5326 
5327 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))5328 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
5329                                          const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
5330     JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5331 
5332     if (x509Type == nullptr) {
5333         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5334         JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5335         return nullptr;
5336     }
5337 
5338     const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
5339 
5340     ScopedLocalRef<jbyteArray> signatureArray(env,
5341                                               env->NewByteArray(ASN1_STRING_length(signature)));
5342     if (env->ExceptionCheck()) {
5343         JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5344         return nullptr;
5345     }
5346 
5347     ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5348     if (signatureBytes.get() == nullptr) {
5349         JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5350         return nullptr;
5351     }
5352 
5353     memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
5354 
5355     JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5356               ASN1_STRING_length(signature));
5357     return signatureArray.release();
5358 }
5359 
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5360 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
5361                                                   CONSCRYPT_UNUSED jobject holder) {
5362     CHECK_ERROR_QUEUE_ON_RETURN;
5363     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5364     JNI_TRACE("get_X509_signature(%p)", x509);
5365 
5366     if (x509 == nullptr) {
5367         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5368         JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
5369         return nullptr;
5370     }
5371     return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5372 }
5373 
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5374 static jbyteArray NativeCrypto_get_X509_CRL_signature(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_signature(%p)", crl);
5379 
5380     if (crl == nullptr) {
5381         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5382         JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
5383         return nullptr;
5384     }
5385     return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5386 }
5387 
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)5388 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
5389                                                 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
5390                                                 CONSCRYPT_UNUSED jobject holder2) {
5391     CHECK_ERROR_QUEUE_ON_RETURN;
5392     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5393     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5394     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5395 
5396     if (x509crl == nullptr) {
5397         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5398         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5399         return 0;
5400     } else if (x509 == nullptr) {
5401         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5402         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5403         return 0;
5404     }
5405 
5406     X509_REVOKED* revoked = nullptr;
5407     int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5408     if (ret == 0) {
5409         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5410         return 0;
5411     }
5412 
5413     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5414     return reinterpret_cast<uintptr_t>(revoked);
5415 }
5416 
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)5417 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
5418                                                   CONSCRYPT_UNUSED jobject holder,
5419                                                   jbyteArray serialArray) {
5420     CHECK_ERROR_QUEUE_ON_RETURN;
5421     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5422     JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5423 
5424     if (x509crl == nullptr) {
5425         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5426         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5427         return 0;
5428     }
5429 
5430     bssl::UniquePtr<BIGNUM> serialBn = arrayToBignum(env, serialArray);
5431     if (serialBn == nullptr) {
5432         if (!env->ExceptionCheck()) {
5433             conscrypt::jniutil::throwNullPointerException(env, "serial == null");
5434         }
5435         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5436         return 0;
5437     }
5438 
5439     bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
5440     if (serialInteger.get() == nullptr) {
5441         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5442         return 0;
5443     }
5444 
5445     X509_REVOKED* revoked = nullptr;
5446     int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5447     if (ret == 0) {
5448         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5449         return 0;
5450     }
5451 
5452     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5453     return reinterpret_cast<uintptr_t>(revoked);
5454 }
5455 
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5456 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
5457                                                     CONSCRYPT_UNUSED jobject holder) {
5458     CHECK_ERROR_QUEUE_ON_RETURN;
5459     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5460     JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5461 
5462     if (crl == nullptr) {
5463         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5464         JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
5465         return nullptr;
5466     }
5467 
5468     STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5469     if (stack == nullptr) {
5470         JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5471         return nullptr;
5472     }
5473 
5474     size_t size = sk_X509_REVOKED_num(stack);
5475 
5476     ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
5477     ScopedLongArrayRW revoked(env, revokedArray.get());
5478     for (size_t i = 0; i < size; i++) {
5479         X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5480         revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5481     }
5482 
5483     JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
5484     return revokedArray.release();
5485 }
5486 
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5487 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
5488                                             CONSCRYPT_UNUSED jobject holder) {
5489     CHECK_ERROR_QUEUE_ON_RETURN;
5490     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5491     JNI_TRACE("i2d_X509_CRL(%p)", crl);
5492 
5493     if (crl == nullptr) {
5494         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5495         JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
5496         return nullptr;
5497     }
5498     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
5499 }
5500 
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5501 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
5502                                        CONSCRYPT_UNUSED jobject holder) {
5503     CHECK_ERROR_QUEUE_ON_RETURN;
5504     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5505     JNI_TRACE("X509_CRL_free(%p)", crl);
5506 
5507     if (crl == nullptr) {
5508         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5509         JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5510         return;
5511     }
5512 
5513     X509_CRL_free(crl);
5514 }
5515 
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5516 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
5517                                         CONSCRYPT_UNUSED jobject holder) {
5518     CHECK_ERROR_QUEUE_ON_RETURN;
5519     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5520     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5521     JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5522 
5523     if (bio == nullptr) {
5524         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5525         JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5526         return;
5527     }
5528 
5529     if (crl == nullptr) {
5530         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5531         JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5532         return;
5533     }
5534 
5535     if (!X509_CRL_print(bio, crl)) {
5536         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
5537         JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5538         return;
5539     }
5540     JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5541 }
5542 
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5543 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5544                                                      CONSCRYPT_UNUSED jobject holder) {
5545     CHECK_ERROR_QUEUE_ON_RETURN;
5546     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5547     JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5548 
5549     if (crl == nullptr) {
5550         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5551         JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
5552         return nullptr;
5553     }
5554 
5555     const X509_ALGOR* sig_alg;
5556     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5557     const ASN1_OBJECT* oid;
5558     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5559     return ASN1_OBJECT_to_OID_string(env, oid);
5560 }
5561 
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)5562 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
5563     int param_type;
5564     const void* param_value;
5565     X509_ALGOR_get0(nullptr, &param_type, &param_value, algor);
5566 
5567     if (param_type == V_ASN1_UNDEF) {
5568         JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
5569         return nullptr;
5570     }
5571 
5572     // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
5573     // recreate it from the returned components.
5574     bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
5575     if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
5576         conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
5577         return nullptr;
5578     }
5579 
5580     return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
5581 }
5582 
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5583 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
5584                                                               CONSCRYPT_UNUSED jobject holder) {
5585     CHECK_ERROR_QUEUE_ON_RETURN;
5586     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5587     JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5588 
5589     if (crl == nullptr) {
5590         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5591         JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5592         return nullptr;
5593     }
5594 
5595     const X509_ALGOR* sig_alg;
5596     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5597     return get_X509_ALGOR_parameter(env, sig_alg);
5598 }
5599 
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5600 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
5601                                                         CONSCRYPT_UNUSED jobject holder) {
5602     CHECK_ERROR_QUEUE_ON_RETURN;
5603     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5604 
5605     if (crl == nullptr) {
5606         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5607         JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
5608         return nullptr;
5609     }
5610     JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5611     return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
5612 }
5613 
5614 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5615 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
5616                                               CONSCRYPT_UNUSED jobject holder) {
5617     CHECK_ERROR_QUEUE_ON_RETURN;
5618     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5619     JNI_TRACE("X509_CRL_get_version(%p)", crl);
5620 
5621     if (crl == nullptr) {
5622         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5623         JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
5624         return 0;
5625     }
5626     // NOLINTNEXTLINE(runtime/int)
5627     long version = X509_CRL_get_version(crl);
5628     JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5629     return version;
5630 }
5631 
5632 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5633           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)5634 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
5635     JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5636 
5637     if (x509Type == nullptr) {
5638         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5639         return nullptr;
5640     }
5641 
5642     ScopedUtfChars oid(env, oidString);
5643     if (oid.c_str() == nullptr) {
5644         return nullptr;
5645     }
5646 
5647     bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
5648     if (asn1.get() == nullptr) {
5649         JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5650         ERR_clear_error();
5651         return nullptr;
5652     }
5653 
5654     int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5655     if (extIndex == -1) {
5656         JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5657         return nullptr;
5658     }
5659 
5660     X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5661     JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5662     return ext;
5663 }
5664 
5665 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5666           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)5667 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
5668     X509_EXTENSION* ext =
5669             X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
5670     if (ext == nullptr) {
5671         JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5672         return nullptr;
5673     }
5674 
5675     JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
5676               X509_EXTENSION_get_data(ext));
5677     return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
5678                                               i2d_ASN1_OCTET_STRING);
5679 }
5680 
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)5681 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
5682                                            CONSCRYPT_UNUSED jobject holder, jstring oid) {
5683     CHECK_ERROR_QUEUE_ON_RETURN;
5684     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5685     JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5686 
5687     if (crl == nullptr) {
5688         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5689         JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
5690         return 0;
5691     }
5692     X509_EXTENSION* ext =
5693             X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
5694     JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5695     return reinterpret_cast<uintptr_t>(ext);
5696 }
5697 
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)5698 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5699                                                jstring oid) {
5700     CHECK_ERROR_QUEUE_ON_RETURN;
5701     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5702     JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5703     X509_EXTENSION* ext =
5704             X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5705                     env, revoked, oid);
5706     JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5707     return reinterpret_cast<uintptr_t>(ext);
5708 }
5709 
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)5710 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5711     CHECK_ERROR_QUEUE_ON_RETURN;
5712     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5713     JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5714 
5715     if (revoked == nullptr) {
5716         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5717         JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5718         return 0;
5719     }
5720 
5721     X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5722     JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5723     return reinterpret_cast<uintptr_t>(dup);
5724 }
5725 
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5726 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5727                                                           jlong x509RevokedRef) {
5728     CHECK_ERROR_QUEUE_ON_RETURN;
5729     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5730     JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5731 
5732     if (revoked == nullptr) {
5733         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5734         JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5735         return 0;
5736     }
5737 
5738     JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5739               X509_REVOKED_get0_revocationDate(revoked));
5740     return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5741 }
5742 
5743 #ifdef __GNUC__
5744 #pragma GCC diagnostic push
5745 #pragma GCC diagnostic ignored "-Wwrite-strings"
5746 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5747 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5748                                             jlong x509RevokedRef) {
5749     CHECK_ERROR_QUEUE_ON_RETURN;
5750     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5751     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5752     JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5753 
5754     if (bio == nullptr) {
5755         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5756         JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5757         return;
5758     }
5759 
5760     if (revoked == nullptr) {
5761         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5762         JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5763         return;
5764     }
5765 
5766     BIO_printf(bio, "Serial Number: ");
5767     i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5768     BIO_printf(bio, "\nRevocation Date: ");
5769     ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5770     BIO_printf(bio, "\n");
5771     // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5772     // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5773     X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5774                             0);
5775 }
5776 #ifndef _WIN32
5777 #pragma GCC diagnostic pop
5778 #endif
5779 
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5780 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5781                                                     CONSCRYPT_UNUSED jobject holder) {
5782     CHECK_ERROR_QUEUE_ON_RETURN;
5783     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5784     JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5785 
5786     if (crl == nullptr) {
5787         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5788         JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5789         return nullptr;
5790     }
5791     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5792 }
5793 
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5794 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5795                                          CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5796     CHECK_ERROR_QUEUE_ON_RETURN;
5797     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5798     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5799     JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5800 
5801     if (pkey == nullptr) {
5802         JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5803         return;
5804     }
5805 
5806     if (crl == nullptr) {
5807         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5808         JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5809         return;
5810     }
5811 
5812     if (X509_CRL_verify(crl, pkey) != 1) {
5813         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5814         JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5815         return;
5816     }
5817     JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5818 }
5819 
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5820 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5821                                                   CONSCRYPT_UNUSED jobject holder) {
5822     CHECK_ERROR_QUEUE_ON_RETURN;
5823     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5824     JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5825 
5826     if (crl == nullptr) {
5827         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5828         JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5829         return 0;
5830     }
5831 
5832     ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5833     JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5834     return reinterpret_cast<uintptr_t>(lastUpdate);
5835 }
5836 
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5837 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5838                                                   CONSCRYPT_UNUSED jobject holder) {
5839     CHECK_ERROR_QUEUE_ON_RETURN;
5840     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5841     JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5842 
5843     if (crl == nullptr) {
5844         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5845         JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5846         return 0;
5847     }
5848 
5849     ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5850     JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5851     return reinterpret_cast<uintptr_t>(nextUpdate);
5852 }
5853 
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5854 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5855     CHECK_ERROR_QUEUE_ON_RETURN;
5856     X509_REVOKED* x509Revoked =
5857             reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5858     JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5859     return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5860 }
5861 
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5862 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5863     CHECK_ERROR_QUEUE_ON_RETURN;
5864     X509_EXTENSION* ext =
5865             reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5866 
5867     if (ext == nullptr) {
5868         conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5869         return 0;
5870     }
5871 
5872     return X509_supported_extension(ext);
5873 }
5874 
decimal_to_integer(const char * data,size_t len,int * out)5875 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5876     int ret = 0;
5877     for (size_t i = 0; i < len; i++) {
5878         ret *= 10;
5879         if (data[i] < '0' || data[i] > '9') {
5880             return false;
5881         }
5882         ret += data[i] - '0';
5883     }
5884     *out = ret;
5885     return true;
5886 }
5887 
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5888 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5889                                                jobject calendar) {
5890     CHECK_ERROR_QUEUE_ON_RETURN;
5891     ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5892     JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5893 
5894     if (asn1Time == nullptr) {
5895         conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5896         return;
5897     }
5898 
5899     if (!ASN1_TIME_check(asn1Time)) {
5900         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5901         return;
5902     }
5903 
5904     bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5905     if (gen.get() == nullptr) {
5906         conscrypt::jniutil::throwParsingException(env,
5907                                                   "ASN1_TIME_to_generalizedtime returned null");
5908         return;
5909     }
5910 
5911     if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5912         conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5913         return;
5914     }
5915 
5916     int year, mon, mday, hour, min, sec;
5917     const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5918     if (!decimal_to_integer(data, 4, &year) ||
5919         !decimal_to_integer(data + 4, 2, &mon) ||
5920         !decimal_to_integer(data + 6, 2, &mday) ||
5921         !decimal_to_integer(data + 8, 2, &hour) ||
5922         !decimal_to_integer(data + 10, 2, &min) ||
5923         !decimal_to_integer(data + 12, 2, &sec)) {
5924         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5925         return;
5926     }
5927 
5928     env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5929                         min, sec);
5930 }
5931 
5932 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5933 // functions so that they can be freed properly when finished.  This struct owns
5934 // all objects pointed to by its members.
5935 struct CbsHandle {
5936     // A pointer to the CBS.
5937     std::unique_ptr<CBS> cbs;
5938     // A pointer to the data held by the CBS.  If the data held by the CBS
5939     // is owned by a different CbsHandle, data will be null.
5940     std::unique_ptr<unsigned char[]> data;
5941 };
5942 
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5943 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5944     CHECK_ERROR_QUEUE_ON_RETURN;
5945     JNI_TRACE("asn1_read_init(%p)", data);
5946 
5947     ScopedByteArrayRO bytes(env, data);
5948     if (bytes.get() == nullptr) {
5949         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5950         return 0;
5951     }
5952 
5953     std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5954     cbs->data.reset(new unsigned char[bytes.size()]);
5955     memcpy(cbs->data.get(), bytes.get(), bytes.size());
5956 
5957     cbs->cbs.reset(new CBS());
5958     CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5959     JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5960     return reinterpret_cast<uintptr_t>(cbs.release());
5961 }
5962 
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5963 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5964     CHECK_ERROR_QUEUE_ON_RETURN;
5965     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5966     JNI_TRACE("asn1_read_sequence(%p)", cbs);
5967 
5968     std::unique_ptr<CbsHandle> seq(new CbsHandle());
5969     seq->cbs.reset(new CBS());
5970     if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5971         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5972         return 0;
5973     }
5974     JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5975     return reinterpret_cast<uintptr_t>(seq.release());
5976 }
5977 
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5978 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5979                                                    jlong cbsRef, jint tag) {
5980     CHECK_ERROR_QUEUE_ON_RETURN;
5981     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5982     JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5983 
5984     int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5985                                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5986     JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5987     return result ? JNI_TRUE : JNI_FALSE;
5988 }
5989 
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5990 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5991     CHECK_ERROR_QUEUE_ON_RETURN;
5992     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5993     JNI_TRACE("asn1_read_tagged(%p)", cbs);
5994 
5995     std::unique_ptr<CbsHandle> tag(new CbsHandle());
5996     tag->cbs.reset(new CBS());
5997     if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5998         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5999         return 0;
6000     }
6001     JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
6002     return reinterpret_cast<uintptr_t>(tag.release());
6003 }
6004 
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)6005 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
6006     CHECK_ERROR_QUEUE_ON_RETURN;
6007     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6008     JNI_TRACE("asn1_read_octetstring(%p)", cbs);
6009 
6010     std::unique_ptr<CBS> str(new CBS());
6011     if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
6012         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6013         return 0;
6014     }
6015     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
6016     if (out.get() == nullptr) {
6017         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6018         return 0;
6019     }
6020     ScopedByteArrayRW outBytes(env, out.get());
6021     if (outBytes.get() == nullptr) {
6022         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6023         return 0;
6024     }
6025     memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
6026     JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
6027     return out.release();
6028 }
6029 
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)6030 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
6031     CHECK_ERROR_QUEUE_ON_RETURN;
6032     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6033     JNI_TRACE("asn1_read_uint64(%p)", cbs);
6034 
6035     // NOLINTNEXTLINE(runtime/int)
6036     uint64_t value;
6037     if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
6038         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6039         return 0;
6040     }
6041     return value;
6042 }
6043 
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)6044 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
6045     CHECK_ERROR_QUEUE_ON_RETURN;
6046     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6047     JNI_TRACE("asn1_read_null(%p)", cbs);
6048 
6049     CBS null_holder;
6050     if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
6051         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6052     }
6053 }
6054 
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)6055 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
6056     CHECK_ERROR_QUEUE_ON_RETURN;
6057     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6058     JNI_TRACE("asn1_read_oid(%p)", cbs);
6059 
6060     CBS oid_cbs;
6061     if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
6062         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6063         return nullptr;
6064     }
6065     int nid = OBJ_cbs2nid(&oid_cbs);
6066     if (nid == NID_undef) {
6067         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
6068         return nullptr;
6069     }
6070     const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
6071     if (obj == nullptr) {
6072         conscrypt::jniutil::throwIOException(env,
6073                                              "Error reading ASN.1 encoding: "
6074                                              "Could not find ASN1_OBJECT for NID");
6075         return nullptr;
6076     }
6077     return ASN1_OBJECT_to_OID_string(env, obj);
6078 }
6079 
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)6080 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
6081                                                 jlong cbsRef) {
6082     CHECK_ERROR_QUEUE_ON_RETURN;
6083     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6084     JNI_TRACE("asn1_read_is_empty(%p)", cbs);
6085 
6086     bool empty = (CBS_len(cbs->cbs.get()) == 0);
6087     JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
6088     return empty;
6089 }
6090 
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)6091 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
6092     CHECK_ERROR_QUEUE_ON_RETURN;
6093     if (cbsRef == 0) {
6094         JNI_TRACE("asn1_read_free(0)");
6095         return;
6096     }
6097     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6098     JNI_TRACE("asn1_read_free(%p)", cbs);
6099     delete cbs;
6100 }
6101 
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)6102 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
6103     CHECK_ERROR_QUEUE_ON_RETURN;
6104     JNI_TRACE("asn1_write_init");
6105     std::unique_ptr<CBB> cbb(new CBB());
6106     if (!CBB_init(cbb.get(), 128)) {
6107         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6108         return 0;
6109     }
6110     JNI_TRACE("asn1_write_init => %p", cbb.get());
6111     return reinterpret_cast<uintptr_t>(cbb.release());
6112 }
6113 
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)6114 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
6115     CHECK_ERROR_QUEUE_ON_RETURN;
6116     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6117     JNI_TRACE("asn1_write_sequence(%p)", cbb);
6118 
6119     std::unique_ptr<CBB> seq(new CBB());
6120     if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
6121         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6122         return 0;
6123     }
6124     JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
6125     return reinterpret_cast<uintptr_t>(seq.release());
6126 }
6127 
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)6128 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
6129     CHECK_ERROR_QUEUE_ON_RETURN;
6130     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6131     JNI_TRACE("asn1_write_tag(%p)", cbb);
6132 
6133     std::unique_ptr<CBB> tag_holder(new CBB());
6134     if (!CBB_add_asn1(cbb, tag_holder.get(),
6135                       CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
6136         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6137         return 0;
6138     }
6139     JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
6140     return reinterpret_cast<uintptr_t>(tag_holder.release());
6141 }
6142 
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)6143 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
6144                                                 jbyteArray data) {
6145     CHECK_ERROR_QUEUE_ON_RETURN;
6146     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6147     JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
6148 
6149     ScopedByteArrayRO bytes(env, data);
6150     if (bytes.get() == nullptr) {
6151         JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
6152         return;
6153     }
6154 
6155     std::unique_ptr<CBB> octetstring(new CBB());
6156     if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
6157         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6158         return;
6159     }
6160     if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
6161                        bytes.size())) {
6162         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6163         return;
6164     }
6165     if (!CBB_flush(cbb)) {
6166         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6167         return;
6168     }
6169 }
6170 
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)6171 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
6172     CHECK_ERROR_QUEUE_ON_RETURN;
6173     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6174     JNI_TRACE("asn1_write_uint64(%p)", cbb);
6175 
6176     if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
6177         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6178         return;
6179     }
6180 }
6181 
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)6182 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
6183     CHECK_ERROR_QUEUE_ON_RETURN;
6184     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6185     JNI_TRACE("asn1_write_null(%p)", cbb);
6186 
6187     CBB null_holder;
6188     if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
6189         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6190         return;
6191     }
6192     if (!CBB_flush(cbb)) {
6193         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6194         return;
6195     }
6196 }
6197 
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)6198 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
6199     CHECK_ERROR_QUEUE_ON_RETURN;
6200     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6201     JNI_TRACE("asn1_write_oid(%p)", cbb);
6202 
6203     ScopedUtfChars oid_chars(env, oid);
6204     if (oid_chars.c_str() == nullptr) {
6205         return;
6206     }
6207 
6208     int nid = OBJ_txt2nid(oid_chars.c_str());
6209     if (nid == NID_undef) {
6210         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6211         return;
6212     }
6213 
6214     if (!OBJ_nid2cbb(cbb, nid)) {
6215         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6216         return;
6217     }
6218 }
6219 
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)6220 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
6221     CHECK_ERROR_QUEUE_ON_RETURN;
6222     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6223     JNI_TRACE("asn1_write_flush(%p)", cbb);
6224 
6225     if (!CBB_flush(cbb)) {
6226         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6227         return;
6228     }
6229 }
6230 
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)6231 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
6232     CHECK_ERROR_QUEUE_ON_RETURN;
6233     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6234     JNI_TRACE("asn1_write_finish(%p)", cbb);
6235 
6236     uint8_t* data;
6237     size_t data_len;
6238     if (!CBB_finish(cbb, &data, &data_len)) {
6239         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6240         return 0;
6241     }
6242     bssl::UniquePtr<uint8_t> data_storage(data);
6243     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
6244     if (out.get() == nullptr) {
6245         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6246         return 0;
6247     }
6248     ScopedByteArrayRW outBytes(env, out.get());
6249     if (outBytes.get() == nullptr) {
6250         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6251         return 0;
6252     }
6253     memcpy(outBytes.get(), data, data_len);
6254     return out.release();
6255 }
6256 
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6257 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6258     CHECK_ERROR_QUEUE_ON_RETURN;
6259     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6260     JNI_TRACE("asn1_write_cleanup(%p)", cbb);
6261 
6262     CBB_cleanup(cbb);
6263 }
6264 
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6265 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6266     CHECK_ERROR_QUEUE_ON_RETURN;
6267     if (cbbRef == 0) {
6268         JNI_TRACE("asn1_write_free(0)");
6269         return;
6270     }
6271     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6272     JNI_TRACE("asn1_write_free(%p)", cbb);
6273     delete cbb;
6274 }
6275 
6276 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)6277 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6278     BIO* bio = to_BIO(env, bioRef);
6279     JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
6280 
6281     if (bio == nullptr) {
6282         return 0;
6283     }
6284 
6285     T* x = d2i_func(bio, nullptr);
6286     if (x == nullptr) {
6287         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
6288         return 0;
6289     }
6290 
6291     return reinterpret_cast<uintptr_t>(x);
6292 }
6293 
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)6294 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
6295     CHECK_ERROR_QUEUE_ON_RETURN;
6296     return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
6297 }
6298 
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)6299 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6300     CHECK_ERROR_QUEUE_ON_RETURN;
6301     return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
6302 }
6303 
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)6304 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
6305     CHECK_ERROR_QUEUE_ON_RETURN;
6306     ScopedByteArrayRO bytes(env, certBytes);
6307     if (bytes.get() == nullptr) {
6308         JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
6309         return 0;
6310     }
6311 
6312     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
6313     // NOLINTNEXTLINE(runtime/int)
6314     X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
6315     if (x == nullptr) {
6316         conscrypt::jniutil::throwExceptionFromBoringSSLError(
6317                 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
6318         return 0;
6319     }
6320     return reinterpret_cast<uintptr_t>(x);
6321 }
6322 
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6323 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
6324                                         CONSCRYPT_UNUSED jobject holder) {
6325     CHECK_ERROR_QUEUE_ON_RETURN;
6326     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6327     JNI_TRACE("i2d_X509(%p)", x509);
6328 
6329     if (x509 == nullptr) {
6330         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6331         JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
6332         return nullptr;
6333     }
6334     return ASN1ToByteArray<X509>(env, x509, i2d_X509);
6335 }
6336 
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6337 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
6338                                                CONSCRYPT_UNUSED jobject holder) {
6339     CHECK_ERROR_QUEUE_ON_RETURN;
6340     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6341     JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
6342 
6343     if (x509 == nullptr) {
6344         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6345         JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
6346         return nullptr;
6347     }
6348     return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
6349 }
6350 
6351 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)6352 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
6353     BIO* bio = to_BIO(env, bioRef);
6354     JNI_TRACE("PEM_to_jlong(%p)", bio);
6355 
6356     if (bio == nullptr) {
6357         JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
6358         return 0;
6359     }
6360 
6361     T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
6362     if (x == nullptr) {
6363         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
6364         JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
6365         return 0;
6366     }
6367 
6368     JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
6369     return reinterpret_cast<uintptr_t>(x);
6370 }
6371 
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)6372 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
6373     CHECK_ERROR_QUEUE_ON_RETURN;
6374     // NOLINTNEXTLINE(runtime/int)
6375     JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
6376     return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
6377 }
6378 
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)6379 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
6380     CHECK_ERROR_QUEUE_ON_RETURN;
6381     // NOLINTNEXTLINE(runtime/int)
6382     JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
6383     return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
6384 }
6385 
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)6386 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
6387     CHECK_ERROR_QUEUE_ON_RETURN;
6388     // NOLINTNEXTLINE(runtime/int)
6389     JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
6390     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
6391 }
6392 
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)6393 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
6394     CHECK_ERROR_QUEUE_ON_RETURN;
6395     // NOLINTNEXTLINE(runtime/int)
6396     JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
6397     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
6398 }
6399 
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)6400 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
6401     if (certs == nullptr) {
6402         return nullptr;
6403     }
6404 
6405     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6406     size_t size = sk_X509_num(certs);
6407     ref_array.reset(env->NewLongArray(size));
6408     ScopedLongArrayRW items(env, ref_array.get());
6409     for (size_t i = 0; i < size; i++) {
6410         X509* cert = sk_X509_value(certs, i);
6411         X509_up_ref(cert);
6412         items[i] = reinterpret_cast<uintptr_t>(cert);
6413     }
6414 
6415     JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
6416     return ref_array.release();
6417 }
6418 
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)6419 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
6420     if (crls == nullptr) {
6421         return nullptr;
6422     }
6423 
6424     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6425     size_t size = sk_X509_CRL_num(crls);
6426     ref_array.reset(env->NewLongArray(size));
6427     ScopedLongArrayRW items(env, ref_array.get());
6428     for (size_t i = 0; i < size; i++) {
6429         X509_CRL* crl = sk_X509_CRL_value(crls, i);
6430         X509_CRL_up_ref(crl);
6431         items[i] = reinterpret_cast<uintptr_t>(crl);
6432     }
6433 
6434     JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
6435     return ref_array.release();
6436 }
6437 
6438 #define PKCS7_CERTS 1
6439 #define PKCS7_CRLS 2
6440 
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)6441 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
6442     CHECK_ERROR_QUEUE_ON_RETURN;
6443     STACK_OF(X509)* stack = sk_X509_new_null();
6444 
6445     ScopedLongArrayRO certs(env, certsArray);
6446     for (size_t i = 0; i < certs.size(); i++) {
6447         X509* item = reinterpret_cast<X509*>(certs[i]);
6448         if (sk_X509_push(stack, item) == 0) {
6449             sk_X509_free(stack);
6450             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
6451             return nullptr;
6452         }
6453     }
6454 
6455     bssl::ScopedCBB out;
6456     CBB_init(out.get(), 1024 * certs.size());
6457     if (!PKCS7_bundle_certificates(out.get(), stack)) {
6458         sk_X509_free(stack);
6459         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
6460         return nullptr;
6461     }
6462 
6463     sk_X509_free(stack);
6464 
6465     return CBBToByteArray(env, out.get());
6466 }
6467 
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)6468 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
6469     CHECK_ERROR_QUEUE_ON_RETURN;
6470     BIO* bio = to_BIO(env, bioRef);
6471     JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
6472 
6473     if (bio == nullptr) {
6474         JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
6475         return nullptr;
6476     }
6477 
6478     if (which == PKCS7_CERTS) {
6479         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6480         if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
6481             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
6482             return nullptr;
6483         }
6484         return X509s_to_ItemArray(env, outCerts.get());
6485     } else if (which == PKCS7_CRLS) {
6486         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6487         if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
6488             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
6489             return nullptr;
6490         }
6491         return X509_CRLs_to_ItemArray(env, outCRLs.get());
6492     } else {
6493         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6494         return nullptr;
6495     }
6496 }
6497 
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)6498 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
6499     CHECK_ERROR_QUEUE_ON_RETURN;
6500     BIO* bio = to_BIO(env, bioRef);
6501     JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
6502 
6503     if (bio == nullptr) {
6504         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
6505         return nullptr;
6506     }
6507 
6508     uint8_t* data;
6509     size_t len;
6510     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6511         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
6512                 conscrypt::jniutil::throwParsingException);
6513         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
6514         return nullptr;
6515     }
6516     bssl::UniquePtr<uint8_t> data_storage(data);
6517 
6518     CBS cbs;
6519     CBS_init(&cbs, data, len);
6520 
6521     if (which == PKCS7_CERTS) {
6522         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6523         if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
6524             conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
6525                     "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
6526             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
6527             return nullptr;
6528         }
6529         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
6530         return X509s_to_ItemArray(env, outCerts.get());
6531     } else if (which == PKCS7_CRLS) {
6532         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6533         if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
6534             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
6535                     conscrypt::jniutil::throwParsingException);
6536             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
6537             return nullptr;
6538         }
6539         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
6540         return X509_CRLs_to_ItemArray(env, outCRLs.get());
6541     } else {
6542         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6543         return nullptr;
6544     }
6545 }
6546 
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)6547 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6548     CHECK_ERROR_QUEUE_ON_RETURN;
6549     BIO* bio = to_BIO(env, bioRef);
6550     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
6551 
6552     if (bio == nullptr) {
6553         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
6554         return nullptr;
6555     }
6556 
6557     uint8_t* data;
6558     size_t len;
6559     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6560         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
6561                 conscrypt::jniutil::throwParsingException);
6562         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
6563         return nullptr;
6564     }
6565     bssl::UniquePtr<uint8_t> data_storage(data);
6566 
6567     bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
6568     if (path.get() == nullptr) {
6569         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
6570         return nullptr;
6571     }
6572 
6573     CBS cbs, sequence;
6574     CBS_init(&cbs, data, len);
6575     if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
6576         conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6577         ERR_clear_error();
6578         return nullptr;
6579     }
6580 
6581     while (CBS_len(&sequence) > 0) {
6582         CBS child;
6583         if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
6584             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6585             ERR_clear_error();
6586             return nullptr;
6587         }
6588 
6589         const uint8_t* tmp = CBS_data(&child);
6590         // NOLINTNEXTLINE(runtime/int)
6591         bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
6592         if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
6593             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6594             ERR_clear_error();
6595             return nullptr;
6596         }
6597 
6598         if (!sk_X509_push(path.get(), cert.get())) {
6599             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
6600             return nullptr;
6601         }
6602         OWNERSHIP_TRANSFERRED(cert);
6603     }
6604 
6605     size_t size = sk_X509_num(path.get());
6606 
6607     ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
6608     ScopedLongArrayRW certs(env, certArray.get());
6609     for (size_t i = 0; i < size; i++) {
6610         X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
6611         certs[i] = reinterpret_cast<uintptr_t>(item);
6612     }
6613 
6614     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
6615     return certArray.release();
6616 }
6617 
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)6618 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
6619     CHECK_ERROR_QUEUE_ON_RETURN;
6620     JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
6621     ScopedLongArrayRO certsArray(env, certs);
6622     if (certsArray.get() == nullptr) {
6623         JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
6624         return nullptr;
6625     }
6626 
6627     bssl::ScopedCBB result;
6628     CBB seq_contents;
6629     if (!CBB_init(result.get(), 2048 * certsArray.size())) {
6630         JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
6631         return nullptr;
6632     }
6633     if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
6634         return nullptr;
6635     }
6636 
6637     for (size_t i = 0; i < certsArray.size(); i++) {
6638         X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
6639         uint8_t* buf;
6640         int len = i2d_X509(x509, nullptr);
6641 
6642         if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
6643             i2d_X509(x509, &buf) < 0) {
6644             return nullptr;
6645         }
6646     }
6647 
6648     return CBBToByteArray(env, result.get());
6649 }
6650 
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6651 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
6652                                    CONSCRYPT_UNUSED jobject holder) {
6653     CHECK_ERROR_QUEUE_ON_RETURN;
6654     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6655     JNI_TRACE("X509_free(%p)", x509);
6656 
6657     if (x509 == nullptr) {
6658         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6659         JNI_TRACE("X509_free(%p) => x509 == null", x509);
6660         return;
6661     }
6662 
6663     X509_free(x509);
6664 }
6665 
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)6666 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
6667                                   CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
6668                                   CONSCRYPT_UNUSED jobject holder2) {
6669     CHECK_ERROR_QUEUE_ON_RETURN;
6670     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
6671     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
6672     JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
6673 
6674     if (x509_1 == nullptr) {
6675         conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
6676         JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
6677         return -1;
6678     }
6679 
6680     if (x509_2 == nullptr) {
6681         conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
6682         JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
6683         return -1;
6684     }
6685 
6686     int ret = X509_cmp(x509_1, x509_2);
6687     JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6688     return ret;
6689 }
6690 
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)6691 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6692                                        CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
6693                                        jlong certflagJava) {
6694     CHECK_ERROR_QUEUE_ON_RETURN;
6695     BIO* bio = to_BIO(env, bioRef);
6696     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6697     // NOLINTNEXTLINE(runtime/int)
6698     unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
6699     // NOLINTNEXTLINE(runtime/int)
6700     unsigned long certflag = static_cast<unsigned long>(certflagJava);
6701     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6702 
6703     if (bio == nullptr) {
6704         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6705         return;
6706     }
6707 
6708     if (x509 == nullptr) {
6709         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6710         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6711         return;
6712     }
6713 
6714     if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6715         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
6716         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6717         return;
6718     }
6719     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6720 }
6721 
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6722 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
6723                                           CONSCRYPT_UNUSED jobject holder) {
6724     CHECK_ERROR_QUEUE_ON_RETURN;
6725     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6726     JNI_TRACE("X509_get_pubkey(%p)", x509);
6727 
6728     if (x509 == nullptr) {
6729         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6730         JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6731         return 0;
6732     }
6733 
6734     bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6735     if (pkey.get() == nullptr) {
6736         const uint32_t last_error = ERR_peek_last_error();
6737         const uint32_t first_error = ERR_peek_error();
6738         if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6739              ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6740             (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6741              ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6742             ERR_clear_error();
6743             conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6744             return 0;
6745         }
6746 
6747         conscrypt::jniutil::throwExceptionFromBoringSSLError(
6748                 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6749         return 0;
6750     }
6751 
6752     JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6753     return reinterpret_cast<uintptr_t>(pkey.release());
6754 }
6755 
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6756 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6757                                                     CONSCRYPT_UNUSED jobject holder) {
6758     CHECK_ERROR_QUEUE_ON_RETURN;
6759     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6760     JNI_TRACE("X509_get_issuer_name(%p)", x509);
6761 
6762     if (x509 == nullptr) {
6763         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6764         JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6765         return nullptr;
6766     }
6767     return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6768 }
6769 
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6770 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6771                                                      CONSCRYPT_UNUSED jobject holder) {
6772     CHECK_ERROR_QUEUE_ON_RETURN;
6773     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6774     JNI_TRACE("X509_get_subject_name(%p)", x509);
6775 
6776     if (x509 == nullptr) {
6777         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6778         JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6779         return nullptr;
6780     }
6781     return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6782 }
6783 
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6784 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6785                                                 CONSCRYPT_UNUSED jobject holder) {
6786     CHECK_ERROR_QUEUE_ON_RETURN;
6787     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6788     JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6789 
6790     if (x509 == nullptr) {
6791         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6792         JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6793         return nullptr;
6794     }
6795 
6796     X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6797     ASN1_OBJECT* algorithm;
6798     X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6799     return ASN1_OBJECT_to_OID_string(env, algorithm);
6800 }
6801 
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6802 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6803                                                  CONSCRYPT_UNUSED jobject holder) {
6804     CHECK_ERROR_QUEUE_ON_RETURN;
6805     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6806     JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6807 
6808     if (x509 == nullptr) {
6809         conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6810         JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6811         return nullptr;
6812     }
6813 
6814     const X509_ALGOR* sig_alg;
6815     X509_get0_signature(nullptr, &sig_alg, x509);
6816     const ASN1_OBJECT* oid;
6817     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6818     return ASN1_OBJECT_to_OID_string(env, oid);
6819 }
6820 
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6821 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6822                                                           CONSCRYPT_UNUSED jobject holder) {
6823     CHECK_ERROR_QUEUE_ON_RETURN;
6824     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6825     JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6826 
6827     if (x509 == nullptr) {
6828         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6829         JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6830         return nullptr;
6831     }
6832 
6833     const X509_ALGOR* sig_alg;
6834     X509_get0_signature(nullptr, &sig_alg, x509);
6835     return get_X509_ALGOR_parameter(env, sig_alg);
6836 }
6837 
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6838 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6839                                                      CONSCRYPT_UNUSED jobject holder) {
6840     CHECK_ERROR_QUEUE_ON_RETURN;
6841     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6842     JNI_TRACE("get_X509_issuerUID(%p)", x509);
6843 
6844     if (x509 == nullptr) {
6845         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6846         JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6847         return nullptr;
6848     }
6849 
6850     const ASN1_BIT_STRING* issuer_uid;
6851     X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6852     if (issuer_uid == nullptr) {
6853         JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6854         return nullptr;
6855     }
6856 
6857     return ASN1BitStringToBooleanArray(env, issuer_uid);
6858 }
6859 
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6860 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6861                                                       CONSCRYPT_UNUSED jobject holder) {
6862     CHECK_ERROR_QUEUE_ON_RETURN;
6863     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6864     JNI_TRACE("get_X509_subjectUID(%p)", x509);
6865 
6866     if (x509 == nullptr) {
6867         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6868         JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6869         return nullptr;
6870     }
6871 
6872     const ASN1_BIT_STRING* subject_uid;
6873     X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6874     if (subject_uid == nullptr) {
6875         JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6876         return nullptr;
6877     }
6878 
6879     return ASN1BitStringToBooleanArray(env, subject_uid);
6880 }
6881 
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6882 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6883                                                      CONSCRYPT_UNUSED jobject holder) {
6884     CHECK_ERROR_QUEUE_ON_RETURN;
6885     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6886     JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6887 
6888     if (x509 == nullptr) {
6889         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6890         JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6891         return nullptr;
6892     }
6893 
6894     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6895     // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6896     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6897     bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6898             static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6899     if (bitStr.get() == nullptr) {
6900         JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6901         ERR_clear_error();
6902         return nullptr;
6903     }
6904 
6905     return ASN1BitStringToBooleanArray(env, bitStr.get());
6906 }
6907 
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6908 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6909                                                      CONSCRYPT_UNUSED jobject holder) {
6910     CHECK_ERROR_QUEUE_ON_RETURN;
6911     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6912     JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6913 
6914     if (x509 == nullptr) {
6915         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6916         JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6917         return nullptr;
6918     }
6919 
6920     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6921     // |ERR_clear_error|, and throw CertificateParsingException.
6922     bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6923             X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6924     if (objArray.get() == nullptr) {
6925         JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6926         ERR_clear_error();
6927         return nullptr;
6928     }
6929 
6930     size_t size = sk_ASN1_OBJECT_num(objArray.get());
6931     ScopedLocalRef<jobjectArray> exKeyUsage(
6932             env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6933                                      nullptr));
6934     if (exKeyUsage.get() == nullptr) {
6935         return nullptr;
6936     }
6937 
6938     for (size_t i = 0; i < size; i++) {
6939         ScopedLocalRef<jstring> oidStr(
6940                 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6941         env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6942     }
6943 
6944     JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6945     return exKeyUsage.release();
6946 }
6947 
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6948 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6949                                              CONSCRYPT_UNUSED jobject holder) {
6950     CHECK_ERROR_QUEUE_ON_RETURN;
6951     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6952     JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6953 
6954     if (x509 == nullptr) {
6955         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6956         JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6957         return 0;
6958     }
6959 
6960     // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6961     // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6962     // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6963     // the constructor even if |EXFLAG_INVALID| is set.
6964     //
6965     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6966     // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6967     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6968     bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6969             X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6970     if (basic_constraints == nullptr) {
6971         JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6972         ERR_clear_error();
6973         return -1;
6974     }
6975 
6976     if (basic_constraints->pathlen == nullptr) {
6977         JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6978         return -1;
6979     }
6980 
6981     if (!basic_constraints->ca) {
6982         // Path length constraints are only valid for CA certificates.
6983         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6984         JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6985         return -1;
6986     }
6987 
6988     if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6989         // Path length constraints may not be negative.
6990         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6991         JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6992         return -1;
6993     }
6994 
6995     long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6996     if (pathlen == -1 || pathlen > INT_MAX) {
6997         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6998         // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6999         // constraint is plausible, but Chromium rejects all values above 255.
7000         JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
7001         return -1;
7002     }
7003 
7004     JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
7005     return pathlen;
7006 }
7007 
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)7008 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
7009                                                 CONSCRYPT_UNUSED jobject holder,
7010                                                 jstring oidString) {
7011     CHECK_ERROR_QUEUE_ON_RETURN;
7012     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7013     JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
7014     return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
7015 }
7016 
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)7017 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
7018                                                     CONSCRYPT_UNUSED jobject holder,
7019                                                     jstring oidString) {
7020     CHECK_ERROR_QUEUE_ON_RETURN;
7021     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
7022     JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
7023 
7024     if (crl == nullptr) {
7025         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
7026         JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
7027         return nullptr;
7028     }
7029     return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
7030                                                                                      oidString);
7031 }
7032 
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)7033 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
7034                                                         jstring oidString) {
7035     CHECK_ERROR_QUEUE_ON_RETURN;
7036     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
7037     JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
7038 
7039     if (revoked == nullptr) {
7040         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
7041         JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
7042         return nullptr;
7043     }
7044     return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
7045             env, revoked, oidString);
7046 }
7047 
7048 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
7049           X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)7050 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
7051     T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
7052     JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
7053 
7054     if (x509 == nullptr) {
7055         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
7056         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
7057         return nullptr;
7058     }
7059 
7060     int lastPos = -1;
7061     int count = 0;
7062     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7063         count++;
7064     }
7065 
7066     JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
7067 
7068     ScopedLocalRef<jobjectArray> joa(
7069             env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
7070     if (joa.get() == nullptr) {
7071         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
7072         return nullptr;
7073     }
7074 
7075     lastPos = -1;
7076     count = 0;
7077     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7078         X509_EXTENSION* ext = get_ext_func(x509, lastPos);
7079 
7080         ScopedLocalRef<jstring> extOid(
7081                 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
7082         if (extOid.get() == nullptr) {
7083             JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
7084             return nullptr;
7085         }
7086 
7087         env->SetObjectArrayElement(joa.get(), count++, extOid.get());
7088     }
7089 
7090     JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
7091     return joa.release();
7092 }
7093 
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)7094 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
7095                                                    CONSCRYPT_UNUSED jobject holder, jint critical) {
7096     CHECK_ERROR_QUEUE_ON_RETURN;
7097     // NOLINTNEXTLINE(runtime/int)
7098     JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
7099     return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
7100                                                                                critical);
7101 }
7102 
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)7103 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
7104                                                        CONSCRYPT_UNUSED jobject holder,
7105                                                        jint critical) {
7106     CHECK_ERROR_QUEUE_ON_RETURN;
7107     // NOLINTNEXTLINE(runtime/int)
7108     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
7109     return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
7110             env, x509CrlRef, critical);
7111 }
7112 
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)7113 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
7114                                                            jlong x509RevokedRef, jint critical) {
7115     CHECK_ERROR_QUEUE_ON_RETURN;
7116     // NOLINTNEXTLINE(runtime/int)
7117     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
7118     return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
7119                                  X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
7120 }
7121 
7122 /**
7123  * Based on example logging call back from SSL_CTX_set_info_callback man page
7124  */
info_callback_LOG(const SSL * s,int where,int ret)7125 static void info_callback_LOG(const SSL* s, int where, int ret) {
7126     int w = where & ~SSL_ST_MASK;
7127     const char* str;
7128     if (w & SSL_ST_CONNECT) {
7129         str = "SSL_connect";
7130     } else if (w & SSL_ST_ACCEPT) {
7131         str = "SSL_accept";
7132     } else {
7133         str = "undefined";
7134     }
7135 
7136     if (where & SSL_CB_LOOP) {
7137         JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
7138     } else if (where & SSL_CB_ALERT) {
7139         str = (where & SSL_CB_READ) ? "read" : "write";
7140         JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
7141                   SSL_alert_desc_string_long(ret));
7142     } else if (where & SSL_CB_EXIT) {
7143         if (ret == 0) {
7144             JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
7145                       SSL_state_string_long(s));
7146         } else if (ret < 0) {
7147             JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
7148                       SSL_state_string_long(s));
7149         } else if (ret == 1) {
7150             JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
7151                       SSL_state_string_long(s));
7152         } else {
7153             JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
7154                       SSL_state_string_long(s));
7155         }
7156     } else if (where & SSL_CB_HANDSHAKE_START) {
7157         JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
7158                   SSL_state_string_long(s));
7159     } else if (where & SSL_CB_HANDSHAKE_DONE) {
7160         JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
7161                   SSL_state_string_long(s));
7162     } else {
7163         JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
7164                   SSL_state_string_long(s));
7165     }
7166 }
7167 
7168 #ifdef _WIN32
7169 
7170 /**
7171  * Dark magic helper function that checks, for a given SSL session, whether it
7172  * can SSL_read() or SSL_write() without blocking. Takes into account any
7173  * concurrent attempts to close the SSLSocket from the Java side. This is
7174  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7175  * while thread #2 is sitting in a blocking read or write. The type argument
7176  * specifies whether we are waiting for readability or writability. It expects
7177  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7178  * only need to wait in case one of these problems occurs.
7179  *
7180  * @param env
7181  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7182  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
7183  * @param appData The application data structure with mutex info etc.
7184  * @param timeout_millis The timeout value for select call, with the special value
7185  *                0 meaning no timeout at all (wait indefinitely). Note: This is
7186  *                the Java semantics of the timeout value, not the usual
7187  *                select() semantics.
7188  * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
7189  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7190 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7191                      int timeout_millis) {
7192     int result = -1;
7193 
7194     NetFd fd(env, fdObject);
7195     do {
7196         if (fd.isClosed()) {
7197             result = THROWN_EXCEPTION;
7198             break;
7199         }
7200 
7201         WSAEVENT events[2];
7202         events[0] = appData->interruptEvent;
7203         events[1] = WSACreateEvent();
7204         if (events[1] == WSA_INVALID_EVENT) {
7205             JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
7206             break;
7207         }
7208 
7209         if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
7210                                                         FD_CLOSE) == SOCKET_ERROR) {
7211             JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
7212             break;
7213         }
7214 
7215         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7216                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7217                   timeout_millis);
7218 
7219         int rc = WSAWaitForMultipleEvents(
7220                 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
7221         if (rc == WSA_WAIT_FAILED) {
7222             JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
7223             result = -1;
7224         } else if (rc == WSA_WAIT_TIMEOUT) {
7225             result = 0;
7226         } else {
7227             result = 1;
7228         }
7229         WSACloseEvent(events[1]);
7230     } while (0);
7231 
7232     JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
7233               (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
7234               result);
7235 
7236     std::lock_guard<std::mutex> appDataLock(appData->mutex);
7237     appData->waitingThreads--;
7238 
7239     return result;
7240 }
7241 
7242 #else   // !defined(_WIN32)
7243 
7244 /**
7245  * Dark magic helper function that checks, for a given SSL session, whether it
7246  * can SSL_read() or SSL_write() without blocking. Takes into account any
7247  * concurrent attempts to close the SSLSocket from the Java side. This is
7248  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7249  * while thread #2 is sitting in a blocking read or write. The type argument
7250  * specifies whether we are waiting for readability or writability. It expects
7251  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7252  * only need to wait in case one of these problems occurs.
7253  *
7254  * @param env
7255  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7256  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
7257  * @param appData The application data structure with mutex info etc.
7258  * @param timeout_millis The timeout value for poll call, with the special value
7259  *                0 meaning no timeout at all (wait indefinitely). Note: This is
7260  *                the Java semantics of the timeout value, not the usual
7261  *                poll() semantics.
7262  * @return The result of the inner poll() call,
7263  * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
7264  * additional errors
7265  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7266 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7267                      int timeout_millis) {
7268     // This loop is an expanded version of the NET_FAILURE_RETRY
7269     // macro. It cannot simply be used in this case because poll
7270     // cannot be restarted without recreating the pollfd structure.
7271     int result;
7272     struct pollfd fds[2];
7273     do {
7274         NetFd fd(env, fdObject);
7275         if (fd.isClosed()) {
7276             result = THROWN_EXCEPTION;
7277             break;
7278         }
7279         int intFd = fd.get();
7280         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7281                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
7282 
7283         memset(&fds, 0, sizeof(fds));
7284         fds[0].fd = intFd;
7285         if (type == SSL_ERROR_WANT_READ) {
7286             fds[0].events = POLLIN | POLLPRI;
7287         } else {
7288             fds[0].events = POLLOUT | POLLPRI;
7289         }
7290 
7291         fds[1].fd = appData->fdsEmergency[0];
7292         fds[1].events = POLLIN | POLLPRI;
7293 
7294         // Converting from Java semantics to Posix semantics.
7295         if (timeout_millis <= 0) {
7296             timeout_millis = -1;
7297         }
7298 
7299         CompatibilityCloseMonitor monitor(intFd);
7300 
7301         result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
7302         JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
7303                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7304                   timeout_millis, result);
7305         if (result == -1) {
7306             if (fd.isClosed()) {
7307                 result = THROWN_EXCEPTION;
7308                 break;
7309             }
7310             if (errno != EINTR) {
7311                 break;
7312             }
7313         }
7314     } while (result == -1);
7315 
7316     std::lock_guard<std::mutex> appDataLock(appData->mutex);
7317 
7318     if (result > 0) {
7319         // We have been woken up by a token in the emergency pipe. We
7320         // can't be sure the token is still in the pipe at this point
7321         // because it could have already been read by the thread that
7322         // originally wrote it if it entered sslSelect and acquired
7323         // the mutex before we did. Thus we cannot safely read from
7324         // the pipe in a blocking way (so we make the pipe
7325         // non-blocking at creation).
7326         if (fds[1].revents & POLLIN) {
7327             char token;
7328             do {
7329                 (void)read(appData->fdsEmergency[0], &token, 1);
7330             } while (errno == EINTR);
7331         }
7332     }
7333 
7334     // Tell the world that there is now one thread less waiting for the
7335     // underlying network.
7336     appData->waitingThreads--;
7337 
7338     return result;
7339 }
7340 #endif  // !defined(_WIN32)
7341 
7342 /**
7343  * Helper function that wakes up a thread blocked in select(), in case there is
7344  * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
7345  * before closing the connection.
7346  *
7347  * @param data The application data structure with mutex info etc.
7348  */
sslNotify(AppData * appData)7349 static void sslNotify(AppData* appData) {
7350 #ifdef _WIN32
7351     SetEvent(appData->interruptEvent);
7352 #else
7353     // Write a byte to the emergency pipe, so a concurrent select() can return.
7354     // Note we have to restore the errno of the original system call, since the
7355     // caller relies on it for generating error messages.
7356     int errnoBackup = errno;
7357     char token = '*';
7358     do {
7359         errno = 0;
7360         (void)write(appData->fdsEmergency[1], &token, 1);
7361     } while (errno == EINTR);
7362     errno = errnoBackup;
7363 #endif
7364 }
7365 
toAppData(const SSL * ssl)7366 static AppData* toAppData(const SSL* ssl) {
7367     return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
7368 }
7369 
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)7370 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
7371     JNI_TRACE("ssl=%p cert_verify_callback", ssl);
7372 
7373     AppData* appData = toAppData(ssl);
7374     JNIEnv* env = appData->env;
7375     if (env == nullptr) {
7376         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
7377         JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
7378         return ssl_verify_invalid;
7379     }
7380 
7381     // Create the byte[][] array that holds all the certs
7382     ScopedLocalRef<jobjectArray> array(
7383             env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
7384     if (array.get() == nullptr) {
7385         return ssl_verify_invalid;
7386     }
7387 
7388     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7389     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
7390 
7391     const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
7392     const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
7393 
7394     JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
7395               authMethod);
7396     ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
7397     env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
7398 
7399     ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
7400     JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
7401     return result;
7402 }
7403 
7404 /**
7405  * Call back to watch for handshake to be completed. This is necessary for
7406  * False Start support, since SSL_do_handshake returns before the handshake is
7407  * completed in this case.
7408  */
info_callback(const SSL * ssl,int type,int value)7409 static void info_callback(const SSL* ssl, int type, int value) {
7410     JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
7411     if (conscrypt::trace::kWithJniTrace) {
7412         info_callback_LOG(ssl, type, value);
7413     }
7414     if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
7415         JNI_TRACE("ssl=%p info_callback ignored", ssl);
7416         return;
7417     }
7418 
7419     AppData* appData = toAppData(ssl);
7420     JNIEnv* env = appData->env;
7421     if (env == nullptr) {
7422         CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
7423         JNI_TRACE("ssl=%p info_callback env error", ssl);
7424         return;
7425     }
7426     if (env->ExceptionCheck()) {
7427         JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
7428         return;
7429     }
7430 
7431     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7432 
7433     JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
7434     env->CallVoidMethod(sslHandshakeCallbacks,
7435                         conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
7436 
7437     if (env->ExceptionCheck()) {
7438         JNI_TRACE("ssl=%p info_callback exception", ssl);
7439     }
7440     JNI_TRACE("ssl=%p info_callback completed", ssl);
7441 }
7442 
7443 /**
7444  * Call back to ask for a certificate. There are three possible exit codes:
7445  *
7446  * 1 is success.
7447  * 0 is error.
7448  * -1 is to pause the handshake to continue from the same place later.
7449  */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)7450 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
7451     JNI_TRACE("ssl=%p cert_cb", ssl);
7452 
7453     // cert_cb is called for both clients and servers, but we are only
7454     // interested in client certificates.
7455     if (SSL_is_server(ssl)) {
7456         JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
7457         return 1;
7458     }
7459 
7460     AppData* appData = toAppData(ssl);
7461     JNIEnv* env = appData->env;
7462     if (env == nullptr) {
7463         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
7464         JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
7465         return 0;
7466     }
7467     if (env->ExceptionCheck()) {
7468         JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
7469         return 0;
7470     }
7471     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7472 
7473     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
7474 
7475     // Call Java callback which can reconfigure the client certificate.
7476     const uint8_t* ctype = nullptr;
7477     size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
7478     const uint16_t* sigalgs = nullptr;
7479     size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
7480     ScopedLocalRef<jobjectArray> issuers(
7481             env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
7482     if (issuers.get() == nullptr) {
7483         return 0;
7484     }
7485 
7486     if (conscrypt::trace::kWithJniTrace) {
7487         for (size_t i = 0; i < ctype_num; i++) {
7488             JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
7489         }
7490         for (size_t i = 0; i < sigalgs_num; i++) {
7491             JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
7492         }
7493     }
7494 
7495     jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
7496     if (keyTypes == nullptr) {
7497         JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
7498         return 0;
7499     }
7500     env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
7501                             reinterpret_cast<const jbyte*>(ctype));
7502 
7503     jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
7504     if (signatureAlgs == nullptr) {
7505         JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
7506         return 0;
7507     }
7508     {
7509         ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
7510         for (size_t i = 0; i < sigalgs_num; i++) {
7511             sigAlgsRW[i] = sigalgs[i];
7512         }
7513     }
7514 
7515     JNI_TRACE(
7516             "ssl=%p clientCertificateRequested calling clientCertificateRequested "
7517             "keyTypes=%p signatureAlgs=%p issuers=%p",
7518             ssl, keyTypes, signatureAlgs, issuers.get());
7519     env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
7520 
7521     if (env->ExceptionCheck()) {
7522         JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
7523         return 0;
7524     }
7525 
7526     JNI_TRACE("ssl=%p cert_cb => 1", ssl);
7527     return 1;
7528 }
7529 
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)7530 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
7531     SSL* ssl = client_hello->ssl;
7532     JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
7533 
7534     AppData* appData = toAppData(ssl);
7535     JNIEnv* env = appData->env;
7536     if (env == nullptr) {
7537         CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
7538         JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
7539         return ssl_select_cert_error;
7540     }
7541     if (env->ExceptionCheck()) {
7542         JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
7543         return ssl_select_cert_error;
7544     }
7545 
7546     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7547     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
7548 
7549     JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
7550     env->CallVoidMethod(sslHandshakeCallbacks, methodID);
7551 
7552     if (env->ExceptionCheck()) {
7553         JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
7554         return ssl_select_cert_error;
7555     }
7556     JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
7557     return ssl_select_cert_success;
7558 }
7559 
7560 /**
7561  * Pre-Shared Key (PSK) client callback.
7562  */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)7563 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
7564                                         unsigned int max_identity_len, unsigned char* psk,
7565                                         unsigned int max_psk_len) {
7566     JNI_TRACE("ssl=%p psk_client_callback", ssl);
7567 
7568     AppData* appData = toAppData(ssl);
7569     JNIEnv* env = appData->env;
7570     if (env == nullptr) {
7571         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
7572         JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
7573         return 0;
7574     }
7575     if (env->ExceptionCheck()) {
7576         JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
7577         return 0;
7578     }
7579 
7580     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7581     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
7582     JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
7583     ScopedLocalRef<jstring> identityHintJava(env,
7584                                              (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
7585     ScopedLocalRef<jbyteArray> identityJava(
7586             env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
7587     if (identityJava.get() == nullptr) {
7588         JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
7589         return 0;
7590     }
7591     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7592     if (keyJava.get() == nullptr) {
7593         JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
7594         return 0;
7595     }
7596     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7597                                      identityJava.get(), keyJava.get());
7598     if (env->ExceptionCheck()) {
7599         JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
7600         return 0;
7601     }
7602     if (keyLen <= 0) {
7603         JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
7604         return 0;
7605     } else if ((unsigned int)keyLen > max_psk_len) {
7606         JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
7607         return 0;
7608     }
7609     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7610     if (keyJavaRo.get() == nullptr) {
7611         JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7612         return 0;
7613     }
7614     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7615 
7616     ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7617     if (identityJavaRo.get() == nullptr) {
7618         JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7619         return 0;
7620     }
7621     memcpy(identity, identityJavaRo.get(), max_identity_len);
7622 
7623     JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7624     return static_cast<unsigned int>(keyLen);
7625 }
7626 
7627 /**
7628  * Pre-Shared Key (PSK) server callback.
7629  */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)7630 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
7631                                         unsigned int max_psk_len) {
7632     JNI_TRACE("ssl=%p psk_server_callback", ssl);
7633 
7634     AppData* appData = toAppData(ssl);
7635     JNIEnv* env = appData->env;
7636     if (env == nullptr) {
7637         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
7638         JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7639         return 0;
7640     }
7641     if (env->ExceptionCheck()) {
7642         JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7643         return 0;
7644     }
7645 
7646     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7647     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
7648     JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7649     const char* identityHint = SSL_get_psk_identity_hint(ssl);
7650     ScopedLocalRef<jstring> identityHintJava(
7651             env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
7652     ScopedLocalRef<jstring> identityJava(
7653             env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
7654     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7655     if (keyJava.get() == nullptr) {
7656         JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7657         return 0;
7658     }
7659     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7660                                      identityJava.get(), keyJava.get());
7661     if (env->ExceptionCheck()) {
7662         JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7663         return 0;
7664     }
7665     if (keyLen <= 0) {
7666         JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7667         return 0;
7668     } else if ((unsigned int)keyLen > max_psk_len) {
7669         JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7670         return 0;
7671     }
7672     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7673     if (keyJavaRo.get() == nullptr) {
7674         JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7675         return 0;
7676     }
7677     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7678 
7679     JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7680     return static_cast<unsigned int>(keyLen);
7681 }
7682 
new_session_callback(SSL * ssl,SSL_SESSION * session)7683 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
7684     JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
7685 
7686     AppData* appData = toAppData(ssl);
7687     JNIEnv* env = appData->env;
7688     if (env == nullptr) {
7689         CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
7690         JNI_TRACE("ssl=%p new_session_callback env error", ssl);
7691         return 0;
7692     }
7693     if (env->ExceptionCheck()) {
7694         JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
7695         return 0;
7696     }
7697 
7698     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7699     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
7700     JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
7701     env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
7702     if (env->ExceptionCheck()) {
7703         JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
7704         env->ExceptionClear();
7705     }
7706     JNI_TRACE("ssl=%p new_session_callback completed", ssl);
7707 
7708     // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
7709     // the reference count.
7710     return 0;
7711 }
7712 
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)7713 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
7714                                                       int* out_copy) {
7715     JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
7716 
7717     // Always set to out_copy to zero. The Java callback will be responsible for incrementing
7718     // the reference count (and any required synchronization).
7719     *out_copy = 0;
7720 
7721     AppData* appData = toAppData(ssl);
7722     JNIEnv* env = appData->env;
7723     if (env == nullptr) {
7724         CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7725         JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7726         return 0;
7727     }
7728     if (env->ExceptionCheck()) {
7729         JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7730         return 0;
7731     }
7732 
7733     // Copy the ID to a byte[].
7734     jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7735     if (id_array == nullptr) {
7736         JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7737         return 0;
7738     }
7739     env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7740                             reinterpret_cast<const jbyte*>(id));
7741 
7742     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7743     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7744     JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7745     jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7746     if (env->ExceptionCheck()) {
7747         JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7748         env->ExceptionClear();
7749     }
7750     SSL_SESSION* ssl_session_ptr =
7751             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7752     JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7753     return ssl_session_ptr;
7754 }
7755 
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7756 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7757     CHECK_ERROR_QUEUE_ON_RETURN;
7758     int ret = 0;
7759     ret = EVP_has_aes_hardware();
7760     JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7761     return ret;
7762 }
7763 
debug_print_session_key(const SSL * ssl,const char * line)7764 static void debug_print_session_key(const SSL* ssl, const char* line) {
7765     JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7766 }
7767 
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7768 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7769     static constexpr size_t kDataWidth = 16;
7770 
7771     struct timeval tv;
7772     if (gettimeofday(&tv, NULL)) {
7773         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7774                       "debug_print_packet_data: could not get time of day");
7775         return;
7776     }
7777 
7778     // Packet preamble for text2pcap
7779     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7780                   static_cast<long>(tv.tv_sec),
7781                   static_cast<long>(tv.tv_usec));  // NOLINT(runtime/int)
7782 
7783     char out[kDataWidth * 3 + 1];
7784     for (size_t i = 0; i < len; i += kDataWidth) {
7785         size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7786 
7787         for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7788             int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7789             if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7790                 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7791                               "debug_print_packet_data failed to output %d", ret);
7792                 return;
7793             }
7794         }
7795 
7796         // Print out packet data in format understood by text2pcap
7797         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7798     }
7799 
7800     // Conclude the packet data
7801     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7802 }
7803 
7804 /*
7805  * public static native int SSL_CTX_new();
7806  */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7807 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7808     CHECK_ERROR_QUEUE_ON_RETURN;
7809     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7810     if (sslCtx.get() == nullptr) {
7811         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7812         return 0;
7813     }
7814     SSL_CTX_set_options(
7815             sslCtx.get(),
7816             SSL_OP_ALL
7817                     // We also disable session tickets for better compatibility b/2682876
7818                     | SSL_OP_NO_TICKET
7819                     // We also disable compression for better compatibility b/2710492 b/2710497
7820                     | SSL_OP_NO_COMPRESSION
7821                     // Generate a fresh ECDH keypair for each key exchange.
7822                     | SSL_OP_SINGLE_ECDH_USE);
7823     SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7824     SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7825 
7826     uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7827     /*
7828      * Turn on "partial write" mode. This means that SSL_write() will
7829      * behave like Posix write() and possibly return after only
7830      * writing a partial buffer. Note: The alternative, perhaps
7831      * surprisingly, is not that SSL_write() always does full writes
7832      * but that it will force you to retry write calls having
7833      * preserved the full state of the original call. (This is icky
7834      * and undesirable.)
7835      */
7836     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7837 
7838     // Reuse empty buffers within the SSL_CTX to save memory
7839     mode |= SSL_MODE_RELEASE_BUFFERS;
7840 
7841     // Enable False Start.
7842     mode |= SSL_MODE_ENABLE_FALSE_START;
7843 
7844     // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7845     // between
7846     // calls to wrap(...).
7847     // See https://github.com/netty/netty-tcnative/issues/100
7848     mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7849 
7850     SSL_CTX_set_mode(sslCtx.get(), mode);
7851 
7852     SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7853     SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7854     SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7855     if (conscrypt::trace::kWithJniTraceKeys) {
7856         SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7857     }
7858 
7859     // By default BoringSSL will cache in server mode, but we want to get
7860     // notified of new sessions being created in client mode. We set
7861     // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7862     // ignore it in server mode in favor of the internal cache.
7863     SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7864     SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7865     SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7866 
7867     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7868     return (jlong)sslCtx.release();
7869 }
7870 
7871 /**
7872  * public static native void SSL_CTX_free(long ssl_ctx)
7873  */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7874 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7875                                       CONSCRYPT_UNUSED jobject holder) {
7876     CHECK_ERROR_QUEUE_ON_RETURN;
7877     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7878     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7879     if (ssl_ctx == nullptr) {
7880         return;
7881     }
7882     SSL_CTX_free(ssl_ctx);
7883 }
7884 
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7885 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7886                                                         CONSCRYPT_UNUSED jobject holder,
7887                                                         jbyteArray sid_ctx) {
7888     CHECK_ERROR_QUEUE_ON_RETURN;
7889     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7890     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7891               sid_ctx);
7892     if (ssl_ctx == nullptr) {
7893         return;
7894     }
7895 
7896     ScopedByteArrayRO buf(env, sid_ctx);
7897     if (buf.get() == nullptr) {
7898         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7899                   ssl_ctx);
7900         return;
7901     }
7902 
7903     unsigned int length = static_cast<unsigned int>(buf.size());
7904     if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7905         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7906                                            "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7907         JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7908         return;
7909     }
7910     const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7911     int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7912     if (result == 0) {
7913         conscrypt::jniutil::throwExceptionFromBoringSSLError(
7914                 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7915         return;
7916     }
7917     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7918 }
7919 
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7920 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7921                                               CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7922     CHECK_ERROR_QUEUE_ON_RETURN;
7923     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7924     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7925     if (ssl_ctx == nullptr) {
7926         return 0L;
7927     }
7928 
7929     return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7930 }
7931 
7932 /**
7933  * public static native int SSL_new(long ssl_ctx) throws SSLException;
7934  */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7935 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7936                                   CONSCRYPT_UNUSED jobject holder) {
7937     CHECK_ERROR_QUEUE_ON_RETURN;
7938     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7939     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7940     if (ssl_ctx == nullptr) {
7941         return 0;
7942     }
7943     bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7944     if (ssl.get() == nullptr) {
7945         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7946                                                            "Unable to create SSL structure");
7947         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7948         return 0;
7949     }
7950 
7951     /*
7952      * Create our special application data.
7953      */
7954     AppData* appData = AppData::create();
7955     if (appData == nullptr) {
7956         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7957         ERR_clear_error();
7958         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7959         return 0;
7960     }
7961     SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7962 
7963     SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7964 
7965     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7966     return (jlong)ssl.release();
7967 }
7968 
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7969 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7970                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
7971     CHECK_ERROR_QUEUE_ON_RETURN;
7972     SSL* ssl = to_SSL(env, ssl_address, true);
7973     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7974     if (ssl == nullptr) {
7975         return;
7976     }
7977 
7978     // NOLINTNEXTLINE(runtime/int)
7979     long ret = SSL_enable_tls_channel_id(ssl);
7980     if (ret != 1L) {
7981         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7982         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7983                                                            "Error enabling Channel ID");
7984         JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7985         return;
7986     }
7987 }
7988 
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7989 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7990                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
7991     CHECK_ERROR_QUEUE_ON_RETURN;
7992     SSL* ssl = to_SSL(env, ssl_address, true);
7993     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7994     if (ssl == nullptr) {
7995         return nullptr;
7996     }
7997 
7998     // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7999     // as a constant anywhere.
8000     jbyteArray javaBytes = env->NewByteArray(64);
8001     ScopedByteArrayRW bytes(env, javaBytes);
8002     if (bytes.get() == nullptr) {
8003         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
8004         return nullptr;
8005     }
8006 
8007     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
8008     // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
8009     // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
8010     // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
8011     size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
8012     if (ret == 0) {
8013         // Channel ID either not set or did not verify
8014         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
8015         return nullptr;
8016     } else if (ret != 64) {
8017         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
8018         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8019                                                            "Error getting Channel ID");
8020         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
8021         return nullptr;
8022     }
8023 
8024     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
8025     return javaBytes;
8026 }
8027 
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)8028 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
8029                                                  CONSCRYPT_UNUSED jobject ssl_holder,
8030                                                  jobject pkeyRef) {
8031     CHECK_ERROR_QUEUE_ON_RETURN;
8032     SSL* ssl = to_SSL(env, ssl_address, true);
8033     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
8034     if (ssl == nullptr) {
8035         return;
8036     }
8037 
8038     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
8039     if (pkey == nullptr) {
8040         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
8041         return;
8042     }
8043 
8044     // NOLINTNEXTLINE(runtime/int)
8045     long ret = SSL_set1_tls_channel_id(ssl, pkey);
8046 
8047     if (ret != 1L) {
8048         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
8049         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8050                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
8051         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
8052         return;
8053     }
8054 
8055     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
8056 }
8057 
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)8058 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
8059                                                     CONSCRYPT_UNUSED jobject ssl_holder,
8060                                                     jobjectArray encodedCertificatesJava,
8061                                                     jobject pkeyRef) {
8062     CHECK_ERROR_QUEUE_ON_RETURN;
8063     SSL* ssl = to_SSL(env, ssl_address, true);
8064     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
8065               encodedCertificatesJava, pkeyRef);
8066     if (ssl == nullptr) {
8067         return;
8068     }
8069     if (encodedCertificatesJava == nullptr) {
8070         conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
8071         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
8072         return;
8073     }
8074     size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
8075     if (numCerts == 0) {
8076         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8077                                            "certificates.length == 0");
8078         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
8079         return;
8080     }
8081     if (pkeyRef == nullptr) {
8082         conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
8083         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
8084         return;
8085     }
8086 
8087     // Get the private key.
8088     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
8089     if (pkey == nullptr) {
8090         conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
8091         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
8092         return;
8093     }
8094 
8095     // Copy the certificates.
8096     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
8097     std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
8098     for (size_t i = 0; i < numCerts; ++i) {
8099         ScopedLocalRef<jbyteArray> certArray(
8100                 env, reinterpret_cast<jbyteArray>(
8101                              env->GetObjectArrayElement(encodedCertificatesJava, i)));
8102         certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
8103         if (!certBufferRefs[i]) {
8104             return;
8105         }
8106         certBuffers[i] = certBufferRefs[i].get();
8107     }
8108 
8109     if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
8110         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8111                                                            "Error configuring certificate");
8112         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
8113         return;
8114     }
8115     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
8116 }
8117 
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)8118 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
8119                                                 CONSCRYPT_UNUSED jobject ssl_holder,
8120                                                 jobjectArray principals) {
8121     CHECK_ERROR_QUEUE_ON_RETURN;
8122     SSL* ssl = to_SSL(env, ssl_address, true);
8123     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
8124     if (ssl == nullptr) {
8125         return;
8126     }
8127 
8128     if (principals == nullptr) {
8129         conscrypt::jniutil::throwNullPointerException(env, "principals == null");
8130         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
8131         return;
8132     }
8133 
8134     int length = env->GetArrayLength(principals);
8135     if (length == 0) {
8136         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8137                                            "principals.length == 0");
8138         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
8139         return;
8140     }
8141 
8142     bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
8143     if (principalsStack.get() == nullptr) {
8144         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
8145         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
8146         return;
8147     }
8148     for (int i = 0; i < length; i++) {
8149         ScopedLocalRef<jbyteArray> principal(
8150                 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
8151         bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
8152         if (!buf) {
8153             return;
8154         }
8155         if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
8156             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
8157             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
8158             return;
8159         }
8160         OWNERSHIP_TRANSFERRED(buf);
8161     }
8162 
8163     SSL_set0_client_CAs(ssl, principalsStack.release());
8164     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
8165 }
8166 
8167 /**
8168  * public static native long SSL_set_mode(long ssl, long mode);
8169  */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)8170 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
8171                                        CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
8172     CHECK_ERROR_QUEUE_ON_RETURN;
8173     SSL* ssl = to_SSL(env, ssl_address, true);
8174     // NOLINTNEXTLINE(runtime/int)
8175     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
8176     if (ssl == nullptr) {
8177         return 0;
8178     }
8179     jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
8180     // NOLINTNEXTLINE(runtime/int)
8181     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
8182     return result;
8183 }
8184 
8185 /**
8186  * public static native long SSL_set_options(long ssl, long options);
8187  */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8188 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
8189                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8190     CHECK_ERROR_QUEUE_ON_RETURN;
8191     SSL* ssl = to_SSL(env, ssl_address, true);
8192     // NOLINTNEXTLINE(runtime/int)
8193     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
8194     if (ssl == nullptr) {
8195         return 0;
8196     }
8197     jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
8198     // NOLINTNEXTLINE(runtime/int)
8199     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
8200     return result;
8201 }
8202 
8203 /**
8204  * public static native long SSL_clear_options(long ssl, long options);
8205  */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8206 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
8207                                             CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8208     CHECK_ERROR_QUEUE_ON_RETURN;
8209     SSL* ssl = to_SSL(env, ssl_address, true);
8210     // NOLINTNEXTLINE(runtime/int)
8211     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
8212     if (ssl == nullptr) {
8213         return 0;
8214     }
8215     jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
8216     // NOLINTNEXTLINE(runtime/int)
8217     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
8218     return result;
8219 }
8220 
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)8221 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
8222                                                    CONSCRYPT_UNUSED jobject ssl_holder,
8223                                                    jint min_version, jint max_version) {
8224     CHECK_ERROR_QUEUE_ON_RETURN;
8225     SSL* ssl = to_SSL(env, ssl_address, true);
8226     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
8227               max_version);
8228     if (ssl == nullptr) {
8229         return 0;
8230     }
8231     int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
8232     int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
8233     // Return failure if either call failed.
8234     int result = 1;
8235     if (!min_result || !max_result) {
8236         result = 0;
8237         // The only possible error is an invalid version, so we don't need the details.
8238         ERR_clear_error();
8239     }
8240     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
8241               min_result, max_result, result);
8242     return result;
8243 }
8244 
8245 /**
8246  * public static native void SSL_enable_signed_cert_timestamps(long ssl);
8247  */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8248 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
8249                                                            CONSCRYPT_UNUSED jobject ssl_holder) {
8250     CHECK_ERROR_QUEUE_ON_RETURN;
8251     SSL* ssl = to_SSL(env, ssl_address, true);
8252     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
8253     if (ssl == nullptr) {
8254         return;
8255     }
8256 
8257     SSL_enable_signed_cert_timestamps(ssl);
8258 }
8259 
8260 /**
8261  * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
8262  */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8263 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
8264         JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
8265     CHECK_ERROR_QUEUE_ON_RETURN;
8266     SSL* ssl = to_SSL(env, ssl_address, true);
8267     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
8268     if (ssl == nullptr) {
8269         return nullptr;
8270     }
8271 
8272     const uint8_t* data;
8273     size_t data_len;
8274     SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
8275 
8276     if (data_len == 0) {
8277         JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
8278         return nullptr;
8279     }
8280 
8281     jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
8282     if (result != nullptr) {
8283         env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
8284     }
8285     return result;
8286 }
8287 
8288 /*
8289  * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
8290  */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)8291 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
8292                                                             CONSCRYPT_UNUSED jobject ssl_holder,
8293                                                             jbyteArray list) {
8294     CHECK_ERROR_QUEUE_ON_RETURN;
8295     SSL* ssl = to_SSL(env, ssl_address, true);
8296     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
8297     if (ssl == nullptr) {
8298         return;
8299     }
8300 
8301     ScopedByteArrayRO listBytes(env, list);
8302     if (listBytes.get() == nullptr) {
8303         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
8304         return;
8305     }
8306 
8307     if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
8308                                             listBytes.size())) {
8309         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
8310     } else {
8311         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
8312     }
8313 }
8314 
8315 /*
8316  * public static native void SSL_enable_ocsp_stapling(long ssl);
8317  */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8318 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
8319                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
8320     CHECK_ERROR_QUEUE_ON_RETURN;
8321     SSL* ssl = to_SSL(env, ssl_address, true);
8322     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
8323     if (ssl == nullptr) {
8324         return;
8325     }
8326 
8327     SSL_enable_ocsp_stapling(ssl);
8328 }
8329 
8330 /*
8331  * public static native byte[] SSL_get_ocsp_response(long ssl);
8332  */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8333 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8334                                                      CONSCRYPT_UNUSED jobject ssl_holder) {
8335     CHECK_ERROR_QUEUE_ON_RETURN;
8336     SSL* ssl = to_SSL(env, ssl_address, true);
8337     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
8338     if (ssl == nullptr) {
8339         return nullptr;
8340     }
8341 
8342     const uint8_t* data;
8343     size_t data_len;
8344     SSL_get0_ocsp_response(ssl, &data, &data_len);
8345 
8346     if (data_len == 0) {
8347         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
8348         return nullptr;
8349     }
8350 
8351     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8352     if (byteArray.get() == nullptr) {
8353         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
8354         return nullptr;
8355     }
8356 
8357     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8358     JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
8359               data_len);
8360 
8361     return byteArray.release();
8362 }
8363 
8364 /*
8365  * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
8366  */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)8367 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8368                                                CONSCRYPT_UNUSED jobject ssl_holder,
8369                                                jbyteArray response) {
8370     CHECK_ERROR_QUEUE_ON_RETURN;
8371     SSL* ssl = to_SSL(env, ssl_address, true);
8372     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
8373     if (ssl == nullptr) {
8374         return;
8375     }
8376 
8377     ScopedByteArrayRO responseBytes(env, response);
8378     if (responseBytes.get() == nullptr) {
8379         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
8380         return;
8381     }
8382 
8383     if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
8384                                responseBytes.size())) {
8385         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
8386     } else {
8387         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
8388     }
8389 }
8390 
8391 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
8392 // to customize the length of their verify_data (with a default of 12 bytes).  We accept
8393 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
8394 // tests and update this value if necessary.
8395 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
8396 
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8397 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
8398                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
8399     CHECK_ERROR_QUEUE_ON_RETURN;
8400     SSL* ssl = to_SSL(env, ssl_address, true);
8401     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
8402     if (ssl == nullptr) {
8403         return nullptr;
8404     }
8405 
8406     uint8_t data[MAX_TLS_UNIQUE_LENGTH];
8407     size_t data_len;
8408     int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
8409 
8410     if (!ret || data_len == 0) {
8411         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
8412         return nullptr;
8413     }
8414 
8415     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8416     if (byteArray.get() == nullptr) {
8417         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
8418         return nullptr;
8419     }
8420 
8421     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8422     JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
8423               data_len);
8424 
8425     return byteArray.release();
8426 }
8427 
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)8428 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
8429                                                           CONSCRYPT_UNUSED jobject ssl_holder,
8430                                                           jbyteArray label, jbyteArray context,
8431                                                           jint num_bytes) {
8432     CHECK_ERROR_QUEUE_ON_RETURN;
8433     SSL* ssl = to_SSL(env, ssl_address, true);
8434     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
8435     if (ssl == nullptr) {
8436         return nullptr;
8437     }
8438     ScopedByteArrayRO labelBytes(env, label);
8439     if (labelBytes.get() == nullptr) {
8440         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
8441         return nullptr;
8442     }
8443     std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
8444     int ret;
8445     if (context == nullptr) {
8446         ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
8447                         reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
8448                         nullptr, 0, 0);
8449     } else {
8450         ScopedByteArrayRO contextBytes(env, context);
8451         if (contextBytes.get() == nullptr) {
8452             JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
8453                       ssl);
8454             return nullptr;
8455         }
8456         ret = SSL_export_keying_material(
8457                 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
8458                 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
8459                 contextBytes.size(), 1);
8460     }
8461     if (!ret) {
8462         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
8463                 conscrypt::jniutil::throwSSLExceptionStr);
8464         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
8465         return nullptr;
8466     }
8467     jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
8468     if (result == nullptr) {
8469         conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
8470         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
8471         return nullptr;
8472     }
8473     const jbyte* src = reinterpret_cast<jbyte*>(out.get());
8474     env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
8475     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
8476     return result;
8477 }
8478 
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)8479 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
8480                                                    CONSCRYPT_UNUSED jobject ssl_holder,
8481                                                    jstring identityHintJava) {
8482     CHECK_ERROR_QUEUE_ON_RETURN;
8483     SSL* ssl = to_SSL(env, ssl_address, true);
8484     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
8485               identityHintJava);
8486     if (ssl == nullptr) {
8487         return;
8488     }
8489 
8490     int ret;
8491     if (identityHintJava == nullptr) {
8492         ret = SSL_use_psk_identity_hint(ssl, nullptr);
8493     } else {
8494         ScopedUtfChars identityHint(env, identityHintJava);
8495         if (identityHint.c_str() == nullptr) {
8496             conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
8497             return;
8498         }
8499         ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
8500     }
8501 
8502     if (ret != 1) {
8503         int sslErrorCode = SSL_get_error(ssl, ret);
8504         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8505                                                            "Failed to set PSK identity hint");
8506     }
8507 }
8508 
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8509 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8510                                                              CONSCRYPT_UNUSED jobject ssl_holder,
8511                                                              jboolean enabled) {
8512     CHECK_ERROR_QUEUE_ON_RETURN;
8513     SSL* ssl = to_SSL(env, ssl_address, true);
8514     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
8515     if (ssl == nullptr) {
8516         return;
8517     }
8518 
8519     SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
8520 }
8521 
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8522 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8523                                                              CONSCRYPT_UNUSED jobject ssl_holder,
8524                                                              jboolean enabled) {
8525     CHECK_ERROR_QUEUE_ON_RETURN;
8526     SSL* ssl = to_SSL(env, ssl_address, true);
8527     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
8528     if (ssl == nullptr) {
8529         return;
8530     }
8531 
8532     SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
8533 }
8534 
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8535 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
8536                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8537     CHECK_ERROR_QUEUE_ON_RETURN;
8538     SSL* ssl = to_SSL(env, ssl_address, true);
8539     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
8540     if (ssl == nullptr) {
8541         return nullptr;
8542     }
8543 
8544     STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
8545     size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
8546     ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
8547     ScopedLongArrayRW ciphers(env, ciphersArray.get());
8548     for (size_t i = 0; i < count; i++) {
8549         ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
8550     }
8551 
8552     JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
8553     return ciphersArray.release();
8554 }
8555 
8556 /**
8557  * Sets the ciphers suites that are enabled in the SSL
8558  */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)8559 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
8560                                               CONSCRYPT_UNUSED jobject ssl_holder,
8561                                               jobjectArray cipherSuites) {
8562     CHECK_ERROR_QUEUE_ON_RETURN;
8563     SSL* ssl = to_SSL(env, ssl_address, true);
8564     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
8565     if (ssl == nullptr) {
8566         return;
8567     }
8568     if (cipherSuites == nullptr) {
8569         conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
8570         return;
8571     }
8572 
8573     int length = env->GetArrayLength(cipherSuites);
8574 
8575     /*
8576      * Special case for empty cipher list. This is considered an error by the
8577      * SSL_set_cipher_list API, but Java allows this silly configuration.
8578      * However, the SSL cipher list is still set even when SSL_set_cipher_list
8579      * returns 0 in this case. Just to make sure, we check the resulting cipher
8580      * list to make sure it's zero length.
8581      */
8582     if (length == 0) {
8583         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
8584         SSL_set_cipher_list(ssl, "");
8585         ERR_clear_error();
8586         if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
8587             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
8588             conscrypt::jniutil::throwRuntimeException(
8589                     env, "SSL_set_cipher_list did not update ciphers!");
8590             ERR_clear_error();
8591         }
8592         return;
8593     }
8594 
8595     static const char noSSLv2[] = "!SSLv2";
8596     size_t cipherStringLen = strlen(noSSLv2);
8597 
8598     for (int i = 0; i < length; i++) {
8599         ScopedLocalRef<jstring> cipherSuite(
8600                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8601         ScopedUtfChars c(env, cipherSuite.get());
8602         if (c.c_str() == nullptr) {
8603             return;
8604         }
8605 
8606         if (cipherStringLen + 1 < cipherStringLen) {
8607             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8608                                                "Overflow in cipher suite strings");
8609             return;
8610         }
8611         cipherStringLen += 1; /* For the separating colon */
8612 
8613         if (cipherStringLen + c.size() < cipherStringLen) {
8614             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8615                                                "Overflow in cipher suite strings");
8616             return;
8617         }
8618         cipherStringLen += c.size();
8619     }
8620 
8621     if (cipherStringLen + 1 < cipherStringLen) {
8622         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8623                                            "Overflow in cipher suite strings");
8624         return;
8625     }
8626     cipherStringLen += 1; /* For final NUL. */
8627 
8628     std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
8629     if (cipherString.get() == nullptr) {
8630         conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
8631         return;
8632     }
8633     memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
8634     size_t j = strlen(noSSLv2);
8635 
8636     for (int i = 0; i < length; i++) {
8637         ScopedLocalRef<jstring> cipherSuite(
8638                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8639         ScopedUtfChars c(env, cipherSuite.get());
8640 
8641         cipherString[j++] = ':';
8642         memcpy(&cipherString[j], c.c_str(), c.size());
8643         j += c.size();
8644     }
8645 
8646     cipherString[j++] = 0;
8647     if (j != cipherStringLen) {
8648         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8649                                            "Internal error");
8650         return;
8651     }
8652 
8653     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
8654     if (!SSL_set_cipher_list(ssl, cipherString.get())) {
8655         ERR_clear_error();
8656         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8657                                            "Illegal cipher suite strings.");
8658         return;
8659     }
8660 }
8661 
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8662 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
8663                                               CONSCRYPT_UNUSED jobject ssl_holder) {
8664     CHECK_ERROR_QUEUE_ON_RETURN;
8665     SSL* ssl = to_SSL(env, ssl_address, true);
8666     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
8667     if (ssl == nullptr) {
8668         return;
8669     }
8670     SSL_set_accept_state(ssl);
8671 }
8672 
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8673 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
8674                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8675     CHECK_ERROR_QUEUE_ON_RETURN;
8676     SSL* ssl = to_SSL(env, ssl_address, true);
8677     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
8678     if (ssl == nullptr) {
8679         return;
8680     }
8681     SSL_set_connect_state(ssl);
8682 }
8683 
8684 /**
8685  * Sets certificate expectations, especially for server to request client auth
8686  */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)8687 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
8688                                         CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
8689     CHECK_ERROR_QUEUE_ON_RETURN;
8690     SSL* ssl = to_SSL(env, ssl_address, true);
8691     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
8692     if (ssl == nullptr) {
8693         return;
8694     }
8695     SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
8696 }
8697 
8698 /**
8699  * Sets the ciphers suites that are enabled in the SSL
8700  */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)8701 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
8702                                          CONSCRYPT_UNUSED jobject ssl_holder,
8703                                          jlong ssl_session_address) {
8704     CHECK_ERROR_QUEUE_ON_RETURN;
8705     SSL* ssl = to_SSL(env, ssl_address, true);
8706     if (ssl == nullptr) {
8707         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
8708         return;
8709     }
8710 
8711     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
8712     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
8713     if (ssl_session == nullptr) {
8714         return;
8715     }
8716 
8717     int ret = SSL_set_session(ssl, ssl_session);
8718     if (ret != 1) {
8719         /*
8720          * Translate the error, and throw if it turns out to be a real
8721          * problem.
8722          */
8723         int sslErrorCode = SSL_get_error(ssl, ret);
8724         if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8725             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8726                                                                "SSL session set");
8727         }
8728     }
8729     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8730               ret);
8731 }
8732 
8733 /**
8734  * Sets the ciphers suites that are enabled in the SSL
8735  */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8736 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8737                                                           CONSCRYPT_UNUSED jobject ssl_holder,
8738                                                           jboolean creation_enabled) {
8739     CHECK_ERROR_QUEUE_ON_RETURN;
8740     SSL* ssl = to_SSL(env, ssl_address, true);
8741     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8742               creation_enabled);
8743     if (ssl == nullptr) {
8744         return;
8745     }
8746 
8747     if (creation_enabled) {
8748         SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8749     } else {
8750         SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8751     }
8752 }
8753 
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8754 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8755                                                 CONSCRYPT_UNUSED jobject ssl_holder) {
8756     CHECK_ERROR_QUEUE_ON_RETURN;
8757     SSL* ssl = to_SSL(env, ssl_address, true);
8758     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8759     if (ssl == nullptr) {
8760         return JNI_FALSE;
8761     }
8762 
8763     int reused = SSL_session_reused(ssl);
8764     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8765     return static_cast<jboolean>(reused);
8766 }
8767 
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8768 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8769                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
8770     CHECK_ERROR_QUEUE_ON_RETURN;
8771     SSL* ssl = to_SSL(env, ssl_address, true);
8772     JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8773     if (ssl == nullptr) {
8774         return;
8775     }
8776 
8777     SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8778 }
8779 
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8780 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8781                                                   CONSCRYPT_UNUSED jobject ssl_holder,
8782                                                   jstring hostname) {
8783     CHECK_ERROR_QUEUE_ON_RETURN;
8784     SSL* ssl = to_SSL(env, ssl_address, true);
8785     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8786     if (ssl == nullptr) {
8787         return;
8788     }
8789 
8790     ScopedUtfChars hostnameChars(env, hostname);
8791     if (hostnameChars.c_str() == nullptr) {
8792         return;
8793     }
8794     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8795               hostnameChars.c_str());
8796 
8797     int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8798     if (ret != 1) {
8799         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8800                                                            "Error setting host name");
8801         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8802         return;
8803     }
8804     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8805 }
8806 
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8807 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8808                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8809     CHECK_ERROR_QUEUE_ON_RETURN;
8810     SSL* ssl = to_SSL(env, ssl_address, true);
8811     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8812     if (ssl == nullptr) {
8813         return nullptr;
8814     }
8815     const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8816     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8817     return env->NewStringUTF(servername);
8818 }
8819 
8820 /**
8821  * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8822  * which should take precedence.
8823  */
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)8824 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8825                                      const unsigned char* primary,
8826                                      const unsigned int primaryLength,
8827                                      const unsigned char* secondary,
8828                                      const unsigned int secondaryLength) {
8829     JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8830 
8831     int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8832                                        secondaryLength);
8833     switch (status) {
8834         case OPENSSL_NPN_NEGOTIATED:
8835             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8836             return SSL_TLSEXT_ERR_OK;
8837             break;
8838         case OPENSSL_NPN_UNSUPPORTED:
8839             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8840             break;
8841         case OPENSSL_NPN_NO_OVERLAP:
8842             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8843             break;
8844     }
8845     return SSL_TLSEXT_ERR_NOACK;
8846 }
8847 
8848 /**
8849  * Calls out to an application-provided selector to choose the ALPN protocol.
8850  */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8851 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8852                                      unsigned char** out,
8853                                      unsigned char* outLen, const unsigned char* in,
8854                                      const unsigned int inLen) {
8855     // Copy the input array.
8856     ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8857     if (protocols.get() == nullptr) {
8858         JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8859         return SSL_TLSEXT_ERR_NOACK;
8860     }
8861     env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8862                             reinterpret_cast<const jbyte*>(in));
8863 
8864     // Invoke the selection method.
8865     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8866     jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8867 
8868     if (offset < 0) {
8869         JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8870         return SSL_TLSEXT_ERR_NOACK;
8871     }
8872 
8873     // Point the output to the selected protocol.
8874     *outLen = *(in + offset);
8875     *out = const_cast<unsigned char*>(in + offset + 1);
8876 
8877     return SSL_TLSEXT_ERR_OK;
8878 }
8879 
8880 /**
8881  * Callback for the server to select an ALPN protocol.
8882  */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8883 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8884                                 const unsigned char* in, unsigned int inLen, void*) {
8885     JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8886 
8887     AppData* appData = toAppData(ssl);
8888     if (appData == nullptr) {
8889         JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8890         return SSL_TLSEXT_ERR_NOACK;
8891     }
8892     JNIEnv* env = appData->env;
8893     if (env == nullptr) {
8894         CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8895         JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8896         return SSL_TLSEXT_ERR_NOACK;
8897     }
8898 
8899     if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8900                           !appData->hasApplicationProtocolSelector)) {
8901         if (out != nullptr && outLen != nullptr) {
8902             *out = nullptr;
8903             *outLen = 0;
8904         }
8905         JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8906         return SSL_TLSEXT_ERR_NOACK;
8907     }
8908 
8909     if (appData->hasApplicationProtocolSelector) {
8910         return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8911                                          const_cast<unsigned char**>(out), outLen, in, inLen);
8912     }
8913 
8914     return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8915                               reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8916                               static_cast<unsigned int>(appData->applicationProtocolsLength),
8917                               in, inLen);
8918 }
8919 
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8920 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8921                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
8922     CHECK_ERROR_QUEUE_ON_RETURN;
8923     SSL* ssl = to_SSL(env, ssl_address, true);
8924     JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8925     if (ssl == nullptr) {
8926         return nullptr;
8927     }
8928     const jbyte* protocol;
8929     unsigned int protocolLength;
8930     SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8931                            &protocolLength);
8932     if (protocolLength == 0) {
8933         return nullptr;
8934     }
8935     jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8936     if (result != nullptr) {
8937         env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8938     }
8939     return result;
8940 }
8941 
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8942 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8943                                                  CONSCRYPT_UNUSED jobject ssl_holder,
8944                                                  jboolean client_mode, jbyteArray protocols) {
8945     CHECK_ERROR_QUEUE_ON_RETURN;
8946     SSL* ssl = to_SSL(env, ssl_address, true);
8947     if (ssl == nullptr) {
8948         return;
8949     }
8950     AppData* appData = toAppData(ssl);
8951     if (appData == nullptr) {
8952         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8953         JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8954         return;
8955     }
8956 
8957     if (protocols != nullptr) {
8958         if (client_mode) {
8959             ScopedByteArrayRO protosBytes(env, protocols);
8960             if (protosBytes.get() == nullptr) {
8961                 JNI_TRACE(
8962                         "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8963                         "protosBytes == null",
8964                         ssl, protocols);
8965                 return;
8966             }
8967 
8968             const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8969             int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8970             if (ret != 0) {
8971                 conscrypt::jniutil::throwSSLExceptionStr(env,
8972                                                          "Unable to set ALPN protocols for client");
8973                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8974                 return;
8975             }
8976         } else {
8977             // Server mode - configure the ALPN protocol selection callback.
8978             if (!appData->setApplicationProtocols(env, protocols)) {
8979                 conscrypt::jniutil::throwSSLExceptionStr(env,
8980                                                          "Unable to set ALPN protocols for server");
8981                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8982                 return;
8983             }
8984             SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8985         }
8986     }
8987 }
8988 
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8989 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8990                                                            CONSCRYPT_UNUSED jobject ssl_holder,
8991                                                            jboolean hasSelector) {
8992     CHECK_ERROR_QUEUE_ON_RETURN;
8993     SSL* ssl = to_SSL(env, ssl_address, true);
8994     JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8995               hasSelector);
8996     if (ssl == nullptr) {
8997         return;
8998     }
8999     AppData* appData = toAppData(ssl);
9000     if (appData == nullptr) {
9001         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9002         JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
9003         return;
9004     }
9005 
9006     appData->hasApplicationProtocolSelector = hasSelector;
9007     if (hasSelector) {
9008         SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
9009     }
9010 }
9011 
9012 /**
9013  * Perform SSL handshake
9014  */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)9015 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9016                                           CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9017                                           jobject shc, jint timeout_millis) {
9018     CHECK_ERROR_QUEUE_ON_RETURN;
9019     SSL* ssl = to_SSL(env, ssl_address, true);
9020     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
9021               shc, timeout_millis);
9022     if (ssl == nullptr) {
9023         return;
9024     }
9025     if (fdObject == nullptr) {
9026         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9027         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
9028         return;
9029     }
9030     if (shc == nullptr) {
9031         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9032         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
9033                   ssl);
9034         return;
9035     }
9036 
9037     NetFd fd(env, fdObject);
9038     if (fd.isClosed()) {
9039         // SocketException thrown by NetFd.isClosed
9040         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
9041         return;
9042     }
9043 
9044     int ret = SSL_set_fd(ssl, fd.get());
9045     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
9046 
9047     if (ret != 1) {
9048         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9049                                                            "Error setting the file descriptor");
9050         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
9051         return;
9052     }
9053 
9054     /*
9055      * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
9056      * forever and we can use select() to find out if the socket is ready.
9057      */
9058     if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
9059         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
9060         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
9061         return;
9062     }
9063 
9064     AppData* appData = toAppData(ssl);
9065     if (appData == nullptr) {
9066         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9067         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
9068         return;
9069     }
9070 
9071     ret = 0;
9072     SslError sslError;
9073     while (appData->aliveAndKicking) {
9074         errno = 0;
9075 
9076         if (!appData->setCallbackState(env, shc, fdObject)) {
9077             // SocketException thrown by NetFd.isClosed
9078             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
9079             return;
9080         }
9081         ret = SSL_do_handshake(ssl);
9082         appData->clearCallbackState();
9083         // cert_verify_callback threw exception
9084         if (env->ExceptionCheck()) {
9085             ERR_clear_error();
9086             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
9087             return;
9088         }
9089         // success case
9090         if (ret == 1) {
9091             break;
9092         }
9093         // retry case
9094         if (errno == EINTR) {
9095             continue;
9096         }
9097         // error case
9098         sslError.reset(ssl, ret);
9099         JNI_TRACE(
9100                 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
9101                 "timeout_millis=%d",
9102                 ssl, ret, errno, sslError.get(), timeout_millis);
9103 
9104         /*
9105          * If SSL_do_handshake doesn't succeed due to the socket being
9106          * either unreadable or unwritable, we use sslSelect to
9107          * wait for it to become ready. If that doesn't happen
9108          * before the specified timeout or an error occurs, we
9109          * cancel the handshake. Otherwise we try the SSL_connect
9110          * again.
9111          */
9112         if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
9113             appData->waitingThreads++;
9114             int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
9115 
9116             if (selectResult == THROWN_EXCEPTION) {
9117                 // SocketException thrown by NetFd.isClosed
9118                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
9119                 return;
9120             }
9121             if (selectResult == -1) {
9122                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9123                         env, ssl, SSL_ERROR_SYSCALL, "handshake error",
9124                         conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9125                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
9126                           ssl);
9127                 return;
9128             }
9129             if (selectResult == 0) {
9130                 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
9131                 ERR_clear_error();
9132                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
9133                           ssl);
9134                 return;
9135             }
9136         } else {
9137             // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
9138             break;
9139         }
9140     }
9141 
9142     // clean error. See SSL_do_handshake(3SSL) man page.
9143     if (ret == 0) {
9144         /*
9145          * The other side closed the socket before the handshake could be
9146          * completed, but everything is within the bounds of the TLS protocol.
9147          * We still might want to find out the real reason of the failure.
9148          */
9149         if (sslError.get() == SSL_ERROR_NONE ||
9150             (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
9151             (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
9152             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9153         } else {
9154             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9155                     env, ssl, sslError.release(), "SSL handshake terminated",
9156                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9157         }
9158         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9159         return;
9160     }
9161 
9162     // unclean error. See SSL_do_handshake(3SSL) man page.
9163     if (ret < 0) {
9164         /*
9165          * Translate the error and throw exception. We are sure it is an error
9166          * at this point.
9167          */
9168         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9169                 env, ssl, sslError.release(), "SSL handshake aborted",
9170                 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9171         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9172         return;
9173     }
9174     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
9175 }
9176 
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9177 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
9178                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
9179     CHECK_ERROR_QUEUE_ON_RETURN;
9180     SSL* ssl = to_SSL(env, ssl_address, true);
9181     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
9182     if (ssl == nullptr) {
9183         return nullptr;
9184     }
9185     const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
9186     if (cipher == nullptr) {
9187         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
9188         return nullptr;
9189     }
9190     const char* name = SSL_CIPHER_standard_name(cipher);
9191     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
9192     return env->NewStringUTF(name);
9193 }
9194 
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9195 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
9196                                             CONSCRYPT_UNUSED jobject ssl_holder) {
9197     CHECK_ERROR_QUEUE_ON_RETURN;
9198     SSL* ssl = to_SSL(env, ssl_address, true);
9199     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
9200     if (ssl == nullptr) {
9201         return nullptr;
9202     }
9203     const char* protocol = SSL_get_version(ssl);
9204     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
9205     return env->NewStringUTF(protocol);
9206 }
9207 
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9208 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
9209                                                             CONSCRYPT_UNUSED jobject ssl_holder) {
9210     CHECK_ERROR_QUEUE_ON_RETURN;
9211     SSL* ssl = to_SSL(env, ssl_address, true);
9212     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
9213     if (ssl == nullptr) {
9214         return nullptr;
9215     }
9216 
9217     const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
9218     if (chain == nullptr) {
9219         return nullptr;
9220     }
9221 
9222     ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
9223     if (array.get() == nullptr) {
9224         return nullptr;
9225     }
9226 
9227     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
9228     return array.release();
9229 }
9230 
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)9231 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
9232                    SslError* sslError, int read_timeout_millis) {
9233     JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
9234 
9235     if (len == 0) {
9236         // Don't bother doing anything in this case.
9237         return 0;
9238     }
9239 
9240     BIO* rbio = SSL_get_rbio(ssl);
9241     BIO* wbio = SSL_get_wbio(ssl);
9242 
9243     AppData* appData = toAppData(ssl);
9244     JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
9245     if (appData == nullptr) {
9246         return THROW_SSLEXCEPTION;
9247     }
9248 
9249     while (appData->aliveAndKicking) {
9250         errno = 0;
9251 
9252         std::unique_lock<std::mutex> appDataLock(appData->mutex);
9253 
9254         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9255             !SSL_renegotiate_pending(ssl)) {
9256             JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
9257                       SSL_state_string_long(ssl));
9258             return THROW_SSLEXCEPTION;
9259         }
9260 
9261         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9262 
9263         if (!appData->setCallbackState(env, shc, fdObject)) {
9264             return THROWN_EXCEPTION;
9265         }
9266         int result = SSL_read(ssl, buf, len);
9267         appData->clearCallbackState();
9268         // callbacks can happen if server requests renegotiation
9269         if (env->ExceptionCheck()) {
9270             JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
9271             return THROWN_EXCEPTION;
9272         }
9273         sslError->reset(ssl, result);
9274 
9275         JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
9276         if (conscrypt::trace::kWithJniTraceData) {
9277             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9278                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9279                 size_t n = result - i;
9280                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9281                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
9282                 }
9283                 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9284             }
9285         }
9286 
9287         // If we have been successful in moving data around, check whether it
9288         // might make sense to wake up other blocked threads, so they can give
9289         // it a try, too.
9290         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9291             appData->waitingThreads > 0) {
9292             sslNotify(appData);
9293         }
9294 
9295         // If we are blocked by the underlying socket, tell the world that
9296         // there will be one more waiting thread now.
9297         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9298             appData->waitingThreads++;
9299         }
9300 
9301         appDataLock.unlock();
9302 
9303         switch (sslError->get()) {
9304             // Successfully read at least one byte.
9305             case SSL_ERROR_NONE: {
9306                 return result;
9307             }
9308 
9309             // Read zero bytes. End of stream reached.
9310             case SSL_ERROR_ZERO_RETURN: {
9311                 return -1;
9312             }
9313 
9314             // Need to wait for availability of underlying layer, then retry.
9315             case SSL_ERROR_WANT_READ:
9316             case SSL_ERROR_WANT_WRITE: {
9317                 int selectResult =
9318                         sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
9319                 if (selectResult == THROWN_EXCEPTION) {
9320                     return THROWN_EXCEPTION;
9321                 }
9322                 if (selectResult == -1) {
9323                     return THROW_SSLEXCEPTION;
9324                 }
9325                 if (selectResult == 0) {
9326                     return THROW_SOCKETTIMEOUTEXCEPTION;
9327                 }
9328 
9329                 break;
9330             }
9331 
9332             // A problem occurred during a system call, but this is not
9333             // necessarily an error.
9334             case SSL_ERROR_SYSCALL: {
9335                 // Connection closed without proper shutdown. Tell caller we
9336                 // have reached end-of-stream.
9337                 if (result == 0) {
9338                     return -1;
9339                 }
9340 
9341                 // System call has been interrupted. Simply retry.
9342                 if (errno == EINTR) {
9343                     break;
9344                 }
9345 
9346                 // Note that for all other system call errors we fall through
9347                 // to the default case, which results in an Exception.
9348                 FALLTHROUGH_INTENDED;
9349             }
9350 
9351             // Everything else is basically an error.
9352             default: { return THROW_SSLEXCEPTION; }
9353         }
9354     }
9355 
9356     return -1;
9357 }
9358 
9359 /**
9360  * OpenSSL read function (2): read into buffer at offset n chunks.
9361  * Returns the number of bytes read (success) or value <= 0 (failure).
9362  */
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)9363 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
9364                                   CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9365                                   jobject shc, jbyteArray b, jint offset, jint len,
9366                                   jint read_timeout_millis) {
9367     CHECK_ERROR_QUEUE_ON_RETURN;
9368     SSL* ssl = to_SSL(env, ssl_address, true);
9369     JNI_TRACE(
9370             "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
9371             "read_timeout_millis=%d",
9372             ssl, fdObject, shc, b, offset, len, read_timeout_millis);
9373     if (ssl == nullptr) {
9374         return 0;
9375     }
9376     if (fdObject == nullptr) {
9377         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9378         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
9379         return 0;
9380     }
9381     if (shc == nullptr) {
9382         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9383         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
9384         return 0;
9385     }
9386     if (b == nullptr) {
9387         conscrypt::jniutil::throwNullPointerException(env, "b == null");
9388         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
9389         return 0;
9390     }
9391 
9392     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9393     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9394         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9395         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
9396         return 0;
9397     }
9398 
9399     SslError sslError;
9400     int ret;
9401     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9402         if (len <= 1024) {
9403             // Allocate small buffers on the stack for performance.
9404             jbyte buf[1024];
9405             ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
9406                           read_timeout_millis);
9407             if (ret > 0) {
9408                 // Don't bother applying changes if issues were encountered.
9409                 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
9410             }
9411         } else {
9412             // Allocate larger buffers on the heap.
9413             // ARRAY_CHUNK_INVALID above ensures that len >= 0.
9414             jint remaining = len;
9415             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9416             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9417             // TODO(flooey): Use new(std::nothrow).
9418             if (buf.get() == nullptr) {
9419                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9420                 return 0;
9421             }
9422             // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
9423             // by the number of internal calls to sslRead() below.
9424             ret = 0;
9425             while (remaining > 0) {
9426                 jint temp_ret;
9427                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9428                 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
9429                                    chunk_size, &sslError, read_timeout_millis);
9430                 if (temp_ret < 0) {
9431                     if (ret > 0) {
9432                         // We've already read some bytes; attempt to preserve them if this is an
9433                         // "expected" error.
9434                         if (temp_ret == -1) {
9435                             // EOF
9436                             break;
9437                         } else if (temp_ret == THROWN_EXCEPTION) {
9438                             // FD closed. Subsequent calls to sslRead should reproduce the
9439                             // exception.
9440                             env->ExceptionClear();
9441                             break;
9442                         }
9443                     }
9444                     // An error was encountered. Handle below.
9445                     ret = temp_ret;
9446                     break;
9447                 }
9448                 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
9449                 if (env->ExceptionCheck()) {
9450                     // Error committing changes to JVM.
9451                     return -1;
9452                 }
9453                 // Accumulate bytes read.
9454                 ret += temp_ret;
9455                 offset += temp_ret;
9456                 remaining -= temp_ret;
9457                 if (temp_ret < chunk_size) {
9458                     // sslRead isn't able to fulfill our request right now.
9459                     break;
9460                 }
9461             }
9462         }
9463     } else {
9464         ScopedByteArrayRW bytes(env, b);
9465         if (bytes.get() == nullptr) {
9466             JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
9467             return 0;
9468         }
9469 
9470         ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
9471                       &sslError, read_timeout_millis);
9472     }
9473 
9474     int result;
9475     switch (ret) {
9476         case THROW_SSLEXCEPTION:
9477             // See sslRead() regarding improper failure to handle normal cases.
9478             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9479                                                                "Read error");
9480             result = -1;
9481             break;
9482         case THROW_SOCKETTIMEOUTEXCEPTION:
9483             conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
9484             result = -1;
9485             break;
9486         case THROWN_EXCEPTION:
9487             // SocketException thrown by NetFd.isClosed
9488             // or RuntimeException thrown by callback
9489             result = -1;
9490             break;
9491         default:
9492             result = ret;
9493             break;
9494     }
9495 
9496     JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
9497     return result;
9498 }
9499 
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)9500 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
9501                     SslError* sslError, int write_timeout_millis) {
9502     JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
9503               write_timeout_millis);
9504 
9505     if (len == 0) {
9506         // Don't bother doing anything in this case.
9507         return 0;
9508     }
9509 
9510     BIO* rbio = SSL_get_rbio(ssl);
9511     BIO* wbio = SSL_get_wbio(ssl);
9512 
9513     AppData* appData = toAppData(ssl);
9514     JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
9515     if (appData == nullptr) {
9516         return THROW_SSLEXCEPTION;
9517     }
9518 
9519     int count = len;
9520 
9521     while (appData->aliveAndKicking && len > 0) {
9522         errno = 0;
9523 
9524         std::unique_lock<std::mutex> appDataLock(appData->mutex);
9525 
9526         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9527             !SSL_renegotiate_pending(ssl)) {
9528             JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
9529                       SSL_state_string_long(ssl));
9530             return THROW_SSLEXCEPTION;
9531         }
9532 
9533         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9534 
9535         if (!appData->setCallbackState(env, shc, fdObject)) {
9536             return THROWN_EXCEPTION;
9537         }
9538         JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
9539         int result = SSL_write(ssl, buf, len);
9540         appData->clearCallbackState();
9541         // callbacks can happen if server requests renegotiation
9542         if (env->ExceptionCheck()) {
9543             JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
9544             return THROWN_EXCEPTION;
9545         }
9546         sslError->reset(ssl, result);
9547 
9548         JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
9549         if (conscrypt::trace::kWithJniTraceData) {
9550             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9551                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9552                 size_t n = result - i;
9553                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9554                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
9555                 }
9556                 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9557             }
9558         }
9559 
9560         // If we have been successful in moving data around, check whether it
9561         // might make sense to wake up other blocked threads, so they can give
9562         // it a try, too.
9563         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9564             appData->waitingThreads > 0) {
9565             sslNotify(appData);
9566         }
9567 
9568         // If we are blocked by the underlying socket, tell the world that
9569         // there will be one more waiting thread now.
9570         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9571             appData->waitingThreads++;
9572         }
9573 
9574         appDataLock.unlock();
9575 
9576         switch (sslError->get()) {
9577             // Successfully wrote at least one byte.
9578             case SSL_ERROR_NONE: {
9579                 buf += result;
9580                 len -= result;
9581                 break;
9582             }
9583 
9584             // Wrote zero bytes. End of stream reached.
9585             case SSL_ERROR_ZERO_RETURN: {
9586                 return -1;
9587             }
9588 
9589             // Need to wait for availability of underlying layer, then retry.
9590             // The concept of a write timeout doesn't really make sense, and
9591             // it's also not standard Java behavior, so we wait forever here.
9592             case SSL_ERROR_WANT_READ:
9593             case SSL_ERROR_WANT_WRITE: {
9594                 int selectResult =
9595                         sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
9596                 if (selectResult == THROWN_EXCEPTION) {
9597                     return THROWN_EXCEPTION;
9598                 }
9599                 if (selectResult == -1) {
9600                     return THROW_SSLEXCEPTION;
9601                 }
9602                 if (selectResult == 0) {
9603                     return THROW_SOCKETTIMEOUTEXCEPTION;
9604                 }
9605 
9606                 break;
9607             }
9608 
9609             // A problem occurred during a system call, but this is not
9610             // necessarily an error.
9611             case SSL_ERROR_SYSCALL: {
9612                 // Connection closed without proper shutdown. Tell caller we
9613                 // have reached end-of-stream.
9614                 if (result == 0) {
9615                     return -1;
9616                 }
9617 
9618                 // System call has been interrupted. Simply retry.
9619                 if (errno == EINTR) {
9620                     break;
9621                 }
9622 
9623                 // Note that for all other system call errors we fall through
9624                 // to the default case, which results in an Exception.
9625                 FALLTHROUGH_INTENDED;
9626             }
9627 
9628             // Everything else is basically an error.
9629             default: { return THROW_SSLEXCEPTION; }
9630         }
9631     }
9632     JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9633 
9634     return count;
9635 }
9636 
9637 /**
9638  * OpenSSL write function (2): write into buffer at offset n chunks.
9639  */
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)9640 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
9641                                    CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9642                                    jobject shc, jbyteArray b, jint offset, jint len,
9643                                    jint write_timeout_millis) {
9644     CHECK_ERROR_QUEUE_ON_RETURN;
9645     SSL* ssl = to_SSL(env, ssl_address, true);
9646     JNI_TRACE(
9647             "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
9648             "write_timeout_millis=%d",
9649             ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9650     if (ssl == nullptr) {
9651         return;
9652     }
9653     if (fdObject == nullptr) {
9654         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9655         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9656         return;
9657     }
9658     if (shc == nullptr) {
9659         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9660         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9661         return;
9662     }
9663     if (b == nullptr) {
9664         conscrypt::jniutil::throwNullPointerException(env, "b == null");
9665         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
9666         return;
9667     }
9668 
9669     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9670     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9671         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9672         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
9673         return;
9674     }
9675 
9676     SslError sslError;
9677     int ret;
9678     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9679         if (len <= 1024) {
9680             jbyte buf[1024];
9681             env->GetByteArrayRegion(b, offset, len, buf);
9682             ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
9683                            &sslError, write_timeout_millis);
9684         } else {
9685             // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
9686             jint remaining = len;
9687             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9688             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9689             if (buf.get() == nullptr) {
9690                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9691                 return;
9692             }
9693             while (remaining > 0) {
9694                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9695                 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
9696                 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
9697                                chunk_size, &sslError, write_timeout_millis);
9698                 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
9699                     ret == THROWN_EXCEPTION) {
9700                     // Encountered an error. Terminate early and handle below.
9701                     break;
9702                 }
9703                 offset += ret;
9704                 remaining -= ret;
9705             }
9706         }
9707     } else {
9708         ScopedByteArrayRO bytes(env, b);
9709         if (bytes.get() == nullptr) {
9710             JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9711             return;
9712         }
9713         ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9714                        len, &sslError, write_timeout_millis);
9715     }
9716 
9717     switch (ret) {
9718         case THROW_SSLEXCEPTION:
9719             // See sslWrite() regarding improper failure to handle normal cases.
9720             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9721                                                                "Write error");
9722             break;
9723         case THROW_SOCKETTIMEOUTEXCEPTION:
9724             conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9725             break;
9726         case THROWN_EXCEPTION:
9727             // SocketException thrown by NetFd.isClosed
9728             break;
9729         default:
9730             break;
9731     }
9732 }
9733 
9734 /**
9735  * Interrupt any pending I/O before closing the socket.
9736  */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9737 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9738                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9739     CHECK_ERROR_QUEUE_ON_RETURN;
9740     SSL* ssl = to_SSL(env, ssl_address, false);
9741     JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9742     if (ssl == nullptr) {
9743         return;
9744     }
9745 
9746     /*
9747      * Mark the connection as quasi-dead, then send something to the emergency
9748      * file descriptor, so any blocking select() calls are woken up.
9749      */
9750     AppData* appData = toAppData(ssl);
9751     if (appData != nullptr) {
9752         appData->aliveAndKicking = false;
9753 
9754         // At most two threads can be waiting.
9755         sslNotify(appData);
9756         sslNotify(appData);
9757     }
9758 }
9759 
9760 /**
9761  * OpenSSL close SSL socket function.
9762  */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9763 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9764                                       CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9765                                       jobject shc) {
9766     CHECK_ERROR_QUEUE_ON_RETURN;
9767     SSL* ssl = to_SSL(env, ssl_address, false);
9768     JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9769     if (ssl == nullptr) {
9770         return;
9771     }
9772     if (fdObject == nullptr) {
9773         return;
9774     }
9775     if (shc == nullptr) {
9776         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9777         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9778         return;
9779     }
9780 
9781     AppData* appData = toAppData(ssl);
9782     if (appData != nullptr) {
9783         if (!appData->setCallbackState(env, shc, fdObject)) {
9784             // SocketException thrown by NetFd.isClosed
9785             ERR_clear_error();
9786             return;
9787         }
9788 
9789         /*
9790          * Try to make socket blocking again. OpenSSL literature recommends this.
9791          */
9792         int fd = SSL_get_fd(ssl);
9793         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9794 #ifndef _WIN32
9795         if (fd != -1) {
9796             conscrypt::netutil::setBlocking(fd, true);
9797         }
9798 #endif
9799 
9800         int ret = SSL_shutdown(ssl);
9801         appData->clearCallbackState();
9802         // callbacks can happen if server requests renegotiation
9803         if (env->ExceptionCheck()) {
9804             JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9805             return;
9806         }
9807         switch (ret) {
9808             case 0:
9809                 /*
9810                  * Shutdown was not successful (yet), but there also
9811                  * is no error. Since we can't know whether the remote
9812                  * server is actually still there, and we don't want to
9813                  * get stuck forever in a second SSL_shutdown() call, we
9814                  * simply return. This is not security a problem as long
9815                  * as we close the underlying socket, which we actually
9816                  * do, because that's where we are just coming from.
9817                  */
9818                 break;
9819             case 1:
9820                 /*
9821                  * Shutdown was successful. We can safely return. Hooray!
9822                  */
9823                 break;
9824             default:
9825                 /*
9826                  * Everything else is a real error condition. We should
9827                  * let the Java layer know about this by throwing an
9828                  * exception.
9829                  */
9830                 int sslError = SSL_get_error(ssl, ret);
9831                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9832                                                                    "SSL shutdown failed");
9833                 break;
9834         }
9835     }
9836 
9837     ERR_clear_error();
9838 }
9839 
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9840 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9841                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9842     CHECK_ERROR_QUEUE_ON_RETURN;
9843     const SSL* ssl = to_SSL(env, ssl_address, true);
9844     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9845     if (ssl == nullptr) {
9846         return 0;
9847     }
9848 
9849     int status = SSL_get_shutdown(ssl);
9850     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9851     return static_cast<jint>(status);
9852 }
9853 
9854 /**
9855  * public static native void SSL_free(long ssl);
9856  */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9857 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9858                                   CONSCRYPT_UNUSED jobject ssl_holder) {
9859     CHECK_ERROR_QUEUE_ON_RETURN;
9860     SSL* ssl = to_SSL(env, ssl_address, true);
9861     JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9862     if (ssl == nullptr) {
9863         return;
9864     }
9865 
9866     AppData* appData = toAppData(ssl);
9867     SSL_set_app_data(ssl, nullptr);
9868     delete appData;
9869     SSL_free(ssl);
9870 }
9871 
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9872 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9873     unsigned int length;
9874     const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9875     JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9876     if (id && length > 0) {
9877         jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9878         if (result != nullptr) {
9879             const jbyte* src = reinterpret_cast<const jbyte*>(id);
9880             env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9881         }
9882         return result;
9883     }
9884     return nullptr;
9885 }
9886 
9887 /**
9888  * Gets and returns in a byte array the ID of the actual SSL session.
9889  */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9890 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9891                                                       jlong ssl_session_address) {
9892     CHECK_ERROR_QUEUE_ON_RETURN;
9893     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9894     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9895     if (ssl_session == nullptr) {
9896         return nullptr;
9897     }
9898     jbyteArray result = get_session_id(env, ssl_session);
9899     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9900     return result;
9901 }
9902 
9903 /**
9904  * Gets and returns in a long integer the creation's time of the
9905  * actual SSL session.
9906  */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9907 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9908     CHECK_ERROR_QUEUE_ON_RETURN;
9909     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9910     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9911     if (ssl_session == nullptr) {
9912         return 0;
9913     }
9914     // result must be jlong, not long or *1000 will overflow
9915     jlong result = SSL_SESSION_get_time(ssl_session);
9916     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9917     // NOLINTNEXTLINE(runtime/int)
9918     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9919               (long long)result);  // NOLINT(runtime/int)
9920     return result;
9921 }
9922 
9923 /**
9924  * Gets and returns in a long integer the creation's time of the
9925  * actual SSL session.
9926  */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9927 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9928                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9929     CHECK_ERROR_QUEUE_ON_RETURN;
9930     SSL* ssl = to_SSL(env, ssl_address, true);
9931     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9932     if (ssl == nullptr) {
9933         return 0;
9934     }
9935 
9936     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9937     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9938     if (ssl_session == nullptr) {
9939         // BoringSSL does not protect against a NULL session.
9940         return 0;
9941     }
9942     // result must be jlong, not long or *1000 will overflow
9943     jlong result = SSL_SESSION_get_time(ssl_session);
9944     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9945     // NOLINTNEXTLINE(runtime/int)
9946     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9947     return result;
9948 }
9949 
9950 /**
9951  * Sets the timeout on the SSL session.
9952  */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9953 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9954                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9955     CHECK_ERROR_QUEUE_ON_RETURN;
9956     SSL* ssl = to_SSL(env, ssl_address, true);
9957     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9958     if (ssl == nullptr) {
9959         return 0;
9960     }
9961 
9962     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9963     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9964     if (ssl_session == nullptr) {
9965         // BoringSSL does not protect against a NULL session.
9966         return 0;
9967     }
9968 
9969     // Convert to seconds
9970     static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9971     uint32_t timeout = static_cast<uint32_t>(
9972             std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9973     return SSL_set_timeout(ssl_session, timeout);
9974 }
9975 
9976 /**
9977  * Gets the timeout for the SSL session.
9978  */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9979 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9980                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9981     CHECK_ERROR_QUEUE_ON_RETURN;
9982     SSL* ssl = to_SSL(env, ssl_address, true);
9983     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9984     if (ssl == nullptr) {
9985         return 0;
9986     }
9987 
9988     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9989     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9990     if (ssl_session == nullptr) {
9991         // BoringSSL does not protect against a NULL session.
9992         return 0;
9993     }
9994 
9995     jlong result = SSL_get_timeout(ssl_session);
9996     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9997     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9998               (long long)result)  // NOLINT(runtime/int);
9999     return result;
10000 }
10001 
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)10002 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
10003                                                               jint signatureAlg) {
10004     CHECK_ERROR_QUEUE_ON_RETURN;
10005     return SSL_get_signature_algorithm_key_type(signatureAlg);
10006 }
10007 
10008 /**
10009  * Gets the timeout for the SSL session.
10010  */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)10011 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
10012     CHECK_ERROR_QUEUE_ON_RETURN;
10013     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10014     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
10015     if (ssl_session == nullptr) {
10016         return 0;
10017     }
10018 
10019     return SSL_get_timeout(ssl_session);
10020 }
10021 
10022 /**
10023  * Gets the ID for the SSL session, or null if no session is currently available.
10024  */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10025 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
10026                                               CONSCRYPT_UNUSED jobject ssl_holder) {
10027     CHECK_ERROR_QUEUE_ON_RETURN;
10028     SSL* ssl = to_SSL(env, ssl_address, true);
10029     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
10030     if (ssl == nullptr) {
10031         return nullptr;
10032     }
10033 
10034     SSL_SESSION* ssl_session = SSL_get_session(ssl);
10035     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
10036     if (ssl_session == nullptr) {
10037         return nullptr;
10038     }
10039     jbyteArray result = get_session_id(env, ssl_session);
10040     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
10041     return result;
10042 }
10043 
10044 /**
10045  * Gets and returns in a string the version of the SSL protocol. If it
10046  * returns the string "unknown" it means that no connection is established.
10047  */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)10048 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
10049                                                     jlong ssl_session_address) {
10050     CHECK_ERROR_QUEUE_ON_RETURN;
10051     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10052     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
10053     if (ssl_session == nullptr) {
10054         return nullptr;
10055     }
10056     const char* protocol = SSL_SESSION_get_version(ssl_session);
10057     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
10058     return env->NewStringUTF(protocol);
10059 }
10060 
10061 /**
10062  * Gets and returns in a string the cipher negotiated for the SSL session.
10063  */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)10064 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
10065     CHECK_ERROR_QUEUE_ON_RETURN;
10066     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10067     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
10068     if (ssl_session == nullptr) {
10069         return nullptr;
10070     }
10071     const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
10072     const char* name = SSL_CIPHER_standard_name(cipher);
10073     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
10074     return env->NewStringUTF(name);
10075 }
10076 
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)10077 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
10078                                                               jlong ssl_session_address) {
10079     CHECK_ERROR_QUEUE_ON_RETURN;
10080     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10081     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
10082     if (ssl_session == nullptr) {
10083         return JNI_FALSE;
10084     }
10085     int single_use = SSL_SESSION_should_be_single_use(ssl_session);
10086     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
10087               single_use);
10088     return single_use ? JNI_TRUE : JNI_FALSE;
10089 }
10090 
10091 /**
10092  * Increments the reference count of the session.
10093  */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)10094 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
10095     CHECK_ERROR_QUEUE_ON_RETURN;
10096     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10097     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
10098     if (ssl_session == nullptr) {
10099         return;
10100     }
10101     SSL_SESSION_up_ref(ssl_session);
10102 }
10103 
10104 /**
10105  * Frees the SSL session.
10106  */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)10107 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
10108     CHECK_ERROR_QUEUE_ON_RETURN;
10109     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10110     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
10111     if (ssl_session == nullptr) {
10112         return;
10113     }
10114     SSL_SESSION_free(ssl_session);
10115 }
10116 
10117 /**
10118  * Serializes the native state of the session (ID, cipher, and keys but
10119  * not certificates). Returns a byte[] containing the DER-encoded state.
10120  * See apache mod_ssl.
10121  */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)10122 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
10123     CHECK_ERROR_QUEUE_ON_RETURN;
10124     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10125     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
10126     if (ssl_session == nullptr) {
10127         return nullptr;
10128     }
10129     return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
10130 }
10131 
10132 /**
10133  * Deserialize the session.
10134  */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)10135 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
10136     CHECK_ERROR_QUEUE_ON_RETURN;
10137     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
10138 
10139     ScopedByteArrayRO bytes(env, javaBytes);
10140     if (bytes.get() == nullptr) {
10141         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
10142         return 0;
10143     }
10144     const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
10145     // NOLINTNEXTLINE(runtime/int)
10146     SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
10147 
10148     if (ssl_session == nullptr ||
10149         ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
10150         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
10151                                                              conscrypt::jniutil::throwIOException);
10152         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
10153         return 0L;
10154     }
10155 
10156     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
10157     return reinterpret_cast<uintptr_t>(ssl_session);
10158 }
10159 
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)10160 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
10161     CHECK_ERROR_QUEUE_ON_RETURN;
10162     const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
10163     if (cipher == nullptr) {
10164         return nullptr;
10165     }
10166 
10167     const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
10168     return env->NewStringUTF(kx_name);
10169 }
10170 
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)10171 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
10172     CHECK_ERROR_QUEUE_ON_RETURN;
10173     ScopedUtfChars selector(env, selectorJava);
10174     if (selector.c_str() == nullptr) {
10175         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10176                                            "selector == null");
10177         return nullptr;
10178     }
10179 
10180     JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
10181 
10182     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
10183     bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
10184 
10185     if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
10186         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10187                                            "Unable to set SSL cipher list");
10188         return nullptr;
10189     }
10190     STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
10191 
10192     size_t size = sk_SSL_CIPHER_num(ciphers);
10193     ScopedLocalRef<jobjectArray> cipherNamesArray(
10194             env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
10195                                      nullptr));
10196     if (cipherNamesArray.get() == nullptr) {
10197         return nullptr;
10198     }
10199 
10200     // Return an array of standard and OpenSSL name pairs.
10201     for (size_t i = 0; i < size; i++) {
10202         const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
10203         ScopedLocalRef<jstring> cipherName(env,
10204                                            env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
10205         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
10206                                    cipherName.get());
10207 
10208         ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
10209         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
10210                                    opensslName.get());
10211     }
10212 
10213     JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
10214               2 * size);
10215     return cipherNamesArray.release();
10216 }
10217 
10218 /**
10219  * Compare the given CertID with a certificate and it's issuer.
10220  * True is returned if the CertID matches.
10221  */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)10222 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
10223     // Get the hash algorithm used by this CertID
10224     CBS hash_algorithm, hash;
10225     if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
10226         !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
10227         return false;
10228     }
10229 
10230     // Get the issuer's name hash from the CertID
10231     CBS issuer_name_hash;
10232     if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
10233         return false;
10234     }
10235 
10236     // Get the issuer's key hash from the CertID
10237     CBS issuer_key_hash;
10238     if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
10239         return false;
10240     }
10241 
10242     // Get the serial number from the CertID
10243     CBS serial;
10244     if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
10245         return false;
10246     }
10247 
10248     // Compare the certificate's serial number with the one from the Cert ID
10249     const uint8_t* p = CBS_data(&serial);
10250     bssl::UniquePtr<ASN1_INTEGER> serial_number(
10251             c2i_ASN1_INTEGER(nullptr, &p,
10252                              static_cast<long>(CBS_len(&serial))));  // NOLINT(runtime/int)
10253     const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
10254     if (serial_number.get() == nullptr ||
10255         ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
10256         return false;
10257     }
10258 
10259     // Find the hash algorithm to be used
10260     const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
10261     if (digest == nullptr) {
10262         return false;
10263     }
10264 
10265     // Hash the issuer's name and compare the hash with the one from the Cert ID
10266     uint8_t md[EVP_MAX_MD_SIZE];
10267     const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
10268     if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
10269         !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
10270         return false;
10271     }
10272 
10273     // Same thing with the issuer's key
10274     const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
10275     if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
10276                     static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
10277                     nullptr) ||
10278         !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
10279         return false;
10280     }
10281 
10282     return true;
10283 }
10284 
10285 /**
10286  * Get a SingleResponse whose CertID matches the given certificate and issuer from a
10287  * SEQUENCE OF SingleResponse.
10288  *
10289  * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
10290  * error occured or no response matches the certificate, false is returned and |out_single_response|
10291  * is unchanged.
10292  */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)10293 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
10294                                       CBS* out_single_response) {
10295     // Iterate over all the SingleResponses, until one matches the certificate
10296     while (CBS_len(responses) > 0) {
10297         // Get the next available SingleResponse from the sequence
10298         CBS single_response;
10299         if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
10300             return false;
10301         }
10302 
10303         // Make a copy of the stream so we pass it back to the caller
10304         CBS single_response_original = single_response;
10305 
10306         // Get the SingleResponse's CertID
10307         // If this fails ignore the current response and move to the next one
10308         CBS cert_id;
10309         if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
10310             continue;
10311         }
10312 
10313         // Compare the CertID with the given certificate and issuer
10314         if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
10315             *out_single_response = single_response_original;
10316             return true;
10317         }
10318     }
10319 
10320     return false;
10321 }
10322 
10323 /**
10324  * Get the BasicOCSPResponse from an OCSPResponse.
10325  * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
10326  * returned.
10327  */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)10328 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
10329     CBS tagged_response_bytes, response_bytes, response_type, response;
10330 
10331     // Get the ResponseBytes out of the OCSPResponse
10332     if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
10333         !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
10334                       CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10335         !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
10336         return false;
10337     }
10338 
10339     // Parse the response type and data out of the ResponseBytes
10340     if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
10341         !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
10342         return false;
10343     }
10344 
10345     // Only basic OCSP responses are supported
10346     if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
10347         return false;
10348     }
10349 
10350     // Parse the octet string as a BasicOCSPResponse
10351     return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
10352 }
10353 
10354 /**
10355  * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
10356  * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
10357  * true is returned.
10358  */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)10359 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
10360     // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
10361     CBS response_data;
10362     if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
10363         return false;
10364     }
10365 
10366     // Skip the version, responderID and producedAt fields
10367     if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
10368                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10369         !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
10370         !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
10371         return false;
10372     }
10373 
10374     // Extract the list of SingleResponse.
10375     return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
10376 }
10377 
10378 /**
10379  * Get the SEQUENCE OF Extension from a SingleResponse.
10380  * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
10381  * returned.
10382  */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)10383 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
10384     // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
10385     if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
10386         !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
10387         !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
10388         !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
10389                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
10390         return false;
10391     }
10392 
10393     // Get the list of Extension
10394     return CBS_get_asn1(single_response, extensions,
10395                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
10396 }
10397 
10398 /*
10399     public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
10400                                                           long x509Ref, long issuerX509Ref);
10401 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)10402 static jbyteArray NativeCrypto_get_ocsp_single_extension(
10403         JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
10404         CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
10405     CHECK_ERROR_QUEUE_ON_RETURN;
10406     ScopedByteArrayRO ocspData(env, ocspDataBytes);
10407     if (ocspData.get() == nullptr) {
10408         return nullptr;
10409     }
10410 
10411     CBS cbs;
10412     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
10413 
10414     // Start parsing the OCSPResponse
10415     CBS ocsp_response;
10416     if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
10417         return nullptr;
10418     }
10419 
10420     // Get the BasicOCSPResponse from the OCSP Response
10421     CBS basic_response;
10422     if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
10423         return nullptr;
10424     }
10425 
10426     // Get the list of SingleResponses from the BasicOCSPResponse
10427     CBS responses;
10428     if (!get_ocsp_single_responses(&basic_response, &responses)) {
10429         return nullptr;
10430     }
10431 
10432     // Find the response matching the certificate
10433     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
10434     X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
10435     CBS single_response;
10436     if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
10437         return nullptr;
10438     }
10439 
10440     // Get the extensions from the SingleResponse
10441     CBS extensions;
10442     if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
10443         return nullptr;
10444     }
10445 
10446     const uint8_t* ptr = CBS_data(&extensions);
10447     bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
10448             d2i_X509_EXTENSIONS(nullptr, &ptr,
10449                                 static_cast<long>(CBS_len(&extensions))));  // NOLINT(runtime/int)
10450     if (x509_exts.get() == nullptr) {
10451         return nullptr;
10452     }
10453 
10454     return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
10455             env, x509_exts.get(), oid);
10456 }
10457 
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)10458 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
10459     // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
10460     // no throwing if the buffer is null or not a direct ByteBuffer.
10461     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
10462         return 0;
10463     }
10464     return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
10465 }
10466 
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)10467 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
10468                                        CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
10469     CHECK_ERROR_QUEUE_ON_RETURN;
10470     SSL* ssl = to_SSL(env, ssl_address, true);
10471     if (ssl == nullptr) {
10472         return 0;
10473     }
10474     return SSL_get_error(ssl, ret);
10475 }
10476 
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)10477 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
10478     ERR_clear_error();
10479 }
10480 
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10481 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
10482                                                     CONSCRYPT_UNUSED jobject ssl_holder) {
10483     CHECK_ERROR_QUEUE_ON_RETURN;
10484     SSL* ssl = to_SSL(env, ssl_address, true);
10485     if (ssl == nullptr) {
10486         return 0;
10487     }
10488     return SSL_pending(ssl);
10489 }
10490 
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)10491 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
10492     CHECK_ERROR_QUEUE_ON_RETURN;
10493     BIO* bio = to_BIO(env, bio_address);
10494     if (bio == nullptr) {
10495         return 0;
10496     }
10497     return static_cast<jint>(BIO_ctrl_pending(bio));
10498 }
10499 
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10500 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
10501                                                CONSCRYPT_UNUSED jobject ssl_holder) {
10502     CHECK_ERROR_QUEUE_ON_RETURN;
10503     SSL* ssl = to_SSL(env, ssl_address, true);
10504     if (ssl == nullptr) {
10505         return 0;
10506     }
10507     return (jint)SSL_max_seal_overhead(ssl);
10508 }
10509 
10510 /**
10511  * public static native int SSL_new_BIO(long ssl) throws SSLException;
10512  */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10513 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
10514                                       CONSCRYPT_UNUSED jobject ssl_holder) {
10515     CHECK_ERROR_QUEUE_ON_RETURN;
10516     SSL* ssl = to_SSL(env, ssl_address, true);
10517     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
10518     if (ssl == nullptr) {
10519         return 0;
10520     }
10521 
10522     BIO* internal_bio;
10523     BIO* network_bio;
10524     if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
10525         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
10526                                                            "BIO_new_bio_pair failed");
10527         JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
10528         return 0;
10529     }
10530 
10531     SSL_set_bio(ssl, internal_bio, internal_bio);
10532 
10533     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
10534     return reinterpret_cast<uintptr_t>(network_bio);
10535 }
10536 
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10537 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
10538                                                  CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10539     CHECK_ERROR_QUEUE_ON_RETURN;
10540     SSL* ssl = to_SSL(env, ssl_address, true);
10541     if (ssl == nullptr) {
10542         return 0;
10543     }
10544     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
10545 
10546     if (shc == nullptr) {
10547         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10548         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
10549                   ssl);
10550         return 0;
10551     }
10552 
10553     AppData* appData = toAppData(ssl);
10554     if (appData == nullptr) {
10555         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10556         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
10557         return 0;
10558     }
10559 
10560     errno = 0;
10561 
10562     if (!appData->setCallbackState(env, shc, nullptr)) {
10563         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10564         ERR_clear_error();
10565         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10566         return 0;
10567     }
10568 
10569     int ret = SSL_do_handshake(ssl);
10570     appData->clearCallbackState();
10571     if (env->ExceptionCheck()) {
10572         // cert_verify_callback threw exception
10573         ERR_clear_error();
10574         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10575         return 0;
10576     }
10577 
10578     SslError sslError(ssl, ret);
10579     int code = sslError.get();
10580 
10581     if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
10582         // Non-exceptional case.
10583         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
10584         return code;
10585     }
10586 
10587     // Exceptional case...
10588     if (ret == 0) {
10589         // TODO(nmittler): Can this happen with memory BIOs?
10590         /*
10591          * Clean error. See SSL_do_handshake(3SSL) man page.
10592          * The other side closed the socket before the handshake could be
10593          * completed, but everything is within the bounds of the TLS protocol.
10594          * We still might want to find out the real reason of the failure.
10595          */
10596         if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
10597             (code == SSL_ERROR_ZERO_RETURN)) {
10598             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
10599         } else {
10600             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10601                     env, ssl, sslError.release(), "SSL handshake terminated",
10602                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10603         }
10604         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
10605         return code;
10606     }
10607 
10608     /*
10609      * Unclean error. See SSL_do_handshake(3SSL) man page.
10610      * Translate the error and throw exception. We are sure it is an error
10611      * at this point.
10612      */
10613     conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10614             env, ssl, sslError.release(), "SSL handshake aborted",
10615             conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10616     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
10617     return code;
10618 }
10619 
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10620 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
10621                                              CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10622     CHECK_ERROR_QUEUE_ON_RETURN;
10623     SSL* ssl = to_SSL(env, ssl_address, false);
10624     if (ssl == nullptr) {
10625         return;
10626     }
10627     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
10628 
10629     if (shc == nullptr) {
10630         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10631         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10632         return;
10633     }
10634 
10635     AppData* appData = toAppData(ssl);
10636     if (appData != nullptr) {
10637         if (!appData->setCallbackState(env, shc, nullptr)) {
10638             conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10639             ERR_clear_error();
10640             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10641             return;
10642         }
10643         int ret = SSL_shutdown(ssl);
10644         appData->clearCallbackState();
10645         // callbacks can happen if server requests renegotiation
10646         if (env->ExceptionCheck()) {
10647             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10648             return;
10649         }
10650         switch (ret) {
10651             case 0:
10652                 /*
10653                  * Shutdown was not successful (yet), but there also
10654                  * is no error. Since we can't know whether the remote
10655                  * server is actually still there, and we don't want to
10656                  * get stuck forever in a second SSL_shutdown() call, we
10657                  * simply return. This is not security a problem as long
10658                  * as we close the underlying socket, which we actually
10659                  * do, because that's where we are just coming from.
10660                  */
10661                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
10662                 break;
10663             case 1:
10664                 /*
10665                  * Shutdown was successful. We can safely return. Hooray!
10666                  */
10667                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
10668                 break;
10669             default:
10670                 /*
10671                  * Everything else is a real error condition. We should
10672                  * let the Java layer know about this by throwing an
10673                  * exception.
10674                  */
10675                 int sslError = SSL_get_error(ssl, ret);
10676                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
10677                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
10678                                                                    "SSL shutdown failed");
10679                 break;
10680         }
10681     }
10682 
10683     ERR_clear_error();
10684 }
10685 
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)10686 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
10687                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10688                                                 jint length, jobject shc) {
10689     CHECK_ERROR_QUEUE_ON_RETURN;
10690     SSL* ssl = to_SSL(env, ssl_address, true);
10691     char* destPtr = reinterpret_cast<char*>(address);
10692     if (ssl == nullptr) {
10693         return -1;
10694     }
10695     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
10696               destPtr, length, shc);
10697 
10698     if (shc == nullptr) {
10699         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10700         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
10701                   ssl);
10702         return -1;
10703     }
10704     AppData* appData = toAppData(ssl);
10705     if (appData == nullptr) {
10706         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10707         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
10708         return -1;
10709     }
10710     if (!appData->setCallbackState(env, shc, nullptr)) {
10711         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10712         ERR_clear_error();
10713         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
10714         return -1;
10715     }
10716 
10717     errno = 0;
10718 
10719     int result = SSL_read(ssl, destPtr, length);
10720     appData->clearCallbackState();
10721     if (env->ExceptionCheck()) {
10722         // An exception was thrown by one of the callbacks. Just propagate that exception.
10723         ERR_clear_error();
10724         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10725         return -1;
10726     }
10727 
10728     SslError sslError(ssl, result);
10729     switch (sslError.get()) {
10730         case SSL_ERROR_NONE: {
10731             // Successfully read at least one byte. Just return the result.
10732             break;
10733         }
10734         case SSL_ERROR_ZERO_RETURN: {
10735             // A close_notify was received, this stream is finished.
10736             return -SSL_ERROR_ZERO_RETURN;
10737         }
10738         case SSL_ERROR_WANT_READ:
10739         case SSL_ERROR_WANT_WRITE: {
10740             // Return the negative of these values.
10741             result = -sslError.get();
10742             break;
10743         }
10744         case SSL_ERROR_SYSCALL: {
10745             // A problem occurred during a system call, but this is not
10746             // necessarily an error.
10747             if (result == 0) {
10748                 // TODO(nmittler): Can this happen with memory BIOs?
10749                 // Connection closed without proper shutdown. Tell caller we
10750                 // have reached end-of-stream.
10751                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10752                 break;
10753             }
10754 
10755             if (errno == EINTR) {
10756                 // TODO(nmittler): Can this happen with memory BIOs?
10757                 // System call has been interrupted. Simply retry.
10758                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10759                                                    "Read error");
10760                 break;
10761             }
10762 
10763             // Note that for all other system call errors we fall through
10764             // to the default case, which results in an Exception.
10765             FALLTHROUGH_INTENDED;
10766         }
10767         default: {
10768             // Everything else is basically an error.
10769             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10770                                                                "Read error");
10771             break;
10772         }
10773     }
10774 
10775     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10776               ssl, destPtr, length, shc, result);
10777     return result;
10778 }
10779 
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)10780 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10781                                                     CONSCRYPT_UNUSED jobject ssl_holder,
10782                                                     jlong bioRef, jlong address, jint len,
10783                                                     jobject shc) {
10784     CHECK_ERROR_QUEUE_ON_RETURN;
10785     SSL* ssl = to_SSL(env, ssl_address, true);
10786     if (ssl == nullptr) {
10787         return -1;
10788     }
10789     if (shc == nullptr) {
10790         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10791         JNI_TRACE(
10792                 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10793                 "sslHandshakeCallbacks == null",
10794                 ssl);
10795         return -1;
10796     }
10797     BIO* bio = to_BIO(env, bioRef);
10798     if (bio == nullptr) {
10799         return -1;
10800     }
10801     if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10802         // The network BIO couldn't handle the entire write. Don't write anything, so that we
10803         // only process one packet at a time.
10804         return 0;
10805     }
10806     const char* sourcePtr = reinterpret_cast<const char*>(address);
10807 
10808     AppData* appData = toAppData(ssl);
10809     if (appData == nullptr) {
10810         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10811         ERR_clear_error();
10812         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10813         return -1;
10814     }
10815     if (!appData->setCallbackState(env, shc, nullptr)) {
10816         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10817         ERR_clear_error();
10818         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10819         return -1;
10820     }
10821 
10822     errno = 0;
10823 
10824     int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10825     appData->clearCallbackState();
10826     JNI_TRACE(
10827             "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10828             "ret=%d",
10829             ssl, bio, sourcePtr, len, shc, result);
10830     JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10831                           static_cast<size_t>(result));
10832     return result;
10833 }
10834 
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)10835 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10836                                                    CONSCRYPT_UNUSED jobject ssl_holder,
10837                                                    jlong bioRef, jlong address, jint outputSize,
10838                                                    jobject shc) {
10839     CHECK_ERROR_QUEUE_ON_RETURN;
10840     SSL* ssl = to_SSL(env, ssl_address, true);
10841     if (ssl == nullptr) {
10842         return -1;
10843     }
10844     if (shc == nullptr) {
10845         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10846         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10847                   ssl);
10848         return -1;
10849     }
10850     BIO* bio = to_BIO(env, bioRef);
10851     if (bio == nullptr) {
10852         return -1;
10853     }
10854     char* destPtr = reinterpret_cast<char*>(address);
10855     if (destPtr == nullptr) {
10856         conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10857         return -1;
10858     }
10859 
10860     AppData* appData = toAppData(ssl);
10861     if (appData == nullptr) {
10862         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10863         ERR_clear_error();
10864         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10865         return -1;
10866     }
10867     if (!appData->setCallbackState(env, shc, nullptr)) {
10868         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10869         ERR_clear_error();
10870         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10871         return -1;
10872     }
10873 
10874     errno = 0;
10875 
10876     int result = BIO_read(bio, destPtr, outputSize);
10877     appData->clearCallbackState();
10878     JNI_TRACE(
10879             "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10880             "=> ret=%d",
10881             ssl, bio, destPtr, outputSize, shc, result);
10882     JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10883     return result;
10884 }
10885 
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10886 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10887                                                CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10888     CHECK_ERROR_QUEUE_ON_RETURN;
10889     SSL* ssl = to_SSL(env, ssl_address, true);
10890     if (ssl == nullptr) {
10891         return;
10892     }
10893     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10894     if (shc == nullptr) {
10895         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10896         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10897                   ssl);
10898         return;
10899     }
10900     AppData* appData = toAppData(ssl);
10901     if (appData == nullptr) {
10902         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10903         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10904         return;
10905     }
10906     if (!appData->setCallbackState(env, shc, nullptr)) {
10907         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10908         ERR_clear_error();
10909         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10910         return;
10911     }
10912     char c;
10913     int result = SSL_peek(ssl, &c, 1);
10914     appData->clearCallbackState();
10915     if (env->ExceptionCheck()) {
10916         // An exception was thrown by one of the callbacks. Just propagate that exception.
10917         ERR_clear_error();
10918         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10919         return;
10920     }
10921 
10922     SslError sslError(ssl, result);
10923     switch (sslError.get()) {
10924         case SSL_ERROR_NONE:
10925         case SSL_ERROR_ZERO_RETURN:
10926         case SSL_ERROR_WANT_READ:
10927         case SSL_ERROR_WANT_WRITE: {
10928             // The call succeeded, lacked data, or the SSL is closed.  All is well.
10929             break;
10930         }
10931         case SSL_ERROR_SYSCALL: {
10932             // A problem occurred during a system call, but this is not
10933             // necessarily an error.
10934             if (result == 0) {
10935                 // TODO(nmittler): Can this happen with memory BIOs?
10936                 // Connection closed without proper shutdown. Tell caller we
10937                 // have reached end-of-stream.
10938                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10939                 break;
10940             }
10941 
10942             if (errno == EINTR) {
10943                 // TODO(nmittler): Can this happen with memory BIOs?
10944                 // System call has been interrupted. Simply retry.
10945                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10946                                                    "Read error");
10947                 break;
10948             }
10949 
10950             // Note that for all other system call errors we fall through
10951             // to the default case, which results in an Exception.
10952             FALLTHROUGH_INTENDED;
10953         }
10954         default: {
10955             // Everything else is basically an error.
10956             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10957                                                                "Read error");
10958             break;
10959         }
10960     }
10961 
10962     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10963 }
10964 
10965 /**
10966  * OpenSSL write function (2): write into buffer at offset n chunks.
10967  */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10968 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10969                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10970                                                 jint len, jobject shc) {
10971     CHECK_ERROR_QUEUE_ON_RETURN;
10972     SSL* ssl = to_SSL(env, ssl_address, true);
10973     const char* sourcePtr = reinterpret_cast<const char*>(address);
10974     if (ssl == nullptr) {
10975         return -1;
10976     }
10977     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10978               sourcePtr, len, shc);
10979     if (shc == nullptr) {
10980         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10981         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10982                   ssl);
10983         return -1;
10984     }
10985 
10986     AppData* appData = toAppData(ssl);
10987     if (appData == nullptr) {
10988         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10989         ERR_clear_error();
10990         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10991         return -1;
10992     }
10993     if (!appData->setCallbackState(env, shc, nullptr)) {
10994         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10995         ERR_clear_error();
10996         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10997         return -1;
10998     }
10999 
11000     errno = 0;
11001 
11002     int result = SSL_write(ssl, sourcePtr, len);
11003     appData->clearCallbackState();
11004     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
11005               ssl, sourcePtr, len, shc, result);
11006     return result;
11007 }
11008 
11009 /**
11010  * public static native bool usesBoringSsl_FIPS_mode();
11011  */
NativeCrypto_usesBoringSsl_FIPS_mode()11012 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
11013     return FIPS_mode();
11014 }
11015 
11016 /**
11017  * Scrypt support
11018  */
11019 
NativeCrypto_Scrypt_generate_key(JNIEnv * env,jclass,jbyteArray password,jbyteArray salt,jint n,jint r,jint p,jint key_len)11020 static jbyteArray NativeCrypto_Scrypt_generate_key(JNIEnv* env, jclass, jbyteArray password, jbyteArray salt,
11021                                                    jint n, jint r, jint p, jint key_len) {
11022     CHECK_ERROR_QUEUE_ON_RETURN;
11023     JNI_TRACE("Scrypt_generate_key(%p, %p, %d, %d, %d, %d)", password, salt, n, r, p, key_len);
11024 
11025     if (password == nullptr) {
11026         conscrypt::jniutil::throwNullPointerException(env, "password == null");
11027         JNI_TRACE("Scrypt_generate_key() => password == null");
11028         return nullptr;
11029     }
11030     if (salt == nullptr) {
11031         conscrypt::jniutil::throwNullPointerException(env, "salt == null");
11032         JNI_TRACE("Scrypt_generate_key() => salt == null");
11033         return nullptr;
11034     }
11035 
11036     jbyteArray key_bytes = env->NewByteArray(static_cast<jsize>(key_len));
11037     ScopedByteArrayRW out_key(env, key_bytes);
11038     if (out_key.get() == nullptr) {
11039         conscrypt::jniutil::throwNullPointerException(env, "out_key == null");
11040         JNI_TRACE("Scrypt_generate_key() => out_key == null");
11041         return nullptr;
11042     }
11043 
11044     size_t memory_limit = 1u << 29;
11045     ScopedByteArrayRO password_bytes(env, password);
11046     ScopedByteArrayRO salt_bytes(env, salt);
11047 
11048     int result = EVP_PBE_scrypt(reinterpret_cast<const char*>(password_bytes.get()), password_bytes.size(),
11049                                 reinterpret_cast<const uint8_t*>(salt_bytes.get()), salt_bytes.size(),
11050                                 n, r, p, memory_limit,
11051                                 reinterpret_cast<uint8_t*>(out_key.get()), key_len);
11052 
11053     if (result <= 0) {
11054         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Scrypt_generate_key");
11055         return nullptr;
11056     }
11057     return key_bytes;
11058 }
11059 
11060 /**
11061  * SPAKE2+ support
11062  */
11063 
11064 #define SPAKE2PLUS_PW_VERIFIER_SIZE 32
11065 #define SPAKE2PLUS_REGISTRATION_RECORD_SIZE 65
11066 
NativeCrypto_SSL_CTX_set_spake_credential(JNIEnv * env,jclass,jbyteArray context,jbyteArray pw_array,jbyteArray id_prover_array,jbyteArray id_verifier_array,jboolean is_client,jint handshake_limit,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)11067 static void NativeCrypto_SSL_CTX_set_spake_credential(JNIEnv* env, jclass,
11068                                                       jbyteArray context, jbyteArray pw_array,
11069                                                       jbyteArray id_prover_array,
11070                                                       jbyteArray id_verifier_array,
11071                                                       jboolean is_client,
11072                                                       jint handshake_limit,
11073                                                       jlong ssl_ctx_address,
11074                                                       CONSCRYPT_UNUSED jobject holder) {
11075     CHECK_ERROR_QUEUE_ON_RETURN;
11076 
11077     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
11078 
11079     if (ssl_ctx == nullptr) {
11080         JNI_TRACE("SSL_CTX_set_spake_credential => ssl_ctx == null");
11081         return;
11082     }
11083 
11084     JNI_TRACE("SSL_CTX_set_spake_credential(%p, %p, %p, %p, %d, %d, %p)", context, pw_array,
11085               id_prover_array, id_verifier_array, is_client, handshake_limit,
11086               ssl_ctx);
11087 
11088     if (context == nullptr || pw_array == nullptr || id_prover_array == nullptr ||
11089         id_verifier_array == nullptr) {
11090         conscrypt::jniutil::throwNullPointerException(env, "Input parameters cannot be null");
11091         return;
11092     }
11093 
11094     ScopedByteArrayRO context_bytes(env, context);
11095     if (context_bytes.get() == nullptr) {
11096         JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11097         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for context");
11098         return;
11099     }
11100 
11101     ScopedByteArrayRO pw_bytes(env, pw_array);
11102     if (pw_bytes.get() == nullptr) {
11103         JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11104         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for pw_array");
11105         return;
11106     }
11107 
11108     ScopedByteArrayRO id_prover_bytes(env, id_prover_array);
11109     if (id_prover_bytes.get() == nullptr) {
11110         JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11111         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for id_prover_array");
11112         return;
11113     }
11114 
11115     ScopedByteArrayRO id_verifier_bytes(env, id_verifier_array);
11116     if (id_verifier_bytes.get() == nullptr) {
11117         JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11118         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for id_verifier_array");
11119         return;
11120     }
11121 
11122     uint8_t pw_verifier_w0[SPAKE2PLUS_PW_VERIFIER_SIZE];
11123     uint8_t pw_verifier_w1[SPAKE2PLUS_PW_VERIFIER_SIZE];
11124     uint8_t registration_record[SPAKE2PLUS_REGISTRATION_RECORD_SIZE];
11125     int ret = SSL_spake2plusv1_register(
11126                 /* out_pw_verifier_w0= */ pw_verifier_w0,
11127                 /* out_pw_verifier_w1= */ pw_verifier_w1,
11128                 /* out_registration_record= */ registration_record,
11129                 /* pw= */ reinterpret_cast<const uint8_t*>(pw_bytes.get()),
11130                 /* pw_len= */ pw_bytes.size(),
11131                 /* id_prover= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11132                 /* id_prover_len= */ id_prover_bytes.size(),
11133                 /* id_verifier= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11134                 /* id_verifier_len= */ id_verifier_bytes.size());
11135     if (ret != 1) {
11136         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_spake2plusv1_register failed");
11137         return;
11138     }
11139 
11140     bssl::UniquePtr<SSL_CREDENTIAL> creds;
11141     if (is_client) {
11142         bssl::UniquePtr<SSL_CREDENTIAL> creds_client(SSL_CREDENTIAL_new_spake2plusv1_client(
11143             /* context= */ reinterpret_cast<const uint8_t*>(context_bytes.get()),
11144             /* context_len= */ context_bytes.size(),
11145             /* client_identity= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11146             /* client_identity_len= */ id_prover_bytes.size(),
11147             /* server_identity= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11148             /* server_identity_len= */ id_verifier_bytes.size(),
11149             /* attempts= */ handshake_limit,
11150             /* w0= */ pw_verifier_w0,
11151             /* w0_len= */ sizeof(pw_verifier_w0),
11152             /* w1= */ pw_verifier_w1,
11153             /* w1_len= */ sizeof(pw_verifier_w1)));
11154             creds = std::move(creds_client);
11155     } else {
11156         bssl::UniquePtr<SSL_CREDENTIAL> creds_server(SSL_CREDENTIAL_new_spake2plusv1_server(
11157             /* context= */ reinterpret_cast<const uint8_t*>(context_bytes.get()),
11158             /* context_len= */ context_bytes.size(),
11159             /* client_identity= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11160             /* client_identity_len= */ id_prover_bytes.size(),
11161             /* server_identity= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11162             /* server_identity_len= */ id_verifier_bytes.size(),
11163             /* attempts= */ handshake_limit,
11164             /* w0= */ pw_verifier_w0,
11165             /* w0_len= */ sizeof(pw_verifier_w0),
11166             /* registration_record= */ registration_record,
11167             /* registration_record_len= */ sizeof(registration_record)));
11168             creds = std::move(creds_server);
11169     }
11170     if (creds == nullptr) {
11171         conscrypt::jniutil::throwSSLExceptionStr(
11172                 env, "SSL_CREDENTIAL_new_spake2plusv1 failed");
11173         return;
11174     }
11175     ret = SSL_CTX_add1_credential(ssl_ctx, creds.get());
11176     if (ret != 1) {
11177         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_add1_credential failed");
11178         return;
11179     }
11180     JNI_TRACE("SSL_CTX_set_spake_credential (%p, %p, %p, %p, %d, %d, %p) => %p", context, pw_array,
11181             id_prover_array, id_verifier_array, is_client, handshake_limit, ssl_ctx, creds.get());
11182     return;
11183 }
11184 
11185 // TESTING METHODS BEGIN
11186 
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)11187 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
11188     CHECK_ERROR_QUEUE_ON_RETURN;
11189     BIO* bio = to_BIO(env, bioRef);
11190     JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
11191 
11192     if (bio == nullptr) {
11193         JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
11194         return 0;
11195     }
11196 
11197     if (outputJavaBytes == nullptr) {
11198         conscrypt::jniutil::throwNullPointerException(env, "output == null");
11199         JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
11200         return 0;
11201     }
11202 
11203     jsize outputSize = env->GetArrayLength(outputJavaBytes);
11204 
11205     std::unique_ptr<unsigned char[]> buffer(
11206             new unsigned char[static_cast<unsigned int>(outputSize)]);
11207     if (buffer.get() == nullptr) {
11208         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
11209         return 0;
11210     }
11211 
11212     int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
11213     if (read <= 0) {
11214         conscrypt::jniutil::throwIOException(env, "BIO_read");
11215         JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
11216         return 0;
11217     }
11218 
11219     env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
11220     JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
11221     return read;
11222 }
11223 
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)11224 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
11225                                    jint offset, jint length) {
11226     CHECK_ERROR_QUEUE_ON_RETURN;
11227     BIO* bio = to_BIO(env, bioRef);
11228     JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
11229 
11230     if (bio == nullptr) {
11231         return;
11232     }
11233 
11234     if (inputJavaBytes == nullptr) {
11235         conscrypt::jniutil::throwNullPointerException(env, "input == null");
11236         return;
11237     }
11238 
11239     int inputSize = env->GetArrayLength(inputJavaBytes);
11240     if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
11241         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
11242                                            "inputJavaBytes");
11243         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
11244         return;
11245     }
11246 
11247     std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
11248     if (buffer.get() == nullptr) {
11249         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
11250         return;
11251     }
11252 
11253     env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
11254     if (BIO_write(bio, buffer.get(), length) != length) {
11255         ERR_clear_error();
11256         conscrypt::jniutil::throwIOException(env, "BIO_write");
11257         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
11258         return;
11259     }
11260 
11261     JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
11262 }
11263 
11264 /**
11265  * public static native long SSL_clear_mode(long ssl, long mode);
11266  */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)11267 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
11268                                          CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
11269     CHECK_ERROR_QUEUE_ON_RETURN;
11270     SSL* ssl = to_SSL(env, ssl_address, true);
11271     // NOLINTNEXTLINE(runtime/int)
11272     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
11273     if (ssl == nullptr) {
11274         return 0;
11275     }
11276     jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
11277     // NOLINTNEXTLINE(runtime/int)
11278     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
11279     return result;
11280 }
11281 
11282 /**
11283  * public static native long SSL_get_mode(long ssl);
11284  */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11285 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
11286                                        CONSCRYPT_UNUSED jobject ssl_holder) {
11287     CHECK_ERROR_QUEUE_ON_RETURN;
11288     SSL* ssl = to_SSL(env, ssl_address, true);
11289     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
11290     if (ssl == nullptr) {
11291         return 0;
11292     }
11293     jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
11294     // NOLINTNEXTLINE(runtime/int)
11295     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
11296     return mode;
11297 }
11298 
11299 /**
11300  * public static native long SSL_get_options(long ssl);
11301  */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11302 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
11303                                           CONSCRYPT_UNUSED jobject ssl_holder) {
11304     CHECK_ERROR_QUEUE_ON_RETURN;
11305     SSL* ssl = to_SSL(env, ssl_address, true);
11306     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
11307     if (ssl == nullptr) {
11308         return 0;
11309     }
11310     jlong options = static_cast<jlong>(SSL_get_options(ssl));
11311     // NOLINTNEXTLINE(runtime/int)
11312     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
11313     return options;
11314 }
11315 
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11316 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
11317                                            CONSCRYPT_UNUSED jobject ssl_holder) {
11318     CHECK_ERROR_QUEUE_ON_RETURN;
11319     SSL* ssl = to_SSL(env, ssl_address, true);
11320     if (ssl == nullptr) {
11321         return 0;
11322     }
11323     return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
11324 }
11325 
11326 // TESTING METHODS END
11327 
11328 #define CONSCRYPT_NATIVE_METHOD(functionName, signature)             \
11329     {                                                                \
11330         /* NOLINTNEXTLINE */                                         \
11331         (char*)#functionName, (char*)(signature),                    \
11332                 reinterpret_cast<void*>(NativeCrypto_##functionName) \
11333     }
11334 
11335 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
11336 #define SSL_CALLBACKS \
11337     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
11338 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
11339 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
11340 #define REF_EVP_CIPHER_CTX \
11341     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
11342 #define REF_EVP_HPKE_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_CTX;"
11343 #define REF_EVP_HPKE_KEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_KEY;"
11344 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
11345 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
11346 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
11347 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
11348 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
11349 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
11350 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
11351 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
11352 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
11353 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
11354 static JNINativeMethod sNativeCryptoMethods[] = {
11355         CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
11356         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
11357         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
11358         CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
11359         CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
11360         CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
11361         CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
11362         CONSCRYPT_NATIVE_METHOD(CMAC_Reset, "(" REF_CMAC_CTX ")V"),
11363         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
11364         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
11365         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
11366         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11367         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11368         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
11369         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11370         CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
11371         CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
11372         CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"),
11373         CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
11374         CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
11375         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
11376         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
11377         CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
11378         CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
11379                                 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
11380         CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
11381         CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
11382         CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11383         CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11384         CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11385         CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11386         CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
11387         CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
11388         CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
11389         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
11390         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
11391         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
11392         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
11393         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
11394         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
11395         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
11396         CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
11397         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
11398         CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
11399         CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
11400         CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
11401                                 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
11402         CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
11403                                 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
11404         CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
11405         CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
11406         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
11407         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
11408         CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
11409         CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
11410         CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11411         CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
11412         CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
11413         CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
11414         CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
11415         CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
11416         CONSCRYPT_NATIVE_METHOD(ED25519_keypair, "([B[B)V"),
11417         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
11418         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
11419         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
11420         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
11421         CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
11422         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11423         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11424         CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
11425         CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
11426         CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
11427         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11428         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11429         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11430         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
11431         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11432         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11433         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11434         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
11435         CONSCRYPT_NATIVE_METHOD(EVP_DigestSign, "(" REF_EVP_MD_CTX "[BII)[B"),
11436         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerify, "(" REF_EVP_MD_CTX "[BII[BII)Z"),
11437         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
11438         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11439         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
11440         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11441         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
11442         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
11443         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
11444         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
11445         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
11446         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
11447         CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
11448         CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
11449         CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
11450         CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
11451         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
11452         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
11453         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
11454         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
11455         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
11456         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
11457         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
11458         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
11459         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
11460         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
11461         CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
11462         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
11463         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
11464         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
11465         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
11466         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
11467         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
11468         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf,
11469                                 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11470         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf,
11471                                 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11472         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_export, "(" REF_EVP_HPKE_CTX "[BI)[B"),
11473         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_free, "(J)V"),
11474         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_open, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11475         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_seal, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11476         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_recipient,
11477                                 "(III[B[B[B)Ljava/lang/Object;"),
11478         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender,
11479                                 "(III[B[B)[Ljava/lang/Object;"),
11480         CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing,
11481                                 "(III[B[B[B)[Ljava/lang/Object;"),
11482         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
11483         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
11484         CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
11485         CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
11486         CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
11487         CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
11488         CONSCRYPT_NATIVE_METHOD(HMAC_Reset, "(" REF_HMAC_CTX ")V"),
11489         CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
11490         CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
11491         CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
11492         CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
11493         CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
11494         CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
11495         CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
11496         CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
11497         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
11498         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
11499         CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
11500         CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
11501         CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
11502         CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
11503         CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
11504         CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
11505         CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
11506         CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
11507         CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
11508         CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
11509         CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11510         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11511         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
11512         CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
11513         CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
11514         CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
11515         CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
11516         CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
11517         CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
11518         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
11519         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
11520         CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
11521         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
11522         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
11523         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
11524         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
11525         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
11526         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
11527         CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
11528         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
11529         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
11530         CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
11531                                 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
11532         CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
11533         CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
11534         CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
11535         CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
11536         CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
11537         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
11538         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext,
11539                                 "(J" REF_X509 "Ljava/lang/String;)[B"),
11540         CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
11541         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
11542         CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
11543         CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
11544         CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
11545         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
11546         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
11547         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
11548         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
11549         CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
11550         CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
11551         CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
11552         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
11553         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
11554         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
11555         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
11556         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
11557         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
11558         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
11559         CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
11560         CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
11561         CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
11562         CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
11563         CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
11564         CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
11565         CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
11566         CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
11567         CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
11568         CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
11569         CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
11570         CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
11571         CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
11572         CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
11573         CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
11574         CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
11575         CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
11576         CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
11577         CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
11578         CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
11579         CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
11580         CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
11581         CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
11582         CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
11583         CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
11584         CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
11585         CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
11586         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
11587         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
11588         CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
11589         CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
11590         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
11591         CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
11592         CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
11593         CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
11594         CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
11595         CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
11596         CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
11597         CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
11598         CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
11599         CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
11600         CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
11601         CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
11602         CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
11603         CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
11604         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
11605         CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
11606         CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
11607         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
11608         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
11609         CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
11610         CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
11611         CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
11612         CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
11613         CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
11614         CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
11615         CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
11616         CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
11617         CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
11618         CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
11619         CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
11620         CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
11621         CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
11622         CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
11623         CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
11624         CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
11625         CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
11626         CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
11627         CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
11628         CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
11629         CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
11630         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
11631         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
11632         CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
11633         CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
11634         CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
11635         CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
11636         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
11637         CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
11638         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
11639         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
11640         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
11641         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
11642         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
11643         CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
11644         CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
11645         CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
11646         CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
11647         CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
11648         CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
11649         CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
11650         CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
11651                                 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
11652         CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
11653         CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
11654         CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
11655         CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
11656         CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
11657         CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
11658         CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
11659         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
11660         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11661         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11662         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11663         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11664         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
11665         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
11666         CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
11667         CONSCRYPT_NATIVE_METHOD(Scrypt_generate_key, "([B[BIIII)[B"),
11668         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_spake_credential, "([B[B[B[BZIJ" REF_SSL_CTX ")V"),
11669 
11670         // Used for testing only.
11671         CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
11672         CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
11673         CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
11674         CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
11675         CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
11676         CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
11677 };
11678 
registerNativeMethods(JNIEnv * env)11679 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
11680     conscrypt::jniutil::jniRegisterNativeMethods(
11681             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
11682             NELEM(sNativeCryptoMethods));
11683 }
11684 
11685 /* Local Variables: */
11686 /* mode: c++ */
11687 /* tab-width: 4 */
11688 /* indent-tabs-mode: nil */
11689 /* c-basic-offset: 4 */
11690 /* End: */
11691 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
11692