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