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