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