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