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