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