• 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 
32 #include <nativehelper/scoped_primitive_array.h>
33 #include <nativehelper/scoped_utf_chars.h>
34 
35 #include <limits.h>
36 
37 #include <openssl/aead.h>
38 #include <openssl/asn1.h>
39 #include <openssl/chacha.h>
40 #include <openssl/cmac.h>
41 #include <openssl/crypto.h>
42 #include <openssl/curve25519.h>
43 #include <openssl/engine.h>
44 #include <openssl/err.h>
45 #include <openssl/evp.h>
46 #include <openssl/hmac.h>
47 #include <openssl/pkcs7.h>
48 #include <openssl/pkcs8.h>
49 #include <openssl/rand.h>
50 #include <openssl/rsa.h>
51 #include <openssl/ssl.h>
52 #include <openssl/x509v3.h>
53 
54 #include <limits>
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 
205 /**
206  * arrayToBignumSize sets |*out_size| to the size of the big-endian number
207  * contained in |source|. It returns true on success and sets an exception and
208  * returns false otherwise.
209  */
arrayToBignumSize(JNIEnv * env,jbyteArray source,size_t * out_size)210 static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
211     JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
212 
213     ScopedByteArrayRO sourceBytes(env, source);
214     if (sourceBytes.get() == nullptr) {
215         JNI_TRACE("arrayToBignum(%p, %p) => null", source, out_size);
216         return false;
217     }
218     const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
219     size_t tmpSize = sourceBytes.size();
220 
221     if (tmpSize == 0) {
222         *out_size = 0;
223         return true;
224     }
225 
226     if ((tmp[0] & 0x80) != 0) {
227         // Negative numbers are invalid.
228         conscrypt::jniutil::throwRuntimeException(env, "Negative number");
229         return false;
230     }
231 
232     while (tmpSize > 0 && tmp[0] == 0) {
233         tmp++;
234         tmpSize--;
235     }
236 
237     *out_size = tmpSize;
238     return true;
239 }
240 
241 /**
242  * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
243  */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)244 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
245     JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
246 
247     if (source == nullptr) {
248         conscrypt::jniutil::throwNullPointerException(env, sourceName);
249         return nullptr;
250     }
251 
252     size_t numBytes = BN_num_bytes(source) + 1;
253     jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
254     ScopedByteArrayRW bytes(env, javaBytes);
255     if (bytes.get() == nullptr) {
256         JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
257         return nullptr;
258     }
259 
260     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
261     if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
262         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
263         return nullptr;
264     }
265 
266     // Set the sign and convert to two's complement if necessary for the Java code.
267     if (BN_is_negative(source)) {
268         bool carry = true;
269         for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
270             tmp[i] ^= 0xFF;
271             if (carry) {
272                 carry = (++tmp[i]) == 0;
273             }
274         }
275         *tmp |= 0x80;
276     } else {
277         *tmp = 0x00;
278     }
279 
280     JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
281     return javaBytes;
282 }
283 
284 /**
285  * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
286  * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
287  * from the OpenSSL ASN.1 API. Note i2d_func may take a const parameter, so we
288  * use a separate type parameter.
289  *
290  * TODO(https://crbug.com/boringssl/407): When all BoringSSL i2d functions are
291  * const, switch back to a single template parameter.
292  */
293 template <typename T, typename U>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(U *,unsigned char **))294 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(U*, unsigned char**)) {
295     // T and U should be the same type, but may differ in const.
296     static_assert(std::is_same<typename std::remove_const<T>::type,
297                                typename std::remove_const<U>::type>::value,
298                   "obj and i2d_func have incompatible types");
299 
300     if (obj == nullptr) {
301         conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
302         JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
303         return nullptr;
304     }
305 
306     int derLen = i2d_func(obj, nullptr);
307     if (derLen < 0) {
308         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
309         JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
310         return nullptr;
311     }
312 
313     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
314     if (byteArray.get() == nullptr) {
315         JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
316         return nullptr;
317     }
318 
319     ScopedByteArrayRW bytes(env, byteArray.get());
320     if (bytes.get() == nullptr) {
321         JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
322         return nullptr;
323     }
324 
325     unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
326     int ret = i2d_func(obj, &p);
327     if (ret < 0) {
328         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
329         JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
330         return nullptr;
331     }
332 
333     JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
334     return byteArray.release();
335 }
336 
337 /**
338  * Finishes a pending CBB and returns a jbyteArray with the contents.
339  */
CBBToByteArray(JNIEnv * env,CBB * cbb)340 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
341     uint8_t* data;
342     size_t len;
343     if (!CBB_finish(cbb, &data, &len)) {
344         conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
345         ERR_clear_error();
346         JNI_TRACE("creating byte array failed");
347         return nullptr;
348     }
349     bssl::UniquePtr<uint8_t> free_data(data);
350 
351     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
352     if (byteArray.get() == nullptr) {
353         JNI_TRACE("creating byte array failed");
354         return nullptr;
355     }
356 
357     ScopedByteArrayRW bytes(env, byteArray.get());
358     if (bytes.get() == nullptr) {
359         JNI_TRACE("using byte array failed");
360         return nullptr;
361     }
362 
363     memcpy(bytes.get(), data, len);
364     return byteArray.release();
365 }
366 
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)367 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
368     if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
369         JNI_TRACE("buffer too large");
370         conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
371         return nullptr;
372     }
373 
374     int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
375     jbyteArray ret = env->NewByteArray(length);
376     if (ret == nullptr) {
377         JNI_TRACE("allocating byte array failed");
378         return nullptr;
379     }
380 
381     env->SetByteArrayRegion(ret, 0, length,
382                             reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
383     return ret;
384 }
385 
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)386 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
387                                                        CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
388     if (array == nullptr) {
389         JNI_TRACE("array was null");
390         conscrypt::jniutil::throwNullPointerException(env, "array == null");
391         return nullptr;
392     }
393 
394     ScopedByteArrayRO arrayRo(env, array);
395     if (arrayRo.get() == nullptr) {
396         JNI_TRACE("failed to get bytes");
397         return nullptr;
398     }
399 
400     bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
401             reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
402     if (!ret) {
403         JNI_TRACE("failed to allocate CRYPTO_BUFFER");
404         conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
405         return nullptr;
406     }
407 
408     return ret;
409 }
410 
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)411 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
412                                                const STACK_OF(CRYPTO_BUFFER)* buffers) {
413     size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
414     if (numBuffers > INT_MAX) {
415         JNI_TRACE("too many buffers");
416         conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
417         return nullptr;
418     }
419 
420     ScopedLocalRef<jobjectArray> array(
421             env, env->NewObjectArray(static_cast<int>(numBuffers),
422                                      conscrypt::jniutil::byteArrayClass, nullptr));
423     if (array.get() == nullptr) {
424         JNI_TRACE("failed to allocate array");
425         return nullptr;
426     }
427 
428     for (size_t i = 0; i < numBuffers; ++i) {
429         CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
430         ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
431         if (bArray.get() == nullptr) {
432             return nullptr;
433         }
434         env->SetObjectArrayElement(array.get(), i, bArray.get());
435     }
436 
437     return array.release();
438 }
439 
440 /**
441  * Converts ASN.1 BIT STRING to a jbooleanArray.
442  */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)443 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
444     int size = ASN1_STRING_length(bitStr) * 8;
445     if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
446         size -= bitStr->flags & 0x07;
447     }
448 
449     ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
450     if (bitsRef.get() == nullptr) {
451         return nullptr;
452     }
453 
454     ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
455     for (size_t i = 0; i < bitsArray.size(); i++) {
456         bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
457     }
458 
459     return bitsRef.release();
460 }
461 
bio_stream_create(BIO * b)462 static int bio_stream_create(BIO* b) {
463     b->init = 1;
464     b->num = 0;
465     b->ptr = nullptr;
466     b->flags = 0;
467     return 1;
468 }
469 
bio_stream_destroy(BIO * b)470 static int bio_stream_destroy(BIO* b) {
471     if (b == nullptr) {
472         return 0;
473     }
474 
475     if (b->ptr != nullptr) {
476         delete static_cast<BioStream*>(b->ptr);
477         b->ptr = nullptr;
478     }
479 
480     b->init = 0;
481     b->flags = 0;
482     return 1;
483 }
484 
bio_stream_read(BIO * b,char * buf,int len)485 static int bio_stream_read(BIO* b, char* buf, int len) {
486     BIO_clear_retry_flags(b);
487     BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
488     int ret = stream->read(buf, len);
489     if (ret == 0) {
490         if (stream->isFinite()) {
491             return 0;
492         }
493         // If the BioInputStream is not finite then EOF doesn't mean that
494         // there's nothing more coming.
495         BIO_set_retry_read(b);
496         return -1;
497     }
498     return ret;
499 }
500 
bio_stream_write(BIO * b,const char * buf,int len)501 static int bio_stream_write(BIO* b, const char* buf, int len) {
502     BIO_clear_retry_flags(b);
503     BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
504     return stream->write(buf, len);
505 }
506 
bio_stream_puts(BIO * b,const char * buf)507 static int bio_stream_puts(BIO* b, const char* buf) {
508     BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
509     return stream->write(buf, static_cast<int>(strlen(buf)));
510 }
511 
bio_stream_gets(BIO * b,char * buf,int len)512 static int bio_stream_gets(BIO* b, char* buf, int len) {
513     BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
514     return stream->gets(buf, len);
515 }
516 
bio_stream_assign(BIO * b,BioStream * stream)517 static void bio_stream_assign(BIO* b, BioStream* stream) {
518     b->ptr = static_cast<void*>(stream);
519 }
520 
521 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)522 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
523     BioStream* stream = static_cast<BioStream*>(b->ptr);
524 
525     switch (cmd) {
526         case BIO_CTRL_EOF:
527             return stream->isEof() ? 1 : 0;
528         case BIO_CTRL_FLUSH:
529             return stream->flush();
530         default:
531             return 0;
532     }
533 }
534 
535 static BIO_METHOD stream_bio_method = {
536         (100 | 0x0400), /* source/sink BIO */
537         "InputStream/OutputStream BIO",
538         bio_stream_write,   /* bio_write */
539         bio_stream_read,    /* bio_read */
540         bio_stream_puts,    /* bio_puts */
541         bio_stream_gets,    /* bio_gets */
542         bio_stream_ctrl,    /* bio_ctrl */
543         bio_stream_create,  /* bio_create */
544         bio_stream_destroy, /* bio_free */
545         nullptr,            /* no bio_callback_ctrl */
546 };
547 
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)548 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
549                                              size_t message_len) {
550     JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
551     if (message_len > std::numeric_limits<jsize>::max()) {
552         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
553         return nullptr;
554     }
555     ScopedLocalRef<jbyteArray> messageArray(env,
556                                             env->NewByteArray(static_cast<jsize>(message_len)));
557     if (env->ExceptionCheck()) {
558         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
559         return nullptr;
560     }
561 
562     {
563         ScopedByteArrayRW messageBytes(env, messageArray.get());
564         if (messageBytes.get() == nullptr) {
565             JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
566             return nullptr;
567         }
568 
569         memcpy(messageBytes.get(), message, message_len);
570     }
571 
572     return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
573             conscrypt::jniutil::cryptoUpcallsClass,
574             conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod, privateKey, messageArray.get()));
575 }
576 
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)577 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
578                                               const char* message, size_t message_len) {
579     if (message_len > std::numeric_limits<jsize>::max()) {
580         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
581         return nullptr;
582     }
583     ScopedLocalRef<jbyteArray> messageArray(env,
584                                             env->NewByteArray(static_cast<jsize>(message_len)));
585     if (env->ExceptionCheck()) {
586         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
587         return nullptr;
588     }
589 
590     {
591         ScopedByteArrayRW messageBytes(env, messageArray.get());
592         if (messageBytes.get() == nullptr) {
593             JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
594             return nullptr;
595         }
596 
597         memcpy(messageBytes.get(), message, message_len);
598     }
599 
600     return reinterpret_cast<jbyteArray>(
601             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
602                                         conscrypt::jniutil::cryptoUpcallsClass_rsaSignMethod,
603                                         privateKey, padding, messageArray.get()));
604 }
605 
606 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
607 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
608 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
609 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)610 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
611                                            const char* ciphertext, size_t ciphertext_len) {
612     if (ciphertext_len > std::numeric_limits<jsize>::max()) {
613         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
614         return nullptr;
615     }
616     ScopedLocalRef<jbyteArray> ciphertextArray(
617             env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
618     if (env->ExceptionCheck()) {
619         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
620         return nullptr;
621     }
622 
623     {
624         ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
625         if (ciphertextBytes.get() == nullptr) {
626             JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
627             return nullptr;
628         }
629 
630         memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
631     }
632 
633     return reinterpret_cast<jbyteArray>(
634             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
635                                         conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
636                                         privateKey, padding, ciphertextArray.get()));
637 }
638 
639 // *********************************************
640 // From keystore_openssl.cpp in Chromium source.
641 // *********************************************
642 
643 namespace {
644 
645 ENGINE* g_engine;
646 int g_rsa_exdata_index;
647 int g_ecdsa_exdata_index;
648 RSA_METHOD g_rsa_method;
649 ECDSA_METHOD g_ecdsa_method;
650 std::once_flag g_engine_once;
651 
652 void init_engine_globals();
653 
ensure_engine_globals()654 void ensure_engine_globals() {
655     std::call_once(g_engine_once, init_engine_globals);
656 }
657 
658 // KeyExData contains the data that is contained in the EX_DATA of the RSA
659 // and ECDSA objects that are created to wrap Android system keys.
660 struct KeyExData {
661     // private_key contains a reference to a Java, private-key object.
662     jobject private_key;
663     // cached_size contains the "size" of the key. This is the size of the
664     // modulus (in bytes) for RSA, or the group order size for ECDSA. This
665     // avoids calling into Java to calculate the size.
666     size_t cached_size;
667 };
668 
669 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
670 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)671 int ExDataDup(CRYPTO_EX_DATA* /* to */,
672               const CRYPTO_EX_DATA* /* from */,
673               void** /* from_d */,
674               int /* index */,
675               long /* argl */ /* NOLINT(runtime/int) */,
676               void* /* argp */) {
677   return 0;
678 }
679 
680 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)681 void ExDataFree(void* /* parent */,
682                 void* ptr,
683                 CRYPTO_EX_DATA* /* ad */,
684                 int /* index */,
685                 long /* argl */ /* NOLINT(runtime/int) */,
686                 void* /* argp */) {
687     // Ensure the global JNI reference created with this wrapper is
688     // properly destroyed with it.
689     KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
690     if (ex_data != nullptr) {
691         JNIEnv* env = conscrypt::jniutil::getJNIEnv();
692         env->DeleteGlobalRef(ex_data->private_key);
693         delete ex_data;
694     }
695 }
696 
RsaGetExData(const RSA * rsa)697 KeyExData* RsaGetExData(const RSA* rsa) {
698     return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
699 }
700 
RsaMethodSize(const RSA * rsa)701 size_t RsaMethodSize(const RSA* rsa) {
702     const KeyExData* ex_data = RsaGetExData(rsa);
703     return ex_data->cached_size;
704 }
705 
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)706 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
707                      size_t in_len, int padding) {
708     if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
709         OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
710         return 0;
711     }
712 
713     // Retrieve private key JNI reference.
714     const KeyExData* ex_data = RsaGetExData(rsa);
715     if (!ex_data || !ex_data->private_key) {
716         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
717         return 0;
718     }
719 
720     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
721     if (env == nullptr) {
722         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
723         return 0;
724     }
725 
726     // For RSA keys, this function behaves as RSA_private_encrypt with
727     // the specified padding.
728     ScopedLocalRef<jbyteArray> signature(
729             env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
730                                              reinterpret_cast<const char*>(in), in_len));
731 
732     if (signature.get() == nullptr) {
733         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
734         return 0;
735     }
736 
737     ScopedByteArrayRO result(env, signature.get());
738 
739     size_t expected_size = static_cast<size_t>(RSA_size(rsa));
740     if (result.size() > expected_size) {
741         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
742         return 0;
743     }
744 
745     if (max_out < expected_size) {
746         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
747         return 0;
748     }
749 
750     // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
751     // should pad with leading 0s, but if it doesn't, pad the result.
752     size_t zero_pad = expected_size - result.size();
753     memset(out, 0, zero_pad);
754     memcpy(out + zero_pad, &result[0], result.size());
755     *out_len = expected_size;
756 
757     return 1;
758 }
759 
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)760 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
761                      size_t in_len, int padding) {
762     // Retrieve private key JNI reference.
763     const KeyExData* ex_data = RsaGetExData(rsa);
764     if (!ex_data || !ex_data->private_key) {
765         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
766         return 0;
767     }
768 
769     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
770     if (env == nullptr) {
771         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
772         return 0;
773     }
774 
775     // This function behaves as RSA_private_decrypt.
776     ScopedLocalRef<jbyteArray> cleartext(
777             env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
778                                           reinterpret_cast<const char*>(in), in_len));
779     if (cleartext.get() == nullptr) {
780         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
781         return 0;
782     }
783 
784     ScopedByteArrayRO cleartextBytes(env, cleartext.get());
785 
786     if (max_out < cleartextBytes.size()) {
787         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
788         return 0;
789     }
790 
791     // Copy result to OpenSSL-provided buffer.
792     memcpy(out, cleartextBytes.get(), cleartextBytes.size());
793     *out_len = cleartextBytes.size();
794 
795     return 1;
796 }
797 
798 // Custom ECDSA_METHOD that uses the platform APIs.
799 // Note that for now, only signing through ECDSA_sign() is really supported.
800 // all other method pointers are either stubs returning errors, or no-ops.
801 
EcKeyGetKey(const EC_KEY * ec_key)802 jobject EcKeyGetKey(const EC_KEY* ec_key) {
803     KeyExData* ex_data =
804             reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
805     return ex_data->private_key;
806 }
807 
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)808 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
809                     EC_KEY* ec_key) {
810     // Retrieve private key JNI reference.
811     jobject private_key = EcKeyGetKey(ec_key);
812     if (!private_key) {
813         CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
814         return 0;
815     }
816 
817     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
818     if (env == nullptr) {
819         return 0;
820     }
821 
822     // Sign message with it through JNI.
823     ScopedLocalRef<jbyteArray> signature(
824             env, ecSignDigestWithPrivateKey(env, private_key,
825                                              reinterpret_cast<const char*>(digest), digest_len));
826     if (signature.get() == nullptr) {
827         CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
828         return 0;
829     }
830 
831     ScopedByteArrayRO signatureBytes(env, signature.get());
832     // Note: With ECDSA, the actual signature may be smaller than
833     // ECDSA_size().
834     size_t max_expected_size = ECDSA_size(ec_key);
835     if (signatureBytes.size() > max_expected_size) {
836         CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
837                             signatureBytes.size(), max_expected_size);
838         return 0;
839     }
840 
841     memcpy(sig, signatureBytes.get(), signatureBytes.size());
842     *sig_len = static_cast<unsigned int>(signatureBytes.size());
843     return 1;
844 }
845 
init_engine_globals()846 void init_engine_globals() {
847     g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
848                                               nullptr /* new_func */, ExDataDup, ExDataFree);
849     g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
850                                                    nullptr /* new_func */, ExDataDup, ExDataFree);
851 
852     g_rsa_method.common.is_static = 1;
853     g_rsa_method.size = RsaMethodSize;
854     g_rsa_method.sign_raw = RsaMethodSignRaw;
855     g_rsa_method.decrypt = RsaMethodDecrypt;
856     g_rsa_method.flags = RSA_FLAG_OPAQUE;
857 
858     g_ecdsa_method.common.is_static = 1;
859     g_ecdsa_method.sign = EcdsaMethodSign;
860     g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
861 
862     g_engine = ENGINE_new();
863     ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
864     ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
865 }
866 
867 }  // anonymous namespace
868 
869 #define THROW_SSLEXCEPTION (-2)
870 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
871 #define THROWN_EXCEPTION (-4)
872 
873 /**
874  * Initialization phase for every OpenSSL job: Loads the Error strings, the
875  * crypto algorithms and reset the OpenSSL library
876  */
NativeCrypto_clinit(JNIEnv *,jclass)877 static void NativeCrypto_clinit(JNIEnv*, jclass) {
878     CRYPTO_library_init();
879 }
880 
881 /**
882  * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
883  */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)884 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
885                                            jbyteArray d, jbyteArray p, jbyteArray q,
886                                            jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
887     CHECK_ERROR_QUEUE_ON_RETURN;
888     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,
889               p, q, dmp1, dmq1, iqmp);
890 
891     bssl::UniquePtr<RSA> rsa(RSA_new());
892     if (rsa.get() == nullptr) {
893         conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
894         return 0;
895     }
896 
897     if (e == nullptr && d == nullptr) {
898         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
899                                            "e == null && d == null");
900         JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
901         return 0;
902     }
903 
904     if (!arrayToBignum(env, n, &rsa->n)) {
905         return 0;
906     }
907 
908     if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
909         return 0;
910     }
911 
912     if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
913         return 0;
914     }
915 
916     if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
917         return 0;
918     }
919 
920     if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
921         return 0;
922     }
923 
924     if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
925         return 0;
926     }
927 
928     if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
929         return 0;
930     }
931 
932     if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
933         return 0;
934     }
935 
936     if (conscrypt::trace::kWithJniTrace) {
937         if (p != nullptr && q != nullptr) {
938             int check = RSA_check_key(rsa.get());
939             JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
940         }
941     }
942 
943     if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
944         conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
945         return 0;
946     }
947 
948     /*
949      * If the private exponent is available, there is the potential to do signing
950      * operations. However, we can only do blinding if the public exponent is also
951      * available. Disable blinding if the public exponent isn't available.
952      *
953      * TODO[kroot]: We should try to recover the public exponent by trying
954      *              some common ones such 3, 17, or 65537.
955      */
956     if (rsa->d != nullptr && rsa->e == nullptr) {
957         JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
958         rsa->flags |= RSA_FLAG_NO_BLINDING;
959     }
960 
961     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
962     if (pkey.get() == nullptr) {
963         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
964         return 0;
965     }
966     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
967         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
968         ERR_clear_error();
969         return 0;
970     }
971     OWNERSHIP_TRANSFERRED(rsa);
972     JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
973               e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
974     return reinterpret_cast<uintptr_t>(pkey.release());
975 }
976 
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)977 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
978                                               jobject pubkeyRef, jbyteArray keyJavaBytes) {
979     CHECK_ERROR_QUEUE_ON_RETURN;
980     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
981     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
982     if (group == nullptr) {
983         return 0;
984     }
985     const EC_POINT* pubkey =
986             pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
987     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
988 
989     bssl::UniquePtr<BIGNUM> key(nullptr);
990     if (keyJavaBytes != nullptr) {
991         BIGNUM* keyRef = nullptr;
992         if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
993             return 0;
994         }
995         key.reset(keyRef);
996     }
997 
998     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
999     if (eckey.get() == nullptr) {
1000         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1001         return 0;
1002     }
1003 
1004     if (EC_KEY_set_group(eckey.get(), group) != 1) {
1005         JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1006                   keyJavaBytes);
1007         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1008         return 0;
1009     }
1010 
1011     if (pubkey != nullptr) {
1012         if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1013             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1014                       pubkey, keyJavaBytes);
1015             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1016             return 0;
1017         }
1018     }
1019 
1020     if (key.get() != nullptr) {
1021         if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1022             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1023                       pubkey, keyJavaBytes);
1024             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1025             return 0;
1026         }
1027         if (pubkey == nullptr) {
1028             bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1029             if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1030                 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1031                           pubkey, keyJavaBytes);
1032                 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1033                 return 0;
1034             }
1035             EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1036         }
1037     }
1038 
1039     if (!EC_KEY_check_key(eckey.get())) {
1040         JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1041                   keyJavaBytes);
1042         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1043         return 0;
1044     }
1045 
1046     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1047     if (pkey.get() == nullptr) {
1048         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1049         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1050         return 0;
1051     }
1052     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1053         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1054         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1055         ERR_clear_error();
1056         return 0;
1057     }
1058     OWNERSHIP_TRANSFERRED(eckey);
1059 
1060     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1061     return reinterpret_cast<uintptr_t>(pkey.release());
1062 }
1063 
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1064 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1065     CHECK_ERROR_QUEUE_ON_RETURN;
1066     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1067     JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1068 
1069     if (pkey == nullptr) {
1070         return -1;
1071     }
1072 
1073     int result = EVP_PKEY_id(pkey);
1074     JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1075     return result;
1076 }
1077 
1078 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1079 
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1080 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1081                               const char* debug_name) {
1082     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1083     JNI_TRACE("%s(%p)", debug_name, pkey);
1084 
1085     if (pkey == nullptr) {
1086         return nullptr;
1087     }
1088 
1089     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1090     if (buffer.get() == nullptr) {
1091         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1092         return nullptr;
1093     }
1094 
1095     if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1096         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1097         return nullptr;
1098     }
1099     // Null terminate this
1100     BIO_write(buffer.get(), "\0", 1);
1101 
1102     char* tmp;
1103     BIO_get_mem_data(buffer.get(), &tmp);
1104     jstring description = env->NewStringUTF(tmp);
1105 
1106     JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1107     return description;
1108 }
1109 
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1110 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1111     CHECK_ERROR_QUEUE_ON_RETURN;
1112     return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1113 }
1114 
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1115 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1116     CHECK_ERROR_QUEUE_ON_RETURN;
1117     return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1118 }
1119 
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1120 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1121     CHECK_ERROR_QUEUE_ON_RETURN;
1122     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1123     JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1124 
1125     if (pkey != nullptr) {
1126         EVP_PKEY_free(pkey);
1127     }
1128 }
1129 
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1130 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1131     CHECK_ERROR_QUEUE_ON_RETURN;
1132     JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1133     EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1134     if (pkey1 == nullptr) {
1135         JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1136         return 0;
1137     }
1138     EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1139     if (pkey2 == nullptr) {
1140         JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1141         return 0;
1142     }
1143     JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1144 
1145     int result = EVP_PKEY_cmp(pkey1, pkey2);
1146     JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1147     return result;
1148 }
1149 
1150 /*
1151  * static native byte[] EVP_marshal_private_key(long)
1152  */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1153 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1154     CHECK_ERROR_QUEUE_ON_RETURN;
1155     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1156     JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1157 
1158     if (pkey == nullptr) {
1159         return nullptr;
1160     }
1161 
1162     bssl::ScopedCBB cbb;
1163     if (!CBB_init(cbb.get(), 64)) {
1164         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1165         JNI_TRACE("CBB_init failed");
1166         return nullptr;
1167     }
1168 
1169     if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1170         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1171         JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1172         return nullptr;
1173     }
1174 
1175     return CBBToByteArray(env, cbb.get());
1176 }
1177 
1178 /*
1179  * static native long EVP_parse_private_key(byte[])
1180  */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1181 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1182     CHECK_ERROR_QUEUE_ON_RETURN;
1183     JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1184 
1185     ScopedByteArrayRO bytes(env, keyJavaBytes);
1186     if (bytes.get() == nullptr) {
1187         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1188         return 0;
1189     }
1190 
1191     CBS cbs;
1192     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1193     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1194     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1195     // allow parsing keys from buffers that are larger than the contained key structure
1196     // so we do the same for compatibility.
1197     if (!pkey) {
1198         conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1199         ERR_clear_error();
1200         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1201         return 0;
1202     }
1203 
1204     JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1205     return reinterpret_cast<uintptr_t>(pkey.release());
1206 }
1207 
1208 /*
1209  * static native byte[] EVP_marshal_public_key(long)
1210  */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1211 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1212     CHECK_ERROR_QUEUE_ON_RETURN;
1213     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1214     JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1215 
1216     if (pkey == nullptr) {
1217         return nullptr;
1218     }
1219 
1220     bssl::ScopedCBB cbb;
1221     if (!CBB_init(cbb.get(), 64)) {
1222         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1223         JNI_TRACE("CBB_init failed");
1224         return nullptr;
1225     }
1226 
1227     if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1228         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1229         JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1230         return nullptr;
1231     }
1232 
1233     return CBBToByteArray(env, cbb.get());
1234 }
1235 
1236 /*
1237  * static native long EVP_parse_public_key(byte[])
1238  */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1239 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1240     CHECK_ERROR_QUEUE_ON_RETURN;
1241     JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1242 
1243     ScopedByteArrayRO bytes(env, keyJavaBytes);
1244     if (bytes.get() == nullptr) {
1245         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1246         return 0;
1247     }
1248 
1249     CBS cbs;
1250     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1251     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1252     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1253     // allow parsing keys from buffers that are larger than the contained key structure
1254     // so we do the same for compatibility.
1255     if (!pkey) {
1256         conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1257         ERR_clear_error();
1258         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1259         return 0;
1260     }
1261 
1262     JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1263     return reinterpret_cast<uintptr_t>(pkey.release());
1264 }
1265 
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1266 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1267                                                   jbyteArray modulusBytes) {
1268     CHECK_ERROR_QUEUE_ON_RETURN;
1269     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1270 
1271     size_t cached_size;
1272     if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
1273         JNI_TRACE("getRSAPrivateKeyWrapper failed");
1274         return 0;
1275     }
1276 
1277     ensure_engine_globals();
1278 
1279     bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1280     if (rsa.get() == nullptr) {
1281         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1282         return 0;
1283     }
1284 
1285     // The PSS padding code needs access to the actual n, so set it even though we
1286     // don't set any other parts of the key
1287     if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1288         return 0;
1289     }
1290 
1291     auto ex_data = new KeyExData;
1292     ex_data->private_key = env->NewGlobalRef(javaKey);
1293     ex_data->cached_size = cached_size;
1294     RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1295 
1296     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1297     if (pkey.get() == nullptr) {
1298         JNI_TRACE("getRSAPrivateKeyWrapper failed");
1299         conscrypt::jniutil::throwRuntimeException(env,
1300                                                   "NativeCrypto_getRSAPrivateKeyWrapper failed");
1301         ERR_clear_error();
1302         return 0;
1303     }
1304 
1305     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1306         conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1307         ERR_clear_error();
1308         return 0;
1309     }
1310     OWNERSHIP_TRANSFERRED(rsa);
1311     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1312     return reinterpret_cast<uintptr_t>(pkey.release());
1313 }
1314 
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1315 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1316                                                  jobject groupRef) {
1317     CHECK_ERROR_QUEUE_ON_RETURN;
1318     EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1319     JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1320     if (group == nullptr) {
1321         return 0;
1322     }
1323 
1324     ensure_engine_globals();
1325 
1326     bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1327     if (ecKey.get() == nullptr) {
1328         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1329         return 0;
1330     }
1331 
1332     if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1333         JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1334         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1335         return 0;
1336     }
1337 
1338     auto ex_data = new KeyExData;
1339     ex_data->private_key = env->NewGlobalRef(javaKey);
1340 
1341     if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1342         env->DeleteGlobalRef(ex_data->private_key);
1343         delete ex_data;
1344         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1345         ERR_clear_error();
1346         return 0;
1347     }
1348 
1349     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1350     if (pkey.get() == nullptr) {
1351         JNI_TRACE("getECPrivateKeyWrapper failed");
1352         conscrypt::jniutil::throwRuntimeException(env,
1353                                                   "NativeCrypto_getECPrivateKeyWrapper failed");
1354         ERR_clear_error();
1355         return 0;
1356     }
1357 
1358     if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1359         conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1360         ERR_clear_error();
1361         return 0;
1362     }
1363     OWNERSHIP_TRANSFERRED(ecKey);
1364     return reinterpret_cast<uintptr_t>(pkey.release());
1365 }
1366 
1367 /*
1368  * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1369  */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1370 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1371                                               jbyteArray publicExponent) {
1372     CHECK_ERROR_QUEUE_ON_RETURN;
1373     JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1374 
1375     BIGNUM* eRef = nullptr;
1376     if (!arrayToBignum(env, publicExponent, &eRef)) {
1377         return 0;
1378     }
1379     bssl::UniquePtr<BIGNUM> e(eRef);
1380 
1381     bssl::UniquePtr<RSA> rsa(RSA_new());
1382     if (rsa.get() == nullptr) {
1383         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1384         return 0;
1385     }
1386 
1387     if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1388         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1389         return 0;
1390     }
1391 
1392     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1393     if (pkey.get() == nullptr) {
1394         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1395         return 0;
1396     }
1397 
1398     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1399         conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1400         ERR_clear_error();
1401         return 0;
1402     }
1403 
1404     OWNERSHIP_TRANSFERRED(rsa);
1405     JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1406     return reinterpret_cast<uintptr_t>(pkey.release());
1407 }
1408 
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1409 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1410     CHECK_ERROR_QUEUE_ON_RETURN;
1411     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1412     JNI_TRACE("RSA_size(%p)", pkey);
1413 
1414     if (pkey == nullptr) {
1415         return 0;
1416     }
1417 
1418     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1419     if (rsa.get() == nullptr) {
1420         conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1421         ERR_clear_error();
1422         return 0;
1423     }
1424 
1425     return static_cast<jint>(RSA_size(rsa.get()));
1426 }
1427 
1428 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1429                               int padding);
1430 
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1431 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1432                                 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1433                                 jobject pkeyRef, jint padding) {
1434     CHECK_ERROR_QUEUE_ON_RETURN;
1435     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1436     JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1437 
1438     if (pkey == nullptr) {
1439         return -1;
1440     }
1441 
1442     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1443     if (rsa.get() == nullptr) {
1444         return -1;
1445     }
1446 
1447     ScopedByteArrayRO from(env, fromJavaBytes);
1448     if (from.get() == nullptr) {
1449         return -1;
1450     }
1451 
1452     ScopedByteArrayRW to(env, toJavaBytes);
1453     if (to.get() == nullptr) {
1454         return -1;
1455     }
1456 
1457     int resultSize =
1458             operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1459                       reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1460     if (resultSize == -1) {
1461         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1462                 conscrypt::jniutil::throwBadPaddingException);
1463         JNI_TRACE("%s => threw error", caller);
1464         return -1;
1465     }
1466 
1467     JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1468               resultSize);
1469     return static_cast<jint>(resultSize);
1470 }
1471 
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1472 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1473                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1474                                              jobject pkeyRef, jint padding) {
1475     CHECK_ERROR_QUEUE_ON_RETURN;
1476     return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1477                                toJavaBytes, pkeyRef, padding);
1478 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1479 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1480                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1481                                             jobject pkeyRef, jint padding) {
1482     CHECK_ERROR_QUEUE_ON_RETURN;
1483     return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1484                                toJavaBytes, pkeyRef, padding);
1485 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1486 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1487                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1488                                             jobject pkeyRef, jint padding) {
1489     CHECK_ERROR_QUEUE_ON_RETURN;
1490     return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1491                                toJavaBytes, pkeyRef, padding);
1492 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1493 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1494                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1495                                              jobject pkeyRef, jint padding) {
1496     CHECK_ERROR_QUEUE_ON_RETURN;
1497     return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1498                                toJavaBytes, pkeyRef, padding);
1499 }
1500 
1501 /*
1502  * public static native byte[][] get_RSA_public_params(long);
1503  */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1504 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1505     CHECK_ERROR_QUEUE_ON_RETURN;
1506     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1507     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1508 
1509     if (pkey == nullptr) {
1510         return nullptr;
1511     }
1512 
1513     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1514     if (rsa.get() == nullptr) {
1515         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1516         return nullptr;
1517     }
1518 
1519     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1520     if (joa == nullptr) {
1521         return nullptr;
1522     }
1523 
1524     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1525     if (env->ExceptionCheck()) {
1526         return nullptr;
1527     }
1528     env->SetObjectArrayElement(joa, 0, n);
1529 
1530     jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1531     if (env->ExceptionCheck()) {
1532         return nullptr;
1533     }
1534     env->SetObjectArrayElement(joa, 1, e);
1535 
1536     return joa;
1537 }
1538 
1539 /*
1540  * public static native byte[][] get_RSA_private_params(long);
1541  */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1542 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1543     CHECK_ERROR_QUEUE_ON_RETURN;
1544     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1545     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1546 
1547     if (pkey == nullptr) {
1548         return nullptr;
1549     }
1550 
1551     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1552     if (rsa.get() == nullptr) {
1553         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1554         return nullptr;
1555     }
1556 
1557     jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1558     if (joa == nullptr) {
1559         return nullptr;
1560     }
1561 
1562     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1563     if (env->ExceptionCheck()) {
1564         return nullptr;
1565     }
1566     env->SetObjectArrayElement(joa, 0, n);
1567 
1568     if (RSA_get0_e(rsa.get()) != nullptr) {
1569         jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1570         if (env->ExceptionCheck()) {
1571             return nullptr;
1572         }
1573         env->SetObjectArrayElement(joa, 1, e);
1574     }
1575 
1576     if (RSA_get0_d(rsa.get()) != nullptr) {
1577         jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1578         if (env->ExceptionCheck()) {
1579             return nullptr;
1580         }
1581         env->SetObjectArrayElement(joa, 2, d);
1582     }
1583 
1584     if (RSA_get0_p(rsa.get()) != nullptr) {
1585         jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1586         if (env->ExceptionCheck()) {
1587             return nullptr;
1588         }
1589         env->SetObjectArrayElement(joa, 3, p);
1590     }
1591 
1592     if (RSA_get0_q(rsa.get()) != nullptr) {
1593         jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1594         if (env->ExceptionCheck()) {
1595             return nullptr;
1596         }
1597         env->SetObjectArrayElement(joa, 4, q);
1598     }
1599 
1600     if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1601         jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1602         if (env->ExceptionCheck()) {
1603             return nullptr;
1604         }
1605         env->SetObjectArrayElement(joa, 5, dmp1);
1606     }
1607 
1608     if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1609         jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1610         if (env->ExceptionCheck()) {
1611             return nullptr;
1612         }
1613         env->SetObjectArrayElement(joa, 6, dmq1);
1614     }
1615 
1616     if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1617         jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1618         if (env->ExceptionCheck()) {
1619             return nullptr;
1620         }
1621         env->SetObjectArrayElement(joa, 7, iqmp);
1622     }
1623 
1624     return joa;
1625 }
1626 
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1627 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1628         jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1629         jbyteArray nonceBytes, jint blockCounter) {
1630     CHECK_ERROR_QUEUE_ON_RETURN;
1631     JNI_TRACE("chacha20_encrypt_decrypt");
1632     ScopedByteArrayRO in(env, inBytes);
1633     if (in.get() == nullptr) {
1634         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1635         return;
1636     }
1637     ScopedByteArrayRW out(env, outBytes);
1638     if (out.get() == nullptr) {
1639         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1640         return;
1641     }
1642     ScopedByteArrayRO key(env, keyBytes);
1643     if (key.get() == nullptr) {
1644         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1645         return;
1646     }
1647     ScopedByteArrayRO nonce(env, nonceBytes);
1648     if (nonce.get() == nullptr) {
1649         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1650         return;
1651     }
1652 
1653     CRYPTO_chacha_20(
1654             reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1655             reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1656             length,
1657             reinterpret_cast<const unsigned char*>(key.get()),
1658             reinterpret_cast<const unsigned char*>(nonce.get()),
1659             blockCounter);
1660 }
1661 
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1662 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1663     CHECK_ERROR_QUEUE_ON_RETURN;
1664     JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1665 
1666     ScopedUtfChars curveName(env, curveNameJava);
1667     if (curveName.c_str() == nullptr) {
1668         return 0;
1669     }
1670     JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1671 
1672     int nid = OBJ_sn2nid(curveName.c_str());
1673     if (nid == NID_undef) {
1674         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1675         return 0;
1676     }
1677 
1678     EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1679     if (group == nullptr) {
1680         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1681         ERR_clear_error();
1682         return 0;
1683     }
1684 
1685     JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1686     return reinterpret_cast<uintptr_t>(group);
1687 }
1688 
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1689 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1690                                                  jbyteArray aBytes, jbyteArray bBytes,
1691                                                  jbyteArray xBytes, jbyteArray yBytes,
1692                                                  jbyteArray orderBytes, jint cofactorInt) {
1693     CHECK_ERROR_QUEUE_ON_RETURN;
1694     BIGNUM *p = nullptr, *a = nullptr, *b = nullptr, *x = nullptr, *y = nullptr;
1695     BIGNUM *order = nullptr, *cofactor = nullptr;
1696 
1697     JNI_TRACE("EC_GROUP_new_arbitrary");
1698 
1699     if (cofactorInt < 1) {
1700         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1701                                            "cofactor < 1");
1702         return 0;
1703     }
1704 
1705     cofactor = BN_new();
1706     if (cofactor == nullptr) {
1707         return 0;
1708     }
1709 
1710     int ok = 1;
1711 
1712     if (!arrayToBignum(env, pBytes, &p) || !arrayToBignum(env, aBytes, &a) ||
1713         !arrayToBignum(env, bBytes, &b) || !arrayToBignum(env, xBytes, &x) ||
1714         !arrayToBignum(env, yBytes, &y) || !arrayToBignum(env, orderBytes, &order) ||
1715         !BN_set_word(cofactor, static_cast<uint32_t>(cofactorInt))) {
1716         ok = 0;
1717     }
1718 
1719     bssl::UniquePtr<BIGNUM> pStorage(p);
1720     bssl::UniquePtr<BIGNUM> aStorage(a);
1721     bssl::UniquePtr<BIGNUM> bStorage(b);
1722     bssl::UniquePtr<BIGNUM> xStorage(x);
1723     bssl::UniquePtr<BIGNUM> yStorage(y);
1724     bssl::UniquePtr<BIGNUM> orderStorage(order);
1725     bssl::UniquePtr<BIGNUM> cofactorStorage(cofactor);
1726 
1727     if (!ok) {
1728         return 0;
1729     }
1730 
1731     bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1732     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
1733     if (group.get() == nullptr) {
1734         JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1735         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1736         return 0;
1737     }
1738 
1739     bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1740     if (generator.get() == nullptr) {
1741         JNI_TRACE("EC_POINT_new => null");
1742         ERR_clear_error();
1743         return 0;
1744     }
1745 
1746     if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
1747         JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1748         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1749                                                              "EC_POINT_set_affine_coordinates_GFp");
1750         return 0;
1751     }
1752 
1753     if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
1754         JNI_TRACE("EC_GROUP_set_generator => error");
1755         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1756         return 0;
1757     }
1758 
1759     JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1760     return reinterpret_cast<uintptr_t>(group.release());
1761 }
1762 
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1763 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1764     CHECK_ERROR_QUEUE_ON_RETURN;
1765     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1766     JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1767 
1768     if (group == nullptr) {
1769         JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1770         return nullptr;
1771     }
1772 
1773     int nid = EC_GROUP_get_curve_name(group);
1774     if (nid == NID_undef) {
1775         JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1776         return nullptr;
1777     }
1778 
1779     const char* shortName = OBJ_nid2sn(nid);
1780     JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1781     return env->NewStringUTF(shortName);
1782 }
1783 
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1784 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1785     CHECK_ERROR_QUEUE_ON_RETURN;
1786     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1787     JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1788     if (group == nullptr) {
1789         JNI_TRACE("EC_GROUP_get_curve => group == null");
1790         return nullptr;
1791     }
1792 
1793     bssl::UniquePtr<BIGNUM> p(BN_new());
1794     bssl::UniquePtr<BIGNUM> a(BN_new());
1795     bssl::UniquePtr<BIGNUM> b(BN_new());
1796 
1797     int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1798     if (ret != 1) {
1799         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1800         return nullptr;
1801     }
1802 
1803     jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1804     if (joa == nullptr) {
1805         return nullptr;
1806     }
1807 
1808     jbyteArray pArray = bignumToArray(env, p.get(), "p");
1809     if (env->ExceptionCheck()) {
1810         return nullptr;
1811     }
1812     env->SetObjectArrayElement(joa, 0, pArray);
1813 
1814     jbyteArray aArray = bignumToArray(env, a.get(), "a");
1815     if (env->ExceptionCheck()) {
1816         return nullptr;
1817     }
1818     env->SetObjectArrayElement(joa, 1, aArray);
1819 
1820     jbyteArray bArray = bignumToArray(env, b.get(), "b");
1821     if (env->ExceptionCheck()) {
1822         return nullptr;
1823     }
1824     env->SetObjectArrayElement(joa, 2, bArray);
1825 
1826     JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1827     return joa;
1828 }
1829 
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1830 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1831     CHECK_ERROR_QUEUE_ON_RETURN;
1832     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1833     JNI_TRACE("EC_GROUP_get_order(%p)", group);
1834     if (group == nullptr) {
1835         return nullptr;
1836     }
1837 
1838     bssl::UniquePtr<BIGNUM> order(BN_new());
1839     if (order.get() == nullptr) {
1840         JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1841         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1842         return nullptr;
1843     }
1844 
1845     if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1846         JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1847         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1848         return nullptr;
1849     }
1850 
1851     jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1852     if (env->ExceptionCheck()) {
1853         return nullptr;
1854     }
1855 
1856     JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1857     return orderArray;
1858 }
1859 
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1860 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1861     CHECK_ERROR_QUEUE_ON_RETURN;
1862     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1863     JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1864     if (group == nullptr) {
1865         return 0;
1866     }
1867 
1868     jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1869     if (degree == 0) {
1870         JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1871         conscrypt::jniutil::throwRuntimeException(env, "not supported");
1872         ERR_clear_error();
1873         return 0;
1874     }
1875 
1876     JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1877     return degree;
1878 }
1879 
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1880 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1881     CHECK_ERROR_QUEUE_ON_RETURN;
1882     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1883     JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1884     if (group == nullptr) {
1885         return nullptr;
1886     }
1887 
1888     bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1889     if (cofactor.get() == nullptr) {
1890         JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1891         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1892         return nullptr;
1893     }
1894 
1895     if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1896         JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1897         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1898         return nullptr;
1899     }
1900 
1901     jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1902     if (env->ExceptionCheck()) {
1903         return nullptr;
1904     }
1905 
1906     JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1907     return cofactorArray;
1908 }
1909 
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1910 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1911     CHECK_ERROR_QUEUE_ON_RETURN;
1912     EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1913     JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1914 
1915     if (group == nullptr) {
1916         JNI_TRACE("EC_GROUP_clear_free => group == null");
1917         conscrypt::jniutil::throwNullPointerException(env, "group == null");
1918         return;
1919     }
1920 
1921     EC_GROUP_free(group);
1922     JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1923 }
1924 
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1925 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1926     CHECK_ERROR_QUEUE_ON_RETURN;
1927     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1928     JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1929 
1930     if (group == nullptr) {
1931         JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
1932         return 0;
1933     }
1934 
1935     const EC_POINT* generator = EC_GROUP_get0_generator(group);
1936 
1937     bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
1938     if (dup.get() == nullptr) {
1939         JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
1940         conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
1941         return 0;
1942     }
1943 
1944     JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
1945     return reinterpret_cast<uintptr_t>(dup.release());
1946 }
1947 
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)1948 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
1949     CHECK_ERROR_QUEUE_ON_RETURN;
1950     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1951     JNI_TRACE("EC_POINT_new(%p)", group);
1952 
1953     if (group == nullptr) {
1954         JNI_TRACE("EC_POINT_new(%p) => group == null", group);
1955         return 0;
1956     }
1957 
1958     EC_POINT* point = EC_POINT_new(group);
1959     if (point == nullptr) {
1960         conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
1961         return 0;
1962     }
1963 
1964     return reinterpret_cast<uintptr_t>(point);
1965 }
1966 
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)1967 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1968     CHECK_ERROR_QUEUE_ON_RETURN;
1969     EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
1970     JNI_TRACE("EC_POINT_clear_free(%p)", group);
1971 
1972     if (group == nullptr) {
1973         JNI_TRACE("EC_POINT_clear_free => group == null");
1974         conscrypt::jniutil::throwNullPointerException(env, "group == null");
1975         return;
1976     }
1977 
1978     EC_POINT_free(group);
1979     JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
1980 }
1981 
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)1982 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
1983                                                          jobject pointRef, jbyteArray xjavaBytes,
1984                                                          jbyteArray yjavaBytes) {
1985     CHECK_ERROR_QUEUE_ON_RETURN;
1986     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
1987               yjavaBytes);
1988     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1989     if (group == nullptr) {
1990         return;
1991     }
1992     EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
1993     if (point == nullptr) {
1994         return;
1995     }
1996     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
1997               yjavaBytes);
1998 
1999     BIGNUM* xRef = nullptr;
2000     if (!arrayToBignum(env, xjavaBytes, &xRef)) {
2001         return;
2002     }
2003     bssl::UniquePtr<BIGNUM> x(xRef);
2004 
2005     BIGNUM* yRef = nullptr;
2006     if (!arrayToBignum(env, yjavaBytes, &yRef)) {
2007         return;
2008     }
2009     bssl::UniquePtr<BIGNUM> y(yRef);
2010 
2011     int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2012     if (ret != 1) {
2013         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2014                                                              "EC_POINT_set_affine_coordinates");
2015         return;
2016     }
2017 
2018     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2019               yjavaBytes, ret);
2020 }
2021 
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2022 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2023                                                                  jobject groupRef,
2024                                                                  jobject pointRef) {
2025     CHECK_ERROR_QUEUE_ON_RETURN;
2026     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2027     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2028     if (group == nullptr) {
2029         return nullptr;
2030     }
2031     const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2032     if (point == nullptr) {
2033         return nullptr;
2034     }
2035     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2036 
2037     bssl::UniquePtr<BIGNUM> x(BN_new());
2038     bssl::UniquePtr<BIGNUM> y(BN_new());
2039 
2040     int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2041     if (ret != 1) {
2042         JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2043         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2044                                                              "EC_POINT_get_affine_coordinates");
2045         return nullptr;
2046     }
2047 
2048     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2049     if (joa == nullptr) {
2050         return nullptr;
2051     }
2052 
2053     jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2054     if (env->ExceptionCheck()) {
2055         return nullptr;
2056     }
2057     env->SetObjectArrayElement(joa, 0, xBytes);
2058 
2059     jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2060     if (env->ExceptionCheck()) {
2061         return nullptr;
2062     }
2063     env->SetObjectArrayElement(joa, 1, yBytes);
2064 
2065     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2066     return joa;
2067 }
2068 
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2069 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2070     CHECK_ERROR_QUEUE_ON_RETURN;
2071     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2072     JNI_TRACE("EC_KEY_generate_key(%p)", group);
2073     if (group == nullptr) {
2074         return 0;
2075     }
2076 
2077     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2078     if (eckey.get() == nullptr) {
2079         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2080         conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2081         return 0;
2082     }
2083 
2084     if (EC_KEY_set_group(eckey.get(), group) != 1) {
2085         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2086         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2087         return 0;
2088     }
2089 
2090     if (EC_KEY_generate_key(eckey.get()) != 1) {
2091         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2092         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2093         return 0;
2094     }
2095 
2096     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2097     if (pkey.get() == nullptr) {
2098         JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2099         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2100         return 0;
2101     }
2102     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2103         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2104         ERR_clear_error();
2105         return 0;
2106     }
2107     OWNERSHIP_TRANSFERRED(eckey);
2108 
2109     JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2110     return reinterpret_cast<uintptr_t>(pkey.release());
2111 }
2112 
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2113 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2114     CHECK_ERROR_QUEUE_ON_RETURN;
2115     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2116     JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2117 
2118     if (pkey == nullptr) {
2119         JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2120         return 0;
2121     }
2122 
2123     if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2124         conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2125         JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2126         return 0;
2127     }
2128 
2129     EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2130     JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2131     return reinterpret_cast<uintptr_t>(group);
2132 }
2133 
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2134 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2135     CHECK_ERROR_QUEUE_ON_RETURN;
2136     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2137     JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2138 
2139     if (pkey == nullptr) {
2140         JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2141         return nullptr;
2142     }
2143 
2144     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2145     if (eckey.get() == nullptr) {
2146         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2147         return nullptr;
2148     }
2149 
2150     const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2151 
2152     jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2153     if (env->ExceptionCheck()) {
2154         JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2155         return nullptr;
2156     }
2157 
2158     JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2159     return privBytes;
2160 }
2161 
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2162 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2163     CHECK_ERROR_QUEUE_ON_RETURN;
2164     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2165     JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2166 
2167     if (pkey == nullptr) {
2168         JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2169         return 0;
2170     }
2171 
2172     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2173     if (eckey.get() == nullptr) {
2174         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2175         return 0;
2176     }
2177 
2178     bssl::UniquePtr<EC_POINT> dup(
2179             EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2180     if (dup.get() == nullptr) {
2181         JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2182         conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2183         ERR_clear_error();
2184         return 0;
2185     }
2186 
2187     JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2188     return reinterpret_cast<uintptr_t>(dup.release());
2189 }
2190 
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2191 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2192     CHECK_ERROR_QUEUE_ON_RETURN;
2193     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2194     JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2195     if (group == nullptr) {
2196         env->ExceptionClear();
2197         conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2198         JNI_TRACE("group=%p EC_KEY_marshal_curve_name => Invalid group pointer", group);
2199         return nullptr;
2200     }
2201 
2202     bssl::ScopedCBB cbb;
2203     if (!CBB_init(cbb.get(), 64)) {
2204         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2205         JNI_TRACE("CBB_init failed");
2206         return nullptr;
2207     }
2208 
2209     if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2210         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2211         ERR_clear_error();
2212         JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2213         return nullptr;
2214     }
2215 
2216     return CBBToByteArray(env, cbb.get());
2217 }
2218 
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2219 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2220     CHECK_ERROR_QUEUE_ON_RETURN;
2221     JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2222 
2223     ScopedByteArrayRO bytes(env, curveNameBytes);
2224     if (bytes.get() == nullptr) {
2225         env->ExceptionClear();
2226         conscrypt::jniutil::throwIOException(env, "Null EC curve name");
2227         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => curveNameBytes == null ", curveNameBytes);
2228         return 0;
2229     }
2230 
2231     CBS cbs;
2232     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2233     bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2234     if (!group || CBS_len(&cbs) != 0) {
2235         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2236         ERR_clear_error();
2237         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2238         return 0;
2239     }
2240 
2241     JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2242     return reinterpret_cast<uintptr_t>(group.release());
2243 }
2244 
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2245 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2246                                           jobject pubkeyRef, jobject privkeyRef) {
2247     CHECK_ERROR_QUEUE_ON_RETURN;
2248     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2249     EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2250     if (pubPkey == nullptr) {
2251         JNI_TRACE("ECDH_compute_key => pubPkey == null");
2252         return -1;
2253     }
2254     EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2255     if (privPkey == nullptr) {
2256         JNI_TRACE("ECDH_compute_key => privPkey == null");
2257         return -1;
2258     }
2259     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2260 
2261     ScopedByteArrayRW out(env, outArray);
2262     if (out.get() == nullptr) {
2263         JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2264                   pubPkey, privPkey);
2265         return -1;
2266     }
2267 
2268     if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2269         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2270                                            nullptr);
2271         return -1;
2272     }
2273 
2274     if (pubPkey == nullptr) {
2275         JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2276         conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2277         return -1;
2278     }
2279 
2280     bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2281     if (pubkey.get() == nullptr) {
2282         JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2283         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2284                                                       conscrypt::jniutil::throwInvalidKeyException);
2285         return -1;
2286     }
2287 
2288     const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2289     if (pubkeyPoint == nullptr) {
2290         JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2291         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2292                                                       conscrypt::jniutil::throwInvalidKeyException);
2293         return -1;
2294     }
2295 
2296     if (privPkey == nullptr) {
2297         JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2298         conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2299         return -1;
2300     }
2301 
2302     bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2303     if (privkey.get() == nullptr) {
2304         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2305                                                       conscrypt::jniutil::throwInvalidKeyException);
2306         return -1;
2307     }
2308 
2309     std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2310     int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2311                                         privkey.get(), nullptr /* No KDF */);
2312     if (outputLength == -1) {
2313         JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2314         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2315                                                       conscrypt::jniutil::throwInvalidKeyException);
2316         return -1;
2317     }
2318 
2319     JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2320     return outputLength;
2321 }
2322 
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2323 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2324     CHECK_ERROR_QUEUE_ON_RETURN;
2325     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2326     JNI_TRACE("ECDSA_size(%p)", pkey);
2327 
2328     if (pkey == nullptr) {
2329         return 0;
2330     }
2331 
2332     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2333     if (ec_key.get() == nullptr) {
2334         conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2335         ERR_clear_error();
2336         return 0;
2337     }
2338 
2339     size_t size = ECDSA_size(ec_key.get());
2340 
2341     JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2342     return static_cast<jint>(size);
2343 }
2344 
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2345 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2346                                     jobject pkeyRef) {
2347     CHECK_ERROR_QUEUE_ON_RETURN;
2348     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2349     JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2350 
2351     if (pkey == nullptr) {
2352         return -1;
2353     }
2354 
2355     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2356     if (ec_key.get() == nullptr) {
2357         return -1;
2358     }
2359 
2360     ScopedByteArrayRO data_array(env, data);
2361     if (data_array.get() == nullptr) {
2362         return -1;
2363     }
2364 
2365     ScopedByteArrayRW sig_array(env, sig);
2366     if (sig_array.get() == nullptr) {
2367         return -1;
2368     }
2369 
2370     unsigned int sig_size;
2371     int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2372                             data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2373                             &sig_size, ec_key.get());
2374     if (result == 0) {
2375         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2376         JNI_TRACE("ECDSA_sign => threw error");
2377         return -1;
2378     }
2379 
2380     JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2381     return static_cast<jint>(sig_size);
2382 }
2383 
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2384 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2385                                       jobject pkeyRef) {
2386     CHECK_ERROR_QUEUE_ON_RETURN;
2387     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2388     JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2389 
2390     if (pkey == nullptr) {
2391         return -1;
2392     }
2393 
2394     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2395     if (ec_key.get() == nullptr) {
2396         return -1;
2397     }
2398 
2399     ScopedByteArrayRO data_array(env, data);
2400     if (data_array.get() == nullptr) {
2401         return -1;
2402     }
2403 
2404     ScopedByteArrayRO sig_array(env, sig);
2405     if (sig_array.get() == nullptr) {
2406         return -1;
2407     }
2408 
2409     int result =
2410             ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2411                          data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2412                          sig_array.size(), ec_key.get());
2413 
2414     if (result == 0) {
2415         // NOLINTNEXTLINE(runtime/int)
2416         unsigned long error = ERR_peek_last_error();
2417         if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2418             (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2419             // This error just means the signature didn't verify, so clear the error and return
2420             // a failed verification
2421             ERR_clear_error();
2422             JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2423             return 0;
2424         }
2425         if (error != 0) {
2426             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2427             JNI_TRACE("ECDSA_verify => threw error");
2428             return -1;
2429         }
2430         return 0;
2431     }
2432 
2433     JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2434     return static_cast<jint>(result);
2435 }
2436 
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2437 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2438                                           jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2439     CHECK_ERROR_QUEUE_ON_RETURN;
2440     JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2441 
2442     ScopedByteArrayRW out(env, outArray);
2443     if (out.get() == nullptr) {
2444         JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2445         return JNI_FALSE;
2446     }
2447 
2448     ScopedByteArrayRO privkey(env, privkeyArray);
2449     if (privkey.get() == nullptr) {
2450         JNI_TRACE("X25519(%p) => privkey == null", outArray);
2451         return JNI_FALSE;
2452     }
2453 
2454     ScopedByteArrayRO pubkey(env, pubkeyArray);
2455     if (pubkey.get() == nullptr) {
2456         JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2457         return JNI_FALSE;
2458     }
2459 
2460     if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2461                reinterpret_cast<const uint8_t*>(privkey.get()),
2462                reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2463         JNI_TRACE("X25519(%p) => failure", outArray);
2464         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2465                                                       conscrypt::jniutil::throwInvalidKeyException);
2466         return JNI_FALSE;
2467     }
2468 
2469     JNI_TRACE("X25519(%p) => success", outArray);
2470     return JNI_TRUE;
2471 }
2472 
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2473 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2474     CHECK_ERROR_QUEUE_ON_RETURN;
2475     JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2476 
2477     ScopedByteArrayRW outPublic(env, outPublicArray);
2478     if (outPublic.get() == nullptr) {
2479         JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2480         return;
2481     }
2482 
2483     ScopedByteArrayRW outPrivate(env, outPrivateArray);
2484     if (outPrivate.get() == nullptr) {
2485         JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2486         return;
2487     }
2488 
2489     if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2490         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2491         return;
2492     }
2493 
2494     X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2495     JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2496 }
2497 
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2498 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2499     CHECK_ERROR_QUEUE_ON_RETURN;
2500     JNI_TRACE_MD("EVP_MD_CTX_create()");
2501 
2502     bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2503     if (ctx.get() == nullptr) {
2504         conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2505         return 0;
2506     }
2507 
2508     JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2509     return reinterpret_cast<uintptr_t>(ctx.release());
2510 }
2511 
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2512 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2513     CHECK_ERROR_QUEUE_ON_RETURN;
2514     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2515     JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2516 
2517     if (ctx != nullptr) {
2518         EVP_MD_CTX_cleanup(ctx);
2519     }
2520 }
2521 
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2522 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2523     CHECK_ERROR_QUEUE_ON_RETURN;
2524     EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2525     JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2526 
2527     if (ctx != nullptr) {
2528         EVP_MD_CTX_destroy(ctx);
2529     }
2530 }
2531 
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2532 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2533                                             jobject srcCtxRef) {
2534     CHECK_ERROR_QUEUE_ON_RETURN;
2535     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2536     EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2537     if (dst_ctx == nullptr) {
2538         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2539         return 0;
2540     }
2541     const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2542     if (src_ctx == nullptr) {
2543         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2544         return 0;
2545     }
2546     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2547 
2548     int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2549     if (result == 0) {
2550         conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2551         ERR_clear_error();
2552     }
2553 
2554     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2555     return result;
2556 }
2557 
2558 /*
2559  * public static native int EVP_DigestFinal_ex(long, byte[], int)
2560  */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2561 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2562                                             jint offset) {
2563     CHECK_ERROR_QUEUE_ON_RETURN;
2564     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2565     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2566 
2567     if (ctx == nullptr) {
2568         JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2569         return -1;
2570     } else if (hash == nullptr) {
2571         conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2572         return -1;
2573     }
2574 
2575     ScopedByteArrayRW hashBytes(env, hash);
2576     if (hashBytes.get() == nullptr) {
2577         return -1;
2578     }
2579     unsigned int bytesWritten = static_cast<unsigned int>(-1);
2580     int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2581                                 &bytesWritten);
2582     if (ok == 0) {
2583         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2584         return -1;
2585     }
2586 
2587     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2588     return static_cast<jint>(bytesWritten);
2589 }
2590 
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2591 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2592                                            jlong evpMdRef) {
2593     CHECK_ERROR_QUEUE_ON_RETURN;
2594     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2595     const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2596     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2597 
2598     if (ctx == nullptr) {
2599         JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2600         return 0;
2601     } else if (evp_md == nullptr) {
2602         conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2603         return 0;
2604     }
2605 
2606     int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2607     if (ok == 0) {
2608         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2609         JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2610         return 0;
2611     }
2612     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2613     return ok;
2614 }
2615 
2616 /*
2617  * public static native int EVP_get_digestbyname(java.lang.String)
2618  */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2619 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2620     CHECK_ERROR_QUEUE_ON_RETURN;
2621     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2622 
2623     if (algorithm == nullptr) {
2624         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2625         return -1;
2626     }
2627 
2628     ScopedUtfChars algorithmChars(env, algorithm);
2629     if (algorithmChars.c_str() == nullptr) {
2630         return 0;
2631     }
2632     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2633 
2634     const char* alg = algorithmChars.c_str();
2635     const EVP_MD* md;
2636 
2637     if (strcasecmp(alg, "md4") == 0) {
2638         md = EVP_md4();
2639     } else if (strcasecmp(alg, "md5") == 0) {
2640         md = EVP_md5();
2641     } else if (strcasecmp(alg, "sha1") == 0) {
2642         md = EVP_sha1();
2643     } else if (strcasecmp(alg, "sha224") == 0) {
2644         md = EVP_sha224();
2645     } else if (strcasecmp(alg, "sha256") == 0) {
2646         md = EVP_sha256();
2647     } else if (strcasecmp(alg, "sha384") == 0) {
2648         md = EVP_sha384();
2649     } else if (strcasecmp(alg, "sha512") == 0) {
2650         md = EVP_sha512();
2651     } else {
2652         JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2653         conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2654         return 0;
2655     }
2656 
2657     return reinterpret_cast<uintptr_t>(md);
2658 }
2659 
2660 /*
2661  * public static native int EVP_MD_size(long)
2662  */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2663 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2664     CHECK_ERROR_QUEUE_ON_RETURN;
2665     EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2666     JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2667 
2668     if (evp_md == nullptr) {
2669         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2670         return -1;
2671     }
2672 
2673     jint result = static_cast<jint>(EVP_MD_size(evp_md));
2674     JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2675     return result;
2676 }
2677 
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)2678 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2679                                      int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2680                                                       ENGINE*, EVP_PKEY*),
2681                                      const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2682                                      jobject pkeyRef) {
2683     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2684     if (mdCtx == nullptr) {
2685         JNI_TRACE("%s => mdCtx == null", jniName);
2686         return 0;
2687     }
2688     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2689     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2690     if (pkey == nullptr) {
2691         JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2692         return 0;
2693     }
2694     JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2695 
2696     if (md == nullptr) {
2697         JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2698         conscrypt::jniutil::throwNullPointerException(env, "md == null");
2699         return 0;
2700     }
2701 
2702     EVP_PKEY_CTX* pctx = nullptr;
2703     if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2704         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2705         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2706         return 0;
2707     }
2708 
2709     JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2710     return reinterpret_cast<jlong>(pctx);
2711 }
2712 
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2713 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2714                                              const jlong evpMdRef, jobject pkeyRef) {
2715     CHECK_ERROR_QUEUE_ON_RETURN;
2716     return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2717                                    evpMdRef, pkeyRef);
2718 }
2719 
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2720 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2721                                                const jlong evpMdRef, jobject pkeyRef) {
2722     CHECK_ERROR_QUEUE_ON_RETURN;
2723     return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2724                                    evpMdRef, pkeyRef);
2725 }
2726 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2727 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2728                       const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2729     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2730     const void* p = reinterpret_cast<const void*>(inPtr);
2731     JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2732 
2733     if (mdCtx == nullptr) {
2734         return;
2735     }
2736 
2737     if (p == nullptr) {
2738         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2739         return;
2740     }
2741 
2742     if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2743         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2744         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2745         return;
2746     }
2747 
2748     JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2749 }
2750 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2751 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2752                       jint inLength, const char* jniName,
2753                       int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2754     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2755     JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2756 
2757     if (mdCtx == nullptr) {
2758         return;
2759     }
2760 
2761     if (inJavaBytes == nullptr) {
2762         conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2763         return;
2764     }
2765 
2766     size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2767     if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2768         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2769                                            "inBytes");
2770         return;
2771     }
2772     if (inLength == 0) {
2773         return;
2774     }
2775     jint in_offset = inOffset;
2776     jint in_size = inLength;
2777 
2778     int update_func_result = -1;
2779     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2780         // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2781         // avoid copying the whole array.
2782         if (in_size <= 1024) {
2783             // For small chunk, it's more efficient to use a bit more space on the stack instead of
2784             // allocating a new buffer.
2785             jbyte buf[1024];
2786             env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2787             update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2788                                              static_cast<size_t>(in_size));
2789         } else {
2790             // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2791             // through the buffer, stopping as soon as update_func fails.
2792             jint remaining = in_size;
2793             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2794             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2795             if (buf.get() == nullptr) {
2796                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2797                 return;
2798             }
2799             while (remaining > 0) {
2800                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2801                 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2802                 update_func_result =
2803                         update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2804                                     static_cast<size_t>(chunk_size));
2805                 if (!update_func_result) {
2806                     // update_func failed. This will be handled later in this method.
2807                     break;
2808                 }
2809                 in_offset += chunk_size;
2810                 remaining -= chunk_size;
2811             }
2812         }
2813     } else {
2814         // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2815         // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2816         // use GetByteArrayElements or another approach.
2817         jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2818         if (array_elements == nullptr) {
2819             conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2820             return;
2821         }
2822         const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2823         update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2824         env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2825     }
2826 
2827     if (!update_func_result) {
2828         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2829         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2830         return;
2831     }
2832 
2833     JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2834 }
2835 
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2836 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2837                                                 jlong inPtr, jint inLength) {
2838     CHECK_ERROR_QUEUE_ON_RETURN;
2839     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2840 }
2841 
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2842 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2843                                           jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2844     CHECK_ERROR_QUEUE_ON_RETURN;
2845     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2846               EVP_DigestUpdate);
2847 }
2848 
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2849 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2850                                               jbyteArray inJavaBytes, jint inOffset,
2851                                               jint inLength) {
2852     CHECK_ERROR_QUEUE_ON_RETURN;
2853     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2854             EVP_DigestSignUpdate);
2855 }
2856 
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2857 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2858         jlong inPtr, jint inLength) {
2859     CHECK_ERROR_QUEUE_ON_RETURN;
2860     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2861             EVP_DigestSignUpdate);
2862 }
2863 
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2864 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2865                                                 jbyteArray inJavaBytes, jint inOffset,
2866                                                 jint inLength) {
2867     CHECK_ERROR_QUEUE_ON_RETURN;
2868     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2869               EVP_DigestVerifyUpdate);
2870 }
2871 
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2872 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2873                                                       jlong inPtr, jint inLength) {
2874     CHECK_ERROR_QUEUE_ON_RETURN;
2875     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2876               EVP_DigestVerifyUpdate);
2877 }
2878 
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2879 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2880     CHECK_ERROR_QUEUE_ON_RETURN;
2881     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2882     JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2883 
2884     if (mdCtx == nullptr) {
2885         return nullptr;
2886     }
2887 
2888     size_t maxLen;
2889     if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2890         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2891         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2892         return nullptr;
2893     }
2894 
2895     std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2896     if (buffer.get() == nullptr) {
2897         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2898         return nullptr;
2899     }
2900     size_t actualLen(maxLen);
2901     if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2902         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2903         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2904         return nullptr;
2905     }
2906     if (actualLen > maxLen) {
2907         JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2908                   maxLen);
2909         conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2910         return nullptr;
2911     }
2912 
2913     ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2914     if (sigJavaBytes.get() == nullptr) {
2915         conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2916         return nullptr;
2917     }
2918     env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2919                             reinterpret_cast<jbyte*>(buffer.get()));
2920 
2921     JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2922     return sigJavaBytes.release();
2923 }
2924 
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2925 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2926                                                    jbyteArray signature, jint offset, jint len) {
2927     CHECK_ERROR_QUEUE_ON_RETURN;
2928     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2929     JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2930 
2931     if (mdCtx == nullptr) {
2932         return 0;
2933     }
2934 
2935     ScopedByteArrayRO sigBytes(env, signature);
2936     if (sigBytes.get() == nullptr) {
2937         return 0;
2938     }
2939 
2940     if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
2941         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2942                                            "signature");
2943         return 0;
2944     }
2945 
2946     const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
2947     int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
2948     jboolean result;
2949     if (err == 1) {
2950         // Signature verified
2951         result = 1;
2952     } else if (err == 0) {
2953         // Signature did not verify
2954         result = 0;
2955     } else {
2956         // Error while verifying signature
2957         JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
2958         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
2959         return 0;
2960     }
2961 
2962     // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
2963     // Clear the error queue to prevent its state from affecting future operations.
2964     ERR_clear_error();
2965 
2966     JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
2967     return result;
2968 }
2969 
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)2970 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
2971                                   int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
2972                                                               const uint8_t*, size_t),
2973                                   const char* jniName, jobject evpPkeyCtxRef,
2974                                   jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
2975                                   jint inOffset, jint inLength) {
2976     EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
2977     JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
2978                  inJavaBytes, inOffset, inLength);
2979 
2980     if (pkeyCtx == nullptr) {
2981         return 0;
2982     }
2983 
2984     ScopedByteArrayRW outBytes(env, outJavaBytes);
2985     if (outBytes.get() == nullptr) {
2986         return 0;
2987     }
2988 
2989     ScopedByteArrayRO inBytes(env, inJavaBytes);
2990     if (inBytes.get() == nullptr) {
2991         return 0;
2992     }
2993 
2994     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
2995         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2996                                            "outBytes");
2997         return 0;
2998     }
2999 
3000     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3001         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3002                                            "inBytes");
3003         return 0;
3004     }
3005 
3006     uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3007     const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3008     size_t outLength = outBytes.size() - outOffset;
3009     if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3010                               static_cast<size_t>(inLength))) {
3011         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3012         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3013                 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3014         return 0;
3015     }
3016 
3017     JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3018               outOffset, inJavaBytes, inOffset, inLength, outLength);
3019     return static_cast<jint>(outLength);
3020 }
3021 
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3022 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3023                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3024                                           jint inOffset, jint inLength) {
3025     CHECK_ERROR_QUEUE_ON_RETURN;
3026     return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3027                                  outOffset, inBytes, inOffset, inLength);
3028 }
3029 
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3030 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3031                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3032                                           jint inOffset, jint inLength) {
3033     CHECK_ERROR_QUEUE_ON_RETURN;
3034     return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3035                                  outOffset, inBytes, inOffset, inLength);
3036 }
3037 
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3038 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3039                                       int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3040     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3041     JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3042     if (pkey == nullptr) {
3043         JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3044         return 0;
3045     }
3046 
3047     bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3048     if (pkeyCtx.get() == nullptr) {
3049         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3050         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3051                 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3052         return 0;
3053     }
3054 
3055     if (!real_func(pkeyCtx.get())) {
3056         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3057         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3058                 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3059         return 0;
3060     }
3061 
3062     JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3063     return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3064 }
3065 
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3066 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3067     CHECK_ERROR_QUEUE_ON_RETURN;
3068     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3069 }
3070 
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3071 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3072     CHECK_ERROR_QUEUE_ON_RETURN;
3073     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3074 }
3075 
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3076 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3077     CHECK_ERROR_QUEUE_ON_RETURN;
3078     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3079     JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3080 
3081     if (pkeyCtx != nullptr) {
3082         EVP_PKEY_CTX_free(pkeyCtx);
3083     }
3084 }
3085 
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3086 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3087     CHECK_ERROR_QUEUE_ON_RETURN;
3088     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3089     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3090     if (pkeyCtx == nullptr) {
3091         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3092         return;
3093     }
3094 
3095     int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3096     if (result <= 0) {
3097         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3098         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3099                 env, "EVP_PKEY_CTX_set_rsa_padding",
3100                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3101         return;
3102     }
3103 
3104     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3105 }
3106 
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3107 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3108                                                           jint len) {
3109     CHECK_ERROR_QUEUE_ON_RETURN;
3110     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3111     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3112     if (pkeyCtx == nullptr) {
3113         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3114         return;
3115     }
3116 
3117     int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3118     if (result <= 0) {
3119         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3120         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3121                 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3122                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3123         return;
3124     }
3125 
3126     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3127 }
3128 
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3129 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3130                                int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3131     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3132     EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3133     JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3134     if (pkeyCtx == nullptr) {
3135         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3136         return;
3137     }
3138     if (md == nullptr) {
3139         conscrypt::jniutil::throwNullPointerException(env, "md == null");
3140         return;
3141     }
3142 
3143     int result = ctrl_func(pkeyCtx, md);
3144     if (result <= 0) {
3145         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3146         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3147                 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3148         return;
3149     }
3150 
3151     JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3152 }
3153 
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3154 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3155                                                       jlong mdRef) {
3156     CHECK_ERROR_QUEUE_ON_RETURN;
3157     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3158                        EVP_PKEY_CTX_set_rsa_mgf1_md);
3159 }
3160 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3161 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3162                                                       jlong mdRef) {
3163     CHECK_ERROR_QUEUE_ON_RETURN;
3164     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3165                        EVP_PKEY_CTX_set_rsa_oaep_md);
3166 }
3167 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3168 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3169                                                          jbyteArray labelJava) {
3170     CHECK_ERROR_QUEUE_ON_RETURN;
3171     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3172     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3173     if (pkeyCtx == nullptr) {
3174         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3175         return;
3176     }
3177 
3178     ScopedByteArrayRO labelBytes(env, labelJava);
3179     if (labelBytes.get() == nullptr) {
3180         return;
3181     }
3182 
3183     bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3184     memcpy(label.get(), labelBytes.get(), labelBytes.size());
3185 
3186     int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3187     if (result <= 0) {
3188         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3189         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3190                 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3191                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3192         return;
3193     }
3194     OWNERSHIP_TRANSFERRED(label);
3195 
3196     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3197 }
3198 
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3199 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3200     CHECK_ERROR_QUEUE_ON_RETURN;
3201     JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3202 
3203     if (algorithm == nullptr) {
3204         conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3205         JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3206         return -1;
3207     }
3208 
3209     ScopedUtfChars scoped_alg(env, algorithm);
3210     const char* alg = scoped_alg.c_str();
3211     const EVP_CIPHER* cipher;
3212 
3213     if (strcasecmp(alg, "rc4") == 0) {
3214         cipher = EVP_rc4();
3215     } else if (strcasecmp(alg, "des-cbc") == 0) {
3216         cipher = EVP_des_cbc();
3217     } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3218         cipher = EVP_des_ede_cbc();
3219     } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3220         cipher = EVP_des_ede3_cbc();
3221     } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3222         cipher = EVP_aes_128_ecb();
3223     } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3224         cipher = EVP_aes_128_cbc();
3225     } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3226         cipher = EVP_aes_128_ctr();
3227     } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3228         cipher = EVP_aes_128_gcm();
3229     } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3230         cipher = EVP_aes_192_ecb();
3231     } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3232         cipher = EVP_aes_192_cbc();
3233     } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3234         cipher = EVP_aes_192_ctr();
3235     } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3236         cipher = EVP_aes_192_gcm();
3237     } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3238         cipher = EVP_aes_256_ecb();
3239     } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3240         cipher = EVP_aes_256_cbc();
3241     } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3242         cipher = EVP_aes_256_ctr();
3243     } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3244         cipher = EVP_aes_256_gcm();
3245     } else {
3246         JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3247         return 0;
3248     }
3249 
3250     return reinterpret_cast<uintptr_t>(cipher);
3251 }
3252 
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3253 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3254                                            jbyteArray keyArray, jbyteArray ivArray,
3255                                            jboolean encrypting) {
3256     CHECK_ERROR_QUEUE_ON_RETURN;
3257     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3258     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3259     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3260               encrypting ? 1 : 0);
3261 
3262     if (ctx == nullptr) {
3263         JNI_TRACE("EVP_CipherUpdate => ctx == null");
3264         return;
3265     }
3266 
3267     // The key can be null if we need to set extra parameters.
3268     std::unique_ptr<unsigned char[]> keyPtr;
3269     if (keyArray != nullptr) {
3270         ScopedByteArrayRO keyBytes(env, keyArray);
3271         if (keyBytes.get() == nullptr) {
3272             return;
3273         }
3274 
3275         keyPtr.reset(new unsigned char[keyBytes.size()]);
3276         memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3277     }
3278 
3279     // The IV can be null if we're using ECB.
3280     std::unique_ptr<unsigned char[]> ivPtr;
3281     if (ivArray != nullptr) {
3282         ScopedByteArrayRO ivBytes(env, ivArray);
3283         if (ivBytes.get() == nullptr) {
3284             return;
3285         }
3286 
3287         ivPtr.reset(new unsigned char[ivBytes.size()]);
3288         memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3289     }
3290 
3291     if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3292                            encrypting ? 1 : 0)) {
3293         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3294         JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3295         return;
3296     }
3297 
3298     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3299               encrypting ? 1 : 0);
3300 }
3301 
3302 /*
3303  *  public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3304  *          int inOffset, int inLength);
3305  */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3306 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3307                                           jint outOffset, jbyteArray inArray, jint inOffset,
3308                                           jint inLength) {
3309     CHECK_ERROR_QUEUE_ON_RETURN;
3310     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3311     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3312 
3313     if (ctx == nullptr) {
3314         JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3315         return 0;
3316     }
3317 
3318     ScopedByteArrayRO inBytes(env, inArray);
3319     if (inBytes.get() == nullptr) {
3320         return 0;
3321     }
3322     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3323         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3324                                            "inBytes");
3325         return 0;
3326     }
3327 
3328     ScopedByteArrayRW outBytes(env, outArray);
3329     if (outBytes.get() == nullptr) {
3330         return 0;
3331     }
3332     if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3333         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3334                                            "outBytes");
3335         return 0;
3336     }
3337 
3338     JNI_TRACE(
3339             "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3340             "out.length=%zd outOffset=%d",
3341             ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3342             outOffset);
3343 
3344     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3345     const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3346 
3347     int outl;
3348     if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3349         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3350         JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3351         return 0;
3352     }
3353 
3354     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3355               inOffset, outl);
3356     return outl;
3357 }
3358 
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3359 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3360                                             jbyteArray outArray, jint outOffset) {
3361     CHECK_ERROR_QUEUE_ON_RETURN;
3362     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3363     JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3364 
3365     if (ctx == nullptr) {
3366         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3367         return 0;
3368     }
3369 
3370     ScopedByteArrayRW outBytes(env, outArray);
3371     if (outBytes.get() == nullptr) {
3372         return 0;
3373     }
3374 
3375     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3376 
3377     int outl;
3378     if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3379         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3380                 conscrypt::jniutil::throwBadPaddingException);
3381         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3382         return 0;
3383     }
3384 
3385     JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3386     return outl;
3387 }
3388 
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3389 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3390     CHECK_ERROR_QUEUE_ON_RETURN;
3391     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3392     JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3393 
3394     if (evpCipher == nullptr) {
3395         conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3396         JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3397         return 0;
3398     }
3399 
3400     jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3401     JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3402     return ivLength;
3403 }
3404 
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3405 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3406     CHECK_ERROR_QUEUE_ON_RETURN;
3407     JNI_TRACE("EVP_CIPHER_CTX_new()");
3408 
3409     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3410     if (ctx.get() == nullptr) {
3411         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3412         JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3413         return 0;
3414     }
3415 
3416     JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3417     return reinterpret_cast<uintptr_t>(ctx.release());
3418 }
3419 
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3420 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3421     CHECK_ERROR_QUEUE_ON_RETURN;
3422     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3423     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3424 
3425     if (ctx == nullptr) {
3426         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3427         return 0;
3428     }
3429 
3430     jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3431     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3432     return blockSize;
3433 }
3434 
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3435 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3436     CHECK_ERROR_QUEUE_ON_RETURN;
3437     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3438     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3439 
3440     if (ctx == nullptr) {
3441         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3442         return 0;
3443     }
3444 
3445     int buf_len = ctx->buf_len;
3446     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3447     return buf_len;
3448 }
3449 
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3450 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3451     CHECK_ERROR_QUEUE_ON_RETURN;
3452     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3453     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3454 
3455     if (ctx == nullptr) {
3456         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3457         return 0;
3458     }
3459 
3460     bool final_used = ctx->final_used != 0;
3461     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3462     return static_cast<jboolean>(final_used);
3463 }
3464 
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3465 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3466                                                     jboolean enablePaddingBool) {
3467     CHECK_ERROR_QUEUE_ON_RETURN;
3468     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3469     jint enablePadding = enablePaddingBool ? 1 : 0;
3470     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3471 
3472     if (ctx == nullptr) {
3473         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3474         return;
3475     }
3476 
3477     EVP_CIPHER_CTX_set_padding(ctx, enablePadding);  // Not void, but always returns 1.
3478     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3479 }
3480 
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3481 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3482                                                        jint keySizeBits) {
3483     CHECK_ERROR_QUEUE_ON_RETURN;
3484     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3485     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3486 
3487     if (ctx == nullptr) {
3488         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3489         return;
3490     }
3491 
3492     if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3493         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3494                 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3495         JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3496         return;
3497     }
3498     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3499 }
3500 
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3501 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3502     CHECK_ERROR_QUEUE_ON_RETURN;
3503     EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3504     JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3505 
3506     EVP_CIPHER_CTX_free(ctx);
3507 }
3508 
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3509 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3510     CHECK_ERROR_QUEUE_ON_RETURN;
3511     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3512     JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3513     return reinterpret_cast<jlong>(ctx);
3514 }
3515 
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3516 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3517     CHECK_ERROR_QUEUE_ON_RETURN;
3518     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3519     JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3520     return reinterpret_cast<jlong>(ctx);
3521 }
3522 
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3523 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3524     CHECK_ERROR_QUEUE_ON_RETURN;
3525     const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3526     JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3527     return reinterpret_cast<jlong>(ctx);
3528 }
3529 
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3530 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3531     CHECK_ERROR_QUEUE_ON_RETURN;
3532     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3533     JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3534     return reinterpret_cast<jlong>(ctx);
3535 }
3536 
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3537 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3538     CHECK_ERROR_QUEUE_ON_RETURN;
3539     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3540     JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3541     return reinterpret_cast<jlong>(ctx);
3542 }
3543 
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3544 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3545     CHECK_ERROR_QUEUE_ON_RETURN;
3546     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3547     JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3548     if (evpAead == nullptr) {
3549         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3550         return 0;
3551     }
3552     jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3553     JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3554     return maxOverhead;
3555 }
3556 
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3557 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3558     CHECK_ERROR_QUEUE_ON_RETURN;
3559     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3560     JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3561     if (evpAead == nullptr) {
3562         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3563         return 0;
3564     }
3565     jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3566     JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3567     return nonceLength;
3568 }
3569 
3570 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3571                                     size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3572                                     const uint8_t* in, size_t in_len, const uint8_t* ad,
3573                                     size_t ad_len);
3574 
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)3575 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3576                                uint8_t* outBuf, jbyteArray nonceArray,
3577                                const uint8_t* inBuf, jbyteArray aadArray,
3578                                evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange)  {
3579     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3580 
3581     ScopedByteArrayRO keyBytes(env, keyArray);
3582     if (keyBytes.get() == nullptr) {
3583         return 0;
3584     }
3585 
3586     std::unique_ptr<ScopedByteArrayRO> aad;
3587     const uint8_t* aad_chars = nullptr;
3588     size_t aad_chars_size = 0;
3589     if (aadArray != nullptr) {
3590         aad.reset(new ScopedByteArrayRO(env, aadArray));
3591         aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3592         if (aad_chars == nullptr) {
3593             return 0;
3594         }
3595         aad_chars_size = aad->size();
3596     }
3597 
3598     ScopedByteArrayRO nonceBytes(env, nonceArray);
3599     if (nonceBytes.get() == nullptr) {
3600         return 0;
3601     }
3602 
3603     bssl::ScopedEVP_AEAD_CTX aeadCtx;
3604     const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3605     if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3606                            static_cast<size_t>(tagLen), nullptr)) {
3607         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3608                                                              "failure initializing AEAD context");
3609         JNI_TRACE(
3610                 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3611                 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3612                 aadArray);
3613         return 0;
3614     }
3615 
3616     const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3617     size_t actualOutLength;
3618 
3619     if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3620                   nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3621                   aad_chars, aad_chars_size)) {
3622         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3623         return 0;
3624     }
3625 
3626     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3627               evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3628               aadArray, actualOutLength);
3629     return static_cast<jint>(actualOutLength);
3630 }
3631 
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)3632 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3633                             jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3634                             jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3635                             evp_aead_ctx_op_func realFunc) {
3636     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3637     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3638               outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3639 
3640 
3641     ScopedByteArrayRW outBytes(env, outArray);
3642     if (outBytes.get() == nullptr) {
3643         return 0;
3644     }
3645 
3646     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3647         JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3648                   evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3649                   inLength, aadArray);
3650         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3651         return 0;
3652     }
3653 
3654     ScopedByteArrayRO inBytes(env, inArray);
3655     if (inBytes.get() == nullptr) {
3656         return 0;
3657     }
3658 
3659     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3660         JNI_TRACE(
3661                 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3662                 "invalid",
3663                 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3664                 inLength, aadArray);
3665         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3666         return 0;
3667     }
3668 
3669     uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3670     const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3671 
3672     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3673                             aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3674 }
3675 
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)3676 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3677                             jobject outBuffer, jbyteArray nonceArray,
3678                             jobject inBuffer, jbyteArray aadArray,
3679                             evp_aead_ctx_op_func realFunc) {
3680 
3681     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3682     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3683               outBuffer, nonceArray, inBuffer, aadArray);
3684 
3685     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3686         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3687                                            "inBuffer is not a direct ByteBuffer");
3688         return 0;
3689     }
3690 
3691     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3692         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3693                                            "outBuffer is not a direct ByteBuffer");
3694         return 0;
3695     }
3696 
3697     uint8_t* inBuf;
3698     jint in_limit;
3699     jint in_position;
3700 
3701     inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3702      // limit is the index of the first element that should not be read or written
3703     in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3704     // position is the index of the next element to be read or written
3705     in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3706 
3707     uint8_t* outBuf;
3708     jint out_limit;
3709     jint out_position;
3710     outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3711     // limit is the index of the first element that should not be read or written
3712     out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3713     // position is the index of the next element to be read or written
3714     out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3715 
3716     // Shifting over of ByteBuffer address to start at true position
3717     inBuf += in_position;
3718     outBuf += out_position;
3719 
3720     size_t inSize = in_limit - in_position;
3721     uint8_t* outBufEnd = outBuf + out_limit - out_position;
3722     uint8_t* inBufEnd = inBuf + inSize;
3723     std::unique_ptr<uint8_t[]> inCopy;
3724     if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3725       inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3726       if (inCopy.get() == nullptr) {
3727             conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3728             return 0;
3729         }
3730         memcpy(inCopy.get(), inBuf, inSize);
3731         inBuf = inCopy.get();
3732     }
3733 
3734     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3735                                inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3736 }
3737 
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)3738 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3739                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3740                                            jint outOffset, jbyteArray nonceArray,
3741                                            jbyteArray inArray, jint inOffset, jint inLength,
3742                                            jbyteArray aadArray) {
3743     CHECK_ERROR_QUEUE_ON_RETURN;
3744     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3745                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3746 }
3747 
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)3748 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3749                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3750                                            jint outOffset, jbyteArray nonceArray,
3751                                            jbyteArray inArray, jint inOffset, jint inLength,
3752                                            jbyteArray aadArray) {
3753     CHECK_ERROR_QUEUE_ON_RETURN;
3754     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3755                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3756 }
3757 
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3758 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3759                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3760                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3761     CHECK_ERROR_QUEUE_ON_RETURN;
3762     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3763                            inBuffer, aadArray, EVP_AEAD_CTX_seal);
3764 }
3765 
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3766 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3767                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3768                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3769     CHECK_ERROR_QUEUE_ON_RETURN;
3770     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3771                            inBuffer, aadArray, EVP_AEAD_CTX_open);
3772 }
3773 
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)3774 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
3775     CHECK_ERROR_QUEUE_ON_RETURN;
3776     JNI_TRACE("CMAC_CTX_new");
3777     auto cmacCtx = CMAC_CTX_new();
3778     if (cmacCtx == nullptr) {
3779         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
3780         return 0;
3781     }
3782 
3783     return reinterpret_cast<jlong>(cmacCtx);
3784 }
3785 
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)3786 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
3787     CHECK_ERROR_QUEUE_ON_RETURN;
3788     CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
3789     JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
3790     if (cmacCtx == nullptr) {
3791         conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
3792         return;
3793     }
3794     CMAC_CTX_free(cmacCtx);
3795 }
3796 
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)3797 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
3798     CHECK_ERROR_QUEUE_ON_RETURN;
3799     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3800     JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
3801     if (cmacCtx == nullptr) {
3802         return;
3803     }
3804     ScopedByteArrayRO keyBytes(env, keyArray);
3805     if (keyBytes.get() == nullptr) {
3806         return;
3807     }
3808 
3809     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3810 
3811     const EVP_CIPHER *cipher;
3812     switch(keyBytes.size()) {
3813       case 16:
3814           cipher = EVP_aes_128_cbc();
3815           break;
3816       case 24:
3817           cipher = EVP_aes_192_cbc();
3818           break;
3819       case 32:
3820           cipher = EVP_aes_256_cbc();
3821           break;
3822       default:
3823           conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3824                                            "CMAC_Init: Unsupported key length");
3825           return;
3826     }
3827 
3828     if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
3829         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
3830         JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
3831         return;
3832     }
3833 }
3834 
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)3835 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
3836                                            int inLength) {
3837     CHECK_ERROR_QUEUE_ON_RETURN;
3838     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3839     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3840     JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
3841 
3842     if (cmacCtx == nullptr) {
3843         return;
3844     }
3845 
3846     if (p == nullptr) {
3847         conscrypt::jniutil::throwNullPointerException(env, nullptr);
3848         return;
3849     }
3850 
3851     if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
3852         JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
3853         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
3854         return;
3855     }
3856 }
3857 
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3858 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
3859                                      jint inOffset, jint inLength) {
3860     CHECK_ERROR_QUEUE_ON_RETURN;
3861     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3862     JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
3863 
3864     if (cmacCtx == nullptr) {
3865         return;
3866     }
3867 
3868     ScopedByteArrayRO inBytes(env, inArray);
3869     if (inBytes.get() == nullptr) {
3870         return;
3871     }
3872 
3873     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3874         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3875                                            "inBytes");
3876         return;
3877     }
3878 
3879     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
3880 
3881     if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
3882         JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
3883                   inLength);
3884         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
3885         return;
3886     }
3887 }
3888 
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)3889 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
3890     CHECK_ERROR_QUEUE_ON_RETURN;
3891     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3892     JNI_TRACE("CMAC_Final(%p)", cmacCtx);
3893 
3894     if (cmacCtx == nullptr) {
3895         return nullptr;
3896     }
3897 
3898     uint8_t result[EVP_MAX_MD_SIZE];
3899     size_t len;
3900     if (!CMAC_Final(cmacCtx, result, &len)) {
3901         JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
3902         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
3903         return nullptr;
3904     }
3905 
3906     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
3907     if (resultArray.get() == nullptr) {
3908         return nullptr;
3909     }
3910     ScopedByteArrayRW resultBytes(env, resultArray.get());
3911     if (resultBytes.get() == nullptr) {
3912         return nullptr;
3913     }
3914     memcpy(resultBytes.get(), result, len);
3915     return resultArray.release();
3916 }
3917 
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)3918 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
3919     CHECK_ERROR_QUEUE_ON_RETURN;
3920     JNI_TRACE("HMAC_CTX_new");
3921     auto hmacCtx = new HMAC_CTX;
3922     if (hmacCtx == nullptr) {
3923         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
3924         return 0;
3925     }
3926 
3927     HMAC_CTX_init(hmacCtx);
3928     return reinterpret_cast<jlong>(hmacCtx);
3929 }
3930 
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)3931 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
3932     CHECK_ERROR_QUEUE_ON_RETURN;
3933     HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
3934     JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
3935     if (hmacCtx == nullptr) {
3936         conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
3937         return;
3938     }
3939     HMAC_CTX_cleanup(hmacCtx);
3940     delete hmacCtx;
3941 }
3942 
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)3943 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
3944                                       jobject evpMdRef) {
3945     CHECK_ERROR_QUEUE_ON_RETURN;
3946     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3947     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3948     JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
3949     if (hmacCtx == nullptr) {
3950         return;
3951     }
3952     ScopedByteArrayRO keyBytes(env, keyArray);
3953     if (keyBytes.get() == nullptr) {
3954         return;
3955     }
3956 
3957     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3958     if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
3959         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
3960         JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
3961         return;
3962     }
3963 }
3964 
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)3965 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
3966                                            int inLength) {
3967     CHECK_ERROR_QUEUE_ON_RETURN;
3968     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3969     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3970     JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
3971 
3972     if (hmacCtx == nullptr) {
3973         return;
3974     }
3975 
3976     if (p == nullptr) {
3977         conscrypt::jniutil::throwNullPointerException(env, nullptr);
3978         return;
3979     }
3980 
3981     if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
3982         JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
3983         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
3984         return;
3985     }
3986 }
3987 
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3988 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
3989                                      jint inOffset, jint inLength) {
3990     CHECK_ERROR_QUEUE_ON_RETURN;
3991     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3992     JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
3993 
3994     if (hmacCtx == nullptr) {
3995         return;
3996     }
3997 
3998     ScopedByteArrayRO inBytes(env, inArray);
3999     if (inBytes.get() == nullptr) {
4000         return;
4001     }
4002 
4003     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4004         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4005                                            "inBytes");
4006         return;
4007     }
4008 
4009     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4010     if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4011         JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4012                   inLength);
4013         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4014         return;
4015     }
4016 }
4017 
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4018 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4019     CHECK_ERROR_QUEUE_ON_RETURN;
4020     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4021     JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4022 
4023     if (hmacCtx == nullptr) {
4024         return nullptr;
4025     }
4026 
4027     uint8_t result[EVP_MAX_MD_SIZE];
4028     unsigned len;
4029     if (!HMAC_Final(hmacCtx, result, &len)) {
4030         JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4031         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4032         return nullptr;
4033     }
4034 
4035     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4036     if (resultArray.get() == nullptr) {
4037         return nullptr;
4038     }
4039     ScopedByteArrayRW resultBytes(env, resultArray.get());
4040     if (resultBytes.get() == nullptr) {
4041         return nullptr;
4042     }
4043     memcpy(resultBytes.get(), result, len);
4044     return resultArray.release();
4045 }
4046 
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4047 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4048     CHECK_ERROR_QUEUE_ON_RETURN;
4049     JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4050 
4051     ScopedByteArrayRW outputBytes(env, output);
4052     if (outputBytes.get() == nullptr) {
4053         return;
4054     }
4055 
4056     unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4057     if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4058         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4059         JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4060         return;
4061     }
4062 
4063     JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4064 }
4065 
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4066 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4067     /*
4068      * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4069      * Just make a buffer that's large enough here. The documentation recommends
4070      * 80 characters.
4071      */
4072     char output[128];
4073     int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4074     if (ret < 0) {
4075         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4076         return nullptr;
4077     } else if (size_t(ret) >= sizeof(output)) {
4078         conscrypt::jniutil::throwRuntimeException(env,
4079                                                   "ASN1_OBJECT_to_OID_string buffer too small");
4080         return nullptr;
4081     }
4082 
4083     JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4084     return env->NewStringUTF(output);
4085 }
4086 
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4087 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4088                                                  jboolean isFinite) {
4089     CHECK_ERROR_QUEUE_ON_RETURN;
4090     JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4091 
4092     if (streamObj == nullptr) {
4093         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4094         return 0;
4095     }
4096 
4097     bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4098     if (bio.get() == nullptr) {
4099         return 0;
4100     }
4101 
4102     bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4103 
4104     JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4105     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4106 }
4107 
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4108 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4109     CHECK_ERROR_QUEUE_ON_RETURN;
4110     JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4111 
4112     if (streamObj == nullptr) {
4113         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4114         return 0;
4115     }
4116 
4117     bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4118     if (bio.get() == nullptr) {
4119         return 0;
4120     }
4121 
4122     bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4123 
4124     JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4125     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4126 }
4127 
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4128 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4129     CHECK_ERROR_QUEUE_ON_RETURN;
4130     BIO* bio = to_BIO(env, bioRef);
4131     JNI_TRACE("BIO_free_all(%p)", bio);
4132 
4133     if (bio == nullptr) {
4134         return;
4135     }
4136 
4137     BIO_free_all(bio);
4138 }
4139 
4140 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4141 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4142     JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4143 
4144     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4145     if (buffer.get() == nullptr) {
4146         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4147         JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4148         return nullptr;
4149     }
4150 
4151     /* Don't interpret the string. */
4152     flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4153 
4154     /* Write in given format and null terminate. */
4155     X509_NAME_print_ex(buffer.get(), name, 0, flags);
4156     BIO_write(buffer.get(), "\0", 1);
4157 
4158     char* tmp;
4159     BIO_get_mem_data(buffer.get(), &tmp);
4160     JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4161     return env->NewStringUTF(tmp);
4162 }
4163 
4164 /**
4165  * Converts GENERAL_NAME items to the output format expected in
4166  * X509Certificate#getSubjectAlternativeNames and
4167  * X509Certificate#getIssuerAlternativeNames return.
4168  */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4169 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4170     switch (gen->type) {
4171         case GEN_EMAIL:
4172         case GEN_DNS:
4173         case GEN_URI: {
4174             // This must be a valid IA5String and must not contain NULs.
4175             // BoringSSL does not currently enforce the former (see
4176             // https://crbug.com/boringssl/427). The latter was historically an
4177             // issue for parsers that truncate at NUL.
4178             const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4179             ssize_t len = ASN1_STRING_length(gen->d.ia5);
4180             std::vector<jchar> jchars;
4181             jchars.reserve(len);
4182             for (ssize_t i = 0; i < len; i++) {
4183                 if (data[i] == 0 || data[i] > 127) {
4184                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4185                     return nullptr;
4186                 }
4187                 // Converting ASCII to UTF-16 is the identity function.
4188                 jchars.push_back(data[i]);
4189             }
4190             JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4191             return env->NewString(jchars.data(), jchars.size());
4192         }
4193         case GEN_DIRNAME:
4194             /* Write in RFC 2253 format */
4195             return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4196         case GEN_IPADD: {
4197 #ifdef _WIN32
4198             void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4199 #else
4200             const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4201 #endif
4202             if (gen->d.ip->length == 4) {
4203                 // IPv4
4204                 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4205                 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4206                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4207                     return env->NewStringUTF(buffer.get());
4208                 } else {
4209                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4210                               strerror(errno));
4211                 }
4212             } else if (gen->d.ip->length == 16) {
4213                 // IPv6
4214                 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4215                 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4216                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4217                     return env->NewStringUTF(buffer.get());
4218                 } else {
4219                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4220                               strerror(errno));
4221                 }
4222             }
4223 
4224             /* Invalid IP encodings are pruned out without throwing an exception. */
4225             return nullptr;
4226         }
4227         case GEN_RID:
4228             return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4229         case GEN_OTHERNAME:
4230         case GEN_X400:
4231         default:
4232             return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4233     }
4234 
4235     return nullptr;
4236 }
4237 
4238 #define GN_STACK_SUBJECT_ALT_NAME 1
4239 #define GN_STACK_ISSUER_ALT_NAME 2
4240 
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4241 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4242                                                              CONSCRYPT_UNUSED jobject holder,
4243                                                              jint type) {
4244     CHECK_ERROR_QUEUE_ON_RETURN;
4245     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4246     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4247 
4248     if (x509 == nullptr) {
4249         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4250         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4251         return nullptr;
4252     }
4253 
4254     bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4255     if (type == GN_STACK_SUBJECT_ALT_NAME) {
4256         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4257                 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4258     } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4259         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4260                 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4261     } else {
4262         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4263         return nullptr;
4264     }
4265     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4266     // |ERR_clear_error|, and throw CertificateParsingException.
4267     if (gn_stack == nullptr) {
4268         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4269         ERR_clear_error();
4270         return nullptr;
4271     }
4272 
4273     int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4274     if (count <= 0) {
4275         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4276         return nullptr;
4277     }
4278 
4279     /*
4280      * Keep track of how many originally so we can ignore any invalid
4281      * values later.
4282      */
4283     const int origCount = count;
4284 
4285     ScopedLocalRef<jobjectArray> joa(
4286             env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4287     for (int i = 0, j = 0; i < origCount; i++, j++) {
4288         GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4289         ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4290         if (env->ExceptionCheck()) {
4291             JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4292                       x509, type);
4293             return nullptr;
4294         }
4295 
4296         /*
4297          * If it's nullptr, we'll have to skip this, reduce the number of total
4298          * entries, and fix up the array later.
4299          */
4300         if (val.get() == nullptr) {
4301             j--;
4302             count--;
4303             continue;
4304         }
4305 
4306         ScopedLocalRef<jobjectArray> item(
4307                 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4308 
4309         ScopedLocalRef<jobject> parsedType(
4310                 env,
4311                 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4312                                             conscrypt::jniutil::integer_valueOfMethod, gen->type));
4313         env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4314         env->SetObjectArrayElement(item.get(), 1, val.get());
4315 
4316         env->SetObjectArrayElement(joa.get(), j, item.get());
4317     }
4318 
4319     if (count == 0) {
4320         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4321                   x509, type, origCount);
4322         joa.reset(nullptr);
4323     } else if (origCount != count) {
4324         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4325                   count);
4326 
4327         ScopedLocalRef<jobjectArray> joa_copy(
4328                 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4329 
4330         for (int i = 0; i < count; i++) {
4331             ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4332             env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4333         }
4334 
4335         joa.reset(joa_copy.release());
4336     }
4337 
4338     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4339     return joa.release();
4340 }
4341 
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4342 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4343                                              CONSCRYPT_UNUSED jobject holder) {
4344     CHECK_ERROR_QUEUE_ON_RETURN;
4345     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4346     JNI_TRACE("X509_get_notBefore(%p)", x509);
4347 
4348     if (x509 == nullptr) {
4349         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4350         JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4351         return 0;
4352     }
4353 
4354     ASN1_TIME* notBefore = X509_get_notBefore(x509);
4355     JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4356     return reinterpret_cast<uintptr_t>(notBefore);
4357 }
4358 
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4359 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4360                                             CONSCRYPT_UNUSED jobject holder) {
4361     CHECK_ERROR_QUEUE_ON_RETURN;
4362     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4363     JNI_TRACE("X509_get_notAfter(%p)", x509);
4364 
4365     if (x509 == nullptr) {
4366         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4367         JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4368         return 0;
4369     }
4370 
4371     ASN1_TIME* notAfter = X509_get_notAfter(x509);
4372     JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4373     return reinterpret_cast<uintptr_t>(notAfter);
4374 }
4375 
4376 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4377 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4378                                           CONSCRYPT_UNUSED jobject holder) {
4379     CHECK_ERROR_QUEUE_ON_RETURN;
4380     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4381     JNI_TRACE("X509_get_version(%p)", x509);
4382 
4383     if (x509 == nullptr) {
4384         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4385         JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
4386         return 0;
4387     }
4388 
4389     // NOLINTNEXTLINE(runtime/int)
4390     long version = X509_get_version(x509);
4391     JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4392     return version;
4393 }
4394 
4395 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4396 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4397                                             const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4398     JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4399 
4400     if (x509Type == nullptr) {
4401         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4402         JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4403         return nullptr;
4404     }
4405 
4406     const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4407     bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4408     if (serialBn.get() == nullptr) {
4409         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4410         return nullptr;
4411     }
4412 
4413     ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4414     if (env->ExceptionCheck()) {
4415         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4416         return nullptr;
4417     }
4418 
4419     JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4420     return serialArray.release();
4421 }
4422 
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4423 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4424                                                      CONSCRYPT_UNUSED jobject holder) {
4425     CHECK_ERROR_QUEUE_ON_RETURN;
4426     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4427     JNI_TRACE("X509_get_serialNumber(%p)", x509);
4428 
4429     if (x509 == nullptr) {
4430         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4431         JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
4432         return nullptr;
4433     }
4434     return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4435 }
4436 
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4437 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
4438                                                              jlong x509RevokedRef) {
4439     CHECK_ERROR_QUEUE_ON_RETURN;
4440     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4441     JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4442 
4443     if (revoked == nullptr) {
4444         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4445         JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
4446         return 0;
4447     }
4448     return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
4449 }
4450 
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4451 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
4452                                      CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4453     CHECK_ERROR_QUEUE_ON_RETURN;
4454     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4455     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4456     JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4457 
4458     if (pkey == nullptr) {
4459         JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4460         return;
4461     }
4462 
4463     if (x509 == nullptr) {
4464         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4465         JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4466         return;
4467     }
4468 
4469     if (X509_verify(x509, pkey) != 1) {
4470         conscrypt::jniutil::throwExceptionFromBoringSSLError(
4471                 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
4472         JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4473         return;
4474     }
4475     JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4476 }
4477 
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4478 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
4479                                                  CONSCRYPT_UNUSED jobject holder) {
4480     CHECK_ERROR_QUEUE_ON_RETURN;
4481     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4482     JNI_TRACE("get_X509_tbs_cert(%p)", x509);
4483     // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
4484     return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
4485 }
4486 
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)4487 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
4488                                                              CONSCRYPT_UNUSED jobject holder,
4489                                                              jstring oidString) {
4490     CHECK_ERROR_QUEUE_ON_RETURN;
4491     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4492     JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
4493 
4494     if (x509 == nullptr) {
4495         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4496         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
4497         return nullptr;
4498     }
4499 
4500     bssl::UniquePtr<X509> copy(X509_dup(x509));
4501     if (copy == nullptr) {
4502         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
4503         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
4504         return nullptr;
4505     }
4506 
4507     ScopedUtfChars oid(env, oidString);
4508     if (oid.c_str() == nullptr) {
4509         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
4510         return nullptr;
4511     }
4512 
4513     bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
4514     if (obj.get() == nullptr) {
4515         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
4516                   oid.c_str());
4517         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4518                                            "Invalid OID.");
4519         ERR_clear_error();
4520         return nullptr;
4521     }
4522 
4523     int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
4524     if (extIndex == -1) {
4525         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
4526         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4527                                            "Extension not found.");
4528         return nullptr;
4529     }
4530 
4531     // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
4532     // cached encoding.
4533     X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
4534     return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
4535 }
4536 
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4537 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
4538                                            CONSCRYPT_UNUSED jobject holder) {
4539     CHECK_ERROR_QUEUE_ON_RETURN;
4540     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4541     JNI_TRACE("get_X509_ex_flags(%p)", x509);
4542 
4543     if (x509 == nullptr) {
4544         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4545         JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4546         return 0;
4547     }
4548 
4549     uint32_t flags = X509_get_extension_flags(x509);
4550     // X509_get_extension_flags sometimes leaves values in the error queue. See
4551     // https://crbug.com/boringssl/382.
4552     //
4553     // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
4554     // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
4555     // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
4556     // this JNI call to EXFLAG_CRITICAL.
4557     ERR_clear_error();
4558     return flags;
4559 }
4560 
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)4561 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
4562                                            CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
4563                                            CONSCRYPT_UNUSED jobject holder2) {
4564     CHECK_ERROR_QUEUE_ON_RETURN;
4565     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4566     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4567     JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4568 
4569     if (x509_1 == nullptr) {
4570         conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
4571         JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
4572         return 0;
4573     }
4574     if (x509_2 == nullptr) {
4575         conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
4576         JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
4577         return 0;
4578     }
4579     int ret = X509_check_issued(x509_1, x509_2);
4580     JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4581     return ret;
4582 }
4583 
get_X509_signature(X509 * x509)4584 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
4585     const ASN1_BIT_STRING* signature;
4586     X509_get0_signature(&signature, nullptr, x509);
4587     return signature;
4588 }
4589 
get_X509_CRL_signature(X509_CRL * crl)4590 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
4591     const ASN1_BIT_STRING* signature;
4592     X509_CRL_get0_signature(crl, &signature, nullptr);
4593     return signature;
4594 }
4595 
4596 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))4597 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
4598                                          const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
4599     JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4600 
4601     if (x509Type == nullptr) {
4602         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4603         JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4604         return nullptr;
4605     }
4606 
4607     const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
4608 
4609     ScopedLocalRef<jbyteArray> signatureArray(env,
4610                                               env->NewByteArray(ASN1_STRING_length(signature)));
4611     if (env->ExceptionCheck()) {
4612         JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4613         return nullptr;
4614     }
4615 
4616     ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4617     if (signatureBytes.get() == nullptr) {
4618         JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4619         return nullptr;
4620     }
4621 
4622     memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
4623 
4624     JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4625               ASN1_STRING_length(signature));
4626     return signatureArray.release();
4627 }
4628 
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4629 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
4630                                                   CONSCRYPT_UNUSED jobject holder) {
4631     CHECK_ERROR_QUEUE_ON_RETURN;
4632     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4633     JNI_TRACE("get_X509_signature(%p)", x509);
4634 
4635     if (x509 == nullptr) {
4636         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4637         JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
4638         return nullptr;
4639     }
4640     return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4641 }
4642 
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4643 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
4644                                                       CONSCRYPT_UNUSED jobject holder) {
4645     CHECK_ERROR_QUEUE_ON_RETURN;
4646     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4647     JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4648 
4649     if (crl == nullptr) {
4650         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4651         JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
4652         return nullptr;
4653     }
4654     return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4655 }
4656 
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)4657 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
4658                                                 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
4659                                                 CONSCRYPT_UNUSED jobject holder2) {
4660     CHECK_ERROR_QUEUE_ON_RETURN;
4661     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4662     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4663     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4664 
4665     if (x509crl == nullptr) {
4666         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4667         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4668         return 0;
4669     } else if (x509 == nullptr) {
4670         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4671         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4672         return 0;
4673     }
4674 
4675     X509_REVOKED* revoked = nullptr;
4676     int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4677     if (ret == 0) {
4678         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4679         return 0;
4680     }
4681 
4682     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4683     return reinterpret_cast<uintptr_t>(revoked);
4684 }
4685 
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)4686 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
4687                                                   CONSCRYPT_UNUSED jobject holder,
4688                                                   jbyteArray serialArray) {
4689     CHECK_ERROR_QUEUE_ON_RETURN;
4690     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4691     JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4692 
4693     if (x509crl == nullptr) {
4694         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4695         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4696         return 0;
4697     }
4698 
4699     bssl::UniquePtr<BIGNUM> serialBn(BN_new());
4700     if (serialBn.get() == nullptr) {
4701         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4702         return 0;
4703     }
4704 
4705     BIGNUM* serialBare = serialBn.get();
4706     if (!arrayToBignum(env, serialArray, &serialBare)) {
4707         if (!env->ExceptionCheck()) {
4708             conscrypt::jniutil::throwNullPointerException(env, "serial == null");
4709         }
4710         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4711         return 0;
4712     }
4713 
4714     bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
4715     if (serialInteger.get() == nullptr) {
4716         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4717         return 0;
4718     }
4719 
4720     X509_REVOKED* revoked = nullptr;
4721     int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4722     if (ret == 0) {
4723         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4724         return 0;
4725     }
4726 
4727     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4728     return reinterpret_cast<uintptr_t>(revoked);
4729 }
4730 
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4731 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
4732                                                     CONSCRYPT_UNUSED jobject holder) {
4733     CHECK_ERROR_QUEUE_ON_RETURN;
4734     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4735     JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4736 
4737     if (crl == nullptr) {
4738         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4739         JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
4740         return nullptr;
4741     }
4742 
4743     STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4744     if (stack == nullptr) {
4745         JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4746         return nullptr;
4747     }
4748 
4749     size_t size = sk_X509_REVOKED_num(stack);
4750 
4751     ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
4752     ScopedLongArrayRW revoked(env, revokedArray.get());
4753     for (size_t i = 0; i < size; i++) {
4754         X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4755         revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4756     }
4757 
4758     JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
4759     return revokedArray.release();
4760 }
4761 
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4762 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
4763                                             CONSCRYPT_UNUSED jobject holder) {
4764     CHECK_ERROR_QUEUE_ON_RETURN;
4765     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4766     JNI_TRACE("i2d_X509_CRL(%p)", crl);
4767 
4768     if (crl == nullptr) {
4769         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4770         JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
4771         return nullptr;
4772     }
4773     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
4774 }
4775 
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4776 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
4777                                        CONSCRYPT_UNUSED jobject holder) {
4778     CHECK_ERROR_QUEUE_ON_RETURN;
4779     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4780     JNI_TRACE("X509_CRL_free(%p)", crl);
4781 
4782     if (crl == nullptr) {
4783         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4784         JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4785         return;
4786     }
4787 
4788     X509_CRL_free(crl);
4789 }
4790 
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4791 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
4792                                         CONSCRYPT_UNUSED jobject holder) {
4793     CHECK_ERROR_QUEUE_ON_RETURN;
4794     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4795     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4796     JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4797 
4798     if (bio == nullptr) {
4799         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4800         JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4801         return;
4802     }
4803 
4804     if (crl == nullptr) {
4805         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4806         JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4807         return;
4808     }
4809 
4810     if (!X509_CRL_print(bio, crl)) {
4811         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
4812         JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4813         return;
4814     }
4815     JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4816 }
4817 
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4818 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
4819                                                      CONSCRYPT_UNUSED jobject holder) {
4820     CHECK_ERROR_QUEUE_ON_RETURN;
4821     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4822     JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4823 
4824     if (crl == nullptr) {
4825         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4826         JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
4827         return nullptr;
4828     }
4829 
4830     const X509_ALGOR* sig_alg;
4831     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4832     const ASN1_OBJECT* oid;
4833     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
4834     return ASN1_OBJECT_to_OID_string(env, oid);
4835 }
4836 
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)4837 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
4838     int param_type;
4839     const void* param_value;
4840     X509_ALGOR_get0(nullptr, &param_type, &param_value, algor);
4841 
4842     if (param_type == V_ASN1_UNDEF) {
4843         JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
4844         return nullptr;
4845     }
4846 
4847     // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
4848     // recreate it from the returned components.
4849     bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
4850     if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
4851         conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
4852         return nullptr;
4853     }
4854 
4855     return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
4856 }
4857 
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4858 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
4859                                                               CONSCRYPT_UNUSED jobject holder) {
4860     CHECK_ERROR_QUEUE_ON_RETURN;
4861     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4862     JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4863 
4864     if (crl == nullptr) {
4865         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4866         JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4867         return nullptr;
4868     }
4869 
4870     const X509_ALGOR* sig_alg;
4871     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4872     return get_X509_ALGOR_parameter(env, sig_alg);
4873 }
4874 
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4875 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
4876                                                         CONSCRYPT_UNUSED jobject holder) {
4877     CHECK_ERROR_QUEUE_ON_RETURN;
4878     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4879 
4880     if (crl == nullptr) {
4881         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4882         JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
4883         return nullptr;
4884     }
4885     JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4886     return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
4887 }
4888 
4889 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4890 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
4891                                               CONSCRYPT_UNUSED jobject holder) {
4892     CHECK_ERROR_QUEUE_ON_RETURN;
4893     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4894     JNI_TRACE("X509_CRL_get_version(%p)", crl);
4895 
4896     if (crl == nullptr) {
4897         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4898         JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
4899         return 0;
4900     }
4901     // NOLINTNEXTLINE(runtime/int)
4902     long version = X509_CRL_get_version(crl);
4903     JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4904     return version;
4905 }
4906 
4907 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4908           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)4909 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
4910     JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4911 
4912     if (x509Type == nullptr) {
4913         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4914         return nullptr;
4915     }
4916 
4917     ScopedUtfChars oid(env, oidString);
4918     if (oid.c_str() == nullptr) {
4919         return nullptr;
4920     }
4921 
4922     bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
4923     if (asn1.get() == nullptr) {
4924         JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4925         ERR_clear_error();
4926         return nullptr;
4927     }
4928 
4929     int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4930     if (extIndex == -1) {
4931         JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4932         return nullptr;
4933     }
4934 
4935     X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4936     JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4937     return ext;
4938 }
4939 
4940 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4941           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)4942 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
4943     X509_EXTENSION* ext =
4944             X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
4945     if (ext == nullptr) {
4946         JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4947         return nullptr;
4948     }
4949 
4950     JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
4951               X509_EXTENSION_get_data(ext));
4952     return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
4953                                               i2d_ASN1_OCTET_STRING);
4954 }
4955 
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)4956 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
4957                                            CONSCRYPT_UNUSED jobject holder, jstring oid) {
4958     CHECK_ERROR_QUEUE_ON_RETURN;
4959     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4960     JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4961 
4962     if (crl == nullptr) {
4963         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4964         JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
4965         return 0;
4966     }
4967     X509_EXTENSION* ext =
4968             X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
4969     JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4970     return reinterpret_cast<uintptr_t>(ext);
4971 }
4972 
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)4973 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4974                                                jstring oid) {
4975     CHECK_ERROR_QUEUE_ON_RETURN;
4976     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4977     JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4978     X509_EXTENSION* ext =
4979             X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
4980                     env, revoked, oid);
4981     JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4982     return reinterpret_cast<uintptr_t>(ext);
4983 }
4984 
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)4985 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4986     CHECK_ERROR_QUEUE_ON_RETURN;
4987     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4988     JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4989 
4990     if (revoked == nullptr) {
4991         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4992         JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4993         return 0;
4994     }
4995 
4996     X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4997     JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4998     return reinterpret_cast<uintptr_t>(dup);
4999 }
5000 
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5001 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5002                                                           jlong x509RevokedRef) {
5003     CHECK_ERROR_QUEUE_ON_RETURN;
5004     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5005     JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5006 
5007     if (revoked == nullptr) {
5008         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5009         JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5010         return 0;
5011     }
5012 
5013     JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5014               X509_REVOKED_get0_revocationDate(revoked));
5015     return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5016 }
5017 
5018 #ifdef __GNUC__
5019 #pragma GCC diagnostic push
5020 #pragma GCC diagnostic ignored "-Wwrite-strings"
5021 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5022 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5023                                             jlong x509RevokedRef) {
5024     CHECK_ERROR_QUEUE_ON_RETURN;
5025     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5026     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5027     JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5028 
5029     if (bio == nullptr) {
5030         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5031         JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5032         return;
5033     }
5034 
5035     if (revoked == nullptr) {
5036         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5037         JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5038         return;
5039     }
5040 
5041     BIO_printf(bio, "Serial Number: ");
5042     i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5043     BIO_printf(bio, "\nRevocation Date: ");
5044     ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5045     BIO_printf(bio, "\n");
5046     // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5047     // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5048     X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5049                             0);
5050 }
5051 #ifndef _WIN32
5052 #pragma GCC diagnostic pop
5053 #endif
5054 
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5055 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5056                                                     CONSCRYPT_UNUSED jobject holder) {
5057     CHECK_ERROR_QUEUE_ON_RETURN;
5058     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5059     JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5060 
5061     if (crl == nullptr) {
5062         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5063         JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5064         return nullptr;
5065     }
5066     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5067 }
5068 
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5069 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5070                                          CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5071     CHECK_ERROR_QUEUE_ON_RETURN;
5072     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5073     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5074     JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5075 
5076     if (pkey == nullptr) {
5077         JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5078         return;
5079     }
5080 
5081     if (crl == nullptr) {
5082         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5083         JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5084         return;
5085     }
5086 
5087     if (X509_CRL_verify(crl, pkey) != 1) {
5088         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5089         JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5090         return;
5091     }
5092     JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5093 }
5094 
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5095 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5096                                                   CONSCRYPT_UNUSED jobject holder) {
5097     CHECK_ERROR_QUEUE_ON_RETURN;
5098     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5099     JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5100 
5101     if (crl == nullptr) {
5102         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5103         JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5104         return 0;
5105     }
5106 
5107     ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5108     JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5109     return reinterpret_cast<uintptr_t>(lastUpdate);
5110 }
5111 
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5112 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5113                                                   CONSCRYPT_UNUSED jobject holder) {
5114     CHECK_ERROR_QUEUE_ON_RETURN;
5115     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5116     JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5117 
5118     if (crl == nullptr) {
5119         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5120         JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5121         return 0;
5122     }
5123 
5124     ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5125     JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5126     return reinterpret_cast<uintptr_t>(nextUpdate);
5127 }
5128 
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5129 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5130     CHECK_ERROR_QUEUE_ON_RETURN;
5131     X509_REVOKED* x509Revoked =
5132             reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5133     JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5134     return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5135 }
5136 
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5137 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5138     CHECK_ERROR_QUEUE_ON_RETURN;
5139     X509_EXTENSION* ext =
5140             reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5141 
5142     if (ext == nullptr) {
5143         conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5144         return 0;
5145     }
5146 
5147     return X509_supported_extension(ext);
5148 }
5149 
decimal_to_integer(const char * data,size_t len,int * out)5150 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5151     int ret = 0;
5152     for (size_t i = 0; i < len; i++) {
5153         ret *= 10;
5154         if (data[i] < '0' || data[i] > '9') {
5155             return false;
5156         }
5157         ret += data[i] - '0';
5158     }
5159     *out = ret;
5160     return true;
5161 }
5162 
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5163 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5164                                                jobject calendar) {
5165     CHECK_ERROR_QUEUE_ON_RETURN;
5166     ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5167     JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5168 
5169     if (asn1Time == nullptr) {
5170         conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5171         return;
5172     }
5173 
5174     if (!ASN1_TIME_check(asn1Time)) {
5175         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5176         return;
5177     }
5178 
5179     bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5180     if (gen.get() == nullptr) {
5181         conscrypt::jniutil::throwParsingException(env,
5182                                                   "ASN1_TIME_to_generalizedtime returned null");
5183         return;
5184     }
5185 
5186     if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5187         conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5188         return;
5189     }
5190 
5191     int year, mon, mday, hour, min, sec;
5192     const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5193     if (!decimal_to_integer(data, 4, &year) ||
5194         !decimal_to_integer(data + 4, 2, &mon) ||
5195         !decimal_to_integer(data + 6, 2, &mday) ||
5196         !decimal_to_integer(data + 8, 2, &hour) ||
5197         !decimal_to_integer(data + 10, 2, &min) ||
5198         !decimal_to_integer(data + 12, 2, &sec)) {
5199         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5200         return;
5201     }
5202 
5203     env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5204                         min, sec);
5205 }
5206 
5207 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5208 // functions so that they can be freed properly when finished.  This struct owns
5209 // all objects pointed to by its members.
5210 struct CbsHandle {
5211     // A pointer to the CBS.
5212     std::unique_ptr<CBS> cbs;
5213     // A pointer to the data held by the CBS.  If the data held by the CBS
5214     // is owned by a different CbsHandle, data will be null.
5215     std::unique_ptr<unsigned char[]> data;
5216 };
5217 
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5218 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5219     CHECK_ERROR_QUEUE_ON_RETURN;
5220     JNI_TRACE("asn1_read_init(%p)", data);
5221 
5222     ScopedByteArrayRO bytes(env, data);
5223     if (bytes.get() == nullptr) {
5224         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5225         return 0;
5226     }
5227 
5228     std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5229     cbs->data.reset(new unsigned char[bytes.size()]);
5230     memcpy(cbs->data.get(), bytes.get(), bytes.size());
5231 
5232     cbs->cbs.reset(new CBS());
5233     CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5234     JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5235     return reinterpret_cast<uintptr_t>(cbs.release());
5236 }
5237 
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5238 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5239     CHECK_ERROR_QUEUE_ON_RETURN;
5240     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5241     JNI_TRACE("asn1_read_sequence(%p)", cbs);
5242 
5243     std::unique_ptr<CbsHandle> seq(new CbsHandle());
5244     seq->cbs.reset(new CBS());
5245     if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5246         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5247         return 0;
5248     }
5249     JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5250     return reinterpret_cast<uintptr_t>(seq.release());
5251 }
5252 
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5253 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5254                                                    jlong cbsRef, jint tag) {
5255     CHECK_ERROR_QUEUE_ON_RETURN;
5256     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5257     JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5258 
5259     int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5260                                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5261     JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5262     return result ? JNI_TRUE : JNI_FALSE;
5263 }
5264 
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5265 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5266     CHECK_ERROR_QUEUE_ON_RETURN;
5267     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5268     JNI_TRACE("asn1_read_tagged(%p)", cbs);
5269 
5270     std::unique_ptr<CbsHandle> tag(new CbsHandle());
5271     tag->cbs.reset(new CBS());
5272     if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5273         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5274         return 0;
5275     }
5276     JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5277     return reinterpret_cast<uintptr_t>(tag.release());
5278 }
5279 
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5280 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5281     CHECK_ERROR_QUEUE_ON_RETURN;
5282     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5283     JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5284 
5285     std::unique_ptr<CBS> str(new CBS());
5286     if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5287         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5288         return 0;
5289     }
5290     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5291     if (out.get() == nullptr) {
5292         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5293         return 0;
5294     }
5295     ScopedByteArrayRW outBytes(env, out.get());
5296     if (outBytes.get() == nullptr) {
5297         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5298         return 0;
5299     }
5300     memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5301     JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5302     return out.release();
5303 }
5304 
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5305 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5306     CHECK_ERROR_QUEUE_ON_RETURN;
5307     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5308     JNI_TRACE("asn1_read_uint64(%p)", cbs);
5309 
5310     // NOLINTNEXTLINE(runtime/int)
5311     uint64_t value;
5312     if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5313         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5314         return 0;
5315     }
5316     return value;
5317 }
5318 
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5319 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5320     CHECK_ERROR_QUEUE_ON_RETURN;
5321     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5322     JNI_TRACE("asn1_read_null(%p)", cbs);
5323 
5324     CBS null_holder;
5325     if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5326         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5327     }
5328 }
5329 
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5330 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5331     CHECK_ERROR_QUEUE_ON_RETURN;
5332     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5333     JNI_TRACE("asn1_read_oid(%p)", cbs);
5334 
5335     CBS oid_cbs;
5336     if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5337         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5338         return nullptr;
5339     }
5340     int nid = OBJ_cbs2nid(&oid_cbs);
5341     if (nid == NID_undef) {
5342         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5343         return nullptr;
5344     }
5345     const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5346     if (obj == nullptr) {
5347         conscrypt::jniutil::throwIOException(env,
5348                                              "Error reading ASN.1 encoding: "
5349                                              "Could not find ASN1_OBJECT for NID");
5350         return nullptr;
5351     }
5352     return ASN1_OBJECT_to_OID_string(env, obj);
5353 }
5354 
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5355 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5356                                                 jlong cbsRef) {
5357     CHECK_ERROR_QUEUE_ON_RETURN;
5358     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5359     JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5360 
5361     bool empty = (CBS_len(cbs->cbs.get()) == 0);
5362     JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5363     return empty;
5364 }
5365 
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5366 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5367     CHECK_ERROR_QUEUE_ON_RETURN;
5368     if (cbsRef == 0) {
5369         JNI_TRACE("asn1_read_free(0)");
5370         return;
5371     }
5372     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5373     JNI_TRACE("asn1_read_free(%p)", cbs);
5374     delete cbs;
5375 }
5376 
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5377 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5378     CHECK_ERROR_QUEUE_ON_RETURN;
5379     JNI_TRACE("asn1_write_init");
5380     std::unique_ptr<CBB> cbb(new CBB());
5381     if (!CBB_init(cbb.get(), 128)) {
5382         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5383         return 0;
5384     }
5385     JNI_TRACE("asn1_write_init => %p", cbb.get());
5386     return reinterpret_cast<uintptr_t>(cbb.release());
5387 }
5388 
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5389 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5390     CHECK_ERROR_QUEUE_ON_RETURN;
5391     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5392     JNI_TRACE("asn1_write_sequence(%p)", cbb);
5393 
5394     std::unique_ptr<CBB> seq(new CBB());
5395     if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5396         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5397         return 0;
5398     }
5399     JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5400     return reinterpret_cast<uintptr_t>(seq.release());
5401 }
5402 
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5403 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5404     CHECK_ERROR_QUEUE_ON_RETURN;
5405     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5406     JNI_TRACE("asn1_write_tag(%p)", cbb);
5407 
5408     std::unique_ptr<CBB> tag_holder(new CBB());
5409     if (!CBB_add_asn1(cbb, tag_holder.get(),
5410                       CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5411         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5412         return 0;
5413     }
5414     JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5415     return reinterpret_cast<uintptr_t>(tag_holder.release());
5416 }
5417 
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5418 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5419                                                 jbyteArray data) {
5420     CHECK_ERROR_QUEUE_ON_RETURN;
5421     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5422     JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5423 
5424     ScopedByteArrayRO bytes(env, data);
5425     if (bytes.get() == nullptr) {
5426         JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5427         return;
5428     }
5429 
5430     std::unique_ptr<CBB> octetstring(new CBB());
5431     if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5432         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5433         return;
5434     }
5435     if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5436                        bytes.size())) {
5437         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5438         return;
5439     }
5440     if (!CBB_flush(cbb)) {
5441         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5442         return;
5443     }
5444 }
5445 
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)5446 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
5447     CHECK_ERROR_QUEUE_ON_RETURN;
5448     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5449     JNI_TRACE("asn1_write_uint64(%p)", cbb);
5450 
5451     if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
5452         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5453         return;
5454     }
5455 }
5456 
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)5457 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
5458     CHECK_ERROR_QUEUE_ON_RETURN;
5459     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5460     JNI_TRACE("asn1_write_null(%p)", cbb);
5461 
5462     CBB null_holder;
5463     if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
5464         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5465         return;
5466     }
5467     if (!CBB_flush(cbb)) {
5468         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5469         return;
5470     }
5471 }
5472 
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)5473 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
5474     CHECK_ERROR_QUEUE_ON_RETURN;
5475     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5476     JNI_TRACE("asn1_write_oid(%p)", cbb);
5477 
5478     ScopedUtfChars oid_chars(env, oid);
5479     if (oid_chars.c_str() == nullptr) {
5480         return;
5481     }
5482 
5483     int nid = OBJ_txt2nid(oid_chars.c_str());
5484     if (nid == NID_undef) {
5485         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5486         return;
5487     }
5488 
5489     if (!OBJ_nid2cbb(cbb, nid)) {
5490         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5491         return;
5492     }
5493 }
5494 
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)5495 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
5496     CHECK_ERROR_QUEUE_ON_RETURN;
5497     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5498     JNI_TRACE("asn1_write_flush(%p)", cbb);
5499 
5500     if (!CBB_flush(cbb)) {
5501         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5502         return;
5503     }
5504 }
5505 
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)5506 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
5507     CHECK_ERROR_QUEUE_ON_RETURN;
5508     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5509     JNI_TRACE("asn1_write_finish(%p)", cbb);
5510 
5511     uint8_t* data;
5512     size_t data_len;
5513     if (!CBB_finish(cbb, &data, &data_len)) {
5514         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5515         return 0;
5516     }
5517     bssl::UniquePtr<uint8_t> data_storage(data);
5518     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
5519     if (out.get() == nullptr) {
5520         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5521         return 0;
5522     }
5523     ScopedByteArrayRW outBytes(env, out.get());
5524     if (outBytes.get() == nullptr) {
5525         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5526         return 0;
5527     }
5528     memcpy(outBytes.get(), data, data_len);
5529     return out.release();
5530 }
5531 
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5532 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5533     CHECK_ERROR_QUEUE_ON_RETURN;
5534     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5535     JNI_TRACE("asn1_write_cleanup(%p)", cbb);
5536 
5537     CBB_cleanup(cbb);
5538 }
5539 
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5540 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5541     CHECK_ERROR_QUEUE_ON_RETURN;
5542     if (cbbRef == 0) {
5543         JNI_TRACE("asn1_write_free(0)");
5544         return;
5545     }
5546     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5547     JNI_TRACE("asn1_write_free(%p)", cbb);
5548     delete cbb;
5549 }
5550 
5551 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5552 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5553     BIO* bio = to_BIO(env, bioRef);
5554     JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5555 
5556     if (bio == nullptr) {
5557         return 0;
5558     }
5559 
5560     T* x = d2i_func(bio, nullptr);
5561     if (x == nullptr) {
5562         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
5563         return 0;
5564     }
5565 
5566     return reinterpret_cast<uintptr_t>(x);
5567 }
5568 
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5569 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5570     CHECK_ERROR_QUEUE_ON_RETURN;
5571     return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5572 }
5573 
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5574 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5575     CHECK_ERROR_QUEUE_ON_RETURN;
5576     return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5577 }
5578 
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5579 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5580     CHECK_ERROR_QUEUE_ON_RETURN;
5581     ScopedByteArrayRO bytes(env, certBytes);
5582     if (bytes.get() == nullptr) {
5583         JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
5584         return 0;
5585     }
5586 
5587     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
5588     // NOLINTNEXTLINE(runtime/int)
5589     X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
5590     if (x == nullptr) {
5591         conscrypt::jniutil::throwExceptionFromBoringSSLError(
5592                 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
5593         return 0;
5594     }
5595     return reinterpret_cast<uintptr_t>(x);
5596 }
5597 
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5598 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
5599                                         CONSCRYPT_UNUSED jobject holder) {
5600     CHECK_ERROR_QUEUE_ON_RETURN;
5601     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5602     JNI_TRACE("i2d_X509(%p)", x509);
5603 
5604     if (x509 == nullptr) {
5605         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5606         JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
5607         return nullptr;
5608     }
5609     return ASN1ToByteArray<X509>(env, x509, i2d_X509);
5610 }
5611 
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5612 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
5613                                                CONSCRYPT_UNUSED jobject holder) {
5614     CHECK_ERROR_QUEUE_ON_RETURN;
5615     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5616     JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5617 
5618     if (x509 == nullptr) {
5619         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5620         JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
5621         return nullptr;
5622     }
5623     return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
5624 }
5625 
5626 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)5627 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
5628     BIO* bio = to_BIO(env, bioRef);
5629     JNI_TRACE("PEM_to_jlong(%p)", bio);
5630 
5631     if (bio == nullptr) {
5632         JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
5633         return 0;
5634     }
5635 
5636     T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
5637     if (x == nullptr) {
5638         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
5639         JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
5640         return 0;
5641     }
5642 
5643     JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
5644     return reinterpret_cast<uintptr_t>(x);
5645 }
5646 
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5647 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5648     CHECK_ERROR_QUEUE_ON_RETURN;
5649     // NOLINTNEXTLINE(runtime/int)
5650     JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
5651     return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5652 }
5653 
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5654 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5655     CHECK_ERROR_QUEUE_ON_RETURN;
5656     // NOLINTNEXTLINE(runtime/int)
5657     JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
5658     return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5659 }
5660 
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)5661 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
5662     CHECK_ERROR_QUEUE_ON_RETURN;
5663     // NOLINTNEXTLINE(runtime/int)
5664     JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
5665     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
5666 }
5667 
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)5668 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
5669     CHECK_ERROR_QUEUE_ON_RETURN;
5670     // NOLINTNEXTLINE(runtime/int)
5671     JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
5672     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
5673 }
5674 
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)5675 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
5676     if (certs == nullptr) {
5677         return nullptr;
5678     }
5679 
5680     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5681     size_t size = sk_X509_num(certs);
5682     ref_array.reset(env->NewLongArray(size));
5683     ScopedLongArrayRW items(env, ref_array.get());
5684     for (size_t i = 0; i < size; i++) {
5685         X509* cert = sk_X509_value(certs, i);
5686         X509_up_ref(cert);
5687         items[i] = reinterpret_cast<uintptr_t>(cert);
5688     }
5689 
5690     JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
5691     return ref_array.release();
5692 }
5693 
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)5694 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
5695     if (crls == nullptr) {
5696         return nullptr;
5697     }
5698 
5699     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5700     size_t size = sk_X509_CRL_num(crls);
5701     ref_array.reset(env->NewLongArray(size));
5702     ScopedLongArrayRW items(env, ref_array.get());
5703     for (size_t i = 0; i < size; i++) {
5704         X509_CRL* crl = sk_X509_CRL_value(crls, i);
5705         X509_CRL_up_ref(crl);
5706         items[i] = reinterpret_cast<uintptr_t>(crl);
5707     }
5708 
5709     JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
5710     return ref_array.release();
5711 }
5712 
5713 #define PKCS7_CERTS 1
5714 #define PKCS7_CRLS 2
5715 
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5716 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5717     CHECK_ERROR_QUEUE_ON_RETURN;
5718     STACK_OF(X509)* stack = sk_X509_new_null();
5719 
5720     ScopedLongArrayRO certs(env, certsArray);
5721     for (size_t i = 0; i < certs.size(); i++) {
5722         X509* item = reinterpret_cast<X509*>(certs[i]);
5723         if (sk_X509_push(stack, item) == 0) {
5724             sk_X509_free(stack);
5725             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
5726             return nullptr;
5727         }
5728     }
5729 
5730     bssl::ScopedCBB out;
5731     CBB_init(out.get(), 1024 * certs.size());
5732     if (!PKCS7_bundle_certificates(out.get(), stack)) {
5733         sk_X509_free(stack);
5734         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
5735         return nullptr;
5736     }
5737 
5738     sk_X509_free(stack);
5739 
5740     return CBBToByteArray(env, out.get());
5741 }
5742 
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5743 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5744     CHECK_ERROR_QUEUE_ON_RETURN;
5745     BIO* bio = to_BIO(env, bioRef);
5746     JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5747 
5748     if (bio == nullptr) {
5749         JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5750         return nullptr;
5751     }
5752 
5753     if (which == PKCS7_CERTS) {
5754         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5755         if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
5756             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
5757             return nullptr;
5758         }
5759         return X509s_to_ItemArray(env, outCerts.get());
5760     } else if (which == PKCS7_CRLS) {
5761         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5762         if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
5763             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
5764             return nullptr;
5765         }
5766         return X509_CRLs_to_ItemArray(env, outCRLs.get());
5767     } else {
5768         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5769         return nullptr;
5770     }
5771 }
5772 
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5773 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5774     CHECK_ERROR_QUEUE_ON_RETURN;
5775     BIO* bio = to_BIO(env, bioRef);
5776     JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5777 
5778     if (bio == nullptr) {
5779         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5780         return nullptr;
5781     }
5782 
5783     uint8_t* data;
5784     size_t len;
5785     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5786         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
5787                 conscrypt::jniutil::throwParsingException);
5788         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
5789         return nullptr;
5790     }
5791     bssl::UniquePtr<uint8_t> data_storage(data);
5792 
5793     CBS cbs;
5794     CBS_init(&cbs, data, len);
5795 
5796     if (which == PKCS7_CERTS) {
5797         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5798         if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
5799             conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
5800                     "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
5801             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
5802             return nullptr;
5803         }
5804         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
5805         return X509s_to_ItemArray(env, outCerts.get());
5806     } else if (which == PKCS7_CRLS) {
5807         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5808         if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
5809             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
5810                     conscrypt::jniutil::throwParsingException);
5811             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
5812             return nullptr;
5813         }
5814         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
5815         return X509_CRLs_to_ItemArray(env, outCRLs.get());
5816     } else {
5817         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5818         return nullptr;
5819     }
5820 }
5821 
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)5822 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5823     CHECK_ERROR_QUEUE_ON_RETURN;
5824     BIO* bio = to_BIO(env, bioRef);
5825     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5826 
5827     if (bio == nullptr) {
5828         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
5829         return nullptr;
5830     }
5831 
5832     uint8_t* data;
5833     size_t len;
5834     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5835         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
5836                 conscrypt::jniutil::throwParsingException);
5837         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
5838         return nullptr;
5839     }
5840     bssl::UniquePtr<uint8_t> data_storage(data);
5841 
5842     bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
5843     if (path.get() == nullptr) {
5844         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
5845         return nullptr;
5846     }
5847 
5848     CBS cbs, sequence;
5849     CBS_init(&cbs, data, len);
5850     if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
5851         conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5852         ERR_clear_error();
5853         return nullptr;
5854     }
5855 
5856     while (CBS_len(&sequence) > 0) {
5857         CBS child;
5858         if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
5859             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5860             ERR_clear_error();
5861             return nullptr;
5862         }
5863 
5864         const uint8_t* tmp = CBS_data(&child);
5865         // NOLINTNEXTLINE(runtime/int)
5866         bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
5867         if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
5868             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5869             ERR_clear_error();
5870             return nullptr;
5871         }
5872 
5873         if (!sk_X509_push(path.get(), cert.get())) {
5874             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
5875             return nullptr;
5876         }
5877         OWNERSHIP_TRANSFERRED(cert);
5878     }
5879 
5880     size_t size = sk_X509_num(path.get());
5881 
5882     ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
5883     ScopedLongArrayRW certs(env, certArray.get());
5884     for (size_t i = 0; i < size; i++) {
5885         X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5886         certs[i] = reinterpret_cast<uintptr_t>(item);
5887     }
5888 
5889     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
5890     return certArray.release();
5891 }
5892 
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5893 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5894     CHECK_ERROR_QUEUE_ON_RETURN;
5895     JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5896     ScopedLongArrayRO certsArray(env, certs);
5897     if (certsArray.get() == nullptr) {
5898         JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5899         return nullptr;
5900     }
5901 
5902     bssl::ScopedCBB result;
5903     CBB seq_contents;
5904     if (!CBB_init(result.get(), 2048 * certsArray.size())) {
5905         JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
5906         return nullptr;
5907     }
5908     if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
5909         return nullptr;
5910     }
5911 
5912     for (size_t i = 0; i < certsArray.size(); i++) {
5913         X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5914         uint8_t* buf;
5915         int len = i2d_X509(x509, nullptr);
5916 
5917         if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
5918             i2d_X509(x509, &buf) < 0) {
5919             return nullptr;
5920         }
5921     }
5922 
5923     return CBBToByteArray(env, result.get());
5924 }
5925 
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5926 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
5927                                    CONSCRYPT_UNUSED jobject holder) {
5928     CHECK_ERROR_QUEUE_ON_RETURN;
5929     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5930     JNI_TRACE("X509_free(%p)", x509);
5931 
5932     if (x509 == nullptr) {
5933         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5934         JNI_TRACE("X509_free(%p) => x509 == null", x509);
5935         return;
5936     }
5937 
5938     X509_free(x509);
5939 }
5940 
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5941 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
5942                                   CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5943                                   CONSCRYPT_UNUSED jobject holder2) {
5944     CHECK_ERROR_QUEUE_ON_RETURN;
5945     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5946     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5947     JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5948 
5949     if (x509_1 == nullptr) {
5950         conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
5951         JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5952         return -1;
5953     }
5954 
5955     if (x509_2 == nullptr) {
5956         conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
5957         JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5958         return -1;
5959     }
5960 
5961     int ret = X509_cmp(x509_1, x509_2);
5962     JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5963     return ret;
5964 }
5965 
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)5966 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5967                                        CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
5968                                        jlong certflagJava) {
5969     CHECK_ERROR_QUEUE_ON_RETURN;
5970     BIO* bio = to_BIO(env, bioRef);
5971     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5972     // NOLINTNEXTLINE(runtime/int)
5973     unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
5974     // NOLINTNEXTLINE(runtime/int)
5975     unsigned long certflag = static_cast<unsigned long>(certflagJava);
5976     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5977 
5978     if (bio == nullptr) {
5979         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5980         return;
5981     }
5982 
5983     if (x509 == nullptr) {
5984         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5985         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5986         return;
5987     }
5988 
5989     if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5990         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
5991         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5992         return;
5993     }
5994     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5995 }
5996 
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5997 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
5998                                           CONSCRYPT_UNUSED jobject holder) {
5999     CHECK_ERROR_QUEUE_ON_RETURN;
6000     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6001     JNI_TRACE("X509_get_pubkey(%p)", x509);
6002 
6003     if (x509 == nullptr) {
6004         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6005         JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6006         return 0;
6007     }
6008 
6009     bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6010     if (pkey.get() == nullptr) {
6011         const uint32_t last_error = ERR_peek_last_error();
6012         const uint32_t first_error = ERR_peek_error();
6013         if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6014              ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6015             (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6016              ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6017             ERR_clear_error();
6018             conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6019             return 0;
6020         }
6021 
6022         conscrypt::jniutil::throwExceptionFromBoringSSLError(
6023                 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6024         return 0;
6025     }
6026 
6027     JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6028     return reinterpret_cast<uintptr_t>(pkey.release());
6029 }
6030 
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6031 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6032                                                     CONSCRYPT_UNUSED jobject holder) {
6033     CHECK_ERROR_QUEUE_ON_RETURN;
6034     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6035     JNI_TRACE("X509_get_issuer_name(%p)", x509);
6036 
6037     if (x509 == nullptr) {
6038         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6039         JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6040         return nullptr;
6041     }
6042     return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6043 }
6044 
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6045 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6046                                                      CONSCRYPT_UNUSED jobject holder) {
6047     CHECK_ERROR_QUEUE_ON_RETURN;
6048     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6049     JNI_TRACE("X509_get_subject_name(%p)", x509);
6050 
6051     if (x509 == nullptr) {
6052         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6053         JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6054         return nullptr;
6055     }
6056     return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6057 }
6058 
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6059 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6060                                                 CONSCRYPT_UNUSED jobject holder) {
6061     CHECK_ERROR_QUEUE_ON_RETURN;
6062     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6063     JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6064 
6065     if (x509 == nullptr) {
6066         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6067         JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6068         return nullptr;
6069     }
6070 
6071     X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6072     ASN1_OBJECT* algorithm;
6073     X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6074     return ASN1_OBJECT_to_OID_string(env, algorithm);
6075 }
6076 
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6077 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6078                                                  CONSCRYPT_UNUSED jobject holder) {
6079     CHECK_ERROR_QUEUE_ON_RETURN;
6080     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6081     JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6082 
6083     if (x509 == nullptr) {
6084         conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6085         JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6086         return nullptr;
6087     }
6088 
6089     const X509_ALGOR* sig_alg;
6090     X509_get0_signature(nullptr, &sig_alg, x509);
6091     const ASN1_OBJECT* oid;
6092     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6093     return ASN1_OBJECT_to_OID_string(env, oid);
6094 }
6095 
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6096 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6097                                                           CONSCRYPT_UNUSED jobject holder) {
6098     CHECK_ERROR_QUEUE_ON_RETURN;
6099     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6100     JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6101 
6102     if (x509 == nullptr) {
6103         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6104         JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6105         return nullptr;
6106     }
6107 
6108     const X509_ALGOR* sig_alg;
6109     X509_get0_signature(nullptr, &sig_alg, x509);
6110     return get_X509_ALGOR_parameter(env, sig_alg);
6111 }
6112 
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6113 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6114                                                      CONSCRYPT_UNUSED jobject holder) {
6115     CHECK_ERROR_QUEUE_ON_RETURN;
6116     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6117     JNI_TRACE("get_X509_issuerUID(%p)", x509);
6118 
6119     if (x509 == nullptr) {
6120         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6121         JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6122         return nullptr;
6123     }
6124 
6125     const ASN1_BIT_STRING* issuer_uid;
6126     X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6127     if (issuer_uid == nullptr) {
6128         JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6129         return nullptr;
6130     }
6131 
6132     return ASN1BitStringToBooleanArray(env, issuer_uid);
6133 }
6134 
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6135 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6136                                                       CONSCRYPT_UNUSED jobject holder) {
6137     CHECK_ERROR_QUEUE_ON_RETURN;
6138     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6139     JNI_TRACE("get_X509_subjectUID(%p)", x509);
6140 
6141     if (x509 == nullptr) {
6142         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6143         JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6144         return nullptr;
6145     }
6146 
6147     const ASN1_BIT_STRING* subject_uid;
6148     X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6149     if (subject_uid == nullptr) {
6150         JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6151         return nullptr;
6152     }
6153 
6154     return ASN1BitStringToBooleanArray(env, subject_uid);
6155 }
6156 
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6157 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6158                                                      CONSCRYPT_UNUSED jobject holder) {
6159     CHECK_ERROR_QUEUE_ON_RETURN;
6160     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6161     JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6162 
6163     if (x509 == nullptr) {
6164         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6165         JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6166         return nullptr;
6167     }
6168 
6169     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6170     // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6171     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6172     bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6173             static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6174     if (bitStr.get() == nullptr) {
6175         JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6176         ERR_clear_error();
6177         return nullptr;
6178     }
6179 
6180     return ASN1BitStringToBooleanArray(env, bitStr.get());
6181 }
6182 
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6183 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6184                                                      CONSCRYPT_UNUSED jobject holder) {
6185     CHECK_ERROR_QUEUE_ON_RETURN;
6186     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6187     JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6188 
6189     if (x509 == nullptr) {
6190         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6191         JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6192         return nullptr;
6193     }
6194 
6195     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6196     // |ERR_clear_error|, and throw CertificateParsingException.
6197     bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6198             X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6199     if (objArray.get() == nullptr) {
6200         JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6201         ERR_clear_error();
6202         return nullptr;
6203     }
6204 
6205     size_t size = sk_ASN1_OBJECT_num(objArray.get());
6206     ScopedLocalRef<jobjectArray> exKeyUsage(
6207             env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6208                                      nullptr));
6209     if (exKeyUsage.get() == nullptr) {
6210         return nullptr;
6211     }
6212 
6213     for (size_t i = 0; i < size; i++) {
6214         ScopedLocalRef<jstring> oidStr(
6215                 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6216         env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6217     }
6218 
6219     JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6220     return exKeyUsage.release();
6221 }
6222 
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6223 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6224                                              CONSCRYPT_UNUSED jobject holder) {
6225     CHECK_ERROR_QUEUE_ON_RETURN;
6226     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6227     JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6228 
6229     if (x509 == nullptr) {
6230         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6231         JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6232         return 0;
6233     }
6234 
6235     // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6236     // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6237     // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6238     // the constructor even if |EXFLAG_INVALID| is set.
6239     //
6240     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6241     // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6242     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6243     bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6244             X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6245     if (basic_constraints == nullptr) {
6246         JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6247         ERR_clear_error();
6248         return -1;
6249     }
6250 
6251     if (basic_constraints->pathlen == nullptr) {
6252         JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6253         return -1;
6254     }
6255 
6256     if (!basic_constraints->ca) {
6257         // Path length constraints are only valid for CA certificates.
6258         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6259         JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6260         return -1;
6261     }
6262 
6263     if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6264         // Path length constraints may not be negative.
6265         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6266         JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6267         return -1;
6268     }
6269 
6270     long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6271     if (pathlen == -1 || pathlen > INT_MAX) {
6272         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6273         // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6274         // constraint is plausible, but Chromium rejects all values above 255.
6275         JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6276         return -1;
6277     }
6278 
6279     JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6280     return pathlen;
6281 }
6282 
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6283 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6284                                                 CONSCRYPT_UNUSED jobject holder,
6285                                                 jstring oidString) {
6286     CHECK_ERROR_QUEUE_ON_RETURN;
6287     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6288     JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6289     return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6290 }
6291 
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6292 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6293                                                     CONSCRYPT_UNUSED jobject holder,
6294                                                     jstring oidString) {
6295     CHECK_ERROR_QUEUE_ON_RETURN;
6296     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6297     JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6298 
6299     if (crl == nullptr) {
6300         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
6301         JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
6302         return nullptr;
6303     }
6304     return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6305                                                                                      oidString);
6306 }
6307 
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6308 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6309                                                         jstring oidString) {
6310     CHECK_ERROR_QUEUE_ON_RETURN;
6311     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6312     JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6313 
6314     if (revoked == nullptr) {
6315         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
6316         JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
6317         return nullptr;
6318     }
6319     return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6320             env, revoked, oidString);
6321 }
6322 
6323 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6324           X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6325 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6326     T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6327     JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6328 
6329     if (x509 == nullptr) {
6330         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6331         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6332         return nullptr;
6333     }
6334 
6335     int lastPos = -1;
6336     int count = 0;
6337     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6338         count++;
6339     }
6340 
6341     JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6342 
6343     ScopedLocalRef<jobjectArray> joa(
6344             env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6345     if (joa.get() == nullptr) {
6346         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6347         return nullptr;
6348     }
6349 
6350     lastPos = -1;
6351     count = 0;
6352     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6353         X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6354 
6355         ScopedLocalRef<jstring> extOid(
6356                 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6357         if (extOid.get() == nullptr) {
6358             JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6359             return nullptr;
6360         }
6361 
6362         env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6363     }
6364 
6365     JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6366     return joa.release();
6367 }
6368 
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6369 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6370                                                    CONSCRYPT_UNUSED jobject holder, jint critical) {
6371     CHECK_ERROR_QUEUE_ON_RETURN;
6372     // NOLINTNEXTLINE(runtime/int)
6373     JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6374     return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6375                                                                                critical);
6376 }
6377 
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6378 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6379                                                        CONSCRYPT_UNUSED jobject holder,
6380                                                        jint critical) {
6381     CHECK_ERROR_QUEUE_ON_RETURN;
6382     // NOLINTNEXTLINE(runtime/int)
6383     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6384     return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6385             env, x509CrlRef, critical);
6386 }
6387 
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6388 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6389                                                            jlong x509RevokedRef, jint critical) {
6390     CHECK_ERROR_QUEUE_ON_RETURN;
6391     // NOLINTNEXTLINE(runtime/int)
6392     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6393     return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6394                                  X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6395 }
6396 
6397 /**
6398  * Based on example logging call back from SSL_CTX_set_info_callback man page
6399  */
info_callback_LOG(const SSL * s,int where,int ret)6400 static void info_callback_LOG(const SSL* s, int where, int ret) {
6401     int w = where & ~SSL_ST_MASK;
6402     const char* str;
6403     if (w & SSL_ST_CONNECT) {
6404         str = "SSL_connect";
6405     } else if (w & SSL_ST_ACCEPT) {
6406         str = "SSL_accept";
6407     } else {
6408         str = "undefined";
6409     }
6410 
6411     if (where & SSL_CB_LOOP) {
6412         JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6413     } else if (where & SSL_CB_ALERT) {
6414         str = (where & SSL_CB_READ) ? "read" : "write";
6415         JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6416                   SSL_alert_desc_string_long(ret));
6417     } else if (where & SSL_CB_EXIT) {
6418         if (ret == 0) {
6419             JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6420                       SSL_state_string_long(s));
6421         } else if (ret < 0) {
6422             JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6423                       SSL_state_string_long(s));
6424         } else if (ret == 1) {
6425             JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6426                       SSL_state_string_long(s));
6427         } else {
6428             JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6429                       SSL_state_string_long(s));
6430         }
6431     } else if (where & SSL_CB_HANDSHAKE_START) {
6432         JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6433                   SSL_state_string_long(s));
6434     } else if (where & SSL_CB_HANDSHAKE_DONE) {
6435         JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6436                   SSL_state_string_long(s));
6437     } else {
6438         JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6439                   SSL_state_string_long(s));
6440     }
6441 }
6442 
6443 #ifdef _WIN32
6444 
6445 /**
6446  * Dark magic helper function that checks, for a given SSL session, whether it
6447  * can SSL_read() or SSL_write() without blocking. Takes into account any
6448  * concurrent attempts to close the SSLSocket from the Java side. This is
6449  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6450  * while thread #2 is sitting in a blocking read or write. The type argument
6451  * specifies whether we are waiting for readability or writability. It expects
6452  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6453  * only need to wait in case one of these problems occurs.
6454  *
6455  * @param env
6456  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6457  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6458  * @param appData The application data structure with mutex info etc.
6459  * @param timeout_millis The timeout value for select call, with the special value
6460  *                0 meaning no timeout at all (wait indefinitely). Note: This is
6461  *                the Java semantics of the timeout value, not the usual
6462  *                select() semantics.
6463  * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
6464  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6465 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6466                      int timeout_millis) {
6467     int result = -1;
6468 
6469     NetFd fd(env, fdObject);
6470     do {
6471         if (fd.isClosed()) {
6472             result = THROWN_EXCEPTION;
6473             break;
6474         }
6475 
6476         WSAEVENT events[2];
6477         events[0] = appData->interruptEvent;
6478         events[1] = WSACreateEvent();
6479         if (events[1] == WSA_INVALID_EVENT) {
6480             JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
6481             break;
6482         }
6483 
6484         if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
6485                                                         FD_CLOSE) == SOCKET_ERROR) {
6486             JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
6487             break;
6488         }
6489 
6490         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6491                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6492                   timeout_millis);
6493 
6494         int rc = WSAWaitForMultipleEvents(
6495                 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
6496         if (rc == WSA_WAIT_FAILED) {
6497             JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
6498             result = -1;
6499         } else if (rc == WSA_WAIT_TIMEOUT) {
6500             result = 0;
6501         } else {
6502             result = 1;
6503         }
6504         WSACloseEvent(events[1]);
6505     } while (0);
6506 
6507     JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
6508               (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
6509               result);
6510 
6511     std::lock_guard<std::mutex> appDataLock(appData->mutex);
6512     appData->waitingThreads--;
6513 
6514     return result;
6515 }
6516 
6517 #else   // !defined(_WIN32)
6518 
6519 /**
6520  * Dark magic helper function that checks, for a given SSL session, whether it
6521  * can SSL_read() or SSL_write() without blocking. Takes into account any
6522  * concurrent attempts to close the SSLSocket from the Java side. This is
6523  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6524  * while thread #2 is sitting in a blocking read or write. The type argument
6525  * specifies whether we are waiting for readability or writability. It expects
6526  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6527  * only need to wait in case one of these problems occurs.
6528  *
6529  * @param env
6530  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6531  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
6532  * @param appData The application data structure with mutex info etc.
6533  * @param timeout_millis The timeout value for poll call, with the special value
6534  *                0 meaning no timeout at all (wait indefinitely). Note: This is
6535  *                the Java semantics of the timeout value, not the usual
6536  *                poll() semantics.
6537  * @return The result of the inner poll() call,
6538  * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6539  * additional errors
6540  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6541 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6542                      int timeout_millis) {
6543     // This loop is an expanded version of the NET_FAILURE_RETRY
6544     // macro. It cannot simply be used in this case because poll
6545     // cannot be restarted without recreating the pollfd structure.
6546     int result;
6547     struct pollfd fds[2];
6548     do {
6549         NetFd fd(env, fdObject);
6550         if (fd.isClosed()) {
6551             result = THROWN_EXCEPTION;
6552             break;
6553         }
6554         int intFd = fd.get();
6555         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6556                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6557 
6558         memset(&fds, 0, sizeof(fds));
6559         fds[0].fd = intFd;
6560         if (type == SSL_ERROR_WANT_READ) {
6561             fds[0].events = POLLIN | POLLPRI;
6562         } else {
6563             fds[0].events = POLLOUT | POLLPRI;
6564         }
6565 
6566         fds[1].fd = appData->fdsEmergency[0];
6567         fds[1].events = POLLIN | POLLPRI;
6568 
6569         // Converting from Java semantics to Posix semantics.
6570         if (timeout_millis <= 0) {
6571             timeout_millis = -1;
6572         }
6573 
6574         CompatibilityCloseMonitor monitor(intFd);
6575 
6576         result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
6577         JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6578                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6579                   timeout_millis, result);
6580         if (result == -1) {
6581             if (fd.isClosed()) {
6582                 result = THROWN_EXCEPTION;
6583                 break;
6584             }
6585             if (errno != EINTR) {
6586                 break;
6587             }
6588         }
6589     } while (result == -1);
6590 
6591     std::lock_guard<std::mutex> appDataLock(appData->mutex);
6592 
6593     if (result > 0) {
6594         // We have been woken up by a token in the emergency pipe. We
6595         // can't be sure the token is still in the pipe at this point
6596         // because it could have already been read by the thread that
6597         // originally wrote it if it entered sslSelect and acquired
6598         // the mutex before we did. Thus we cannot safely read from
6599         // the pipe in a blocking way (so we make the pipe
6600         // non-blocking at creation).
6601         if (fds[1].revents & POLLIN) {
6602             char token;
6603             do {
6604                 (void)read(appData->fdsEmergency[0], &token, 1);
6605             } while (errno == EINTR);
6606         }
6607     }
6608 
6609     // Tell the world that there is now one thread less waiting for the
6610     // underlying network.
6611     appData->waitingThreads--;
6612 
6613     return result;
6614 }
6615 #endif  // !defined(_WIN32)
6616 
6617 /**
6618  * Helper function that wakes up a thread blocked in select(), in case there is
6619  * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6620  * before closing the connection.
6621  *
6622  * @param data The application data structure with mutex info etc.
6623  */
sslNotify(AppData * appData)6624 static void sslNotify(AppData* appData) {
6625 #ifdef _WIN32
6626     SetEvent(appData->interruptEvent);
6627 #else
6628     // Write a byte to the emergency pipe, so a concurrent select() can return.
6629     // Note we have to restore the errno of the original system call, since the
6630     // caller relies on it for generating error messages.
6631     int errnoBackup = errno;
6632     char token = '*';
6633     do {
6634         errno = 0;
6635         (void)write(appData->fdsEmergency[1], &token, 1);
6636     } while (errno == EINTR);
6637     errno = errnoBackup;
6638 #endif
6639 }
6640 
toAppData(const SSL * ssl)6641 static AppData* toAppData(const SSL* ssl) {
6642     return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6643 }
6644 
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)6645 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
6646     JNI_TRACE("ssl=%p cert_verify_callback", ssl);
6647 
6648     AppData* appData = toAppData(ssl);
6649     JNIEnv* env = appData->env;
6650     if (env == nullptr) {
6651         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
6652         JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6653         return ssl_verify_invalid;
6654     }
6655 
6656     // Create the byte[][] array that holds all the certs
6657     ScopedLocalRef<jobjectArray> array(
6658             env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
6659     if (array.get() == nullptr) {
6660         return ssl_verify_invalid;
6661     }
6662 
6663     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6664     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
6665 
6666     const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
6667     const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
6668 
6669     JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
6670               authMethod);
6671     ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
6672     env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
6673 
6674     ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
6675     JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6676     return result;
6677 }
6678 
6679 /**
6680  * Call back to watch for handshake to be completed. This is necessary for
6681  * False Start support, since SSL_do_handshake returns before the handshake is
6682  * completed in this case.
6683  */
info_callback(const SSL * ssl,int type,int value)6684 static void info_callback(const SSL* ssl, int type, int value) {
6685     JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
6686     if (conscrypt::trace::kWithJniTrace) {
6687         info_callback_LOG(ssl, type, value);
6688     }
6689     if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
6690         JNI_TRACE("ssl=%p info_callback ignored", ssl);
6691         return;
6692     }
6693 
6694     AppData* appData = toAppData(ssl);
6695     JNIEnv* env = appData->env;
6696     if (env == nullptr) {
6697         CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
6698         JNI_TRACE("ssl=%p info_callback env error", ssl);
6699         return;
6700     }
6701     if (env->ExceptionCheck()) {
6702         JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6703         return;
6704     }
6705 
6706     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6707 
6708     JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6709     env->CallVoidMethod(sslHandshakeCallbacks,
6710                         conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
6711 
6712     if (env->ExceptionCheck()) {
6713         JNI_TRACE("ssl=%p info_callback exception", ssl);
6714     }
6715     JNI_TRACE("ssl=%p info_callback completed", ssl);
6716 }
6717 
6718 /**
6719  * Call back to ask for a certificate. There are three possible exit codes:
6720  *
6721  * 1 is success.
6722  * 0 is error.
6723  * -1 is to pause the handshake to continue from the same place later.
6724  */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)6725 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
6726     JNI_TRACE("ssl=%p cert_cb", ssl);
6727 
6728     // cert_cb is called for both clients and servers, but we are only
6729     // interested in client certificates.
6730     if (SSL_is_server(ssl)) {
6731         JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
6732         return 1;
6733     }
6734 
6735     AppData* appData = toAppData(ssl);
6736     JNIEnv* env = appData->env;
6737     if (env == nullptr) {
6738         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
6739         JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
6740         return 0;
6741     }
6742     if (env->ExceptionCheck()) {
6743         JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
6744         return 0;
6745     }
6746     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6747 
6748     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
6749 
6750     // Call Java callback which can reconfigure the client certificate.
6751     const uint8_t* ctype = nullptr;
6752     size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
6753     const uint16_t* sigalgs = nullptr;
6754     size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
6755     ScopedLocalRef<jobjectArray> issuers(
6756             env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
6757     if (issuers.get() == nullptr) {
6758         return 0;
6759     }
6760 
6761     if (conscrypt::trace::kWithJniTrace) {
6762         for (size_t i = 0; i < ctype_num; i++) {
6763             JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
6764         }
6765         for (size_t i = 0; i < sigalgs_num; i++) {
6766             JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
6767         }
6768     }
6769 
6770     jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
6771     if (keyTypes == nullptr) {
6772         JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
6773         return 0;
6774     }
6775     env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
6776                             reinterpret_cast<const jbyte*>(ctype));
6777 
6778     jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
6779     if (signatureAlgs == nullptr) {
6780         JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
6781         return 0;
6782     }
6783     {
6784         ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
6785         for (size_t i = 0; i < sigalgs_num; i++) {
6786             sigAlgsRW[i] = sigalgs[i];
6787         }
6788     }
6789 
6790     JNI_TRACE(
6791             "ssl=%p clientCertificateRequested calling clientCertificateRequested "
6792             "keyTypes=%p signatureAlgs=%p issuers=%p",
6793             ssl, keyTypes, signatureAlgs, issuers.get());
6794     env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
6795 
6796     if (env->ExceptionCheck()) {
6797         JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
6798         return 0;
6799     }
6800 
6801     JNI_TRACE("ssl=%p cert_cb => 1", ssl);
6802     return 1;
6803 }
6804 
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)6805 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
6806     SSL* ssl = client_hello->ssl;
6807     JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
6808 
6809     AppData* appData = toAppData(ssl);
6810     JNIEnv* env = appData->env;
6811     if (env == nullptr) {
6812         CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
6813         JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
6814         return ssl_select_cert_error;
6815     }
6816     if (env->ExceptionCheck()) {
6817         JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
6818         return ssl_select_cert_error;
6819     }
6820 
6821     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6822     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
6823 
6824     JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
6825     env->CallVoidMethod(sslHandshakeCallbacks, methodID);
6826 
6827     if (env->ExceptionCheck()) {
6828         JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
6829         return ssl_select_cert_error;
6830     }
6831     JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
6832     return ssl_select_cert_success;
6833 }
6834 
6835 /**
6836  * Pre-Shared Key (PSK) client callback.
6837  */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6838 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
6839                                         unsigned int max_identity_len, unsigned char* psk,
6840                                         unsigned int max_psk_len) {
6841     JNI_TRACE("ssl=%p psk_client_callback", ssl);
6842 
6843     AppData* appData = toAppData(ssl);
6844     JNIEnv* env = appData->env;
6845     if (env == nullptr) {
6846         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
6847         JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6848         return 0;
6849     }
6850     if (env->ExceptionCheck()) {
6851         JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6852         return 0;
6853     }
6854 
6855     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6856     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
6857     JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6858     ScopedLocalRef<jstring> identityHintJava(env,
6859                                              (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
6860     ScopedLocalRef<jbyteArray> identityJava(
6861             env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
6862     if (identityJava.get() == nullptr) {
6863         JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6864         return 0;
6865     }
6866     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6867     if (keyJava.get() == nullptr) {
6868         JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6869         return 0;
6870     }
6871     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6872                                      identityJava.get(), keyJava.get());
6873     if (env->ExceptionCheck()) {
6874         JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6875         return 0;
6876     }
6877     if (keyLen <= 0) {
6878         JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6879         return 0;
6880     } else if ((unsigned int)keyLen > max_psk_len) {
6881         JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6882         return 0;
6883     }
6884     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6885     if (keyJavaRo.get() == nullptr) {
6886         JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
6887         return 0;
6888     }
6889     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6890 
6891     ScopedByteArrayRO identityJavaRo(env, identityJava.get());
6892     if (identityJavaRo.get() == nullptr) {
6893         JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
6894         return 0;
6895     }
6896     memcpy(identity, identityJavaRo.get(), max_identity_len);
6897 
6898     JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
6899     return static_cast<unsigned int>(keyLen);
6900 }
6901 
6902 /**
6903  * Pre-Shared Key (PSK) server callback.
6904  */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)6905 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
6906                                         unsigned int max_psk_len) {
6907     JNI_TRACE("ssl=%p psk_server_callback", ssl);
6908 
6909     AppData* appData = toAppData(ssl);
6910     JNIEnv* env = appData->env;
6911     if (env == nullptr) {
6912         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
6913         JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
6914         return 0;
6915     }
6916     if (env->ExceptionCheck()) {
6917         JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
6918         return 0;
6919     }
6920 
6921     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6922     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
6923     JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
6924     const char* identityHint = SSL_get_psk_identity_hint(ssl);
6925     ScopedLocalRef<jstring> identityHintJava(
6926             env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
6927     ScopedLocalRef<jstring> identityJava(
6928             env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
6929     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6930     if (keyJava.get() == nullptr) {
6931         JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
6932         return 0;
6933     }
6934     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6935                                      identityJava.get(), keyJava.get());
6936     if (env->ExceptionCheck()) {
6937         JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
6938         return 0;
6939     }
6940     if (keyLen <= 0) {
6941         JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
6942         return 0;
6943     } else if ((unsigned int)keyLen > max_psk_len) {
6944         JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
6945         return 0;
6946     }
6947     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6948     if (keyJavaRo.get() == nullptr) {
6949         JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
6950         return 0;
6951     }
6952     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6953 
6954     JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
6955     return static_cast<unsigned int>(keyLen);
6956 }
6957 
new_session_callback(SSL * ssl,SSL_SESSION * session)6958 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
6959     JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
6960 
6961     AppData* appData = toAppData(ssl);
6962     JNIEnv* env = appData->env;
6963     if (env == nullptr) {
6964         CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
6965         JNI_TRACE("ssl=%p new_session_callback env error", ssl);
6966         return 0;
6967     }
6968     if (env->ExceptionCheck()) {
6969         JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
6970         return 0;
6971     }
6972 
6973     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6974     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
6975     JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
6976     env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
6977     if (env->ExceptionCheck()) {
6978         JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
6979         env->ExceptionClear();
6980     }
6981     JNI_TRACE("ssl=%p new_session_callback completed", ssl);
6982 
6983     // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
6984     // the reference count.
6985     return 0;
6986 }
6987 
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)6988 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
6989                                                       int* out_copy) {
6990     JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
6991 
6992     // Always set to out_copy to zero. The Java callback will be responsible for incrementing
6993     // the reference count (and any required synchronization).
6994     *out_copy = 0;
6995 
6996     AppData* appData = toAppData(ssl);
6997     JNIEnv* env = appData->env;
6998     if (env == nullptr) {
6999         CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7000         JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7001         return 0;
7002     }
7003     if (env->ExceptionCheck()) {
7004         JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7005         return 0;
7006     }
7007 
7008     // Copy the ID to a byte[].
7009     jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7010     if (id_array == nullptr) {
7011         JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7012         return 0;
7013     }
7014     env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7015                             reinterpret_cast<const jbyte*>(id));
7016 
7017     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7018     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7019     JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7020     jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7021     if (env->ExceptionCheck()) {
7022         JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7023         env->ExceptionClear();
7024     }
7025     SSL_SESSION* ssl_session_ptr =
7026             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7027     JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7028     return ssl_session_ptr;
7029 }
7030 
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7031 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7032     CHECK_ERROR_QUEUE_ON_RETURN;
7033     int ret = 0;
7034     ret = EVP_has_aes_hardware();
7035     JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7036     return ret;
7037 }
7038 
debug_print_session_key(const SSL * ssl,const char * line)7039 static void debug_print_session_key(const SSL* ssl, const char* line) {
7040     JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7041 }
7042 
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7043 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7044     static constexpr size_t kDataWidth = 16;
7045 
7046     struct timeval tv;
7047     if (gettimeofday(&tv, NULL)) {
7048         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7049                       "debug_print_packet_data: could not get time of day");
7050         return;
7051     }
7052 
7053     // Packet preamble for text2pcap
7054     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7055                   static_cast<long>(tv.tv_sec),
7056                   static_cast<long>(tv.tv_usec));  // NOLINT(runtime/int)
7057 
7058     char out[kDataWidth * 3 + 1];
7059     for (size_t i = 0; i < len; i += kDataWidth) {
7060         size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7061 
7062         for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7063             int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7064             if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7065                 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7066                               "debug_print_packet_data failed to output %d", ret);
7067                 return;
7068             }
7069         }
7070 
7071         // Print out packet data in format understood by text2pcap
7072         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7073     }
7074 
7075     // Conclude the packet data
7076     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7077 }
7078 
7079 /*
7080  * public static native int SSL_CTX_new();
7081  */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7082 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7083     CHECK_ERROR_QUEUE_ON_RETURN;
7084     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7085     if (sslCtx.get() == nullptr) {
7086         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7087         return 0;
7088     }
7089     SSL_CTX_set_options(
7090             sslCtx.get(),
7091             SSL_OP_ALL
7092                     // We also disable session tickets for better compatibility b/2682876
7093                     | SSL_OP_NO_TICKET
7094                     // We also disable compression for better compatibility b/2710492 b/2710497
7095                     | SSL_OP_NO_COMPRESSION
7096                     // Generate a fresh ECDH keypair for each key exchange.
7097                     | SSL_OP_SINGLE_ECDH_USE);
7098     SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7099     SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7100 
7101     uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7102     /*
7103      * Turn on "partial write" mode. This means that SSL_write() will
7104      * behave like Posix write() and possibly return after only
7105      * writing a partial buffer. Note: The alternative, perhaps
7106      * surprisingly, is not that SSL_write() always does full writes
7107      * but that it will force you to retry write calls having
7108      * preserved the full state of the original call. (This is icky
7109      * and undesirable.)
7110      */
7111     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7112 
7113     // Reuse empty buffers within the SSL_CTX to save memory
7114     mode |= SSL_MODE_RELEASE_BUFFERS;
7115 
7116     // Enable False Start.
7117     mode |= SSL_MODE_ENABLE_FALSE_START;
7118 
7119     // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7120     // between
7121     // calls to wrap(...).
7122     // See https://github.com/netty/netty-tcnative/issues/100
7123     mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7124 
7125     SSL_CTX_set_mode(sslCtx.get(), mode);
7126 
7127     SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7128     SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7129     SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7130     if (conscrypt::trace::kWithJniTraceKeys) {
7131         SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7132     }
7133 
7134     // By default BoringSSL will cache in server mode, but we want to get
7135     // notified of new sessions being created in client mode. We set
7136     // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7137     // ignore it in server mode in favor of the internal cache.
7138     SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7139     SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7140     SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7141 
7142     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7143     return (jlong)sslCtx.release();
7144 }
7145 
7146 /**
7147  * public static native void SSL_CTX_free(long ssl_ctx)
7148  */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7149 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7150                                       CONSCRYPT_UNUSED jobject holder) {
7151     CHECK_ERROR_QUEUE_ON_RETURN;
7152     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7153     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7154     if (ssl_ctx == nullptr) {
7155         return;
7156     }
7157     SSL_CTX_free(ssl_ctx);
7158 }
7159 
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7160 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7161                                                         CONSCRYPT_UNUSED jobject holder,
7162                                                         jbyteArray sid_ctx) {
7163     CHECK_ERROR_QUEUE_ON_RETURN;
7164     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7165     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7166               sid_ctx);
7167     if (ssl_ctx == nullptr) {
7168         return;
7169     }
7170 
7171     ScopedByteArrayRO buf(env, sid_ctx);
7172     if (buf.get() == nullptr) {
7173         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7174                   ssl_ctx);
7175         return;
7176     }
7177 
7178     unsigned int length = static_cast<unsigned int>(buf.size());
7179     if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7180         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7181                                            "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7182         JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7183         return;
7184     }
7185     const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7186     int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7187     if (result == 0) {
7188         conscrypt::jniutil::throwExceptionFromBoringSSLError(
7189                 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7190         return;
7191     }
7192     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7193 }
7194 
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7195 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7196                                               CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7197     CHECK_ERROR_QUEUE_ON_RETURN;
7198     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7199     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7200     if (ssl_ctx == nullptr) {
7201         return 0L;
7202     }
7203 
7204     return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7205 }
7206 
7207 /**
7208  * public static native int SSL_new(long ssl_ctx) throws SSLException;
7209  */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7210 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7211                                   CONSCRYPT_UNUSED jobject holder) {
7212     CHECK_ERROR_QUEUE_ON_RETURN;
7213     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7214     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7215     if (ssl_ctx == nullptr) {
7216         return 0;
7217     }
7218     bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7219     if (ssl.get() == nullptr) {
7220         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7221                                                            "Unable to create SSL structure");
7222         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7223         return 0;
7224     }
7225 
7226     /*
7227      * Create our special application data.
7228      */
7229     AppData* appData = AppData::create();
7230     if (appData == nullptr) {
7231         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7232         ERR_clear_error();
7233         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7234         return 0;
7235     }
7236     SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7237 
7238     SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7239 
7240     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7241     return (jlong)ssl.release();
7242 }
7243 
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7244 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7245                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
7246     CHECK_ERROR_QUEUE_ON_RETURN;
7247     SSL* ssl = to_SSL(env, ssl_address, true);
7248     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7249     if (ssl == nullptr) {
7250         return;
7251     }
7252 
7253     // NOLINTNEXTLINE(runtime/int)
7254     long ret = SSL_enable_tls_channel_id(ssl);
7255     if (ret != 1L) {
7256         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7257         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7258                                                            "Error enabling Channel ID");
7259         JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7260         return;
7261     }
7262 }
7263 
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7264 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7265                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
7266     CHECK_ERROR_QUEUE_ON_RETURN;
7267     SSL* ssl = to_SSL(env, ssl_address, true);
7268     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7269     if (ssl == nullptr) {
7270         return nullptr;
7271     }
7272 
7273     // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7274     // as a constant anywhere.
7275     jbyteArray javaBytes = env->NewByteArray(64);
7276     ScopedByteArrayRW bytes(env, javaBytes);
7277     if (bytes.get() == nullptr) {
7278         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7279         return nullptr;
7280     }
7281 
7282     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7283     // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7284     // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7285     // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7286     size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7287     if (ret == 0) {
7288         // Channel ID either not set or did not verify
7289         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7290         return nullptr;
7291     } else if (ret != 64) {
7292         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7293         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7294                                                            "Error getting Channel ID");
7295         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7296         return nullptr;
7297     }
7298 
7299     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7300     return javaBytes;
7301 }
7302 
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7303 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7304                                                  CONSCRYPT_UNUSED jobject ssl_holder,
7305                                                  jobject pkeyRef) {
7306     CHECK_ERROR_QUEUE_ON_RETURN;
7307     SSL* ssl = to_SSL(env, ssl_address, true);
7308     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7309     if (ssl == nullptr) {
7310         return;
7311     }
7312 
7313     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7314     if (pkey == nullptr) {
7315         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7316         return;
7317     }
7318 
7319     // NOLINTNEXTLINE(runtime/int)
7320     long ret = SSL_set1_tls_channel_id(ssl, pkey);
7321 
7322     if (ret != 1L) {
7323         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7324         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7325                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7326         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7327         return;
7328     }
7329 
7330     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7331 }
7332 
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7333 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7334                                                     CONSCRYPT_UNUSED jobject ssl_holder,
7335                                                     jobjectArray encodedCertificatesJava,
7336                                                     jobject pkeyRef) {
7337     CHECK_ERROR_QUEUE_ON_RETURN;
7338     SSL* ssl = to_SSL(env, ssl_address, true);
7339     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7340               encodedCertificatesJava, pkeyRef);
7341     if (ssl == nullptr) {
7342         return;
7343     }
7344     if (encodedCertificatesJava == nullptr) {
7345         conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7346         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7347         return;
7348     }
7349     size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7350     if (numCerts == 0) {
7351         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7352                                            "certificates.length == 0");
7353         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7354         return;
7355     }
7356     if (pkeyRef == nullptr) {
7357         conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7358         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7359         return;
7360     }
7361 
7362     // Get the private key.
7363     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7364     if (pkey == nullptr) {
7365         conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7366         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7367         return;
7368     }
7369 
7370     // Copy the certificates.
7371     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7372     std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7373     for (size_t i = 0; i < numCerts; ++i) {
7374         ScopedLocalRef<jbyteArray> certArray(
7375                 env, reinterpret_cast<jbyteArray>(
7376                              env->GetObjectArrayElement(encodedCertificatesJava, i)));
7377         certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7378         if (!certBufferRefs[i]) {
7379             return;
7380         }
7381         certBuffers[i] = certBufferRefs[i].get();
7382     }
7383 
7384     if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7385         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7386                                                            "Error configuring certificate");
7387         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7388         return;
7389     }
7390     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7391 }
7392 
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7393 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7394                                                 CONSCRYPT_UNUSED jobject ssl_holder,
7395                                                 jobjectArray principals) {
7396     CHECK_ERROR_QUEUE_ON_RETURN;
7397     SSL* ssl = to_SSL(env, ssl_address, true);
7398     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7399     if (ssl == nullptr) {
7400         return;
7401     }
7402 
7403     if (principals == nullptr) {
7404         conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7405         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7406         return;
7407     }
7408 
7409     int length = env->GetArrayLength(principals);
7410     if (length == 0) {
7411         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7412                                            "principals.length == 0");
7413         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7414         return;
7415     }
7416 
7417     bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7418     if (principalsStack.get() == nullptr) {
7419         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7420         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7421         return;
7422     }
7423     for (int i = 0; i < length; i++) {
7424         ScopedLocalRef<jbyteArray> principal(
7425                 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7426         bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7427         if (!buf) {
7428             return;
7429         }
7430         if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7431             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7432             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7433             return;
7434         }
7435         OWNERSHIP_TRANSFERRED(buf);
7436     }
7437 
7438     SSL_set0_client_CAs(ssl, principalsStack.release());
7439     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7440 }
7441 
7442 /**
7443  * public static native long SSL_set_mode(long ssl, long mode);
7444  */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)7445 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
7446                                        CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
7447     CHECK_ERROR_QUEUE_ON_RETURN;
7448     SSL* ssl = to_SSL(env, ssl_address, true);
7449     // NOLINTNEXTLINE(runtime/int)
7450     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
7451     if (ssl == nullptr) {
7452         return 0;
7453     }
7454     jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
7455     // NOLINTNEXTLINE(runtime/int)
7456     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
7457     return result;
7458 }
7459 
7460 /**
7461  * public static native long SSL_set_options(long ssl, long options);
7462  */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7463 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
7464                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7465     CHECK_ERROR_QUEUE_ON_RETURN;
7466     SSL* ssl = to_SSL(env, ssl_address, true);
7467     // NOLINTNEXTLINE(runtime/int)
7468     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
7469     if (ssl == nullptr) {
7470         return 0;
7471     }
7472     jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
7473     // NOLINTNEXTLINE(runtime/int)
7474     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
7475     return result;
7476 }
7477 
7478 /**
7479  * public static native long SSL_clear_options(long ssl, long options);
7480  */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7481 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
7482                                             CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7483     CHECK_ERROR_QUEUE_ON_RETURN;
7484     SSL* ssl = to_SSL(env, ssl_address, true);
7485     // NOLINTNEXTLINE(runtime/int)
7486     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
7487     if (ssl == nullptr) {
7488         return 0;
7489     }
7490     jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
7491     // NOLINTNEXTLINE(runtime/int)
7492     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
7493     return result;
7494 }
7495 
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)7496 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
7497                                                    CONSCRYPT_UNUSED jobject ssl_holder,
7498                                                    jint min_version, jint max_version) {
7499     CHECK_ERROR_QUEUE_ON_RETURN;
7500     SSL* ssl = to_SSL(env, ssl_address, true);
7501     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
7502               max_version);
7503     if (ssl == nullptr) {
7504         return 0;
7505     }
7506     int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
7507     int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
7508     // Return failure if either call failed.
7509     int result = 1;
7510     if (!min_result || !max_result) {
7511         result = 0;
7512         // The only possible error is an invalid version, so we don't need the details.
7513         ERR_clear_error();
7514     }
7515     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
7516               min_result, max_result, result);
7517     return result;
7518 }
7519 
7520 /**
7521  * public static native void SSL_enable_signed_cert_timestamps(long ssl);
7522  */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7523 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
7524                                                            CONSCRYPT_UNUSED jobject ssl_holder) {
7525     CHECK_ERROR_QUEUE_ON_RETURN;
7526     SSL* ssl = to_SSL(env, ssl_address, true);
7527     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
7528     if (ssl == nullptr) {
7529         return;
7530     }
7531 
7532     SSL_enable_signed_cert_timestamps(ssl);
7533 }
7534 
7535 /**
7536  * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
7537  */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7538 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
7539         JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
7540     CHECK_ERROR_QUEUE_ON_RETURN;
7541     SSL* ssl = to_SSL(env, ssl_address, true);
7542     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
7543     if (ssl == nullptr) {
7544         return nullptr;
7545     }
7546 
7547     const uint8_t* data;
7548     size_t data_len;
7549     SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
7550 
7551     if (data_len == 0) {
7552         JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
7553         return nullptr;
7554     }
7555 
7556     jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
7557     if (result != nullptr) {
7558         env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
7559     }
7560     return result;
7561 }
7562 
7563 /*
7564  * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
7565  */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)7566 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
7567                                                             CONSCRYPT_UNUSED jobject ssl_holder,
7568                                                             jbyteArray list) {
7569     CHECK_ERROR_QUEUE_ON_RETURN;
7570     SSL* ssl = to_SSL(env, ssl_address, true);
7571     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
7572     if (ssl == nullptr) {
7573         return;
7574     }
7575 
7576     ScopedByteArrayRO listBytes(env, list);
7577     if (listBytes.get() == nullptr) {
7578         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
7579         return;
7580     }
7581 
7582     if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
7583                                             listBytes.size())) {
7584         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
7585     } else {
7586         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
7587     }
7588 }
7589 
7590 /*
7591  * public static native void SSL_enable_ocsp_stapling(long ssl);
7592  */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7593 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
7594                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
7595     CHECK_ERROR_QUEUE_ON_RETURN;
7596     SSL* ssl = to_SSL(env, ssl_address, true);
7597     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
7598     if (ssl == nullptr) {
7599         return;
7600     }
7601 
7602     SSL_enable_ocsp_stapling(ssl);
7603 }
7604 
7605 /*
7606  * public static native byte[] SSL_get_ocsp_response(long ssl);
7607  */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7608 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7609                                                      CONSCRYPT_UNUSED jobject ssl_holder) {
7610     CHECK_ERROR_QUEUE_ON_RETURN;
7611     SSL* ssl = to_SSL(env, ssl_address, true);
7612     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
7613     if (ssl == nullptr) {
7614         return nullptr;
7615     }
7616 
7617     const uint8_t* data;
7618     size_t data_len;
7619     SSL_get0_ocsp_response(ssl, &data, &data_len);
7620 
7621     if (data_len == 0) {
7622         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
7623         return nullptr;
7624     }
7625 
7626     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7627     if (byteArray.get() == nullptr) {
7628         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
7629         return nullptr;
7630     }
7631 
7632     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7633     JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
7634               data_len);
7635 
7636     return byteArray.release();
7637 }
7638 
7639 /*
7640  * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
7641  */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)7642 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7643                                                CONSCRYPT_UNUSED jobject ssl_holder,
7644                                                jbyteArray response) {
7645     CHECK_ERROR_QUEUE_ON_RETURN;
7646     SSL* ssl = to_SSL(env, ssl_address, true);
7647     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
7648     if (ssl == nullptr) {
7649         return;
7650     }
7651 
7652     ScopedByteArrayRO responseBytes(env, response);
7653     if (responseBytes.get() == nullptr) {
7654         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
7655         return;
7656     }
7657 
7658     if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
7659                                responseBytes.size())) {
7660         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
7661     } else {
7662         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
7663     }
7664 }
7665 
7666 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
7667 // to customize the length of their verify_data (with a default of 12 bytes).  We accept
7668 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
7669 // tests and update this value if necessary.
7670 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
7671 
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7672 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
7673                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
7674     CHECK_ERROR_QUEUE_ON_RETURN;
7675     SSL* ssl = to_SSL(env, ssl_address, true);
7676     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
7677     if (ssl == nullptr) {
7678         return nullptr;
7679     }
7680 
7681     uint8_t data[MAX_TLS_UNIQUE_LENGTH];
7682     size_t data_len;
7683     int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
7684 
7685     if (!ret || data_len == 0) {
7686         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
7687         return nullptr;
7688     }
7689 
7690     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7691     if (byteArray.get() == nullptr) {
7692         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
7693         return nullptr;
7694     }
7695 
7696     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7697     JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
7698               data_len);
7699 
7700     return byteArray.release();
7701 }
7702 
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)7703 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
7704                                                           CONSCRYPT_UNUSED jobject ssl_holder,
7705                                                           jbyteArray label, jbyteArray context,
7706                                                           jint num_bytes) {
7707     CHECK_ERROR_QUEUE_ON_RETURN;
7708     SSL* ssl = to_SSL(env, ssl_address, true);
7709     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
7710     if (ssl == nullptr) {
7711         return nullptr;
7712     }
7713     ScopedByteArrayRO labelBytes(env, label);
7714     if (labelBytes.get() == nullptr) {
7715         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
7716         return nullptr;
7717     }
7718     std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
7719     int ret;
7720     if (context == nullptr) {
7721         ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
7722                         reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
7723                         nullptr, 0, 0);
7724     } else {
7725         ScopedByteArrayRO contextBytes(env, context);
7726         if (contextBytes.get() == nullptr) {
7727             JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
7728                       ssl);
7729             return nullptr;
7730         }
7731         ret = SSL_export_keying_material(
7732                 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
7733                 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
7734                 contextBytes.size(), 1);
7735     }
7736     if (!ret) {
7737         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
7738                 conscrypt::jniutil::throwSSLExceptionStr);
7739         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
7740         return nullptr;
7741     }
7742     jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
7743     if (result == nullptr) {
7744         conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
7745         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
7746         return nullptr;
7747     }
7748     const jbyte* src = reinterpret_cast<jbyte*>(out.get());
7749     env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
7750     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
7751     return result;
7752 }
7753 
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)7754 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
7755                                                    CONSCRYPT_UNUSED jobject ssl_holder,
7756                                                    jstring identityHintJava) {
7757     CHECK_ERROR_QUEUE_ON_RETURN;
7758     SSL* ssl = to_SSL(env, ssl_address, true);
7759     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
7760               identityHintJava);
7761     if (ssl == nullptr) {
7762         return;
7763     }
7764 
7765     int ret;
7766     if (identityHintJava == nullptr) {
7767         ret = SSL_use_psk_identity_hint(ssl, nullptr);
7768     } else {
7769         ScopedUtfChars identityHint(env, identityHintJava);
7770         if (identityHint.c_str() == nullptr) {
7771             conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7772             return;
7773         }
7774         ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7775     }
7776 
7777     if (ret != 1) {
7778         int sslErrorCode = SSL_get_error(ssl, ret);
7779         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7780                                                            "Failed to set PSK identity hint");
7781     }
7782 }
7783 
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7784 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7785                                                              CONSCRYPT_UNUSED jobject ssl_holder,
7786                                                              jboolean enabled) {
7787     CHECK_ERROR_QUEUE_ON_RETURN;
7788     SSL* ssl = to_SSL(env, ssl_address, true);
7789     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
7790     if (ssl == nullptr) {
7791         return;
7792     }
7793 
7794     SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
7795 }
7796 
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7797 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7798                                                              CONSCRYPT_UNUSED jobject ssl_holder,
7799                                                              jboolean enabled) {
7800     CHECK_ERROR_QUEUE_ON_RETURN;
7801     SSL* ssl = to_SSL(env, ssl_address, true);
7802     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
7803     if (ssl == nullptr) {
7804         return;
7805     }
7806 
7807     SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
7808 }
7809 
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7810 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
7811                                                CONSCRYPT_UNUSED jobject ssl_holder) {
7812     CHECK_ERROR_QUEUE_ON_RETURN;
7813     SSL* ssl = to_SSL(env, ssl_address, true);
7814     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7815     if (ssl == nullptr) {
7816         return nullptr;
7817     }
7818 
7819     STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7820     size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7821     ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
7822     ScopedLongArrayRW ciphers(env, ciphersArray.get());
7823     for (size_t i = 0; i < count; i++) {
7824         ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7825     }
7826 
7827     JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
7828     return ciphersArray.release();
7829 }
7830 
7831 /**
7832  * Sets the ciphers suites that are enabled in the SSL
7833  */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)7834 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
7835                                               CONSCRYPT_UNUSED jobject ssl_holder,
7836                                               jobjectArray cipherSuites) {
7837     CHECK_ERROR_QUEUE_ON_RETURN;
7838     SSL* ssl = to_SSL(env, ssl_address, true);
7839     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7840     if (ssl == nullptr) {
7841         return;
7842     }
7843     if (cipherSuites == nullptr) {
7844         conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
7845         return;
7846     }
7847 
7848     int length = env->GetArrayLength(cipherSuites);
7849 
7850     /*
7851      * Special case for empty cipher list. This is considered an error by the
7852      * SSL_set_cipher_list API, but Java allows this silly configuration.
7853      * However, the SSL cipher list is still set even when SSL_set_cipher_list
7854      * returns 0 in this case. Just to make sure, we check the resulting cipher
7855      * list to make sure it's zero length.
7856      */
7857     if (length == 0) {
7858         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
7859         SSL_set_cipher_list(ssl, "");
7860         ERR_clear_error();
7861         if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
7862             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
7863             conscrypt::jniutil::throwRuntimeException(
7864                     env, "SSL_set_cipher_list did not update ciphers!");
7865             ERR_clear_error();
7866         }
7867         return;
7868     }
7869 
7870     static const char noSSLv2[] = "!SSLv2";
7871     size_t cipherStringLen = strlen(noSSLv2);
7872 
7873     for (int i = 0; i < length; i++) {
7874         ScopedLocalRef<jstring> cipherSuite(
7875                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7876         ScopedUtfChars c(env, cipherSuite.get());
7877         if (c.c_str() == nullptr) {
7878             return;
7879         }
7880 
7881         if (cipherStringLen + 1 < cipherStringLen) {
7882             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7883                                                "Overflow in cipher suite strings");
7884             return;
7885         }
7886         cipherStringLen += 1; /* For the separating colon */
7887 
7888         if (cipherStringLen + c.size() < cipherStringLen) {
7889             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7890                                                "Overflow in cipher suite strings");
7891             return;
7892         }
7893         cipherStringLen += c.size();
7894     }
7895 
7896     if (cipherStringLen + 1 < cipherStringLen) {
7897         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7898                                            "Overflow in cipher suite strings");
7899         return;
7900     }
7901     cipherStringLen += 1; /* For final NUL. */
7902 
7903     std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
7904     if (cipherString.get() == nullptr) {
7905         conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
7906         return;
7907     }
7908     memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
7909     size_t j = strlen(noSSLv2);
7910 
7911     for (int i = 0; i < length; i++) {
7912         ScopedLocalRef<jstring> cipherSuite(
7913                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7914         ScopedUtfChars c(env, cipherSuite.get());
7915 
7916         cipherString[j++] = ':';
7917         memcpy(&cipherString[j], c.c_str(), c.size());
7918         j += c.size();
7919     }
7920 
7921     cipherString[j++] = 0;
7922     if (j != cipherStringLen) {
7923         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7924                                            "Internal error");
7925         return;
7926     }
7927 
7928     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
7929     if (!SSL_set_cipher_list(ssl, cipherString.get())) {
7930         ERR_clear_error();
7931         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7932                                            "Illegal cipher suite strings.");
7933         return;
7934     }
7935 }
7936 
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7937 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
7938                                               CONSCRYPT_UNUSED jobject ssl_holder) {
7939     CHECK_ERROR_QUEUE_ON_RETURN;
7940     SSL* ssl = to_SSL(env, ssl_address, true);
7941     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7942     if (ssl == nullptr) {
7943         return;
7944     }
7945     SSL_set_accept_state(ssl);
7946 }
7947 
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7948 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
7949                                                CONSCRYPT_UNUSED jobject ssl_holder) {
7950     CHECK_ERROR_QUEUE_ON_RETURN;
7951     SSL* ssl = to_SSL(env, ssl_address, true);
7952     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7953     if (ssl == nullptr) {
7954         return;
7955     }
7956     SSL_set_connect_state(ssl);
7957 }
7958 
7959 /**
7960  * Sets certificate expectations, especially for server to request client auth
7961  */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)7962 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
7963                                         CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
7964     CHECK_ERROR_QUEUE_ON_RETURN;
7965     SSL* ssl = to_SSL(env, ssl_address, true);
7966     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7967     if (ssl == nullptr) {
7968         return;
7969     }
7970     SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
7971 }
7972 
7973 /**
7974  * Sets the ciphers suites that are enabled in the SSL
7975  */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)7976 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
7977                                          CONSCRYPT_UNUSED jobject ssl_holder,
7978                                          jlong ssl_session_address) {
7979     CHECK_ERROR_QUEUE_ON_RETURN;
7980     SSL* ssl = to_SSL(env, ssl_address, true);
7981     if (ssl == nullptr) {
7982         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
7983         return;
7984     }
7985 
7986     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7987     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7988     if (ssl_session == nullptr) {
7989         return;
7990     }
7991 
7992     int ret = SSL_set_session(ssl, ssl_session);
7993     if (ret != 1) {
7994         /*
7995          * Translate the error, and throw if it turns out to be a real
7996          * problem.
7997          */
7998         int sslErrorCode = SSL_get_error(ssl, ret);
7999         if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8000             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8001                                                                "SSL session set");
8002         }
8003     }
8004     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8005               ret);
8006 }
8007 
8008 /**
8009  * Sets the ciphers suites that are enabled in the SSL
8010  */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8011 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8012                                                           CONSCRYPT_UNUSED jobject ssl_holder,
8013                                                           jboolean creation_enabled) {
8014     CHECK_ERROR_QUEUE_ON_RETURN;
8015     SSL* ssl = to_SSL(env, ssl_address, true);
8016     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8017               creation_enabled);
8018     if (ssl == nullptr) {
8019         return;
8020     }
8021 
8022     if (creation_enabled) {
8023         SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8024     } else {
8025         SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8026     }
8027 }
8028 
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8029 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8030                                                 CONSCRYPT_UNUSED jobject ssl_holder) {
8031     CHECK_ERROR_QUEUE_ON_RETURN;
8032     SSL* ssl = to_SSL(env, ssl_address, true);
8033     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8034     if (ssl == nullptr) {
8035         return JNI_FALSE;
8036     }
8037 
8038     int reused = SSL_session_reused(ssl);
8039     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8040     return static_cast<jboolean>(reused);
8041 }
8042 
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8043 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8044                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
8045     CHECK_ERROR_QUEUE_ON_RETURN;
8046     SSL* ssl = to_SSL(env, ssl_address, true);
8047     JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8048     if (ssl == nullptr) {
8049         return;
8050     }
8051 
8052     SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8053 }
8054 
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8055 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8056                                                   CONSCRYPT_UNUSED jobject ssl_holder,
8057                                                   jstring hostname) {
8058     CHECK_ERROR_QUEUE_ON_RETURN;
8059     SSL* ssl = to_SSL(env, ssl_address, true);
8060     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8061     if (ssl == nullptr) {
8062         return;
8063     }
8064 
8065     ScopedUtfChars hostnameChars(env, hostname);
8066     if (hostnameChars.c_str() == nullptr) {
8067         return;
8068     }
8069     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8070               hostnameChars.c_str());
8071 
8072     int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8073     if (ret != 1) {
8074         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8075                                                            "Error setting host name");
8076         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8077         return;
8078     }
8079     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8080 }
8081 
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8082 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8083                                                CONSCRYPT_UNUSED jobject ssl_holder) {
8084     CHECK_ERROR_QUEUE_ON_RETURN;
8085     SSL* ssl = to_SSL(env, ssl_address, true);
8086     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8087     if (ssl == nullptr) {
8088         return nullptr;
8089     }
8090     const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8091     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8092     return env->NewStringUTF(servername);
8093 }
8094 
8095 /**
8096  * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8097  * which should take precedence.
8098  */
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)8099 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8100                                      const unsigned char* primary,
8101                                      const unsigned int primaryLength,
8102                                      const unsigned char* secondary,
8103                                      const unsigned int secondaryLength) {
8104     JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8105 
8106     int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8107                                        secondaryLength);
8108     switch (status) {
8109         case OPENSSL_NPN_NEGOTIATED:
8110             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8111             return SSL_TLSEXT_ERR_OK;
8112             break;
8113         case OPENSSL_NPN_UNSUPPORTED:
8114             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8115             break;
8116         case OPENSSL_NPN_NO_OVERLAP:
8117             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8118             break;
8119     }
8120     return SSL_TLSEXT_ERR_NOACK;
8121 }
8122 
8123 /**
8124  * Calls out to an application-provided selector to choose the ALPN protocol.
8125  */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8126 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8127                                      unsigned char** out,
8128                                      unsigned char* outLen, const unsigned char* in,
8129                                      const unsigned int inLen) {
8130     // Copy the input array.
8131     ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8132     if (protocols.get() == nullptr) {
8133         JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8134         return SSL_TLSEXT_ERR_NOACK;
8135     }
8136     env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8137                             reinterpret_cast<const jbyte*>(in));
8138 
8139     // Invoke the selection method.
8140     jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8141     jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8142 
8143     if (offset < 0) {
8144         JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8145         return SSL_TLSEXT_ERR_NOACK;
8146     }
8147 
8148     // Point the output to the selected protocol.
8149     *outLen = *(in + offset);
8150     *out = const_cast<unsigned char*>(in + offset + 1);
8151 
8152     return SSL_TLSEXT_ERR_OK;
8153 }
8154 
8155 /**
8156  * Callback for the server to select an ALPN protocol.
8157  */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8158 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8159                                 const unsigned char* in, unsigned int inLen, void*) {
8160     JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8161 
8162     AppData* appData = toAppData(ssl);
8163     if (appData == nullptr) {
8164         JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8165         return SSL_TLSEXT_ERR_NOACK;
8166     }
8167     JNIEnv* env = appData->env;
8168     if (env == nullptr) {
8169         CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8170         JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8171         return SSL_TLSEXT_ERR_NOACK;
8172     }
8173 
8174     if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8175                           !appData->hasApplicationProtocolSelector)) {
8176         if (out != nullptr && outLen != nullptr) {
8177             *out = nullptr;
8178             *outLen = 0;
8179         }
8180         JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8181         return SSL_TLSEXT_ERR_NOACK;
8182     }
8183 
8184     if (appData->hasApplicationProtocolSelector) {
8185         return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8186                                          const_cast<unsigned char**>(out), outLen, in, inLen);
8187     }
8188 
8189     return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8190                               reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8191                               static_cast<unsigned int>(appData->applicationProtocolsLength),
8192                               in, inLen);
8193 }
8194 
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8195 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8196                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
8197     CHECK_ERROR_QUEUE_ON_RETURN;
8198     SSL* ssl = to_SSL(env, ssl_address, true);
8199     JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8200     if (ssl == nullptr) {
8201         return nullptr;
8202     }
8203     const jbyte* protocol;
8204     unsigned int protocolLength;
8205     SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8206                            &protocolLength);
8207     if (protocolLength == 0) {
8208         return nullptr;
8209     }
8210     jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8211     if (result != nullptr) {
8212         env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8213     }
8214     return result;
8215 }
8216 
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8217 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8218                                                  CONSCRYPT_UNUSED jobject ssl_holder,
8219                                                  jboolean client_mode, jbyteArray protocols) {
8220     CHECK_ERROR_QUEUE_ON_RETURN;
8221     SSL* ssl = to_SSL(env, ssl_address, true);
8222     if (ssl == nullptr) {
8223         return;
8224     }
8225     AppData* appData = toAppData(ssl);
8226     if (appData == nullptr) {
8227         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8228         JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8229         return;
8230     }
8231 
8232     if (protocols != nullptr) {
8233         if (client_mode) {
8234             ScopedByteArrayRO protosBytes(env, protocols);
8235             if (protosBytes.get() == nullptr) {
8236                 JNI_TRACE(
8237                         "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8238                         "protosBytes == null",
8239                         ssl, protocols);
8240                 return;
8241             }
8242 
8243             const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8244             int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8245             if (ret != 0) {
8246                 conscrypt::jniutil::throwSSLExceptionStr(env,
8247                                                          "Unable to set ALPN protocols for client");
8248                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8249                 return;
8250             }
8251         } else {
8252             // Server mode - configure the ALPN protocol selection callback.
8253             if (!appData->setApplicationProtocols(env, protocols)) {
8254                 conscrypt::jniutil::throwSSLExceptionStr(env,
8255                                                          "Unable to set ALPN protocols for server");
8256                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8257                 return;
8258             }
8259             SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8260         }
8261     }
8262 }
8263 
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8264 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8265                                                            CONSCRYPT_UNUSED jobject ssl_holder,
8266                                                            jboolean hasSelector) {
8267     CHECK_ERROR_QUEUE_ON_RETURN;
8268     SSL* ssl = to_SSL(env, ssl_address, true);
8269     JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8270               hasSelector);
8271     if (ssl == nullptr) {
8272         return;
8273     }
8274     AppData* appData = toAppData(ssl);
8275     if (appData == nullptr) {
8276         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8277         JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8278         return;
8279     }
8280 
8281     appData->hasApplicationProtocolSelector = hasSelector;
8282     if (hasSelector) {
8283         SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8284     }
8285 }
8286 
8287 /**
8288  * Perform SSL handshake
8289  */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8290 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8291                                           CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8292                                           jobject shc, jint timeout_millis) {
8293     CHECK_ERROR_QUEUE_ON_RETURN;
8294     SSL* ssl = to_SSL(env, ssl_address, true);
8295     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8296               shc, timeout_millis);
8297     if (ssl == nullptr) {
8298         return;
8299     }
8300     if (fdObject == nullptr) {
8301         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8302         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8303         return;
8304     }
8305     if (shc == nullptr) {
8306         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8307         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8308                   ssl);
8309         return;
8310     }
8311 
8312     NetFd fd(env, fdObject);
8313     if (fd.isClosed()) {
8314         // SocketException thrown by NetFd.isClosed
8315         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8316         return;
8317     }
8318 
8319     int ret = SSL_set_fd(ssl, fd.get());
8320     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8321 
8322     if (ret != 1) {
8323         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8324                                                            "Error setting the file descriptor");
8325         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8326         return;
8327     }
8328 
8329     /*
8330      * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8331      * forever and we can use select() to find out if the socket is ready.
8332      */
8333     if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8334         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8335         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8336         return;
8337     }
8338 
8339     AppData* appData = toAppData(ssl);
8340     if (appData == nullptr) {
8341         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8342         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8343         return;
8344     }
8345 
8346     ret = 0;
8347     SslError sslError;
8348     while (appData->aliveAndKicking) {
8349         errno = 0;
8350 
8351         if (!appData->setCallbackState(env, shc, fdObject)) {
8352             // SocketException thrown by NetFd.isClosed
8353             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8354             return;
8355         }
8356         ret = SSL_do_handshake(ssl);
8357         appData->clearCallbackState();
8358         // cert_verify_callback threw exception
8359         if (env->ExceptionCheck()) {
8360             ERR_clear_error();
8361             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8362             return;
8363         }
8364         // success case
8365         if (ret == 1) {
8366             break;
8367         }
8368         // retry case
8369         if (errno == EINTR) {
8370             continue;
8371         }
8372         // error case
8373         sslError.reset(ssl, ret);
8374         JNI_TRACE(
8375                 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8376                 "timeout_millis=%d",
8377                 ssl, ret, errno, sslError.get(), timeout_millis);
8378 
8379         /*
8380          * If SSL_do_handshake doesn't succeed due to the socket being
8381          * either unreadable or unwritable, we use sslSelect to
8382          * wait for it to become ready. If that doesn't happen
8383          * before the specified timeout or an error occurs, we
8384          * cancel the handshake. Otherwise we try the SSL_connect
8385          * again.
8386          */
8387         if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8388             appData->waitingThreads++;
8389             int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8390 
8391             if (selectResult == THROWN_EXCEPTION) {
8392                 // SocketException thrown by NetFd.isClosed
8393                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8394                 return;
8395             }
8396             if (selectResult == -1) {
8397                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8398                         env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8399                         conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8400                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8401                           ssl);
8402                 return;
8403             }
8404             if (selectResult == 0) {
8405                 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8406                 ERR_clear_error();
8407                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8408                           ssl);
8409                 return;
8410             }
8411         } else {
8412             // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8413             break;
8414         }
8415     }
8416 
8417     // clean error. See SSL_do_handshake(3SSL) man page.
8418     if (ret == 0) {
8419         /*
8420          * The other side closed the socket before the handshake could be
8421          * completed, but everything is within the bounds of the TLS protocol.
8422          * We still might want to find out the real reason of the failure.
8423          */
8424         if (sslError.get() == SSL_ERROR_NONE ||
8425             (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8426             (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8427             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8428         } else {
8429             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8430                     env, ssl, sslError.release(), "SSL handshake terminated",
8431                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8432         }
8433         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8434         return;
8435     }
8436 
8437     // unclean error. See SSL_do_handshake(3SSL) man page.
8438     if (ret < 0) {
8439         /*
8440          * Translate the error and throw exception. We are sure it is an error
8441          * at this point.
8442          */
8443         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8444                 env, ssl, sslError.release(), "SSL handshake aborted",
8445                 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8446         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
8447         return;
8448     }
8449     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
8450 }
8451 
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8452 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
8453                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
8454     CHECK_ERROR_QUEUE_ON_RETURN;
8455     SSL* ssl = to_SSL(env, ssl_address, true);
8456     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
8457     if (ssl == nullptr) {
8458         return nullptr;
8459     }
8460     const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
8461     if (cipher == nullptr) {
8462         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
8463         return nullptr;
8464     }
8465     const char* name = SSL_CIPHER_standard_name(cipher);
8466     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
8467     return env->NewStringUTF(name);
8468 }
8469 
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8470 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
8471                                             CONSCRYPT_UNUSED jobject ssl_holder) {
8472     CHECK_ERROR_QUEUE_ON_RETURN;
8473     SSL* ssl = to_SSL(env, ssl_address, true);
8474     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
8475     if (ssl == nullptr) {
8476         return nullptr;
8477     }
8478     const char* protocol = SSL_get_version(ssl);
8479     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
8480     return env->NewStringUTF(protocol);
8481 }
8482 
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8483 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
8484                                                             CONSCRYPT_UNUSED jobject ssl_holder) {
8485     CHECK_ERROR_QUEUE_ON_RETURN;
8486     SSL* ssl = to_SSL(env, ssl_address, true);
8487     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
8488     if (ssl == nullptr) {
8489         return nullptr;
8490     }
8491 
8492     const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
8493     if (chain == nullptr) {
8494         return nullptr;
8495     }
8496 
8497     ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
8498     if (array.get() == nullptr) {
8499         return nullptr;
8500     }
8501 
8502     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
8503     return array.release();
8504 }
8505 
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)8506 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8507                    SslError* sslError, int read_timeout_millis) {
8508     JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8509 
8510     if (len == 0) {
8511         // Don't bother doing anything in this case.
8512         return 0;
8513     }
8514 
8515     BIO* rbio = SSL_get_rbio(ssl);
8516     BIO* wbio = SSL_get_wbio(ssl);
8517 
8518     AppData* appData = toAppData(ssl);
8519     JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8520     if (appData == nullptr) {
8521         return THROW_SSLEXCEPTION;
8522     }
8523 
8524     while (appData->aliveAndKicking) {
8525         errno = 0;
8526 
8527         std::unique_lock<std::mutex> appDataLock(appData->mutex);
8528 
8529         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8530             !SSL_renegotiate_pending(ssl)) {
8531             JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
8532                       SSL_state_string_long(ssl));
8533             return THROW_SSLEXCEPTION;
8534         }
8535 
8536         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8537 
8538         if (!appData->setCallbackState(env, shc, fdObject)) {
8539             return THROWN_EXCEPTION;
8540         }
8541         int result = SSL_read(ssl, buf, len);
8542         appData->clearCallbackState();
8543         // callbacks can happen if server requests renegotiation
8544         if (env->ExceptionCheck()) {
8545             JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8546             return THROWN_EXCEPTION;
8547         }
8548         sslError->reset(ssl, result);
8549 
8550         JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
8551         if (conscrypt::trace::kWithJniTraceData) {
8552             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8553                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8554                 size_t n = result - i;
8555                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8556                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
8557                 }
8558                 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8559             }
8560         }
8561 
8562         // If we have been successful in moving data around, check whether it
8563         // might make sense to wake up other blocked threads, so they can give
8564         // it a try, too.
8565         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8566             appData->waitingThreads > 0) {
8567             sslNotify(appData);
8568         }
8569 
8570         // If we are blocked by the underlying socket, tell the world that
8571         // there will be one more waiting thread now.
8572         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8573             appData->waitingThreads++;
8574         }
8575 
8576         appDataLock.unlock();
8577 
8578         switch (sslError->get()) {
8579             // Successfully read at least one byte.
8580             case SSL_ERROR_NONE: {
8581                 return result;
8582             }
8583 
8584             // Read zero bytes. End of stream reached.
8585             case SSL_ERROR_ZERO_RETURN: {
8586                 return -1;
8587             }
8588 
8589             // Need to wait for availability of underlying layer, then retry.
8590             case SSL_ERROR_WANT_READ:
8591             case SSL_ERROR_WANT_WRITE: {
8592                 int selectResult =
8593                         sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
8594                 if (selectResult == THROWN_EXCEPTION) {
8595                     return THROWN_EXCEPTION;
8596                 }
8597                 if (selectResult == -1) {
8598                     return THROW_SSLEXCEPTION;
8599                 }
8600                 if (selectResult == 0) {
8601                     return THROW_SOCKETTIMEOUTEXCEPTION;
8602                 }
8603 
8604                 break;
8605             }
8606 
8607             // A problem occurred during a system call, but this is not
8608             // necessarily an error.
8609             case SSL_ERROR_SYSCALL: {
8610                 // Connection closed without proper shutdown. Tell caller we
8611                 // have reached end-of-stream.
8612                 if (result == 0) {
8613                     return -1;
8614                 }
8615 
8616                 // System call has been interrupted. Simply retry.
8617                 if (errno == EINTR) {
8618                     break;
8619                 }
8620 
8621                 // Note that for all other system call errors we fall through
8622                 // to the default case, which results in an Exception.
8623                 FALLTHROUGH_INTENDED;
8624             }
8625 
8626             // Everything else is basically an error.
8627             default: { return THROW_SSLEXCEPTION; }
8628         }
8629     }
8630 
8631     return -1;
8632 }
8633 
8634 /**
8635  * OpenSSL read function (2): read into buffer at offset n chunks.
8636  * Returns the number of bytes read (success) or value <= 0 (failure).
8637  */
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)8638 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
8639                                   CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8640                                   jobject shc, jbyteArray b, jint offset, jint len,
8641                                   jint read_timeout_millis) {
8642     CHECK_ERROR_QUEUE_ON_RETURN;
8643     SSL* ssl = to_SSL(env, ssl_address, true);
8644     JNI_TRACE(
8645             "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
8646             "read_timeout_millis=%d",
8647             ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8648     if (ssl == nullptr) {
8649         return 0;
8650     }
8651     if (fdObject == nullptr) {
8652         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8653         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8654         return 0;
8655     }
8656     if (shc == nullptr) {
8657         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8658         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8659         return 0;
8660     }
8661     if (b == nullptr) {
8662         conscrypt::jniutil::throwNullPointerException(env, "b == null");
8663         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
8664         return 0;
8665     }
8666 
8667     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8668     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8669         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8670         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
8671         return 0;
8672     }
8673 
8674     SslError sslError;
8675     int ret;
8676     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8677         if (len <= 1024) {
8678             // Allocate small buffers on the stack for performance.
8679             jbyte buf[1024];
8680             ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
8681                           read_timeout_millis);
8682             if (ret > 0) {
8683                 // Don't bother applying changes if issues were encountered.
8684                 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
8685             }
8686         } else {
8687             // Allocate larger buffers on the heap.
8688             // ARRAY_CHUNK_INVALID above ensures that len >= 0.
8689             jint remaining = len;
8690             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8691             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8692             // TODO(flooey): Use new(std::nothrow).
8693             if (buf.get() == nullptr) {
8694                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8695                 return 0;
8696             }
8697             // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
8698             // by the number of internal calls to sslRead() below.
8699             ret = 0;
8700             while (remaining > 0) {
8701                 jint temp_ret;
8702                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8703                 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
8704                                    chunk_size, &sslError, read_timeout_millis);
8705                 if (temp_ret < 0) {
8706                     if (ret > 0) {
8707                         // We've already read some bytes; attempt to preserve them if this is an
8708                         // "expected" error.
8709                         if (temp_ret == -1) {
8710                             // EOF
8711                             break;
8712                         } else if (temp_ret == THROWN_EXCEPTION) {
8713                             // FD closed. Subsequent calls to sslRead should reproduce the
8714                             // exception.
8715                             env->ExceptionClear();
8716                             break;
8717                         }
8718                     }
8719                     // An error was encountered. Handle below.
8720                     ret = temp_ret;
8721                     break;
8722                 }
8723                 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
8724                 if (env->ExceptionCheck()) {
8725                     // Error committing changes to JVM.
8726                     return -1;
8727                 }
8728                 // Accumulate bytes read.
8729                 ret += temp_ret;
8730                 offset += temp_ret;
8731                 remaining -= temp_ret;
8732                 if (temp_ret < chunk_size) {
8733                     // sslRead isn't able to fulfill our request right now.
8734                     break;
8735                 }
8736             }
8737         }
8738     } else {
8739         ScopedByteArrayRW bytes(env, b);
8740         if (bytes.get() == nullptr) {
8741             JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8742             return 0;
8743         }
8744 
8745         ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8746                       &sslError, read_timeout_millis);
8747     }
8748 
8749     int result;
8750     switch (ret) {
8751         case THROW_SSLEXCEPTION:
8752             // See sslRead() regarding improper failure to handle normal cases.
8753             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8754                                                                "Read error");
8755             result = -1;
8756             break;
8757         case THROW_SOCKETTIMEOUTEXCEPTION:
8758             conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
8759             result = -1;
8760             break;
8761         case THROWN_EXCEPTION:
8762             // SocketException thrown by NetFd.isClosed
8763             // or RuntimeException thrown by callback
8764             result = -1;
8765             break;
8766         default:
8767             result = ret;
8768             break;
8769     }
8770 
8771     JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8772     return result;
8773 }
8774 
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)8775 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8776                     SslError* sslError, int write_timeout_millis) {
8777     JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
8778               write_timeout_millis);
8779 
8780     if (len == 0) {
8781         // Don't bother doing anything in this case.
8782         return 0;
8783     }
8784 
8785     BIO* rbio = SSL_get_rbio(ssl);
8786     BIO* wbio = SSL_get_wbio(ssl);
8787 
8788     AppData* appData = toAppData(ssl);
8789     JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8790     if (appData == nullptr) {
8791         return THROW_SSLEXCEPTION;
8792     }
8793 
8794     int count = len;
8795 
8796     while (appData->aliveAndKicking && len > 0) {
8797         errno = 0;
8798 
8799         std::unique_lock<std::mutex> appDataLock(appData->mutex);
8800 
8801         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8802             !SSL_renegotiate_pending(ssl)) {
8803             JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
8804                       SSL_state_string_long(ssl));
8805             return THROW_SSLEXCEPTION;
8806         }
8807 
8808         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8809 
8810         if (!appData->setCallbackState(env, shc, fdObject)) {
8811             return THROWN_EXCEPTION;
8812         }
8813         JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
8814         int result = SSL_write(ssl, buf, len);
8815         appData->clearCallbackState();
8816         // callbacks can happen if server requests renegotiation
8817         if (env->ExceptionCheck()) {
8818             JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8819             return THROWN_EXCEPTION;
8820         }
8821         sslError->reset(ssl, result);
8822 
8823         JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
8824         if (conscrypt::trace::kWithJniTraceData) {
8825             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8826                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8827                 size_t n = result - i;
8828                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8829                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
8830                 }
8831                 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8832             }
8833         }
8834 
8835         // If we have been successful in moving data around, check whether it
8836         // might make sense to wake up other blocked threads, so they can give
8837         // it a try, too.
8838         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8839             appData->waitingThreads > 0) {
8840             sslNotify(appData);
8841         }
8842 
8843         // If we are blocked by the underlying socket, tell the world that
8844         // there will be one more waiting thread now.
8845         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8846             appData->waitingThreads++;
8847         }
8848 
8849         appDataLock.unlock();
8850 
8851         switch (sslError->get()) {
8852             // Successfully wrote at least one byte.
8853             case SSL_ERROR_NONE: {
8854                 buf += result;
8855                 len -= result;
8856                 break;
8857             }
8858 
8859             // Wrote zero bytes. End of stream reached.
8860             case SSL_ERROR_ZERO_RETURN: {
8861                 return -1;
8862             }
8863 
8864             // Need to wait for availability of underlying layer, then retry.
8865             // The concept of a write timeout doesn't really make sense, and
8866             // it's also not standard Java behavior, so we wait forever here.
8867             case SSL_ERROR_WANT_READ:
8868             case SSL_ERROR_WANT_WRITE: {
8869                 int selectResult =
8870                         sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
8871                 if (selectResult == THROWN_EXCEPTION) {
8872                     return THROWN_EXCEPTION;
8873                 }
8874                 if (selectResult == -1) {
8875                     return THROW_SSLEXCEPTION;
8876                 }
8877                 if (selectResult == 0) {
8878                     return THROW_SOCKETTIMEOUTEXCEPTION;
8879                 }
8880 
8881                 break;
8882             }
8883 
8884             // A problem occurred during a system call, but this is not
8885             // necessarily an error.
8886             case SSL_ERROR_SYSCALL: {
8887                 // Connection closed without proper shutdown. Tell caller we
8888                 // have reached end-of-stream.
8889                 if (result == 0) {
8890                     return -1;
8891                 }
8892 
8893                 // System call has been interrupted. Simply retry.
8894                 if (errno == EINTR) {
8895                     break;
8896                 }
8897 
8898                 // Note that for all other system call errors we fall through
8899                 // to the default case, which results in an Exception.
8900                 FALLTHROUGH_INTENDED;
8901             }
8902 
8903             // Everything else is basically an error.
8904             default: { return THROW_SSLEXCEPTION; }
8905         }
8906     }
8907     JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8908 
8909     return count;
8910 }
8911 
8912 /**
8913  * OpenSSL write function (2): write into buffer at offset n chunks.
8914  */
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)8915 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
8916                                    CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8917                                    jobject shc, jbyteArray b, jint offset, jint len,
8918                                    jint write_timeout_millis) {
8919     CHECK_ERROR_QUEUE_ON_RETURN;
8920     SSL* ssl = to_SSL(env, ssl_address, true);
8921     JNI_TRACE(
8922             "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
8923             "write_timeout_millis=%d",
8924             ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8925     if (ssl == nullptr) {
8926         return;
8927     }
8928     if (fdObject == nullptr) {
8929         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8930         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8931         return;
8932     }
8933     if (shc == nullptr) {
8934         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8935         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8936         return;
8937     }
8938     if (b == nullptr) {
8939         conscrypt::jniutil::throwNullPointerException(env, "b == null");
8940         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
8941         return;
8942     }
8943 
8944     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8945     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8946         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8947         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
8948         return;
8949     }
8950 
8951     SslError sslError;
8952     int ret;
8953     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8954         if (len <= 1024) {
8955             jbyte buf[1024];
8956             env->GetByteArrayRegion(b, offset, len, buf);
8957             ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
8958                            &sslError, write_timeout_millis);
8959         } else {
8960             // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
8961             jint remaining = len;
8962             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8963             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8964             if (buf.get() == nullptr) {
8965                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8966                 return;
8967             }
8968             while (remaining > 0) {
8969                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8970                 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
8971                 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
8972                                chunk_size, &sslError, write_timeout_millis);
8973                 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
8974                     ret == THROWN_EXCEPTION) {
8975                     // Encountered an error. Terminate early and handle below.
8976                     break;
8977                 }
8978                 offset += ret;
8979                 remaining -= ret;
8980             }
8981         }
8982     } else {
8983         ScopedByteArrayRO bytes(env, b);
8984         if (bytes.get() == nullptr) {
8985             JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8986             return;
8987         }
8988         ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8989                        len, &sslError, write_timeout_millis);
8990     }
8991 
8992     switch (ret) {
8993         case THROW_SSLEXCEPTION:
8994             // See sslWrite() regarding improper failure to handle normal cases.
8995             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8996                                                                "Write error");
8997             break;
8998         case THROW_SOCKETTIMEOUTEXCEPTION:
8999             conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9000             break;
9001         case THROWN_EXCEPTION:
9002             // SocketException thrown by NetFd.isClosed
9003             break;
9004         default:
9005             break;
9006     }
9007 }
9008 
9009 /**
9010  * Interrupt any pending I/O before closing the socket.
9011  */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9012 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9013                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9014     CHECK_ERROR_QUEUE_ON_RETURN;
9015     SSL* ssl = to_SSL(env, ssl_address, false);
9016     JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9017     if (ssl == nullptr) {
9018         return;
9019     }
9020 
9021     /*
9022      * Mark the connection as quasi-dead, then send something to the emergency
9023      * file descriptor, so any blocking select() calls are woken up.
9024      */
9025     AppData* appData = toAppData(ssl);
9026     if (appData != nullptr) {
9027         appData->aliveAndKicking = false;
9028 
9029         // At most two threads can be waiting.
9030         sslNotify(appData);
9031         sslNotify(appData);
9032     }
9033 }
9034 
9035 /**
9036  * OpenSSL close SSL socket function.
9037  */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9038 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9039                                       CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9040                                       jobject shc) {
9041     CHECK_ERROR_QUEUE_ON_RETURN;
9042     SSL* ssl = to_SSL(env, ssl_address, false);
9043     JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9044     if (ssl == nullptr) {
9045         return;
9046     }
9047     if (fdObject == nullptr) {
9048         return;
9049     }
9050     if (shc == nullptr) {
9051         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9052         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9053         return;
9054     }
9055 
9056     AppData* appData = toAppData(ssl);
9057     if (appData != nullptr) {
9058         if (!appData->setCallbackState(env, shc, fdObject)) {
9059             // SocketException thrown by NetFd.isClosed
9060             ERR_clear_error();
9061             return;
9062         }
9063 
9064         /*
9065          * Try to make socket blocking again. OpenSSL literature recommends this.
9066          */
9067         int fd = SSL_get_fd(ssl);
9068         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9069 #ifndef _WIN32
9070         if (fd != -1) {
9071             conscrypt::netutil::setBlocking(fd, true);
9072         }
9073 #endif
9074 
9075         int ret = SSL_shutdown(ssl);
9076         appData->clearCallbackState();
9077         // callbacks can happen if server requests renegotiation
9078         if (env->ExceptionCheck()) {
9079             JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9080             return;
9081         }
9082         switch (ret) {
9083             case 0:
9084                 /*
9085                  * Shutdown was not successful (yet), but there also
9086                  * is no error. Since we can't know whether the remote
9087                  * server is actually still there, and we don't want to
9088                  * get stuck forever in a second SSL_shutdown() call, we
9089                  * simply return. This is not security a problem as long
9090                  * as we close the underlying socket, which we actually
9091                  * do, because that's where we are just coming from.
9092                  */
9093                 break;
9094             case 1:
9095                 /*
9096                  * Shutdown was successful. We can safely return. Hooray!
9097                  */
9098                 break;
9099             default:
9100                 /*
9101                  * Everything else is a real error condition. We should
9102                  * let the Java layer know about this by throwing an
9103                  * exception.
9104                  */
9105                 int sslError = SSL_get_error(ssl, ret);
9106                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9107                                                                    "SSL shutdown failed");
9108                 break;
9109         }
9110     }
9111 
9112     ERR_clear_error();
9113 }
9114 
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9115 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9116                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9117     CHECK_ERROR_QUEUE_ON_RETURN;
9118     const SSL* ssl = to_SSL(env, ssl_address, true);
9119     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9120     if (ssl == nullptr) {
9121         return 0;
9122     }
9123 
9124     int status = SSL_get_shutdown(ssl);
9125     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9126     return static_cast<jint>(status);
9127 }
9128 
9129 /**
9130  * public static native void SSL_free(long ssl);
9131  */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9132 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9133                                   CONSCRYPT_UNUSED jobject ssl_holder) {
9134     CHECK_ERROR_QUEUE_ON_RETURN;
9135     SSL* ssl = to_SSL(env, ssl_address, true);
9136     JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9137     if (ssl == nullptr) {
9138         return;
9139     }
9140 
9141     AppData* appData = toAppData(ssl);
9142     SSL_set_app_data(ssl, nullptr);
9143     delete appData;
9144     SSL_free(ssl);
9145 }
9146 
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9147 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9148     unsigned int length;
9149     const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9150     JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9151     if (id && length > 0) {
9152         jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9153         if (result != nullptr) {
9154             const jbyte* src = reinterpret_cast<const jbyte*>(id);
9155             env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9156         }
9157         return result;
9158     }
9159     return nullptr;
9160 }
9161 
9162 /**
9163  * Gets and returns in a byte array the ID of the actual SSL session.
9164  */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9165 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9166                                                       jlong ssl_session_address) {
9167     CHECK_ERROR_QUEUE_ON_RETURN;
9168     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9169     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9170     if (ssl_session == nullptr) {
9171         return nullptr;
9172     }
9173     jbyteArray result = get_session_id(env, ssl_session);
9174     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9175     return result;
9176 }
9177 
9178 /**
9179  * Gets and returns in a long integer the creation's time of the
9180  * actual SSL session.
9181  */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9182 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9183     CHECK_ERROR_QUEUE_ON_RETURN;
9184     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9185     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9186     if (ssl_session == nullptr) {
9187         return 0;
9188     }
9189     // result must be jlong, not long or *1000 will overflow
9190     jlong result = SSL_SESSION_get_time(ssl_session);
9191     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9192     // NOLINTNEXTLINE(runtime/int)
9193     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9194               (long long)result);  // NOLINT(runtime/int)
9195     return result;
9196 }
9197 
9198 /**
9199  * Gets and returns in a long integer the creation's time of the
9200  * actual SSL session.
9201  */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9202 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9203                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9204     CHECK_ERROR_QUEUE_ON_RETURN;
9205     SSL* ssl = to_SSL(env, ssl_address, true);
9206     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9207     if (ssl == nullptr) {
9208         return 0;
9209     }
9210 
9211     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9212     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9213     if (ssl_session == nullptr) {
9214         // BoringSSL does not protect against a NULL session.
9215         return 0;
9216     }
9217     // result must be jlong, not long or *1000 will overflow
9218     jlong result = SSL_SESSION_get_time(ssl_session);
9219     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9220     // NOLINTNEXTLINE(runtime/int)
9221     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9222     return result;
9223 }
9224 
9225 /**
9226  * Sets the timeout on the SSL session.
9227  */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9228 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9229                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9230     CHECK_ERROR_QUEUE_ON_RETURN;
9231     SSL* ssl = to_SSL(env, ssl_address, true);
9232     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9233     if (ssl == nullptr) {
9234         return 0;
9235     }
9236 
9237     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9238     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9239     if (ssl_session == nullptr) {
9240         // BoringSSL does not protect against a NULL session.
9241         return 0;
9242     }
9243 
9244     // Convert to seconds
9245     static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9246     uint32_t timeout = static_cast<uint32_t>(
9247             std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9248     return SSL_set_timeout(ssl_session, timeout);
9249 }
9250 
9251 /**
9252  * Gets the timeout for the SSL session.
9253  */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9254 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9255                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9256     CHECK_ERROR_QUEUE_ON_RETURN;
9257     SSL* ssl = to_SSL(env, ssl_address, true);
9258     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9259     if (ssl == nullptr) {
9260         return 0;
9261     }
9262 
9263     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9264     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9265     if (ssl_session == nullptr) {
9266         // BoringSSL does not protect against a NULL session.
9267         return 0;
9268     }
9269 
9270     jlong result = SSL_get_timeout(ssl_session);
9271     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9272     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9273               (long long)result)  // NOLINT(runtime/int);
9274     return result;
9275 }
9276 
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9277 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9278                                                               jint signatureAlg) {
9279     CHECK_ERROR_QUEUE_ON_RETURN;
9280     return SSL_get_signature_algorithm_key_type(signatureAlg);
9281 }
9282 
9283 /**
9284  * Gets the timeout for the SSL session.
9285  */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9286 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9287     CHECK_ERROR_QUEUE_ON_RETURN;
9288     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9289     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9290     if (ssl_session == nullptr) {
9291         return 0;
9292     }
9293 
9294     return SSL_get_timeout(ssl_session);
9295 }
9296 
9297 /**
9298  * Gets the ID for the SSL session, or null if no session is currently available.
9299  */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9300 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9301                                               CONSCRYPT_UNUSED jobject ssl_holder) {
9302     CHECK_ERROR_QUEUE_ON_RETURN;
9303     SSL* ssl = to_SSL(env, ssl_address, true);
9304     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9305     if (ssl == nullptr) {
9306         return nullptr;
9307     }
9308 
9309     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9310     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9311     if (ssl_session == nullptr) {
9312         return nullptr;
9313     }
9314     jbyteArray result = get_session_id(env, ssl_session);
9315     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9316     return result;
9317 }
9318 
9319 /**
9320  * Gets and returns in a string the version of the SSL protocol. If it
9321  * returns the string "unknown" it means that no connection is established.
9322  */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9323 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9324                                                     jlong ssl_session_address) {
9325     CHECK_ERROR_QUEUE_ON_RETURN;
9326     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9327     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9328     if (ssl_session == nullptr) {
9329         return nullptr;
9330     }
9331     const char* protocol = SSL_SESSION_get_version(ssl_session);
9332     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9333     return env->NewStringUTF(protocol);
9334 }
9335 
9336 /**
9337  * Gets and returns in a string the cipher negotiated for the SSL session.
9338  */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9339 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9340     CHECK_ERROR_QUEUE_ON_RETURN;
9341     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9342     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9343     if (ssl_session == nullptr) {
9344         return nullptr;
9345     }
9346     const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9347     const char* name = SSL_CIPHER_standard_name(cipher);
9348     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9349     return env->NewStringUTF(name);
9350 }
9351 
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9352 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9353                                                               jlong ssl_session_address) {
9354     CHECK_ERROR_QUEUE_ON_RETURN;
9355     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9356     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9357     if (ssl_session == nullptr) {
9358         return JNI_FALSE;
9359     }
9360     int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9361     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9362               single_use);
9363     return single_use ? JNI_TRUE : JNI_FALSE;
9364 }
9365 
9366 /**
9367  * Increments the reference count of the session.
9368  */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9369 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9370     CHECK_ERROR_QUEUE_ON_RETURN;
9371     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9372     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9373     if (ssl_session == nullptr) {
9374         return;
9375     }
9376     SSL_SESSION_up_ref(ssl_session);
9377 }
9378 
9379 /**
9380  * Frees the SSL session.
9381  */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9382 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9383     CHECK_ERROR_QUEUE_ON_RETURN;
9384     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9385     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9386     if (ssl_session == nullptr) {
9387         return;
9388     }
9389     SSL_SESSION_free(ssl_session);
9390 }
9391 
9392 /**
9393  * Serializes the native state of the session (ID, cipher, and keys but
9394  * not certificates). Returns a byte[] containing the DER-encoded state.
9395  * See apache mod_ssl.
9396  */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9397 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9398     CHECK_ERROR_QUEUE_ON_RETURN;
9399     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9400     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9401     if (ssl_session == nullptr) {
9402         return nullptr;
9403     }
9404     return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9405 }
9406 
9407 /**
9408  * Deserialize the session.
9409  */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9410 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9411     CHECK_ERROR_QUEUE_ON_RETURN;
9412     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9413 
9414     ScopedByteArrayRO bytes(env, javaBytes);
9415     if (bytes.get() == nullptr) {
9416         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9417         return 0;
9418     }
9419     const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9420     // NOLINTNEXTLINE(runtime/int)
9421     SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9422 
9423     if (ssl_session == nullptr ||
9424         ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9425         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9426                                                              conscrypt::jniutil::throwIOException);
9427         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9428         return 0L;
9429     }
9430 
9431     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9432     return reinterpret_cast<uintptr_t>(ssl_session);
9433 }
9434 
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9435 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9436     CHECK_ERROR_QUEUE_ON_RETURN;
9437     const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
9438     if (cipher == nullptr) {
9439         return nullptr;
9440     }
9441 
9442     const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
9443     return env->NewStringUTF(kx_name);
9444 }
9445 
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)9446 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
9447     CHECK_ERROR_QUEUE_ON_RETURN;
9448     ScopedUtfChars selector(env, selectorJava);
9449     if (selector.c_str() == nullptr) {
9450         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9451                                            "selector == null");
9452         return nullptr;
9453     }
9454 
9455     JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
9456 
9457     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
9458     bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
9459 
9460     if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
9461         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9462                                            "Unable to set SSL cipher list");
9463         return nullptr;
9464     }
9465     STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
9466 
9467     size_t size = sk_SSL_CIPHER_num(ciphers);
9468     ScopedLocalRef<jobjectArray> cipherNamesArray(
9469             env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
9470                                      nullptr));
9471     if (cipherNamesArray.get() == nullptr) {
9472         return nullptr;
9473     }
9474 
9475     // Return an array of standard and OpenSSL name pairs.
9476     for (size_t i = 0; i < size; i++) {
9477         const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
9478         ScopedLocalRef<jstring> cipherName(env,
9479                                            env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
9480         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
9481                                    cipherName.get());
9482 
9483         ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
9484         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
9485                                    opensslName.get());
9486     }
9487 
9488     JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
9489               2 * size);
9490     return cipherNamesArray.release();
9491 }
9492 
9493 /**
9494  * Compare the given CertID with a certificate and it's issuer.
9495  * True is returned if the CertID matches.
9496  */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)9497 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
9498     // Get the hash algorithm used by this CertID
9499     CBS hash_algorithm, hash;
9500     if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
9501         !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
9502         return false;
9503     }
9504 
9505     // Get the issuer's name hash from the CertID
9506     CBS issuer_name_hash;
9507     if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
9508         return false;
9509     }
9510 
9511     // Get the issuer's key hash from the CertID
9512     CBS issuer_key_hash;
9513     if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
9514         return false;
9515     }
9516 
9517     // Get the serial number from the CertID
9518     CBS serial;
9519     if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
9520         return false;
9521     }
9522 
9523     // Compare the certificate's serial number with the one from the Cert ID
9524     const uint8_t* p = CBS_data(&serial);
9525     bssl::UniquePtr<ASN1_INTEGER> serial_number(
9526             c2i_ASN1_INTEGER(nullptr, &p,
9527                              static_cast<long>(CBS_len(&serial))));  // NOLINT(runtime/int)
9528     const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
9529     if (serial_number.get() == nullptr ||
9530         ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
9531         return false;
9532     }
9533 
9534     // Find the hash algorithm to be used
9535     const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
9536     if (digest == nullptr) {
9537         return false;
9538     }
9539 
9540     // Hash the issuer's name and compare the hash with the one from the Cert ID
9541     uint8_t md[EVP_MAX_MD_SIZE];
9542     const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
9543     if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
9544         !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
9545         return false;
9546     }
9547 
9548     // Same thing with the issuer's key
9549     const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
9550     if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
9551                     static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
9552                     nullptr) ||
9553         !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
9554         return false;
9555     }
9556 
9557     return true;
9558 }
9559 
9560 /**
9561  * Get a SingleResponse whose CertID matches the given certificate and issuer from a
9562  * SEQUENCE OF SingleResponse.
9563  *
9564  * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
9565  * error occured or no response matches the certificate, false is returned and |out_single_response|
9566  * is unchanged.
9567  */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)9568 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
9569                                       CBS* out_single_response) {
9570     // Iterate over all the SingleResponses, until one matches the certificate
9571     while (CBS_len(responses) > 0) {
9572         // Get the next available SingleResponse from the sequence
9573         CBS single_response;
9574         if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
9575             return false;
9576         }
9577 
9578         // Make a copy of the stream so we pass it back to the caller
9579         CBS single_response_original = single_response;
9580 
9581         // Get the SingleResponse's CertID
9582         // If this fails ignore the current response and move to the next one
9583         CBS cert_id;
9584         if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
9585             continue;
9586         }
9587 
9588         // Compare the CertID with the given certificate and issuer
9589         if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
9590             *out_single_response = single_response_original;
9591             return true;
9592         }
9593     }
9594 
9595     return false;
9596 }
9597 
9598 /**
9599  * Get the BasicOCSPResponse from an OCSPResponse.
9600  * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
9601  * returned.
9602  */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)9603 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
9604     CBS tagged_response_bytes, response_bytes, response_type, response;
9605 
9606     // Get the ResponseBytes out of the OCSPResponse
9607     if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
9608         !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
9609                       CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9610         !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
9611         return false;
9612     }
9613 
9614     // Parse the response type and data out of the ResponseBytes
9615     if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
9616         !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
9617         return false;
9618     }
9619 
9620     // Only basic OCSP responses are supported
9621     if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
9622         return false;
9623     }
9624 
9625     // Parse the octet string as a BasicOCSPResponse
9626     return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
9627 }
9628 
9629 /**
9630  * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
9631  * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
9632  * true is returned.
9633  */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)9634 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
9635     // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
9636     CBS response_data;
9637     if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
9638         return false;
9639     }
9640 
9641     // Skip the version, responderID and producedAt fields
9642     if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
9643                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9644         !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
9645         !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
9646         return false;
9647     }
9648 
9649     // Extract the list of SingleResponse.
9650     return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
9651 }
9652 
9653 /**
9654  * Get the SEQUENCE OF Extension from a SingleResponse.
9655  * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
9656  * returned.
9657  */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)9658 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
9659     // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
9660     if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
9661         !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
9662         !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
9663         !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
9664                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
9665         return false;
9666     }
9667 
9668     // Get the list of Extension
9669     return CBS_get_asn1(single_response, extensions,
9670                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
9671 }
9672 
9673 /*
9674     public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
9675                                                           long x509Ref, long issuerX509Ref);
9676 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)9677 static jbyteArray NativeCrypto_get_ocsp_single_extension(
9678         JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
9679         CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
9680     CHECK_ERROR_QUEUE_ON_RETURN;
9681     ScopedByteArrayRO ocspData(env, ocspDataBytes);
9682     if (ocspData.get() == nullptr) {
9683         return nullptr;
9684     }
9685 
9686     CBS cbs;
9687     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
9688 
9689     // Start parsing the OCSPResponse
9690     CBS ocsp_response;
9691     if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
9692         return nullptr;
9693     }
9694 
9695     // Get the BasicOCSPResponse from the OCSP Response
9696     CBS basic_response;
9697     if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
9698         return nullptr;
9699     }
9700 
9701     // Get the list of SingleResponses from the BasicOCSPResponse
9702     CBS responses;
9703     if (!get_ocsp_single_responses(&basic_response, &responses)) {
9704         return nullptr;
9705     }
9706 
9707     // Find the response matching the certificate
9708     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
9709     X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
9710     CBS single_response;
9711     if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
9712         return nullptr;
9713     }
9714 
9715     // Get the extensions from the SingleResponse
9716     CBS extensions;
9717     if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
9718         return nullptr;
9719     }
9720 
9721     const uint8_t* ptr = CBS_data(&extensions);
9722     bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
9723             d2i_X509_EXTENSIONS(nullptr, &ptr,
9724                                 static_cast<long>(CBS_len(&extensions))));  // NOLINT(runtime/int)
9725     if (x509_exts.get() == nullptr) {
9726         return nullptr;
9727     }
9728 
9729     return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
9730             env, x509_exts.get(), oid);
9731 }
9732 
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)9733 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
9734     // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
9735     // no throwing if the buffer is null or not a direct ByteBuffer.
9736     if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
9737         return 0;
9738     }
9739     return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
9740 }
9741 
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)9742 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
9743                                        CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
9744     CHECK_ERROR_QUEUE_ON_RETURN;
9745     SSL* ssl = to_SSL(env, ssl_address, true);
9746     if (ssl == nullptr) {
9747         return 0;
9748     }
9749     return SSL_get_error(ssl, ret);
9750 }
9751 
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)9752 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
9753     ERR_clear_error();
9754 }
9755 
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9756 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
9757                                                     CONSCRYPT_UNUSED jobject ssl_holder) {
9758     CHECK_ERROR_QUEUE_ON_RETURN;
9759     SSL* ssl = to_SSL(env, ssl_address, true);
9760     if (ssl == nullptr) {
9761         return 0;
9762     }
9763     return SSL_pending(ssl);
9764 }
9765 
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)9766 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
9767     CHECK_ERROR_QUEUE_ON_RETURN;
9768     BIO* bio = to_BIO(env, bio_address);
9769     if (bio == nullptr) {
9770         return 0;
9771     }
9772     return static_cast<jint>(BIO_ctrl_pending(bio));
9773 }
9774 
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9775 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
9776                                                CONSCRYPT_UNUSED jobject ssl_holder) {
9777     CHECK_ERROR_QUEUE_ON_RETURN;
9778     SSL* ssl = to_SSL(env, ssl_address, true);
9779     if (ssl == nullptr) {
9780         return 0;
9781     }
9782     return (jint)SSL_max_seal_overhead(ssl);
9783 }
9784 
9785 /**
9786  * public static native int SSL_new_BIO(long ssl) throws SSLException;
9787  */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9788 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
9789                                       CONSCRYPT_UNUSED jobject ssl_holder) {
9790     CHECK_ERROR_QUEUE_ON_RETURN;
9791     SSL* ssl = to_SSL(env, ssl_address, true);
9792     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
9793     if (ssl == nullptr) {
9794         return 0;
9795     }
9796 
9797     BIO* internal_bio;
9798     BIO* network_bio;
9799     if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
9800         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9801                                                            "BIO_new_bio_pair failed");
9802         JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
9803         return 0;
9804     }
9805 
9806     SSL_set_bio(ssl, internal_bio, internal_bio);
9807 
9808     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
9809     return reinterpret_cast<uintptr_t>(network_bio);
9810 }
9811 
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9812 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9813                                                  CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9814     CHECK_ERROR_QUEUE_ON_RETURN;
9815     SSL* ssl = to_SSL(env, ssl_address, true);
9816     if (ssl == nullptr) {
9817         return 0;
9818     }
9819     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
9820 
9821     if (shc == nullptr) {
9822         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9823         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
9824                   ssl);
9825         return 0;
9826     }
9827 
9828     AppData* appData = toAppData(ssl);
9829     if (appData == nullptr) {
9830         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9831         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
9832         return 0;
9833     }
9834 
9835     errno = 0;
9836 
9837     if (!appData->setCallbackState(env, shc, nullptr)) {
9838         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9839         ERR_clear_error();
9840         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9841         return 0;
9842     }
9843 
9844     int ret = SSL_do_handshake(ssl);
9845     appData->clearCallbackState();
9846     if (env->ExceptionCheck()) {
9847         // cert_verify_callback threw exception
9848         ERR_clear_error();
9849         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9850         return 0;
9851     }
9852 
9853     SslError sslError(ssl, ret);
9854     int code = sslError.get();
9855 
9856     if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
9857         // Non-exceptional case.
9858         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
9859         return code;
9860     }
9861 
9862     // Exceptional case...
9863     if (ret == 0) {
9864         // TODO(nmittler): Can this happen with memory BIOs?
9865         /*
9866          * Clean error. See SSL_do_handshake(3SSL) man page.
9867          * The other side closed the socket before the handshake could be
9868          * completed, but everything is within the bounds of the TLS protocol.
9869          * We still might want to find out the real reason of the failure.
9870          */
9871         if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
9872             (code == SSL_ERROR_ZERO_RETURN)) {
9873             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9874         } else {
9875             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9876                     env, ssl, sslError.release(), "SSL handshake terminated",
9877                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9878         }
9879         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9880         return code;
9881     }
9882 
9883     /*
9884      * Unclean error. See SSL_do_handshake(3SSL) man page.
9885      * Translate the error and throw exception. We are sure it is an error
9886      * at this point.
9887      */
9888     conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9889             env, ssl, sslError.release(), "SSL handshake aborted",
9890             conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9891     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9892     return code;
9893 }
9894 
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9895 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9896                                              CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9897     CHECK_ERROR_QUEUE_ON_RETURN;
9898     SSL* ssl = to_SSL(env, ssl_address, false);
9899     if (ssl == nullptr) {
9900         return;
9901     }
9902     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
9903 
9904     if (shc == nullptr) {
9905         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9906         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9907         return;
9908     }
9909 
9910     AppData* appData = toAppData(ssl);
9911     if (appData != nullptr) {
9912         if (!appData->setCallbackState(env, shc, nullptr)) {
9913             conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9914             ERR_clear_error();
9915             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9916             return;
9917         }
9918         int ret = SSL_shutdown(ssl);
9919         appData->clearCallbackState();
9920         // callbacks can happen if server requests renegotiation
9921         if (env->ExceptionCheck()) {
9922             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9923             return;
9924         }
9925         switch (ret) {
9926             case 0:
9927                 /*
9928                  * Shutdown was not successful (yet), but there also
9929                  * is no error. Since we can't know whether the remote
9930                  * server is actually still there, and we don't want to
9931                  * get stuck forever in a second SSL_shutdown() call, we
9932                  * simply return. This is not security a problem as long
9933                  * as we close the underlying socket, which we actually
9934                  * do, because that's where we are just coming from.
9935                  */
9936                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
9937                 break;
9938             case 1:
9939                 /*
9940                  * Shutdown was successful. We can safely return. Hooray!
9941                  */
9942                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
9943                 break;
9944             default:
9945                 /*
9946                  * Everything else is a real error condition. We should
9947                  * let the Java layer know about this by throwing an
9948                  * exception.
9949                  */
9950                 int sslError = SSL_get_error(ssl, ret);
9951                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
9952                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9953                                                                    "SSL shutdown failed");
9954                 break;
9955         }
9956     }
9957 
9958     ERR_clear_error();
9959 }
9960 
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)9961 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
9962                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9963                                                 jint length, jobject shc) {
9964     CHECK_ERROR_QUEUE_ON_RETURN;
9965     SSL* ssl = to_SSL(env, ssl_address, true);
9966     char* destPtr = reinterpret_cast<char*>(address);
9967     if (ssl == nullptr) {
9968         return -1;
9969     }
9970     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
9971               destPtr, length, shc);
9972 
9973     if (shc == nullptr) {
9974         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9975         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
9976                   ssl);
9977         return -1;
9978     }
9979     AppData* appData = toAppData(ssl);
9980     if (appData == nullptr) {
9981         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9982         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
9983         return -1;
9984     }
9985     if (!appData->setCallbackState(env, shc, nullptr)) {
9986         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9987         ERR_clear_error();
9988         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
9989         return -1;
9990     }
9991 
9992     errno = 0;
9993 
9994     int result = SSL_read(ssl, destPtr, length);
9995     appData->clearCallbackState();
9996     if (env->ExceptionCheck()) {
9997         // An exception was thrown by one of the callbacks. Just propagate that exception.
9998         ERR_clear_error();
9999         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10000         return -1;
10001     }
10002 
10003     SslError sslError(ssl, result);
10004     switch (sslError.get()) {
10005         case SSL_ERROR_NONE: {
10006             // Successfully read at least one byte. Just return the result.
10007             break;
10008         }
10009         case SSL_ERROR_ZERO_RETURN: {
10010             // A close_notify was received, this stream is finished.
10011             return -SSL_ERROR_ZERO_RETURN;
10012         }
10013         case SSL_ERROR_WANT_READ:
10014         case SSL_ERROR_WANT_WRITE: {
10015             // Return the negative of these values.
10016             result = -sslError.get();
10017             break;
10018         }
10019         case SSL_ERROR_SYSCALL: {
10020             // A problem occurred during a system call, but this is not
10021             // necessarily an error.
10022             if (result == 0) {
10023                 // TODO(nmittler): Can this happen with memory BIOs?
10024                 // Connection closed without proper shutdown. Tell caller we
10025                 // have reached end-of-stream.
10026                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10027                 break;
10028             }
10029 
10030             if (errno == EINTR) {
10031                 // TODO(nmittler): Can this happen with memory BIOs?
10032                 // System call has been interrupted. Simply retry.
10033                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10034                                                    "Read error");
10035                 break;
10036             }
10037 
10038             // Note that for all other system call errors we fall through
10039             // to the default case, which results in an Exception.
10040             FALLTHROUGH_INTENDED;
10041         }
10042         default: {
10043             // Everything else is basically an error.
10044             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10045                                                                "Read error");
10046             break;
10047         }
10048     }
10049 
10050     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10051               ssl, destPtr, length, shc, result);
10052     return result;
10053 }
10054 
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)10055 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10056                                                     CONSCRYPT_UNUSED jobject ssl_holder,
10057                                                     jlong bioRef, jlong address, jint len,
10058                                                     jobject shc) {
10059     CHECK_ERROR_QUEUE_ON_RETURN;
10060     SSL* ssl = to_SSL(env, ssl_address, true);
10061     if (ssl == nullptr) {
10062         return -1;
10063     }
10064     if (shc == nullptr) {
10065         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10066         JNI_TRACE(
10067                 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10068                 "sslHandshakeCallbacks == null",
10069                 ssl);
10070         return -1;
10071     }
10072     BIO* bio = to_BIO(env, bioRef);
10073     if (bio == nullptr) {
10074         return -1;
10075     }
10076     if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10077         // The network BIO couldn't handle the entire write. Don't write anything, so that we
10078         // only process one packet at a time.
10079         return 0;
10080     }
10081     const char* sourcePtr = reinterpret_cast<const char*>(address);
10082 
10083     AppData* appData = toAppData(ssl);
10084     if (appData == nullptr) {
10085         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10086         ERR_clear_error();
10087         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10088         return -1;
10089     }
10090     if (!appData->setCallbackState(env, shc, nullptr)) {
10091         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10092         ERR_clear_error();
10093         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10094         return -1;
10095     }
10096 
10097     errno = 0;
10098 
10099     int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10100     appData->clearCallbackState();
10101     JNI_TRACE(
10102             "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10103             "ret=%d",
10104             ssl, bio, sourcePtr, len, shc, result);
10105     JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10106                           static_cast<size_t>(result));
10107     return result;
10108 }
10109 
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)10110 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10111                                                    CONSCRYPT_UNUSED jobject ssl_holder,
10112                                                    jlong bioRef, jlong address, jint outputSize,
10113                                                    jobject shc) {
10114     CHECK_ERROR_QUEUE_ON_RETURN;
10115     SSL* ssl = to_SSL(env, ssl_address, true);
10116     if (ssl == nullptr) {
10117         return -1;
10118     }
10119     if (shc == nullptr) {
10120         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10121         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10122                   ssl);
10123         return -1;
10124     }
10125     BIO* bio = to_BIO(env, bioRef);
10126     if (bio == nullptr) {
10127         return -1;
10128     }
10129     char* destPtr = reinterpret_cast<char*>(address);
10130     if (destPtr == nullptr) {
10131         conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10132         return -1;
10133     }
10134 
10135     AppData* appData = toAppData(ssl);
10136     if (appData == nullptr) {
10137         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10138         ERR_clear_error();
10139         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10140         return -1;
10141     }
10142     if (!appData->setCallbackState(env, shc, nullptr)) {
10143         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10144         ERR_clear_error();
10145         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10146         return -1;
10147     }
10148 
10149     errno = 0;
10150 
10151     int result = BIO_read(bio, destPtr, outputSize);
10152     appData->clearCallbackState();
10153     JNI_TRACE(
10154             "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10155             "=> ret=%d",
10156             ssl, bio, destPtr, outputSize, shc, result);
10157     JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10158     return result;
10159 }
10160 
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10161 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10162                                                CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10163     CHECK_ERROR_QUEUE_ON_RETURN;
10164     SSL* ssl = to_SSL(env, ssl_address, true);
10165     if (ssl == nullptr) {
10166         return;
10167     }
10168     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10169     if (shc == nullptr) {
10170         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10171         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10172                   ssl);
10173         return;
10174     }
10175     AppData* appData = toAppData(ssl);
10176     if (appData == nullptr) {
10177         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10178         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10179         return;
10180     }
10181     if (!appData->setCallbackState(env, shc, nullptr)) {
10182         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10183         ERR_clear_error();
10184         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10185         return;
10186     }
10187     char c;
10188     int result = SSL_peek(ssl, &c, 1);
10189     appData->clearCallbackState();
10190     if (env->ExceptionCheck()) {
10191         // An exception was thrown by one of the callbacks. Just propagate that exception.
10192         ERR_clear_error();
10193         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10194         return;
10195     }
10196 
10197     SslError sslError(ssl, result);
10198     switch (sslError.get()) {
10199         case SSL_ERROR_NONE:
10200         case SSL_ERROR_ZERO_RETURN:
10201         case SSL_ERROR_WANT_READ:
10202         case SSL_ERROR_WANT_WRITE: {
10203             // The call succeeded, lacked data, or the SSL is closed.  All is well.
10204             break;
10205         }
10206         case SSL_ERROR_SYSCALL: {
10207             // A problem occurred during a system call, but this is not
10208             // necessarily an error.
10209             if (result == 0) {
10210                 // TODO(nmittler): Can this happen with memory BIOs?
10211                 // Connection closed without proper shutdown. Tell caller we
10212                 // have reached end-of-stream.
10213                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10214                 break;
10215             }
10216 
10217             if (errno == EINTR) {
10218                 // TODO(nmittler): Can this happen with memory BIOs?
10219                 // System call has been interrupted. Simply retry.
10220                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10221                                                    "Read error");
10222                 break;
10223             }
10224 
10225             // Note that for all other system call errors we fall through
10226             // to the default case, which results in an Exception.
10227             FALLTHROUGH_INTENDED;
10228         }
10229         default: {
10230             // Everything else is basically an error.
10231             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10232                                                                "Read error");
10233             break;
10234         }
10235     }
10236 
10237     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10238 }
10239 
10240 /**
10241  * OpenSSL write function (2): write into buffer at offset n chunks.
10242  */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10243 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10244                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10245                                                 jint len, jobject shc) {
10246     CHECK_ERROR_QUEUE_ON_RETURN;
10247     SSL* ssl = to_SSL(env, ssl_address, true);
10248     const char* sourcePtr = reinterpret_cast<const char*>(address);
10249     if (ssl == nullptr) {
10250         return -1;
10251     }
10252     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10253               sourcePtr, len, shc);
10254     if (shc == nullptr) {
10255         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10256         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10257                   ssl);
10258         return -1;
10259     }
10260 
10261     AppData* appData = toAppData(ssl);
10262     if (appData == nullptr) {
10263         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10264         ERR_clear_error();
10265         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10266         return -1;
10267     }
10268     if (!appData->setCallbackState(env, shc, nullptr)) {
10269         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10270         ERR_clear_error();
10271         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10272         return -1;
10273     }
10274 
10275     errno = 0;
10276 
10277     int result = SSL_write(ssl, sourcePtr, len);
10278     appData->clearCallbackState();
10279     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10280               ssl, sourcePtr, len, shc, result);
10281     return result;
10282 }
10283 
10284 /**
10285  * public static native bool usesBoringSsl_FIPS_mode();
10286  */
NativeCrypto_usesBoringSsl_FIPS_mode()10287 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
10288     return FIPS_mode();
10289 }
10290 
10291 // TESTING METHODS BEGIN
10292 
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10293 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10294     CHECK_ERROR_QUEUE_ON_RETURN;
10295     BIO* bio = to_BIO(env, bioRef);
10296     JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10297 
10298     if (bio == nullptr) {
10299         JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10300         return 0;
10301     }
10302 
10303     if (outputJavaBytes == nullptr) {
10304         conscrypt::jniutil::throwNullPointerException(env, "output == null");
10305         JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10306         return 0;
10307     }
10308 
10309     jsize outputSize = env->GetArrayLength(outputJavaBytes);
10310 
10311     std::unique_ptr<unsigned char[]> buffer(
10312             new unsigned char[static_cast<unsigned int>(outputSize)]);
10313     if (buffer.get() == nullptr) {
10314         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10315         return 0;
10316     }
10317 
10318     int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10319     if (read <= 0) {
10320         conscrypt::jniutil::throwIOException(env, "BIO_read");
10321         JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10322         return 0;
10323     }
10324 
10325     env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10326     JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10327     return read;
10328 }
10329 
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10330 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10331                                    jint offset, jint length) {
10332     CHECK_ERROR_QUEUE_ON_RETURN;
10333     BIO* bio = to_BIO(env, bioRef);
10334     JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10335 
10336     if (bio == nullptr) {
10337         return;
10338     }
10339 
10340     if (inputJavaBytes == nullptr) {
10341         conscrypt::jniutil::throwNullPointerException(env, "input == null");
10342         return;
10343     }
10344 
10345     int inputSize = env->GetArrayLength(inputJavaBytes);
10346     if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10347         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10348                                            "inputJavaBytes");
10349         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10350         return;
10351     }
10352 
10353     std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10354     if (buffer.get() == nullptr) {
10355         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10356         return;
10357     }
10358 
10359     env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10360     if (BIO_write(bio, buffer.get(), length) != length) {
10361         ERR_clear_error();
10362         conscrypt::jniutil::throwIOException(env, "BIO_write");
10363         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10364         return;
10365     }
10366 
10367     JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10368 }
10369 
10370 /**
10371  * public static native long SSL_clear_mode(long ssl, long mode);
10372  */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10373 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10374                                          CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10375     CHECK_ERROR_QUEUE_ON_RETURN;
10376     SSL* ssl = to_SSL(env, ssl_address, true);
10377     // NOLINTNEXTLINE(runtime/int)
10378     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10379     if (ssl == nullptr) {
10380         return 0;
10381     }
10382     jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10383     // NOLINTNEXTLINE(runtime/int)
10384     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10385     return result;
10386 }
10387 
10388 /**
10389  * public static native long SSL_get_mode(long ssl);
10390  */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10391 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10392                                        CONSCRYPT_UNUSED jobject ssl_holder) {
10393     CHECK_ERROR_QUEUE_ON_RETURN;
10394     SSL* ssl = to_SSL(env, ssl_address, true);
10395     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10396     if (ssl == nullptr) {
10397         return 0;
10398     }
10399     jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
10400     // NOLINTNEXTLINE(runtime/int)
10401     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
10402     return mode;
10403 }
10404 
10405 /**
10406  * public static native long SSL_get_options(long ssl);
10407  */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10408 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
10409                                           CONSCRYPT_UNUSED jobject ssl_holder) {
10410     CHECK_ERROR_QUEUE_ON_RETURN;
10411     SSL* ssl = to_SSL(env, ssl_address, true);
10412     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
10413     if (ssl == nullptr) {
10414         return 0;
10415     }
10416     jlong options = static_cast<jlong>(SSL_get_options(ssl));
10417     // NOLINTNEXTLINE(runtime/int)
10418     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
10419     return options;
10420 }
10421 
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10422 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
10423                                            CONSCRYPT_UNUSED jobject ssl_holder) {
10424     CHECK_ERROR_QUEUE_ON_RETURN;
10425     SSL* ssl = to_SSL(env, ssl_address, true);
10426     if (ssl == nullptr) {
10427         return 0;
10428     }
10429     return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
10430 }
10431 
10432 // TESTING METHODS END
10433 
10434 #define CONSCRYPT_NATIVE_METHOD(functionName, signature)             \
10435     {                                                                \
10436         /* NOLINTNEXTLINE */                                         \
10437         (char*)#functionName, (char*)(signature),                    \
10438                 reinterpret_cast<void*>(NativeCrypto_##functionName) \
10439     }
10440 
10441 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10442 #define SSL_CALLBACKS \
10443     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
10444 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10445 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
10446 #define REF_EVP_CIPHER_CTX \
10447     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
10448 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
10449 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
10450 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
10451 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
10452 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
10453 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
10454 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
10455 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
10456 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
10457 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
10458 static JNINativeMethod sNativeCryptoMethods[] = {
10459         CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
10460         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
10461         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
10462         CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
10463         CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
10464         CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
10465         CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
10466         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
10467         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
10468         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10469         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10470         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10471         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
10472         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10473         CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
10474         CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
10475         CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
10476         CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
10477         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
10478         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
10479         CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10480         CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
10481                                 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
10482         CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
10483         CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
10484         CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10485         CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10486         CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10487         CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10488         CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10489         CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
10490         CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
10491         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
10492         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
10493         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10494         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10495         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10496         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10497         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
10498         CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
10499         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10500         CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
10501         CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
10502         CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
10503                                 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10504         CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
10505                                 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10506         CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10507         CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
10508         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10509         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10510         CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
10511         CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
10512         CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10513         CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
10514         CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
10515         CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
10516         CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
10517         CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
10518         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
10519         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
10520         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
10521         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
10522         CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
10523         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10524         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10525         CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
10526         CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10527         CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
10528         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10529         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10530         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10531         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
10532         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10533         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10534         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10535         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
10536         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
10537         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10538         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
10539         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10540         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
10541         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
10542         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
10543         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
10544         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
10545         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
10546         CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
10547         CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10548         CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10549         CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
10550         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
10551         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
10552         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10553         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
10554         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
10555         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10556         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
10557         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
10558         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
10559         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
10560         CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
10561         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
10562         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
10563         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
10564         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
10565         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
10566         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
10567         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10568         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10569         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
10570         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
10571         CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
10572         CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
10573         CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
10574         CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
10575         CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
10576         CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
10577         CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10578         CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
10579         CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
10580         CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
10581         CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
10582         CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
10583         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
10584         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
10585         CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
10586         CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
10587         CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
10588         CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
10589         CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
10590         CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
10591         CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
10592         CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
10593         CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
10594         CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
10595         CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10596         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10597         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
10598         CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
10599         CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
10600         CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
10601         CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
10602         CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
10603         CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
10604         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
10605         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
10606         CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
10607         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
10608         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
10609         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10610         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
10611         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
10612         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
10613         CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
10614         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
10615         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10616         CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
10617                                 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
10618         CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
10619         CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
10620         CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
10621         CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
10622         CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
10623         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
10624         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext, "(J" REF_X509 "Ljava/lang/String;)[B"),
10625         CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
10626         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
10627         CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
10628         CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
10629         CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
10630         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
10631         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
10632         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
10633         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
10634         CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
10635         CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
10636         CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
10637         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
10638         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
10639         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
10640         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
10641         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
10642         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10643         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
10644         CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
10645         CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
10646         CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10647         CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
10648         CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
10649         CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
10650         CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
10651         CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
10652         CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
10653         CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
10654         CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
10655         CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
10656         CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
10657         CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
10658         CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
10659         CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
10660         CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
10661         CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
10662         CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
10663         CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
10664         CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
10665         CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
10666         CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
10667         CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
10668         CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
10669         CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
10670         CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
10671         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
10672         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
10673         CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
10674         CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
10675         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
10676         CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
10677         CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
10678         CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
10679         CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
10680         CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
10681         CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
10682         CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
10683         CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
10684         CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
10685         CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
10686         CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
10687         CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
10688         CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
10689         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
10690         CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
10691         CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
10692         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
10693         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
10694         CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
10695         CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
10696         CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
10697         CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
10698         CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
10699         CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
10700         CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
10701         CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
10702         CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
10703         CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
10704         CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
10705         CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
10706         CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
10707         CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
10708         CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
10709         CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
10710         CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
10711         CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
10712         CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
10713         CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
10714         CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
10715         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
10716         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
10717         CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
10718         CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
10719         CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
10720         CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
10721         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
10722         CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
10723         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10724         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10725         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
10726         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
10727         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
10728         CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
10729         CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
10730         CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
10731         CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
10732         CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
10733         CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
10734         CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
10735         CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
10736                                 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
10737         CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
10738         CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
10739         CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
10740         CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
10741         CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
10742         CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
10743         CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
10744         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
10745         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10746         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10747         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10748         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10749         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
10750         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
10751         CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
10752 
10753         // Used for testing only.
10754         CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
10755         CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
10756         CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
10757         CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
10758         CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
10759         CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
10760 };
10761 
registerNativeMethods(JNIEnv * env)10762 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
10763     conscrypt::jniutil::jniRegisterNativeMethods(
10764             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
10765             NELEM(sNativeCryptoMethods));
10766 }
10767 
10768 /* Local Variables: */
10769 /* mode: c++ */
10770 /* tab-width: 4 */
10771 /* indent-tabs-mode: nil */
10772 /* c-basic-offset: 4 */
10773 /* End: */
10774 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
10775