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