• 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/curve25519.h>
41 #include <openssl/cmac.h>
42 #include <openssl/crypto.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 <vector>
56 
57 using conscrypt::AppData;
58 using conscrypt::BioInputStream;
59 using conscrypt::BioOutputStream;
60 using conscrypt::BioStream;
61 using conscrypt::CompatibilityCloseMonitor;
62 using conscrypt::NativeCrypto;
63 using conscrypt::SslError;
64 
65 /**
66  * Helper function that grabs the casts an ssl pointer and then checks for nullness.
67  * If this function returns nullptr and <code>throwIfNull</code> is
68  * passed as <code>true</code>, then this function will call
69  * <code>throwSSLExceptionStr</code> before returning, so in this case of
70  * nullptr, a caller of this function should simply return and allow JNI
71  * to do its thing.
72  *
73  * @param env the JNI environment
74  * @param ssl_address; the ssl_address pointer as an integer
75  * @param throwIfNull whether to throw if the SSL pointer is nullptr
76  * @returns the pointer, which may be nullptr
77  */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)78 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
79     SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
80     if ((ssl_ctx == nullptr) && throwIfNull) {
81         JNI_TRACE("ssl_ctx == null");
82         conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
83     }
84     return ssl_ctx;
85 }
86 
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)87 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
88     SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
89     if ((ssl == nullptr) && throwIfNull) {
90         JNI_TRACE("ssl == null");
91         conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
92     }
93     return ssl;
94 }
95 
to_BIO(JNIEnv * env,jlong bio_address)96 static BIO* to_BIO(JNIEnv* env, jlong bio_address) {
97     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
98     if (bio == nullptr) {
99         JNI_TRACE("bio == null");
100         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
101     }
102     return bio;
103 }
104 
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)105 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
106     SSL_SESSION* ssl_session =
107             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
108     if ((ssl_session == nullptr) && throwIfNull) {
109         JNI_TRACE("ssl_session == null");
110         conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
111     }
112     return ssl_session;
113 }
114 
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)115 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
116     SSL_CIPHER* ssl_cipher =
117             reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
118     if ((ssl_cipher == nullptr) && throwIfNull) {
119         JNI_TRACE("ssl_cipher == null");
120         conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
121     }
122     return ssl_cipher;
123 }
124 
125 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)126 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
127     if (contextObject == nullptr) {
128         JNI_TRACE("contextObject == null");
129         conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
130         return nullptr;
131     }
132     T* ref = reinterpret_cast<T*>(
133             env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
134     if (ref == nullptr) {
135         JNI_TRACE("ref == null");
136         conscrypt::jniutil::throwNullPointerException(env, "ref == null");
137         return nullptr;
138     }
139     return ref;
140 }
141 
142 /**
143  * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
144  * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
145  * return value is false, there is a pending exception.
146  */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)147 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
148     JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
149     if (dest == nullptr) {
150         JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
151         conscrypt::jniutil::throwNullPointerException(env, "dest == null");
152         return false;
153     }
154     JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
155 
156     ScopedByteArrayRO sourceBytes(env, source);
157     if (sourceBytes.get() == nullptr) {
158         JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
159         return false;
160     }
161     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
162     size_t tmpSize = sourceBytes.size();
163 
164     /* if the array is empty, it is zero. */
165     if (tmpSize == 0) {
166         if (*dest == nullptr) {
167             *dest = BN_new();
168         }
169         BN_zero(*dest);
170         return true;
171     }
172 
173     std::unique_ptr<unsigned char[]> twosComplement;
174     bool negative = (tmp[0] & 0x80) != 0;
175     if (negative) {
176         // Need to convert to two's complement.
177         twosComplement.reset(new unsigned char[tmpSize]);
178         unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
179         memcpy(twosBytes, tmp, tmpSize);
180         tmp = twosBytes;
181 
182         bool carry = true;
183         for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
184             twosBytes[i] ^= 0xFF;
185             if (carry) {
186                 carry = (++twosBytes[i]) == 0;
187             }
188         }
189     }
190     BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
191     if (ret == nullptr) {
192         conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
193         ERR_clear_error();
194         JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
195         return false;
196     }
197     BN_set_negative(ret, negative ? 1 : 0);
198 
199     *dest = ret;
200     JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
201     return true;
202 }
203 
204 /**
205  * arrayToBignumSize sets |*out_size| to the size of the big-endian number
206  * contained in |source|. It returns true on success and sets an exception and
207  * returns false otherwise.
208  */
arrayToBignumSize(JNIEnv * env,jbyteArray source,size_t * out_size)209 static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
210     JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
211 
212     ScopedByteArrayRO sourceBytes(env, source);
213     if (sourceBytes.get() == nullptr) {
214         JNI_TRACE("arrayToBignum(%p, %p) => null", source, out_size);
215         return false;
216     }
217     const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
218     size_t tmpSize = sourceBytes.size();
219 
220     if (tmpSize == 0) {
221         *out_size = 0;
222         return true;
223     }
224 
225     if ((tmp[0] & 0x80) != 0) {
226         // Negative numbers are invalid.
227         conscrypt::jniutil::throwRuntimeException(env, "Negative number");
228         return false;
229     }
230 
231     while (tmpSize > 0 && tmp[0] == 0) {
232         tmp++;
233         tmpSize--;
234     }
235 
236     *out_size = tmpSize;
237     return true;
238 }
239 
240 /**
241  * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
242  */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)243 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
244     JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
245 
246     if (source == nullptr) {
247         conscrypt::jniutil::throwNullPointerException(env, sourceName);
248         return nullptr;
249     }
250 
251     size_t numBytes = BN_num_bytes(source) + 1;
252     jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
253     ScopedByteArrayRW bytes(env, javaBytes);
254     if (bytes.get() == nullptr) {
255         JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
256         return nullptr;
257     }
258 
259     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
260     if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
261         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
262         return nullptr;
263     }
264 
265     // Set the sign and convert to two's complement if necessary for the Java code.
266     if (BN_is_negative(source)) {
267         bool carry = true;
268         for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
269             tmp[i] ^= 0xFF;
270             if (carry) {
271                 carry = (++tmp[i]) == 0;
272             }
273         }
274         *tmp |= 0x80;
275     } else {
276         *tmp = 0x00;
277     }
278 
279     JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
280     return javaBytes;
281 }
282 
283 /**
284  * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
285  * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
286  * from the OpenSSL ASN.1 API.
287  */
288 template <typename T>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(T *,unsigned char **))289 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(T*, unsigned char**)) {
290     if (obj == nullptr) {
291         conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
292         JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
293         return nullptr;
294     }
295 
296     int derLen = i2d_func(obj, nullptr);
297     if (derLen < 0) {
298         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
299         JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
300         return nullptr;
301     }
302 
303     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
304     if (byteArray.get() == nullptr) {
305         JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
306         return nullptr;
307     }
308 
309     ScopedByteArrayRW bytes(env, byteArray.get());
310     if (bytes.get() == nullptr) {
311         JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
312         return nullptr;
313     }
314 
315     unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
316     int ret = i2d_func(obj, &p);
317     if (ret < 0) {
318         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
319         JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
320         return nullptr;
321     }
322 
323     JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
324     return byteArray.release();
325 }
326 
327 /**
328  * Finishes a pending CBB and returns a jbyteArray with the contents.
329  */
CBBToByteArray(JNIEnv * env,CBB * cbb)330 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
331     uint8_t* data;
332     size_t len;
333     if (!CBB_finish(cbb, &data, &len)) {
334         conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
335         ERR_clear_error();
336         JNI_TRACE("creating byte array failed");
337         return nullptr;
338     }
339     bssl::UniquePtr<uint8_t> free_data(data);
340 
341     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
342     if (byteArray.get() == nullptr) {
343         JNI_TRACE("creating byte array failed");
344         return nullptr;
345     }
346 
347     ScopedByteArrayRW bytes(env, byteArray.get());
348     if (bytes.get() == nullptr) {
349         JNI_TRACE("using byte array failed");
350         return nullptr;
351     }
352 
353     memcpy(bytes.get(), data, len);
354     return byteArray.release();
355 }
356 
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)357 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
358     if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
359         JNI_TRACE("buffer too large");
360         conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
361         return nullptr;
362     }
363 
364     int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
365     jbyteArray ret = env->NewByteArray(length);
366     if (ret == nullptr) {
367         JNI_TRACE("allocating byte array failed");
368         return nullptr;
369     }
370 
371     env->SetByteArrayRegion(ret, 0, length,
372                             reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
373     return ret;
374 }
375 
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)376 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
377                                                        CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
378     if (array == nullptr) {
379         JNI_TRACE("array was null");
380         conscrypt::jniutil::throwNullPointerException(env, "array == null");
381         return nullptr;
382     }
383 
384     ScopedByteArrayRO arrayRo(env, array);
385     if (arrayRo.get() == nullptr) {
386         JNI_TRACE("failed to get bytes");
387         return nullptr;
388     }
389 
390     bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
391             reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
392     if (!ret) {
393         JNI_TRACE("failed to allocate CRYPTO_BUFFER");
394         conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
395         return nullptr;
396     }
397 
398     return ret;
399 }
400 
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)401 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
402                                                const STACK_OF(CRYPTO_BUFFER) * buffers) {
403     size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
404     if (numBuffers > INT_MAX) {
405         JNI_TRACE("too many buffers");
406         conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
407         return nullptr;
408     }
409 
410     ScopedLocalRef<jobjectArray> array(
411             env, env->NewObjectArray(static_cast<int>(numBuffers),
412                                      conscrypt::jniutil::byteArrayClass, nullptr));
413     if (array.get() == nullptr) {
414         JNI_TRACE("failed to allocate array");
415         return nullptr;
416     }
417 
418     for (size_t i = 0; i < numBuffers; ++i) {
419         CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
420         ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
421         if (bArray.get() == nullptr) {
422             return nullptr;
423         }
424         env->SetObjectArrayElement(array.get(), i, bArray.get());
425     }
426 
427     return array.release();
428 }
429 
430 /**
431  * Converts ASN.1 BIT STRING to a jbooleanArray.
432  */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)433 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
434     int size = ASN1_STRING_length(bitStr) * 8;
435     if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
436         size -= bitStr->flags & 0x07;
437     }
438 
439     ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
440     if (bitsRef.get() == nullptr) {
441         return nullptr;
442     }
443 
444     ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
445     for (size_t i = 0; i < bitsArray.size(); i++) {
446         bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
447     }
448 
449     return bitsRef.release();
450 }
451 
bio_stream_create(BIO * b)452 static int bio_stream_create(BIO* b) {
453     b->init = 1;
454     b->num = 0;
455     b->ptr = nullptr;
456     b->flags = 0;
457     return 1;
458 }
459 
bio_stream_destroy(BIO * b)460 static int bio_stream_destroy(BIO* b) {
461     if (b == nullptr) {
462         return 0;
463     }
464 
465     if (b->ptr != nullptr) {
466         delete static_cast<BioStream*>(b->ptr);
467         b->ptr = nullptr;
468     }
469 
470     b->init = 0;
471     b->flags = 0;
472     return 1;
473 }
474 
bio_stream_read(BIO * b,char * buf,int len)475 static int bio_stream_read(BIO* b, char* buf, int len) {
476     BIO_clear_retry_flags(b);
477     BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
478     int ret = stream->read(buf, len);
479     if (ret == 0) {
480         if (stream->isFinite()) {
481             return 0;
482         }
483         // If the BioInputStream is not finite then EOF doesn't mean that
484         // there's nothing more coming.
485         BIO_set_retry_read(b);
486         return -1;
487     }
488     return ret;
489 }
490 
bio_stream_write(BIO * b,const char * buf,int len)491 static int bio_stream_write(BIO* b, const char* buf, int len) {
492     BIO_clear_retry_flags(b);
493     BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
494     return stream->write(buf, len);
495 }
496 
bio_stream_puts(BIO * b,const char * buf)497 static int bio_stream_puts(BIO* b, const char* buf) {
498     BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
499     return stream->write(buf, static_cast<int>(strlen(buf)));
500 }
501 
bio_stream_gets(BIO * b,char * buf,int len)502 static int bio_stream_gets(BIO* b, char* buf, int len) {
503     BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
504     return stream->gets(buf, len);
505 }
506 
bio_stream_assign(BIO * b,BioStream * stream)507 static void bio_stream_assign(BIO* b, BioStream* stream) {
508     b->ptr = static_cast<void*>(stream);
509 }
510 
511 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)512 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
513     BioStream* stream = static_cast<BioStream*>(b->ptr);
514 
515     switch (cmd) {
516         case BIO_CTRL_EOF:
517             return stream->isEof() ? 1 : 0;
518         case BIO_CTRL_FLUSH:
519             return stream->flush();
520         default:
521             return 0;
522     }
523 }
524 
525 static BIO_METHOD stream_bio_method = {
526         (100 | 0x0400), /* source/sink BIO */
527         "InputStream/OutputStream BIO",
528         bio_stream_write,   /* bio_write */
529         bio_stream_read,    /* bio_read */
530         bio_stream_puts,    /* bio_puts */
531         bio_stream_gets,    /* bio_gets */
532         bio_stream_ctrl,    /* bio_ctrl */
533         bio_stream_create,  /* bio_create */
534         bio_stream_destroy, /* bio_free */
535         nullptr,            /* no bio_callback_ctrl */
536 };
537 
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)538 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
539                                              size_t message_len) {
540     JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
541     if (message_len > std::numeric_limits<jsize>::max()) {
542         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
543         return nullptr;
544     }
545     ScopedLocalRef<jbyteArray> messageArray(env,
546                                             env->NewByteArray(static_cast<jsize>(message_len)));
547     if (env->ExceptionCheck()) {
548         JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
549         return nullptr;
550     }
551 
552     {
553         ScopedByteArrayRW messageBytes(env, messageArray.get());
554         if (messageBytes.get() == nullptr) {
555             JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
556             return nullptr;
557         }
558 
559         memcpy(messageBytes.get(), message, message_len);
560     }
561 
562     jmethodID rawSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
563                                                      "ecSignDigestWithPrivateKey",
564                                                      "(Ljava/security/PrivateKey;[B)[B");
565     if (rawSignMethod == nullptr) {
566         CONSCRYPT_LOG_ERROR("Could not find ecSignDigestWithPrivateKey");
567         return nullptr;
568     }
569 
570     return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
571             conscrypt::jniutil::cryptoUpcallsClass, rawSignMethod, privateKey, messageArray.get()));
572 }
573 
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)574 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
575                                               const char* message, size_t message_len) {
576     if (message_len > std::numeric_limits<jsize>::max()) {
577         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
578         return nullptr;
579     }
580     ScopedLocalRef<jbyteArray> messageArray(env,
581                                             env->NewByteArray(static_cast<jsize>(message_len)));
582     if (env->ExceptionCheck()) {
583         JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
584         return nullptr;
585     }
586 
587     {
588         ScopedByteArrayRW messageBytes(env, messageArray.get());
589         if (messageBytes.get() == nullptr) {
590             JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
591             return nullptr;
592         }
593 
594         memcpy(messageBytes.get(), message, message_len);
595     }
596 
597     jmethodID rsaSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
598                                                      "rsaSignDigestWithPrivateKey",
599                                                      "(Ljava/security/PrivateKey;I[B)[B");
600     if (rsaSignMethod == nullptr) {
601         CONSCRYPT_LOG_ERROR("Could not find rsaSignDigestWithPrivateKey");
602         return nullptr;
603     }
604 
605     return reinterpret_cast<jbyteArray>(
606             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaSignMethod,
607                                         privateKey, padding, messageArray.get()));
608 }
609 
610 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
611 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
612 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
613 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)614 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
615                                            const char* ciphertext, size_t ciphertext_len) {
616     if (ciphertext_len > std::numeric_limits<jsize>::max()) {
617         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
618         return nullptr;
619     }
620     ScopedLocalRef<jbyteArray> ciphertextArray(
621             env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
622     if (env->ExceptionCheck()) {
623         JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
624         return nullptr;
625     }
626 
627     {
628         ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
629         if (ciphertextBytes.get() == nullptr) {
630             JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
631             return nullptr;
632         }
633 
634         memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
635     }
636 
637     jmethodID rsaDecryptMethod =
638             env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
639                                    "rsaDecryptWithPrivateKey", "(Ljava/security/PrivateKey;I[B)[B");
640     if (rsaDecryptMethod == nullptr) {
641         CONSCRYPT_LOG_ERROR("Could not find rsaDecryptWithPrivateKey");
642         return nullptr;
643     }
644 
645     return reinterpret_cast<jbyteArray>(
646             env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaDecryptMethod,
647                                         privateKey, padding, ciphertextArray.get()));
648 }
649 
650 // *********************************************
651 // From keystore_openssl.cpp in Chromium source.
652 // *********************************************
653 
654 namespace {
655 
656 ENGINE* g_engine;
657 int g_rsa_exdata_index;
658 int g_ecdsa_exdata_index;
659 RSA_METHOD g_rsa_method;
660 ECDSA_METHOD g_ecdsa_method;
661 std::once_flag g_engine_once;
662 
663 void init_engine_globals();
664 
ensure_engine_globals()665 void ensure_engine_globals() {
666     std::call_once(g_engine_once, init_engine_globals);
667 }
668 
669 // KeyExData contains the data that is contained in the EX_DATA of the RSA
670 // and ECDSA objects that are created to wrap Android system keys.
671 struct KeyExData {
672     // private_key contains a reference to a Java, private-key object.
673     jobject private_key;
674     // cached_size contains the "size" of the key. This is the size of the
675     // modulus (in bytes) for RSA, or the group order size for ECDSA. This
676     // avoids calling into Java to calculate the size.
677     size_t cached_size;
678 };
679 
680 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
681 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)682 int ExDataDup(CRYPTO_EX_DATA* /* to */,
683               const CRYPTO_EX_DATA* /* from */,
684               void** /* from_d */,
685               int /* index */,
686               long /* argl */ /* NOLINT(runtime/int) */,
687               void* /* argp */) {
688   return 0;
689 }
690 
691 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)692 void ExDataFree(void* /* parent */,
693                 void* ptr,
694                 CRYPTO_EX_DATA* /* ad */,
695                 int /* index */,
696                 long /* argl */ /* NOLINT(runtime/int) */,
697                 void* /* argp */) {
698     // Ensure the global JNI reference created with this wrapper is
699     // properly destroyed with it.
700     KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
701     if (ex_data != nullptr) {
702         JNIEnv* env = conscrypt::jniutil::getJNIEnv();
703         env->DeleteGlobalRef(ex_data->private_key);
704         delete ex_data;
705     }
706 }
707 
RsaGetExData(const RSA * rsa)708 KeyExData* RsaGetExData(const RSA* rsa) {
709     return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
710 }
711 
RsaMethodSize(const RSA * rsa)712 size_t RsaMethodSize(const RSA* rsa) {
713     const KeyExData* ex_data = RsaGetExData(rsa);
714     return ex_data->cached_size;
715 }
716 
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)717 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
718                      size_t in_len, int padding) {
719     if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
720         OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
721         return 0;
722     }
723 
724     // Retrieve private key JNI reference.
725     const KeyExData* ex_data = RsaGetExData(rsa);
726     if (!ex_data || !ex_data->private_key) {
727         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
728         return 0;
729     }
730 
731     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
732     if (env == nullptr) {
733         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
734         return 0;
735     }
736 
737     // For RSA keys, this function behaves as RSA_private_encrypt with
738     // the specified padding.
739     ScopedLocalRef<jbyteArray> signature(
740             env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
741                                              reinterpret_cast<const char*>(in), in_len));
742 
743     if (signature.get() == nullptr) {
744         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
745         return 0;
746     }
747 
748     ScopedByteArrayRO result(env, signature.get());
749 
750     size_t expected_size = static_cast<size_t>(RSA_size(rsa));
751     if (result.size() > expected_size) {
752         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
753         return 0;
754     }
755 
756     if (max_out < expected_size) {
757         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
758         return 0;
759     }
760 
761     // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
762     // should pad with leading 0s, but if it doesn't, pad the result.
763     size_t zero_pad = expected_size - result.size();
764     memset(out, 0, zero_pad);
765     memcpy(out + zero_pad, &result[0], result.size());
766     *out_len = expected_size;
767 
768     return 1;
769 }
770 
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)771 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
772                      size_t in_len, int padding) {
773     // Retrieve private key JNI reference.
774     const KeyExData* ex_data = RsaGetExData(rsa);
775     if (!ex_data || !ex_data->private_key) {
776         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
777         return 0;
778     }
779 
780     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
781     if (env == nullptr) {
782         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
783         return 0;
784     }
785 
786     // This function behaves as RSA_private_decrypt.
787     ScopedLocalRef<jbyteArray> cleartext(
788             env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
789                                           reinterpret_cast<const char*>(in), in_len));
790     if (cleartext.get() == nullptr) {
791         OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
792         return 0;
793     }
794 
795     ScopedByteArrayRO cleartextBytes(env, cleartext.get());
796 
797     if (max_out < cleartextBytes.size()) {
798         OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
799         return 0;
800     }
801 
802     // Copy result to OpenSSL-provided buffer.
803     memcpy(out, cleartextBytes.get(), cleartextBytes.size());
804     *out_len = cleartextBytes.size();
805 
806     return 1;
807 }
808 
809 // Custom ECDSA_METHOD that uses the platform APIs.
810 // Note that for now, only signing through ECDSA_sign() is really supported.
811 // all other method pointers are either stubs returning errors, or no-ops.
812 
EcKeyGetKey(const EC_KEY * ec_key)813 jobject EcKeyGetKey(const EC_KEY* ec_key) {
814     KeyExData* ex_data =
815             reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
816     return ex_data->private_key;
817 }
818 
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)819 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
820                     EC_KEY* ec_key) {
821     // Retrieve private key JNI reference.
822     jobject private_key = EcKeyGetKey(ec_key);
823     if (!private_key) {
824         CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
825         return 0;
826     }
827 
828     JNIEnv* env = conscrypt::jniutil::getJNIEnv();
829     if (env == nullptr) {
830         return 0;
831     }
832 
833     // Sign message with it through JNI.
834     ScopedLocalRef<jbyteArray> signature(
835             env, ecSignDigestWithPrivateKey(env, private_key,
836                                              reinterpret_cast<const char*>(digest), digest_len));
837     if (signature.get() == nullptr) {
838         CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
839         return 0;
840     }
841 
842     ScopedByteArrayRO signatureBytes(env, signature.get());
843     // Note: With ECDSA, the actual signature may be smaller than
844     // ECDSA_size().
845     size_t max_expected_size = ECDSA_size(ec_key);
846     if (signatureBytes.size() > max_expected_size) {
847         CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
848                             signatureBytes.size(), max_expected_size);
849         return 0;
850     }
851 
852     memcpy(sig, signatureBytes.get(), signatureBytes.size());
853     *sig_len = static_cast<unsigned int>(signatureBytes.size());
854     return 1;
855 }
856 
init_engine_globals()857 void init_engine_globals() {
858     g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
859                                               nullptr /* new_func */, ExDataDup, ExDataFree);
860     g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
861                                                    nullptr /* new_func */, ExDataDup, ExDataFree);
862 
863     g_rsa_method.common.is_static = 1;
864     g_rsa_method.size = RsaMethodSize;
865     g_rsa_method.sign_raw = RsaMethodSignRaw;
866     g_rsa_method.decrypt = RsaMethodDecrypt;
867     g_rsa_method.flags = RSA_FLAG_OPAQUE;
868 
869     g_ecdsa_method.common.is_static = 1;
870     g_ecdsa_method.sign = EcdsaMethodSign;
871     g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
872 
873     g_engine = ENGINE_new();
874     ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
875     ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
876 }
877 
878 }  // anonymous namespace
879 
880 #define THROW_SSLEXCEPTION (-2)
881 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
882 #define THROWN_EXCEPTION (-4)
883 
884 /**
885  * Initialization phase for every OpenSSL job: Loads the Error strings, the
886  * crypto algorithms and reset the OpenSSL library
887  */
NativeCrypto_clinit(JNIEnv *,jclass)888 static void NativeCrypto_clinit(JNIEnv*, jclass) {
889     CRYPTO_library_init();
890 }
891 
892 /**
893  * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
894  */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)895 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
896                                            jbyteArray d, jbyteArray p, jbyteArray q,
897                                            jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
898     CHECK_ERROR_QUEUE_ON_RETURN;
899     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,
900               p, q, dmp1, dmq1, iqmp);
901 
902     bssl::UniquePtr<RSA> rsa(RSA_new());
903     if (rsa.get() == nullptr) {
904         conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
905         return 0;
906     }
907 
908     if (e == nullptr && d == nullptr) {
909         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
910                                            "e == null && d == null");
911         JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
912         return 0;
913     }
914 
915     if (!arrayToBignum(env, n, &rsa->n)) {
916         return 0;
917     }
918 
919     if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
920         return 0;
921     }
922 
923     if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
924         return 0;
925     }
926 
927     if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
928         return 0;
929     }
930 
931     if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
932         return 0;
933     }
934 
935     if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
936         return 0;
937     }
938 
939     if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
940         return 0;
941     }
942 
943     if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
944         return 0;
945     }
946 
947     if (conscrypt::trace::kWithJniTrace) {
948         if (p != nullptr && q != nullptr) {
949             int check = RSA_check_key(rsa.get());
950             JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
951         }
952     }
953 
954     if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
955         conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
956         return 0;
957     }
958 
959     /*
960      * If the private exponent is available, there is the potential to do signing
961      * operations. However, we can only do blinding if the public exponent is also
962      * available. Disable blinding if the public exponent isn't available.
963      *
964      * TODO[kroot]: We should try to recover the public exponent by trying
965      *              some common ones such 3, 17, or 65537.
966      */
967     if (rsa->d != nullptr && rsa->e == nullptr) {
968         JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
969         rsa->flags |= RSA_FLAG_NO_BLINDING;
970     }
971 
972     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
973     if (pkey.get() == nullptr) {
974         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
975         return 0;
976     }
977     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
978         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
979         ERR_clear_error();
980         return 0;
981     }
982     OWNERSHIP_TRANSFERRED(rsa);
983     JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
984               e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
985     return reinterpret_cast<uintptr_t>(pkey.release());
986 }
987 
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)988 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
989                                               jobject pubkeyRef, jbyteArray keyJavaBytes) {
990     CHECK_ERROR_QUEUE_ON_RETURN;
991     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
992     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
993     if (group == nullptr) {
994         return 0;
995     }
996     const EC_POINT* pubkey =
997             pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
998     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
999 
1000     bssl::UniquePtr<BIGNUM> key(nullptr);
1001     if (keyJavaBytes != nullptr) {
1002         BIGNUM* keyRef = nullptr;
1003         if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
1004             return 0;
1005         }
1006         key.reset(keyRef);
1007     }
1008 
1009     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
1010     if (eckey.get() == nullptr) {
1011         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1012         return 0;
1013     }
1014 
1015     if (EC_KEY_set_group(eckey.get(), group) != 1) {
1016         JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1017                   keyJavaBytes);
1018         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1019         return 0;
1020     }
1021 
1022     if (pubkey != nullptr) {
1023         if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1024             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1025                       pubkey, keyJavaBytes);
1026             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1027             return 0;
1028         }
1029     }
1030 
1031     if (key.get() != nullptr) {
1032         if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1033             JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1034                       pubkey, keyJavaBytes);
1035             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1036             return 0;
1037         }
1038         if (pubkey == nullptr) {
1039             bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1040             if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1041                 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1042                           pubkey, keyJavaBytes);
1043                 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1044                 return 0;
1045             }
1046             EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1047         }
1048     }
1049 
1050     if (!EC_KEY_check_key(eckey.get())) {
1051         JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1052                   keyJavaBytes);
1053         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1054         return 0;
1055     }
1056 
1057     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1058     if (pkey.get() == nullptr) {
1059         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1060         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1061         return 0;
1062     }
1063     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1064         JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1065         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1066         ERR_clear_error();
1067         return 0;
1068     }
1069     OWNERSHIP_TRANSFERRED(eckey);
1070 
1071     JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1072     return reinterpret_cast<uintptr_t>(pkey.release());
1073 }
1074 
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1075 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1076     CHECK_ERROR_QUEUE_ON_RETURN;
1077     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1078     JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1079 
1080     if (pkey == nullptr) {
1081         return -1;
1082     }
1083 
1084     int result = EVP_PKEY_id(pkey);
1085     JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1086     return result;
1087 }
1088 
1089 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1090 
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1091 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1092                               const char* debug_name) {
1093     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1094     JNI_TRACE("%s(%p)", debug_name, pkey);
1095 
1096     if (pkey == nullptr) {
1097         return nullptr;
1098     }
1099 
1100     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1101     if (buffer.get() == nullptr) {
1102         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1103         return nullptr;
1104     }
1105 
1106     if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1107         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1108         return nullptr;
1109     }
1110     // Null terminate this
1111     BIO_write(buffer.get(), "\0", 1);
1112 
1113     char* tmp;
1114     BIO_get_mem_data(buffer.get(), &tmp);
1115     jstring description = env->NewStringUTF(tmp);
1116 
1117     JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1118     return description;
1119 }
1120 
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1121 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1122     CHECK_ERROR_QUEUE_ON_RETURN;
1123     return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1124 }
1125 
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1126 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1127     CHECK_ERROR_QUEUE_ON_RETURN;
1128     return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1129 }
1130 
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1131 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1132     CHECK_ERROR_QUEUE_ON_RETURN;
1133     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1134     JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1135 
1136     if (pkey != nullptr) {
1137         EVP_PKEY_free(pkey);
1138     }
1139 }
1140 
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1141 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1142     CHECK_ERROR_QUEUE_ON_RETURN;
1143     JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1144     EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1145     if (pkey1 == nullptr) {
1146         JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1147         return 0;
1148     }
1149     EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1150     if (pkey2 == nullptr) {
1151         JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1152         return 0;
1153     }
1154     JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1155 
1156     int result = EVP_PKEY_cmp(pkey1, pkey2);
1157     JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1158     return result;
1159 }
1160 
1161 /*
1162  * static native byte[] EVP_marshal_private_key(long)
1163  */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1164 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1165     CHECK_ERROR_QUEUE_ON_RETURN;
1166     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1167     JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1168 
1169     if (pkey == nullptr) {
1170         return nullptr;
1171     }
1172 
1173     bssl::ScopedCBB cbb;
1174     if (!CBB_init(cbb.get(), 64)) {
1175         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1176         JNI_TRACE("CBB_init failed");
1177         return nullptr;
1178     }
1179 
1180     if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1181         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1182         JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1183         return nullptr;
1184     }
1185 
1186     return CBBToByteArray(env, cbb.get());
1187 }
1188 
1189 /*
1190  * static native long EVP_parse_private_key(byte[])
1191  */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1192 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1193     CHECK_ERROR_QUEUE_ON_RETURN;
1194     JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1195 
1196     ScopedByteArrayRO bytes(env, keyJavaBytes);
1197     if (bytes.get() == nullptr) {
1198         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1199         return 0;
1200     }
1201 
1202     CBS cbs;
1203     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1204     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1205     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1206     // allow parsing keys from buffers that are larger than the contained key structure
1207     // so we do the same for compatibility.
1208     if (!pkey) {
1209         conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1210         ERR_clear_error();
1211         JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1212         return 0;
1213     }
1214 
1215     JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1216     return reinterpret_cast<uintptr_t>(pkey.release());
1217 }
1218 
1219 /*
1220  * static native byte[] EVP_marshal_public_key(long)
1221  */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1222 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1223     CHECK_ERROR_QUEUE_ON_RETURN;
1224     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1225     JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1226 
1227     if (pkey == nullptr) {
1228         return nullptr;
1229     }
1230 
1231     bssl::ScopedCBB cbb;
1232     if (!CBB_init(cbb.get(), 64)) {
1233         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1234         JNI_TRACE("CBB_init failed");
1235         return nullptr;
1236     }
1237 
1238     if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1239         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1240         JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1241         return nullptr;
1242     }
1243 
1244     return CBBToByteArray(env, cbb.get());
1245 }
1246 
1247 /*
1248  * static native long EVP_parse_public_key(byte[])
1249  */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1250 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1251     CHECK_ERROR_QUEUE_ON_RETURN;
1252     JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1253 
1254     ScopedByteArrayRO bytes(env, keyJavaBytes);
1255     if (bytes.get() == nullptr) {
1256         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1257         return 0;
1258     }
1259 
1260     CBS cbs;
1261     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1262     bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1263     // We intentionally do not check that cbs is exhausted, as JCA providers typically
1264     // allow parsing keys from buffers that are larger than the contained key structure
1265     // so we do the same for compatibility.
1266     if (!pkey) {
1267         conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1268         ERR_clear_error();
1269         JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1270         return 0;
1271     }
1272 
1273     JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1274     return reinterpret_cast<uintptr_t>(pkey.release());
1275 }
1276 
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1277 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1278                                                   jbyteArray modulusBytes) {
1279     CHECK_ERROR_QUEUE_ON_RETURN;
1280     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1281 
1282     size_t cached_size;
1283     if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
1284         JNI_TRACE("getRSAPrivateKeyWrapper failed");
1285         return 0;
1286     }
1287 
1288     ensure_engine_globals();
1289 
1290     bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1291     if (rsa.get() == nullptr) {
1292         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1293         return 0;
1294     }
1295 
1296     // The PSS padding code needs access to the actual n, so set it even though we
1297     // don't set any other parts of the key
1298     if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1299         return 0;
1300     }
1301 
1302     auto ex_data = new KeyExData;
1303     ex_data->private_key = env->NewGlobalRef(javaKey);
1304     ex_data->cached_size = cached_size;
1305     RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1306 
1307     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1308     if (pkey.get() == nullptr) {
1309         JNI_TRACE("getRSAPrivateKeyWrapper failed");
1310         conscrypt::jniutil::throwRuntimeException(env,
1311                                                   "NativeCrypto_getRSAPrivateKeyWrapper failed");
1312         ERR_clear_error();
1313         return 0;
1314     }
1315 
1316     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1317         conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1318         ERR_clear_error();
1319         return 0;
1320     }
1321     OWNERSHIP_TRANSFERRED(rsa);
1322     JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1323     return reinterpret_cast<uintptr_t>(pkey.release());
1324 }
1325 
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1326 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1327                                                  jobject groupRef) {
1328     CHECK_ERROR_QUEUE_ON_RETURN;
1329     EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1330     JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1331     if (group == nullptr) {
1332         return 0;
1333     }
1334 
1335     ensure_engine_globals();
1336 
1337     bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1338     if (ecKey.get() == nullptr) {
1339         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1340         return 0;
1341     }
1342 
1343     if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1344         JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1345         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1346         return 0;
1347     }
1348 
1349     auto ex_data = new KeyExData;
1350     ex_data->private_key = env->NewGlobalRef(javaKey);
1351 
1352     if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1353         env->DeleteGlobalRef(ex_data->private_key);
1354         delete ex_data;
1355         conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1356         ERR_clear_error();
1357         return 0;
1358     }
1359 
1360     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1361     if (pkey.get() == nullptr) {
1362         JNI_TRACE("getECPrivateKeyWrapper failed");
1363         conscrypt::jniutil::throwRuntimeException(env,
1364                                                   "NativeCrypto_getECPrivateKeyWrapper failed");
1365         ERR_clear_error();
1366         return 0;
1367     }
1368 
1369     if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1370         conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1371         ERR_clear_error();
1372         return 0;
1373     }
1374     OWNERSHIP_TRANSFERRED(ecKey);
1375     return reinterpret_cast<uintptr_t>(pkey.release());
1376 }
1377 
1378 /*
1379  * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1380  */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1381 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1382                                               jbyteArray publicExponent) {
1383     CHECK_ERROR_QUEUE_ON_RETURN;
1384     JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1385 
1386     BIGNUM* eRef = nullptr;
1387     if (!arrayToBignum(env, publicExponent, &eRef)) {
1388         return 0;
1389     }
1390     bssl::UniquePtr<BIGNUM> e(eRef);
1391 
1392     bssl::UniquePtr<RSA> rsa(RSA_new());
1393     if (rsa.get() == nullptr) {
1394         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1395         return 0;
1396     }
1397 
1398     if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1399         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1400         return 0;
1401     }
1402 
1403     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1404     if (pkey.get() == nullptr) {
1405         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1406         return 0;
1407     }
1408 
1409     if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1410         conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1411         ERR_clear_error();
1412         return 0;
1413     }
1414 
1415     OWNERSHIP_TRANSFERRED(rsa);
1416     JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1417     return reinterpret_cast<uintptr_t>(pkey.release());
1418 }
1419 
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1420 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1421     CHECK_ERROR_QUEUE_ON_RETURN;
1422     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1423     JNI_TRACE("RSA_size(%p)", pkey);
1424 
1425     if (pkey == nullptr) {
1426         return 0;
1427     }
1428 
1429     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1430     if (rsa.get() == nullptr) {
1431         conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1432         ERR_clear_error();
1433         return 0;
1434     }
1435 
1436     return static_cast<jint>(RSA_size(rsa.get()));
1437 }
1438 
1439 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1440                               int padding);
1441 
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1442 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1443                                 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1444                                 jobject pkeyRef, jint padding) {
1445     CHECK_ERROR_QUEUE_ON_RETURN;
1446     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1447     JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1448 
1449     if (pkey == nullptr) {
1450         return -1;
1451     }
1452 
1453     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1454     if (rsa.get() == nullptr) {
1455         return -1;
1456     }
1457 
1458     ScopedByteArrayRO from(env, fromJavaBytes);
1459     if (from.get() == nullptr) {
1460         return -1;
1461     }
1462 
1463     ScopedByteArrayRW to(env, toJavaBytes);
1464     if (to.get() == nullptr) {
1465         return -1;
1466     }
1467 
1468     int resultSize =
1469             operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1470                       reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1471     if (resultSize == -1) {
1472         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1473                 conscrypt::jniutil::throwBadPaddingException);
1474         JNI_TRACE("%s => threw error", caller);
1475         return -1;
1476     }
1477 
1478     JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1479               resultSize);
1480     return static_cast<jint>(resultSize);
1481 }
1482 
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1483 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1484                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1485                                              jobject pkeyRef, jint padding) {
1486     CHECK_ERROR_QUEUE_ON_RETURN;
1487     return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1488                                toJavaBytes, pkeyRef, padding);
1489 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1490 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1491                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1492                                             jobject pkeyRef, jint padding) {
1493     CHECK_ERROR_QUEUE_ON_RETURN;
1494     return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1495                                toJavaBytes, pkeyRef, padding);
1496 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1497 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1498                                             jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1499                                             jobject pkeyRef, jint padding) {
1500     CHECK_ERROR_QUEUE_ON_RETURN;
1501     return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1502                                toJavaBytes, pkeyRef, padding);
1503 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1504 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1505                                              jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1506                                              jobject pkeyRef, jint padding) {
1507     CHECK_ERROR_QUEUE_ON_RETURN;
1508     return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1509                                toJavaBytes, pkeyRef, padding);
1510 }
1511 
1512 /*
1513  * public static native byte[][] get_RSA_public_params(long);
1514  */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1515 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1516     CHECK_ERROR_QUEUE_ON_RETURN;
1517     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1518     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1519 
1520     if (pkey == nullptr) {
1521         return nullptr;
1522     }
1523 
1524     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1525     if (rsa.get() == nullptr) {
1526         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1527         return nullptr;
1528     }
1529 
1530     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1531     if (joa == nullptr) {
1532         return nullptr;
1533     }
1534 
1535     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1536     if (env->ExceptionCheck()) {
1537         return nullptr;
1538     }
1539     env->SetObjectArrayElement(joa, 0, n);
1540 
1541     jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1542     if (env->ExceptionCheck()) {
1543         return nullptr;
1544     }
1545     env->SetObjectArrayElement(joa, 1, e);
1546 
1547     return joa;
1548 }
1549 
1550 /*
1551  * public static native byte[][] get_RSA_private_params(long);
1552  */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1553 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1554     CHECK_ERROR_QUEUE_ON_RETURN;
1555     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1556     JNI_TRACE("get_RSA_public_params(%p)", pkey);
1557 
1558     if (pkey == nullptr) {
1559         return nullptr;
1560     }
1561 
1562     bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1563     if (rsa.get() == nullptr) {
1564         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1565         return nullptr;
1566     }
1567 
1568     jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1569     if (joa == nullptr) {
1570         return nullptr;
1571     }
1572 
1573     jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1574     if (env->ExceptionCheck()) {
1575         return nullptr;
1576     }
1577     env->SetObjectArrayElement(joa, 0, n);
1578 
1579     if (RSA_get0_e(rsa.get()) != nullptr) {
1580         jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1581         if (env->ExceptionCheck()) {
1582             return nullptr;
1583         }
1584         env->SetObjectArrayElement(joa, 1, e);
1585     }
1586 
1587     if (RSA_get0_d(rsa.get()) != nullptr) {
1588         jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1589         if (env->ExceptionCheck()) {
1590             return nullptr;
1591         }
1592         env->SetObjectArrayElement(joa, 2, d);
1593     }
1594 
1595     if (RSA_get0_p(rsa.get()) != nullptr) {
1596         jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1597         if (env->ExceptionCheck()) {
1598             return nullptr;
1599         }
1600         env->SetObjectArrayElement(joa, 3, p);
1601     }
1602 
1603     if (RSA_get0_q(rsa.get()) != nullptr) {
1604         jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1605         if (env->ExceptionCheck()) {
1606             return nullptr;
1607         }
1608         env->SetObjectArrayElement(joa, 4, q);
1609     }
1610 
1611     if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1612         jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1613         if (env->ExceptionCheck()) {
1614             return nullptr;
1615         }
1616         env->SetObjectArrayElement(joa, 5, dmp1);
1617     }
1618 
1619     if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1620         jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1621         if (env->ExceptionCheck()) {
1622             return nullptr;
1623         }
1624         env->SetObjectArrayElement(joa, 6, dmq1);
1625     }
1626 
1627     if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1628         jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1629         if (env->ExceptionCheck()) {
1630             return nullptr;
1631         }
1632         env->SetObjectArrayElement(joa, 7, iqmp);
1633     }
1634 
1635     return joa;
1636 }
1637 
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1638 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1639         jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1640         jbyteArray nonceBytes, jint blockCounter) {
1641     CHECK_ERROR_QUEUE_ON_RETURN;
1642     JNI_TRACE("chacha20_encrypt_decrypt");
1643     ScopedByteArrayRO in(env, inBytes);
1644     if (in.get() == nullptr) {
1645         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1646         return;
1647     }
1648     ScopedByteArrayRW out(env, outBytes);
1649     if (out.get() == nullptr) {
1650         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1651         return;
1652     }
1653     ScopedByteArrayRO key(env, keyBytes);
1654     if (key.get() == nullptr) {
1655         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1656         return;
1657     }
1658     ScopedByteArrayRO nonce(env, nonceBytes);
1659     if (nonce.get() == nullptr) {
1660         JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1661         return;
1662     }
1663 
1664     CRYPTO_chacha_20(
1665             reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1666             reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1667             length,
1668             reinterpret_cast<const unsigned char*>(key.get()),
1669             reinterpret_cast<const unsigned char*>(nonce.get()),
1670             blockCounter);
1671 }
1672 
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1673 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1674     CHECK_ERROR_QUEUE_ON_RETURN;
1675     JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1676 
1677     ScopedUtfChars curveName(env, curveNameJava);
1678     if (curveName.c_str() == nullptr) {
1679         return 0;
1680     }
1681     JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1682 
1683     int nid = OBJ_sn2nid(curveName.c_str());
1684     if (nid == NID_undef) {
1685         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1686         return 0;
1687     }
1688 
1689     EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1690     if (group == nullptr) {
1691         JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1692         ERR_clear_error();
1693         return 0;
1694     }
1695 
1696     JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1697     return reinterpret_cast<uintptr_t>(group);
1698 }
1699 
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1700 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1701                                                  jbyteArray aBytes, jbyteArray bBytes,
1702                                                  jbyteArray xBytes, jbyteArray yBytes,
1703                                                  jbyteArray orderBytes, jint cofactorInt) {
1704     CHECK_ERROR_QUEUE_ON_RETURN;
1705     BIGNUM *p = nullptr, *a = nullptr, *b = nullptr, *x = nullptr, *y = nullptr;
1706     BIGNUM *order = nullptr, *cofactor = nullptr;
1707 
1708     JNI_TRACE("EC_GROUP_new_arbitrary");
1709 
1710     if (cofactorInt < 1) {
1711         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1712                                            "cofactor < 1");
1713         return 0;
1714     }
1715 
1716     cofactor = BN_new();
1717     if (cofactor == nullptr) {
1718         return 0;
1719     }
1720 
1721     int ok = 1;
1722 
1723     if (!arrayToBignum(env, pBytes, &p) || !arrayToBignum(env, aBytes, &a) ||
1724         !arrayToBignum(env, bBytes, &b) || !arrayToBignum(env, xBytes, &x) ||
1725         !arrayToBignum(env, yBytes, &y) || !arrayToBignum(env, orderBytes, &order) ||
1726         !BN_set_word(cofactor, static_cast<uint32_t>(cofactorInt))) {
1727         ok = 0;
1728     }
1729 
1730     bssl::UniquePtr<BIGNUM> pStorage(p);
1731     bssl::UniquePtr<BIGNUM> aStorage(a);
1732     bssl::UniquePtr<BIGNUM> bStorage(b);
1733     bssl::UniquePtr<BIGNUM> xStorage(x);
1734     bssl::UniquePtr<BIGNUM> yStorage(y);
1735     bssl::UniquePtr<BIGNUM> orderStorage(order);
1736     bssl::UniquePtr<BIGNUM> cofactorStorage(cofactor);
1737 
1738     if (!ok) {
1739         return 0;
1740     }
1741 
1742     bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1743     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
1744     if (group.get() == nullptr) {
1745         JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1746         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1747         return 0;
1748     }
1749 
1750     bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1751     if (generator.get() == nullptr) {
1752         JNI_TRACE("EC_POINT_new => null");
1753         ERR_clear_error();
1754         return 0;
1755     }
1756 
1757     if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
1758         JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1759         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1760                                                              "EC_POINT_set_affine_coordinates_GFp");
1761         return 0;
1762     }
1763 
1764     if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
1765         JNI_TRACE("EC_GROUP_set_generator => error");
1766         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1767         return 0;
1768     }
1769 
1770     JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1771     return reinterpret_cast<uintptr_t>(group.release());
1772 }
1773 
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1774 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1775     CHECK_ERROR_QUEUE_ON_RETURN;
1776     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1777     JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1778 
1779     if (group == nullptr) {
1780         JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1781         return nullptr;
1782     }
1783 
1784     int nid = EC_GROUP_get_curve_name(group);
1785     if (nid == NID_undef) {
1786         JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1787         return nullptr;
1788     }
1789 
1790     const char* shortName = OBJ_nid2sn(nid);
1791     JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1792     return env->NewStringUTF(shortName);
1793 }
1794 
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1795 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1796     CHECK_ERROR_QUEUE_ON_RETURN;
1797     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1798     JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1799     if (group == nullptr) {
1800         JNI_TRACE("EC_GROUP_get_curve => group == null");
1801         return nullptr;
1802     }
1803 
1804     bssl::UniquePtr<BIGNUM> p(BN_new());
1805     bssl::UniquePtr<BIGNUM> a(BN_new());
1806     bssl::UniquePtr<BIGNUM> b(BN_new());
1807 
1808     int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1809     if (ret != 1) {
1810         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1811         return nullptr;
1812     }
1813 
1814     jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1815     if (joa == nullptr) {
1816         return nullptr;
1817     }
1818 
1819     jbyteArray pArray = bignumToArray(env, p.get(), "p");
1820     if (env->ExceptionCheck()) {
1821         return nullptr;
1822     }
1823     env->SetObjectArrayElement(joa, 0, pArray);
1824 
1825     jbyteArray aArray = bignumToArray(env, a.get(), "a");
1826     if (env->ExceptionCheck()) {
1827         return nullptr;
1828     }
1829     env->SetObjectArrayElement(joa, 1, aArray);
1830 
1831     jbyteArray bArray = bignumToArray(env, b.get(), "b");
1832     if (env->ExceptionCheck()) {
1833         return nullptr;
1834     }
1835     env->SetObjectArrayElement(joa, 2, bArray);
1836 
1837     JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1838     return joa;
1839 }
1840 
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1841 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1842     CHECK_ERROR_QUEUE_ON_RETURN;
1843     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1844     JNI_TRACE("EC_GROUP_get_order(%p)", group);
1845     if (group == nullptr) {
1846         return nullptr;
1847     }
1848 
1849     bssl::UniquePtr<BIGNUM> order(BN_new());
1850     if (order.get() == nullptr) {
1851         JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1852         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1853         return nullptr;
1854     }
1855 
1856     if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1857         JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1858         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1859         return nullptr;
1860     }
1861 
1862     jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1863     if (env->ExceptionCheck()) {
1864         return nullptr;
1865     }
1866 
1867     JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1868     return orderArray;
1869 }
1870 
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1871 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1872     CHECK_ERROR_QUEUE_ON_RETURN;
1873     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1874     JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1875     if (group == nullptr) {
1876         return 0;
1877     }
1878 
1879     jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1880     if (degree == 0) {
1881         JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1882         conscrypt::jniutil::throwRuntimeException(env, "not supported");
1883         ERR_clear_error();
1884         return 0;
1885     }
1886 
1887     JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1888     return degree;
1889 }
1890 
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1891 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1892     CHECK_ERROR_QUEUE_ON_RETURN;
1893     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1894     JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1895     if (group == nullptr) {
1896         return nullptr;
1897     }
1898 
1899     bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1900     if (cofactor.get() == nullptr) {
1901         JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1902         conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1903         return nullptr;
1904     }
1905 
1906     if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1907         JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1908         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1909         return nullptr;
1910     }
1911 
1912     jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1913     if (env->ExceptionCheck()) {
1914         return nullptr;
1915     }
1916 
1917     JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1918     return cofactorArray;
1919 }
1920 
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1921 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1922     CHECK_ERROR_QUEUE_ON_RETURN;
1923     EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1924     JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1925 
1926     if (group == nullptr) {
1927         JNI_TRACE("EC_GROUP_clear_free => group == null");
1928         conscrypt::jniutil::throwNullPointerException(env, "group == null");
1929         return;
1930     }
1931 
1932     EC_GROUP_free(group);
1933     JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1934 }
1935 
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1936 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1937     CHECK_ERROR_QUEUE_ON_RETURN;
1938     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1939     JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1940 
1941     if (group == nullptr) {
1942         JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
1943         return 0;
1944     }
1945 
1946     const EC_POINT* generator = EC_GROUP_get0_generator(group);
1947 
1948     bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
1949     if (dup.get() == nullptr) {
1950         JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
1951         conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
1952         return 0;
1953     }
1954 
1955     JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
1956     return reinterpret_cast<uintptr_t>(dup.release());
1957 }
1958 
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)1959 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
1960     CHECK_ERROR_QUEUE_ON_RETURN;
1961     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1962     JNI_TRACE("EC_POINT_new(%p)", group);
1963 
1964     if (group == nullptr) {
1965         JNI_TRACE("EC_POINT_new(%p) => group == null", group);
1966         return 0;
1967     }
1968 
1969     EC_POINT* point = EC_POINT_new(group);
1970     if (point == nullptr) {
1971         conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
1972         return 0;
1973     }
1974 
1975     return reinterpret_cast<uintptr_t>(point);
1976 }
1977 
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)1978 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1979     CHECK_ERROR_QUEUE_ON_RETURN;
1980     EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
1981     JNI_TRACE("EC_POINT_clear_free(%p)", group);
1982 
1983     if (group == nullptr) {
1984         JNI_TRACE("EC_POINT_clear_free => group == null");
1985         conscrypt::jniutil::throwNullPointerException(env, "group == null");
1986         return;
1987     }
1988 
1989     EC_POINT_free(group);
1990     JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
1991 }
1992 
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)1993 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
1994                                                          jobject pointRef, jbyteArray xjavaBytes,
1995                                                          jbyteArray yjavaBytes) {
1996     CHECK_ERROR_QUEUE_ON_RETURN;
1997     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
1998               yjavaBytes);
1999     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2000     if (group == nullptr) {
2001         return;
2002     }
2003     EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2004     if (point == nullptr) {
2005         return;
2006     }
2007     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
2008               yjavaBytes);
2009 
2010     BIGNUM* xRef = nullptr;
2011     if (!arrayToBignum(env, xjavaBytes, &xRef)) {
2012         return;
2013     }
2014     bssl::UniquePtr<BIGNUM> x(xRef);
2015 
2016     BIGNUM* yRef = nullptr;
2017     if (!arrayToBignum(env, yjavaBytes, &yRef)) {
2018         return;
2019     }
2020     bssl::UniquePtr<BIGNUM> y(yRef);
2021 
2022     int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2023     if (ret != 1) {
2024         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2025                                                              "EC_POINT_set_affine_coordinates");
2026         return;
2027     }
2028 
2029     JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2030               yjavaBytes, ret);
2031 }
2032 
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2033 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2034                                                                  jobject groupRef,
2035                                                                  jobject pointRef) {
2036     CHECK_ERROR_QUEUE_ON_RETURN;
2037     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2038     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2039     if (group == nullptr) {
2040         return nullptr;
2041     }
2042     const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2043     if (point == nullptr) {
2044         return nullptr;
2045     }
2046     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2047 
2048     bssl::UniquePtr<BIGNUM> x(BN_new());
2049     bssl::UniquePtr<BIGNUM> y(BN_new());
2050 
2051     int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2052     if (ret != 1) {
2053         JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2054         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2055                                                              "EC_POINT_get_affine_coordinates");
2056         return nullptr;
2057     }
2058 
2059     jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2060     if (joa == nullptr) {
2061         return nullptr;
2062     }
2063 
2064     jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2065     if (env->ExceptionCheck()) {
2066         return nullptr;
2067     }
2068     env->SetObjectArrayElement(joa, 0, xBytes);
2069 
2070     jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2071     if (env->ExceptionCheck()) {
2072         return nullptr;
2073     }
2074     env->SetObjectArrayElement(joa, 1, yBytes);
2075 
2076     JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2077     return joa;
2078 }
2079 
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2080 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2081     CHECK_ERROR_QUEUE_ON_RETURN;
2082     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2083     JNI_TRACE("EC_KEY_generate_key(%p)", group);
2084     if (group == nullptr) {
2085         return 0;
2086     }
2087 
2088     bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2089     if (eckey.get() == nullptr) {
2090         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2091         conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2092         return 0;
2093     }
2094 
2095     if (EC_KEY_set_group(eckey.get(), group) != 1) {
2096         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2097         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2098         return 0;
2099     }
2100 
2101     if (EC_KEY_generate_key(eckey.get()) != 1) {
2102         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2103         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2104         return 0;
2105     }
2106 
2107     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2108     if (pkey.get() == nullptr) {
2109         JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2110         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2111         return 0;
2112     }
2113     if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2114         conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2115         ERR_clear_error();
2116         return 0;
2117     }
2118     OWNERSHIP_TRANSFERRED(eckey);
2119 
2120     JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2121     return reinterpret_cast<uintptr_t>(pkey.release());
2122 }
2123 
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2124 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2125     CHECK_ERROR_QUEUE_ON_RETURN;
2126     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2127     JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2128 
2129     if (pkey == nullptr) {
2130         JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2131         return 0;
2132     }
2133 
2134     if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2135         conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2136         JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2137         return 0;
2138     }
2139 
2140     EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2141     JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2142     return reinterpret_cast<uintptr_t>(group);
2143 }
2144 
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2145 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2146     CHECK_ERROR_QUEUE_ON_RETURN;
2147     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2148     JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2149 
2150     if (pkey == nullptr) {
2151         JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2152         return nullptr;
2153     }
2154 
2155     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2156     if (eckey.get() == nullptr) {
2157         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2158         return nullptr;
2159     }
2160 
2161     const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2162 
2163     jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2164     if (env->ExceptionCheck()) {
2165         JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2166         return nullptr;
2167     }
2168 
2169     JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2170     return privBytes;
2171 }
2172 
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2173 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2174     CHECK_ERROR_QUEUE_ON_RETURN;
2175     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2176     JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2177 
2178     if (pkey == nullptr) {
2179         JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2180         return 0;
2181     }
2182 
2183     bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2184     if (eckey.get() == nullptr) {
2185         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2186         return 0;
2187     }
2188 
2189     bssl::UniquePtr<EC_POINT> dup(
2190             EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2191     if (dup.get() == nullptr) {
2192         JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2193         conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2194         ERR_clear_error();
2195         return 0;
2196     }
2197 
2198     JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2199     return reinterpret_cast<uintptr_t>(dup.release());
2200 }
2201 
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2202 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2203     CHECK_ERROR_QUEUE_ON_RETURN;
2204     const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2205     JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2206     if (group == nullptr) {
2207         conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2208         return nullptr;
2209     }
2210 
2211     bssl::ScopedCBB cbb;
2212     if (!CBB_init(cbb.get(), 64)) {
2213         conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2214         JNI_TRACE("CBB_init failed");
2215         return nullptr;
2216     }
2217 
2218     if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2219         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2220         ERR_clear_error();
2221         JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2222         return nullptr;
2223     }
2224 
2225     return CBBToByteArray(env, cbb.get());
2226 }
2227 
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2228 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2229     CHECK_ERROR_QUEUE_ON_RETURN;
2230     JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2231 
2232     ScopedByteArrayRO bytes(env, curveNameBytes);
2233     if (bytes.get() == nullptr) {
2234         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2235         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2236         return 0;
2237     }
2238 
2239     CBS cbs;
2240     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2241     bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2242     if (!group || CBS_len(&cbs) != 0) {
2243         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2244         ERR_clear_error();
2245         JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2246         return 0;
2247     }
2248 
2249     JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2250     return reinterpret_cast<uintptr_t>(group.release());
2251 }
2252 
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2253 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2254                                           jobject pubkeyRef, jobject privkeyRef) {
2255     CHECK_ERROR_QUEUE_ON_RETURN;
2256     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2257     EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2258     if (pubPkey == nullptr) {
2259         JNI_TRACE("ECDH_compute_key => pubPkey == null");
2260         return -1;
2261     }
2262     EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2263     if (privPkey == nullptr) {
2264         JNI_TRACE("ECDH_compute_key => privPkey == null");
2265         return -1;
2266     }
2267     JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2268 
2269     ScopedByteArrayRW out(env, outArray);
2270     if (out.get() == nullptr) {
2271         JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2272                   pubPkey, privPkey);
2273         return -1;
2274     }
2275 
2276     if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2277         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2278                                            nullptr);
2279         return -1;
2280     }
2281 
2282     if (pubPkey == nullptr) {
2283         JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2284         conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2285         return -1;
2286     }
2287 
2288     bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2289     if (pubkey.get() == nullptr) {
2290         JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2291         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2292                                                       conscrypt::jniutil::throwInvalidKeyException);
2293         return -1;
2294     }
2295 
2296     const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2297     if (pubkeyPoint == nullptr) {
2298         JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2299         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2300                                                       conscrypt::jniutil::throwInvalidKeyException);
2301         return -1;
2302     }
2303 
2304     if (privPkey == nullptr) {
2305         JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2306         conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2307         return -1;
2308     }
2309 
2310     bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2311     if (privkey.get() == nullptr) {
2312         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2313                                                       conscrypt::jniutil::throwInvalidKeyException);
2314         return -1;
2315     }
2316 
2317     std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2318     int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2319                                         privkey.get(), nullptr /* No KDF */);
2320     if (outputLength == -1) {
2321         JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2322         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2323                                                       conscrypt::jniutil::throwInvalidKeyException);
2324         return -1;
2325     }
2326 
2327     JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2328     return outputLength;
2329 }
2330 
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2331 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2332     CHECK_ERROR_QUEUE_ON_RETURN;
2333     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2334     JNI_TRACE("ECDSA_size(%p)", pkey);
2335 
2336     if (pkey == nullptr) {
2337         return 0;
2338     }
2339 
2340     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2341     if (ec_key.get() == nullptr) {
2342         conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2343         ERR_clear_error();
2344         return 0;
2345     }
2346 
2347     size_t size = ECDSA_size(ec_key.get());
2348 
2349     JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2350     return static_cast<jint>(size);
2351 }
2352 
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2353 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2354                                     jobject pkeyRef) {
2355     CHECK_ERROR_QUEUE_ON_RETURN;
2356     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2357     JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2358 
2359     if (pkey == nullptr) {
2360         return -1;
2361     }
2362 
2363     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2364     if (ec_key.get() == nullptr) {
2365         return -1;
2366     }
2367 
2368     ScopedByteArrayRO data_array(env, data);
2369     if (data_array.get() == nullptr) {
2370         return -1;
2371     }
2372 
2373     ScopedByteArrayRW sig_array(env, sig);
2374     if (sig_array.get() == nullptr) {
2375         return -1;
2376     }
2377 
2378     unsigned int sig_size;
2379     int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2380                             data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2381                             &sig_size, ec_key.get());
2382     if (result == 0) {
2383         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2384         JNI_TRACE("ECDSA_sign => threw error");
2385         return -1;
2386     }
2387 
2388     JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2389     return static_cast<jint>(sig_size);
2390 }
2391 
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2392 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2393                                       jobject pkeyRef) {
2394     CHECK_ERROR_QUEUE_ON_RETURN;
2395     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2396     JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2397 
2398     if (pkey == nullptr) {
2399         return -1;
2400     }
2401 
2402     bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2403     if (ec_key.get() == nullptr) {
2404         return -1;
2405     }
2406 
2407     ScopedByteArrayRO data_array(env, data);
2408     if (data_array.get() == nullptr) {
2409         return -1;
2410     }
2411 
2412     ScopedByteArrayRO sig_array(env, sig);
2413     if (sig_array.get() == nullptr) {
2414         return -1;
2415     }
2416 
2417     int result =
2418             ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2419                          data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2420                          sig_array.size(), ec_key.get());
2421 
2422     if (result == 0) {
2423         // NOLINTNEXTLINE(runtime/int)
2424         unsigned long error = ERR_peek_last_error();
2425         if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2426             (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2427             // This error just means the signature didn't verify, so clear the error and return
2428             // a failed verification
2429             ERR_clear_error();
2430             JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2431             return 0;
2432         }
2433         if (error != 0) {
2434             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2435             JNI_TRACE("ECDSA_verify => threw error");
2436             return -1;
2437         }
2438         return 0;
2439     }
2440 
2441     JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2442     return static_cast<jint>(result);
2443 }
2444 
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2445 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2446                                           jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2447     CHECK_ERROR_QUEUE_ON_RETURN;
2448     JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2449 
2450     ScopedByteArrayRW out(env, outArray);
2451     if (out.get() == nullptr) {
2452         JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2453         return JNI_FALSE;
2454     }
2455 
2456     ScopedByteArrayRO privkey(env, privkeyArray);
2457     if (privkey.get() == nullptr) {
2458         JNI_TRACE("X25519(%p) => privkey == null", outArray);
2459         return JNI_FALSE;
2460     }
2461 
2462     ScopedByteArrayRO pubkey(env, pubkeyArray);
2463     if (pubkey.get() == nullptr) {
2464         JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2465         return JNI_FALSE;
2466     }
2467 
2468     if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2469                reinterpret_cast<const uint8_t*>(privkey.get()),
2470                reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2471         JNI_TRACE("X25519(%p) => failure", outArray);
2472         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2473                                                       conscrypt::jniutil::throwInvalidKeyException);
2474         return JNI_FALSE;
2475     }
2476 
2477     JNI_TRACE("X25519(%p) => success", outArray);
2478     return JNI_TRUE;
2479 }
2480 
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2481 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2482     CHECK_ERROR_QUEUE_ON_RETURN;
2483     JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2484 
2485     ScopedByteArrayRW outPublic(env, outPublicArray);
2486     if (outPublic.get() == nullptr) {
2487         JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2488         return;
2489     }
2490 
2491     ScopedByteArrayRW outPrivate(env, outPrivateArray);
2492     if (outPrivate.get() == nullptr) {
2493         JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2494         return;
2495     }
2496 
2497     if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2498         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2499         return;
2500     }
2501 
2502     X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2503     JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2504 }
2505 
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2506 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2507     CHECK_ERROR_QUEUE_ON_RETURN;
2508     JNI_TRACE_MD("EVP_MD_CTX_create()");
2509 
2510     bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2511     if (ctx.get() == nullptr) {
2512         conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2513         return 0;
2514     }
2515 
2516     JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2517     return reinterpret_cast<uintptr_t>(ctx.release());
2518 }
2519 
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2520 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2521     CHECK_ERROR_QUEUE_ON_RETURN;
2522     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2523     JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2524 
2525     if (ctx != nullptr) {
2526         EVP_MD_CTX_cleanup(ctx);
2527     }
2528 }
2529 
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2530 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2531     CHECK_ERROR_QUEUE_ON_RETURN;
2532     EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2533     JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2534 
2535     if (ctx != nullptr) {
2536         EVP_MD_CTX_destroy(ctx);
2537     }
2538 }
2539 
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2540 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2541                                             jobject srcCtxRef) {
2542     CHECK_ERROR_QUEUE_ON_RETURN;
2543     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2544     EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2545     if (dst_ctx == nullptr) {
2546         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2547         return 0;
2548     }
2549     const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2550     if (src_ctx == nullptr) {
2551         JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2552         return 0;
2553     }
2554     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2555 
2556     int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2557     if (result == 0) {
2558         conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2559         ERR_clear_error();
2560     }
2561 
2562     JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2563     return result;
2564 }
2565 
2566 /*
2567  * public static native int EVP_DigestFinal_ex(long, byte[], int)
2568  */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2569 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2570                                             jint offset) {
2571     CHECK_ERROR_QUEUE_ON_RETURN;
2572     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2573     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2574 
2575     if (ctx == nullptr) {
2576         JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2577         return -1;
2578     } else if (hash == nullptr) {
2579         conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2580         return -1;
2581     }
2582 
2583     ScopedByteArrayRW hashBytes(env, hash);
2584     if (hashBytes.get() == nullptr) {
2585         return -1;
2586     }
2587     unsigned int bytesWritten = static_cast<unsigned int>(-1);
2588     int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2589                                 &bytesWritten);
2590     if (ok == 0) {
2591         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2592         return -1;
2593     }
2594 
2595     JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2596     return static_cast<jint>(bytesWritten);
2597 }
2598 
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2599 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2600                                            jlong evpMdRef) {
2601     CHECK_ERROR_QUEUE_ON_RETURN;
2602     EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2603     const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2604     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2605 
2606     if (ctx == nullptr) {
2607         JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2608         return 0;
2609     } else if (evp_md == nullptr) {
2610         conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2611         return 0;
2612     }
2613 
2614     int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2615     if (ok == 0) {
2616         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2617         JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2618         return 0;
2619     }
2620     JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2621     return ok;
2622 }
2623 
2624 /*
2625  * public static native int EVP_get_digestbyname(java.lang.String)
2626  */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2627 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2628     CHECK_ERROR_QUEUE_ON_RETURN;
2629     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2630 
2631     if (algorithm == nullptr) {
2632         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2633         return -1;
2634     }
2635 
2636     ScopedUtfChars algorithmChars(env, algorithm);
2637     if (algorithmChars.c_str() == nullptr) {
2638         return 0;
2639     }
2640     JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2641 
2642     const char* alg = algorithmChars.c_str();
2643     const EVP_MD* md;
2644 
2645     if (strcasecmp(alg, "md4") == 0) {
2646         md = EVP_md4();
2647     } else if (strcasecmp(alg, "md5") == 0) {
2648         md = EVP_md5();
2649     } else if (strcasecmp(alg, "sha1") == 0) {
2650         md = EVP_sha1();
2651     } else if (strcasecmp(alg, "sha224") == 0) {
2652         md = EVP_sha224();
2653     } else if (strcasecmp(alg, "sha256") == 0) {
2654         md = EVP_sha256();
2655     } else if (strcasecmp(alg, "sha384") == 0) {
2656         md = EVP_sha384();
2657     } else if (strcasecmp(alg, "sha512") == 0) {
2658         md = EVP_sha512();
2659     } else {
2660         JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2661         conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2662         return 0;
2663     }
2664 
2665     return reinterpret_cast<uintptr_t>(md);
2666 }
2667 
2668 /*
2669  * public static native int EVP_MD_size(long)
2670  */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2671 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2672     CHECK_ERROR_QUEUE_ON_RETURN;
2673     EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2674     JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2675 
2676     if (evp_md == nullptr) {
2677         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2678         return -1;
2679     }
2680 
2681     jint result = static_cast<jint>(EVP_MD_size(evp_md));
2682     JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2683     return result;
2684 }
2685 
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)2686 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2687                                      int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2688                                                       ENGINE*, EVP_PKEY*),
2689                                      const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2690                                      jobject pkeyRef) {
2691     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2692     if (mdCtx == nullptr) {
2693         JNI_TRACE("%s => mdCtx == null", jniName);
2694         return 0;
2695     }
2696     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2697     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2698     if (pkey == nullptr) {
2699         JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2700         return 0;
2701     }
2702     JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2703 
2704     if (md == nullptr) {
2705         JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2706         conscrypt::jniutil::throwNullPointerException(env, "md == null");
2707         return 0;
2708     }
2709 
2710     EVP_PKEY_CTX* pctx = nullptr;
2711     if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2712         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2713         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2714         return 0;
2715     }
2716 
2717     JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2718     return reinterpret_cast<jlong>(pctx);
2719 }
2720 
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2721 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2722                                              const jlong evpMdRef, jobject pkeyRef) {
2723     CHECK_ERROR_QUEUE_ON_RETURN;
2724     return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2725                                    evpMdRef, pkeyRef);
2726 }
2727 
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2728 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2729                                                const jlong evpMdRef, jobject pkeyRef) {
2730     CHECK_ERROR_QUEUE_ON_RETURN;
2731     return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2732                                    evpMdRef, pkeyRef);
2733 }
2734 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2735 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2736                       const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2737     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2738     const void* p = reinterpret_cast<const void*>(inPtr);
2739     JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2740 
2741     if (mdCtx == nullptr) {
2742         return;
2743     }
2744 
2745     if (p == nullptr) {
2746         conscrypt::jniutil::throwNullPointerException(env, nullptr);
2747         return;
2748     }
2749 
2750     if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2751         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2752         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2753         return;
2754     }
2755 
2756     JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2757 }
2758 
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2759 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2760                       jint inLength, const char* jniName,
2761                       int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2762     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2763     JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2764 
2765     if (mdCtx == nullptr) {
2766         return;
2767     }
2768 
2769     if (inJavaBytes == nullptr) {
2770         conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2771         return;
2772     }
2773 
2774     size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2775     if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2776         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2777                                            "inBytes");
2778         return;
2779     }
2780     if (inLength == 0) {
2781         return;
2782     }
2783     jint in_offset = inOffset;
2784     jint in_size = inLength;
2785 
2786     int update_func_result = -1;
2787     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2788         // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2789         // avoid copying the whole array.
2790         if (in_size <= 1024) {
2791             // For small chunk, it's more efficient to use a bit more space on the stack instead of
2792             // allocating a new buffer.
2793             jbyte buf[1024];
2794             env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2795             update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2796                                              static_cast<size_t>(in_size));
2797         } else {
2798             // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2799             // through the buffer, stopping as soon as update_func fails.
2800             jint remaining = in_size;
2801             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2802             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2803             if (buf.get() == nullptr) {
2804                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2805                 return;
2806             }
2807             while (remaining > 0) {
2808                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2809                 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2810                 update_func_result =
2811                         update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2812                                     static_cast<size_t>(chunk_size));
2813                 if (!update_func_result) {
2814                     // update_func failed. This will be handled later in this method.
2815                     break;
2816                 }
2817                 in_offset += chunk_size;
2818                 remaining -= chunk_size;
2819             }
2820         }
2821     } else {
2822         // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2823         // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2824         // use GetByteArrayElements or another approach.
2825         jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2826         if (array_elements == nullptr) {
2827             conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2828             return;
2829         }
2830         const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2831         update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2832         env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2833     }
2834 
2835     if (!update_func_result) {
2836         JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2837         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2838         return;
2839     }
2840 
2841     JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2842 }
2843 
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2844 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2845                                                 jlong inPtr, jint inLength) {
2846     CHECK_ERROR_QUEUE_ON_RETURN;
2847     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2848 }
2849 
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2850 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2851                                           jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2852     CHECK_ERROR_QUEUE_ON_RETURN;
2853     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2854               EVP_DigestUpdate);
2855 }
2856 
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2857 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2858                                               jbyteArray inJavaBytes, jint inOffset,
2859                                               jint inLength) {
2860     CHECK_ERROR_QUEUE_ON_RETURN;
2861     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2862             EVP_DigestSignUpdate);
2863 }
2864 
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2865 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2866         jlong inPtr, jint inLength) {
2867     CHECK_ERROR_QUEUE_ON_RETURN;
2868     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2869             EVP_DigestSignUpdate);
2870 }
2871 
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2872 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2873                                                 jbyteArray inJavaBytes, jint inOffset,
2874                                                 jint inLength) {
2875     CHECK_ERROR_QUEUE_ON_RETURN;
2876     evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2877               EVP_DigestVerifyUpdate);
2878 }
2879 
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2880 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2881                                                       jlong inPtr, jint inLength) {
2882     CHECK_ERROR_QUEUE_ON_RETURN;
2883     evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2884               EVP_DigestVerifyUpdate);
2885 }
2886 
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2887 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2888     CHECK_ERROR_QUEUE_ON_RETURN;
2889     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2890     JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2891 
2892     if (mdCtx == nullptr) {
2893         return nullptr;
2894     }
2895 
2896     size_t maxLen;
2897     if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2898         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2899         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2900         return nullptr;
2901     }
2902 
2903     std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2904     if (buffer.get() == nullptr) {
2905         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2906         return nullptr;
2907     }
2908     size_t actualLen(maxLen);
2909     if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2910         JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2911         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2912         return nullptr;
2913     }
2914     if (actualLen > maxLen) {
2915         JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2916                   maxLen);
2917         conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2918         return nullptr;
2919     }
2920 
2921     ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2922     if (sigJavaBytes.get() == nullptr) {
2923         conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2924         return nullptr;
2925     }
2926     env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2927                             reinterpret_cast<jbyte*>(buffer.get()));
2928 
2929     JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2930     return sigJavaBytes.release();
2931 }
2932 
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2933 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2934                                                    jbyteArray signature, jint offset, jint len) {
2935     CHECK_ERROR_QUEUE_ON_RETURN;
2936     EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2937     JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2938 
2939     if (mdCtx == nullptr) {
2940         return 0;
2941     }
2942 
2943     ScopedByteArrayRO sigBytes(env, signature);
2944     if (sigBytes.get() == nullptr) {
2945         return 0;
2946     }
2947 
2948     if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
2949         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2950                                            "signature");
2951         return 0;
2952     }
2953 
2954     const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
2955     int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
2956     jboolean result;
2957     if (err == 1) {
2958         // Signature verified
2959         result = 1;
2960     } else if (err == 0) {
2961         // Signature did not verify
2962         result = 0;
2963     } else {
2964         // Error while verifying signature
2965         JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
2966         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
2967         return 0;
2968     }
2969 
2970     // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
2971     // Clear the error queue to prevent its state from affecting future operations.
2972     ERR_clear_error();
2973 
2974     JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
2975     return result;
2976 }
2977 
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)2978 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
2979                                   int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
2980                                                               const uint8_t*, size_t),
2981                                   const char* jniName, jobject evpPkeyCtxRef,
2982                                   jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
2983                                   jint inOffset, jint inLength) {
2984     EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
2985     JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
2986                  inJavaBytes, inOffset, inLength);
2987 
2988     if (pkeyCtx == nullptr) {
2989         return 0;
2990     }
2991 
2992     ScopedByteArrayRW outBytes(env, outJavaBytes);
2993     if (outBytes.get() == nullptr) {
2994         return 0;
2995     }
2996 
2997     ScopedByteArrayRO inBytes(env, inJavaBytes);
2998     if (inBytes.get() == nullptr) {
2999         return 0;
3000     }
3001 
3002     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3003         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3004                                            "outBytes");
3005         return 0;
3006     }
3007 
3008     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3009         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3010                                            "inBytes");
3011         return 0;
3012     }
3013 
3014     uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3015     const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3016     size_t outLength = outBytes.size() - outOffset;
3017     if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3018                               static_cast<size_t>(inLength))) {
3019         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3020         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3021                 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3022         return 0;
3023     }
3024 
3025     JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3026               outOffset, inJavaBytes, inOffset, inLength, outLength);
3027     return static_cast<jint>(outLength);
3028 }
3029 
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3030 static jint NativeCrypto_EVP_PKEY_encrypt(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_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3035                                  outOffset, inBytes, inOffset, inLength);
3036 }
3037 
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3038 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3039                                           jbyteArray out, jint outOffset, jbyteArray inBytes,
3040                                           jint inOffset, jint inLength) {
3041     CHECK_ERROR_QUEUE_ON_RETURN;
3042     return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3043                                  outOffset, inBytes, inOffset, inLength);
3044 }
3045 
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3046 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3047                                       int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3048     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3049     JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3050     if (pkey == nullptr) {
3051         JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3052         return 0;
3053     }
3054 
3055     bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3056     if (pkeyCtx.get() == nullptr) {
3057         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3058         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3059                 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3060         return 0;
3061     }
3062 
3063     if (!real_func(pkeyCtx.get())) {
3064         JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3065         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3066                 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3067         return 0;
3068     }
3069 
3070     JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3071     return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3072 }
3073 
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3074 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3075     CHECK_ERROR_QUEUE_ON_RETURN;
3076     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3077 }
3078 
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3079 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3080     CHECK_ERROR_QUEUE_ON_RETURN;
3081     return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3082 }
3083 
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3084 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3085     CHECK_ERROR_QUEUE_ON_RETURN;
3086     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3087     JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3088 
3089     if (pkeyCtx != nullptr) {
3090         EVP_PKEY_CTX_free(pkeyCtx);
3091     }
3092 }
3093 
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3094 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3095     CHECK_ERROR_QUEUE_ON_RETURN;
3096     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3097     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3098     if (pkeyCtx == nullptr) {
3099         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3100         return;
3101     }
3102 
3103     int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3104     if (result <= 0) {
3105         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3106         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3107                 env, "EVP_PKEY_CTX_set_rsa_padding",
3108                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3109         return;
3110     }
3111 
3112     JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3113 }
3114 
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3115 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3116                                                           jint len) {
3117     CHECK_ERROR_QUEUE_ON_RETURN;
3118     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3119     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3120     if (pkeyCtx == nullptr) {
3121         conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3122         return;
3123     }
3124 
3125     int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3126     if (result <= 0) {
3127         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3128         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3129                 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3130                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3131         return;
3132     }
3133 
3134     JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3135 }
3136 
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3137 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3138                                int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3139     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3140     EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3141     JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3142     if (pkeyCtx == nullptr) {
3143         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3144         return;
3145     }
3146     if (md == nullptr) {
3147         conscrypt::jniutil::throwNullPointerException(env, "md == null");
3148         return;
3149     }
3150 
3151     int result = ctrl_func(pkeyCtx, md);
3152     if (result <= 0) {
3153         JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3154         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3155                 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3156         return;
3157     }
3158 
3159     JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3160 }
3161 
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3162 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3163                                                       jlong mdRef) {
3164     CHECK_ERROR_QUEUE_ON_RETURN;
3165     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3166                        EVP_PKEY_CTX_set_rsa_mgf1_md);
3167 }
3168 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3169 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3170                                                       jlong mdRef) {
3171     CHECK_ERROR_QUEUE_ON_RETURN;
3172     evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3173                        EVP_PKEY_CTX_set_rsa_oaep_md);
3174 }
3175 
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3176 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3177                                                          jbyteArray labelJava) {
3178     CHECK_ERROR_QUEUE_ON_RETURN;
3179     EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3180     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3181     if (pkeyCtx == nullptr) {
3182         conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3183         return;
3184     }
3185 
3186     ScopedByteArrayRO labelBytes(env, labelJava);
3187     if (labelBytes.get() == nullptr) {
3188         return;
3189     }
3190 
3191     bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3192     memcpy(label.get(), labelBytes.get(), labelBytes.size());
3193 
3194     int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3195     if (result <= 0) {
3196         JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3197         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3198                 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3199                 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3200         return;
3201     }
3202     OWNERSHIP_TRANSFERRED(label);
3203 
3204     JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3205 }
3206 
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3207 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3208     CHECK_ERROR_QUEUE_ON_RETURN;
3209     JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3210 
3211     ScopedUtfChars scoped_alg(env, algorithm);
3212     const char* alg = scoped_alg.c_str();
3213     const EVP_CIPHER* cipher;
3214 
3215     if (strcasecmp(alg, "rc4") == 0) {
3216         cipher = EVP_rc4();
3217     } else if (strcasecmp(alg, "des-cbc") == 0) {
3218         cipher = EVP_des_cbc();
3219     } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3220         cipher = EVP_des_ede_cbc();
3221     } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3222         cipher = EVP_des_ede3_cbc();
3223     } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3224         cipher = EVP_aes_128_ecb();
3225     } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3226         cipher = EVP_aes_128_cbc();
3227     } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3228         cipher = EVP_aes_128_ctr();
3229     } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3230         cipher = EVP_aes_128_gcm();
3231     } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3232         cipher = EVP_aes_192_ecb();
3233     } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3234         cipher = EVP_aes_192_cbc();
3235     } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3236         cipher = EVP_aes_192_ctr();
3237     } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3238         cipher = EVP_aes_192_gcm();
3239     } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3240         cipher = EVP_aes_256_ecb();
3241     } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3242         cipher = EVP_aes_256_cbc();
3243     } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3244         cipher = EVP_aes_256_ctr();
3245     } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3246         cipher = EVP_aes_256_gcm();
3247     } else {
3248         JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
3249         return 0;
3250     }
3251 
3252     return reinterpret_cast<uintptr_t>(cipher);
3253 }
3254 
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3255 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3256                                            jbyteArray keyArray, jbyteArray ivArray,
3257                                            jboolean encrypting) {
3258     CHECK_ERROR_QUEUE_ON_RETURN;
3259     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3260     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3261     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3262               encrypting ? 1 : 0);
3263 
3264     if (ctx == nullptr) {
3265         JNI_TRACE("EVP_CipherUpdate => ctx == null");
3266         return;
3267     }
3268 
3269     // The key can be null if we need to set extra parameters.
3270     std::unique_ptr<unsigned char[]> keyPtr;
3271     if (keyArray != nullptr) {
3272         ScopedByteArrayRO keyBytes(env, keyArray);
3273         if (keyBytes.get() == nullptr) {
3274             return;
3275         }
3276 
3277         keyPtr.reset(new unsigned char[keyBytes.size()]);
3278         memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3279     }
3280 
3281     // The IV can be null if we're using ECB.
3282     std::unique_ptr<unsigned char[]> ivPtr;
3283     if (ivArray != nullptr) {
3284         ScopedByteArrayRO ivBytes(env, ivArray);
3285         if (ivBytes.get() == nullptr) {
3286             return;
3287         }
3288 
3289         ivPtr.reset(new unsigned char[ivBytes.size()]);
3290         memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3291     }
3292 
3293     if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3294                            encrypting ? 1 : 0)) {
3295         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3296         JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3297         return;
3298     }
3299 
3300     JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3301               encrypting ? 1 : 0);
3302 }
3303 
3304 /*
3305  *  public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3306  *          int inOffset, int inLength);
3307  */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3308 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3309                                           jint outOffset, jbyteArray inArray, jint inOffset,
3310                                           jint inLength) {
3311     CHECK_ERROR_QUEUE_ON_RETURN;
3312     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3313     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3314 
3315     if (ctx == nullptr) {
3316         JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3317         return 0;
3318     }
3319 
3320     ScopedByteArrayRO inBytes(env, inArray);
3321     if (inBytes.get() == nullptr) {
3322         return 0;
3323     }
3324     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3325         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3326                                            "inBytes");
3327         return 0;
3328     }
3329 
3330     ScopedByteArrayRW outBytes(env, outArray);
3331     if (outBytes.get() == nullptr) {
3332         return 0;
3333     }
3334     if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3335         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3336                                            "outBytes");
3337         return 0;
3338     }
3339 
3340     JNI_TRACE(
3341             "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3342             "out.length=%zd outOffset=%d",
3343             ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3344             outOffset);
3345 
3346     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3347     const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3348 
3349     int outl;
3350     if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3351         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3352         JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3353         return 0;
3354     }
3355 
3356     JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3357               inOffset, outl);
3358     return outl;
3359 }
3360 
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3361 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3362                                             jbyteArray outArray, jint outOffset) {
3363     CHECK_ERROR_QUEUE_ON_RETURN;
3364     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3365     JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3366 
3367     if (ctx == nullptr) {
3368         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3369         return 0;
3370     }
3371 
3372     ScopedByteArrayRW outBytes(env, outArray);
3373     if (outBytes.get() == nullptr) {
3374         return 0;
3375     }
3376 
3377     unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3378 
3379     int outl;
3380     if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3381         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3382                 conscrypt::jniutil::throwBadPaddingException);
3383         JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3384         return 0;
3385     }
3386 
3387     JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3388     return outl;
3389 }
3390 
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3391 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3392     CHECK_ERROR_QUEUE_ON_RETURN;
3393     const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3394     JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3395 
3396     if (evpCipher == nullptr) {
3397         conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3398         JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3399         return 0;
3400     }
3401 
3402     jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3403     JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3404     return ivLength;
3405 }
3406 
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3407 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3408     CHECK_ERROR_QUEUE_ON_RETURN;
3409     JNI_TRACE("EVP_CIPHER_CTX_new()");
3410 
3411     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3412     if (ctx.get() == nullptr) {
3413         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3414         JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3415         return 0;
3416     }
3417 
3418     JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3419     return reinterpret_cast<uintptr_t>(ctx.release());
3420 }
3421 
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3422 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3423     CHECK_ERROR_QUEUE_ON_RETURN;
3424     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3425     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3426 
3427     if (ctx == nullptr) {
3428         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3429         return 0;
3430     }
3431 
3432     jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3433     JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3434     return blockSize;
3435 }
3436 
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3437 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3438     CHECK_ERROR_QUEUE_ON_RETURN;
3439     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3440     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3441 
3442     if (ctx == nullptr) {
3443         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3444         return 0;
3445     }
3446 
3447     int buf_len = ctx->buf_len;
3448     JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3449     return buf_len;
3450 }
3451 
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3452 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3453     CHECK_ERROR_QUEUE_ON_RETURN;
3454     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3455     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3456 
3457     if (ctx == nullptr) {
3458         JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3459         return 0;
3460     }
3461 
3462     bool final_used = ctx->final_used != 0;
3463     JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3464     return static_cast<jboolean>(final_used);
3465 }
3466 
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3467 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3468                                                     jboolean enablePaddingBool) {
3469     CHECK_ERROR_QUEUE_ON_RETURN;
3470     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3471     jint enablePadding = enablePaddingBool ? 1 : 0;
3472     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3473 
3474     if (ctx == nullptr) {
3475         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3476         return;
3477     }
3478 
3479     EVP_CIPHER_CTX_set_padding(ctx, enablePadding);  // Not void, but always returns 1.
3480     JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3481 }
3482 
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3483 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3484                                                        jint keySizeBits) {
3485     CHECK_ERROR_QUEUE_ON_RETURN;
3486     EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3487     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3488 
3489     if (ctx == nullptr) {
3490         JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3491         return;
3492     }
3493 
3494     if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3495         conscrypt::jniutil::throwExceptionFromBoringSSLError(
3496                 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3497         JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3498         return;
3499     }
3500     JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3501 }
3502 
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3503 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3504     CHECK_ERROR_QUEUE_ON_RETURN;
3505     EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3506     JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3507 
3508     EVP_CIPHER_CTX_free(ctx);
3509 }
3510 
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3511 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3512     CHECK_ERROR_QUEUE_ON_RETURN;
3513     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3514     JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3515     return reinterpret_cast<jlong>(ctx);
3516 }
3517 
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3518 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3519     CHECK_ERROR_QUEUE_ON_RETURN;
3520     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3521     JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3522     return reinterpret_cast<jlong>(ctx);
3523 }
3524 
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3525 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3526     CHECK_ERROR_QUEUE_ON_RETURN;
3527     const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3528     JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3529     return reinterpret_cast<jlong>(ctx);
3530 }
3531 
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3532 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3533     CHECK_ERROR_QUEUE_ON_RETURN;
3534     const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3535     JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3536     return reinterpret_cast<jlong>(ctx);
3537 }
3538 
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3539 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3540     CHECK_ERROR_QUEUE_ON_RETURN;
3541     const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3542     JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3543     return reinterpret_cast<jlong>(ctx);
3544 }
3545 
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3546 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3547     CHECK_ERROR_QUEUE_ON_RETURN;
3548     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3549     JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3550     if (evpAead == nullptr) {
3551         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3552         return 0;
3553     }
3554     jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3555     JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3556     return maxOverhead;
3557 }
3558 
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3559 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3560     CHECK_ERROR_QUEUE_ON_RETURN;
3561     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3562     JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3563     if (evpAead == nullptr) {
3564         conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3565         return 0;
3566     }
3567     jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3568     JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3569     return nonceLength;
3570 }
3571 
3572 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3573                                     size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3574                                     const uint8_t* in, size_t in_len, const uint8_t* ad,
3575                                     size_t ad_len);
3576 
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)3577 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3578                                uint8_t* outBuf, jbyteArray nonceArray,
3579                                const uint8_t* inBuf, jbyteArray aadArray,
3580                                evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange)  {
3581     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3582 
3583     ScopedByteArrayRO keyBytes(env, keyArray);
3584     if (keyBytes.get() == nullptr) {
3585         return 0;
3586     }
3587 
3588     std::unique_ptr<ScopedByteArrayRO> aad;
3589     const uint8_t* aad_chars = nullptr;
3590     size_t aad_chars_size = 0;
3591     if (aadArray != nullptr) {
3592         aad.reset(new ScopedByteArrayRO(env, aadArray));
3593         aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3594         if (aad_chars == nullptr) {
3595             return 0;
3596         }
3597         aad_chars_size = aad->size();
3598     }
3599 
3600     ScopedByteArrayRO nonceBytes(env, nonceArray);
3601     if (nonceBytes.get() == nullptr) {
3602         return 0;
3603     }
3604 
3605     bssl::ScopedEVP_AEAD_CTX aeadCtx;
3606     const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3607     if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3608                            static_cast<size_t>(tagLen), nullptr)) {
3609         conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3610                                                              "failure initializing AEAD context");
3611         JNI_TRACE(
3612                 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3613                 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3614                 aadArray);
3615         return 0;
3616     }
3617 
3618     const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3619     size_t actualOutLength;
3620 
3621     if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3622                   nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3623                   aad_chars, aad_chars_size)) {
3624         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3625         return 0;
3626     }
3627 
3628     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3629               evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3630               aadArray, actualOutLength);
3631     return static_cast<jint>(actualOutLength);
3632 }
3633 
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)3634 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3635                             jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3636                             jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3637                             evp_aead_ctx_op_func realFunc) {
3638     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3639     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3640               outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3641 
3642 
3643     ScopedByteArrayRW outBytes(env, outArray);
3644     if (outBytes.get() == nullptr) {
3645         return 0;
3646     }
3647 
3648     if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3649         JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3650                   evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3651                   inLength, aadArray);
3652         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3653         return 0;
3654     }
3655 
3656     ScopedByteArrayRO inBytes(env, inArray);
3657     if (inBytes.get() == nullptr) {
3658         return 0;
3659     }
3660 
3661     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3662         JNI_TRACE(
3663                 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3664                 "invalid",
3665                 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3666                 inLength, aadArray);
3667         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3668         return 0;
3669     }
3670 
3671     uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3672     const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3673 
3674     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3675                             aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3676 }
3677 
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)3678 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3679                             jobject outBuffer, jbyteArray nonceArray,
3680                             jobject inBuffer, jbyteArray aadArray,
3681                             evp_aead_ctx_op_func realFunc) {
3682 
3683     const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3684     JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3685               outBuffer, nonceArray, inBuffer, aadArray);
3686 
3687     if (env->IsInstanceOf(inBuffer, conscrypt::jniutil::byteBufferClass) != JNI_TRUE ||
3688                         env->IsInstanceOf(outBuffer, conscrypt::jniutil::byteBufferClass) != JNI_TRUE  ) {
3689         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "ByteBuffer Class Error");
3690         return 0;
3691     }
3692 
3693     uint8_t* inBuf;
3694     jint in_limit;
3695     jint in_position;
3696     jint inCapacity = env->GetDirectBufferCapacity(inBuffer);
3697     if (inCapacity == -1) {
3698         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Non Direct ByteBuffer  Error");
3699         return 0;
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     jint outCapacity = env->GetDirectBufferCapacity(outBuffer);
3711     if (outCapacity == -1) {
3712         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Non Direct ByteBuffer  Error");
3713         return 0;
3714     }
3715     outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3716     // limit is the index of the first element that should not be read or written
3717     out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3718     // position is the index of the next element to be read or written
3719     out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3720 
3721     // Shifting over of ByteBuffer address to start at true position
3722     inBuf += in_position;
3723     outBuf += out_position;
3724 
3725     size_t inSize = in_limit - in_position;
3726     uint8_t* outBufEnd = outBuf + out_limit - out_position;
3727     uint8_t* inBufEnd = inBuf + inSize;
3728     std::unique_ptr<uint8_t[]> inCopy;
3729     if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3730       inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3731       if (inCopy.get() == nullptr) {
3732             conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3733             return 0;
3734         }
3735         memcpy(inCopy.get(), inBuf, inSize);
3736         inBuf = inCopy.get();
3737     }
3738 
3739     return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3740                                inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3741 }
3742 
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)3743 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3744                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3745                                            jint outOffset, jbyteArray nonceArray,
3746                                            jbyteArray inArray, jint inOffset, jint inLength,
3747                                            jbyteArray aadArray) {
3748     CHECK_ERROR_QUEUE_ON_RETURN;
3749     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3750                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3751 }
3752 
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)3753 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3754                                            jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3755                                            jint outOffset, jbyteArray nonceArray,
3756                                            jbyteArray inArray, jint inOffset, jint inLength,
3757                                            jbyteArray aadArray) {
3758     CHECK_ERROR_QUEUE_ON_RETURN;
3759     return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3760                            inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3761 }
3762 
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3763 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3764                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3765                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3766     CHECK_ERROR_QUEUE_ON_RETURN;
3767     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3768                            inBuffer, aadArray, EVP_AEAD_CTX_seal);
3769 }
3770 
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3771 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3772                                            jbyteArray keyArray, jint tagLen, jobject outBuffer,
3773                                            jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3774     CHECK_ERROR_QUEUE_ON_RETURN;
3775     return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3776                            inBuffer, aadArray, EVP_AEAD_CTX_open);
3777 }
3778 
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)3779 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
3780     CHECK_ERROR_QUEUE_ON_RETURN;
3781     JNI_TRACE("CMAC_CTX_new");
3782     auto cmacCtx = CMAC_CTX_new();
3783     if (cmacCtx == nullptr) {
3784         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
3785         return 0;
3786     }
3787 
3788     return reinterpret_cast<jlong>(cmacCtx);
3789 }
3790 
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)3791 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
3792     CHECK_ERROR_QUEUE_ON_RETURN;
3793     CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
3794     JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
3795     if (cmacCtx == nullptr) {
3796         conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
3797         return;
3798     }
3799     CMAC_CTX_free(cmacCtx);
3800 }
3801 
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)3802 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
3803     CHECK_ERROR_QUEUE_ON_RETURN;
3804     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3805     JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
3806     if (cmacCtx == nullptr) {
3807         return;
3808     }
3809     ScopedByteArrayRO keyBytes(env, keyArray);
3810     if (keyBytes.get() == nullptr) {
3811         return;
3812     }
3813 
3814     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3815 
3816     const EVP_CIPHER *cipher;
3817     switch(keyBytes.size()) {
3818       case 16:
3819           cipher = EVP_aes_128_cbc();
3820           break;
3821       case 24:
3822           cipher = EVP_aes_192_cbc();
3823           break;
3824       case 32:
3825           cipher = EVP_aes_256_cbc();
3826           break;
3827       default:
3828           conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3829                                            "CMAC_Init: Unsupported key length");
3830           return;
3831     }
3832 
3833     if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
3834         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
3835         JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
3836         return;
3837     }
3838 }
3839 
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)3840 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
3841                                            int inLength) {
3842     CHECK_ERROR_QUEUE_ON_RETURN;
3843     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3844     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3845     JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
3846 
3847     if (cmacCtx == nullptr) {
3848         return;
3849     }
3850 
3851     if (p == nullptr) {
3852         conscrypt::jniutil::throwNullPointerException(env, nullptr);
3853         return;
3854     }
3855 
3856     if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
3857         JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
3858         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
3859         return;
3860     }
3861 }
3862 
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3863 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
3864                                      jint inOffset, jint inLength) {
3865     CHECK_ERROR_QUEUE_ON_RETURN;
3866     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3867     JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
3868 
3869     if (cmacCtx == nullptr) {
3870         return;
3871     }
3872 
3873     ScopedByteArrayRO inBytes(env, inArray);
3874     if (inBytes.get() == nullptr) {
3875         return;
3876     }
3877 
3878     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3879         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3880                                            "inBytes");
3881         return;
3882     }
3883 
3884     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
3885 
3886     if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
3887         JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
3888                   inLength);
3889         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
3890         return;
3891     }
3892 }
3893 
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)3894 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
3895     CHECK_ERROR_QUEUE_ON_RETURN;
3896     CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3897     JNI_TRACE("CMAC_Final(%p)", cmacCtx);
3898 
3899     if (cmacCtx == nullptr) {
3900         return nullptr;
3901     }
3902 
3903     uint8_t result[EVP_MAX_MD_SIZE];
3904     size_t len;
3905     if (!CMAC_Final(cmacCtx, result, &len)) {
3906         JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
3907         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
3908         return nullptr;
3909     }
3910 
3911     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
3912     if (resultArray.get() == nullptr) {
3913         return nullptr;
3914     }
3915     ScopedByteArrayRW resultBytes(env, resultArray.get());
3916     if (resultBytes.get() == nullptr) {
3917         return nullptr;
3918     }
3919     memcpy(resultBytes.get(), result, len);
3920     return resultArray.release();
3921 }
3922 
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)3923 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
3924     CHECK_ERROR_QUEUE_ON_RETURN;
3925     JNI_TRACE("HMAC_CTX_new");
3926     auto hmacCtx = new HMAC_CTX;
3927     if (hmacCtx == nullptr) {
3928         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
3929         return 0;
3930     }
3931 
3932     HMAC_CTX_init(hmacCtx);
3933     return reinterpret_cast<jlong>(hmacCtx);
3934 }
3935 
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)3936 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
3937     CHECK_ERROR_QUEUE_ON_RETURN;
3938     HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
3939     JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
3940     if (hmacCtx == nullptr) {
3941         conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
3942         return;
3943     }
3944     HMAC_CTX_cleanup(hmacCtx);
3945     delete hmacCtx;
3946 }
3947 
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)3948 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
3949                                       jobject evpMdRef) {
3950     CHECK_ERROR_QUEUE_ON_RETURN;
3951     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3952     const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3953     JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
3954     if (hmacCtx == nullptr) {
3955         return;
3956     }
3957     ScopedByteArrayRO keyBytes(env, keyArray);
3958     if (keyBytes.get() == nullptr) {
3959         return;
3960     }
3961 
3962     const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3963     if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
3964         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
3965         JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
3966         return;
3967     }
3968 }
3969 
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)3970 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
3971                                            int inLength) {
3972     CHECK_ERROR_QUEUE_ON_RETURN;
3973     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3974     const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3975     JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
3976 
3977     if (hmacCtx == nullptr) {
3978         return;
3979     }
3980 
3981     if (p == nullptr) {
3982         conscrypt::jniutil::throwNullPointerException(env, nullptr);
3983         return;
3984     }
3985 
3986     if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
3987         JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
3988         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
3989         return;
3990     }
3991 }
3992 
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3993 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
3994                                      jint inOffset, jint inLength) {
3995     CHECK_ERROR_QUEUE_ON_RETURN;
3996     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3997     JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
3998 
3999     if (hmacCtx == nullptr) {
4000         return;
4001     }
4002 
4003     ScopedByteArrayRO inBytes(env, inArray);
4004     if (inBytes.get() == nullptr) {
4005         return;
4006     }
4007 
4008     if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4009         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4010                                            "inBytes");
4011         return;
4012     }
4013 
4014     const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4015     if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4016         JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4017                   inLength);
4018         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4019         return;
4020     }
4021 }
4022 
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4023 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4024     CHECK_ERROR_QUEUE_ON_RETURN;
4025     HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4026     JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4027 
4028     if (hmacCtx == nullptr) {
4029         return nullptr;
4030     }
4031 
4032     uint8_t result[EVP_MAX_MD_SIZE];
4033     unsigned len;
4034     if (!HMAC_Final(hmacCtx, result, &len)) {
4035         JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4036         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4037         return nullptr;
4038     }
4039 
4040     ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4041     if (resultArray.get() == nullptr) {
4042         return nullptr;
4043     }
4044     ScopedByteArrayRW resultBytes(env, resultArray.get());
4045     if (resultBytes.get() == nullptr) {
4046         return nullptr;
4047     }
4048     memcpy(resultBytes.get(), result, len);
4049     return resultArray.release();
4050 }
4051 
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4052 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4053     CHECK_ERROR_QUEUE_ON_RETURN;
4054     JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4055 
4056     ScopedByteArrayRW outputBytes(env, output);
4057     if (outputBytes.get() == nullptr) {
4058         return;
4059     }
4060 
4061     unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4062     if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4063         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4064         JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4065         return;
4066     }
4067 
4068     JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4069 }
4070 
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4071 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4072     /*
4073      * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4074      * Just make a buffer that's large enough here. The documentation recommends
4075      * 80 characters.
4076      */
4077     char output[128];
4078     int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4079     if (ret < 0) {
4080         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4081         return nullptr;
4082     } else if (size_t(ret) >= sizeof(output)) {
4083         conscrypt::jniutil::throwRuntimeException(env,
4084                                                   "ASN1_OBJECT_to_OID_string buffer too small");
4085         return nullptr;
4086     }
4087 
4088     JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4089     return env->NewStringUTF(output);
4090 }
4091 
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4092 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4093                                                  jboolean isFinite) {
4094     CHECK_ERROR_QUEUE_ON_RETURN;
4095     JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4096 
4097     if (streamObj == nullptr) {
4098         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4099         return 0;
4100     }
4101 
4102     bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4103     if (bio.get() == nullptr) {
4104         return 0;
4105     }
4106 
4107     bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4108 
4109     JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4110     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4111 }
4112 
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4113 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4114     CHECK_ERROR_QUEUE_ON_RETURN;
4115     JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4116 
4117     if (streamObj == nullptr) {
4118         conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4119         return 0;
4120     }
4121 
4122     bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4123     if (bio.get() == nullptr) {
4124         return 0;
4125     }
4126 
4127     bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4128 
4129     JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4130     return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4131 }
4132 
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4133 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4134     CHECK_ERROR_QUEUE_ON_RETURN;
4135     BIO* bio = to_BIO(env, bioRef);
4136     JNI_TRACE("BIO_free_all(%p)", bio);
4137 
4138     if (bio == nullptr) {
4139         return;
4140     }
4141 
4142     BIO_free_all(bio);
4143 }
4144 
4145 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4146 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4147     JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4148 
4149     bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4150     if (buffer.get() == nullptr) {
4151         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4152         JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4153         return nullptr;
4154     }
4155 
4156     /* Don't interpret the string. */
4157     flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4158 
4159     /* Write in given format and null terminate. */
4160     X509_NAME_print_ex(buffer.get(), name, 0, flags);
4161     BIO_write(buffer.get(), "\0", 1);
4162 
4163     char* tmp;
4164     BIO_get_mem_data(buffer.get(), &tmp);
4165     JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4166     return env->NewStringUTF(tmp);
4167 }
4168 
4169 /**
4170  * Converts GENERAL_NAME items to the output format expected in
4171  * X509Certificate#getSubjectAlternativeNames and
4172  * X509Certificate#getIssuerAlternativeNames return.
4173  */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4174 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4175     switch (gen->type) {
4176         case GEN_EMAIL:
4177         case GEN_DNS:
4178         case GEN_URI: {
4179             // This must not be a T61String and must not contain NULs.
4180             const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
4181             ssize_t len = ASN1_STRING_length(gen->d.ia5);
4182             if ((len == static_cast<ssize_t>(strlen(data))) &&
4183                 (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
4184                 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
4185                 return env->NewStringUTF(data);
4186             } else {
4187                 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4188                 return nullptr;
4189             }
4190         }
4191         case GEN_DIRNAME:
4192             /* Write in RFC 2253 format */
4193             return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4194         case GEN_IPADD: {
4195 #ifdef _WIN32
4196             void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4197 #else
4198             const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4199 #endif
4200             if (gen->d.ip->length == 4) {
4201                 // IPv4
4202                 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4203                 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4204                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4205                     return env->NewStringUTF(buffer.get());
4206                 } else {
4207                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4208                               strerror(errno));
4209                 }
4210             } else if (gen->d.ip->length == 16) {
4211                 // IPv6
4212                 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4213                 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4214                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4215                     return env->NewStringUTF(buffer.get());
4216                 } else {
4217                     JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4218                               strerror(errno));
4219                 }
4220             }
4221 
4222             /* Invalid IP encodings are pruned out without throwing an exception. */
4223             return nullptr;
4224         }
4225         case GEN_RID:
4226             return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4227         case GEN_OTHERNAME:
4228         case GEN_X400:
4229         default:
4230             return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4231     }
4232 
4233     return nullptr;
4234 }
4235 
4236 #define GN_STACK_SUBJECT_ALT_NAME 1
4237 #define GN_STACK_ISSUER_ALT_NAME 2
4238 
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4239 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4240                                                              CONSCRYPT_UNUSED jobject holder,
4241                                                              jint type) {
4242     CHECK_ERROR_QUEUE_ON_RETURN;
4243     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4244     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4245 
4246     if (x509 == nullptr) {
4247         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4248         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4249         return nullptr;
4250     }
4251 
4252     bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4253     if (type == GN_STACK_SUBJECT_ALT_NAME) {
4254         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4255                 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4256     } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4257         gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4258                 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4259     } else {
4260         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4261         return nullptr;
4262     }
4263     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4264     // |ERR_clear_error|, and throw CertificateParsingException.
4265     if (gn_stack == nullptr) {
4266         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4267         ERR_clear_error();
4268         return nullptr;
4269     }
4270 
4271     int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4272     if (count <= 0) {
4273         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4274         return nullptr;
4275     }
4276 
4277     /*
4278      * Keep track of how many originally so we can ignore any invalid
4279      * values later.
4280      */
4281     const int origCount = count;
4282 
4283     ScopedLocalRef<jobjectArray> joa(
4284             env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4285     for (int i = 0, j = 0; i < origCount; i++, j++) {
4286         GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4287         ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4288         if (env->ExceptionCheck()) {
4289             JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4290                       x509, type);
4291             return nullptr;
4292         }
4293 
4294         /*
4295          * If it's nullptr, we'll have to skip this, reduce the number of total
4296          * entries, and fix up the array later.
4297          */
4298         if (val.get() == nullptr) {
4299             j--;
4300             count--;
4301             continue;
4302         }
4303 
4304         ScopedLocalRef<jobjectArray> item(
4305                 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4306 
4307         ScopedLocalRef<jobject> parsedType(
4308                 env,
4309                 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4310                                             conscrypt::jniutil::integer_valueOfMethod, gen->type));
4311         env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4312         env->SetObjectArrayElement(item.get(), 1, val.get());
4313 
4314         env->SetObjectArrayElement(joa.get(), j, item.get());
4315     }
4316 
4317     if (count == 0) {
4318         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4319                   x509, type, origCount);
4320         joa.reset(nullptr);
4321     } else if (origCount != count) {
4322         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4323                   count);
4324 
4325         ScopedLocalRef<jobjectArray> joa_copy(
4326                 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4327 
4328         for (int i = 0; i < count; i++) {
4329             ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4330             env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4331         }
4332 
4333         joa.reset(joa_copy.release());
4334     }
4335 
4336     JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4337     return joa.release();
4338 }
4339 
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4340 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4341                                              CONSCRYPT_UNUSED jobject holder) {
4342     CHECK_ERROR_QUEUE_ON_RETURN;
4343     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4344     JNI_TRACE("X509_get_notBefore(%p)", x509);
4345 
4346     if (x509 == nullptr) {
4347         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4348         JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4349         return 0;
4350     }
4351 
4352     ASN1_TIME* notBefore = X509_get_notBefore(x509);
4353     JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4354     return reinterpret_cast<uintptr_t>(notBefore);
4355 }
4356 
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4357 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4358                                             CONSCRYPT_UNUSED jobject holder) {
4359     CHECK_ERROR_QUEUE_ON_RETURN;
4360     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4361     JNI_TRACE("X509_get_notAfter(%p)", x509);
4362 
4363     if (x509 == nullptr) {
4364         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4365         JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4366         return 0;
4367     }
4368 
4369     ASN1_TIME* notAfter = X509_get_notAfter(x509);
4370     JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4371     return reinterpret_cast<uintptr_t>(notAfter);
4372 }
4373 
4374 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4375 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4376                                           CONSCRYPT_UNUSED jobject holder) {
4377     CHECK_ERROR_QUEUE_ON_RETURN;
4378     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4379     JNI_TRACE("X509_get_version(%p)", x509);
4380 
4381     // NOLINTNEXTLINE(runtime/int)
4382     long version = X509_get_version(x509);
4383     JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4384     return version;
4385 }
4386 
4387 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4388 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4389                                             const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4390     JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4391 
4392     if (x509Type == nullptr) {
4393         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4394         JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4395         return nullptr;
4396     }
4397 
4398     const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4399     bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4400     if (serialBn.get() == nullptr) {
4401         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4402         return nullptr;
4403     }
4404 
4405     ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4406     if (env->ExceptionCheck()) {
4407         JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4408         return nullptr;
4409     }
4410 
4411     JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4412     return serialArray.release();
4413 }
4414 
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4415 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4416                                                      CONSCRYPT_UNUSED jobject holder) {
4417     CHECK_ERROR_QUEUE_ON_RETURN;
4418     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4419     JNI_TRACE("X509_get_serialNumber(%p)", x509);
4420     return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4421 }
4422 
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4423 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
4424                                                              jlong x509RevokedRef) {
4425     CHECK_ERROR_QUEUE_ON_RETURN;
4426     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4427     JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4428     return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
4429 }
4430 
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4431 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
4432                                      CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4433     CHECK_ERROR_QUEUE_ON_RETURN;
4434     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4435     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4436     JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4437 
4438     if (pkey == nullptr) {
4439         JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4440         return;
4441     }
4442 
4443     if (x509 == nullptr) {
4444         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4445         JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4446         return;
4447     }
4448 
4449     if (X509_verify(x509, pkey) != 1) {
4450         conscrypt::jniutil::throwExceptionFromBoringSSLError(
4451                 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
4452         JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4453         return;
4454     }
4455     JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4456 }
4457 
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4458 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
4459                                                  CONSCRYPT_UNUSED jobject holder) {
4460     CHECK_ERROR_QUEUE_ON_RETURN;
4461     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4462     JNI_TRACE("get_X509_tbs_cert(%p)", x509);
4463     // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
4464     return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
4465 }
4466 
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)4467 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
4468                                                              CONSCRYPT_UNUSED jobject holder,
4469                                                              jstring oidString) {
4470     CHECK_ERROR_QUEUE_ON_RETURN;
4471     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4472     JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
4473 
4474     if (x509 == nullptr) {
4475         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4476         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
4477         return nullptr;
4478     }
4479 
4480     bssl::UniquePtr<X509> copy(X509_dup(x509));
4481     if (copy == nullptr) {
4482         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
4483         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
4484         return nullptr;
4485     }
4486 
4487     ScopedUtfChars oid(env, oidString);
4488     if (oid.c_str() == nullptr) {
4489         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
4490         return nullptr;
4491     }
4492 
4493     bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
4494     if (obj.get() == nullptr) {
4495         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
4496                   oid.c_str());
4497         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4498                                            "Invalid OID.");
4499         ERR_clear_error();
4500         return nullptr;
4501     }
4502 
4503     int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
4504     if (extIndex == -1) {
4505         JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
4506         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4507                                            "Extension not found.");
4508         return nullptr;
4509     }
4510 
4511     // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
4512     // cached encoding.
4513     X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
4514     return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
4515 }
4516 
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4517 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
4518                                            CONSCRYPT_UNUSED jobject holder) {
4519     CHECK_ERROR_QUEUE_ON_RETURN;
4520     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4521     JNI_TRACE("get_X509_ex_flags(%p)", x509);
4522 
4523     if (x509 == nullptr) {
4524         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4525         JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4526         return 0;
4527     }
4528 
4529     uint32_t flags = X509_get_extension_flags(x509);
4530     // X509_get_extension_flags sometimes leaves values in the error queue. See
4531     // https://crbug.com/boringssl/382.
4532     //
4533     // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
4534     // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
4535     // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
4536     // this JNI call to EXFLAG_CRITICAL.
4537     ERR_clear_error();
4538     return flags;
4539 }
4540 
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)4541 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
4542                                            CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
4543                                            CONSCRYPT_UNUSED jobject holder2) {
4544     CHECK_ERROR_QUEUE_ON_RETURN;
4545     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4546     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4547     JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4548 
4549     int ret = X509_check_issued(x509_1, x509_2);
4550     JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4551     return ret;
4552 }
4553 
get_X509_signature(X509 * x509)4554 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
4555     const ASN1_BIT_STRING* signature;
4556     X509_get0_signature(&signature, nullptr, x509);
4557     return signature;
4558 }
4559 
get_X509_CRL_signature(X509_CRL * crl)4560 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
4561     const ASN1_BIT_STRING* signature;
4562     X509_CRL_get0_signature(crl, &signature, nullptr);
4563     return signature;
4564 }
4565 
4566 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))4567 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
4568                                          const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
4569     JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4570 
4571     if (x509Type == nullptr) {
4572         conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4573         JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4574         return nullptr;
4575     }
4576 
4577     const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
4578 
4579     ScopedLocalRef<jbyteArray> signatureArray(env,
4580                                               env->NewByteArray(ASN1_STRING_length(signature)));
4581     if (env->ExceptionCheck()) {
4582         JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4583         return nullptr;
4584     }
4585 
4586     ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4587     if (signatureBytes.get() == nullptr) {
4588         JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4589         return nullptr;
4590     }
4591 
4592     memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
4593 
4594     JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4595               ASN1_STRING_length(signature));
4596     return signatureArray.release();
4597 }
4598 
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4599 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
4600                                                   CONSCRYPT_UNUSED jobject holder) {
4601     CHECK_ERROR_QUEUE_ON_RETURN;
4602     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4603     JNI_TRACE("get_X509_signature(%p)", x509);
4604     return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4605 }
4606 
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4607 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
4608                                                       CONSCRYPT_UNUSED jobject holder) {
4609     CHECK_ERROR_QUEUE_ON_RETURN;
4610     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4611     JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4612     return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4613 }
4614 
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)4615 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
4616                                                 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
4617                                                 CONSCRYPT_UNUSED jobject holder2) {
4618     CHECK_ERROR_QUEUE_ON_RETURN;
4619     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4620     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4621     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4622 
4623     if (x509crl == nullptr) {
4624         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4625         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4626         return 0;
4627     } else if (x509 == nullptr) {
4628         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4629         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4630         return 0;
4631     }
4632 
4633     X509_REVOKED* revoked = nullptr;
4634     int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4635     if (ret == 0) {
4636         JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4637         return 0;
4638     }
4639 
4640     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4641     return reinterpret_cast<uintptr_t>(revoked);
4642 }
4643 
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)4644 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
4645                                                   CONSCRYPT_UNUSED jobject holder,
4646                                                   jbyteArray serialArray) {
4647     CHECK_ERROR_QUEUE_ON_RETURN;
4648     X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4649     JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4650 
4651     if (x509crl == nullptr) {
4652         conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4653         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4654         return 0;
4655     }
4656 
4657     bssl::UniquePtr<BIGNUM> serialBn(BN_new());
4658     if (serialBn.get() == nullptr) {
4659         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4660         return 0;
4661     }
4662 
4663     BIGNUM* serialBare = serialBn.get();
4664     if (!arrayToBignum(env, serialArray, &serialBare)) {
4665         if (!env->ExceptionCheck()) {
4666             conscrypt::jniutil::throwNullPointerException(env, "serial == null");
4667         }
4668         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4669         return 0;
4670     }
4671 
4672     bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
4673     if (serialInteger.get() == nullptr) {
4674         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4675         return 0;
4676     }
4677 
4678     X509_REVOKED* revoked = nullptr;
4679     int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4680     if (ret == 0) {
4681         JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4682         return 0;
4683     }
4684 
4685     JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4686     return reinterpret_cast<uintptr_t>(revoked);
4687 }
4688 
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4689 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
4690                                                     CONSCRYPT_UNUSED jobject holder) {
4691     CHECK_ERROR_QUEUE_ON_RETURN;
4692     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4693     JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4694 
4695     if (crl == nullptr) {
4696         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4697         return nullptr;
4698     }
4699 
4700     STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4701     if (stack == nullptr) {
4702         JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4703         return nullptr;
4704     }
4705 
4706     size_t size = sk_X509_REVOKED_num(stack);
4707 
4708     ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
4709     ScopedLongArrayRW revoked(env, revokedArray.get());
4710     for (size_t i = 0; i < size; i++) {
4711         X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4712         revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4713     }
4714 
4715     JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
4716     return revokedArray.release();
4717 }
4718 
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4719 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
4720                                             CONSCRYPT_UNUSED jobject holder) {
4721     CHECK_ERROR_QUEUE_ON_RETURN;
4722     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4723     JNI_TRACE("i2d_X509_CRL(%p)", crl);
4724     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
4725 }
4726 
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4727 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
4728                                        CONSCRYPT_UNUSED jobject holder) {
4729     CHECK_ERROR_QUEUE_ON_RETURN;
4730     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4731     JNI_TRACE("X509_CRL_free(%p)", crl);
4732 
4733     if (crl == nullptr) {
4734         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4735         JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4736         return;
4737     }
4738 
4739     X509_CRL_free(crl);
4740 }
4741 
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4742 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
4743                                         CONSCRYPT_UNUSED jobject holder) {
4744     CHECK_ERROR_QUEUE_ON_RETURN;
4745     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4746     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4747     JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4748 
4749     if (bio == nullptr) {
4750         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4751         JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4752         return;
4753     }
4754 
4755     if (crl == nullptr) {
4756         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4757         JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4758         return;
4759     }
4760 
4761     if (!X509_CRL_print(bio, crl)) {
4762         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
4763         JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4764         return;
4765     }
4766     JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4767 }
4768 
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4769 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
4770                                                      CONSCRYPT_UNUSED jobject holder) {
4771     CHECK_ERROR_QUEUE_ON_RETURN;
4772     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4773     JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4774 
4775     if (crl == nullptr) {
4776         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4777         JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
4778         return nullptr;
4779     }
4780 
4781     const X509_ALGOR *sig_alg;
4782     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4783     const ASN1_OBJECT *oid;
4784     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
4785     return ASN1_OBJECT_to_OID_string(env, oid);
4786 }
4787 
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)4788 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR *algor) {
4789     int param_type;
4790     const void* param_value;
4791     X509_ALGOR_get0(nullptr, &param_type, &param_value, algor);
4792 
4793     if (param_type == V_ASN1_UNDEF) {
4794         JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
4795         return nullptr;
4796     }
4797 
4798     // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
4799     // recreate it from the returned components.
4800     bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
4801     if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
4802         conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
4803         return nullptr;
4804     }
4805 
4806     return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
4807 }
4808 
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4809 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
4810                                                               CONSCRYPT_UNUSED jobject holder) {
4811     CHECK_ERROR_QUEUE_ON_RETURN;
4812     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4813     JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4814 
4815     if (crl == nullptr) {
4816         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4817         JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4818         return nullptr;
4819     }
4820 
4821     const X509_ALGOR *sig_alg;
4822     X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4823     return get_X509_ALGOR_parameter(env, sig_alg);
4824 }
4825 
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4826 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
4827                                                         CONSCRYPT_UNUSED jobject holder) {
4828     CHECK_ERROR_QUEUE_ON_RETURN;
4829     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4830     JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4831     return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
4832 }
4833 
4834 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4835 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
4836                                               CONSCRYPT_UNUSED jobject holder) {
4837     CHECK_ERROR_QUEUE_ON_RETURN;
4838     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4839     JNI_TRACE("X509_CRL_get_version(%p)", crl);
4840 
4841     // NOLINTNEXTLINE(runtime/int)
4842     long version = X509_CRL_get_version(crl);
4843     JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4844     return version;
4845 }
4846 
4847 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4848           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)4849 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
4850     JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4851 
4852     if (x509Type == nullptr) {
4853         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4854         return nullptr;
4855     }
4856 
4857     ScopedUtfChars oid(env, oidString);
4858     if (oid.c_str() == nullptr) {
4859         return nullptr;
4860     }
4861 
4862     bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
4863     if (asn1.get() == nullptr) {
4864         JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4865         ERR_clear_error();
4866         return nullptr;
4867     }
4868 
4869     int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4870     if (extIndex == -1) {
4871         JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4872         return nullptr;
4873     }
4874 
4875     X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4876     JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4877     return ext;
4878 }
4879 
4880 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4881           X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)4882 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
4883     X509_EXTENSION* ext =
4884             X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
4885     if (ext == nullptr) {
4886         JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4887         return nullptr;
4888     }
4889 
4890     JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
4891               X509_EXTENSION_get_data(ext));
4892     return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
4893                                               i2d_ASN1_OCTET_STRING);
4894 }
4895 
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)4896 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
4897                                            CONSCRYPT_UNUSED jobject holder, jstring oid) {
4898     CHECK_ERROR_QUEUE_ON_RETURN;
4899     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4900     JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4901     X509_EXTENSION* ext =
4902             X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
4903     JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4904     return reinterpret_cast<uintptr_t>(ext);
4905 }
4906 
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)4907 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4908                                                jstring oid) {
4909     CHECK_ERROR_QUEUE_ON_RETURN;
4910     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4911     JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4912     X509_EXTENSION* ext =
4913             X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
4914                     env, revoked, oid);
4915     JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4916     return reinterpret_cast<uintptr_t>(ext);
4917 }
4918 
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)4919 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4920     CHECK_ERROR_QUEUE_ON_RETURN;
4921     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4922     JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4923 
4924     if (revoked == nullptr) {
4925         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4926         JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4927         return 0;
4928     }
4929 
4930     X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4931     JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4932     return reinterpret_cast<uintptr_t>(dup);
4933 }
4934 
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)4935 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
4936                                                           jlong x509RevokedRef) {
4937     CHECK_ERROR_QUEUE_ON_RETURN;
4938     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4939     JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
4940 
4941     if (revoked == nullptr) {
4942         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4943         JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
4944         return 0;
4945     }
4946 
4947     JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
4948               X509_REVOKED_get0_revocationDate(revoked));
4949     return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
4950 }
4951 
4952 #ifdef __GNUC__
4953 #pragma GCC diagnostic push
4954 #pragma GCC diagnostic ignored "-Wwrite-strings"
4955 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)4956 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
4957                                             jlong x509RevokedRef) {
4958     CHECK_ERROR_QUEUE_ON_RETURN;
4959     BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4960     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4961     JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
4962 
4963     if (bio == nullptr) {
4964         conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4965         JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
4966         return;
4967     }
4968 
4969     if (revoked == nullptr) {
4970         conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4971         JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
4972         return;
4973     }
4974 
4975     BIO_printf(bio, "Serial Number: ");
4976     i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
4977     BIO_printf(bio, "\nRevocation Date: ");
4978     ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
4979     BIO_printf(bio, "\n");
4980     // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
4981     // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
4982     X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
4983                             0);
4984 }
4985 #ifndef _WIN32
4986 #pragma GCC diagnostic pop
4987 #endif
4988 
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4989 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
4990                                                     CONSCRYPT_UNUSED jobject holder) {
4991     CHECK_ERROR_QUEUE_ON_RETURN;
4992     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4993     JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
4994     return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
4995 }
4996 
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4997 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
4998                                          CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4999     CHECK_ERROR_QUEUE_ON_RETURN;
5000     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5001     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5002     JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5003 
5004     if (pkey == nullptr) {
5005         JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5006         return;
5007     }
5008 
5009     if (crl == nullptr) {
5010         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5011         JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5012         return;
5013     }
5014 
5015     if (X509_CRL_verify(crl, pkey) != 1) {
5016         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5017         JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5018         return;
5019     }
5020     JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5021 }
5022 
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5023 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5024                                                   CONSCRYPT_UNUSED jobject holder) {
5025     CHECK_ERROR_QUEUE_ON_RETURN;
5026     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5027     JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5028 
5029     if (crl == nullptr) {
5030         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5031         JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5032         return 0;
5033     }
5034 
5035     ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5036     JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5037     return reinterpret_cast<uintptr_t>(lastUpdate);
5038 }
5039 
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5040 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5041                                                   CONSCRYPT_UNUSED jobject holder) {
5042     CHECK_ERROR_QUEUE_ON_RETURN;
5043     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5044     JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5045 
5046     if (crl == nullptr) {
5047         conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5048         JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5049         return 0;
5050     }
5051 
5052     ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5053     JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5054     return reinterpret_cast<uintptr_t>(nextUpdate);
5055 }
5056 
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5057 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5058     CHECK_ERROR_QUEUE_ON_RETURN;
5059     X509_REVOKED* x509Revoked =
5060             reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5061     JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5062     return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5063 }
5064 
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5065 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5066     CHECK_ERROR_QUEUE_ON_RETURN;
5067     X509_EXTENSION* ext =
5068             reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5069 
5070     if (ext == nullptr) {
5071         conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5072         return 0;
5073     }
5074 
5075     return X509_supported_extension(ext);
5076 }
5077 
decimal_to_integer(const char * data,size_t len,int * out)5078 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5079     int ret = 0;
5080     for (size_t i = 0; i < len; i++) {
5081         ret *= 10;
5082         if (data[i] < '0' || data[i] > '9') {
5083             return false;
5084         }
5085         ret += data[i] - '0';
5086     }
5087     *out = ret;
5088     return true;
5089 }
5090 
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5091 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5092                                                jobject calendar) {
5093     CHECK_ERROR_QUEUE_ON_RETURN;
5094     ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5095     JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5096 
5097     if (asn1Time == nullptr) {
5098         conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5099         return;
5100     }
5101 
5102     if (!ASN1_TIME_check(asn1Time)) {
5103         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5104         return;
5105     }
5106 
5107     bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5108     if (gen.get() == nullptr) {
5109         conscrypt::jniutil::throwParsingException(env,
5110                                                   "ASN1_TIME_to_generalizedtime returned null");
5111         return;
5112     }
5113 
5114     if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5115         conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5116         return;
5117     }
5118 
5119     int year, mon, mday, hour, min, sec;
5120     const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5121     if (!decimal_to_integer(data, 4, &year) ||
5122         !decimal_to_integer(data + 4, 2, &mon) ||
5123         !decimal_to_integer(data + 6, 2, &mday) ||
5124         !decimal_to_integer(data + 8, 2, &hour) ||
5125         !decimal_to_integer(data + 10, 2, &min) ||
5126         !decimal_to_integer(data + 12, 2, &sec)) {
5127         conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5128         return;
5129     }
5130 
5131     env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5132                         min, sec);
5133 }
5134 
5135 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5136 // functions so that they can be freed properly when finished.  This struct owns
5137 // all objects pointed to by its members.
5138 struct CbsHandle {
5139     // A pointer to the CBS.
5140     std::unique_ptr<CBS> cbs;
5141     // A pointer to the data held by the CBS.  If the data held by the CBS
5142     // is owned by a different CbsHandle, data will be null.
5143     std::unique_ptr<unsigned char[]> data;
5144 };
5145 
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5146 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5147     CHECK_ERROR_QUEUE_ON_RETURN;
5148     JNI_TRACE("asn1_read_init(%p)", data);
5149 
5150     ScopedByteArrayRO bytes(env, data);
5151     if (bytes.get() == nullptr) {
5152         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5153         return 0;
5154     }
5155 
5156     std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5157     cbs->data.reset(new unsigned char[bytes.size()]);
5158     memcpy(cbs->data.get(), bytes.get(), bytes.size());
5159 
5160     cbs->cbs.reset(new CBS());
5161     CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5162     JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5163     return reinterpret_cast<uintptr_t>(cbs.release());
5164 }
5165 
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5166 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5167     CHECK_ERROR_QUEUE_ON_RETURN;
5168     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5169     JNI_TRACE("asn1_read_sequence(%p)", cbs);
5170 
5171     std::unique_ptr<CbsHandle> seq(new CbsHandle());
5172     seq->cbs.reset(new CBS());
5173     if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5174         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5175         return 0;
5176     }
5177     JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5178     return reinterpret_cast<uintptr_t>(seq.release());
5179 }
5180 
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5181 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5182                                                    jlong cbsRef, jint tag) {
5183     CHECK_ERROR_QUEUE_ON_RETURN;
5184     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5185     JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5186 
5187     int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5188                                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5189     JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5190     return result ? JNI_TRUE : JNI_FALSE;
5191 }
5192 
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5193 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5194     CHECK_ERROR_QUEUE_ON_RETURN;
5195     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5196     JNI_TRACE("asn1_read_tagged(%p)", cbs);
5197 
5198     std::unique_ptr<CbsHandle> tag(new CbsHandle());
5199     tag->cbs.reset(new CBS());
5200     if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5201         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5202         return 0;
5203     }
5204     JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5205     return reinterpret_cast<uintptr_t>(tag.release());
5206 }
5207 
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5208 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5209     CHECK_ERROR_QUEUE_ON_RETURN;
5210     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5211     JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5212 
5213     std::unique_ptr<CBS> str(new CBS());
5214     if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5215         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5216         return 0;
5217     }
5218     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5219     if (out.get() == nullptr) {
5220         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5221         return 0;
5222     }
5223     ScopedByteArrayRW outBytes(env, out.get());
5224     if (outBytes.get() == nullptr) {
5225         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5226         return 0;
5227     }
5228     memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5229     JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5230     return out.release();
5231 }
5232 
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5233 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5234     CHECK_ERROR_QUEUE_ON_RETURN;
5235     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5236     JNI_TRACE("asn1_read_uint64(%p)", cbs);
5237 
5238     // NOLINTNEXTLINE(runtime/int)
5239     uint64_t value;
5240     if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5241         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5242         return 0;
5243     }
5244     return value;
5245 }
5246 
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5247 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5248     CHECK_ERROR_QUEUE_ON_RETURN;
5249     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5250     JNI_TRACE("asn1_read_null(%p)", cbs);
5251 
5252     CBS null_holder;
5253     if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5254         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5255     }
5256 }
5257 
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5258 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5259     CHECK_ERROR_QUEUE_ON_RETURN;
5260     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5261     JNI_TRACE("asn1_read_oid(%p)", cbs);
5262 
5263     CBS oid_cbs;
5264     if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5265         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5266         return nullptr;
5267     }
5268     int nid = OBJ_cbs2nid(&oid_cbs);
5269     if (nid == NID_undef) {
5270         conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5271         return nullptr;
5272     }
5273     const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5274     if (obj == nullptr) {
5275         conscrypt::jniutil::throwIOException(env,
5276                                              "Error reading ASN.1 encoding: "
5277                                              "Could not find ASN1_OBJECT for NID");
5278         return nullptr;
5279     }
5280     return ASN1_OBJECT_to_OID_string(env, obj);
5281 }
5282 
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5283 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5284                                                 jlong cbsRef) {
5285     CHECK_ERROR_QUEUE_ON_RETURN;
5286     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5287     JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5288 
5289     bool empty = (CBS_len(cbs->cbs.get()) == 0);
5290     JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5291     return empty;
5292 }
5293 
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5294 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5295     CHECK_ERROR_QUEUE_ON_RETURN;
5296     if (cbsRef == 0) {
5297         JNI_TRACE("asn1_read_free(0)");
5298         return;
5299     }
5300     CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5301     JNI_TRACE("asn1_read_free(%p)", cbs);
5302     delete cbs;
5303 }
5304 
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5305 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5306     CHECK_ERROR_QUEUE_ON_RETURN;
5307     JNI_TRACE("asn1_write_init");
5308     std::unique_ptr<CBB> cbb(new CBB());
5309     if (!CBB_init(cbb.get(), 128)) {
5310         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5311         return 0;
5312     }
5313     JNI_TRACE("asn1_write_init => %p", cbb.get());
5314     return reinterpret_cast<uintptr_t>(cbb.release());
5315 }
5316 
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5317 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5318     CHECK_ERROR_QUEUE_ON_RETURN;
5319     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5320     JNI_TRACE("asn1_write_sequence(%p)", cbb);
5321 
5322     std::unique_ptr<CBB> seq(new CBB());
5323     if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5324         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5325         return 0;
5326     }
5327     JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5328     return reinterpret_cast<uintptr_t>(seq.release());
5329 }
5330 
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5331 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5332     CHECK_ERROR_QUEUE_ON_RETURN;
5333     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5334     JNI_TRACE("asn1_write_tag(%p)", cbb);
5335 
5336     std::unique_ptr<CBB> tag_holder(new CBB());
5337     if (!CBB_add_asn1(cbb, tag_holder.get(),
5338                       CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5339         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5340         return 0;
5341     }
5342     JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5343     return reinterpret_cast<uintptr_t>(tag_holder.release());
5344 }
5345 
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5346 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5347                                                 jbyteArray data) {
5348     CHECK_ERROR_QUEUE_ON_RETURN;
5349     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5350     JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5351 
5352     ScopedByteArrayRO bytes(env, data);
5353     if (bytes.get() == nullptr) {
5354         JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5355         return;
5356     }
5357 
5358     std::unique_ptr<CBB> octetstring(new CBB());
5359     if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5360         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5361         return;
5362     }
5363     if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5364                        bytes.size())) {
5365         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5366         return;
5367     }
5368     if (!CBB_flush(cbb)) {
5369         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5370         return;
5371     }
5372 }
5373 
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)5374 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
5375     CHECK_ERROR_QUEUE_ON_RETURN;
5376     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5377     JNI_TRACE("asn1_write_uint64(%p)", cbb);
5378 
5379     if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
5380         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5381         return;
5382     }
5383 }
5384 
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)5385 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
5386     CHECK_ERROR_QUEUE_ON_RETURN;
5387     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5388     JNI_TRACE("asn1_write_null(%p)", cbb);
5389 
5390     CBB null_holder;
5391     if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
5392         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5393         return;
5394     }
5395     if (!CBB_flush(cbb)) {
5396         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5397         return;
5398     }
5399 }
5400 
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)5401 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
5402     CHECK_ERROR_QUEUE_ON_RETURN;
5403     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5404     JNI_TRACE("asn1_write_oid(%p)", cbb);
5405 
5406     ScopedUtfChars oid_chars(env, oid);
5407     if (oid_chars.c_str() == nullptr) {
5408         return;
5409     }
5410 
5411     int nid = OBJ_txt2nid(oid_chars.c_str());
5412     if (nid == NID_undef) {
5413         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5414         return;
5415     }
5416 
5417     if (!OBJ_nid2cbb(cbb, nid)) {
5418         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5419         return;
5420     }
5421 }
5422 
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)5423 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
5424     CHECK_ERROR_QUEUE_ON_RETURN;
5425     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5426     JNI_TRACE("asn1_write_flush(%p)", cbb);
5427 
5428     if (!CBB_flush(cbb)) {
5429         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5430         return;
5431     }
5432 }
5433 
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)5434 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
5435     CHECK_ERROR_QUEUE_ON_RETURN;
5436     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5437     JNI_TRACE("asn1_write_finish(%p)", cbb);
5438 
5439     uint8_t* data;
5440     size_t data_len;
5441     if (!CBB_finish(cbb, &data, &data_len)) {
5442         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5443         return 0;
5444     }
5445     bssl::UniquePtr<uint8_t> data_storage(data);
5446     ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
5447     if (out.get() == nullptr) {
5448         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5449         return 0;
5450     }
5451     ScopedByteArrayRW outBytes(env, out.get());
5452     if (outBytes.get() == nullptr) {
5453         conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5454         return 0;
5455     }
5456     memcpy(outBytes.get(), data, data_len);
5457     return out.release();
5458 }
5459 
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5460 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5461     CHECK_ERROR_QUEUE_ON_RETURN;
5462     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5463     JNI_TRACE("asn1_write_cleanup(%p)", cbb);
5464 
5465     CBB_cleanup(cbb);
5466 }
5467 
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5468 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5469     CHECK_ERROR_QUEUE_ON_RETURN;
5470     if (cbbRef == 0) {
5471         JNI_TRACE("asn1_write_free(0)");
5472         return;
5473     }
5474     CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5475     JNI_TRACE("asn1_write_free(%p)", cbb);
5476     delete cbb;
5477 }
5478 
5479 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5480 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5481     BIO* bio = to_BIO(env, bioRef);
5482     JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5483 
5484     if (bio == nullptr) {
5485         return 0;
5486     }
5487 
5488     T* x = d2i_func(bio, nullptr);
5489     if (x == nullptr) {
5490         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
5491         return 0;
5492     }
5493 
5494     return reinterpret_cast<uintptr_t>(x);
5495 }
5496 
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5497 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5498     CHECK_ERROR_QUEUE_ON_RETURN;
5499     return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5500 }
5501 
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5502 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5503     CHECK_ERROR_QUEUE_ON_RETURN;
5504     return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5505 }
5506 
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5507 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5508     CHECK_ERROR_QUEUE_ON_RETURN;
5509     ScopedByteArrayRO bytes(env, certBytes);
5510     if (bytes.get() == nullptr) {
5511         JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
5512         return 0;
5513     }
5514 
5515     const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
5516     // NOLINTNEXTLINE(runtime/int)
5517     X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
5518     if (x == nullptr) {
5519         conscrypt::jniutil::throwExceptionFromBoringSSLError(
5520                 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
5521         return 0;
5522     }
5523     return reinterpret_cast<uintptr_t>(x);
5524 }
5525 
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5526 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
5527                                         CONSCRYPT_UNUSED jobject holder) {
5528     CHECK_ERROR_QUEUE_ON_RETURN;
5529     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5530     JNI_TRACE("i2d_X509(%p)", x509);
5531     return ASN1ToByteArray<X509>(env, x509, i2d_X509);
5532 }
5533 
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5534 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
5535                                                CONSCRYPT_UNUSED jobject holder) {
5536     CHECK_ERROR_QUEUE_ON_RETURN;
5537     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5538     JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5539     return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
5540 }
5541 
5542 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)5543 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
5544     BIO* bio = to_BIO(env, bioRef);
5545     JNI_TRACE("PEM_to_jlong(%p)", bio);
5546 
5547     if (bio == nullptr) {
5548         JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
5549         return 0;
5550     }
5551 
5552     T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
5553     if (x == nullptr) {
5554         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
5555         JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
5556         return 0;
5557     }
5558 
5559     JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
5560     return reinterpret_cast<uintptr_t>(x);
5561 }
5562 
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5563 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5564     CHECK_ERROR_QUEUE_ON_RETURN;
5565     // NOLINTNEXTLINE(runtime/int)
5566     JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
5567     return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5568 }
5569 
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5570 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5571     CHECK_ERROR_QUEUE_ON_RETURN;
5572     // NOLINTNEXTLINE(runtime/int)
5573     JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
5574     return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5575 }
5576 
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)5577 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
5578     CHECK_ERROR_QUEUE_ON_RETURN;
5579     // NOLINTNEXTLINE(runtime/int)
5580     JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
5581     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
5582 }
5583 
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)5584 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
5585     CHECK_ERROR_QUEUE_ON_RETURN;
5586     // NOLINTNEXTLINE(runtime/int)
5587     JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
5588     return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
5589 }
5590 
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)5591 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509) *certs) {
5592     if (certs == nullptr) {
5593         return nullptr;
5594     }
5595 
5596     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5597     size_t size = sk_X509_num(certs);
5598     ref_array.reset(env->NewLongArray(size));
5599     ScopedLongArrayRW items(env, ref_array.get());
5600     for (size_t i = 0; i < size; i++) {
5601         X509* cert = sk_X509_value(certs, i);
5602         X509_up_ref(cert);
5603         items[i] = reinterpret_cast<uintptr_t>(cert);
5604     }
5605 
5606     JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
5607     return ref_array.release();
5608 }
5609 
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)5610 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL) *crls) {
5611     if (crls == nullptr) {
5612         return nullptr;
5613     }
5614 
5615     ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5616     size_t size = sk_X509_CRL_num(crls);
5617     ref_array.reset(env->NewLongArray(size));
5618     ScopedLongArrayRW items(env, ref_array.get());
5619     for (size_t i = 0; i < size; i++) {
5620         X509_CRL* crl = sk_X509_CRL_value(crls, i);
5621         X509_CRL_up_ref(crl);
5622         items[i] = reinterpret_cast<uintptr_t>(crl);
5623     }
5624 
5625     JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
5626     return ref_array.release();
5627 }
5628 
5629 #define PKCS7_CERTS 1
5630 #define PKCS7_CRLS 2
5631 
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5632 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5633     CHECK_ERROR_QUEUE_ON_RETURN;
5634     STACK_OF(X509)* stack = sk_X509_new_null();
5635 
5636     ScopedLongArrayRO certs(env, certsArray);
5637     for (size_t i = 0; i < certs.size(); i++) {
5638         X509* item = reinterpret_cast<X509*>(certs[i]);
5639         if (sk_X509_push(stack, item) == 0) {
5640             sk_X509_free(stack);
5641             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
5642             return nullptr;
5643         }
5644     }
5645 
5646     bssl::ScopedCBB out;
5647     CBB_init(out.get(), 1024 * certs.size());
5648     if (!PKCS7_bundle_certificates(out.get(), stack)) {
5649         sk_X509_free(stack);
5650         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
5651         return nullptr;
5652     }
5653 
5654     sk_X509_free(stack);
5655 
5656     return CBBToByteArray(env, out.get());
5657 }
5658 
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5659 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5660     CHECK_ERROR_QUEUE_ON_RETURN;
5661     BIO* bio = to_BIO(env, bioRef);
5662     JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5663 
5664     if (bio == nullptr) {
5665         JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5666         return nullptr;
5667     }
5668 
5669     if (which == PKCS7_CERTS) {
5670         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5671         if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
5672             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
5673             return nullptr;
5674         }
5675         return X509s_to_ItemArray(env, outCerts.get());
5676     } else if (which == PKCS7_CRLS) {
5677         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5678         if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
5679             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
5680             return nullptr;
5681         }
5682         return X509_CRLs_to_ItemArray(env, outCRLs.get());
5683     } else {
5684         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5685         return nullptr;
5686     }
5687 }
5688 
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5689 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5690     CHECK_ERROR_QUEUE_ON_RETURN;
5691     BIO* bio = to_BIO(env, bioRef);
5692     JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5693 
5694     if (bio == nullptr) {
5695         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5696         return nullptr;
5697     }
5698 
5699     uint8_t* data;
5700     size_t len;
5701     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5702         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
5703                 conscrypt::jniutil::throwParsingException);
5704         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
5705         return nullptr;
5706     }
5707     bssl::UniquePtr<uint8_t> data_storage(data);
5708 
5709     CBS cbs;
5710     CBS_init(&cbs, data, len);
5711 
5712     if (which == PKCS7_CERTS) {
5713         bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5714         if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
5715             conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
5716                     "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
5717             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
5718             return nullptr;
5719         }
5720         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
5721         return X509s_to_ItemArray(env, outCerts.get());
5722     } else if (which == PKCS7_CRLS) {
5723         bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5724         if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
5725             conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
5726                     conscrypt::jniutil::throwParsingException);
5727             JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
5728             return nullptr;
5729         }
5730         JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
5731         return X509_CRLs_to_ItemArray(env, outCRLs.get());
5732     } else {
5733         conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5734         return nullptr;
5735     }
5736 }
5737 
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)5738 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5739     CHECK_ERROR_QUEUE_ON_RETURN;
5740     BIO* bio = to_BIO(env, bioRef);
5741     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5742 
5743     if (bio == nullptr) {
5744         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
5745         return nullptr;
5746     }
5747 
5748     uint8_t* data;
5749     size_t len;
5750     if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5751         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
5752                 conscrypt::jniutil::throwParsingException);
5753         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
5754         return nullptr;
5755     }
5756     bssl::UniquePtr<uint8_t> data_storage(data);
5757 
5758     bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
5759     if (path.get() == nullptr) {
5760         JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
5761         return nullptr;
5762     }
5763 
5764     CBS cbs, sequence;
5765     CBS_init(&cbs, data, len);
5766     if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
5767         conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5768         ERR_clear_error();
5769         return nullptr;
5770     }
5771 
5772     while (CBS_len(&sequence) > 0) {
5773         CBS child;
5774         if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
5775             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5776             ERR_clear_error();
5777             return nullptr;
5778         }
5779 
5780         const uint8_t* tmp = CBS_data(&child);
5781         // NOLINTNEXTLINE(runtime/int)
5782         bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
5783         if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
5784             conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5785             ERR_clear_error();
5786             return nullptr;
5787         }
5788 
5789         if (!sk_X509_push(path.get(), cert.get())) {
5790             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
5791             return nullptr;
5792         }
5793         OWNERSHIP_TRANSFERRED(cert);
5794     }
5795 
5796     size_t size = sk_X509_num(path.get());
5797 
5798     ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
5799     ScopedLongArrayRW certs(env, certArray.get());
5800     for (size_t i = 0; i < size; i++) {
5801         X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5802         certs[i] = reinterpret_cast<uintptr_t>(item);
5803     }
5804 
5805     JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
5806     return certArray.release();
5807 }
5808 
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5809 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5810     CHECK_ERROR_QUEUE_ON_RETURN;
5811     JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5812     ScopedLongArrayRO certsArray(env, certs);
5813     if (certsArray.get() == nullptr) {
5814         JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5815         return nullptr;
5816     }
5817 
5818     bssl::ScopedCBB result;
5819     CBB seq_contents;
5820     if (!CBB_init(result.get(), 2048 * certsArray.size())) {
5821         JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
5822         return nullptr;
5823     }
5824     if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
5825         return nullptr;
5826     }
5827 
5828     for (size_t i = 0; i < certsArray.size(); i++) {
5829         X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5830         uint8_t* buf;
5831         int len = i2d_X509(x509, nullptr);
5832 
5833         if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
5834             i2d_X509(x509, &buf) < 0) {
5835             return nullptr;
5836         }
5837     }
5838 
5839     return CBBToByteArray(env, result.get());
5840 }
5841 
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5842 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
5843                                    CONSCRYPT_UNUSED jobject holder) {
5844     CHECK_ERROR_QUEUE_ON_RETURN;
5845     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5846     JNI_TRACE("X509_free(%p)", x509);
5847 
5848     if (x509 == nullptr) {
5849         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5850         JNI_TRACE("X509_free(%p) => x509 == null", x509);
5851         return;
5852     }
5853 
5854     X509_free(x509);
5855 }
5856 
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5857 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
5858                                   CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5859                                   CONSCRYPT_UNUSED jobject holder2) {
5860     CHECK_ERROR_QUEUE_ON_RETURN;
5861     X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5862     X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5863     JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5864 
5865     if (x509_1 == nullptr) {
5866         conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
5867         JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5868         return -1;
5869     }
5870 
5871     if (x509_2 == nullptr) {
5872         conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
5873         JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5874         return -1;
5875     }
5876 
5877     int ret = X509_cmp(x509_1, x509_2);
5878     JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5879     return ret;
5880 }
5881 
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)5882 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5883                                        CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
5884                                        jlong certflagJava) {
5885     CHECK_ERROR_QUEUE_ON_RETURN;
5886     BIO* bio = to_BIO(env, bioRef);
5887     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5888     // NOLINTNEXTLINE(runtime/int)
5889     unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
5890     // NOLINTNEXTLINE(runtime/int)
5891     unsigned long certflag = static_cast<unsigned long>(certflagJava);
5892     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5893 
5894     if (bio == nullptr) {
5895         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5896         return;
5897     }
5898 
5899     if (x509 == nullptr) {
5900         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5901         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5902         return;
5903     }
5904 
5905     if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5906         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
5907         JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5908         return;
5909     }
5910     JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5911 }
5912 
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5913 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
5914                                           CONSCRYPT_UNUSED jobject holder) {
5915     CHECK_ERROR_QUEUE_ON_RETURN;
5916     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5917     JNI_TRACE("X509_get_pubkey(%p)", x509);
5918 
5919     if (x509 == nullptr) {
5920         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5921         JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
5922         return 0;
5923     }
5924 
5925     bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
5926     if (pkey.get() == nullptr) {
5927         const uint32_t last_error = ERR_peek_last_error();
5928         const uint32_t first_error = ERR_peek_error();
5929         if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
5930              ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
5931             (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
5932              ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
5933             ERR_clear_error();
5934             conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
5935             return 0;
5936         }
5937 
5938         conscrypt::jniutil::throwExceptionFromBoringSSLError(
5939                 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
5940         return 0;
5941     }
5942 
5943     JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
5944     return reinterpret_cast<uintptr_t>(pkey.release());
5945 }
5946 
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5947 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
5948                                                     CONSCRYPT_UNUSED jobject holder) {
5949     CHECK_ERROR_QUEUE_ON_RETURN;
5950     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5951     JNI_TRACE("X509_get_issuer_name(%p)", x509);
5952     return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
5953 }
5954 
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5955 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
5956                                                      CONSCRYPT_UNUSED jobject holder) {
5957     CHECK_ERROR_QUEUE_ON_RETURN;
5958     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5959     JNI_TRACE("X509_get_subject_name(%p)", x509);
5960     return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
5961 }
5962 
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5963 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
5964                                                 CONSCRYPT_UNUSED jobject holder) {
5965     CHECK_ERROR_QUEUE_ON_RETURN;
5966     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5967     JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
5968 
5969     if (x509 == nullptr) {
5970         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5971         JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
5972         return nullptr;
5973     }
5974 
5975     X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
5976     ASN1_OBJECT* algorithm;
5977     X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
5978     return ASN1_OBJECT_to_OID_string(env, algorithm);
5979 }
5980 
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5981 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
5982                                                  CONSCRYPT_UNUSED jobject holder) {
5983     CHECK_ERROR_QUEUE_ON_RETURN;
5984     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5985     JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
5986 
5987     if (x509 == nullptr) {
5988         conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
5989         JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
5990         return nullptr;
5991     }
5992 
5993     const X509_ALGOR *sig_alg;
5994     X509_get0_signature(nullptr, &sig_alg, x509);
5995     const ASN1_OBJECT *oid;
5996     X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5997     return ASN1_OBJECT_to_OID_string(env, oid);
5998 }
5999 
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6000 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6001                                                           CONSCRYPT_UNUSED jobject holder) {
6002     CHECK_ERROR_QUEUE_ON_RETURN;
6003     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6004     JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6005 
6006     if (x509 == nullptr) {
6007         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6008         JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6009         return nullptr;
6010     }
6011 
6012     const X509_ALGOR *sig_alg;
6013     X509_get0_signature(nullptr, &sig_alg, x509);
6014     return get_X509_ALGOR_parameter(env, sig_alg);
6015 }
6016 
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6017 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6018                                                      CONSCRYPT_UNUSED jobject holder) {
6019     CHECK_ERROR_QUEUE_ON_RETURN;
6020     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6021     JNI_TRACE("get_X509_issuerUID(%p)", x509);
6022 
6023     if (x509 == nullptr) {
6024         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6025         JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6026         return nullptr;
6027     }
6028 
6029     const ASN1_BIT_STRING *issuer_uid;
6030     X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6031     if (issuer_uid == nullptr) {
6032         JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6033         return nullptr;
6034     }
6035 
6036     return ASN1BitStringToBooleanArray(env, issuer_uid);
6037 }
6038 
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6039 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6040                                                       CONSCRYPT_UNUSED jobject holder) {
6041     CHECK_ERROR_QUEUE_ON_RETURN;
6042     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6043     JNI_TRACE("get_X509_subjectUID(%p)", x509);
6044 
6045     if (x509 == nullptr) {
6046         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6047         JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6048         return nullptr;
6049     }
6050 
6051     const ASN1_BIT_STRING *subject_uid;
6052     X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6053     if (subject_uid == nullptr) {
6054         JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6055         return nullptr;
6056     }
6057 
6058     return ASN1BitStringToBooleanArray(env, subject_uid);
6059 }
6060 
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6061 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6062                                                      CONSCRYPT_UNUSED jobject holder) {
6063     CHECK_ERROR_QUEUE_ON_RETURN;
6064     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6065     JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6066 
6067     if (x509 == nullptr) {
6068         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6069         JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6070         return nullptr;
6071     }
6072 
6073     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6074     // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6075     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6076     bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6077             static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6078     if (bitStr.get() == nullptr) {
6079         JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6080         ERR_clear_error();
6081         return nullptr;
6082     }
6083 
6084     return ASN1BitStringToBooleanArray(env, bitStr.get());
6085 }
6086 
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6087 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6088                                                      CONSCRYPT_UNUSED jobject holder) {
6089     CHECK_ERROR_QUEUE_ON_RETURN;
6090     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6091     JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6092 
6093     if (x509 == nullptr) {
6094         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6095         JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6096         return nullptr;
6097     }
6098 
6099     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6100     // |ERR_clear_error|, and throw CertificateParsingException.
6101     bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6102             X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6103     if (objArray.get() == nullptr) {
6104         JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6105         ERR_clear_error();
6106         return nullptr;
6107     }
6108 
6109     size_t size = sk_ASN1_OBJECT_num(objArray.get());
6110     ScopedLocalRef<jobjectArray> exKeyUsage(
6111             env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6112                                      nullptr));
6113     if (exKeyUsage.get() == nullptr) {
6114         return nullptr;
6115     }
6116 
6117     for (size_t i = 0; i < size; i++) {
6118         ScopedLocalRef<jstring> oidStr(
6119                 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6120         env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6121     }
6122 
6123     JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6124     return exKeyUsage.release();
6125 }
6126 
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6127 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6128                                              CONSCRYPT_UNUSED jobject holder) {
6129     CHECK_ERROR_QUEUE_ON_RETURN;
6130     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6131     JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6132 
6133     if (x509 == nullptr) {
6134         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6135         JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6136         return 0;
6137     }
6138 
6139     // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6140     // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6141     // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6142     // the constructor even if |EXFLAG_INVALID| is set.
6143     //
6144     // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6145     // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6146     // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6147     bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6148             X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6149     if (basic_constraints == nullptr) {
6150         JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6151         ERR_clear_error();
6152         return -1;
6153     }
6154 
6155     if (basic_constraints->pathlen == nullptr) {
6156         JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6157         return -1;
6158     }
6159 
6160     if (!basic_constraints->ca) {
6161         // Path length constraints are only valid for CA certificates.
6162         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6163         JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6164         return -1;
6165     }
6166 
6167     if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6168         // Path length constraints may not be negative.
6169         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6170         JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6171         return -1;
6172     }
6173 
6174     long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6175     if (pathlen == -1 || pathlen > INT_MAX) {
6176         // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6177         // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6178         // constraint is plausible, but Chromium rejects all values above 255.
6179         JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6180         return -1;
6181     }
6182 
6183     JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6184     return pathlen;
6185 }
6186 
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6187 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6188                                                 CONSCRYPT_UNUSED jobject holder,
6189                                                 jstring oidString) {
6190     CHECK_ERROR_QUEUE_ON_RETURN;
6191     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6192     JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6193     return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6194 }
6195 
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6196 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6197                                                     CONSCRYPT_UNUSED jobject holder,
6198                                                     jstring oidString) {
6199     CHECK_ERROR_QUEUE_ON_RETURN;
6200     X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6201     JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6202     return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6203                                                                                      oidString);
6204 }
6205 
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6206 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6207                                                         jstring oidString) {
6208     CHECK_ERROR_QUEUE_ON_RETURN;
6209     X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6210     JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6211     return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6212             env, revoked, oidString);
6213 }
6214 
6215 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6216           X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6217 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6218     T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6219     JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6220 
6221     if (x509 == nullptr) {
6222         conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6223         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6224         return nullptr;
6225     }
6226 
6227     int lastPos = -1;
6228     int count = 0;
6229     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6230         count++;
6231     }
6232 
6233     JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6234 
6235     ScopedLocalRef<jobjectArray> joa(
6236             env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6237     if (joa.get() == nullptr) {
6238         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6239         return nullptr;
6240     }
6241 
6242     lastPos = -1;
6243     count = 0;
6244     while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6245         X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6246 
6247         ScopedLocalRef<jstring> extOid(
6248                 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6249         if (extOid.get() == nullptr) {
6250             JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6251             return nullptr;
6252         }
6253 
6254         env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6255     }
6256 
6257     JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6258     return joa.release();
6259 }
6260 
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6261 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6262                                                    CONSCRYPT_UNUSED jobject holder, jint critical) {
6263     CHECK_ERROR_QUEUE_ON_RETURN;
6264     // NOLINTNEXTLINE(runtime/int)
6265     JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6266     return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6267                                                                                critical);
6268 }
6269 
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6270 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6271                                                        CONSCRYPT_UNUSED jobject holder,
6272                                                        jint critical) {
6273     CHECK_ERROR_QUEUE_ON_RETURN;
6274     // NOLINTNEXTLINE(runtime/int)
6275     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6276     return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6277             env, x509CrlRef, critical);
6278 }
6279 
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6280 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6281                                                            jlong x509RevokedRef, jint critical) {
6282     CHECK_ERROR_QUEUE_ON_RETURN;
6283     // NOLINTNEXTLINE(runtime/int)
6284     JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6285     return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6286                                  X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6287 }
6288 
6289 /**
6290  * Based on example logging call back from SSL_CTX_set_info_callback man page
6291  */
info_callback_LOG(const SSL * s,int where,int ret)6292 static void info_callback_LOG(const SSL* s, int where, int ret) {
6293     int w = where & ~SSL_ST_MASK;
6294     const char* str;
6295     if (w & SSL_ST_CONNECT) {
6296         str = "SSL_connect";
6297     } else if (w & SSL_ST_ACCEPT) {
6298         str = "SSL_accept";
6299     } else {
6300         str = "undefined";
6301     }
6302 
6303     if (where & SSL_CB_LOOP) {
6304         JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6305     } else if (where & SSL_CB_ALERT) {
6306         str = (where & SSL_CB_READ) ? "read" : "write";
6307         JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6308                   SSL_alert_desc_string_long(ret));
6309     } else if (where & SSL_CB_EXIT) {
6310         if (ret == 0) {
6311             JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6312                       SSL_state_string_long(s));
6313         } else if (ret < 0) {
6314             JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6315                       SSL_state_string_long(s));
6316         } else if (ret == 1) {
6317             JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6318                       SSL_state_string_long(s));
6319         } else {
6320             JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6321                       SSL_state_string_long(s));
6322         }
6323     } else if (where & SSL_CB_HANDSHAKE_START) {
6324         JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6325                   SSL_state_string_long(s));
6326     } else if (where & SSL_CB_HANDSHAKE_DONE) {
6327         JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6328                   SSL_state_string_long(s));
6329     } else {
6330         JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6331                   SSL_state_string_long(s));
6332     }
6333 }
6334 
6335 #ifdef _WIN32
6336 
6337 /**
6338  * Dark magic helper function that checks, for a given SSL session, whether it
6339  * can SSL_read() or SSL_write() without blocking. Takes into account any
6340  * concurrent attempts to close the SSLSocket from the Java side. This is
6341  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6342  * while thread #2 is sitting in a blocking read or write. The type argument
6343  * specifies whether we are waiting for readability or writability. It expects
6344  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6345  * only need to wait in case one of these problems occurs.
6346  *
6347  * @param env
6348  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6349  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6350  * @param appData The application data structure with mutex info etc.
6351  * @param timeout_millis The timeout value for select call, with the special value
6352  *                0 meaning no timeout at all (wait indefinitely). Note: This is
6353  *                the Java semantics of the timeout value, not the usual
6354  *                select() semantics.
6355  * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
6356  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6357 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6358                      int timeout_millis) {
6359     int result = -1;
6360 
6361     NetFd fd(env, fdObject);
6362     do {
6363         if (fd.isClosed()) {
6364             result = THROWN_EXCEPTION;
6365             break;
6366         }
6367 
6368         WSAEVENT events[2];
6369         events[0] = appData->interruptEvent;
6370         events[1] = WSACreateEvent();
6371         if (events[1] == WSA_INVALID_EVENT) {
6372             JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
6373             break;
6374         }
6375 
6376         if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
6377                                                         FD_CLOSE) == SOCKET_ERROR) {
6378             JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
6379             break;
6380         }
6381 
6382         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6383                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6384                   timeout_millis);
6385 
6386         int rc = WSAWaitForMultipleEvents(
6387                 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
6388         if (rc == WSA_WAIT_FAILED) {
6389             JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
6390             result = -1;
6391         } else if (rc == WSA_WAIT_TIMEOUT) {
6392             result = 0;
6393         } else {
6394             result = 1;
6395         }
6396         WSACloseEvent(events[1]);
6397     } while (0);
6398 
6399     JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
6400               (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
6401               result);
6402 
6403     std::lock_guard<std::mutex> appDataLock(appData->mutex);
6404     appData->waitingThreads--;
6405 
6406     return result;
6407 }
6408 
6409 #else   // !defined(_WIN32)
6410 
6411 /**
6412  * Dark magic helper function that checks, for a given SSL session, whether it
6413  * can SSL_read() or SSL_write() without blocking. Takes into account any
6414  * concurrent attempts to close the SSLSocket from the Java side. This is
6415  * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6416  * while thread #2 is sitting in a blocking read or write. The type argument
6417  * specifies whether we are waiting for readability or writability. It expects
6418  * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6419  * only need to wait in case one of these problems occurs.
6420  *
6421  * @param env
6422  * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6423  * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
6424  * @param appData The application data structure with mutex info etc.
6425  * @param timeout_millis The timeout value for poll call, with the special value
6426  *                0 meaning no timeout at all (wait indefinitely). Note: This is
6427  *                the Java semantics of the timeout value, not the usual
6428  *                poll() semantics.
6429  * @return The result of the inner poll() call,
6430  * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6431  * additional errors
6432  */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6433 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6434                      int timeout_millis) {
6435     // This loop is an expanded version of the NET_FAILURE_RETRY
6436     // macro. It cannot simply be used in this case because poll
6437     // cannot be restarted without recreating the pollfd structure.
6438     int result;
6439     struct pollfd fds[2];
6440     do {
6441         NetFd fd(env, fdObject);
6442         if (fd.isClosed()) {
6443             result = THROWN_EXCEPTION;
6444             break;
6445         }
6446         int intFd = fd.get();
6447         JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6448                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6449 
6450         memset(&fds, 0, sizeof(fds));
6451         fds[0].fd = intFd;
6452         if (type == SSL_ERROR_WANT_READ) {
6453             fds[0].events = POLLIN | POLLPRI;
6454         } else {
6455             fds[0].events = POLLOUT | POLLPRI;
6456         }
6457 
6458         fds[1].fd = appData->fdsEmergency[0];
6459         fds[1].events = POLLIN | POLLPRI;
6460 
6461         // Converting from Java semantics to Posix semantics.
6462         if (timeout_millis <= 0) {
6463             timeout_millis = -1;
6464         }
6465 
6466         CompatibilityCloseMonitor monitor(intFd);
6467 
6468         result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
6469         JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6470                   (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6471                   timeout_millis, result);
6472         if (result == -1) {
6473             if (fd.isClosed()) {
6474                 result = THROWN_EXCEPTION;
6475                 break;
6476             }
6477             if (errno != EINTR) {
6478                 break;
6479             }
6480         }
6481     } while (result == -1);
6482 
6483     std::lock_guard<std::mutex> appDataLock(appData->mutex);
6484 
6485     if (result > 0) {
6486         // We have been woken up by a token in the emergency pipe. We
6487         // can't be sure the token is still in the pipe at this point
6488         // because it could have already been read by the thread that
6489         // originally wrote it if it entered sslSelect and acquired
6490         // the mutex before we did. Thus we cannot safely read from
6491         // the pipe in a blocking way (so we make the pipe
6492         // non-blocking at creation).
6493         if (fds[1].revents & POLLIN) {
6494             char token;
6495             do {
6496                 (void)read(appData->fdsEmergency[0], &token, 1);
6497             } while (errno == EINTR);
6498         }
6499     }
6500 
6501     // Tell the world that there is now one thread less waiting for the
6502     // underlying network.
6503     appData->waitingThreads--;
6504 
6505     return result;
6506 }
6507 #endif  // !defined(_WIN32)
6508 
6509 /**
6510  * Helper function that wakes up a thread blocked in select(), in case there is
6511  * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6512  * before closing the connection.
6513  *
6514  * @param data The application data structure with mutex info etc.
6515  */
sslNotify(AppData * appData)6516 static void sslNotify(AppData* appData) {
6517 #ifdef _WIN32
6518     SetEvent(appData->interruptEvent);
6519 #else
6520     // Write a byte to the emergency pipe, so a concurrent select() can return.
6521     // Note we have to restore the errno of the original system call, since the
6522     // caller relies on it for generating error messages.
6523     int errnoBackup = errno;
6524     char token = '*';
6525     do {
6526         errno = 0;
6527         (void)write(appData->fdsEmergency[1], &token, 1);
6528     } while (errno == EINTR);
6529     errno = errnoBackup;
6530 #endif
6531 }
6532 
toAppData(const SSL * ssl)6533 static AppData* toAppData(const SSL* ssl) {
6534     return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6535 }
6536 
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)6537 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
6538     JNI_TRACE("ssl=%p cert_verify_callback", ssl);
6539 
6540     AppData* appData = toAppData(ssl);
6541     JNIEnv* env = appData->env;
6542     if (env == nullptr) {
6543         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
6544         JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6545         return ssl_verify_invalid;
6546     }
6547 
6548     // Create the byte[][] array that holds all the certs
6549     ScopedLocalRef<jobjectArray> array(
6550             env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
6551     if (array.get() == nullptr) {
6552         return ssl_verify_invalid;
6553     }
6554 
6555     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6556     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6557     jmethodID methodID =
6558             env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
6559 
6560     const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
6561     const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
6562 
6563     JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
6564               authMethod);
6565     ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
6566     env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
6567 
6568     ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
6569     JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6570     return result;
6571 }
6572 
6573 /**
6574  * Call back to watch for handshake to be completed. This is necessary for
6575  * False Start support, since SSL_do_handshake returns before the handshake is
6576  * completed in this case.
6577  */
info_callback(const SSL * ssl,int type,int value)6578 static void info_callback(const SSL* ssl, int type, int value) {
6579     JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
6580     if (conscrypt::trace::kWithJniTrace) {
6581         info_callback_LOG(ssl, type, value);
6582     }
6583     if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
6584         JNI_TRACE("ssl=%p info_callback ignored", ssl);
6585         return;
6586     }
6587 
6588     AppData* appData = toAppData(ssl);
6589     JNIEnv* env = appData->env;
6590     if (env == nullptr) {
6591         CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
6592         JNI_TRACE("ssl=%p info_callback env error", ssl);
6593         return;
6594     }
6595     if (env->ExceptionCheck()) {
6596         JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6597         return;
6598     }
6599 
6600     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6601 
6602     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6603     jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(II)V");
6604 
6605     JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6606     env->CallVoidMethod(sslHandshakeCallbacks, methodID, type, value);
6607 
6608     if (env->ExceptionCheck()) {
6609         JNI_TRACE("ssl=%p info_callback exception", ssl);
6610     }
6611     JNI_TRACE("ssl=%p info_callback completed", ssl);
6612 }
6613 
6614 /**
6615  * Call back to ask for a certificate. There are three possible exit codes:
6616  *
6617  * 1 is success.
6618  * 0 is error.
6619  * -1 is to pause the handshake to continue from the same place later.
6620  */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)6621 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
6622     JNI_TRACE("ssl=%p cert_cb", ssl);
6623 
6624     // cert_cb is called for both clients and servers, but we are only
6625     // interested in client certificates.
6626     if (SSL_is_server(ssl)) {
6627         JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
6628         return 1;
6629     }
6630 
6631     AppData* appData = toAppData(ssl);
6632     JNIEnv* env = appData->env;
6633     if (env == nullptr) {
6634         CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
6635         JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
6636         return 0;
6637     }
6638     if (env->ExceptionCheck()) {
6639         JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
6640         return 0;
6641     }
6642     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6643 
6644     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6645     jmethodID methodID = env->GetMethodID(cls, "clientCertificateRequested", "([B[I[[B)V");
6646 
6647     // Call Java callback which can reconfigure the client certificate.
6648     const uint8_t* ctype = nullptr;
6649     size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
6650     const uint16_t* sigalgs = nullptr;
6651     size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
6652     ScopedLocalRef<jobjectArray> issuers(
6653             env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
6654     if (issuers.get() == nullptr) {
6655         return 0;
6656     }
6657 
6658     if (conscrypt::trace::kWithJniTrace) {
6659         for (size_t i = 0; i < ctype_num; i++) {
6660             JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
6661         }
6662         for (size_t i = 0; i < sigalgs_num; i++) {
6663             JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
6664         }
6665     }
6666 
6667     jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
6668     if (keyTypes == nullptr) {
6669         JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
6670         return 0;
6671     }
6672     env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
6673                             reinterpret_cast<const jbyte*>(ctype));
6674 
6675     jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
6676     if (signatureAlgs == nullptr) {
6677         JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
6678         return 0;
6679     }
6680     {
6681         ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
6682         for (size_t i = 0; i < sigalgs_num; i++) {
6683             sigAlgsRW[i] = sigalgs[i];
6684         }
6685     }
6686 
6687     JNI_TRACE(
6688             "ssl=%p clientCertificateRequested calling clientCertificateRequested "
6689             "keyTypes=%p signatureAlgs=%p issuers=%p",
6690             ssl, keyTypes, signatureAlgs, issuers.get());
6691     env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
6692 
6693     if (env->ExceptionCheck()) {
6694         JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
6695         return 0;
6696     }
6697 
6698     JNI_TRACE("ssl=%p cert_cb => 1", ssl);
6699     return 1;
6700 }
6701 
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)6702 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
6703     SSL* ssl = client_hello->ssl;
6704     JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
6705 
6706     AppData* appData = toAppData(ssl);
6707     JNIEnv* env = appData->env;
6708     if (env == nullptr) {
6709         CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
6710         JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
6711         return ssl_select_cert_error;
6712     }
6713     if (env->ExceptionCheck()) {
6714         JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
6715         return ssl_select_cert_error;
6716     }
6717 
6718     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6719     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6720     jmethodID methodID = env->GetMethodID(cls, "serverCertificateRequested", "()V");
6721 
6722     JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
6723     env->CallVoidMethod(sslHandshakeCallbacks, methodID);
6724 
6725     if (env->ExceptionCheck()) {
6726         JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
6727         return ssl_select_cert_error;
6728     }
6729     JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
6730     return ssl_select_cert_success;
6731 }
6732 
6733 /**
6734  * Pre-Shared Key (PSK) client callback.
6735  */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6736 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
6737                                         unsigned int max_identity_len, unsigned char* psk,
6738                                         unsigned int max_psk_len) {
6739     JNI_TRACE("ssl=%p psk_client_callback", ssl);
6740 
6741     AppData* appData = toAppData(ssl);
6742     JNIEnv* env = appData->env;
6743     if (env == nullptr) {
6744         CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
6745         JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6746         return 0;
6747     }
6748     if (env->ExceptionCheck()) {
6749         JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6750         return 0;
6751     }
6752 
6753     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6754     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6755     jmethodID methodID =
6756             env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
6757     JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6758     ScopedLocalRef<jstring> identityHintJava(env,
6759                                              (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
6760     ScopedLocalRef<jbyteArray> identityJava(
6761             env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
6762     if (identityJava.get() == nullptr) {
6763         JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6764         return 0;
6765     }
6766     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6767     if (keyJava.get() == nullptr) {
6768         JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6769         return 0;
6770     }
6771     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6772                                      identityJava.get(), keyJava.get());
6773     if (env->ExceptionCheck()) {
6774         JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6775         return 0;
6776     }
6777     if (keyLen <= 0) {
6778         JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6779         return 0;
6780     } else if ((unsigned int)keyLen > max_psk_len) {
6781         JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6782         return 0;
6783     }
6784     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6785     if (keyJavaRo.get() == nullptr) {
6786         JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
6787         return 0;
6788     }
6789     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6790 
6791     ScopedByteArrayRO identityJavaRo(env, identityJava.get());
6792     if (identityJavaRo.get() == nullptr) {
6793         JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
6794         return 0;
6795     }
6796     memcpy(identity, identityJavaRo.get(), max_identity_len);
6797 
6798     JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
6799     return static_cast<unsigned int>(keyLen);
6800 }
6801 
6802 /**
6803  * Pre-Shared Key (PSK) server callback.
6804  */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)6805 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
6806                                         unsigned int max_psk_len) {
6807     JNI_TRACE("ssl=%p psk_server_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 psk_server_callback");
6813         JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
6814         return 0;
6815     }
6816     if (env->ExceptionCheck()) {
6817         JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
6818         return 0;
6819     }
6820 
6821     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6822     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6823     jmethodID methodID = env->GetMethodID(cls, "serverPSKKeyRequested",
6824                                           "(Ljava/lang/String;Ljava/lang/String;[B)I");
6825     JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
6826     const char* identityHint = SSL_get_psk_identity_hint(ssl);
6827     ScopedLocalRef<jstring> identityHintJava(
6828             env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
6829     ScopedLocalRef<jstring> identityJava(
6830             env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
6831     ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6832     if (keyJava.get() == nullptr) {
6833         JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
6834         return 0;
6835     }
6836     jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6837                                      identityJava.get(), keyJava.get());
6838     if (env->ExceptionCheck()) {
6839         JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
6840         return 0;
6841     }
6842     if (keyLen <= 0) {
6843         JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
6844         return 0;
6845     } else if ((unsigned int)keyLen > max_psk_len) {
6846         JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
6847         return 0;
6848     }
6849     ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6850     if (keyJavaRo.get() == nullptr) {
6851         JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
6852         return 0;
6853     }
6854     memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6855 
6856     JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
6857     return static_cast<unsigned int>(keyLen);
6858 }
6859 
new_session_callback(SSL * ssl,SSL_SESSION * session)6860 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
6861     JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
6862 
6863     AppData* appData = toAppData(ssl);
6864     JNIEnv* env = appData->env;
6865     if (env == nullptr) {
6866         CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
6867         JNI_TRACE("ssl=%p new_session_callback env error", ssl);
6868         return 0;
6869     }
6870     if (env->ExceptionCheck()) {
6871         JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
6872         return 0;
6873     }
6874 
6875     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6876     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6877     jmethodID methodID = env->GetMethodID(cls, "onNewSessionEstablished", "(J)V");
6878     JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
6879     env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
6880     if (env->ExceptionCheck()) {
6881         JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
6882         env->ExceptionClear();
6883     }
6884     JNI_TRACE("ssl=%p new_session_callback completed", ssl);
6885 
6886     // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
6887     // the reference count.
6888     return 0;
6889 }
6890 
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)6891 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
6892                                                       int* out_copy) {
6893     JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
6894 
6895     // Always set to out_copy to zero. The Java callback will be responsible for incrementing
6896     // the reference count (and any required synchronization).
6897     *out_copy = 0;
6898 
6899     AppData* appData = toAppData(ssl);
6900     JNIEnv* env = appData->env;
6901     if (env == nullptr) {
6902         CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
6903         JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
6904         return 0;
6905     }
6906     if (env->ExceptionCheck()) {
6907         JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
6908         return 0;
6909     }
6910 
6911     // Copy the ID to a byte[].
6912     jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
6913     if (id_array == nullptr) {
6914         JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
6915         return 0;
6916     }
6917     env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
6918                             reinterpret_cast<const jbyte*>(id));
6919 
6920     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6921     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6922     jmethodID methodID = env->GetMethodID(cls, "serverSessionRequested", "([B)J");
6923     JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
6924     jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
6925     if (env->ExceptionCheck()) {
6926         JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
6927         env->ExceptionClear();
6928     }
6929     SSL_SESSION* ssl_session_ptr =
6930             reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
6931     JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
6932     return ssl_session_ptr;
6933 }
6934 
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)6935 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
6936     CHECK_ERROR_QUEUE_ON_RETURN;
6937     int ret = 0;
6938     ret = EVP_has_aes_hardware();
6939     JNI_TRACE("EVP_has_aes_hardware => %d", ret);
6940     return ret;
6941 }
6942 
debug_print_session_key(const SSL * ssl,const char * line)6943 static void debug_print_session_key(const SSL* ssl, const char* line) {
6944     JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
6945 }
6946 
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)6947 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
6948     static constexpr size_t kDataWidth = 16;
6949 
6950     struct timeval tv;
6951     if (gettimeofday(&tv, NULL)) {
6952         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6953                       "debug_print_packet_data: could not get time of day");
6954         return;
6955     }
6956 
6957     // Packet preamble for text2pcap
6958     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
6959                   tv.tv_sec, static_cast<long>(tv.tv_usec));  // NOLINT(runtime/int)
6960 
6961     char out[kDataWidth * 3 + 1];
6962     for (size_t i = 0; i < len; i += kDataWidth) {
6963         size_t n = len - i < kDataWidth ? len - i : kDataWidth;
6964 
6965         for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
6966             int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
6967             if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
6968                 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6969                               "debug_print_packet_data failed to output %d", ret);
6970                 return;
6971             }
6972         }
6973 
6974         // Print out packet data in format understood by text2pcap
6975         CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
6976     }
6977 
6978     // Conclude the packet data
6979     CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
6980 }
6981 
6982 /*
6983  * public static native int SSL_CTX_new();
6984  */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)6985 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
6986     CHECK_ERROR_QUEUE_ON_RETURN;
6987     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
6988     if (sslCtx.get() == nullptr) {
6989         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
6990         return 0;
6991     }
6992     SSL_CTX_set_options(
6993             sslCtx.get(),
6994             SSL_OP_ALL
6995                     // We also disable session tickets for better compatibility b/2682876
6996                     | SSL_OP_NO_TICKET
6997                     // We also disable compression for better compatibility b/2710492 b/2710497
6998                     | SSL_OP_NO_COMPRESSION
6999                     // Generate a fresh ECDH keypair for each key exchange.
7000                     | SSL_OP_SINGLE_ECDH_USE);
7001     SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7002     SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7003 
7004     uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7005     /*
7006      * Turn on "partial write" mode. This means that SSL_write() will
7007      * behave like Posix write() and possibly return after only
7008      * writing a partial buffer. Note: The alternative, perhaps
7009      * surprisingly, is not that SSL_write() always does full writes
7010      * but that it will force you to retry write calls having
7011      * preserved the full state of the original call. (This is icky
7012      * and undesirable.)
7013      */
7014     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7015 
7016     // Reuse empty buffers within the SSL_CTX to save memory
7017     mode |= SSL_MODE_RELEASE_BUFFERS;
7018 
7019     // Enable False Start.
7020     mode |= SSL_MODE_ENABLE_FALSE_START;
7021 
7022     // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7023     // between
7024     // calls to wrap(...).
7025     // See https://github.com/netty/netty-tcnative/issues/100
7026     mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7027 
7028     SSL_CTX_set_mode(sslCtx.get(), mode);
7029 
7030     SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7031     SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7032     SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7033     if (conscrypt::trace::kWithJniTraceKeys) {
7034         SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7035     }
7036 
7037     // By default BoringSSL will cache in server mode, but we want to get
7038     // notified of new sessions being created in client mode. We set
7039     // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7040     // ignore it in server mode in favor of the internal cache.
7041     SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7042     SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7043     SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7044 
7045     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7046     return (jlong)sslCtx.release();
7047 }
7048 
7049 /**
7050  * public static native void SSL_CTX_free(long ssl_ctx)
7051  */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7052 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7053                                       CONSCRYPT_UNUSED jobject holder) {
7054     CHECK_ERROR_QUEUE_ON_RETURN;
7055     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7056     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7057     if (ssl_ctx == nullptr) {
7058         return;
7059     }
7060     SSL_CTX_free(ssl_ctx);
7061 }
7062 
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7063 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7064                                                         CONSCRYPT_UNUSED jobject holder,
7065                                                         jbyteArray sid_ctx) {
7066     CHECK_ERROR_QUEUE_ON_RETURN;
7067     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7068     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7069               sid_ctx);
7070     if (ssl_ctx == nullptr) {
7071         return;
7072     }
7073 
7074     ScopedByteArrayRO buf(env, sid_ctx);
7075     if (buf.get() == nullptr) {
7076         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7077                   ssl_ctx);
7078         return;
7079     }
7080 
7081     unsigned int length = static_cast<unsigned int>(buf.size());
7082     if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7083         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7084                                            "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7085         JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7086         return;
7087     }
7088     const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7089     int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7090     if (result == 0) {
7091         conscrypt::jniutil::throwExceptionFromBoringSSLError(
7092                 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7093         return;
7094     }
7095     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7096 }
7097 
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7098 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7099                                               CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7100     CHECK_ERROR_QUEUE_ON_RETURN;
7101     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7102     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7103     if (ssl_ctx == nullptr) {
7104         return 0L;
7105     }
7106 
7107     return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7108 }
7109 
7110 /**
7111  * public static native int SSL_new(long ssl_ctx) throws SSLException;
7112  */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7113 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7114                                   CONSCRYPT_UNUSED jobject holder) {
7115     CHECK_ERROR_QUEUE_ON_RETURN;
7116     SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7117     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7118     if (ssl_ctx == nullptr) {
7119         return 0;
7120     }
7121     bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7122     if (ssl.get() == nullptr) {
7123         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7124                                                            "Unable to create SSL structure");
7125         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7126         return 0;
7127     }
7128 
7129     /*
7130      * Create our special application data.
7131      */
7132     AppData* appData = AppData::create();
7133     if (appData == nullptr) {
7134         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7135         ERR_clear_error();
7136         JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7137         return 0;
7138     }
7139     SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7140 
7141     SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7142 
7143     JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7144     return (jlong)ssl.release();
7145 }
7146 
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject ssl_holder)7147 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7148                                                    CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject
7149                                                            ssl_holder) {
7150     CHECK_ERROR_QUEUE_ON_RETURN;
7151     SSL* ssl = to_SSL(env, ssl_address, true);
7152     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7153     if (ssl == nullptr) {
7154         return;
7155     }
7156 
7157     // NOLINTNEXTLINE(runtime/int)
7158     long ret = SSL_enable_tls_channel_id(ssl);
7159     if (ret != 1L) {
7160         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7161         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7162                                                            "Error enabling Channel ID");
7163         JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7164         return;
7165     }
7166 }
7167 
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7168 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7169                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
7170     CHECK_ERROR_QUEUE_ON_RETURN;
7171     SSL* ssl = to_SSL(env, ssl_address, true);
7172     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7173     if (ssl == nullptr) {
7174         return nullptr;
7175     }
7176 
7177     // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7178     // as a constant anywhere.
7179     jbyteArray javaBytes = env->NewByteArray(64);
7180     ScopedByteArrayRW bytes(env, javaBytes);
7181     if (bytes.get() == nullptr) {
7182         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7183         return nullptr;
7184     }
7185 
7186     unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7187     // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7188     // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7189     // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7190     size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7191     if (ret == 0) {
7192         // Channel ID either not set or did not verify
7193         JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7194         return nullptr;
7195     } else if (ret != 64) {
7196         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7197         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7198                                                            "Error getting Channel ID");
7199         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7200         return nullptr;
7201     }
7202 
7203     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7204     return javaBytes;
7205 }
7206 
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7207 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7208                                                  CONSCRYPT_UNUSED jobject ssl_holder,
7209                                                  jobject pkeyRef) {
7210     CHECK_ERROR_QUEUE_ON_RETURN;
7211     SSL* ssl = to_SSL(env, ssl_address, true);
7212     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7213     if (ssl == nullptr) {
7214         return;
7215     }
7216 
7217     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7218     if (pkey == nullptr) {
7219         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7220         return;
7221     }
7222 
7223     // NOLINTNEXTLINE(runtime/int)
7224     long ret = SSL_set1_tls_channel_id(ssl, pkey);
7225 
7226     if (ret != 1L) {
7227         CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7228         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7229                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7230         JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7231         return;
7232     }
7233 
7234     JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7235 }
7236 
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7237 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7238                                                     CONSCRYPT_UNUSED jobject ssl_holder,
7239                                                     jobjectArray encodedCertificatesJava,
7240                                                     jobject pkeyRef) {
7241     CHECK_ERROR_QUEUE_ON_RETURN;
7242     SSL* ssl = to_SSL(env, ssl_address, true);
7243     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7244               encodedCertificatesJava, pkeyRef);
7245     if (ssl == nullptr) {
7246         return;
7247     }
7248     if (encodedCertificatesJava == nullptr) {
7249         conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7250         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7251         return;
7252     }
7253     size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7254     if (numCerts == 0) {
7255         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7256                                            "certificates.length == 0");
7257         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7258         return;
7259     }
7260     if (pkeyRef == nullptr) {
7261         conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7262         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7263         return;
7264     }
7265 
7266     // Get the private key.
7267     EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7268     if (pkey == nullptr) {
7269         conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7270         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7271         return;
7272     }
7273 
7274     // Copy the certificates.
7275     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7276     std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7277     for (size_t i = 0; i < numCerts; ++i) {
7278         ScopedLocalRef<jbyteArray> certArray(
7279                 env, reinterpret_cast<jbyteArray>(
7280                              env->GetObjectArrayElement(encodedCertificatesJava, i)));
7281         certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7282         if (!certBufferRefs[i]) {
7283             return;
7284         }
7285         certBuffers[i] = certBufferRefs[i].get();
7286     }
7287 
7288     if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7289         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7290                                                            "Error configuring certificate");
7291         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7292         return;
7293     }
7294     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7295 }
7296 
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7297 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7298                                                 CONSCRYPT_UNUSED jobject ssl_holder,
7299                                                 jobjectArray principals) {
7300     CHECK_ERROR_QUEUE_ON_RETURN;
7301     SSL* ssl = to_SSL(env, ssl_address, true);
7302     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7303     if (ssl == nullptr) {
7304         return;
7305     }
7306 
7307     if (principals == nullptr) {
7308         conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7309         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7310         return;
7311     }
7312 
7313     int length = env->GetArrayLength(principals);
7314     if (length == 0) {
7315         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7316                                            "principals.length == 0");
7317         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7318         return;
7319     }
7320 
7321     bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7322     if (principalsStack.get() == nullptr) {
7323         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7324         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7325         return;
7326     }
7327     for (int i = 0; i < length; i++) {
7328         ScopedLocalRef<jbyteArray> principal(
7329                 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7330         bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7331         if (!buf) {
7332             return;
7333         }
7334         if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7335             conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7336             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7337             return;
7338         }
7339         OWNERSHIP_TRANSFERRED(buf);
7340     }
7341 
7342     SSL_set0_client_CAs(ssl, principalsStack.release());
7343     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7344 }
7345 
7346 /**
7347  * public static native long SSL_set_mode(long ssl, long mode);
7348  */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)7349 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
7350                                        CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
7351     CHECK_ERROR_QUEUE_ON_RETURN;
7352     SSL* ssl = to_SSL(env, ssl_address, true);
7353     // NOLINTNEXTLINE(runtime/int)
7354     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
7355     if (ssl == nullptr) {
7356         return 0;
7357     }
7358     jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
7359     // NOLINTNEXTLINE(runtime/int)
7360     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
7361     return result;
7362 }
7363 
7364 /**
7365  * public static native long SSL_set_options(long ssl, long options);
7366  */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7367 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
7368                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7369     CHECK_ERROR_QUEUE_ON_RETURN;
7370     SSL* ssl = to_SSL(env, ssl_address, true);
7371     // NOLINTNEXTLINE(runtime/int)
7372     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
7373     if (ssl == nullptr) {
7374         return 0;
7375     }
7376     jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
7377     // NOLINTNEXTLINE(runtime/int)
7378     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
7379     return result;
7380 }
7381 
7382 /**
7383  * public static native long SSL_clear_options(long ssl, long options);
7384  */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7385 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
7386                                             CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7387     CHECK_ERROR_QUEUE_ON_RETURN;
7388     SSL* ssl = to_SSL(env, ssl_address, true);
7389     // NOLINTNEXTLINE(runtime/int)
7390     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
7391     if (ssl == nullptr) {
7392         return 0;
7393     }
7394     jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
7395     // NOLINTNEXTLINE(runtime/int)
7396     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
7397     return result;
7398 }
7399 
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)7400 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
7401                                                    CONSCRYPT_UNUSED jobject ssl_holder,
7402                                                    jint min_version, jint max_version) {
7403     CHECK_ERROR_QUEUE_ON_RETURN;
7404     SSL* ssl = to_SSL(env, ssl_address, true);
7405     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
7406               max_version);
7407     if (ssl == nullptr) {
7408         return 0;
7409     }
7410     int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
7411     int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
7412     // Return failure if either call failed.
7413     int result = 1;
7414     if (!min_result || !max_result) {
7415         result = 0;
7416         // The only possible error is an invalid version, so we don't need the details.
7417         ERR_clear_error();
7418     }
7419     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
7420               min_result, max_result, result);
7421     return result;
7422 }
7423 
7424 /**
7425  * public static native void SSL_enable_signed_cert_timestamps(long ssl);
7426  */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7427 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
7428                                                            CONSCRYPT_UNUSED jobject ssl_holder) {
7429     CHECK_ERROR_QUEUE_ON_RETURN;
7430     SSL* ssl = to_SSL(env, ssl_address, true);
7431     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
7432     if (ssl == nullptr) {
7433         return;
7434     }
7435 
7436     SSL_enable_signed_cert_timestamps(ssl);
7437 }
7438 
7439 /**
7440  * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
7441  */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7442 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
7443         JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
7444     CHECK_ERROR_QUEUE_ON_RETURN;
7445     SSL* ssl = to_SSL(env, ssl_address, true);
7446     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
7447     if (ssl == nullptr) {
7448         return nullptr;
7449     }
7450 
7451     const uint8_t* data;
7452     size_t data_len;
7453     SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
7454 
7455     if (data_len == 0) {
7456         JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
7457         return nullptr;
7458     }
7459 
7460     jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
7461     if (result != nullptr) {
7462         env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
7463     }
7464     return result;
7465 }
7466 
7467 /*
7468  * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
7469  */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)7470 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
7471                                                             CONSCRYPT_UNUSED jobject ssl_holder,
7472                                                             jbyteArray list) {
7473     CHECK_ERROR_QUEUE_ON_RETURN;
7474     SSL* ssl = to_SSL(env, ssl_address, true);
7475     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
7476     if (ssl == nullptr) {
7477         return;
7478     }
7479 
7480     ScopedByteArrayRO listBytes(env, list);
7481     if (listBytes.get() == nullptr) {
7482         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
7483         return;
7484     }
7485 
7486     if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
7487                                             listBytes.size())) {
7488         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
7489     } else {
7490         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
7491     }
7492 }
7493 
7494 /*
7495  * public static native void SSL_enable_ocsp_stapling(long ssl);
7496  */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7497 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
7498                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
7499     CHECK_ERROR_QUEUE_ON_RETURN;
7500     SSL* ssl = to_SSL(env, ssl_address, true);
7501     JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
7502     if (ssl == nullptr) {
7503         return;
7504     }
7505 
7506     SSL_enable_ocsp_stapling(ssl);
7507 }
7508 
7509 /*
7510  * public static native byte[] SSL_get_ocsp_response(long ssl);
7511  */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7512 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7513                                                      CONSCRYPT_UNUSED jobject ssl_holder) {
7514     CHECK_ERROR_QUEUE_ON_RETURN;
7515     SSL* ssl = to_SSL(env, ssl_address, true);
7516     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
7517     if (ssl == nullptr) {
7518         return nullptr;
7519     }
7520 
7521     const uint8_t* data;
7522     size_t data_len;
7523     SSL_get0_ocsp_response(ssl, &data, &data_len);
7524 
7525     if (data_len == 0) {
7526         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
7527         return nullptr;
7528     }
7529 
7530     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7531     if (byteArray.get() == nullptr) {
7532         JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
7533         return nullptr;
7534     }
7535 
7536     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7537     JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
7538               data_len);
7539 
7540     return byteArray.release();
7541 }
7542 
7543 /*
7544  * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
7545  */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)7546 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7547                                                CONSCRYPT_UNUSED jobject ssl_holder,
7548                                                jbyteArray response) {
7549     CHECK_ERROR_QUEUE_ON_RETURN;
7550     SSL* ssl = to_SSL(env, ssl_address, true);
7551     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
7552     if (ssl == nullptr) {
7553         return;
7554     }
7555 
7556     ScopedByteArrayRO responseBytes(env, response);
7557     if (responseBytes.get() == nullptr) {
7558         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
7559         return;
7560     }
7561 
7562     if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
7563                                responseBytes.size())) {
7564         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
7565     } else {
7566         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
7567     }
7568 }
7569 
7570 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
7571 // to customize the length of their verify_data (with a default of 12 bytes).  We accept
7572 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
7573 // tests and update this value if necessary.
7574 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
7575 
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7576 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
7577                                                   CONSCRYPT_UNUSED jobject ssl_holder) {
7578     CHECK_ERROR_QUEUE_ON_RETURN;
7579     SSL* ssl = to_SSL(env, ssl_address, true);
7580     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
7581     if (ssl == nullptr) {
7582         return nullptr;
7583     }
7584 
7585     uint8_t data[MAX_TLS_UNIQUE_LENGTH];
7586     size_t data_len;
7587     int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
7588 
7589     if (!ret || data_len == 0) {
7590         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
7591         return nullptr;
7592     }
7593 
7594     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7595     if (byteArray.get() == nullptr) {
7596         JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
7597         return nullptr;
7598     }
7599 
7600     env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7601     JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
7602               data_len);
7603 
7604     return byteArray.release();
7605 }
7606 
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)7607 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
7608                                                           CONSCRYPT_UNUSED jobject ssl_holder,
7609                                                           jbyteArray label, jbyteArray context,
7610                                                           jint num_bytes) {
7611     CHECK_ERROR_QUEUE_ON_RETURN;
7612     SSL* ssl = to_SSL(env, ssl_address, true);
7613     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
7614     if (ssl == nullptr) {
7615         return nullptr;
7616     }
7617     ScopedByteArrayRO labelBytes(env, label);
7618     if (labelBytes.get() == nullptr) {
7619         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
7620         return nullptr;
7621     }
7622     std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
7623     int ret;
7624     if (context == nullptr) {
7625         ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
7626                         reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
7627                         nullptr, 0, 0);
7628     } else {
7629         ScopedByteArrayRO contextBytes(env, context);
7630         if (contextBytes.get() == nullptr) {
7631             JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
7632                       ssl);
7633             return nullptr;
7634         }
7635         ret = SSL_export_keying_material(
7636                 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
7637                 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
7638                 contextBytes.size(), 1);
7639     }
7640     if (!ret) {
7641         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
7642                 conscrypt::jniutil::throwSSLExceptionStr);
7643         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
7644         return nullptr;
7645     }
7646     jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
7647     if (result == nullptr) {
7648         conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
7649         JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
7650         return nullptr;
7651     }
7652     const jbyte* src = reinterpret_cast<jbyte*>(out.get());
7653     env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
7654     JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
7655     return result;
7656 }
7657 
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)7658 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
7659                                                    CONSCRYPT_UNUSED jobject ssl_holder,
7660                                                    jstring identityHintJava) {
7661     CHECK_ERROR_QUEUE_ON_RETURN;
7662     SSL* ssl = to_SSL(env, ssl_address, true);
7663     JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
7664               identityHintJava);
7665     if (ssl == nullptr) {
7666         return;
7667     }
7668 
7669     int ret;
7670     if (identityHintJava == nullptr) {
7671         ret = SSL_use_psk_identity_hint(ssl, nullptr);
7672     } else {
7673         ScopedUtfChars identityHint(env, identityHintJava);
7674         if (identityHint.c_str() == nullptr) {
7675             conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7676             return;
7677         }
7678         ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7679     }
7680 
7681     if (ret != 1) {
7682         int sslErrorCode = SSL_get_error(ssl, ret);
7683         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7684                                                            "Failed to set PSK identity hint");
7685     }
7686 }
7687 
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7688 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7689                                                              CONSCRYPT_UNUSED jobject ssl_holder,
7690                                                              jboolean enabled) {
7691     CHECK_ERROR_QUEUE_ON_RETURN;
7692     SSL* ssl = to_SSL(env, ssl_address, true);
7693     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
7694     if (ssl == nullptr) {
7695         return;
7696     }
7697 
7698     SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
7699 }
7700 
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7701 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7702                                                              CONSCRYPT_UNUSED jobject ssl_holder,
7703                                                              jboolean enabled) {
7704     CHECK_ERROR_QUEUE_ON_RETURN;
7705     SSL* ssl = to_SSL(env, ssl_address, true);
7706     JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
7707     if (ssl == nullptr) {
7708         return;
7709     }
7710 
7711     SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
7712 }
7713 
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7714 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
7715                                                CONSCRYPT_UNUSED jobject ssl_holder) {
7716     CHECK_ERROR_QUEUE_ON_RETURN;
7717     SSL* ssl = to_SSL(env, ssl_address, true);
7718     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7719     if (ssl == nullptr) {
7720         return nullptr;
7721     }
7722 
7723     STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7724     size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7725     ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
7726     ScopedLongArrayRW ciphers(env, ciphersArray.get());
7727     for (size_t i = 0; i < count; i++) {
7728         ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7729     }
7730 
7731     JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
7732     return ciphersArray.release();
7733 }
7734 
7735 /**
7736  * Sets the ciphers suites that are enabled in the SSL
7737  */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)7738 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
7739                                               CONSCRYPT_UNUSED jobject ssl_holder,
7740                                               jobjectArray cipherSuites) {
7741     CHECK_ERROR_QUEUE_ON_RETURN;
7742     SSL* ssl = to_SSL(env, ssl_address, true);
7743     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7744     if (ssl == nullptr) {
7745         return;
7746     }
7747     if (cipherSuites == nullptr) {
7748         conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
7749         return;
7750     }
7751 
7752     int length = env->GetArrayLength(cipherSuites);
7753 
7754     /*
7755      * Special case for empty cipher list. This is considered an error by the
7756      * SSL_set_cipher_list API, but Java allows this silly configuration.
7757      * However, the SSL cipher list is still set even when SSL_set_cipher_list
7758      * returns 0 in this case. Just to make sure, we check the resulting cipher
7759      * list to make sure it's zero length.
7760      */
7761     if (length == 0) {
7762         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
7763         SSL_set_cipher_list(ssl, "");
7764         ERR_clear_error();
7765         if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
7766             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
7767             conscrypt::jniutil::throwRuntimeException(
7768                     env, "SSL_set_cipher_list did not update ciphers!");
7769             ERR_clear_error();
7770         }
7771         return;
7772     }
7773 
7774     static const char noSSLv2[] = "!SSLv2";
7775     size_t cipherStringLen = strlen(noSSLv2);
7776 
7777     for (int i = 0; i < length; i++) {
7778         ScopedLocalRef<jstring> cipherSuite(
7779                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7780         ScopedUtfChars c(env, cipherSuite.get());
7781         if (c.c_str() == nullptr) {
7782             return;
7783         }
7784 
7785         if (cipherStringLen + 1 < cipherStringLen) {
7786             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7787                                                "Overflow in cipher suite strings");
7788             return;
7789         }
7790         cipherStringLen += 1; /* For the separating colon */
7791 
7792         if (cipherStringLen + c.size() < cipherStringLen) {
7793             conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7794                                                "Overflow in cipher suite strings");
7795             return;
7796         }
7797         cipherStringLen += c.size();
7798     }
7799 
7800     if (cipherStringLen + 1 < cipherStringLen) {
7801         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7802                                            "Overflow in cipher suite strings");
7803         return;
7804     }
7805     cipherStringLen += 1; /* For final NUL. */
7806 
7807     std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
7808     if (cipherString.get() == nullptr) {
7809         conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
7810         return;
7811     }
7812     memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
7813     size_t j = strlen(noSSLv2);
7814 
7815     for (int i = 0; i < length; i++) {
7816         ScopedLocalRef<jstring> cipherSuite(
7817                 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7818         ScopedUtfChars c(env, cipherSuite.get());
7819 
7820         cipherString[j++] = ':';
7821         memcpy(&cipherString[j], c.c_str(), c.size());
7822         j += c.size();
7823     }
7824 
7825     cipherString[j++] = 0;
7826     if (j != cipherStringLen) {
7827         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7828                                            "Internal error");
7829         return;
7830     }
7831 
7832     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
7833     if (!SSL_set_cipher_list(ssl, cipherString.get())) {
7834         ERR_clear_error();
7835         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7836                                            "Illegal cipher suite strings.");
7837         return;
7838     }
7839 }
7840 
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7841 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
7842                                               CONSCRYPT_UNUSED jobject ssl_holder) {
7843     CHECK_ERROR_QUEUE_ON_RETURN;
7844     SSL* ssl = to_SSL(env, ssl_address, true);
7845     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7846     if (ssl == nullptr) {
7847         return;
7848     }
7849     SSL_set_accept_state(ssl);
7850 }
7851 
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7852 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
7853                                                CONSCRYPT_UNUSED jobject ssl_holder) {
7854     CHECK_ERROR_QUEUE_ON_RETURN;
7855     SSL* ssl = to_SSL(env, ssl_address, true);
7856     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7857     if (ssl == nullptr) {
7858         return;
7859     }
7860     SSL_set_connect_state(ssl);
7861 }
7862 
7863 /**
7864  * Sets certificate expectations, especially for server to request client auth
7865  */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)7866 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
7867                                         CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
7868     CHECK_ERROR_QUEUE_ON_RETURN;
7869     SSL* ssl = to_SSL(env, ssl_address, true);
7870     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7871     if (ssl == nullptr) {
7872         return;
7873     }
7874     SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
7875 }
7876 
7877 /**
7878  * Sets the ciphers suites that are enabled in the SSL
7879  */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)7880 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
7881                                          CONSCRYPT_UNUSED jobject ssl_holder,
7882                                          jlong ssl_session_address) {
7883     CHECK_ERROR_QUEUE_ON_RETURN;
7884     SSL* ssl = to_SSL(env, ssl_address, true);
7885     if (ssl == nullptr) {
7886         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
7887         return;
7888     }
7889 
7890     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7891     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7892     if (ssl_session == nullptr) {
7893         return;
7894     }
7895 
7896     int ret = SSL_set_session(ssl, ssl_session);
7897     if (ret != 1) {
7898         /*
7899          * Translate the error, and throw if it turns out to be a real
7900          * problem.
7901          */
7902         int sslErrorCode = SSL_get_error(ssl, ret);
7903         if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7904             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7905                                                                "SSL session set");
7906         }
7907     }
7908     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
7909               ret);
7910 }
7911 
7912 /**
7913  * Sets the ciphers suites that are enabled in the SSL
7914  */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)7915 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
7916                                                           CONSCRYPT_UNUSED jobject ssl_holder,
7917                                                           jboolean creation_enabled) {
7918     CHECK_ERROR_QUEUE_ON_RETURN;
7919     SSL* ssl = to_SSL(env, ssl_address, true);
7920     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
7921               creation_enabled);
7922     if (ssl == nullptr) {
7923         return;
7924     }
7925 
7926     if (creation_enabled) {
7927         SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7928     } else {
7929         SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7930     }
7931 }
7932 
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7933 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
7934                                                 CONSCRYPT_UNUSED jobject ssl_holder) {
7935     CHECK_ERROR_QUEUE_ON_RETURN;
7936     SSL* ssl = to_SSL(env, ssl_address, true);
7937     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
7938     if (ssl == nullptr) {
7939         return JNI_FALSE;
7940     }
7941 
7942     int reused = SSL_session_reused(ssl);
7943     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
7944     return static_cast<jboolean>(reused);
7945 }
7946 
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7947 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
7948                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
7949     CHECK_ERROR_QUEUE_ON_RETURN;
7950     SSL* ssl = to_SSL(env, ssl_address, true);
7951     JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
7952     if (ssl == nullptr) {
7953         return;
7954     }
7955 
7956     SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
7957 }
7958 
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)7959 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
7960                                                   CONSCRYPT_UNUSED jobject ssl_holder,
7961                                                   jstring hostname) {
7962     CHECK_ERROR_QUEUE_ON_RETURN;
7963     SSL* ssl = to_SSL(env, ssl_address, true);
7964     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
7965     if (ssl == nullptr) {
7966         return;
7967     }
7968 
7969     ScopedUtfChars hostnameChars(env, hostname);
7970     if (hostnameChars.c_str() == nullptr) {
7971         return;
7972     }
7973     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
7974               hostnameChars.c_str());
7975 
7976     int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7977     if (ret != 1) {
7978         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7979                                                            "Error setting host name");
7980         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7981         return;
7982     }
7983     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7984 }
7985 
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7986 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
7987                                                CONSCRYPT_UNUSED jobject ssl_holder) {
7988     CHECK_ERROR_QUEUE_ON_RETURN;
7989     SSL* ssl = to_SSL(env, ssl_address, true);
7990     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7991     if (ssl == nullptr) {
7992         return nullptr;
7993     }
7994     const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7995     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7996     return env->NewStringUTF(servername);
7997 }
7998 
7999 /**
8000  * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8001  * which should take precedence.
8002  */
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)8003 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8004                                      const unsigned char* primary,
8005                                      const unsigned int primaryLength,
8006                                      const unsigned char* secondary,
8007                                      const unsigned int secondaryLength) {
8008     JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8009 
8010     int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8011                                        secondaryLength);
8012     switch (status) {
8013         case OPENSSL_NPN_NEGOTIATED:
8014             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8015             return SSL_TLSEXT_ERR_OK;
8016             break;
8017         case OPENSSL_NPN_UNSUPPORTED:
8018             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8019             break;
8020         case OPENSSL_NPN_NO_OVERLAP:
8021             JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8022             break;
8023     }
8024     return SSL_TLSEXT_ERR_NOACK;
8025 }
8026 
8027 /**
8028  * Calls out to an application-provided selector to choose the ALPN protocol.
8029  */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8030 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8031                                      unsigned char** out,
8032                                      unsigned char* outLen, const unsigned char* in,
8033                                      const unsigned int inLen) {
8034     // Copy the input array.
8035     ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8036     if (protocols.get() == nullptr) {
8037         JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8038         return SSL_TLSEXT_ERR_NOACK;
8039     }
8040     env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8041                             reinterpret_cast<const jbyte*>(in));
8042 
8043     // Invoke the selection method.
8044     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
8045     jmethodID methodID = env->GetMethodID(cls, "selectApplicationProtocol", "([B)I");
8046     jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8047 
8048     if (offset < 0) {
8049         JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8050         return SSL_TLSEXT_ERR_NOACK;
8051     }
8052 
8053     // Point the output to the selected protocol.
8054     *outLen = *(in + offset);
8055     *out = const_cast<unsigned char*>(in + offset + 1);
8056 
8057     return SSL_TLSEXT_ERR_OK;
8058 }
8059 
8060 /**
8061  * Callback for the server to select an ALPN protocol.
8062  */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8063 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8064                                 const unsigned char* in, unsigned int inLen, void*) {
8065     JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8066 
8067     AppData* appData = toAppData(ssl);
8068     if (appData == nullptr) {
8069         JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8070         return SSL_TLSEXT_ERR_NOACK;
8071     }
8072     JNIEnv* env = appData->env;
8073     if (env == nullptr) {
8074         CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8075         JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8076         return SSL_TLSEXT_ERR_NOACK;
8077     }
8078 
8079     if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8080                           !appData->hasApplicationProtocolSelector)) {
8081         if (out != nullptr && outLen != nullptr) {
8082             *out = nullptr;
8083             *outLen = 0;
8084         }
8085         JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8086         return SSL_TLSEXT_ERR_NOACK;
8087     }
8088 
8089     if (appData->hasApplicationProtocolSelector) {
8090         return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8091                                          const_cast<unsigned char**>(out), outLen, in, inLen);
8092     }
8093 
8094     return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8095                               reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8096                               static_cast<unsigned int>(appData->applicationProtocolsLength),
8097                               in, inLen);
8098 }
8099 
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8100 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8101                                                       CONSCRYPT_UNUSED jobject ssl_holder) {
8102     CHECK_ERROR_QUEUE_ON_RETURN;
8103     SSL* ssl = to_SSL(env, ssl_address, true);
8104     JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8105     if (ssl == nullptr) {
8106         return nullptr;
8107     }
8108     const jbyte* protocol;
8109     unsigned int protocolLength;
8110     SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8111                            &protocolLength);
8112     if (protocolLength == 0) {
8113         return nullptr;
8114     }
8115     jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8116     if (result != nullptr) {
8117         env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8118     }
8119     return result;
8120 }
8121 
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8122 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8123                                                  CONSCRYPT_UNUSED jobject ssl_holder,
8124                                                  jboolean client_mode, jbyteArray protocols) {
8125     CHECK_ERROR_QUEUE_ON_RETURN;
8126     SSL* ssl = to_SSL(env, ssl_address, true);
8127     if (ssl == nullptr) {
8128         return;
8129     }
8130     AppData* appData = toAppData(ssl);
8131     if (appData == nullptr) {
8132         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8133         JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8134         return;
8135     }
8136 
8137     if (protocols != nullptr) {
8138         if (client_mode) {
8139             ScopedByteArrayRO protosBytes(env, protocols);
8140             if (protosBytes.get() == nullptr) {
8141                 JNI_TRACE(
8142                         "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8143                         "protosBytes == null",
8144                         ssl, protocols);
8145                 return;
8146             }
8147 
8148             const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8149             int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8150             if (ret != 0) {
8151                 conscrypt::jniutil::throwSSLExceptionStr(env,
8152                                                          "Unable to set ALPN protocols for client");
8153                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8154                 return;
8155             }
8156         } else {
8157             // Server mode - configure the ALPN protocol selection callback.
8158             if (!appData->setApplicationProtocols(env, protocols)) {
8159                 conscrypt::jniutil::throwSSLExceptionStr(env,
8160                                                          "Unable to set ALPN protocols for server");
8161                 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8162                 return;
8163             }
8164             SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8165         }
8166     }
8167 }
8168 
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8169 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8170                                                            CONSCRYPT_UNUSED jobject ssl_holder,
8171                                                            jboolean hasSelector) {
8172     CHECK_ERROR_QUEUE_ON_RETURN;
8173     SSL* ssl = to_SSL(env, ssl_address, true);
8174     JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8175               hasSelector);
8176     if (ssl == nullptr) {
8177         return;
8178     }
8179     AppData* appData = toAppData(ssl);
8180     if (appData == nullptr) {
8181         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8182         JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8183         return;
8184     }
8185 
8186     appData->hasApplicationProtocolSelector = hasSelector;
8187     if (hasSelector) {
8188         SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8189     }
8190 }
8191 
8192 /**
8193  * Perform SSL handshake
8194  */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8195 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8196                                           CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8197                                           jobject shc, jint timeout_millis) {
8198     CHECK_ERROR_QUEUE_ON_RETURN;
8199     SSL* ssl = to_SSL(env, ssl_address, true);
8200     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8201               shc, timeout_millis);
8202     if (ssl == nullptr) {
8203         return;
8204     }
8205     if (fdObject == nullptr) {
8206         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8207         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8208         return;
8209     }
8210     if (shc == nullptr) {
8211         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8212         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8213                   ssl);
8214         return;
8215     }
8216 
8217     NetFd fd(env, fdObject);
8218     if (fd.isClosed()) {
8219         // SocketException thrown by NetFd.isClosed
8220         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8221         return;
8222     }
8223 
8224     int ret = SSL_set_fd(ssl, fd.get());
8225     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8226 
8227     if (ret != 1) {
8228         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8229                                                            "Error setting the file descriptor");
8230         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8231         return;
8232     }
8233 
8234     /*
8235      * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8236      * forever and we can use select() to find out if the socket is ready.
8237      */
8238     if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8239         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8240         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8241         return;
8242     }
8243 
8244     AppData* appData = toAppData(ssl);
8245     if (appData == nullptr) {
8246         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8247         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8248         return;
8249     }
8250 
8251     ret = 0;
8252     SslError sslError;
8253     while (appData->aliveAndKicking) {
8254         errno = 0;
8255 
8256         if (!appData->setCallbackState(env, shc, fdObject)) {
8257             // SocketException thrown by NetFd.isClosed
8258             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8259             return;
8260         }
8261         ret = SSL_do_handshake(ssl);
8262         appData->clearCallbackState();
8263         // cert_verify_callback threw exception
8264         if (env->ExceptionCheck()) {
8265             ERR_clear_error();
8266             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8267             return;
8268         }
8269         // success case
8270         if (ret == 1) {
8271             break;
8272         }
8273         // retry case
8274         if (errno == EINTR) {
8275             continue;
8276         }
8277         // error case
8278         sslError.reset(ssl, ret);
8279         JNI_TRACE(
8280                 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8281                 "timeout_millis=%d",
8282                 ssl, ret, errno, sslError.get(), timeout_millis);
8283 
8284         /*
8285          * If SSL_do_handshake doesn't succeed due to the socket being
8286          * either unreadable or unwritable, we use sslSelect to
8287          * wait for it to become ready. If that doesn't happen
8288          * before the specified timeout or an error occurs, we
8289          * cancel the handshake. Otherwise we try the SSL_connect
8290          * again.
8291          */
8292         if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8293             appData->waitingThreads++;
8294             int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8295 
8296             if (selectResult == THROWN_EXCEPTION) {
8297                 // SocketException thrown by NetFd.isClosed
8298                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8299                 return;
8300             }
8301             if (selectResult == -1) {
8302                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8303                         env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8304                         conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8305                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8306                           ssl);
8307                 return;
8308             }
8309             if (selectResult == 0) {
8310                 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8311                 ERR_clear_error();
8312                 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8313                           ssl);
8314                 return;
8315             }
8316         } else {
8317             // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8318             break;
8319         }
8320     }
8321 
8322     // clean error. See SSL_do_handshake(3SSL) man page.
8323     if (ret == 0) {
8324         /*
8325          * The other side closed the socket before the handshake could be
8326          * completed, but everything is within the bounds of the TLS protocol.
8327          * We still might want to find out the real reason of the failure.
8328          */
8329         if (sslError.get() == SSL_ERROR_NONE ||
8330             (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8331             (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8332             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8333         } else {
8334             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8335                     env, ssl, sslError.release(), "SSL handshake terminated",
8336                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8337         }
8338         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8339         return;
8340     }
8341 
8342     // unclean error. See SSL_do_handshake(3SSL) man page.
8343     if (ret < 0) {
8344         /*
8345          * Translate the error and throw exception. We are sure it is an error
8346          * at this point.
8347          */
8348         conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8349                 env, ssl, sslError.release(), "SSL handshake aborted",
8350                 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8351         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
8352         return;
8353     }
8354     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
8355 }
8356 
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8357 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
8358                                                    CONSCRYPT_UNUSED jobject ssl_holder) {
8359     CHECK_ERROR_QUEUE_ON_RETURN;
8360     SSL* ssl = to_SSL(env, ssl_address, true);
8361     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
8362     if (ssl == nullptr) {
8363         return nullptr;
8364     }
8365     const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
8366     if (cipher == nullptr) {
8367         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
8368         return nullptr;
8369     }
8370     const char* name = SSL_CIPHER_standard_name(cipher);
8371     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
8372     return env->NewStringUTF(name);
8373 }
8374 
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8375 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
8376                                             CONSCRYPT_UNUSED jobject ssl_holder) {
8377     CHECK_ERROR_QUEUE_ON_RETURN;
8378     SSL* ssl = to_SSL(env, ssl_address, true);
8379     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
8380     if (ssl == nullptr) {
8381         return nullptr;
8382     }
8383     const char* protocol = SSL_get_version(ssl);
8384     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
8385     return env->NewStringUTF(protocol);
8386 }
8387 
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8388 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
8389                                                             CONSCRYPT_UNUSED jobject ssl_holder) {
8390     CHECK_ERROR_QUEUE_ON_RETURN;
8391     SSL* ssl = to_SSL(env, ssl_address, true);
8392     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
8393     if (ssl == nullptr) {
8394         return nullptr;
8395     }
8396 
8397     const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
8398     if (chain == nullptr) {
8399         return nullptr;
8400     }
8401 
8402     ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
8403     if (array.get() == nullptr) {
8404         return nullptr;
8405     }
8406 
8407     JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
8408     return array.release();
8409 }
8410 
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)8411 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8412                    SslError* sslError, int read_timeout_millis) {
8413     JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8414 
8415     if (len == 0) {
8416         // Don't bother doing anything in this case.
8417         return 0;
8418     }
8419 
8420     BIO* rbio = SSL_get_rbio(ssl);
8421     BIO* wbio = SSL_get_wbio(ssl);
8422 
8423     AppData* appData = toAppData(ssl);
8424     JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8425     if (appData == nullptr) {
8426         return THROW_SSLEXCEPTION;
8427     }
8428 
8429     while (appData->aliveAndKicking) {
8430         errno = 0;
8431 
8432         std::unique_lock<std::mutex> appDataLock(appData->mutex);
8433 
8434         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8435             !SSL_renegotiate_pending(ssl)) {
8436             JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
8437                       SSL_state_string_long(ssl));
8438             return THROW_SSLEXCEPTION;
8439         }
8440 
8441         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8442 
8443         if (!appData->setCallbackState(env, shc, fdObject)) {
8444             return THROWN_EXCEPTION;
8445         }
8446         int result = SSL_read(ssl, buf, len);
8447         appData->clearCallbackState();
8448         // callbacks can happen if server requests renegotiation
8449         if (env->ExceptionCheck()) {
8450             JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8451             return THROWN_EXCEPTION;
8452         }
8453         sslError->reset(ssl, result);
8454 
8455         JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
8456         if (conscrypt::trace::kWithJniTraceData) {
8457             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8458                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8459                 size_t n = result - i;
8460                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8461                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
8462                 }
8463                 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8464             }
8465         }
8466 
8467         // If we have been successful in moving data around, check whether it
8468         // might make sense to wake up other blocked threads, so they can give
8469         // it a try, too.
8470         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8471             appData->waitingThreads > 0) {
8472             sslNotify(appData);
8473         }
8474 
8475         // If we are blocked by the underlying socket, tell the world that
8476         // there will be one more waiting thread now.
8477         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8478             appData->waitingThreads++;
8479         }
8480 
8481         appDataLock.unlock();
8482 
8483         switch (sslError->get()) {
8484             // Successfully read at least one byte.
8485             case SSL_ERROR_NONE: {
8486                 return result;
8487             }
8488 
8489             // Read zero bytes. End of stream reached.
8490             case SSL_ERROR_ZERO_RETURN: {
8491                 return -1;
8492             }
8493 
8494             // Need to wait for availability of underlying layer, then retry.
8495             case SSL_ERROR_WANT_READ:
8496             case SSL_ERROR_WANT_WRITE: {
8497                 int selectResult =
8498                         sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
8499                 if (selectResult == THROWN_EXCEPTION) {
8500                     return THROWN_EXCEPTION;
8501                 }
8502                 if (selectResult == -1) {
8503                     return THROW_SSLEXCEPTION;
8504                 }
8505                 if (selectResult == 0) {
8506                     return THROW_SOCKETTIMEOUTEXCEPTION;
8507                 }
8508 
8509                 break;
8510             }
8511 
8512             // A problem occurred during a system call, but this is not
8513             // necessarily an error.
8514             case SSL_ERROR_SYSCALL: {
8515                 // Connection closed without proper shutdown. Tell caller we
8516                 // have reached end-of-stream.
8517                 if (result == 0) {
8518                     return -1;
8519                 }
8520 
8521                 // System call has been interrupted. Simply retry.
8522                 if (errno == EINTR) {
8523                     break;
8524                 }
8525 
8526                 // Note that for all other system call errors we fall through
8527                 // to the default case, which results in an Exception.
8528                 FALLTHROUGH_INTENDED;
8529             }
8530 
8531             // Everything else is basically an error.
8532             default: { return THROW_SSLEXCEPTION; }
8533         }
8534     }
8535 
8536     return -1;
8537 }
8538 
8539 /**
8540  * OpenSSL read function (2): read into buffer at offset n chunks.
8541  * Returns the number of bytes read (success) or value <= 0 (failure).
8542  */
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)8543 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
8544                                   CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8545                                   jobject shc, jbyteArray b, jint offset, jint len,
8546                                   jint read_timeout_millis) {
8547     CHECK_ERROR_QUEUE_ON_RETURN;
8548     SSL* ssl = to_SSL(env, ssl_address, true);
8549     JNI_TRACE(
8550             "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
8551             "read_timeout_millis=%d",
8552             ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8553     if (ssl == nullptr) {
8554         return 0;
8555     }
8556     if (fdObject == nullptr) {
8557         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8558         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8559         return 0;
8560     }
8561     if (shc == nullptr) {
8562         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8563         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8564         return 0;
8565     }
8566     if (b == nullptr) {
8567         conscrypt::jniutil::throwNullPointerException(env, "b == null");
8568         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
8569         return 0;
8570     }
8571 
8572     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8573     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8574         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8575         JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
8576         return 0;
8577     }
8578 
8579     SslError sslError;
8580     int ret;
8581     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8582         if (len <= 1024) {
8583             // Allocate small buffers on the stack for performance.
8584             jbyte buf[1024];
8585             ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
8586                           read_timeout_millis);
8587             if (ret > 0) {
8588                 // Don't bother applying changes if issues were encountered.
8589                 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
8590             }
8591         } else {
8592             // Allocate larger buffers on the heap.
8593             // ARRAY_CHUNK_INVALID above ensures that len >= 0.
8594             jint remaining = len;
8595             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8596             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8597             // TODO(flooey): Use new(std::nothrow).
8598             if (buf.get() == nullptr) {
8599                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8600                 return 0;
8601             }
8602             // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
8603             // by the number of internal calls to sslRead() below.
8604             ret = 0;
8605             while (remaining > 0) {
8606                 jint temp_ret;
8607                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8608                 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
8609                                    chunk_size, &sslError, read_timeout_millis);
8610                 if (temp_ret < 0) {
8611                     if (ret > 0) {
8612                         // We've already read some bytes; attempt to preserve them if this is an
8613                         // "expected" error.
8614                         if (temp_ret == -1) {
8615                             // EOF
8616                             break;
8617                         } else if (temp_ret == THROWN_EXCEPTION) {
8618                             // FD closed. Subsequent calls to sslRead should reproduce the
8619                             // exception.
8620                             env->ExceptionClear();
8621                             break;
8622                         }
8623                     }
8624                     // An error was encountered. Handle below.
8625                     ret = temp_ret;
8626                     break;
8627                 }
8628                 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
8629                 if (env->ExceptionCheck()) {
8630                     // Error committing changes to JVM.
8631                     return -1;
8632                 }
8633                 // Accumulate bytes read.
8634                 ret += temp_ret;
8635                 offset += temp_ret;
8636                 remaining -= temp_ret;
8637                 if (temp_ret < chunk_size) {
8638                     // sslRead isn't able to fulfill our request right now.
8639                     break;
8640                 }
8641             }
8642         }
8643     } else {
8644         ScopedByteArrayRW bytes(env, b);
8645         if (bytes.get() == nullptr) {
8646             JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8647             return 0;
8648         }
8649 
8650         ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8651                       &sslError, read_timeout_millis);
8652     }
8653 
8654     int result;
8655     switch (ret) {
8656         case THROW_SSLEXCEPTION:
8657             // See sslRead() regarding improper failure to handle normal cases.
8658             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8659                                                                "Read error");
8660             result = -1;
8661             break;
8662         case THROW_SOCKETTIMEOUTEXCEPTION:
8663             conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
8664             result = -1;
8665             break;
8666         case THROWN_EXCEPTION:
8667             // SocketException thrown by NetFd.isClosed
8668             // or RuntimeException thrown by callback
8669             result = -1;
8670             break;
8671         default:
8672             result = ret;
8673             break;
8674     }
8675 
8676     JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8677     return result;
8678 }
8679 
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)8680 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8681                     SslError* sslError, int write_timeout_millis) {
8682     JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
8683               write_timeout_millis);
8684 
8685     if (len == 0) {
8686         // Don't bother doing anything in this case.
8687         return 0;
8688     }
8689 
8690     BIO* rbio = SSL_get_rbio(ssl);
8691     BIO* wbio = SSL_get_wbio(ssl);
8692 
8693     AppData* appData = toAppData(ssl);
8694     JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8695     if (appData == nullptr) {
8696         return THROW_SSLEXCEPTION;
8697     }
8698 
8699     int count = len;
8700 
8701     while (appData->aliveAndKicking && len > 0) {
8702         errno = 0;
8703 
8704         std::unique_lock<std::mutex> appDataLock(appData->mutex);
8705 
8706         if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8707             !SSL_renegotiate_pending(ssl)) {
8708             JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
8709                       SSL_state_string_long(ssl));
8710             return THROW_SSLEXCEPTION;
8711         }
8712 
8713         size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8714 
8715         if (!appData->setCallbackState(env, shc, fdObject)) {
8716             return THROWN_EXCEPTION;
8717         }
8718         JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
8719         int result = SSL_write(ssl, buf, len);
8720         appData->clearCallbackState();
8721         // callbacks can happen if server requests renegotiation
8722         if (env->ExceptionCheck()) {
8723             JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8724             return THROWN_EXCEPTION;
8725         }
8726         sslError->reset(ssl, result);
8727 
8728         JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
8729         if (conscrypt::trace::kWithJniTraceData) {
8730             for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8731                  i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8732                 size_t n = result - i;
8733                 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8734                     n = conscrypt::trace::kWithJniTraceDataChunkSize;
8735                 }
8736                 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8737             }
8738         }
8739 
8740         // If we have been successful in moving data around, check whether it
8741         // might make sense to wake up other blocked threads, so they can give
8742         // it a try, too.
8743         if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8744             appData->waitingThreads > 0) {
8745             sslNotify(appData);
8746         }
8747 
8748         // If we are blocked by the underlying socket, tell the world that
8749         // there will be one more waiting thread now.
8750         if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8751             appData->waitingThreads++;
8752         }
8753 
8754         appDataLock.unlock();
8755 
8756         switch (sslError->get()) {
8757             // Successfully wrote at least one byte.
8758             case SSL_ERROR_NONE: {
8759                 buf += result;
8760                 len -= result;
8761                 break;
8762             }
8763 
8764             // Wrote zero bytes. End of stream reached.
8765             case SSL_ERROR_ZERO_RETURN: {
8766                 return -1;
8767             }
8768 
8769             // Need to wait for availability of underlying layer, then retry.
8770             // The concept of a write timeout doesn't really make sense, and
8771             // it's also not standard Java behavior, so we wait forever here.
8772             case SSL_ERROR_WANT_READ:
8773             case SSL_ERROR_WANT_WRITE: {
8774                 int selectResult =
8775                         sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
8776                 if (selectResult == THROWN_EXCEPTION) {
8777                     return THROWN_EXCEPTION;
8778                 }
8779                 if (selectResult == -1) {
8780                     return THROW_SSLEXCEPTION;
8781                 }
8782                 if (selectResult == 0) {
8783                     return THROW_SOCKETTIMEOUTEXCEPTION;
8784                 }
8785 
8786                 break;
8787             }
8788 
8789             // A problem occurred during a system call, but this is not
8790             // necessarily an error.
8791             case SSL_ERROR_SYSCALL: {
8792                 // Connection closed without proper shutdown. Tell caller we
8793                 // have reached end-of-stream.
8794                 if (result == 0) {
8795                     return -1;
8796                 }
8797 
8798                 // System call has been interrupted. Simply retry.
8799                 if (errno == EINTR) {
8800                     break;
8801                 }
8802 
8803                 // Note that for all other system call errors we fall through
8804                 // to the default case, which results in an Exception.
8805                 FALLTHROUGH_INTENDED;
8806             }
8807 
8808             // Everything else is basically an error.
8809             default: { return THROW_SSLEXCEPTION; }
8810         }
8811     }
8812     JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8813 
8814     return count;
8815 }
8816 
8817 /**
8818  * OpenSSL write function (2): write into buffer at offset n chunks.
8819  */
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)8820 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
8821                                    CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8822                                    jobject shc, jbyteArray b, jint offset, jint len,
8823                                    jint write_timeout_millis) {
8824     CHECK_ERROR_QUEUE_ON_RETURN;
8825     SSL* ssl = to_SSL(env, ssl_address, true);
8826     JNI_TRACE(
8827             "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
8828             "write_timeout_millis=%d",
8829             ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8830     if (ssl == nullptr) {
8831         return;
8832     }
8833     if (fdObject == nullptr) {
8834         conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8835         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8836         return;
8837     }
8838     if (shc == nullptr) {
8839         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8840         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8841         return;
8842     }
8843     if (b == nullptr) {
8844         conscrypt::jniutil::throwNullPointerException(env, "b == null");
8845         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
8846         return;
8847     }
8848 
8849     size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8850     if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8851         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8852         JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
8853         return;
8854     }
8855 
8856     SslError sslError;
8857     int ret;
8858     if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8859         if (len <= 1024) {
8860             jbyte buf[1024];
8861             env->GetByteArrayRegion(b, offset, len, buf);
8862             ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
8863                            &sslError, write_timeout_millis);
8864         } else {
8865             // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
8866             jint remaining = len;
8867             jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8868             std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8869             if (buf.get() == nullptr) {
8870                 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8871                 return;
8872             }
8873             while (remaining > 0) {
8874                 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8875                 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
8876                 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
8877                                chunk_size, &sslError, write_timeout_millis);
8878                 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
8879                     ret == THROWN_EXCEPTION) {
8880                     // Encountered an error. Terminate early and handle below.
8881                     break;
8882                 }
8883                 offset += ret;
8884                 remaining -= ret;
8885             }
8886         }
8887     } else {
8888         ScopedByteArrayRO bytes(env, b);
8889         if (bytes.get() == nullptr) {
8890             JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8891             return;
8892         }
8893         ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8894                        len, &sslError, write_timeout_millis);
8895     }
8896 
8897     switch (ret) {
8898         case THROW_SSLEXCEPTION:
8899             // See sslWrite() regarding improper failure to handle normal cases.
8900             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8901                                                                "Write error");
8902             break;
8903         case THROW_SOCKETTIMEOUTEXCEPTION:
8904             conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
8905             break;
8906         case THROWN_EXCEPTION:
8907             // SocketException thrown by NetFd.isClosed
8908             break;
8909         default:
8910             break;
8911     }
8912 }
8913 
8914 /**
8915  * Interrupt any pending I/O before closing the socket.
8916  */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8917 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
8918                                        CONSCRYPT_UNUSED jobject ssl_holder) {
8919     CHECK_ERROR_QUEUE_ON_RETURN;
8920     SSL* ssl = to_SSL(env, ssl_address, false);
8921     JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
8922     if (ssl == nullptr) {
8923         return;
8924     }
8925 
8926     /*
8927      * Mark the connection as quasi-dead, then send something to the emergency
8928      * file descriptor, so any blocking select() calls are woken up.
8929      */
8930     AppData* appData = toAppData(ssl);
8931     if (appData != nullptr) {
8932         appData->aliveAndKicking = false;
8933 
8934         // At most two threads can be waiting.
8935         sslNotify(appData);
8936         sslNotify(appData);
8937     }
8938 }
8939 
8940 /**
8941  * OpenSSL close SSL socket function.
8942  */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)8943 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
8944                                       CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8945                                       jobject shc) {
8946     CHECK_ERROR_QUEUE_ON_RETURN;
8947     SSL* ssl = to_SSL(env, ssl_address, false);
8948     JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
8949     if (ssl == nullptr) {
8950         return;
8951     }
8952     if (fdObject == nullptr) {
8953         return;
8954     }
8955     if (shc == nullptr) {
8956         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8957         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
8958         return;
8959     }
8960 
8961     AppData* appData = toAppData(ssl);
8962     if (appData != nullptr) {
8963         if (!appData->setCallbackState(env, shc, fdObject)) {
8964             // SocketException thrown by NetFd.isClosed
8965             ERR_clear_error();
8966             return;
8967         }
8968 
8969         /*
8970          * Try to make socket blocking again. OpenSSL literature recommends this.
8971          */
8972         int fd = SSL_get_fd(ssl);
8973         JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
8974 #ifndef _WIN32
8975         if (fd != -1) {
8976             conscrypt::netutil::setBlocking(fd, true);
8977         }
8978 #endif
8979 
8980         int ret = SSL_shutdown(ssl);
8981         appData->clearCallbackState();
8982         // callbacks can happen if server requests renegotiation
8983         if (env->ExceptionCheck()) {
8984             JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
8985             return;
8986         }
8987         switch (ret) {
8988             case 0:
8989                 /*
8990                  * Shutdown was not successful (yet), but there also
8991                  * is no error. Since we can't know whether the remote
8992                  * server is actually still there, and we don't want to
8993                  * get stuck forever in a second SSL_shutdown() call, we
8994                  * simply return. This is not security a problem as long
8995                  * as we close the underlying socket, which we actually
8996                  * do, because that's where we are just coming from.
8997                  */
8998                 break;
8999             case 1:
9000                 /*
9001                  * Shutdown was successful. We can safely return. Hooray!
9002                  */
9003                 break;
9004             default:
9005                 /*
9006                  * Everything else is a real error condition. We should
9007                  * let the Java layer know about this by throwing an
9008                  * exception.
9009                  */
9010                 int sslError = SSL_get_error(ssl, ret);
9011                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9012                                                                    "SSL shutdown failed");
9013                 break;
9014         }
9015     }
9016 
9017     ERR_clear_error();
9018 }
9019 
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9020 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9021                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9022     CHECK_ERROR_QUEUE_ON_RETURN;
9023     const SSL* ssl = to_SSL(env, ssl_address, true);
9024     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9025     if (ssl == nullptr) {
9026         return 0;
9027     }
9028 
9029     int status = SSL_get_shutdown(ssl);
9030     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9031     return static_cast<jint>(status);
9032 }
9033 
9034 /**
9035  * public static native void SSL_free(long ssl);
9036  */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9037 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9038                                   CONSCRYPT_UNUSED jobject ssl_holder) {
9039     CHECK_ERROR_QUEUE_ON_RETURN;
9040     SSL* ssl = to_SSL(env, ssl_address, true);
9041     JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9042     if (ssl == nullptr) {
9043         return;
9044     }
9045 
9046     AppData* appData = toAppData(ssl);
9047     SSL_set_app_data(ssl, nullptr);
9048     delete appData;
9049     SSL_free(ssl);
9050 }
9051 
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9052 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9053     unsigned int length;
9054     const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9055     JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9056     if (id && length > 0) {
9057         jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9058         if (result != nullptr) {
9059             const jbyte* src = reinterpret_cast<const jbyte*>(id);
9060             env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9061         }
9062         return result;
9063     }
9064     return nullptr;
9065 }
9066 
9067 /**
9068  * Gets and returns in a byte array the ID of the actual SSL session.
9069  */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9070 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9071                                                       jlong ssl_session_address) {
9072     CHECK_ERROR_QUEUE_ON_RETURN;
9073     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9074     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9075     if (ssl_session == nullptr) {
9076         return nullptr;
9077     }
9078     jbyteArray result = get_session_id(env, ssl_session);
9079     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9080     return result;
9081 }
9082 
9083 /**
9084  * Gets and returns in a long integer the creation's time of the
9085  * actual SSL session.
9086  */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9087 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9088     CHECK_ERROR_QUEUE_ON_RETURN;
9089     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9090     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9091     if (ssl_session == nullptr) {
9092         return 0;
9093     }
9094     // result must be jlong, not long or *1000 will overflow
9095     jlong result = SSL_SESSION_get_time(ssl_session);
9096     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9097     // NOLINTNEXTLINE(runtime/int)
9098     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9099               (long long)result);  // NOLINT(runtime/int)
9100     return result;
9101 }
9102 
9103 /**
9104  * Gets and returns in a long integer the creation's time of the
9105  * actual SSL session.
9106  */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9107 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9108                                        CONSCRYPT_UNUSED jobject ssl_holder) {
9109     CHECK_ERROR_QUEUE_ON_RETURN;
9110     SSL* ssl = to_SSL(env, ssl_address, true);
9111     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9112     if (ssl == nullptr) {
9113         return 0;
9114     }
9115 
9116     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9117     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9118     if (ssl_session == nullptr) {
9119         // BoringSSL does not protect against a NULL session.
9120         return 0;
9121     }
9122     // result must be jlong, not long or *1000 will overflow
9123     jlong result = SSL_SESSION_get_time(ssl_session);
9124     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9125     // NOLINTNEXTLINE(runtime/int)
9126     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9127     return result;
9128 }
9129 
9130 /**
9131  * Sets the timeout on the SSL session.
9132  */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9133 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9134                                           CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9135     CHECK_ERROR_QUEUE_ON_RETURN;
9136     SSL* ssl = to_SSL(env, ssl_address, true);
9137     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9138     if (ssl == nullptr) {
9139         return 0;
9140     }
9141 
9142     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9143     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9144     if (ssl_session == nullptr) {
9145         // BoringSSL does not protect against a NULL session.
9146         return 0;
9147     }
9148 
9149     // Convert to seconds
9150     static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9151     uint32_t timeout = static_cast<uint32_t>(
9152             std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9153     return SSL_set_timeout(ssl_session, timeout);
9154 }
9155 
9156 /**
9157  * Gets the timeout for the SSL session.
9158  */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9159 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9160                                           CONSCRYPT_UNUSED jobject ssl_holder) {
9161     CHECK_ERROR_QUEUE_ON_RETURN;
9162     SSL* ssl = to_SSL(env, ssl_address, true);
9163     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9164     if (ssl == nullptr) {
9165         return 0;
9166     }
9167 
9168     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9169     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9170     if (ssl_session == nullptr) {
9171         // BoringSSL does not protect against a NULL session.
9172         return 0;
9173     }
9174 
9175     jlong result = SSL_get_timeout(ssl_session);
9176     result *= 1000;  // OpenSSL uses seconds, Java uses milliseconds.
9177     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9178               (long long)result)  // NOLINT(runtime/int);
9179     return result;
9180 }
9181 
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9182 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9183                                                               jint signatureAlg) {
9184     CHECK_ERROR_QUEUE_ON_RETURN;
9185     return SSL_get_signature_algorithm_key_type(signatureAlg);
9186 }
9187 
9188 /**
9189  * Gets the timeout for the SSL session.
9190  */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9191 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9192     CHECK_ERROR_QUEUE_ON_RETURN;
9193     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9194     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9195     if (ssl_session == nullptr) {
9196         return 0;
9197     }
9198 
9199     return SSL_get_timeout(ssl_session);
9200 }
9201 
9202 /**
9203  * Gets the ID for the SSL session, or null if no session is currently available.
9204  */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9205 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9206                                               CONSCRYPT_UNUSED jobject ssl_holder) {
9207     CHECK_ERROR_QUEUE_ON_RETURN;
9208     SSL* ssl = to_SSL(env, ssl_address, true);
9209     JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9210     if (ssl == nullptr) {
9211         return nullptr;
9212     }
9213 
9214     SSL_SESSION* ssl_session = SSL_get_session(ssl);
9215     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9216     if (ssl_session == nullptr) {
9217         return nullptr;
9218     }
9219     jbyteArray result = get_session_id(env, ssl_session);
9220     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9221     return result;
9222 }
9223 
9224 /**
9225  * Gets and returns in a string the version of the SSL protocol. If it
9226  * returns the string "unknown" it means that no connection is established.
9227  */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9228 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9229                                                     jlong ssl_session_address) {
9230     CHECK_ERROR_QUEUE_ON_RETURN;
9231     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9232     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9233     if (ssl_session == nullptr) {
9234         return nullptr;
9235     }
9236     const char* protocol = SSL_SESSION_get_version(ssl_session);
9237     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9238     return env->NewStringUTF(protocol);
9239 }
9240 
9241 /**
9242  * Gets and returns in a string the cipher negotiated for the SSL session.
9243  */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9244 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9245     CHECK_ERROR_QUEUE_ON_RETURN;
9246     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9247     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9248     if (ssl_session == nullptr) {
9249         return nullptr;
9250     }
9251     const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9252     const char* name = SSL_CIPHER_standard_name(cipher);
9253     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9254     return env->NewStringUTF(name);
9255 }
9256 
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9257 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9258                                                               jlong ssl_session_address) {
9259     CHECK_ERROR_QUEUE_ON_RETURN;
9260     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9261     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9262     if (ssl_session == nullptr) {
9263         return JNI_FALSE;
9264     }
9265     int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9266     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9267               single_use);
9268     return single_use ? JNI_TRUE : JNI_FALSE;
9269 }
9270 
9271 /**
9272  * Increments the reference count of the session.
9273  */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9274 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9275     CHECK_ERROR_QUEUE_ON_RETURN;
9276     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9277     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9278     if (ssl_session == nullptr) {
9279         return;
9280     }
9281     SSL_SESSION_up_ref(ssl_session);
9282 }
9283 
9284 /**
9285  * Frees the SSL session.
9286  */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9287 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9288     CHECK_ERROR_QUEUE_ON_RETURN;
9289     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9290     JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9291     if (ssl_session == nullptr) {
9292         return;
9293     }
9294     SSL_SESSION_free(ssl_session);
9295 }
9296 
9297 /**
9298  * Serializes the native state of the session (ID, cipher, and keys but
9299  * not certificates). Returns a byte[] containing the DER-encoded state.
9300  * See apache mod_ssl.
9301  */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9302 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9303     CHECK_ERROR_QUEUE_ON_RETURN;
9304     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9305     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9306     if (ssl_session == nullptr) {
9307         return nullptr;
9308     }
9309     return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9310 }
9311 
9312 /**
9313  * Deserialize the session.
9314  */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9315 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9316     CHECK_ERROR_QUEUE_ON_RETURN;
9317     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9318 
9319     ScopedByteArrayRO bytes(env, javaBytes);
9320     if (bytes.get() == nullptr) {
9321         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9322         return 0;
9323     }
9324     const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9325     // NOLINTNEXTLINE(runtime/int)
9326     SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9327 
9328     if (ssl_session == nullptr ||
9329         ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9330         conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9331                                                              conscrypt::jniutil::throwIOException);
9332         JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9333         return 0L;
9334     }
9335 
9336     JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9337     return reinterpret_cast<uintptr_t>(ssl_session);
9338 }
9339 
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9340 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9341     CHECK_ERROR_QUEUE_ON_RETURN;
9342     const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, true);
9343     const char* kx_name = nullptr;
9344 
9345     kx_name = SSL_CIPHER_get_kx_name(cipher);
9346 
9347     return env->NewStringUTF(kx_name);
9348 }
9349 
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)9350 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
9351     CHECK_ERROR_QUEUE_ON_RETURN;
9352     ScopedUtfChars selector(env, selectorJava);
9353     if (selector.c_str() == nullptr) {
9354         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9355                                            "selector == null");
9356         return nullptr;
9357     }
9358 
9359     JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
9360 
9361     bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
9362     bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
9363 
9364     if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
9365         conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9366                                            "Unable to set SSL cipher list");
9367         return nullptr;
9368     }
9369     STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
9370 
9371     size_t size = sk_SSL_CIPHER_num(ciphers);
9372     ScopedLocalRef<jobjectArray> cipherNamesArray(
9373             env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
9374                                      nullptr));
9375     if (cipherNamesArray.get() == nullptr) {
9376         return nullptr;
9377     }
9378 
9379     // Return an array of standard and OpenSSL name pairs.
9380     for (size_t i = 0; i < size; i++) {
9381         const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
9382         ScopedLocalRef<jstring> cipherName(env,
9383                                            env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
9384         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
9385                                    cipherName.get());
9386 
9387         ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
9388         env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
9389                                    opensslName.get());
9390     }
9391 
9392     JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
9393               2 * size);
9394     return cipherNamesArray.release();
9395 }
9396 
9397 /**
9398  * Compare the given CertID with a certificate and it's issuer.
9399  * True is returned if the CertID matches.
9400  */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)9401 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
9402     // Get the hash algorithm used by this CertID
9403     CBS hash_algorithm, hash;
9404     if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
9405         !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
9406         return false;
9407     }
9408 
9409     // Get the issuer's name hash from the CertID
9410     CBS issuer_name_hash;
9411     if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
9412         return false;
9413     }
9414 
9415     // Get the issuer's key hash from the CertID
9416     CBS issuer_key_hash;
9417     if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
9418         return false;
9419     }
9420 
9421     // Get the serial number from the CertID
9422     CBS serial;
9423     if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
9424         return false;
9425     }
9426 
9427     // Compare the certificate's serial number with the one from the Cert ID
9428     const uint8_t* p = CBS_data(&serial);
9429     bssl::UniquePtr<ASN1_INTEGER> serial_number(
9430             c2i_ASN1_INTEGER(nullptr, &p,
9431                              static_cast<long>(CBS_len(&serial))));  // NOLINT(runtime/int)
9432     const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
9433     if (serial_number.get() == nullptr ||
9434         ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
9435         return false;
9436     }
9437 
9438     // Find the hash algorithm to be used
9439     const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
9440     if (digest == nullptr) {
9441         return false;
9442     }
9443 
9444     // Hash the issuer's name and compare the hash with the one from the Cert ID
9445     uint8_t md[EVP_MAX_MD_SIZE];
9446     const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
9447     if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
9448         !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
9449         return false;
9450     }
9451 
9452     // Same thing with the issuer's key
9453     const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
9454     if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
9455                     static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
9456                     nullptr) ||
9457         !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
9458         return false;
9459     }
9460 
9461     return true;
9462 }
9463 
9464 /**
9465  * Get a SingleResponse whose CertID matches the given certificate and issuer from a
9466  * SEQUENCE OF SingleResponse.
9467  *
9468  * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
9469  * error occured or no response matches the certificate, false is returned and |out_single_response|
9470  * is unchanged.
9471  */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)9472 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
9473                                       CBS* out_single_response) {
9474     // Iterate over all the SingleResponses, until one matches the certificate
9475     while (CBS_len(responses) > 0) {
9476         // Get the next available SingleResponse from the sequence
9477         CBS single_response;
9478         if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
9479             return false;
9480         }
9481 
9482         // Make a copy of the stream so we pass it back to the caller
9483         CBS single_response_original = single_response;
9484 
9485         // Get the SingleResponse's CertID
9486         // If this fails ignore the current response and move to the next one
9487         CBS cert_id;
9488         if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
9489             continue;
9490         }
9491 
9492         // Compare the CertID with the given certificate and issuer
9493         if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
9494             *out_single_response = single_response_original;
9495             return true;
9496         }
9497     }
9498 
9499     return false;
9500 }
9501 
9502 /**
9503  * Get the BasicOCSPResponse from an OCSPResponse.
9504  * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
9505  * returned.
9506  */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)9507 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
9508     CBS tagged_response_bytes, response_bytes, response_type, response;
9509 
9510     // Get the ResponseBytes out of the OCSPResponse
9511     if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
9512         !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
9513                       CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9514         !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
9515         return false;
9516     }
9517 
9518     // Parse the response type and data out of the ResponseBytes
9519     if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
9520         !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
9521         return false;
9522     }
9523 
9524     // Only basic OCSP responses are supported
9525     if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
9526         return false;
9527     }
9528 
9529     // Parse the octet string as a BasicOCSPResponse
9530     return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
9531 }
9532 
9533 /**
9534  * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
9535  * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
9536  * true is returned.
9537  */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)9538 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
9539     // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
9540     CBS response_data;
9541     if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
9542         return false;
9543     }
9544 
9545     // Skip the version, responderID and producedAt fields
9546     if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
9547                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9548         !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
9549         !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
9550         return false;
9551     }
9552 
9553     // Extract the list of SingleResponse.
9554     return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
9555 }
9556 
9557 /**
9558  * Get the SEQUENCE OF Extension from a SingleResponse.
9559  * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
9560  * returned.
9561  */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)9562 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
9563     // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
9564     if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
9565         !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
9566         !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
9567         !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
9568                                CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
9569         return false;
9570     }
9571 
9572     // Get the list of Extension
9573     return CBS_get_asn1(single_response, extensions,
9574                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
9575 }
9576 
9577 /*
9578     public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
9579                                                           long x509Ref, long issuerX509Ref);
9580 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)9581 static jbyteArray NativeCrypto_get_ocsp_single_extension(
9582         JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
9583         CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
9584     CHECK_ERROR_QUEUE_ON_RETURN;
9585     ScopedByteArrayRO ocspData(env, ocspDataBytes);
9586     if (ocspData.get() == nullptr) {
9587         return nullptr;
9588     }
9589 
9590     CBS cbs;
9591     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
9592 
9593     // Start parsing the OCSPResponse
9594     CBS ocsp_response;
9595     if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
9596         return nullptr;
9597     }
9598 
9599     // Get the BasicOCSPResponse from the OCSP Response
9600     CBS basic_response;
9601     if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
9602         return nullptr;
9603     }
9604 
9605     // Get the list of SingleResponses from the BasicOCSPResponse
9606     CBS responses;
9607     if (!get_ocsp_single_responses(&basic_response, &responses)) {
9608         return nullptr;
9609     }
9610 
9611     // Find the response matching the certificate
9612     X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
9613     X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
9614     CBS single_response;
9615     if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
9616         return nullptr;
9617     }
9618 
9619     // Get the extensions from the SingleResponse
9620     CBS extensions;
9621     if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
9622         return nullptr;
9623     }
9624 
9625     const uint8_t* ptr = CBS_data(&extensions);
9626     bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
9627             d2i_X509_EXTENSIONS(nullptr, &ptr,
9628                                 static_cast<long>(CBS_len(&extensions))));  // NOLINT(runtime/int)
9629     if (x509_exts.get() == nullptr) {
9630         return nullptr;
9631     }
9632 
9633     return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
9634             env, x509_exts.get(), oid);
9635 }
9636 
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)9637 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
9638     return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
9639 }
9640 
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)9641 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
9642                                        CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
9643     CHECK_ERROR_QUEUE_ON_RETURN;
9644     SSL* ssl = to_SSL(env, ssl_address, true);
9645     if (ssl == nullptr) {
9646         return 0;
9647     }
9648     return SSL_get_error(ssl, ret);
9649 }
9650 
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)9651 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
9652     ERR_clear_error();
9653 }
9654 
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9655 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
9656                                                     CONSCRYPT_UNUSED jobject ssl_holder) {
9657     CHECK_ERROR_QUEUE_ON_RETURN;
9658     SSL* ssl = to_SSL(env, ssl_address, true);
9659     if (ssl == nullptr) {
9660         return 0;
9661     }
9662     return SSL_pending(ssl);
9663 }
9664 
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)9665 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
9666     CHECK_ERROR_QUEUE_ON_RETURN;
9667     BIO* bio = to_BIO(env, bio_address);
9668     if (bio == nullptr) {
9669         return 0;
9670     }
9671     return static_cast<jint>(BIO_ctrl_pending(bio));
9672 }
9673 
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9674 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
9675                                                CONSCRYPT_UNUSED jobject ssl_holder) {
9676     CHECK_ERROR_QUEUE_ON_RETURN;
9677     SSL* ssl = to_SSL(env, ssl_address, true);
9678     if (ssl == nullptr) {
9679         return 0;
9680     }
9681     return (jint)SSL_max_seal_overhead(ssl);
9682 }
9683 
9684 /**
9685  * public static native int SSL_new_BIO(long ssl) throws SSLException;
9686  */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9687 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
9688                                       CONSCRYPT_UNUSED jobject ssl_holder) {
9689     CHECK_ERROR_QUEUE_ON_RETURN;
9690     SSL* ssl = to_SSL(env, ssl_address, true);
9691     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
9692     if (ssl == nullptr) {
9693         return 0;
9694     }
9695 
9696     BIO* internal_bio;
9697     BIO* network_bio;
9698     if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
9699         conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9700                                                            "BIO_new_bio_pair failed");
9701         JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
9702         return 0;
9703     }
9704 
9705     SSL_set_bio(ssl, internal_bio, internal_bio);
9706 
9707     JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
9708     return reinterpret_cast<uintptr_t>(network_bio);
9709 }
9710 
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9711 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9712                                                  CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9713     CHECK_ERROR_QUEUE_ON_RETURN;
9714     SSL* ssl = to_SSL(env, ssl_address, true);
9715     if (ssl == nullptr) {
9716         return 0;
9717     }
9718     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
9719 
9720     if (shc == nullptr) {
9721         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9722         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
9723                   ssl);
9724         return 0;
9725     }
9726 
9727     AppData* appData = toAppData(ssl);
9728     if (appData == nullptr) {
9729         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9730         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
9731         return 0;
9732     }
9733 
9734     errno = 0;
9735 
9736     if (!appData->setCallbackState(env, shc, nullptr)) {
9737         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9738         ERR_clear_error();
9739         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9740         return 0;
9741     }
9742 
9743     int ret = SSL_do_handshake(ssl);
9744     appData->clearCallbackState();
9745     if (env->ExceptionCheck()) {
9746         // cert_verify_callback threw exception
9747         ERR_clear_error();
9748         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9749         return 0;
9750     }
9751 
9752     SslError sslError(ssl, ret);
9753     int code = sslError.get();
9754 
9755     if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
9756         // Non-exceptional case.
9757         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
9758         return code;
9759     }
9760 
9761     // Exceptional case...
9762     if (ret == 0) {
9763         // TODO(nmittler): Can this happen with memory BIOs?
9764         /*
9765          * Clean error. See SSL_do_handshake(3SSL) man page.
9766          * The other side closed the socket before the handshake could be
9767          * completed, but everything is within the bounds of the TLS protocol.
9768          * We still might want to find out the real reason of the failure.
9769          */
9770         if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
9771             (code == SSL_ERROR_ZERO_RETURN)) {
9772             conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9773         } else {
9774             conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9775                     env, ssl, sslError.release(), "SSL handshake terminated",
9776                     conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9777         }
9778         JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9779         return code;
9780     }
9781 
9782     /*
9783      * Unclean error. See SSL_do_handshake(3SSL) man page.
9784      * Translate the error and throw exception. We are sure it is an error
9785      * at this point.
9786      */
9787     conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9788             env, ssl, sslError.release(), "SSL handshake aborted",
9789             conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9790     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9791     return code;
9792 }
9793 
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9794 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9795                                              CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9796     CHECK_ERROR_QUEUE_ON_RETURN;
9797     SSL* ssl = to_SSL(env, ssl_address, false);
9798     if (ssl == nullptr) {
9799         return;
9800     }
9801     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
9802 
9803     if (shc == nullptr) {
9804         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9805         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9806         return;
9807     }
9808 
9809     AppData* appData = toAppData(ssl);
9810     if (appData != nullptr) {
9811         if (!appData->setCallbackState(env, shc, nullptr)) {
9812             conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9813             ERR_clear_error();
9814             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9815             return;
9816         }
9817         int ret = SSL_shutdown(ssl);
9818         appData->clearCallbackState();
9819         // callbacks can happen if server requests renegotiation
9820         if (env->ExceptionCheck()) {
9821             JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9822             return;
9823         }
9824         switch (ret) {
9825             case 0:
9826                 /*
9827                  * Shutdown was not successful (yet), but there also
9828                  * is no error. Since we can't know whether the remote
9829                  * server is actually still there, and we don't want to
9830                  * get stuck forever in a second SSL_shutdown() call, we
9831                  * simply return. This is not security a problem as long
9832                  * as we close the underlying socket, which we actually
9833                  * do, because that's where we are just coming from.
9834                  */
9835                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
9836                 break;
9837             case 1:
9838                 /*
9839                  * Shutdown was successful. We can safely return. Hooray!
9840                  */
9841                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
9842                 break;
9843             default:
9844                 /*
9845                  * Everything else is a real error condition. We should
9846                  * let the Java layer know about this by throwing an
9847                  * exception.
9848                  */
9849                 int sslError = SSL_get_error(ssl, ret);
9850                 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
9851                 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9852                                                                    "SSL shutdown failed");
9853                 break;
9854         }
9855     }
9856 
9857     ERR_clear_error();
9858 }
9859 
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)9860 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
9861                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9862                                                 jint length, jobject shc) {
9863     CHECK_ERROR_QUEUE_ON_RETURN;
9864     SSL* ssl = to_SSL(env, ssl_address, true);
9865     char* destPtr = reinterpret_cast<char*>(address);
9866     if (ssl == nullptr) {
9867         return -1;
9868     }
9869     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
9870               destPtr, length, shc);
9871 
9872     if (shc == nullptr) {
9873         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9874         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
9875                   ssl);
9876         return -1;
9877     }
9878     AppData* appData = toAppData(ssl);
9879     if (appData == nullptr) {
9880         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9881         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
9882         return -1;
9883     }
9884     if (!appData->setCallbackState(env, shc, nullptr)) {
9885         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9886         ERR_clear_error();
9887         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
9888         return -1;
9889     }
9890 
9891     errno = 0;
9892 
9893     int result = SSL_read(ssl, destPtr, length);
9894     appData->clearCallbackState();
9895     if (env->ExceptionCheck()) {
9896         // An exception was thrown by one of the callbacks. Just propagate that exception.
9897         ERR_clear_error();
9898         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
9899         return -1;
9900     }
9901 
9902     SslError sslError(ssl, result);
9903     switch (sslError.get()) {
9904         case SSL_ERROR_NONE: {
9905             // Successfully read at least one byte. Just return the result.
9906             break;
9907         }
9908         case SSL_ERROR_ZERO_RETURN: {
9909             // A close_notify was received, this stream is finished.
9910             return -SSL_ERROR_ZERO_RETURN;
9911         }
9912         case SSL_ERROR_WANT_READ:
9913         case SSL_ERROR_WANT_WRITE: {
9914             // Return the negative of these values.
9915             result = -sslError.get();
9916             break;
9917         }
9918         case SSL_ERROR_SYSCALL: {
9919             // A problem occurred during a system call, but this is not
9920             // necessarily an error.
9921             if (result == 0) {
9922                 // TODO(nmittler): Can this happen with memory BIOs?
9923                 // Connection closed without proper shutdown. Tell caller we
9924                 // have reached end-of-stream.
9925                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
9926                 break;
9927             }
9928 
9929             if (errno == EINTR) {
9930                 // TODO(nmittler): Can this happen with memory BIOs?
9931                 // System call has been interrupted. Simply retry.
9932                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
9933                                                    "Read error");
9934                 break;
9935             }
9936 
9937             // Note that for all other system call errors we fall through
9938             // to the default case, which results in an Exception.
9939             FALLTHROUGH_INTENDED;
9940         }
9941         default: {
9942             // Everything else is basically an error.
9943             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9944                                                                "Read error");
9945             break;
9946         }
9947     }
9948 
9949     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
9950               ssl, destPtr, length, shc, result);
9951     return result;
9952 }
9953 
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)9954 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
9955                                                     CONSCRYPT_UNUSED jobject ssl_holder,
9956                                                     jlong bioRef, jlong address, jint len,
9957                                                     jobject shc) {
9958     CHECK_ERROR_QUEUE_ON_RETURN;
9959     SSL* ssl = to_SSL(env, ssl_address, true);
9960     if (ssl == nullptr) {
9961         return -1;
9962     }
9963     if (shc == nullptr) {
9964         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9965         JNI_TRACE(
9966                 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
9967                 "sslHandshakeCallbacks == null",
9968                 ssl);
9969         return -1;
9970     }
9971     BIO* bio = to_BIO(env, bioRef);
9972     if (bio == nullptr) {
9973         return -1;
9974     }
9975     if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
9976         // The network BIO couldn't handle the entire write. Don't write anything, so that we
9977         // only process one packet at a time.
9978         return 0;
9979     }
9980     const char* sourcePtr = reinterpret_cast<const char*>(address);
9981 
9982     AppData* appData = toAppData(ssl);
9983     if (appData == nullptr) {
9984         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9985         ERR_clear_error();
9986         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
9987         return -1;
9988     }
9989     if (!appData->setCallbackState(env, shc, nullptr)) {
9990         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9991         ERR_clear_error();
9992         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
9993         return -1;
9994     }
9995 
9996     errno = 0;
9997 
9998     int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
9999     appData->clearCallbackState();
10000     JNI_TRACE(
10001             "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10002             "ret=%d",
10003             ssl, bio, sourcePtr, len, shc, result);
10004     JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10005                           static_cast<size_t>(result));
10006     return result;
10007 }
10008 
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)10009 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10010                                                    CONSCRYPT_UNUSED jobject ssl_holder,
10011                                                    jlong bioRef, jlong address, jint outputSize,
10012                                                    jobject shc) {
10013     CHECK_ERROR_QUEUE_ON_RETURN;
10014     SSL* ssl = to_SSL(env, ssl_address, true);
10015     if (ssl == nullptr) {
10016         return -1;
10017     }
10018     if (shc == nullptr) {
10019         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10020         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10021                   ssl);
10022         return -1;
10023     }
10024     BIO* bio = to_BIO(env, bioRef);
10025     if (bio == nullptr) {
10026         return -1;
10027     }
10028     char* destPtr = reinterpret_cast<char*>(address);
10029     if (destPtr == nullptr) {
10030         conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10031         return -1;
10032     }
10033 
10034     AppData* appData = toAppData(ssl);
10035     if (appData == nullptr) {
10036         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10037         ERR_clear_error();
10038         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10039         return -1;
10040     }
10041     if (!appData->setCallbackState(env, shc, nullptr)) {
10042         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10043         ERR_clear_error();
10044         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10045         return -1;
10046     }
10047 
10048     errno = 0;
10049 
10050     int result = BIO_read(bio, destPtr, outputSize);
10051     appData->clearCallbackState();
10052     JNI_TRACE(
10053             "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10054             "=> ret=%d",
10055             ssl, bio, destPtr, outputSize, shc, result);
10056     JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10057     return result;
10058 }
10059 
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10060 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10061                                                CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10062     CHECK_ERROR_QUEUE_ON_RETURN;
10063     SSL* ssl = to_SSL(env, ssl_address, true);
10064     if (ssl == nullptr) {
10065         return;
10066     }
10067     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10068     if (shc == nullptr) {
10069         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10070         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10071                   ssl);
10072         return;
10073     }
10074     AppData* appData = toAppData(ssl);
10075     if (appData == nullptr) {
10076         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10077         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10078         return;
10079     }
10080     if (!appData->setCallbackState(env, shc, nullptr)) {
10081         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10082         ERR_clear_error();
10083         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10084         return;
10085     }
10086     char c;
10087     int result = SSL_peek(ssl, &c, 1);
10088     appData->clearCallbackState();
10089     if (env->ExceptionCheck()) {
10090         // An exception was thrown by one of the callbacks. Just propagate that exception.
10091         ERR_clear_error();
10092         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10093         return;
10094     }
10095 
10096     SslError sslError(ssl, result);
10097     switch (sslError.get()) {
10098         case SSL_ERROR_NONE:
10099         case SSL_ERROR_ZERO_RETURN:
10100         case SSL_ERROR_WANT_READ:
10101         case SSL_ERROR_WANT_WRITE: {
10102             // The call succeeded, lacked data, or the SSL is closed.  All is well.
10103             break;
10104         }
10105         case SSL_ERROR_SYSCALL: {
10106             // A problem occurred during a system call, but this is not
10107             // necessarily an error.
10108             if (result == 0) {
10109                 // TODO(nmittler): Can this happen with memory BIOs?
10110                 // Connection closed without proper shutdown. Tell caller we
10111                 // have reached end-of-stream.
10112                 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10113                 break;
10114             }
10115 
10116             if (errno == EINTR) {
10117                 // TODO(nmittler): Can this happen with memory BIOs?
10118                 // System call has been interrupted. Simply retry.
10119                 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10120                                                    "Read error");
10121                 break;
10122             }
10123 
10124             // Note that for all other system call errors we fall through
10125             // to the default case, which results in an Exception.
10126             FALLTHROUGH_INTENDED;
10127         }
10128         default: {
10129             // Everything else is basically an error.
10130             conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10131                                                                "Read error");
10132             break;
10133         }
10134     }
10135 
10136     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10137 }
10138 
10139 /**
10140  * OpenSSL write function (2): write into buffer at offset n chunks.
10141  */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10142 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10143                                                 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10144                                                 jint len, jobject shc) {
10145     CHECK_ERROR_QUEUE_ON_RETURN;
10146     SSL* ssl = to_SSL(env, ssl_address, true);
10147     const char* sourcePtr = reinterpret_cast<const char*>(address);
10148     if (ssl == nullptr) {
10149         return -1;
10150     }
10151     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10152               sourcePtr, len, shc);
10153     if (shc == nullptr) {
10154         conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10155         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10156                   ssl);
10157         return -1;
10158     }
10159 
10160     AppData* appData = toAppData(ssl);
10161     if (appData == nullptr) {
10162         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10163         ERR_clear_error();
10164         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10165         return -1;
10166     }
10167     if (!appData->setCallbackState(env, shc, nullptr)) {
10168         conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10169         ERR_clear_error();
10170         JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10171         return -1;
10172     }
10173 
10174     errno = 0;
10175 
10176     int result = SSL_write(ssl, sourcePtr, len);
10177     appData->clearCallbackState();
10178     JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10179               ssl, sourcePtr, len, shc, result);
10180     return result;
10181 }
10182 
10183 /**
10184  * public static native bool BoringSSL_FIPS_mode();
10185  */
NativeCrypto_usesBoringSSL_FIPS_mode()10186 static jboolean NativeCrypto_usesBoringSSL_FIPS_mode() {
10187     return FIPS_mode();
10188 }
10189 
10190 // TESTING METHODS BEGIN
10191 
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10192 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10193     CHECK_ERROR_QUEUE_ON_RETURN;
10194     BIO* bio = to_BIO(env, bioRef);
10195     JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10196 
10197     if (bio == nullptr) {
10198         JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10199         return 0;
10200     }
10201 
10202     if (outputJavaBytes == nullptr) {
10203         conscrypt::jniutil::throwNullPointerException(env, "output == null");
10204         JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10205         return 0;
10206     }
10207 
10208     jsize outputSize = env->GetArrayLength(outputJavaBytes);
10209 
10210     std::unique_ptr<unsigned char[]> buffer(
10211             new unsigned char[static_cast<unsigned int>(outputSize)]);
10212     if (buffer.get() == nullptr) {
10213         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10214         return 0;
10215     }
10216 
10217     int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10218     if (read <= 0) {
10219         conscrypt::jniutil::throwIOException(env, "BIO_read");
10220         JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10221         return 0;
10222     }
10223 
10224     env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10225     JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10226     return read;
10227 }
10228 
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10229 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10230                                    jint offset, jint length) {
10231     CHECK_ERROR_QUEUE_ON_RETURN;
10232     BIO* bio = to_BIO(env, bioRef);
10233     JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10234 
10235     if (bio == nullptr) {
10236         return;
10237     }
10238 
10239     if (inputJavaBytes == nullptr) {
10240         conscrypt::jniutil::throwNullPointerException(env, "input == null");
10241         return;
10242     }
10243 
10244     int inputSize = env->GetArrayLength(inputJavaBytes);
10245     if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10246         conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10247                                            "inputJavaBytes");
10248         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10249         return;
10250     }
10251 
10252     std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10253     if (buffer.get() == nullptr) {
10254         conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10255         return;
10256     }
10257 
10258     env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10259     if (BIO_write(bio, buffer.get(), length) != length) {
10260         ERR_clear_error();
10261         conscrypt::jniutil::throwIOException(env, "BIO_write");
10262         JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10263         return;
10264     }
10265 
10266     JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10267 }
10268 
10269 /**
10270  * public static native long SSL_clear_mode(long ssl, long mode);
10271  */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10272 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10273                                          CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10274     CHECK_ERROR_QUEUE_ON_RETURN;
10275     SSL* ssl = to_SSL(env, ssl_address, true);
10276     // NOLINTNEXTLINE(runtime/int)
10277     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10278     if (ssl == nullptr) {
10279         return 0;
10280     }
10281     jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10282     // NOLINTNEXTLINE(runtime/int)
10283     JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10284     return result;
10285 }
10286 
10287 /**
10288  * public static native long SSL_get_mode(long ssl);
10289  */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10290 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10291                                        CONSCRYPT_UNUSED jobject ssl_holder) {
10292     CHECK_ERROR_QUEUE_ON_RETURN;
10293     SSL* ssl = to_SSL(env, ssl_address, true);
10294     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10295     if (ssl == nullptr) {
10296         return 0;
10297     }
10298     jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
10299     // NOLINTNEXTLINE(runtime/int)
10300     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
10301     return mode;
10302 }
10303 
10304 /**
10305  * public static native long SSL_get_options(long ssl);
10306  */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10307 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
10308                                           CONSCRYPT_UNUSED jobject ssl_holder) {
10309     CHECK_ERROR_QUEUE_ON_RETURN;
10310     SSL* ssl = to_SSL(env, ssl_address, true);
10311     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
10312     if (ssl == nullptr) {
10313         return 0;
10314     }
10315     jlong options = static_cast<jlong>(SSL_get_options(ssl));
10316     // NOLINTNEXTLINE(runtime/int)
10317     JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
10318     return options;
10319 }
10320 
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10321 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
10322                                            CONSCRYPT_UNUSED jobject ssl_holder) {
10323     CHECK_ERROR_QUEUE_ON_RETURN;
10324     SSL* ssl = to_SSL(env, ssl_address, true);
10325     if (ssl == nullptr) {
10326         return 0;
10327     }
10328     return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
10329 }
10330 
10331 // TESTING METHODS END
10332 
10333 #define CONSCRYPT_NATIVE_METHOD(functionName, signature)             \
10334     {                                                                \
10335         /* NOLINTNEXTLINE */                                         \
10336         (char*)#functionName, (char*)(signature),                    \
10337                 reinterpret_cast<void*>(NativeCrypto_##functionName) \
10338     }
10339 
10340 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10341 #define SSL_CALLBACKS \
10342     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
10343 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10344 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
10345 #define REF_EVP_CIPHER_CTX \
10346     "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
10347 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
10348 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
10349 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
10350 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
10351 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
10352 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
10353 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
10354 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
10355 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
10356 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
10357 static JNINativeMethod sNativeCryptoMethods[] = {
10358         CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
10359         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
10360         CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
10361         CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
10362         CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
10363         CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
10364         CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
10365         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
10366         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
10367         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10368         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10369         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10370         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
10371         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10372         CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
10373         CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
10374         CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
10375         CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
10376         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
10377         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
10378         CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10379         CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
10380                                 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
10381         CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
10382         CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
10383         CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10384         CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10385         CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10386         CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10387         CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10388         CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
10389         CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
10390         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
10391         CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
10392         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10393         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10394         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10395         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10396         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
10397         CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
10398         CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10399         CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
10400         CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
10401         CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
10402                                 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10403         CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
10404                                 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10405         CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10406         CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
10407         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10408         CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10409         CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
10410         CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
10411         CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10412         CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
10413         CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
10414         CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
10415         CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
10416         CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
10417         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
10418         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
10419         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
10420         CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
10421         CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
10422         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10423         CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10424         CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
10425         CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10426         CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
10427         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10428         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10429         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10430         CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
10431         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10432         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10433         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10434         CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
10435         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
10436         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10437         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
10438         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10439         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
10440         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
10441         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
10442         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
10443         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
10444         CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
10445         CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
10446         CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10447         CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10448         CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
10449         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
10450         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
10451         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10452         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
10453         CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
10454         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10455         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
10456         CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
10457         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
10458         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
10459         CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
10460         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
10461         CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
10462         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
10463         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
10464         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
10465         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
10466         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10467         CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10468         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
10469         CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
10470         CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
10471         CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
10472         CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
10473         CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
10474         CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
10475         CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
10476         CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10477         CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
10478         CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
10479         CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
10480         CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
10481         CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
10482         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
10483         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
10484         CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
10485         CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
10486         CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
10487         CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
10488         CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
10489         CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
10490         CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
10491         CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
10492         CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
10493         CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
10494         CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10495         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10496         CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
10497         CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
10498         CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
10499         CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
10500         CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
10501         CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
10502         CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
10503         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
10504         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
10505         CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
10506         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
10507         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
10508         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10509         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
10510         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
10511         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
10512         CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
10513         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
10514         CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10515         CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
10516                                 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
10517         CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
10518         CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
10519         CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
10520         CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
10521         CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
10522         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
10523         CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext, "(J" REF_X509 "Ljava/lang/String;)[B"),
10524         CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
10525         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
10526         CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
10527         CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
10528         CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
10529         CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
10530         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
10531         CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
10532         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
10533         CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
10534         CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
10535         CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
10536         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
10537         CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
10538         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
10539         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
10540         CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
10541         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10542         CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
10543         CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
10544         CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
10545         CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10546         CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
10547         CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
10548         CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
10549         CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
10550         CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
10551         CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
10552         CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
10553         CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
10554         CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
10555         CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
10556         CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
10557         CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
10558         CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
10559         CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
10560         CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
10561         CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
10562         CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
10563         CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
10564         CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
10565         CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
10566         CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
10567         CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
10568         CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
10569         CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
10570         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
10571         CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
10572         CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
10573         CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
10574         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
10575         CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
10576         CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
10577         CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
10578         CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
10579         CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
10580         CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
10581         CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
10582         CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
10583         CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
10584         CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
10585         CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
10586         CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
10587         CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
10588         CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
10589         CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
10590         CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
10591         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
10592         CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
10593         CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
10594         CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
10595         CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
10596         CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
10597         CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
10598         CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
10599         CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
10600         CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
10601         CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
10602         CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
10603         CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
10604         CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
10605         CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
10606         CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
10607         CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
10608         CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
10609         CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
10610         CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
10611         CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
10612         CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
10613         CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
10614         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
10615         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
10616         CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
10617         CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
10618         CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
10619         CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
10620         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
10621         CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
10622         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10623         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10624         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
10625         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
10626         CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
10627         CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
10628         CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
10629         CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
10630         CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
10631         CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
10632         CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
10633         CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
10634         CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
10635                                 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
10636         CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
10637         CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
10638         CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
10639         CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
10640         CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
10641         CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
10642         CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
10643         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
10644         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10645         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10646         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10647         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10648         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
10649         CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
10650         CONSCRYPT_NATIVE_METHOD(usesBoringSSL_FIPS_mode, "()Z"),
10651 
10652         // Used for testing only.
10653         CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
10654         CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
10655         CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
10656         CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
10657         CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
10658         CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
10659 };
10660 
registerNativeMethods(JNIEnv * env)10661 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
10662     conscrypt::jniutil::jniRegisterNativeMethods(
10663             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
10664             NELEM(sNativeCryptoMethods));
10665 }
10666 
10667 /* Local Variables: */
10668 /* mode: c++ */
10669 /* tab-width: 4 */
10670 /* indent-tabs-mode: nil */
10671 /* c-basic-offset: 4 */
10672 /* End: */
10673 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
10674