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