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 <conscrypt/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/logging.h>
26 #include <conscrypt/macros.h>
27 #include <conscrypt/native_crypto.h>
28 #include <conscrypt/netutil.h>
29 #include <conscrypt/scoped_ssl_bio.h>
30 #include <conscrypt/ssl_error.h>
31
32 #include <nativehelper/scoped_primitive_array.h>
33 #include <nativehelper/scoped_utf_chars.h>
34
35 #include <limits.h>
36
37 #include <openssl/aead.h>
38 #include <openssl/asn1.h>
39 #include <openssl/chacha.h>
40 #include <openssl/engine.h>
41 #include <openssl/err.h>
42 #include <openssl/evp.h>
43 #include <openssl/hmac.h>
44 #include <openssl/pkcs7.h>
45 #include <openssl/pkcs8.h>
46 #include <openssl/rand.h>
47 #include <openssl/rsa.h>
48 #include <openssl/ssl.h>
49 #include <openssl/x509v3.h>
50
51 #include <limits>
52 #include <vector>
53
54 using conscrypt::AppData;
55 using conscrypt::BioInputStream;
56 using conscrypt::BioOutputStream;
57 using conscrypt::BioStream;
58 using conscrypt::CompatibilityCloseMonitor;
59 using conscrypt::NativeCrypto;
60 using conscrypt::SslError;
61
62 /**
63 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
64 * If this function returns nullptr and <code>throwIfNull</code> is
65 * passed as <code>true</code>, then this function will call
66 * <code>throwSSLExceptionStr</code> before returning, so in this case of
67 * nullptr, a caller of this function should simply return and allow JNI
68 * to do its thing.
69 *
70 * @param env the JNI environment
71 * @param ssl_address; the ssl_address pointer as an integer
72 * @param throwIfNull whether to throw if the SSL pointer is nullptr
73 * @returns the pointer, which may be nullptr
74 */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)75 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
76 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
77 if ((ssl_ctx == nullptr) && throwIfNull) {
78 JNI_TRACE("ssl_ctx == null");
79 conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
80 }
81 return ssl_ctx;
82 }
83
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)84 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
85 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
86 if ((ssl == nullptr) && throwIfNull) {
87 JNI_TRACE("ssl == null");
88 conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
89 }
90 return ssl;
91 }
92
to_SSL_BIO(JNIEnv * env,jlong bio_address,bool throwIfNull)93 static BIO* to_SSL_BIO(JNIEnv* env, jlong bio_address, bool throwIfNull) {
94 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
95 if ((bio == nullptr) && throwIfNull) {
96 JNI_TRACE("bio == null");
97 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
98 }
99 return bio;
100 }
101
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)102 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
103 SSL_SESSION* ssl_session =
104 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
105 if ((ssl_session == nullptr) && throwIfNull) {
106 JNI_TRACE("ssl_session == null");
107 conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
108 }
109 return ssl_session;
110 }
111
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)112 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
113 SSL_CIPHER* ssl_cipher =
114 reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
115 if ((ssl_cipher == nullptr) && throwIfNull) {
116 JNI_TRACE("ssl_cipher == null");
117 conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
118 }
119 return ssl_cipher;
120 }
121
122 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)123 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
124 if (contextObject == nullptr) {
125 JNI_TRACE("contextObject == null");
126 conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
127 return nullptr;
128 }
129 T* ref = reinterpret_cast<T*>(
130 env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
131 if (ref == nullptr) {
132 JNI_TRACE("ref == null");
133 conscrypt::jniutil::throwNullPointerException(env, "ref == null");
134 return nullptr;
135 }
136 return ref;
137 }
138
139 /**
140 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
141 * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
142 * return value is false, there is a pending exception.
143 */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)144 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
145 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
146 if (dest == nullptr) {
147 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
148 conscrypt::jniutil::throwNullPointerException(env, "dest == null");
149 return false;
150 }
151 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
152
153 ScopedByteArrayRO sourceBytes(env, source);
154 if (sourceBytes.get() == nullptr) {
155 JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
156 return false;
157 }
158 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
159 size_t tmpSize = sourceBytes.size();
160
161 /* if the array is empty, it is zero. */
162 if (tmpSize == 0) {
163 if (*dest == nullptr) {
164 *dest = BN_new();
165 }
166 BN_zero(*dest);
167 return true;
168 }
169
170 std::unique_ptr<unsigned char[]> twosComplement;
171 bool negative = (tmp[0] & 0x80) != 0;
172 if (negative) {
173 // Need to convert to two's complement.
174 twosComplement.reset(new unsigned char[tmpSize]);
175 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
176 memcpy(twosBytes, tmp, tmpSize);
177 tmp = twosBytes;
178
179 bool carry = true;
180 for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
181 twosBytes[i] ^= 0xFF;
182 if (carry) {
183 carry = (++twosBytes[i]) == 0;
184 }
185 }
186 }
187 BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
188 if (ret == nullptr) {
189 conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
190 ERR_clear_error();
191 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
192 return false;
193 }
194 BN_set_negative(ret, negative ? 1 : 0);
195
196 *dest = ret;
197 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
198 return true;
199 }
200
201 /**
202 * arrayToBignumSize sets |*out_size| to the size of the big-endian number
203 * contained in |source|. It returns true on success and sets an exception and
204 * returns false otherwise.
205 */
arrayToBignumSize(JNIEnv * env,jbyteArray source,size_t * out_size)206 static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
207 JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
208
209 ScopedByteArrayRO sourceBytes(env, source);
210 if (sourceBytes.get() == nullptr) {
211 JNI_TRACE("arrayToBignum(%p, %p) => null", source, out_size);
212 return false;
213 }
214 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
215 size_t tmpSize = sourceBytes.size();
216
217 if (tmpSize == 0) {
218 *out_size = 0;
219 return true;
220 }
221
222 if ((tmp[0] & 0x80) != 0) {
223 // Negative numbers are invalid.
224 conscrypt::jniutil::throwRuntimeException(env, "Negative number");
225 return false;
226 }
227
228 while (tmpSize > 0 && tmp[0] == 0) {
229 tmp++;
230 tmpSize--;
231 }
232
233 *out_size = tmpSize;
234 return true;
235 }
236
237 /**
238 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
239 */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)240 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
241 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
242
243 if (source == nullptr) {
244 conscrypt::jniutil::throwNullPointerException(env, sourceName);
245 return nullptr;
246 }
247
248 size_t numBytes = BN_num_bytes(source) + 1;
249 jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
250 ScopedByteArrayRW bytes(env, javaBytes);
251 if (bytes.get() == nullptr) {
252 JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
253 return nullptr;
254 }
255
256 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
257 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
258 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
259 return nullptr;
260 }
261
262 // Set the sign and convert to two's complement if necessary for the Java code.
263 if (BN_is_negative(source)) {
264 bool carry = true;
265 for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
266 tmp[i] ^= 0xFF;
267 if (carry) {
268 carry = (++tmp[i]) == 0;
269 }
270 }
271 *tmp |= 0x80;
272 } else {
273 *tmp = 0x00;
274 }
275
276 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
277 return javaBytes;
278 }
279
280 /**
281 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
282 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
283 * from the OpenSSL ASN.1 API.
284 */
285 template <typename T>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(T *,unsigned char **))286 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(T*, unsigned char**)) {
287 if (obj == nullptr) {
288 conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
289 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
290 return nullptr;
291 }
292
293 int derLen = i2d_func(obj, nullptr);
294 if (derLen < 0) {
295 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
296 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
297 return nullptr;
298 }
299
300 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
301 if (byteArray.get() == nullptr) {
302 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
303 return nullptr;
304 }
305
306 ScopedByteArrayRW bytes(env, byteArray.get());
307 if (bytes.get() == nullptr) {
308 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
309 return nullptr;
310 }
311
312 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
313 int ret = i2d_func(obj, &p);
314 if (ret < 0) {
315 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
316 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
317 return nullptr;
318 }
319
320 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
321 return byteArray.release();
322 }
323
324 /**
325 * Finishes a pending CBB and returns a jbyteArray with the contents.
326 */
CBBToByteArray(JNIEnv * env,CBB * cbb)327 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
328 uint8_t* data;
329 size_t len;
330 if (!CBB_finish(cbb, &data, &len)) {
331 conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
332 ERR_clear_error();
333 JNI_TRACE("creating byte array failed");
334 return nullptr;
335 }
336 bssl::UniquePtr<uint8_t> free_data(data);
337
338 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
339 if (byteArray.get() == nullptr) {
340 JNI_TRACE("creating byte array failed");
341 return nullptr;
342 }
343
344 ScopedByteArrayRW bytes(env, byteArray.get());
345 if (bytes.get() == nullptr) {
346 JNI_TRACE("using byte array failed");
347 return nullptr;
348 }
349
350 memcpy(bytes.get(), data, len);
351 return byteArray.release();
352 }
353
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)354 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
355 if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
356 JNI_TRACE("buffer too large");
357 conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
358 return nullptr;
359 }
360
361 int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
362 jbyteArray ret = env->NewByteArray(length);
363 if (ret == nullptr) {
364 JNI_TRACE("allocating byte array failed");
365 return nullptr;
366 }
367
368 env->SetByteArrayRegion(ret, 0, length,
369 reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
370 return ret;
371 }
372
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)373 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
374 CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
375 if (array == nullptr) {
376 JNI_TRACE("array was null");
377 conscrypt::jniutil::throwNullPointerException(env, "array == null");
378 return nullptr;
379 }
380
381 ScopedByteArrayRO arrayRo(env, array);
382 if (arrayRo.get() == nullptr) {
383 JNI_TRACE("failed to get bytes");
384 return nullptr;
385 }
386
387 bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
388 reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
389 if (!ret) {
390 JNI_TRACE("failed to allocate CRYPTO_BUFFER");
391 conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
392 return nullptr;
393 }
394
395 return ret;
396 }
397
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)398 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
399 const STACK_OF(CRYPTO_BUFFER) * buffers) {
400 size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
401 if (numBuffers > INT_MAX) {
402 JNI_TRACE("too many buffers");
403 conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
404 return nullptr;
405 }
406
407 ScopedLocalRef<jobjectArray> array(
408 env, env->NewObjectArray(static_cast<int>(numBuffers),
409 conscrypt::jniutil::byteArrayClass, nullptr));
410 if (array.get() == nullptr) {
411 JNI_TRACE("failed to allocate array");
412 return nullptr;
413 }
414
415 for (size_t i = 0; i < numBuffers; ++i) {
416 CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
417 ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
418 if (bArray.get() == nullptr) {
419 return nullptr;
420 }
421 env->SetObjectArrayElement(array.get(), i, bArray.get());
422 }
423
424 return array.release();
425 }
426
427 /**
428 * Converts ASN.1 BIT STRING to a jbooleanArray.
429 */
ASN1BitStringToBooleanArray(JNIEnv * env,ASN1_BIT_STRING * bitStr)430 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, ASN1_BIT_STRING* bitStr) {
431 int size = bitStr->length * 8;
432 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
433 size -= bitStr->flags & 0x07;
434 }
435
436 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
437 if (bitsRef.get() == nullptr) {
438 return nullptr;
439 }
440
441 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
442 for (size_t i = 0; i < bitsArray.size(); i++) {
443 bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
444 }
445
446 return bitsRef.release();
447 }
448
bio_stream_create(BIO * b)449 static int bio_stream_create(BIO* b) {
450 b->init = 1;
451 b->num = 0;
452 b->ptr = nullptr;
453 b->flags = 0;
454 return 1;
455 }
456
bio_stream_destroy(BIO * b)457 static int bio_stream_destroy(BIO* b) {
458 if (b == nullptr) {
459 return 0;
460 }
461
462 if (b->ptr != nullptr) {
463 delete static_cast<BioStream*>(b->ptr);
464 b->ptr = nullptr;
465 }
466
467 b->init = 0;
468 b->flags = 0;
469 return 1;
470 }
471
bio_stream_read(BIO * b,char * buf,int len)472 static int bio_stream_read(BIO* b, char* buf, int len) {
473 BIO_clear_retry_flags(b);
474 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
475 int ret = stream->read(buf, len);
476 if (ret == 0) {
477 if (stream->isFinite()) {
478 return 0;
479 }
480 // If the BioInputStream is not finite then EOF doesn't mean that
481 // there's nothing more coming.
482 BIO_set_retry_read(b);
483 return -1;
484 }
485 return ret;
486 }
487
bio_stream_write(BIO * b,const char * buf,int len)488 static int bio_stream_write(BIO* b, const char* buf, int len) {
489 BIO_clear_retry_flags(b);
490 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
491 return stream->write(buf, len);
492 }
493
bio_stream_puts(BIO * b,const char * buf)494 static int bio_stream_puts(BIO* b, const char* buf) {
495 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
496 return stream->write(buf, static_cast<int>(strlen(buf)));
497 }
498
bio_stream_gets(BIO * b,char * buf,int len)499 static int bio_stream_gets(BIO* b, char* buf, int len) {
500 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
501 return stream->gets(buf, len);
502 }
503
bio_stream_assign(BIO * b,BioStream * stream)504 static void bio_stream_assign(BIO* b, BioStream* stream) {
505 b->ptr = static_cast<void*>(stream);
506 }
507
508 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)509 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
510 BioStream* stream = static_cast<BioStream*>(b->ptr);
511
512 switch (cmd) {
513 case BIO_CTRL_EOF:
514 return stream->isEof() ? 1 : 0;
515 case BIO_CTRL_FLUSH:
516 return stream->flush();
517 default:
518 return 0;
519 }
520 }
521
522 static BIO_METHOD stream_bio_method = {
523 (100 | 0x0400), /* source/sink BIO */
524 "InputStream/OutputStream BIO",
525 bio_stream_write, /* bio_write */
526 bio_stream_read, /* bio_read */
527 bio_stream_puts, /* bio_puts */
528 bio_stream_gets, /* bio_gets */
529 bio_stream_ctrl, /* bio_ctrl */
530 bio_stream_create, /* bio_create */
531 bio_stream_destroy, /* bio_free */
532 nullptr, /* no bio_callback_ctrl */
533 };
534
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)535 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
536 size_t message_len) {
537 JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
538 if (message_len > std::numeric_limits<jsize>::max()) {
539 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
540 return nullptr;
541 }
542 ScopedLocalRef<jbyteArray> messageArray(env,
543 env->NewByteArray(static_cast<jsize>(message_len)));
544 if (env->ExceptionCheck()) {
545 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
546 return nullptr;
547 }
548
549 {
550 ScopedByteArrayRW messageBytes(env, messageArray.get());
551 if (messageBytes.get() == nullptr) {
552 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
553 return nullptr;
554 }
555
556 memcpy(messageBytes.get(), message, message_len);
557 }
558
559 jmethodID rawSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
560 "ecSignDigestWithPrivateKey",
561 "(Ljava/security/PrivateKey;[B)[B");
562 if (rawSignMethod == nullptr) {
563 CONSCRYPT_LOG_ERROR("Could not find ecSignDigestWithPrivateKey");
564 return nullptr;
565 }
566
567 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
568 conscrypt::jniutil::cryptoUpcallsClass, rawSignMethod, privateKey, messageArray.get()));
569 }
570
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)571 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
572 const char* message, size_t message_len) {
573 if (message_len > std::numeric_limits<jsize>::max()) {
574 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
575 return nullptr;
576 }
577 ScopedLocalRef<jbyteArray> messageArray(env,
578 env->NewByteArray(static_cast<jsize>(message_len)));
579 if (env->ExceptionCheck()) {
580 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
581 return nullptr;
582 }
583
584 {
585 ScopedByteArrayRW messageBytes(env, messageArray.get());
586 if (messageBytes.get() == nullptr) {
587 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
588 return nullptr;
589 }
590
591 memcpy(messageBytes.get(), message, message_len);
592 }
593
594 jmethodID rsaSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
595 "rsaSignDigestWithPrivateKey",
596 "(Ljava/security/PrivateKey;I[B)[B");
597 if (rsaSignMethod == nullptr) {
598 CONSCRYPT_LOG_ERROR("Could not find rsaSignDigestWithPrivateKey");
599 return nullptr;
600 }
601
602 return reinterpret_cast<jbyteArray>(
603 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaSignMethod,
604 privateKey, padding, messageArray.get()));
605 }
606
607 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
608 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
609 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
610 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)611 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
612 const char* ciphertext, size_t ciphertext_len) {
613 if (ciphertext_len > std::numeric_limits<jsize>::max()) {
614 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
615 return nullptr;
616 }
617 ScopedLocalRef<jbyteArray> ciphertextArray(
618 env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
619 if (env->ExceptionCheck()) {
620 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
621 return nullptr;
622 }
623
624 {
625 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
626 if (ciphertextBytes.get() == nullptr) {
627 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
628 return nullptr;
629 }
630
631 memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
632 }
633
634 jmethodID rsaDecryptMethod =
635 env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
636 "rsaDecryptWithPrivateKey", "(Ljava/security/PrivateKey;I[B)[B");
637 if (rsaDecryptMethod == nullptr) {
638 CONSCRYPT_LOG_ERROR("Could not find rsaDecryptWithPrivateKey");
639 return nullptr;
640 }
641
642 return reinterpret_cast<jbyteArray>(
643 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaDecryptMethod,
644 privateKey, padding, ciphertextArray.get()));
645 }
646
647 // *********************************************
648 // From keystore_openssl.cpp in Chromium source.
649 // *********************************************
650
651 namespace {
652
653 ENGINE* g_engine;
654 int g_rsa_exdata_index;
655 int g_ecdsa_exdata_index;
656 RSA_METHOD g_rsa_method;
657 ECDSA_METHOD g_ecdsa_method;
658 std::once_flag g_engine_once;
659
660 void init_engine_globals();
661
ensure_engine_globals()662 void ensure_engine_globals() {
663 std::call_once(g_engine_once, init_engine_globals);
664 }
665
666 // KeyExData contains the data that is contained in the EX_DATA of the RSA
667 // and ECDSA objects that are created to wrap Android system keys.
668 struct KeyExData {
669 // private_key contains a reference to a Java, private-key object.
670 jobject private_key;
671 // cached_size contains the "size" of the key. This is the size of the
672 // modulus (in bytes) for RSA, or the group order size for ECDSA. This
673 // avoids calling into Java to calculate the size.
674 size_t cached_size;
675 };
676
677 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
678 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)679 int ExDataDup(CRYPTO_EX_DATA* /* to */,
680 const CRYPTO_EX_DATA* /* from */,
681 void** /* from_d */,
682 int /* index */,
683 long /* argl */ /* NOLINT(runtime/int) */,
684 void* /* argp */) {
685 return 0;
686 }
687
688 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)689 void ExDataFree(void* /* parent */,
690 void* ptr,
691 CRYPTO_EX_DATA* /* ad */,
692 int /* index */,
693 long /* argl */ /* NOLINT(runtime/int) */,
694 void* /* argp */) {
695 // Ensure the global JNI reference created with this wrapper is
696 // properly destroyed with it.
697 KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
698 if (ex_data != nullptr) {
699 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
700 env->DeleteGlobalRef(ex_data->private_key);
701 delete ex_data;
702 }
703 }
704
RsaGetExData(const RSA * rsa)705 KeyExData* RsaGetExData(const RSA* rsa) {
706 return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
707 }
708
RsaMethodSize(const RSA * rsa)709 size_t RsaMethodSize(const RSA* rsa) {
710 const KeyExData* ex_data = RsaGetExData(rsa);
711 return ex_data->cached_size;
712 }
713
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)714 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
715 size_t in_len, int padding) {
716 if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
717 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
718 return 0;
719 }
720
721 // Retrieve private key JNI reference.
722 const KeyExData* ex_data = RsaGetExData(rsa);
723 if (!ex_data || !ex_data->private_key) {
724 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
725 return 0;
726 }
727
728 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
729 if (env == nullptr) {
730 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
731 return 0;
732 }
733
734 // For RSA keys, this function behaves as RSA_private_encrypt with
735 // the specified padding.
736 ScopedLocalRef<jbyteArray> signature(
737 env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
738 reinterpret_cast<const char*>(in), in_len));
739
740 if (signature.get() == nullptr) {
741 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
742 return 0;
743 }
744
745 ScopedByteArrayRO result(env, signature.get());
746
747 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
748 if (result.size() > expected_size) {
749 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
750 return 0;
751 }
752
753 if (max_out < expected_size) {
754 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
755 return 0;
756 }
757
758 // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
759 // should pad with leading 0s, but if it doesn't, pad the result.
760 size_t zero_pad = expected_size - result.size();
761 memset(out, 0, zero_pad);
762 memcpy(out + zero_pad, &result[0], result.size());
763 *out_len = expected_size;
764
765 return 1;
766 }
767
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)768 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
769 size_t in_len, int padding) {
770 // Retrieve private key JNI reference.
771 const KeyExData* ex_data = RsaGetExData(rsa);
772 if (!ex_data || !ex_data->private_key) {
773 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
774 return 0;
775 }
776
777 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
778 if (env == nullptr) {
779 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
780 return 0;
781 }
782
783 // This function behaves as RSA_private_decrypt.
784 ScopedLocalRef<jbyteArray> cleartext(
785 env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
786 reinterpret_cast<const char*>(in), in_len));
787 if (cleartext.get() == nullptr) {
788 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
789 return 0;
790 }
791
792 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
793
794 if (max_out < cleartextBytes.size()) {
795 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
796 return 0;
797 }
798
799 // Copy result to OpenSSL-provided buffer.
800 memcpy(out, cleartextBytes.get(), cleartextBytes.size());
801 *out_len = cleartextBytes.size();
802
803 return 1;
804 }
805
806 // Custom ECDSA_METHOD that uses the platform APIs.
807 // Note that for now, only signing through ECDSA_sign() is really supported.
808 // all other method pointers are either stubs returning errors, or no-ops.
809
EcKeyGetKey(const EC_KEY * ec_key)810 jobject EcKeyGetKey(const EC_KEY* ec_key) {
811 KeyExData* ex_data =
812 reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
813 return ex_data->private_key;
814 }
815
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)816 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
817 EC_KEY* ec_key) {
818 // Retrieve private key JNI reference.
819 jobject private_key = EcKeyGetKey(ec_key);
820 if (!private_key) {
821 CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
822 return 0;
823 }
824
825 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
826 if (env == nullptr) {
827 return 0;
828 }
829
830 // Sign message with it through JNI.
831 ScopedLocalRef<jbyteArray> signature(
832 env, ecSignDigestWithPrivateKey(env, private_key,
833 reinterpret_cast<const char*>(digest), digest_len));
834 if (signature.get() == nullptr) {
835 CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
836 return 0;
837 }
838
839 ScopedByteArrayRO signatureBytes(env, signature.get());
840 // Note: With ECDSA, the actual signature may be smaller than
841 // ECDSA_size().
842 size_t max_expected_size = ECDSA_size(ec_key);
843 if (signatureBytes.size() > max_expected_size) {
844 CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
845 signatureBytes.size(), max_expected_size);
846 return 0;
847 }
848
849 memcpy(sig, signatureBytes.get(), signatureBytes.size());
850 *sig_len = static_cast<unsigned int>(signatureBytes.size());
851 return 1;
852 }
853
init_engine_globals()854 void init_engine_globals() {
855 g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
856 nullptr /* new_func */, ExDataDup, ExDataFree);
857 g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
858 nullptr /* new_func */, ExDataDup, ExDataFree);
859
860 g_rsa_method.common.is_static = 1;
861 g_rsa_method.size = RsaMethodSize;
862 g_rsa_method.sign_raw = RsaMethodSignRaw;
863 g_rsa_method.decrypt = RsaMethodDecrypt;
864 g_rsa_method.flags = RSA_FLAG_OPAQUE;
865
866 g_ecdsa_method.common.is_static = 1;
867 g_ecdsa_method.sign = EcdsaMethodSign;
868 g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
869
870 g_engine = ENGINE_new();
871 ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
872 ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
873 }
874
875 } // anonymous namespace
876
877 #define THROW_SSLEXCEPTION (-2)
878 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
879 #define THROWN_EXCEPTION (-4)
880
881 /**
882 * Initialization phase for every OpenSSL job: Loads the Error strings, the
883 * crypto algorithms and reset the OpenSSL library
884 */
NativeCrypto_clinit(JNIEnv *,jclass)885 static void NativeCrypto_clinit(JNIEnv*, jclass) {
886 CRYPTO_library_init();
887 }
888
889 /**
890 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
891 */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)892 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
893 jbyteArray d, jbyteArray p, jbyteArray q,
894 jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
895 CHECK_ERROR_QUEUE_ON_RETURN;
896 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,
897 p, q, dmp1, dmq1, iqmp);
898
899 bssl::UniquePtr<RSA> rsa(RSA_new());
900 if (rsa.get() == nullptr) {
901 conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
902 return 0;
903 }
904
905 if (e == nullptr && d == nullptr) {
906 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
907 "e == null && d == null");
908 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
909 return 0;
910 }
911
912 if (!arrayToBignum(env, n, &rsa->n)) {
913 return 0;
914 }
915
916 if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
917 return 0;
918 }
919
920 if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
921 return 0;
922 }
923
924 if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
925 return 0;
926 }
927
928 if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
929 return 0;
930 }
931
932 if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
933 return 0;
934 }
935
936 if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
937 return 0;
938 }
939
940 if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
941 return 0;
942 }
943
944 if (conscrypt::trace::kWithJniTrace) {
945 if (p != nullptr && q != nullptr) {
946 int check = RSA_check_key(rsa.get());
947 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
948 }
949 }
950
951 if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
952 conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
953 return 0;
954 }
955
956 /*
957 * If the private exponent is available, there is the potential to do signing
958 * operations. However, we can only do blinding if the public exponent is also
959 * available. Disable blinding if the public exponent isn't available.
960 *
961 * TODO[kroot]: We should try to recover the public exponent by trying
962 * some common ones such 3, 17, or 65537.
963 */
964 if (rsa->d != nullptr && rsa->e == nullptr) {
965 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
966 rsa->flags |= RSA_FLAG_NO_BLINDING;
967 }
968
969 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
970 if (pkey.get() == nullptr) {
971 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
972 return 0;
973 }
974 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
975 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
976 ERR_clear_error();
977 return 0;
978 }
979 OWNERSHIP_TRANSFERRED(rsa);
980 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
981 e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
982 return reinterpret_cast<uintptr_t>(pkey.release());
983 }
984
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)985 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
986 jobject pubkeyRef, jbyteArray keyJavaBytes) {
987 CHECK_ERROR_QUEUE_ON_RETURN;
988 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
989 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
990 if (group == nullptr) {
991 return 0;
992 }
993 const EC_POINT* pubkey =
994 pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
995 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
996
997 bssl::UniquePtr<BIGNUM> key(nullptr);
998 if (keyJavaBytes != nullptr) {
999 BIGNUM* keyRef = nullptr;
1000 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
1001 return 0;
1002 }
1003 key.reset(keyRef);
1004 }
1005
1006 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
1007 if (eckey.get() == nullptr) {
1008 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1009 return 0;
1010 }
1011
1012 if (EC_KEY_set_group(eckey.get(), group) != 1) {
1013 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1014 keyJavaBytes);
1015 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1016 return 0;
1017 }
1018
1019 if (pubkey != nullptr) {
1020 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1021 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1022 pubkey, keyJavaBytes);
1023 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1024 return 0;
1025 }
1026 }
1027
1028 if (key.get() != nullptr) {
1029 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1030 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1031 pubkey, keyJavaBytes);
1032 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1033 return 0;
1034 }
1035 if (pubkey == nullptr) {
1036 bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1037 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1038 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1039 pubkey, keyJavaBytes);
1040 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1041 return 0;
1042 }
1043 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1044 }
1045 }
1046
1047 if (!EC_KEY_check_key(eckey.get())) {
1048 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1049 keyJavaBytes);
1050 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1051 return 0;
1052 }
1053
1054 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1055 if (pkey.get() == nullptr) {
1056 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1057 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1058 return 0;
1059 }
1060 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1061 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1062 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1063 ERR_clear_error();
1064 return 0;
1065 }
1066 OWNERSHIP_TRANSFERRED(eckey);
1067
1068 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1069 return reinterpret_cast<uintptr_t>(pkey.release());
1070 }
1071
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1072 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1073 CHECK_ERROR_QUEUE_ON_RETURN;
1074 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1075 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1076
1077 if (pkey == nullptr) {
1078 return -1;
1079 }
1080
1081 int result = EVP_PKEY_type(pkey->type);
1082 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1083 return result;
1084 }
1085
1086 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1087
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1088 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1089 const char* debug_name) {
1090 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1091 JNI_TRACE("%s(%p)", debug_name, pkey);
1092
1093 if (pkey == nullptr) {
1094 return nullptr;
1095 }
1096
1097 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1098 if (buffer.get() == nullptr) {
1099 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1100 return nullptr;
1101 }
1102
1103 if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1104 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1105 return nullptr;
1106 }
1107 // Null terminate this
1108 BIO_write(buffer.get(), "\0", 1);
1109
1110 char* tmp;
1111 BIO_get_mem_data(buffer.get(), &tmp);
1112 jstring description = env->NewStringUTF(tmp);
1113
1114 JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1115 return description;
1116 }
1117
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1118 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1119 CHECK_ERROR_QUEUE_ON_RETURN;
1120 return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1121 }
1122
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1123 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1124 CHECK_ERROR_QUEUE_ON_RETURN;
1125 return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1126 }
1127
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1128 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1129 CHECK_ERROR_QUEUE_ON_RETURN;
1130 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1131 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1132
1133 if (pkey != nullptr) {
1134 EVP_PKEY_free(pkey);
1135 }
1136 }
1137
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1138 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1139 CHECK_ERROR_QUEUE_ON_RETURN;
1140 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1141 EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1142 if (pkey1 == nullptr) {
1143 JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1144 return 0;
1145 }
1146 EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1147 if (pkey2 == nullptr) {
1148 JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1149 return 0;
1150 }
1151 JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1152
1153 int result = EVP_PKEY_cmp(pkey1, pkey2);
1154 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1155 return result;
1156 }
1157
1158 /*
1159 * static native byte[] EVP_marshal_private_key(long)
1160 */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1161 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1162 CHECK_ERROR_QUEUE_ON_RETURN;
1163 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1164 JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1165
1166 if (pkey == nullptr) {
1167 return nullptr;
1168 }
1169
1170 bssl::ScopedCBB cbb;
1171 if (!CBB_init(cbb.get(), 64)) {
1172 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1173 JNI_TRACE("CBB_init failed");
1174 return nullptr;
1175 }
1176
1177 if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1178 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1179 JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1180 return nullptr;
1181 }
1182
1183 return CBBToByteArray(env, cbb.get());
1184 }
1185
1186 /*
1187 * static native long EVP_parse_private_key(byte[])
1188 */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1189 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1190 CHECK_ERROR_QUEUE_ON_RETURN;
1191 JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1192
1193 ScopedByteArrayRO bytes(env, keyJavaBytes);
1194 if (bytes.get() == nullptr) {
1195 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1196 return 0;
1197 }
1198
1199 CBS cbs;
1200 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1201 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1202 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1203 // allow parsing keys from buffers that are larger than the contained key structure
1204 // so we do the same for compatibility.
1205 if (!pkey) {
1206 conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1207 ERR_clear_error();
1208 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1209 return 0;
1210 }
1211
1212 JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1213 return reinterpret_cast<uintptr_t>(pkey.release());
1214 }
1215
1216 /*
1217 * static native byte[] EVP_marshal_public_key(long)
1218 */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1219 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1220 CHECK_ERROR_QUEUE_ON_RETURN;
1221 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1222 JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1223
1224 if (pkey == nullptr) {
1225 return nullptr;
1226 }
1227
1228 bssl::ScopedCBB cbb;
1229 if (!CBB_init(cbb.get(), 64)) {
1230 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1231 JNI_TRACE("CBB_init failed");
1232 return nullptr;
1233 }
1234
1235 if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1236 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1237 JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1238 return nullptr;
1239 }
1240
1241 return CBBToByteArray(env, cbb.get());
1242 }
1243
1244 /*
1245 * static native long EVP_parse_public_key(byte[])
1246 */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1247 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1248 CHECK_ERROR_QUEUE_ON_RETURN;
1249 JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1250
1251 ScopedByteArrayRO bytes(env, keyJavaBytes);
1252 if (bytes.get() == nullptr) {
1253 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1254 return 0;
1255 }
1256
1257 CBS cbs;
1258 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1259 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1260 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1261 // allow parsing keys from buffers that are larger than the contained key structure
1262 // so we do the same for compatibility.
1263 if (!pkey) {
1264 conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1265 ERR_clear_error();
1266 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1267 return 0;
1268 }
1269
1270 JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1271 return reinterpret_cast<uintptr_t>(pkey.release());
1272 }
1273
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1274 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1275 jbyteArray modulusBytes) {
1276 CHECK_ERROR_QUEUE_ON_RETURN;
1277 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1278
1279 size_t cached_size;
1280 if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
1281 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1282 return 0;
1283 }
1284
1285 ensure_engine_globals();
1286
1287 bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1288 if (rsa.get() == nullptr) {
1289 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1290 return 0;
1291 }
1292
1293 // The PSS padding code needs access to the actual n, so set it even though we
1294 // don't set any other parts of the key
1295 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1296 return 0;
1297 }
1298
1299 auto ex_data = new KeyExData;
1300 ex_data->private_key = env->NewGlobalRef(javaKey);
1301 ex_data->cached_size = cached_size;
1302 RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1303
1304 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1305 if (pkey.get() == nullptr) {
1306 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1307 conscrypt::jniutil::throwRuntimeException(env,
1308 "NativeCrypto_getRSAPrivateKeyWrapper failed");
1309 ERR_clear_error();
1310 return 0;
1311 }
1312
1313 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1314 conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1315 ERR_clear_error();
1316 return 0;
1317 }
1318 OWNERSHIP_TRANSFERRED(rsa);
1319 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1320 return reinterpret_cast<uintptr_t>(pkey.release());
1321 }
1322
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1323 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1324 jobject groupRef) {
1325 CHECK_ERROR_QUEUE_ON_RETURN;
1326 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1327 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1328 if (group == nullptr) {
1329 return 0;
1330 }
1331
1332 ensure_engine_globals();
1333
1334 bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1335 if (ecKey.get() == nullptr) {
1336 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1337 return 0;
1338 }
1339
1340 if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1341 JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1342 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1343 return 0;
1344 }
1345
1346 auto ex_data = new KeyExData;
1347 ex_data->private_key = env->NewGlobalRef(javaKey);
1348
1349 if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1350 env->DeleteGlobalRef(ex_data->private_key);
1351 delete ex_data;
1352 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1353 ERR_clear_error();
1354 return 0;
1355 }
1356
1357 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1358 if (pkey.get() == nullptr) {
1359 JNI_TRACE("getECPrivateKeyWrapper failed");
1360 conscrypt::jniutil::throwRuntimeException(env,
1361 "NativeCrypto_getECPrivateKeyWrapper failed");
1362 ERR_clear_error();
1363 return 0;
1364 }
1365
1366 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1367 conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1368 ERR_clear_error();
1369 return 0;
1370 }
1371 OWNERSHIP_TRANSFERRED(ecKey);
1372 return reinterpret_cast<uintptr_t>(pkey.release());
1373 }
1374
1375 /*
1376 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1377 */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1378 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1379 jbyteArray publicExponent) {
1380 CHECK_ERROR_QUEUE_ON_RETURN;
1381 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1382
1383 BIGNUM* eRef = nullptr;
1384 if (!arrayToBignum(env, publicExponent, &eRef)) {
1385 return 0;
1386 }
1387 bssl::UniquePtr<BIGNUM> e(eRef);
1388
1389 bssl::UniquePtr<RSA> rsa(RSA_new());
1390 if (rsa.get() == nullptr) {
1391 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1392 return 0;
1393 }
1394
1395 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1396 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1397 return 0;
1398 }
1399
1400 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1401 if (pkey.get() == nullptr) {
1402 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1403 return 0;
1404 }
1405
1406 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1407 conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1408 ERR_clear_error();
1409 return 0;
1410 }
1411
1412 OWNERSHIP_TRANSFERRED(rsa);
1413 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1414 return reinterpret_cast<uintptr_t>(pkey.release());
1415 }
1416
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1417 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1418 CHECK_ERROR_QUEUE_ON_RETURN;
1419 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1420 JNI_TRACE("RSA_size(%p)", pkey);
1421
1422 if (pkey == nullptr) {
1423 return 0;
1424 }
1425
1426 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1427 if (rsa.get() == nullptr) {
1428 conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1429 ERR_clear_error();
1430 return 0;
1431 }
1432
1433 return static_cast<jint>(RSA_size(rsa.get()));
1434 }
1435
1436 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1437 int padding);
1438
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1439 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1440 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1441 jobject pkeyRef, jint padding) {
1442 CHECK_ERROR_QUEUE_ON_RETURN;
1443 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1444 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1445
1446 if (pkey == nullptr) {
1447 return -1;
1448 }
1449
1450 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1451 if (rsa.get() == nullptr) {
1452 return -1;
1453 }
1454
1455 ScopedByteArrayRO from(env, fromJavaBytes);
1456 if (from.get() == nullptr) {
1457 return -1;
1458 }
1459
1460 ScopedByteArrayRW to(env, toJavaBytes);
1461 if (to.get() == nullptr) {
1462 return -1;
1463 }
1464
1465 int resultSize =
1466 operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1467 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1468 if (resultSize == -1) {
1469 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1470 conscrypt::jniutil::throwBadPaddingException);
1471 JNI_TRACE("%s => threw error", caller);
1472 return -1;
1473 }
1474
1475 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1476 resultSize);
1477 return static_cast<jint>(resultSize);
1478 }
1479
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1480 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1481 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1482 jobject pkeyRef, jint padding) {
1483 CHECK_ERROR_QUEUE_ON_RETURN;
1484 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1485 toJavaBytes, pkeyRef, padding);
1486 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1487 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1488 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1489 jobject pkeyRef, jint padding) {
1490 CHECK_ERROR_QUEUE_ON_RETURN;
1491 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1492 toJavaBytes, pkeyRef, padding);
1493 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1494 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1495 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1496 jobject pkeyRef, jint padding) {
1497 CHECK_ERROR_QUEUE_ON_RETURN;
1498 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1499 toJavaBytes, pkeyRef, padding);
1500 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1501 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1502 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1503 jobject pkeyRef, jint padding) {
1504 CHECK_ERROR_QUEUE_ON_RETURN;
1505 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1506 toJavaBytes, pkeyRef, padding);
1507 }
1508
1509 /*
1510 * public static native byte[][] get_RSA_public_params(long);
1511 */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1512 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1513 CHECK_ERROR_QUEUE_ON_RETURN;
1514 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1515 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1516
1517 if (pkey == nullptr) {
1518 return nullptr;
1519 }
1520
1521 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1522 if (rsa.get() == nullptr) {
1523 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1524 return nullptr;
1525 }
1526
1527 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1528 if (joa == nullptr) {
1529 return nullptr;
1530 }
1531
1532 jbyteArray n = bignumToArray(env, rsa->n, "n");
1533 if (env->ExceptionCheck()) {
1534 return nullptr;
1535 }
1536 env->SetObjectArrayElement(joa, 0, n);
1537
1538 jbyteArray e = bignumToArray(env, rsa->e, "e");
1539 if (env->ExceptionCheck()) {
1540 return nullptr;
1541 }
1542 env->SetObjectArrayElement(joa, 1, e);
1543
1544 return joa;
1545 }
1546
1547 /*
1548 * public static native byte[][] get_RSA_private_params(long);
1549 */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1550 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1551 CHECK_ERROR_QUEUE_ON_RETURN;
1552 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1553 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1554
1555 if (pkey == nullptr) {
1556 return nullptr;
1557 }
1558
1559 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1560 if (rsa.get() == nullptr) {
1561 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1562 return nullptr;
1563 }
1564
1565 jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1566 if (joa == nullptr) {
1567 return nullptr;
1568 }
1569
1570 jbyteArray n = bignumToArray(env, rsa->n, "n");
1571 if (env->ExceptionCheck()) {
1572 return nullptr;
1573 }
1574 env->SetObjectArrayElement(joa, 0, n);
1575
1576 if (rsa->e != nullptr) {
1577 jbyteArray e = bignumToArray(env, rsa->e, "e");
1578 if (env->ExceptionCheck()) {
1579 return nullptr;
1580 }
1581 env->SetObjectArrayElement(joa, 1, e);
1582 }
1583
1584 if (rsa->d != nullptr) {
1585 jbyteArray d = bignumToArray(env, rsa->d, "d");
1586 if (env->ExceptionCheck()) {
1587 return nullptr;
1588 }
1589 env->SetObjectArrayElement(joa, 2, d);
1590 }
1591
1592 if (rsa->p != nullptr) {
1593 jbyteArray p = bignumToArray(env, rsa->p, "p");
1594 if (env->ExceptionCheck()) {
1595 return nullptr;
1596 }
1597 env->SetObjectArrayElement(joa, 3, p);
1598 }
1599
1600 if (rsa->q != nullptr) {
1601 jbyteArray q = bignumToArray(env, rsa->q, "q");
1602 if (env->ExceptionCheck()) {
1603 return nullptr;
1604 }
1605 env->SetObjectArrayElement(joa, 4, q);
1606 }
1607
1608 if (rsa->dmp1 != nullptr) {
1609 jbyteArray dmp1 = bignumToArray(env, rsa->dmp1, "dmp1");
1610 if (env->ExceptionCheck()) {
1611 return nullptr;
1612 }
1613 env->SetObjectArrayElement(joa, 5, dmp1);
1614 }
1615
1616 if (rsa->dmq1 != nullptr) {
1617 jbyteArray dmq1 = bignumToArray(env, rsa->dmq1, "dmq1");
1618 if (env->ExceptionCheck()) {
1619 return nullptr;
1620 }
1621 env->SetObjectArrayElement(joa, 6, dmq1);
1622 }
1623
1624 if (rsa->iqmp != nullptr) {
1625 jbyteArray iqmp = bignumToArray(env, rsa->iqmp, "iqmp");
1626 if (env->ExceptionCheck()) {
1627 return nullptr;
1628 }
1629 env->SetObjectArrayElement(joa, 7, iqmp);
1630 }
1631
1632 return joa;
1633 }
1634
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1635 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1636 jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1637 jbyteArray nonceBytes, jint blockCounter) {
1638 CHECK_ERROR_QUEUE_ON_RETURN;
1639 JNI_TRACE("chacha20_encrypt_decrypt");
1640 ScopedByteArrayRO in(env, inBytes);
1641 if (in.get() == nullptr) {
1642 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1643 return;
1644 }
1645 ScopedByteArrayRW out(env, outBytes);
1646 if (out.get() == nullptr) {
1647 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1648 return;
1649 }
1650 ScopedByteArrayRO key(env, keyBytes);
1651 if (key.get() == nullptr) {
1652 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1653 return;
1654 }
1655 ScopedByteArrayRO nonce(env, nonceBytes);
1656 if (nonce.get() == nullptr) {
1657 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1658 return;
1659 }
1660
1661 CRYPTO_chacha_20(
1662 reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1663 reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1664 length,
1665 reinterpret_cast<const unsigned char*>(key.get()),
1666 reinterpret_cast<const unsigned char*>(nonce.get()),
1667 blockCounter);
1668 }
1669
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1670 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1671 CHECK_ERROR_QUEUE_ON_RETURN;
1672 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1673
1674 ScopedUtfChars curveName(env, curveNameJava);
1675 if (curveName.c_str() == nullptr) {
1676 return 0;
1677 }
1678 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1679
1680 int nid = OBJ_sn2nid(curveName.c_str());
1681 if (nid == NID_undef) {
1682 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1683 return 0;
1684 }
1685
1686 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1687 if (group == nullptr) {
1688 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1689 ERR_clear_error();
1690 return 0;
1691 }
1692
1693 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1694 return reinterpret_cast<uintptr_t>(group);
1695 }
1696
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1697 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1698 jbyteArray aBytes, jbyteArray bBytes,
1699 jbyteArray xBytes, jbyteArray yBytes,
1700 jbyteArray orderBytes, jint cofactorInt) {
1701 CHECK_ERROR_QUEUE_ON_RETURN;
1702 BIGNUM *p = nullptr, *a = nullptr, *b = nullptr, *x = nullptr, *y = nullptr;
1703 BIGNUM *order = nullptr, *cofactor = nullptr;
1704
1705 JNI_TRACE("EC_GROUP_new_arbitrary");
1706
1707 if (cofactorInt < 1) {
1708 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1709 "cofactor < 1");
1710 return 0;
1711 }
1712
1713 cofactor = BN_new();
1714 if (cofactor == nullptr) {
1715 return 0;
1716 }
1717
1718 int ok = 1;
1719
1720 if (!arrayToBignum(env, pBytes, &p) || !arrayToBignum(env, aBytes, &a) ||
1721 !arrayToBignum(env, bBytes, &b) || !arrayToBignum(env, xBytes, &x) ||
1722 !arrayToBignum(env, yBytes, &y) || !arrayToBignum(env, orderBytes, &order) ||
1723 !BN_set_word(cofactor, static_cast<uint32_t>(cofactorInt))) {
1724 ok = 0;
1725 }
1726
1727 bssl::UniquePtr<BIGNUM> pStorage(p);
1728 bssl::UniquePtr<BIGNUM> aStorage(a);
1729 bssl::UniquePtr<BIGNUM> bStorage(b);
1730 bssl::UniquePtr<BIGNUM> xStorage(x);
1731 bssl::UniquePtr<BIGNUM> yStorage(y);
1732 bssl::UniquePtr<BIGNUM> orderStorage(order);
1733 bssl::UniquePtr<BIGNUM> cofactorStorage(cofactor);
1734
1735 if (!ok) {
1736 return 0;
1737 }
1738
1739 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1740 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
1741 if (group.get() == nullptr) {
1742 JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1743 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1744 return 0;
1745 }
1746
1747 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1748 if (generator.get() == nullptr) {
1749 JNI_TRACE("EC_POINT_new => null");
1750 ERR_clear_error();
1751 return 0;
1752 }
1753
1754 if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
1755 JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1756 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1757 "EC_POINT_set_affine_coordinates_GFp");
1758 return 0;
1759 }
1760
1761 if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
1762 JNI_TRACE("EC_GROUP_set_generator => error");
1763 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1764 return 0;
1765 }
1766
1767 JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1768 return reinterpret_cast<uintptr_t>(group.release());
1769 }
1770
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1771 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1772 CHECK_ERROR_QUEUE_ON_RETURN;
1773 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1774 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1775
1776 if (group == nullptr) {
1777 JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1778 return nullptr;
1779 }
1780
1781 int nid = EC_GROUP_get_curve_name(group);
1782 if (nid == NID_undef) {
1783 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1784 return nullptr;
1785 }
1786
1787 const char* shortName = OBJ_nid2sn(nid);
1788 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1789 return env->NewStringUTF(shortName);
1790 }
1791
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1792 static jobjectArray NativeCrypto_EC_GROUP_get_curve(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_curve(%p)", group);
1796 if (group == nullptr) {
1797 JNI_TRACE("EC_GROUP_get_curve => group == null");
1798 return nullptr;
1799 }
1800
1801 bssl::UniquePtr<BIGNUM> p(BN_new());
1802 bssl::UniquePtr<BIGNUM> a(BN_new());
1803 bssl::UniquePtr<BIGNUM> b(BN_new());
1804
1805 int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1806 if (ret != 1) {
1807 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1808 return nullptr;
1809 }
1810
1811 jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1812 if (joa == nullptr) {
1813 return nullptr;
1814 }
1815
1816 jbyteArray pArray = bignumToArray(env, p.get(), "p");
1817 if (env->ExceptionCheck()) {
1818 return nullptr;
1819 }
1820 env->SetObjectArrayElement(joa, 0, pArray);
1821
1822 jbyteArray aArray = bignumToArray(env, a.get(), "a");
1823 if (env->ExceptionCheck()) {
1824 return nullptr;
1825 }
1826 env->SetObjectArrayElement(joa, 1, aArray);
1827
1828 jbyteArray bArray = bignumToArray(env, b.get(), "b");
1829 if (env->ExceptionCheck()) {
1830 return nullptr;
1831 }
1832 env->SetObjectArrayElement(joa, 2, bArray);
1833
1834 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1835 return joa;
1836 }
1837
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1838 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1839 CHECK_ERROR_QUEUE_ON_RETURN;
1840 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1841 JNI_TRACE("EC_GROUP_get_order(%p)", group);
1842 if (group == nullptr) {
1843 return nullptr;
1844 }
1845
1846 bssl::UniquePtr<BIGNUM> order(BN_new());
1847 if (order.get() == nullptr) {
1848 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1849 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1850 return nullptr;
1851 }
1852
1853 if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1854 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1855 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1856 return nullptr;
1857 }
1858
1859 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1860 if (env->ExceptionCheck()) {
1861 return nullptr;
1862 }
1863
1864 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1865 return orderArray;
1866 }
1867
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1868 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1869 CHECK_ERROR_QUEUE_ON_RETURN;
1870 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1871 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1872 if (group == nullptr) {
1873 return 0;
1874 }
1875
1876 jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1877 if (degree == 0) {
1878 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1879 conscrypt::jniutil::throwRuntimeException(env, "not supported");
1880 ERR_clear_error();
1881 return 0;
1882 }
1883
1884 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1885 return degree;
1886 }
1887
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1888 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1889 CHECK_ERROR_QUEUE_ON_RETURN;
1890 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1891 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1892 if (group == nullptr) {
1893 return nullptr;
1894 }
1895
1896 bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1897 if (cofactor.get() == nullptr) {
1898 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1899 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1900 return nullptr;
1901 }
1902
1903 if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1904 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1905 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1906 return nullptr;
1907 }
1908
1909 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1910 if (env->ExceptionCheck()) {
1911 return nullptr;
1912 }
1913
1914 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1915 return cofactorArray;
1916 }
1917
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1918 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1919 CHECK_ERROR_QUEUE_ON_RETURN;
1920 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1921 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1922
1923 if (group == nullptr) {
1924 JNI_TRACE("EC_GROUP_clear_free => group == null");
1925 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1926 return;
1927 }
1928
1929 EC_GROUP_free(group);
1930 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1931 }
1932
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1933 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1934 CHECK_ERROR_QUEUE_ON_RETURN;
1935 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1936 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1937
1938 if (group == nullptr) {
1939 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
1940 return 0;
1941 }
1942
1943 const EC_POINT* generator = EC_GROUP_get0_generator(group);
1944
1945 bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
1946 if (dup.get() == nullptr) {
1947 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
1948 conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
1949 return 0;
1950 }
1951
1952 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
1953 return reinterpret_cast<uintptr_t>(dup.release());
1954 }
1955
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)1956 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
1957 CHECK_ERROR_QUEUE_ON_RETURN;
1958 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1959 JNI_TRACE("EC_POINT_new(%p)", group);
1960
1961 if (group == nullptr) {
1962 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
1963 return 0;
1964 }
1965
1966 EC_POINT* point = EC_POINT_new(group);
1967 if (point == nullptr) {
1968 conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
1969 return 0;
1970 }
1971
1972 return reinterpret_cast<uintptr_t>(point);
1973 }
1974
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)1975 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1976 CHECK_ERROR_QUEUE_ON_RETURN;
1977 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
1978 JNI_TRACE("EC_POINT_clear_free(%p)", group);
1979
1980 if (group == nullptr) {
1981 JNI_TRACE("EC_POINT_clear_free => group == null");
1982 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1983 return;
1984 }
1985
1986 EC_POINT_free(group);
1987 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
1988 }
1989
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)1990 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
1991 jobject pointRef, jbyteArray xjavaBytes,
1992 jbyteArray yjavaBytes) {
1993 CHECK_ERROR_QUEUE_ON_RETURN;
1994 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
1995 yjavaBytes);
1996 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1997 if (group == nullptr) {
1998 return;
1999 }
2000 EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2001 if (point == nullptr) {
2002 return;
2003 }
2004 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
2005 yjavaBytes);
2006
2007 BIGNUM* xRef = nullptr;
2008 if (!arrayToBignum(env, xjavaBytes, &xRef)) {
2009 return;
2010 }
2011 bssl::UniquePtr<BIGNUM> x(xRef);
2012
2013 BIGNUM* yRef = nullptr;
2014 if (!arrayToBignum(env, yjavaBytes, &yRef)) {
2015 return;
2016 }
2017 bssl::UniquePtr<BIGNUM> y(yRef);
2018
2019 int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2020 if (ret != 1) {
2021 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2022 "EC_POINT_set_affine_coordinates");
2023 return;
2024 }
2025
2026 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2027 yjavaBytes, ret);
2028 }
2029
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2030 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2031 jobject groupRef,
2032 jobject pointRef) {
2033 CHECK_ERROR_QUEUE_ON_RETURN;
2034 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2035 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2036 if (group == nullptr) {
2037 return nullptr;
2038 }
2039 const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2040 if (point == nullptr) {
2041 return nullptr;
2042 }
2043 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2044
2045 bssl::UniquePtr<BIGNUM> x(BN_new());
2046 bssl::UniquePtr<BIGNUM> y(BN_new());
2047
2048 int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2049 if (ret != 1) {
2050 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2051 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2052 "EC_POINT_get_affine_coordinates");
2053 return nullptr;
2054 }
2055
2056 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2057 if (joa == nullptr) {
2058 return nullptr;
2059 }
2060
2061 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2062 if (env->ExceptionCheck()) {
2063 return nullptr;
2064 }
2065 env->SetObjectArrayElement(joa, 0, xBytes);
2066
2067 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2068 if (env->ExceptionCheck()) {
2069 return nullptr;
2070 }
2071 env->SetObjectArrayElement(joa, 1, yBytes);
2072
2073 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2074 return joa;
2075 }
2076
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2077 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2078 CHECK_ERROR_QUEUE_ON_RETURN;
2079 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2080 JNI_TRACE("EC_KEY_generate_key(%p)", group);
2081 if (group == nullptr) {
2082 return 0;
2083 }
2084
2085 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2086 if (eckey.get() == nullptr) {
2087 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2088 conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2089 return 0;
2090 }
2091
2092 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2093 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2094 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2095 return 0;
2096 }
2097
2098 if (EC_KEY_generate_key(eckey.get()) != 1) {
2099 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2100 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2101 return 0;
2102 }
2103
2104 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2105 if (pkey.get() == nullptr) {
2106 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2107 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2108 return 0;
2109 }
2110 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2111 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2112 ERR_clear_error();
2113 return 0;
2114 }
2115 OWNERSHIP_TRANSFERRED(eckey);
2116
2117 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2118 return reinterpret_cast<uintptr_t>(pkey.release());
2119 }
2120
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2121 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2122 CHECK_ERROR_QUEUE_ON_RETURN;
2123 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2124 JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2125
2126 if (pkey == nullptr) {
2127 JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2128 return 0;
2129 }
2130
2131 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
2132 conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2133 JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey,
2134 EVP_PKEY_type(pkey->type));
2135 return 0;
2136 }
2137
2138 EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(pkey->pkey.ec));
2139 JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2140 return reinterpret_cast<uintptr_t>(group);
2141 }
2142
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2143 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2144 CHECK_ERROR_QUEUE_ON_RETURN;
2145 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2146 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2147
2148 if (pkey == nullptr) {
2149 JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2150 return nullptr;
2151 }
2152
2153 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2154 if (eckey.get() == nullptr) {
2155 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2156 return nullptr;
2157 }
2158
2159 const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2160
2161 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2162 if (env->ExceptionCheck()) {
2163 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2164 return nullptr;
2165 }
2166
2167 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2168 return privBytes;
2169 }
2170
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2171 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2172 CHECK_ERROR_QUEUE_ON_RETURN;
2173 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2174 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2175
2176 if (pkey == nullptr) {
2177 JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2178 return 0;
2179 }
2180
2181 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2182 if (eckey.get() == nullptr) {
2183 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2184 return 0;
2185 }
2186
2187 bssl::UniquePtr<EC_POINT> dup(
2188 EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2189 if (dup.get() == nullptr) {
2190 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2191 conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2192 ERR_clear_error();
2193 return 0;
2194 }
2195
2196 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2197 return reinterpret_cast<uintptr_t>(dup.release());
2198 }
2199
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2200 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2201 CHECK_ERROR_QUEUE_ON_RETURN;
2202 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2203 JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2204 if (group == nullptr) {
2205 conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2206 return nullptr;
2207 }
2208
2209 bssl::ScopedCBB cbb;
2210 if (!CBB_init(cbb.get(), 64)) {
2211 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2212 JNI_TRACE("CBB_init failed");
2213 return nullptr;
2214 }
2215
2216 if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2217 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2218 ERR_clear_error();
2219 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2220 return nullptr;
2221 }
2222
2223 return CBBToByteArray(env, cbb.get());
2224 }
2225
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2226 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2227 CHECK_ERROR_QUEUE_ON_RETURN;
2228 JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2229
2230 ScopedByteArrayRO bytes(env, curveNameBytes);
2231 if (bytes.get() == nullptr) {
2232 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2233 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2234 return 0;
2235 }
2236
2237 CBS cbs;
2238 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2239 bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2240 if (!group || CBS_len(&cbs) != 0) {
2241 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2242 ERR_clear_error();
2243 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2244 return 0;
2245 }
2246
2247 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2248 return reinterpret_cast<uintptr_t>(group.release());
2249 }
2250
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2251 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2252 jobject pubkeyRef, jobject privkeyRef) {
2253 CHECK_ERROR_QUEUE_ON_RETURN;
2254 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2255 EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2256 if (pubPkey == nullptr) {
2257 JNI_TRACE("ECDH_compute_key => pubPkey == null");
2258 return -1;
2259 }
2260 EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2261 if (privPkey == nullptr) {
2262 JNI_TRACE("ECDH_compute_key => privPkey == null");
2263 return -1;
2264 }
2265 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2266
2267 ScopedByteArrayRW out(env, outArray);
2268 if (out.get() == nullptr) {
2269 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2270 pubPkey, privPkey);
2271 return -1;
2272 }
2273
2274 if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2275 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2276 nullptr);
2277 return -1;
2278 }
2279
2280 if (pubPkey == nullptr) {
2281 JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2282 conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2283 return -1;
2284 }
2285
2286 bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2287 if (pubkey.get() == nullptr) {
2288 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2289 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2290 conscrypt::jniutil::throwInvalidKeyException);
2291 return -1;
2292 }
2293
2294 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2295 if (pubkeyPoint == nullptr) {
2296 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2297 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2298 conscrypt::jniutil::throwInvalidKeyException);
2299 return -1;
2300 }
2301
2302 if (privPkey == nullptr) {
2303 JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2304 conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2305 return -1;
2306 }
2307
2308 bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2309 if (privkey.get() == nullptr) {
2310 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2311 conscrypt::jniutil::throwInvalidKeyException);
2312 return -1;
2313 }
2314
2315 std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2316 int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2317 privkey.get(), nullptr /* No KDF */);
2318 if (outputLength == -1) {
2319 JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2320 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2321 conscrypt::jniutil::throwInvalidKeyException);
2322 return -1;
2323 }
2324
2325 JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2326 return outputLength;
2327 }
2328
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2329 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2330 CHECK_ERROR_QUEUE_ON_RETURN;
2331 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2332 JNI_TRACE("ECDSA_size(%p)", pkey);
2333
2334 if (pkey == nullptr) {
2335 return 0;
2336 }
2337
2338 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2339 if (ec_key.get() == nullptr) {
2340 conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2341 ERR_clear_error();
2342 return 0;
2343 }
2344
2345 size_t size = ECDSA_size(ec_key.get());
2346
2347 JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2348 return static_cast<jint>(size);
2349 }
2350
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2351 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2352 jobject pkeyRef) {
2353 CHECK_ERROR_QUEUE_ON_RETURN;
2354 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2355 JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2356
2357 if (pkey == nullptr) {
2358 return -1;
2359 }
2360
2361 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2362 if (ec_key.get() == nullptr) {
2363 return -1;
2364 }
2365
2366 ScopedByteArrayRO data_array(env, data);
2367 if (data_array.get() == nullptr) {
2368 return -1;
2369 }
2370
2371 ScopedByteArrayRW sig_array(env, sig);
2372 if (sig_array.get() == nullptr) {
2373 return -1;
2374 }
2375
2376 unsigned int sig_size;
2377 int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2378 data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2379 &sig_size, ec_key.get());
2380 if (result == 0) {
2381 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2382 JNI_TRACE("ECDSA_sign => threw error");
2383 return -1;
2384 }
2385
2386 JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2387 return static_cast<jint>(sig_size);
2388 }
2389
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2390 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2391 jobject pkeyRef) {
2392 CHECK_ERROR_QUEUE_ON_RETURN;
2393 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2394 JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2395
2396 if (pkey == nullptr) {
2397 return -1;
2398 }
2399
2400 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2401 if (ec_key.get() == nullptr) {
2402 return -1;
2403 }
2404
2405 ScopedByteArrayRO data_array(env, data);
2406 if (data_array.get() == nullptr) {
2407 return -1;
2408 }
2409
2410 ScopedByteArrayRO sig_array(env, sig);
2411 if (sig_array.get() == nullptr) {
2412 return -1;
2413 }
2414
2415 int result =
2416 ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2417 data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2418 sig_array.size(), ec_key.get());
2419
2420 if (result == 0) {
2421 // NOLINTNEXTLINE(runtime/int)
2422 unsigned long error = ERR_peek_last_error();
2423 if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2424 (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2425 // This error just means the signature didn't verify, so clear the error and return
2426 // a failed verification
2427 ERR_clear_error();
2428 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2429 return 0;
2430 }
2431 if (error != 0) {
2432 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2433 JNI_TRACE("ECDSA_verify => threw error");
2434 return -1;
2435 }
2436 return 0;
2437 }
2438
2439 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2440 return static_cast<jint>(result);
2441 }
2442
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2443 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2444 CHECK_ERROR_QUEUE_ON_RETURN;
2445 JNI_TRACE_MD("EVP_MD_CTX_create()");
2446
2447 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2448 if (ctx.get() == nullptr) {
2449 conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2450 return 0;
2451 }
2452
2453 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2454 return reinterpret_cast<uintptr_t>(ctx.release());
2455 }
2456
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2457 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2458 CHECK_ERROR_QUEUE_ON_RETURN;
2459 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2460 JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2461
2462 if (ctx != nullptr) {
2463 EVP_MD_CTX_cleanup(ctx);
2464 }
2465 }
2466
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2467 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2468 CHECK_ERROR_QUEUE_ON_RETURN;
2469 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2470 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2471
2472 if (ctx != nullptr) {
2473 EVP_MD_CTX_destroy(ctx);
2474 }
2475 }
2476
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2477 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2478 jobject srcCtxRef) {
2479 CHECK_ERROR_QUEUE_ON_RETURN;
2480 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2481 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2482 if (dst_ctx == nullptr) {
2483 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2484 return 0;
2485 }
2486 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2487 if (src_ctx == nullptr) {
2488 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2489 return 0;
2490 }
2491 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2492
2493 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2494 if (result == 0) {
2495 conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2496 ERR_clear_error();
2497 }
2498
2499 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2500 return result;
2501 }
2502
2503 /*
2504 * public static native int EVP_DigestFinal_ex(long, byte[], int)
2505 */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2506 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2507 jint offset) {
2508 CHECK_ERROR_QUEUE_ON_RETURN;
2509 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2510 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2511
2512 if (ctx == nullptr) {
2513 JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2514 return -1;
2515 } else if (hash == nullptr) {
2516 conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2517 return -1;
2518 }
2519
2520 ScopedByteArrayRW hashBytes(env, hash);
2521 if (hashBytes.get() == nullptr) {
2522 return -1;
2523 }
2524 unsigned int bytesWritten = static_cast<unsigned int>(-1);
2525 int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2526 &bytesWritten);
2527 if (ok == 0) {
2528 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2529 return -1;
2530 }
2531
2532 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2533 return static_cast<jint>(bytesWritten);
2534 }
2535
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2536 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2537 jlong evpMdRef) {
2538 CHECK_ERROR_QUEUE_ON_RETURN;
2539 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2540 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2541 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2542
2543 if (ctx == nullptr) {
2544 JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2545 return 0;
2546 } else if (evp_md == nullptr) {
2547 conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2548 return 0;
2549 }
2550
2551 int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2552 if (ok == 0) {
2553 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2554 JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2555 return 0;
2556 }
2557 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2558 return ok;
2559 }
2560
2561 /*
2562 * public static native int EVP_get_digestbyname(java.lang.String)
2563 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2564 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2565 CHECK_ERROR_QUEUE_ON_RETURN;
2566 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2567
2568 if (algorithm == nullptr) {
2569 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2570 return -1;
2571 }
2572
2573 ScopedUtfChars algorithmChars(env, algorithm);
2574 if (algorithmChars.c_str() == nullptr) {
2575 return 0;
2576 }
2577 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2578
2579 const char* alg = algorithmChars.c_str();
2580 const EVP_MD* md;
2581
2582 if (strcasecmp(alg, "md4") == 0) {
2583 md = EVP_md4();
2584 } else if (strcasecmp(alg, "md5") == 0) {
2585 md = EVP_md5();
2586 } else if (strcasecmp(alg, "sha1") == 0) {
2587 md = EVP_sha1();
2588 } else if (strcasecmp(alg, "sha224") == 0) {
2589 md = EVP_sha224();
2590 } else if (strcasecmp(alg, "sha256") == 0) {
2591 md = EVP_sha256();
2592 } else if (strcasecmp(alg, "sha384") == 0) {
2593 md = EVP_sha384();
2594 } else if (strcasecmp(alg, "sha512") == 0) {
2595 md = EVP_sha512();
2596 } else {
2597 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2598 conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2599 return 0;
2600 }
2601
2602 return reinterpret_cast<uintptr_t>(md);
2603 }
2604
2605 /*
2606 * public static native int EVP_MD_size(long)
2607 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2608 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2609 CHECK_ERROR_QUEUE_ON_RETURN;
2610 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2611 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2612
2613 if (evp_md == nullptr) {
2614 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2615 return -1;
2616 }
2617
2618 jint result = static_cast<jint>(EVP_MD_size(evp_md));
2619 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2620 return result;
2621 }
2622
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)2623 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2624 int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2625 ENGINE*, EVP_PKEY*),
2626 const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2627 jobject pkeyRef) {
2628 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2629 if (mdCtx == nullptr) {
2630 JNI_TRACE("%s => mdCtx == null", jniName);
2631 return 0;
2632 }
2633 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2634 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2635 if (pkey == nullptr) {
2636 JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2637 return 0;
2638 }
2639 JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2640
2641 if (md == nullptr) {
2642 JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2643 conscrypt::jniutil::throwNullPointerException(env, "md == null");
2644 return 0;
2645 }
2646
2647 EVP_PKEY_CTX* pctx = nullptr;
2648 if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2649 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2650 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2651 return 0;
2652 }
2653
2654 JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2655 return reinterpret_cast<jlong>(pctx);
2656 }
2657
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2658 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2659 const jlong evpMdRef, jobject pkeyRef) {
2660 CHECK_ERROR_QUEUE_ON_RETURN;
2661 return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2662 evpMdRef, pkeyRef);
2663 }
2664
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2665 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2666 const jlong evpMdRef, jobject pkeyRef) {
2667 CHECK_ERROR_QUEUE_ON_RETURN;
2668 return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2669 evpMdRef, pkeyRef);
2670 }
2671
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2672 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2673 const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2674 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2675 const void* p = reinterpret_cast<const void*>(inPtr);
2676 JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2677
2678 if (mdCtx == nullptr) {
2679 return;
2680 }
2681
2682 if (p == nullptr) {
2683 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2684 return;
2685 }
2686
2687 if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2688 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2689 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2690 return;
2691 }
2692
2693 JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2694 }
2695
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2696 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2697 jint inLength, const char* jniName,
2698 int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2699 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2700 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2701
2702 if (mdCtx == nullptr) {
2703 return;
2704 }
2705
2706 if (inJavaBytes == nullptr) {
2707 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2708 return;
2709 }
2710
2711 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2712 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2713 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2714 "inBytes");
2715 return;
2716 }
2717 if (inLength == 0) {
2718 return;
2719 }
2720 jint in_offset = inOffset;
2721 jint in_size = inLength;
2722
2723 int update_func_result = -1;
2724 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2725 // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2726 // avoid copying the whole array.
2727 if (in_size <= 1024) {
2728 // For small chunk, it's more efficient to use a bit more space on the stack instead of
2729 // allocating a new buffer.
2730 jbyte buf[1024];
2731 env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2732 update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2733 static_cast<size_t>(in_size));
2734 } else {
2735 // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2736 // through the buffer, stopping as soon as update_func fails.
2737 jint remaining = in_size;
2738 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2739 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2740 if (buf.get() == nullptr) {
2741 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2742 return;
2743 }
2744 while (remaining > 0) {
2745 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2746 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2747 update_func_result =
2748 update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2749 static_cast<size_t>(chunk_size));
2750 if (!update_func_result) {
2751 // update_func failed. This will be handled later in this method.
2752 break;
2753 }
2754 in_offset += chunk_size;
2755 remaining -= chunk_size;
2756 }
2757 }
2758 } else {
2759 // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2760 // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2761 // use GetByteArrayElements or another approach.
2762 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2763 if (array_elements == nullptr) {
2764 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2765 return;
2766 }
2767 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2768 update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2769 env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2770 }
2771
2772 if (!update_func_result) {
2773 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2774 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2775 return;
2776 }
2777
2778 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2779 }
2780
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2781 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2782 jlong inPtr, jint inLength) {
2783 CHECK_ERROR_QUEUE_ON_RETURN;
2784 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2785 }
2786
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2787 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2788 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2789 CHECK_ERROR_QUEUE_ON_RETURN;
2790 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2791 EVP_DigestUpdate);
2792 }
2793
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2794 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2795 jbyteArray inJavaBytes, jint inOffset,
2796 jint inLength) {
2797 CHECK_ERROR_QUEUE_ON_RETURN;
2798 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2799 EVP_DigestSignUpdate);
2800 }
2801
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2802 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2803 jlong inPtr, jint inLength) {
2804 CHECK_ERROR_QUEUE_ON_RETURN;
2805 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2806 EVP_DigestSignUpdate);
2807 }
2808
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2809 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2810 jbyteArray inJavaBytes, jint inOffset,
2811 jint inLength) {
2812 CHECK_ERROR_QUEUE_ON_RETURN;
2813 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2814 EVP_DigestVerifyUpdate);
2815 }
2816
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2817 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2818 jlong inPtr, jint inLength) {
2819 CHECK_ERROR_QUEUE_ON_RETURN;
2820 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2821 EVP_DigestVerifyUpdate);
2822 }
2823
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2824 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2825 CHECK_ERROR_QUEUE_ON_RETURN;
2826 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2827 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2828
2829 if (mdCtx == nullptr) {
2830 return nullptr;
2831 }
2832
2833 size_t maxLen;
2834 if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2835 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2836 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2837 return nullptr;
2838 }
2839
2840 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2841 if (buffer.get() == nullptr) {
2842 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2843 return nullptr;
2844 }
2845 size_t actualLen(maxLen);
2846 if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2847 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2848 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2849 return nullptr;
2850 }
2851 if (actualLen > maxLen) {
2852 JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2853 maxLen);
2854 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2855 return nullptr;
2856 }
2857
2858 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2859 if (sigJavaBytes.get() == nullptr) {
2860 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2861 return nullptr;
2862 }
2863 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2864 reinterpret_cast<jbyte*>(buffer.get()));
2865
2866 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2867 return sigJavaBytes.release();
2868 }
2869
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2870 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2871 jbyteArray signature, jint offset, jint len) {
2872 CHECK_ERROR_QUEUE_ON_RETURN;
2873 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2874 JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2875
2876 if (mdCtx == nullptr) {
2877 return 0;
2878 }
2879
2880 ScopedByteArrayRO sigBytes(env, signature);
2881 if (sigBytes.get() == nullptr) {
2882 return 0;
2883 }
2884
2885 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
2886 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2887 "signature");
2888 return 0;
2889 }
2890
2891 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
2892 int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
2893 jboolean result;
2894 if (err == 1) {
2895 // Signature verified
2896 result = 1;
2897 } else if (err == 0) {
2898 // Signature did not verify
2899 result = 0;
2900 } else {
2901 // Error while verifying signature
2902 JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
2903 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
2904 return 0;
2905 }
2906
2907 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
2908 // Clear the error queue to prevent its state from affecting future operations.
2909 ERR_clear_error();
2910
2911 JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
2912 return result;
2913 }
2914
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)2915 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
2916 int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
2917 const uint8_t*, size_t),
2918 const char* jniName, jobject evpPkeyCtxRef,
2919 jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
2920 jint inOffset, jint inLength) {
2921 EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
2922 JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
2923 inJavaBytes, inOffset, inLength);
2924
2925 if (pkeyCtx == nullptr) {
2926 return 0;
2927 }
2928
2929 ScopedByteArrayRW outBytes(env, outJavaBytes);
2930 if (outBytes.get() == nullptr) {
2931 return 0;
2932 }
2933
2934 ScopedByteArrayRO inBytes(env, inJavaBytes);
2935 if (inBytes.get() == nullptr) {
2936 return 0;
2937 }
2938
2939 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
2940 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2941 "outBytes");
2942 return 0;
2943 }
2944
2945 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
2946 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2947 "inBytes");
2948 return 0;
2949 }
2950
2951 uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
2952 const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
2953 size_t outLength = outBytes.size() - outOffset;
2954 if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
2955 static_cast<size_t>(inLength))) {
2956 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
2957 conscrypt::jniutil::throwExceptionFromBoringSSLError(
2958 env, jniName, conscrypt::jniutil::throwBadPaddingException);
2959 return 0;
2960 }
2961
2962 JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
2963 outOffset, inJavaBytes, inOffset, inLength, outLength);
2964 return static_cast<jint>(outLength);
2965 }
2966
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)2967 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
2968 jbyteArray out, jint outOffset, jbyteArray inBytes,
2969 jint inOffset, jint inLength) {
2970 CHECK_ERROR_QUEUE_ON_RETURN;
2971 return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
2972 outOffset, inBytes, inOffset, inLength);
2973 }
2974
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)2975 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
2976 jbyteArray out, jint outOffset, jbyteArray inBytes,
2977 jint inOffset, jint inLength) {
2978 CHECK_ERROR_QUEUE_ON_RETURN;
2979 return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
2980 outOffset, inBytes, inOffset, inLength);
2981 }
2982
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)2983 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
2984 int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
2985 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
2986 JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
2987 if (pkey == nullptr) {
2988 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
2989 return 0;
2990 }
2991
2992 bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
2993 if (pkeyCtx.get() == nullptr) {
2994 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
2995 conscrypt::jniutil::throwExceptionFromBoringSSLError(
2996 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
2997 return 0;
2998 }
2999
3000 if (!real_func(pkeyCtx.get())) {
3001 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3002 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3003 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3004 return 0;
3005 }
3006
3007 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3008 return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3009 }
3010
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3011 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3012 CHECK_ERROR_QUEUE_ON_RETURN;
3013 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3014 }
3015
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3016 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3017 CHECK_ERROR_QUEUE_ON_RETURN;
3018 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3019 }
3020
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3021 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3022 CHECK_ERROR_QUEUE_ON_RETURN;
3023 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3024 JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3025
3026 if (pkeyCtx != nullptr) {
3027 EVP_PKEY_CTX_free(pkeyCtx);
3028 }
3029 }
3030
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3031 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3032 CHECK_ERROR_QUEUE_ON_RETURN;
3033 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3034 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3035 if (pkeyCtx == nullptr) {
3036 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3037 return;
3038 }
3039
3040 int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3041 if (result <= 0) {
3042 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3043 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3044 env, "EVP_PKEY_CTX_set_rsa_padding",
3045 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3046 return;
3047 }
3048
3049 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3050 }
3051
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3052 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3053 jint len) {
3054 CHECK_ERROR_QUEUE_ON_RETURN;
3055 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3056 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3057 if (pkeyCtx == nullptr) {
3058 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3059 return;
3060 }
3061
3062 int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3063 if (result <= 0) {
3064 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3065 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3066 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3067 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3068 return;
3069 }
3070
3071 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3072 }
3073
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3074 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3075 int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3076 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3077 EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3078 JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3079 if (pkeyCtx == nullptr) {
3080 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3081 return;
3082 }
3083 if (md == nullptr) {
3084 conscrypt::jniutil::throwNullPointerException(env, "md == null");
3085 return;
3086 }
3087
3088 int result = ctrl_func(pkeyCtx, md);
3089 if (result <= 0) {
3090 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3091 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3092 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3093 return;
3094 }
3095
3096 JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3097 }
3098
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3099 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3100 jlong mdRef) {
3101 CHECK_ERROR_QUEUE_ON_RETURN;
3102 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3103 EVP_PKEY_CTX_set_rsa_mgf1_md);
3104 }
3105
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3106 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3107 jlong mdRef) {
3108 CHECK_ERROR_QUEUE_ON_RETURN;
3109 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3110 EVP_PKEY_CTX_set_rsa_oaep_md);
3111 }
3112
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3113 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3114 jbyteArray labelJava) {
3115 CHECK_ERROR_QUEUE_ON_RETURN;
3116 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3117 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3118 if (pkeyCtx == nullptr) {
3119 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3120 return;
3121 }
3122
3123 ScopedByteArrayRO labelBytes(env, labelJava);
3124 if (labelBytes.get() == nullptr) {
3125 return;
3126 }
3127
3128 bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3129 memcpy(label.get(), labelBytes.get(), labelBytes.size());
3130
3131 int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3132 if (result <= 0) {
3133 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3134 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3135 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3136 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3137 return;
3138 }
3139 OWNERSHIP_TRANSFERRED(label);
3140
3141 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3142 }
3143
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3144 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3145 CHECK_ERROR_QUEUE_ON_RETURN;
3146 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3147
3148 ScopedUtfChars scoped_alg(env, algorithm);
3149 const char* alg = scoped_alg.c_str();
3150 const EVP_CIPHER* cipher;
3151
3152 if (strcasecmp(alg, "rc4") == 0) {
3153 cipher = EVP_rc4();
3154 } else if (strcasecmp(alg, "des-cbc") == 0) {
3155 cipher = EVP_des_cbc();
3156 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3157 cipher = EVP_des_ede_cbc();
3158 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3159 cipher = EVP_des_ede3_cbc();
3160 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3161 cipher = EVP_aes_128_ecb();
3162 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3163 cipher = EVP_aes_128_cbc();
3164 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3165 cipher = EVP_aes_128_ctr();
3166 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3167 cipher = EVP_aes_128_gcm();
3168 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3169 cipher = EVP_aes_192_ecb();
3170 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3171 cipher = EVP_aes_192_cbc();
3172 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3173 cipher = EVP_aes_192_ctr();
3174 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3175 cipher = EVP_aes_192_gcm();
3176 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3177 cipher = EVP_aes_256_ecb();
3178 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3179 cipher = EVP_aes_256_cbc();
3180 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3181 cipher = EVP_aes_256_ctr();
3182 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3183 cipher = EVP_aes_256_gcm();
3184 } else {
3185 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
3186 return 0;
3187 }
3188
3189 return reinterpret_cast<uintptr_t>(cipher);
3190 }
3191
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3192 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3193 jbyteArray keyArray, jbyteArray ivArray,
3194 jboolean encrypting) {
3195 CHECK_ERROR_QUEUE_ON_RETURN;
3196 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3197 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3198 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3199 encrypting ? 1 : 0);
3200
3201 if (ctx == nullptr) {
3202 JNI_TRACE("EVP_CipherUpdate => ctx == null");
3203 return;
3204 }
3205
3206 // The key can be null if we need to set extra parameters.
3207 std::unique_ptr<unsigned char[]> keyPtr;
3208 if (keyArray != nullptr) {
3209 ScopedByteArrayRO keyBytes(env, keyArray);
3210 if (keyBytes.get() == nullptr) {
3211 return;
3212 }
3213
3214 keyPtr.reset(new unsigned char[keyBytes.size()]);
3215 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3216 }
3217
3218 // The IV can be null if we're using ECB.
3219 std::unique_ptr<unsigned char[]> ivPtr;
3220 if (ivArray != nullptr) {
3221 ScopedByteArrayRO ivBytes(env, ivArray);
3222 if (ivBytes.get() == nullptr) {
3223 return;
3224 }
3225
3226 ivPtr.reset(new unsigned char[ivBytes.size()]);
3227 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3228 }
3229
3230 if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3231 encrypting ? 1 : 0)) {
3232 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3233 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3234 return;
3235 }
3236
3237 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3238 encrypting ? 1 : 0);
3239 }
3240
3241 /*
3242 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3243 * int inOffset, int inLength);
3244 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3245 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3246 jint outOffset, jbyteArray inArray, jint inOffset,
3247 jint inLength) {
3248 CHECK_ERROR_QUEUE_ON_RETURN;
3249 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3250 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3251
3252 if (ctx == nullptr) {
3253 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3254 return 0;
3255 }
3256
3257 ScopedByteArrayRO inBytes(env, inArray);
3258 if (inBytes.get() == nullptr) {
3259 return 0;
3260 }
3261 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3262 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3263 "inBytes");
3264 return 0;
3265 }
3266
3267 ScopedByteArrayRW outBytes(env, outArray);
3268 if (outBytes.get() == nullptr) {
3269 return 0;
3270 }
3271 if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3272 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3273 "outBytes");
3274 return 0;
3275 }
3276
3277 JNI_TRACE(
3278 "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3279 "out.length=%zd outOffset=%d",
3280 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3281 outOffset);
3282
3283 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3284 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3285
3286 int outl;
3287 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3288 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3289 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3290 return 0;
3291 }
3292
3293 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3294 inOffset, outl);
3295 return outl;
3296 }
3297
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3298 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3299 jbyteArray outArray, jint outOffset) {
3300 CHECK_ERROR_QUEUE_ON_RETURN;
3301 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3302 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3303
3304 if (ctx == nullptr) {
3305 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3306 return 0;
3307 }
3308
3309 ScopedByteArrayRW outBytes(env, outArray);
3310 if (outBytes.get() == nullptr) {
3311 return 0;
3312 }
3313
3314 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3315
3316 int outl;
3317 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3318 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3319 conscrypt::jniutil::throwBadPaddingException);
3320 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3321 return 0;
3322 }
3323
3324 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3325 return outl;
3326 }
3327
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3328 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3329 CHECK_ERROR_QUEUE_ON_RETURN;
3330 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3331 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3332
3333 if (evpCipher == nullptr) {
3334 conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3335 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3336 return 0;
3337 }
3338
3339 jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3340 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3341 return ivLength;
3342 }
3343
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3344 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3345 CHECK_ERROR_QUEUE_ON_RETURN;
3346 JNI_TRACE("EVP_CIPHER_CTX_new()");
3347
3348 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3349 if (ctx.get() == nullptr) {
3350 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3351 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3352 return 0;
3353 }
3354
3355 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3356 return reinterpret_cast<uintptr_t>(ctx.release());
3357 }
3358
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3359 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3360 CHECK_ERROR_QUEUE_ON_RETURN;
3361 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3362 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3363
3364 if (ctx == nullptr) {
3365 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3366 return 0;
3367 }
3368
3369 jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3370 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3371 return blockSize;
3372 }
3373
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3374 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3375 CHECK_ERROR_QUEUE_ON_RETURN;
3376 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3377 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3378
3379 if (ctx == nullptr) {
3380 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3381 return 0;
3382 }
3383
3384 int buf_len = ctx->buf_len;
3385 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3386 return buf_len;
3387 }
3388
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3389 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3390 CHECK_ERROR_QUEUE_ON_RETURN;
3391 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3392 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3393
3394 if (ctx == nullptr) {
3395 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3396 return 0;
3397 }
3398
3399 bool final_used = ctx->final_used != 0;
3400 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3401 return static_cast<jboolean>(final_used);
3402 }
3403
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3404 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3405 jboolean enablePaddingBool) {
3406 CHECK_ERROR_QUEUE_ON_RETURN;
3407 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3408 jint enablePadding = enablePaddingBool ? 1 : 0;
3409 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3410
3411 if (ctx == nullptr) {
3412 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3413 return;
3414 }
3415
3416 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3417 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3418 }
3419
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3420 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3421 jint keySizeBits) {
3422 CHECK_ERROR_QUEUE_ON_RETURN;
3423 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3424 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3425
3426 if (ctx == nullptr) {
3427 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3428 return;
3429 }
3430
3431 if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3432 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3433 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3434 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3435 return;
3436 }
3437 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3438 }
3439
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3440 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3441 CHECK_ERROR_QUEUE_ON_RETURN;
3442 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3443 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3444
3445 EVP_CIPHER_CTX_free(ctx);
3446 }
3447
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3448 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3449 CHECK_ERROR_QUEUE_ON_RETURN;
3450 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3451 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3452 return reinterpret_cast<jlong>(ctx);
3453 }
3454
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3455 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3456 CHECK_ERROR_QUEUE_ON_RETURN;
3457 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3458 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3459 return reinterpret_cast<jlong>(ctx);
3460 }
3461
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3462 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3463 CHECK_ERROR_QUEUE_ON_RETURN;
3464 const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3465 JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3466 return reinterpret_cast<jlong>(ctx);
3467 }
3468
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3469 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3470 CHECK_ERROR_QUEUE_ON_RETURN;
3471 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3472 JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3473 return reinterpret_cast<jlong>(ctx);
3474 }
3475
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3476 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3477 CHECK_ERROR_QUEUE_ON_RETURN;
3478 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3479 JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3480 return reinterpret_cast<jlong>(ctx);
3481 }
3482
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3483 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3484 CHECK_ERROR_QUEUE_ON_RETURN;
3485 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3486 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3487 if (evpAead == nullptr) {
3488 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3489 return 0;
3490 }
3491 jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3492 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3493 return maxOverhead;
3494 }
3495
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3496 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3497 CHECK_ERROR_QUEUE_ON_RETURN;
3498 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3499 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3500 if (evpAead == nullptr) {
3501 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3502 return 0;
3503 }
3504 jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3505 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3506 return nonceLength;
3507 }
3508
3509 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3510 size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3511 const uint8_t* in, size_t in_len, const uint8_t* ad,
3512 size_t ad_len);
3513
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)3514 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3515 jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3516 jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3517 evp_aead_ctx_op_func realFunc) {
3518 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3519 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3520 outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3521
3522 ScopedByteArrayRO keyBytes(env, keyArray);
3523 if (keyBytes.get() == nullptr) {
3524 return 0;
3525 }
3526
3527 ScopedByteArrayRW outBytes(env, outArray);
3528 if (outBytes.get() == nullptr) {
3529 return 0;
3530 }
3531
3532 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3533 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3534 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3535 inLength, aadArray);
3536 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3537 return 0;
3538 }
3539
3540 ScopedByteArrayRO inBytes(env, inArray);
3541 if (inBytes.get() == nullptr) {
3542 return 0;
3543 }
3544
3545 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3546 JNI_TRACE(
3547 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3548 "invalid",
3549 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3550 inLength, aadArray);
3551 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3552 return 0;
3553 }
3554
3555 std::unique_ptr<ScopedByteArrayRO> aad;
3556 const uint8_t* aad_chars = nullptr;
3557 size_t aad_chars_size = 0;
3558 if (aadArray != nullptr) {
3559 aad.reset(new ScopedByteArrayRO(env, aadArray));
3560 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3561 if (aad_chars == nullptr) {
3562 return 0;
3563 }
3564 aad_chars_size = aad->size();
3565 }
3566
3567 ScopedByteArrayRO nonceBytes(env, nonceArray);
3568 if (nonceBytes.get() == nullptr) {
3569 return 0;
3570 }
3571
3572 bssl::ScopedEVP_AEAD_CTX aeadCtx;
3573 const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3574 if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3575 static_cast<size_t>(tagLen), nullptr)) {
3576 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3577 "failure initializing AEAD context");
3578 JNI_TRACE(
3579 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => fail EVP_AEAD_CTX_init",
3580 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3581 inLength, aadArray);
3582 return 0;
3583 }
3584
3585 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3586 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3587 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3588 size_t actualOutLength;
3589 if (!realFunc(aeadCtx.get(), outTmp + outOffset, &actualOutLength, outBytes.size() - outOffset,
3590 nonceTmp, nonceBytes.size(), inTmp + inOffset, static_cast<size_t>(inLength),
3591 aad_chars, aad_chars_size)) {
3592 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3593 return 0;
3594 }
3595
3596 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => success outlength=%zd",
3597 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3598 inLength, aadArray, actualOutLength);
3599 return static_cast<jint>(actualOutLength);
3600 }
3601
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)3602 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3603 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3604 jint outOffset, jbyteArray nonceArray,
3605 jbyteArray inArray, jint inOffset, jint inLength,
3606 jbyteArray aadArray) {
3607 CHECK_ERROR_QUEUE_ON_RETURN;
3608 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3609 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3610 }
3611
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)3612 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3613 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3614 jint outOffset, jbyteArray nonceArray,
3615 jbyteArray inArray, jint inOffset, jint inLength,
3616 jbyteArray aadArray) {
3617 CHECK_ERROR_QUEUE_ON_RETURN;
3618 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3619 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3620 }
3621
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)3622 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
3623 CHECK_ERROR_QUEUE_ON_RETURN;
3624 JNI_TRACE("HMAC_CTX_new");
3625 auto hmacCtx = new HMAC_CTX;
3626 if (hmacCtx == nullptr) {
3627 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
3628 return 0;
3629 }
3630
3631 HMAC_CTX_init(hmacCtx);
3632 return reinterpret_cast<jlong>(hmacCtx);
3633 }
3634
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)3635 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
3636 CHECK_ERROR_QUEUE_ON_RETURN;
3637 HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
3638 JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
3639 if (hmacCtx == nullptr) {
3640 return;
3641 }
3642 HMAC_CTX_cleanup(hmacCtx);
3643 delete hmacCtx;
3644 }
3645
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)3646 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
3647 jobject evpMdRef) {
3648 CHECK_ERROR_QUEUE_ON_RETURN;
3649 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3650 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3651 JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
3652 if (hmacCtx == nullptr) {
3653 return;
3654 }
3655 ScopedByteArrayRO keyBytes(env, keyArray);
3656 if (keyBytes.get() == nullptr) {
3657 return;
3658 }
3659
3660 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3661 if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
3662 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
3663 JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
3664 return;
3665 }
3666 }
3667
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)3668 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
3669 int inLength) {
3670 CHECK_ERROR_QUEUE_ON_RETURN;
3671 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3672 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3673 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
3674
3675 if (hmacCtx == nullptr) {
3676 return;
3677 }
3678
3679 if (p == nullptr) {
3680 conscrypt::jniutil::throwNullPointerException(env, nullptr);
3681 return;
3682 }
3683
3684 if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
3685 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
3686 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
3687 return;
3688 }
3689 }
3690
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,int inLength)3691 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
3692 jint inOffset, int inLength) {
3693 CHECK_ERROR_QUEUE_ON_RETURN;
3694 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3695 JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
3696
3697 if (hmacCtx == nullptr) {
3698 return;
3699 }
3700
3701 ScopedByteArrayRO inBytes(env, inArray);
3702 if (inBytes.get() == nullptr) {
3703 return;
3704 }
3705
3706 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3707 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3708 "inBytes");
3709 return;
3710 }
3711
3712 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
3713 if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
3714 JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
3715 inLength);
3716 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
3717 return;
3718 }
3719 }
3720
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)3721 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
3722 CHECK_ERROR_QUEUE_ON_RETURN;
3723 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3724 JNI_TRACE("HMAC_Final(%p)", hmacCtx);
3725
3726 if (hmacCtx == nullptr) {
3727 return nullptr;
3728 }
3729
3730 uint8_t result[EVP_MAX_MD_SIZE];
3731 unsigned len;
3732 if (!HMAC_Final(hmacCtx, result, &len)) {
3733 JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
3734 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
3735 return nullptr;
3736 }
3737
3738 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
3739 if (resultArray.get() == nullptr) {
3740 return nullptr;
3741 }
3742 ScopedByteArrayRW resultBytes(env, resultArray.get());
3743 if (resultBytes.get() == nullptr) {
3744 return nullptr;
3745 }
3746 memcpy(resultBytes.get(), result, len);
3747 return resultArray.release();
3748 }
3749
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)3750 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
3751 CHECK_ERROR_QUEUE_ON_RETURN;
3752 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
3753
3754 ScopedByteArrayRW outputBytes(env, output);
3755 if (outputBytes.get() == nullptr) {
3756 return;
3757 }
3758
3759 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
3760 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
3761 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
3762 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
3763 return;
3764 }
3765
3766 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
3767 }
3768
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)3769 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
3770 /*
3771 * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
3772 * Just make a buffer that's large enough here. The documentation recommends
3773 * 80 characters.
3774 */
3775 char output[128];
3776 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
3777 if (ret < 0) {
3778 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
3779 return nullptr;
3780 } else if (size_t(ret) >= sizeof(output)) {
3781 conscrypt::jniutil::throwRuntimeException(env,
3782 "ASN1_OBJECT_to_OID_string buffer too small");
3783 return nullptr;
3784 }
3785
3786 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
3787 return env->NewStringUTF(output);
3788 }
3789
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)3790 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
3791 jboolean isFinite) {
3792 CHECK_ERROR_QUEUE_ON_RETURN;
3793 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
3794
3795 if (streamObj == nullptr) {
3796 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
3797 return 0;
3798 }
3799
3800 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
3801 if (bio.get() == nullptr) {
3802 return 0;
3803 }
3804
3805 bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
3806
3807 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
3808 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
3809 }
3810
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)3811 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
3812 CHECK_ERROR_QUEUE_ON_RETURN;
3813 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
3814
3815 if (streamObj == nullptr) {
3816 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
3817 return 0;
3818 }
3819
3820 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
3821 if (bio.get() == nullptr) {
3822 return 0;
3823 }
3824
3825 bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
3826
3827 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
3828 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
3829 }
3830
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)3831 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
3832 CHECK_ERROR_QUEUE_ON_RETURN;
3833 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
3834 JNI_TRACE("BIO_free_all(%p)", bio);
3835
3836 if (bio == nullptr) {
3837 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
3838 return;
3839 }
3840
3841 BIO_free_all(bio);
3842 }
3843
3844 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)3845 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
3846 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
3847
3848 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
3849 if (buffer.get() == nullptr) {
3850 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
3851 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
3852 return nullptr;
3853 }
3854
3855 /* Don't interpret the string. */
3856 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
3857
3858 /* Write in given format and null terminate. */
3859 X509_NAME_print_ex(buffer.get(), name, 0, flags);
3860 BIO_write(buffer.get(), "\0", 1);
3861
3862 char* tmp;
3863 BIO_get_mem_data(buffer.get(), &tmp);
3864 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
3865 return env->NewStringUTF(tmp);
3866 }
3867
3868 /**
3869 * Converts GENERAL_NAME items to the output format expected in
3870 * X509Certificate#getSubjectAlternativeNames and
3871 * X509Certificate#getIssuerAlternativeNames return.
3872 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)3873 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
3874 switch (gen->type) {
3875 case GEN_EMAIL:
3876 case GEN_DNS:
3877 case GEN_URI: {
3878 // This must not be a T61String and must not contain NULs.
3879 const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
3880 ssize_t len = ASN1_STRING_length(gen->d.ia5);
3881 if ((len == static_cast<ssize_t>(strlen(data))) &&
3882 (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
3883 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
3884 return env->NewStringUTF(data);
3885 } else {
3886 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
3887 return nullptr;
3888 }
3889 }
3890 case GEN_DIRNAME:
3891 /* Write in RFC 2253 format */
3892 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
3893 case GEN_IPADD: {
3894 #ifdef _WIN32
3895 void* ip = reinterpret_cast<void*>(gen->d.ip->data);
3896 #else
3897 const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
3898 #endif
3899 if (gen->d.ip->length == 4) {
3900 // IPv4
3901 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
3902 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
3903 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
3904 return env->NewStringUTF(buffer.get());
3905 } else {
3906 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
3907 strerror(errno));
3908 }
3909 } else if (gen->d.ip->length == 16) {
3910 // IPv6
3911 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
3912 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
3913 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
3914 return env->NewStringUTF(buffer.get());
3915 } else {
3916 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
3917 strerror(errno));
3918 }
3919 }
3920
3921 /* Invalid IP encodings are pruned out without throwing an exception. */
3922 return nullptr;
3923 }
3924 case GEN_RID:
3925 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
3926 case GEN_OTHERNAME:
3927 case GEN_X400:
3928 default:
3929 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
3930 }
3931
3932 return nullptr;
3933 }
3934
3935 #define GN_STACK_SUBJECT_ALT_NAME 1
3936 #define GN_STACK_ISSUER_ALT_NAME 2
3937
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)3938 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
3939 CONSCRYPT_UNUSED jobject holder,
3940 jint type) {
3941 CHECK_ERROR_QUEUE_ON_RETURN;
3942 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
3943 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
3944
3945 if (x509 == nullptr) {
3946 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
3947 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
3948 return nullptr;
3949 }
3950
3951 X509_check_ca(x509);
3952
3953 STACK_OF(GENERAL_NAME) * gn_stack;
3954 bssl::UniquePtr<STACK_OF(GENERAL_NAME)> stackHolder;
3955 if (type == GN_STACK_SUBJECT_ALT_NAME) {
3956 gn_stack = x509->altname;
3957 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
3958 stackHolder.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
3959 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
3960 gn_stack = stackHolder.get();
3961 } else {
3962 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
3963 return nullptr;
3964 }
3965
3966 int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack));
3967 if (count <= 0) {
3968 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
3969 return nullptr;
3970 }
3971
3972 /*
3973 * Keep track of how many originally so we can ignore any invalid
3974 * values later.
3975 */
3976 const int origCount = count;
3977
3978 ScopedLocalRef<jobjectArray> joa(
3979 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
3980 for (int i = 0, j = 0; i < origCount; i++, j++) {
3981 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, static_cast<size_t>(i));
3982 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
3983 if (env->ExceptionCheck()) {
3984 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
3985 x509, type);
3986 return nullptr;
3987 }
3988
3989 /*
3990 * If it's nullptr, we'll have to skip this, reduce the number of total
3991 * entries, and fix up the array later.
3992 */
3993 if (val.get() == nullptr) {
3994 j--;
3995 count--;
3996 continue;
3997 }
3998
3999 ScopedLocalRef<jobjectArray> item(
4000 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4001
4002 ScopedLocalRef<jobject> parsedType(
4003 env,
4004 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4005 conscrypt::jniutil::integer_valueOfMethod, gen->type));
4006 env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4007 env->SetObjectArrayElement(item.get(), 1, val.get());
4008
4009 env->SetObjectArrayElement(joa.get(), j, item.get());
4010 }
4011
4012 if (count == 0) {
4013 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4014 x509, type, origCount);
4015 joa.reset(nullptr);
4016 } else if (origCount != count) {
4017 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4018 count);
4019
4020 ScopedLocalRef<jobjectArray> joa_copy(
4021 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4022
4023 for (int i = 0; i < count; i++) {
4024 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4025 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4026 }
4027
4028 joa.reset(joa_copy.release());
4029 }
4030
4031 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4032 return joa.release();
4033 }
4034
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4035 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4036 CONSCRYPT_UNUSED jobject holder) {
4037 CHECK_ERROR_QUEUE_ON_RETURN;
4038 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4039 JNI_TRACE("X509_get_notBefore(%p)", x509);
4040
4041 if (x509 == nullptr) {
4042 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4043 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4044 return 0;
4045 }
4046
4047 ASN1_TIME* notBefore = X509_get_notBefore(x509);
4048 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4049 return reinterpret_cast<uintptr_t>(notBefore);
4050 }
4051
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4052 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4053 CONSCRYPT_UNUSED jobject holder) {
4054 CHECK_ERROR_QUEUE_ON_RETURN;
4055 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4056 JNI_TRACE("X509_get_notAfter(%p)", x509);
4057
4058 if (x509 == nullptr) {
4059 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4060 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4061 return 0;
4062 }
4063
4064 ASN1_TIME* notAfter = X509_get_notAfter(x509);
4065 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4066 return reinterpret_cast<uintptr_t>(notAfter);
4067 }
4068
4069 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4070 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4071 CONSCRYPT_UNUSED jobject holder) {
4072 CHECK_ERROR_QUEUE_ON_RETURN;
4073 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4074 JNI_TRACE("X509_get_version(%p)", x509);
4075
4076 // NOLINTNEXTLINE(runtime/int)
4077 long version = X509_get_version(x509);
4078 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4079 return version;
4080 }
4081
4082 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,T * x509Type,ASN1_INTEGER * (* get_serial_func)(T *))4083 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type,
4084 ASN1_INTEGER* (*get_serial_func)(T*)) {
4085 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4086
4087 if (x509Type == nullptr) {
4088 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4089 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4090 return nullptr;
4091 }
4092
4093 ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4094 bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4095 if (serialBn.get() == nullptr) {
4096 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4097 return nullptr;
4098 }
4099
4100 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4101 if (env->ExceptionCheck()) {
4102 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4103 return nullptr;
4104 }
4105
4106 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4107 return serialArray.release();
4108 }
4109
4110 /* OpenSSL includes set_serialNumber but not get. */
4111 #if !defined(X509_REVOKED_get_serialNumber)
X509_REVOKED_get_serialNumber(X509_REVOKED * x)4112 static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) {
4113 return x->serialNumber;
4114 }
4115 #endif
4116
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4117 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4118 CONSCRYPT_UNUSED jobject holder) {
4119 CHECK_ERROR_QUEUE_ON_RETURN;
4120 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4121 JNI_TRACE("X509_get_serialNumber(%p)", x509);
4122 return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber);
4123 }
4124
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4125 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
4126 jlong x509RevokedRef) {
4127 CHECK_ERROR_QUEUE_ON_RETURN;
4128 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4129 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4130 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber);
4131 }
4132
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4133 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
4134 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4135 CHECK_ERROR_QUEUE_ON_RETURN;
4136 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4137 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4138 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4139
4140 if (pkey == nullptr) {
4141 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4142 return;
4143 }
4144
4145 if (x509 == nullptr) {
4146 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4147 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4148 return;
4149 }
4150
4151 if (X509_ALGOR_cmp(x509->sig_alg, X509_CINF_get_signature(X509_get_cert_info(x509)))) {
4152 conscrypt::jniutil::throwCertificateException(env,
4153 "Certificate signature algorithms do not match");
4154 JNI_TRACE("X509_verify(%p, %p) => signature alg mismatch", x509, pkey);
4155 return;
4156 }
4157
4158 if (X509_verify(x509, pkey) != 1) {
4159 conscrypt::jniutil::throwExceptionFromBoringSSLError(
4160 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
4161 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4162 return;
4163 }
4164 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4165 }
4166
NativeCrypto_get_X509_cert_info_enc(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4167 static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref,
4168 CONSCRYPT_UNUSED jobject holder) {
4169 CHECK_ERROR_QUEUE_ON_RETURN;
4170 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4171 JNI_TRACE("get_X509_cert_info_enc(%p)", x509);
4172 return ASN1ToByteArray<X509_CINF>(env, x509->cert_info, i2d_X509_CINF);
4173 }
4174
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4175 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
4176 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_ex_flags(%p)", x509);
4180
4181 if (x509 == nullptr) {
4182 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4183 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4184 return 0;
4185 }
4186
4187 X509_check_ca(x509);
4188
4189 return static_cast<jint>(x509->ex_flags);
4190 }
4191
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)4192 static jboolean NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
4193 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
4194 CONSCRYPT_UNUSED jobject holder2) {
4195 CHECK_ERROR_QUEUE_ON_RETURN;
4196 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4197 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4198 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4199
4200 int ret = X509_check_issued(x509_1, x509_2);
4201 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4202 return static_cast<jboolean>(ret);
4203 }
4204
get_X509_signature(X509 * x509,ASN1_BIT_STRING ** signature)4205 static void get_X509_signature(X509* x509, ASN1_BIT_STRING** signature) {
4206 *signature = x509->signature;
4207 }
4208
get_X509_CRL_signature(X509_CRL * crl,ASN1_BIT_STRING ** signature)4209 static void get_X509_CRL_signature(X509_CRL* crl, ASN1_BIT_STRING** signature) {
4210 *signature = crl->signature;
4211 }
4212
4213 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,void (* get_signature_func)(T *,ASN1_BIT_STRING **))4214 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
4215 void (*get_signature_func)(T*, ASN1_BIT_STRING**)) {
4216 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4217
4218 if (x509Type == nullptr) {
4219 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4220 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4221 return nullptr;
4222 }
4223
4224 ASN1_BIT_STRING* signature;
4225 get_signature_func(x509Type, &signature);
4226
4227 ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length));
4228 if (env->ExceptionCheck()) {
4229 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4230 return nullptr;
4231 }
4232
4233 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4234 if (signatureBytes.get() == nullptr) {
4235 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4236 return nullptr;
4237 }
4238
4239 memcpy(signatureBytes.get(), signature->data, signature->length);
4240
4241 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4242 signature->length);
4243 return signatureArray.release();
4244 }
4245
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4246 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
4247 CONSCRYPT_UNUSED jobject holder) {
4248 CHECK_ERROR_QUEUE_ON_RETURN;
4249 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4250 JNI_TRACE("get_X509_signature(%p)", x509);
4251 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4252 }
4253
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4254 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
4255 CONSCRYPT_UNUSED jobject holder) {
4256 CHECK_ERROR_QUEUE_ON_RETURN;
4257 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4258 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4259 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4260 }
4261
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)4262 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
4263 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
4264 CONSCRYPT_UNUSED jobject holder2) {
4265 CHECK_ERROR_QUEUE_ON_RETURN;
4266 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4267 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4268 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4269
4270 if (x509crl == nullptr) {
4271 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4272 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4273 return 0;
4274 } else if (x509 == nullptr) {
4275 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4276 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4277 return 0;
4278 }
4279
4280 X509_REVOKED* revoked = nullptr;
4281 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4282 if (ret == 0) {
4283 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4284 return 0;
4285 }
4286
4287 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4288 return reinterpret_cast<uintptr_t>(revoked);
4289 }
4290
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)4291 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
4292 CONSCRYPT_UNUSED jobject holder,
4293 jbyteArray serialArray) {
4294 CHECK_ERROR_QUEUE_ON_RETURN;
4295 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4296 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4297
4298 if (x509crl == nullptr) {
4299 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4300 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4301 return 0;
4302 }
4303
4304 bssl::UniquePtr<BIGNUM> serialBn(BN_new());
4305 if (serialBn.get() == nullptr) {
4306 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4307 return 0;
4308 }
4309
4310 BIGNUM* serialBare = serialBn.get();
4311 if (!arrayToBignum(env, serialArray, &serialBare)) {
4312 if (!env->ExceptionCheck()) {
4313 conscrypt::jniutil::throwNullPointerException(env, "serial == null");
4314 }
4315 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4316 return 0;
4317 }
4318
4319 bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
4320 if (serialInteger.get() == nullptr) {
4321 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4322 return 0;
4323 }
4324
4325 X509_REVOKED* revoked = nullptr;
4326 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4327 if (ret == 0) {
4328 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4329 return 0;
4330 }
4331
4332 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4333 return reinterpret_cast<uintptr_t>(revoked);
4334 }
4335
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4336 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
4337 CONSCRYPT_UNUSED jobject holder) {
4338 CHECK_ERROR_QUEUE_ON_RETURN;
4339 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4340 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4341
4342 if (crl == nullptr) {
4343 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4344 return nullptr;
4345 }
4346
4347 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4348 if (stack == nullptr) {
4349 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4350 return nullptr;
4351 }
4352
4353 size_t size = sk_X509_REVOKED_num(stack);
4354
4355 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
4356 ScopedLongArrayRW revoked(env, revokedArray.get());
4357 for (size_t i = 0; i < size; i++) {
4358 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4359 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4360 }
4361
4362 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
4363 return revokedArray.release();
4364 }
4365
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4366 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
4367 CONSCRYPT_UNUSED jobject holder) {
4368 CHECK_ERROR_QUEUE_ON_RETURN;
4369 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4370 JNI_TRACE("i2d_X509_CRL(%p)", crl);
4371 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
4372 }
4373
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4374 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
4375 CONSCRYPT_UNUSED jobject holder) {
4376 CHECK_ERROR_QUEUE_ON_RETURN;
4377 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4378 JNI_TRACE("X509_CRL_free(%p)", crl);
4379
4380 if (crl == nullptr) {
4381 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4382 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4383 return;
4384 }
4385
4386 X509_CRL_free(crl);
4387 }
4388
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4389 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
4390 CONSCRYPT_UNUSED jobject holder) {
4391 CHECK_ERROR_QUEUE_ON_RETURN;
4392 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4393 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4394 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4395
4396 if (bio == nullptr) {
4397 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4398 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4399 return;
4400 }
4401
4402 if (crl == nullptr) {
4403 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4404 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4405 return;
4406 }
4407
4408 if (!X509_CRL_print(bio, crl)) {
4409 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
4410 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4411 return;
4412 }
4413 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4414 }
4415
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4416 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
4417 CONSCRYPT_UNUSED jobject holder) {
4418 CHECK_ERROR_QUEUE_ON_RETURN;
4419 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4420 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4421
4422 if (crl == nullptr || crl->sig_alg == nullptr) {
4423 conscrypt::jniutil::throwNullPointerException(env, "crl == null || crl->sig_alg == null");
4424 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
4425 return nullptr;
4426 }
4427
4428 return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm);
4429 }
4430
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4431 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
4432 CONSCRYPT_UNUSED jobject holder) {
4433 CHECK_ERROR_QUEUE_ON_RETURN;
4434 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4435 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4436
4437 if (crl == nullptr) {
4438 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4439 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4440 return nullptr;
4441 }
4442
4443 if (crl->sig_alg->parameter == nullptr) {
4444 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl);
4445 return nullptr;
4446 }
4447
4448 return ASN1ToByteArray<ASN1_TYPE>(env, crl->sig_alg->parameter, i2d_ASN1_TYPE);
4449 }
4450
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4451 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
4452 CONSCRYPT_UNUSED jobject holder) {
4453 CHECK_ERROR_QUEUE_ON_RETURN;
4454 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4455 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4456 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
4457 }
4458
4459 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4460 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
4461 CONSCRYPT_UNUSED jobject holder) {
4462 CHECK_ERROR_QUEUE_ON_RETURN;
4463 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4464 JNI_TRACE("X509_CRL_get_version(%p)", crl);
4465
4466 // NOLINTNEXTLINE(runtime/int)
4467 long version = X509_CRL_get_version(crl);
4468 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4469 return version;
4470 }
4471
4472 template <typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
4473 X509_EXTENSION* (*get_ext_func)(T*, int)>
X509Type_get_ext(JNIEnv * env,T * x509Type,jstring oidString)4474 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) {
4475 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4476
4477 if (x509Type == nullptr) {
4478 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4479 return nullptr;
4480 }
4481
4482 ScopedUtfChars oid(env, oidString);
4483 if (oid.c_str() == nullptr) {
4484 return nullptr;
4485 }
4486
4487 bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
4488 if (asn1.get() == nullptr) {
4489 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4490 ERR_clear_error();
4491 return nullptr;
4492 }
4493
4494 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4495 if (extIndex == -1) {
4496 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4497 return nullptr;
4498 }
4499
4500 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4501 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4502 return ext;
4503 }
4504
4505 template <typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
4506 X509_EXTENSION* (*get_ext_func)(T*, int)>
X509Type_get_ext_oid(JNIEnv * env,T * x509Type,jstring oidString)4507 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) {
4508 X509_EXTENSION* ext =
4509 X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
4510 if (ext == nullptr) {
4511 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4512 return nullptr;
4513 }
4514
4515 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value);
4516 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, ext->value, i2d_ASN1_OCTET_STRING);
4517 }
4518
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)4519 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
4520 CONSCRYPT_UNUSED jobject holder, jstring oid) {
4521 CHECK_ERROR_QUEUE_ON_RETURN;
4522 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4523 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4524 X509_EXTENSION* ext =
4525 X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
4526 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4527 return reinterpret_cast<uintptr_t>(ext);
4528 }
4529
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)4530 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4531 jstring oid) {
4532 CHECK_ERROR_QUEUE_ON_RETURN;
4533 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4534 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4535 X509_EXTENSION* ext =
4536 X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
4537 env, revoked, oid);
4538 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4539 return reinterpret_cast<uintptr_t>(ext);
4540 }
4541
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)4542 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4543 CHECK_ERROR_QUEUE_ON_RETURN;
4544 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4545 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4546
4547 if (revoked == nullptr) {
4548 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4549 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4550 return 0;
4551 }
4552
4553 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4554 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4555 return reinterpret_cast<uintptr_t>(dup);
4556 }
4557
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)4558 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
4559 jlong x509RevokedRef) {
4560 CHECK_ERROR_QUEUE_ON_RETURN;
4561 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4562 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
4563
4564 if (revoked == nullptr) {
4565 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4566 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
4567 return 0;
4568 }
4569
4570 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate);
4571 return reinterpret_cast<uintptr_t>(revoked->revocationDate);
4572 }
4573
4574 #ifdef __GNUC__
4575 #pragma GCC diagnostic push
4576 #pragma GCC diagnostic ignored "-Wwrite-strings"
4577 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)4578 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
4579 jlong x509RevokedRef) {
4580 CHECK_ERROR_QUEUE_ON_RETURN;
4581 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4582 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4583 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
4584
4585 if (bio == nullptr) {
4586 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4587 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
4588 return;
4589 }
4590
4591 if (revoked == nullptr) {
4592 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4593 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
4594 return;
4595 }
4596
4597 BIO_printf(bio, "Serial Number: ");
4598 i2a_ASN1_INTEGER(bio, revoked->serialNumber);
4599 BIO_printf(bio, "\nRevocation Date: ");
4600 ASN1_TIME_print(bio, revoked->revocationDate);
4601 BIO_printf(bio, "\n");
4602 X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
4603 }
4604 #ifndef _WIN32
4605 #pragma GCC diagnostic pop
4606 #endif
4607
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4608 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
4609 CONSCRYPT_UNUSED jobject holder) {
4610 CHECK_ERROR_QUEUE_ON_RETURN;
4611 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4612 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
4613 return ASN1ToByteArray<X509_CRL_INFO>(env, crl->crl, i2d_X509_CRL_INFO);
4614 }
4615
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4616 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
4617 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4618 CHECK_ERROR_QUEUE_ON_RETURN;
4619 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4620 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4621 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
4622
4623 if (pkey == nullptr) {
4624 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
4625 return;
4626 }
4627
4628 if (crl == nullptr) {
4629 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4630 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
4631 return;
4632 }
4633
4634 if (X509_CRL_verify(crl, pkey) != 1) {
4635 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
4636 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
4637 return;
4638 }
4639 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
4640 }
4641
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4642 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
4643 CONSCRYPT_UNUSED jobject holder) {
4644 CHECK_ERROR_QUEUE_ON_RETURN;
4645 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4646 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
4647
4648 if (crl == nullptr) {
4649 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4650 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
4651 return 0;
4652 }
4653
4654 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
4655 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
4656 return reinterpret_cast<uintptr_t>(lastUpdate);
4657 }
4658
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4659 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
4660 CONSCRYPT_UNUSED jobject holder) {
4661 CHECK_ERROR_QUEUE_ON_RETURN;
4662 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4663 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
4664
4665 if (crl == nullptr) {
4666 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4667 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
4668 return 0;
4669 }
4670
4671 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
4672 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
4673 return reinterpret_cast<uintptr_t>(nextUpdate);
4674 }
4675
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)4676 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
4677 CHECK_ERROR_QUEUE_ON_RETURN;
4678 X509_REVOKED* x509Revoked =
4679 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4680 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
4681 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
4682 }
4683
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)4684 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
4685 CHECK_ERROR_QUEUE_ON_RETURN;
4686 X509_EXTENSION* ext =
4687 reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
4688
4689 if (ext == nullptr) {
4690 conscrypt::jniutil::throwNullPointerException(env, "ext == null");
4691 return 0;
4692 }
4693
4694 return X509_supported_extension(ext);
4695 }
4696
get_ASN1_TIME_data(char ** data,int * output,size_t len)4697 static inline void get_ASN1_TIME_data(char** data, int* output, size_t len) {
4698 char c = **data;
4699 **data = '\0';
4700 *data -= len;
4701 *output = atoi(*data);
4702 *(*data + len) = c;
4703 }
4704
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)4705 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
4706 jobject calendar) {
4707 CHECK_ERROR_QUEUE_ON_RETURN;
4708 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
4709 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
4710
4711 if (asn1Time == nullptr) {
4712 conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
4713 return;
4714 }
4715
4716 if (!ASN1_TIME_check(asn1Time)) {
4717 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
4718 return;
4719 }
4720
4721 bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
4722 if (gen.get() == nullptr) {
4723 conscrypt::jniutil::throwParsingException(env,
4724 "ASN1_TIME_to_generalizedtime returned null");
4725 return;
4726 }
4727
4728 if (gen->length < 14 || gen->data == nullptr) {
4729 conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
4730 return;
4731 }
4732
4733 int sec, min, hour, mday, mon, year;
4734
4735 char* p = reinterpret_cast<char*>(&gen->data[14]);
4736
4737 get_ASN1_TIME_data(&p, &sec, 2);
4738 get_ASN1_TIME_data(&p, &min, 2);
4739 get_ASN1_TIME_data(&p, &hour, 2);
4740 get_ASN1_TIME_data(&p, &mday, 2);
4741 get_ASN1_TIME_data(&p, &mon, 2);
4742 get_ASN1_TIME_data(&p, &year, 4);
4743
4744 env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
4745 min, sec);
4746 }
4747
4748 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
4749 // functions so that they can be freed properly when finished. This struct owns
4750 // all objects pointed to by its members.
4751 struct CbsHandle {
4752 // A pointer to the CBS.
4753 std::unique_ptr<CBS> cbs;
4754 // A pointer to the data held by the CBS. If the data held by the CBS
4755 // is owned by a different CbsHandle, data will be null.
4756 std::unique_ptr<unsigned char[]> data;
4757 };
4758
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)4759 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
4760 CHECK_ERROR_QUEUE_ON_RETURN;
4761 JNI_TRACE("asn1_read_init(%p)", data);
4762
4763 ScopedByteArrayRO bytes(env, data);
4764 if (bytes.get() == nullptr) {
4765 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4766 return 0;
4767 }
4768
4769 std::unique_ptr<CbsHandle> cbs(new CbsHandle());
4770 cbs->data.reset(new unsigned char[bytes.size()]);
4771 memcpy(cbs->data.get(), bytes.get(), bytes.size());
4772
4773 cbs->cbs.reset(new CBS());
4774 CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
4775 JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
4776 return reinterpret_cast<uintptr_t>(cbs.release());
4777 }
4778
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)4779 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
4780 CHECK_ERROR_QUEUE_ON_RETURN;
4781 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4782 JNI_TRACE("asn1_read_sequence(%p)", cbs);
4783
4784 std::unique_ptr<CbsHandle> seq(new CbsHandle());
4785 seq->cbs.reset(new CBS());
4786 if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
4787 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4788 return 0;
4789 }
4790 JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
4791 return reinterpret_cast<uintptr_t>(seq.release());
4792 }
4793
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)4794 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
4795 jlong cbsRef, jint tag) {
4796 CHECK_ERROR_QUEUE_ON_RETURN;
4797 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4798 JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
4799
4800 int result = CBS_peek_asn1_tag(cbs->cbs.get(),
4801 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
4802 JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
4803 return result ? JNI_TRUE : JNI_FALSE;
4804 }
4805
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)4806 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
4807 CHECK_ERROR_QUEUE_ON_RETURN;
4808 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4809 JNI_TRACE("asn1_read_tagged(%p)", cbs);
4810
4811 std::unique_ptr<CbsHandle> tag(new CbsHandle());
4812 tag->cbs.reset(new CBS());
4813 if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
4814 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4815 return 0;
4816 }
4817 JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
4818 return reinterpret_cast<uintptr_t>(tag.release());
4819 }
4820
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)4821 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
4822 CHECK_ERROR_QUEUE_ON_RETURN;
4823 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4824 JNI_TRACE("asn1_read_octetstring(%p)", cbs);
4825
4826 std::unique_ptr<CBS> str(new CBS());
4827 if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
4828 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4829 return 0;
4830 }
4831 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
4832 if (out.get() == nullptr) {
4833 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4834 return 0;
4835 }
4836 ScopedByteArrayRW outBytes(env, out.get());
4837 if (outBytes.get() == nullptr) {
4838 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4839 return 0;
4840 }
4841 memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
4842 JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
4843 return out.release();
4844 }
4845
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)4846 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
4847 CHECK_ERROR_QUEUE_ON_RETURN;
4848 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4849 JNI_TRACE("asn1_read_uint64(%p)", cbs);
4850
4851 // NOLINTNEXTLINE(runtime/int)
4852 uint64_t value;
4853 if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
4854 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4855 return 0;
4856 }
4857 return value;
4858 }
4859
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)4860 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
4861 CHECK_ERROR_QUEUE_ON_RETURN;
4862 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4863 JNI_TRACE("asn1_read_null(%p)", cbs);
4864
4865 CBS null_holder;
4866 if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
4867 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4868 }
4869 }
4870
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)4871 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
4872 CHECK_ERROR_QUEUE_ON_RETURN;
4873 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4874 JNI_TRACE("asn1_read_oid(%p)", cbs);
4875
4876 CBS oid_cbs;
4877 if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
4878 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
4879 return nullptr;
4880 }
4881 int nid = OBJ_cbs2nid(&oid_cbs);
4882 if (nid == NID_undef) {
4883 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
4884 return nullptr;
4885 }
4886 const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
4887 if (obj == nullptr) {
4888 conscrypt::jniutil::throwIOException(env,
4889 "Error reading ASN.1 encoding: "
4890 "Could not find ASN1_OBJECT for NID");
4891 return nullptr;
4892 }
4893 return ASN1_OBJECT_to_OID_string(env, obj);
4894 }
4895
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)4896 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
4897 jlong cbsRef) {
4898 CHECK_ERROR_QUEUE_ON_RETURN;
4899 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4900 JNI_TRACE("asn1_read_is_empty(%p)", cbs);
4901
4902 bool empty = (CBS_len(cbs->cbs.get()) == 0);
4903 JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
4904 return empty;
4905 }
4906
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)4907 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
4908 CHECK_ERROR_QUEUE_ON_RETURN;
4909 if (cbsRef == 0) {
4910 JNI_TRACE("asn1_read_free(0)");
4911 return;
4912 }
4913 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
4914 JNI_TRACE("asn1_read_free(%p)", cbs);
4915 delete cbs;
4916 }
4917
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)4918 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
4919 CHECK_ERROR_QUEUE_ON_RETURN;
4920 JNI_TRACE("asn1_write_init");
4921 std::unique_ptr<CBB> cbb(new CBB());
4922 if (!CBB_init(cbb.get(), 128)) {
4923 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4924 return 0;
4925 }
4926 JNI_TRACE("asn1_write_init => %p", cbb.get());
4927 return reinterpret_cast<uintptr_t>(cbb.release());
4928 }
4929
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)4930 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
4931 CHECK_ERROR_QUEUE_ON_RETURN;
4932 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
4933 JNI_TRACE("asn1_write_sequence(%p)", cbb);
4934
4935 std::unique_ptr<CBB> seq(new CBB());
4936 if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
4937 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4938 return 0;
4939 }
4940 JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
4941 return reinterpret_cast<uintptr_t>(seq.release());
4942 }
4943
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)4944 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
4945 CHECK_ERROR_QUEUE_ON_RETURN;
4946 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
4947 JNI_TRACE("asn1_write_tag(%p)", cbb);
4948
4949 std::unique_ptr<CBB> tag_holder(new CBB());
4950 if (!CBB_add_asn1(cbb, tag_holder.get(),
4951 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
4952 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4953 return 0;
4954 }
4955 JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
4956 return reinterpret_cast<uintptr_t>(tag_holder.release());
4957 }
4958
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)4959 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
4960 jbyteArray data) {
4961 CHECK_ERROR_QUEUE_ON_RETURN;
4962 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
4963 JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
4964
4965 ScopedByteArrayRO bytes(env, data);
4966 if (bytes.get() == nullptr) {
4967 JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
4968 return;
4969 }
4970
4971 std::unique_ptr<CBB> octetstring(new CBB());
4972 if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
4973 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4974 return;
4975 }
4976 if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
4977 bytes.size())) {
4978 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4979 return;
4980 }
4981 if (!CBB_flush(cbb)) {
4982 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4983 return;
4984 }
4985 }
4986
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)4987 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
4988 CHECK_ERROR_QUEUE_ON_RETURN;
4989 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
4990 JNI_TRACE("asn1_write_uint64(%p)", cbb);
4991
4992 if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
4993 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
4994 return;
4995 }
4996 }
4997
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)4998 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
4999 CHECK_ERROR_QUEUE_ON_RETURN;
5000 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5001 JNI_TRACE("asn1_write_null(%p)", cbb);
5002
5003 CBB null_holder;
5004 if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
5005 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5006 return;
5007 }
5008 if (!CBB_flush(cbb)) {
5009 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5010 return;
5011 }
5012 }
5013
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)5014 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
5015 CHECK_ERROR_QUEUE_ON_RETURN;
5016 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5017 JNI_TRACE("asn1_write_oid(%p)", cbb);
5018
5019 ScopedUtfChars oid_chars(env, oid);
5020 if (oid_chars.c_str() == nullptr) {
5021 return;
5022 }
5023
5024 int nid = OBJ_txt2nid(oid_chars.c_str());
5025 if (nid == NID_undef) {
5026 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5027 return;
5028 }
5029
5030 if (!OBJ_nid2cbb(cbb, nid)) {
5031 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5032 return;
5033 }
5034 }
5035
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)5036 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
5037 CHECK_ERROR_QUEUE_ON_RETURN;
5038 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5039 JNI_TRACE("asn1_write_flush(%p)", cbb);
5040
5041 if (!CBB_flush(cbb)) {
5042 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5043 return;
5044 }
5045 }
5046
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)5047 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
5048 CHECK_ERROR_QUEUE_ON_RETURN;
5049 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5050 JNI_TRACE("asn1_write_finish(%p)", cbb);
5051
5052 uint8_t* data;
5053 size_t data_len;
5054 if (!CBB_finish(cbb, &data, &data_len)) {
5055 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5056 return 0;
5057 }
5058 bssl::UniquePtr<uint8_t> data_storage(data);
5059 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
5060 if (out.get() == nullptr) {
5061 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5062 return 0;
5063 }
5064 ScopedByteArrayRW outBytes(env, out.get());
5065 if (outBytes.get() == nullptr) {
5066 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5067 return 0;
5068 }
5069 memcpy(outBytes.get(), data, data_len);
5070 return out.release();
5071 }
5072
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5073 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5074 CHECK_ERROR_QUEUE_ON_RETURN;
5075 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5076 JNI_TRACE("asn1_write_cleanup(%p)", cbb);
5077
5078 CBB_cleanup(cbb);
5079 }
5080
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5081 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5082 CHECK_ERROR_QUEUE_ON_RETURN;
5083 if (cbbRef == 0) {
5084 JNI_TRACE("asn1_write_free(0)");
5085 return;
5086 }
5087 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5088 JNI_TRACE("asn1_write_free(%p)", cbb);
5089 delete cbb;
5090 }
5091
5092 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5093 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5094 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5095 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5096
5097 if (bio == nullptr) {
5098 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5099 return 0;
5100 }
5101
5102 T* x = d2i_func(bio, nullptr);
5103 if (x == nullptr) {
5104 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
5105 return 0;
5106 }
5107
5108 return reinterpret_cast<uintptr_t>(x);
5109 }
5110
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5111 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5112 CHECK_ERROR_QUEUE_ON_RETURN;
5113 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5114 }
5115
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5116 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5117 CHECK_ERROR_QUEUE_ON_RETURN;
5118 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5119 }
5120
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5121 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5122 CHECK_ERROR_QUEUE_ON_RETURN;
5123 ScopedByteArrayRO bytes(env, certBytes);
5124 if (bytes.get() == nullptr) {
5125 JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
5126 return 0;
5127 }
5128
5129 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
5130 // NOLINTNEXTLINE(runtime/int)
5131 X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
5132 if (x == nullptr) {
5133 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5134 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
5135 return 0;
5136 }
5137 return reinterpret_cast<uintptr_t>(x);
5138 }
5139
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5140 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
5141 CONSCRYPT_UNUSED jobject holder) {
5142 CHECK_ERROR_QUEUE_ON_RETURN;
5143 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5144 JNI_TRACE("i2d_X509(%p)", x509);
5145 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
5146 }
5147
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5148 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
5149 CONSCRYPT_UNUSED jobject holder) {
5150 CHECK_ERROR_QUEUE_ON_RETURN;
5151 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5152 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5153 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
5154 }
5155
5156 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)5157 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
5158 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5159 JNI_TRACE("PEM_to_jlong(%p)", bio);
5160
5161 if (bio == nullptr) {
5162 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5163 JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
5164 return 0;
5165 }
5166
5167 T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
5168 if (x == nullptr) {
5169 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
5170 JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
5171 return 0;
5172 }
5173
5174 JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
5175 return reinterpret_cast<uintptr_t>(x);
5176 }
5177
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5178 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5179 CHECK_ERROR_QUEUE_ON_RETURN;
5180 // NOLINTNEXTLINE(runtime/int)
5181 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
5182 return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5183 }
5184
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5185 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5186 CHECK_ERROR_QUEUE_ON_RETURN;
5187 // NOLINTNEXTLINE(runtime/int)
5188 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
5189 return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5190 }
5191
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)5192 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
5193 CHECK_ERROR_QUEUE_ON_RETURN;
5194 // NOLINTNEXTLINE(runtime/int)
5195 JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
5196 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
5197 }
5198
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)5199 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
5200 CHECK_ERROR_QUEUE_ON_RETURN;
5201 // NOLINTNEXTLINE(runtime/int)
5202 JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
5203 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
5204 }
5205
5206 template <typename T, typename T_stack>
PKCS7_to_ItemArray(JNIEnv * env,T_stack * stack,T * (* dup_func)(T *))5207 static jlongArray PKCS7_to_ItemArray(JNIEnv* env, T_stack* stack, T* (*dup_func)(T*)) {
5208 if (stack == nullptr) {
5209 return nullptr;
5210 }
5211
5212 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5213 size_t size = sk_num(reinterpret_cast<_STACK*>(stack));
5214 ref_array.reset(env->NewLongArray(size));
5215 ScopedLongArrayRW items(env, ref_array.get());
5216 for (size_t i = 0; i < size; i++) {
5217 T* item = reinterpret_cast<T*>(sk_value(reinterpret_cast<_STACK*>(stack), i));
5218 items[i] = reinterpret_cast<uintptr_t>(dup_func(item));
5219 }
5220
5221 JNI_TRACE("PKCS7_to_ItemArray(%p) => %p [size=%zd]", stack, ref_array.get(), size);
5222 return ref_array.release();
5223 }
5224
5225 #define PKCS7_CERTS 1
5226 #define PKCS7_CRLS 2
5227
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5228 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5229 CHECK_ERROR_QUEUE_ON_RETURN;
5230 STACK_OF(X509)* stack = sk_X509_new_null();
5231
5232 ScopedLongArrayRO certs(env, certsArray);
5233 for (size_t i = 0; i < certs.size(); i++) {
5234 X509* item = reinterpret_cast<X509*>(certs[i]);
5235 if (sk_X509_push(stack, item) == 0) {
5236 sk_X509_free(stack);
5237 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
5238 return nullptr;
5239 }
5240 }
5241
5242 bssl::ScopedCBB out;
5243 CBB_init(out.get(), 1024 * certs.size());
5244 if (!PKCS7_bundle_certificates(out.get(), stack)) {
5245 sk_X509_free(stack);
5246 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
5247 return nullptr;
5248 }
5249
5250 sk_X509_free(stack);
5251
5252 return CBBToByteArray(env, out.get());
5253 }
5254
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5255 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5256 CHECK_ERROR_QUEUE_ON_RETURN;
5257 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5258 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5259
5260 if (bio == nullptr) {
5261 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5262 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5263 return nullptr;
5264 }
5265
5266 if (which == PKCS7_CERTS) {
5267 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5268 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
5269 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
5270 return nullptr;
5271 }
5272 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, outCerts.get(), X509_dup);
5273 } else if (which == PKCS7_CRLS) {
5274 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5275 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
5276 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
5277 return nullptr;
5278 }
5279 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, outCRLs.get(), X509_CRL_dup);
5280 } else {
5281 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5282 return nullptr;
5283 }
5284 }
5285
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5286 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5287 CHECK_ERROR_QUEUE_ON_RETURN;
5288 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5289 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5290
5291 if (bio == nullptr) {
5292 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5293 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5294 return nullptr;
5295 }
5296
5297 uint8_t* data;
5298 size_t len;
5299 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5300 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
5301 conscrypt::jniutil::throwParsingException);
5302 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
5303 return nullptr;
5304 }
5305 bssl::UniquePtr<uint8_t> data_storage(data);
5306
5307 CBS cbs;
5308 CBS_init(&cbs, data, len);
5309
5310 if (which == PKCS7_CERTS) {
5311 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5312 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
5313 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
5314 "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
5315 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
5316 return nullptr;
5317 }
5318 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
5319 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, outCerts.get(), X509_dup);
5320 } else if (which == PKCS7_CRLS) {
5321 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5322 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
5323 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
5324 conscrypt::jniutil::throwParsingException);
5325 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
5326 return nullptr;
5327 }
5328 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
5329 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, outCRLs.get(), X509_CRL_dup);
5330 } else {
5331 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5332 return nullptr;
5333 }
5334 }
5335
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)5336 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5337 CHECK_ERROR_QUEUE_ON_RETURN;
5338 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5339 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5340
5341 uint8_t* data;
5342 size_t len;
5343 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5344 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
5345 conscrypt::jniutil::throwParsingException);
5346 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
5347 return nullptr;
5348 }
5349 bssl::UniquePtr<uint8_t> data_storage(data);
5350
5351 bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
5352 if (path.get() == nullptr) {
5353 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
5354 return nullptr;
5355 }
5356
5357 CBS cbs, sequence;
5358 CBS_init(&cbs, data, len);
5359 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
5360 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5361 ERR_clear_error();
5362 return nullptr;
5363 }
5364
5365 while (CBS_len(&sequence) > 0) {
5366 CBS child;
5367 if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
5368 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5369 ERR_clear_error();
5370 return nullptr;
5371 }
5372
5373 const uint8_t* tmp = CBS_data(&child);
5374 // NOLINTNEXTLINE(runtime/int)
5375 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
5376 if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
5377 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5378 ERR_clear_error();
5379 return nullptr;
5380 }
5381
5382 if (!sk_X509_push(path.get(), cert.get())) {
5383 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
5384 return nullptr;
5385 }
5386 OWNERSHIP_TRANSFERRED(cert);
5387 }
5388
5389 size_t size = sk_X509_num(path.get());
5390
5391 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
5392 ScopedLongArrayRW certs(env, certArray.get());
5393 for (size_t i = 0; i < size; i++) {
5394 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5395 certs[i] = reinterpret_cast<uintptr_t>(item);
5396 }
5397
5398 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
5399 return certArray.release();
5400 }
5401
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5402 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5403 CHECK_ERROR_QUEUE_ON_RETURN;
5404 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5405 ScopedLongArrayRO certsArray(env, certs);
5406 if (certsArray.get() == nullptr) {
5407 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5408 return nullptr;
5409 }
5410
5411 bssl::ScopedCBB result;
5412 CBB seq_contents;
5413 if (!CBB_init(result.get(), 2048 * certsArray.size())) {
5414 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
5415 return nullptr;
5416 }
5417 if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
5418 return nullptr;
5419 }
5420
5421 for (size_t i = 0; i < certsArray.size(); i++) {
5422 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5423 uint8_t* buf;
5424 int len = i2d_X509(x509, nullptr);
5425
5426 if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
5427 i2d_X509(x509, &buf) < 0) {
5428 return nullptr;
5429 }
5430 }
5431
5432 return CBBToByteArray(env, result.get());
5433 }
5434
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5435 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
5436 CONSCRYPT_UNUSED jobject holder) {
5437 CHECK_ERROR_QUEUE_ON_RETURN;
5438 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5439 JNI_TRACE("X509_free(%p)", x509);
5440
5441 if (x509 == nullptr) {
5442 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5443 JNI_TRACE("X509_free(%p) => x509 == null", x509);
5444 return;
5445 }
5446
5447 X509_free(x509);
5448 }
5449
NativeCrypto_X509_dup(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5450 static jlong NativeCrypto_X509_dup(JNIEnv* env, jclass, jlong x509Ref,
5451 CONSCRYPT_UNUSED jobject holder) {
5452 CHECK_ERROR_QUEUE_ON_RETURN;
5453 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5454 JNI_TRACE("X509_dup(%p)", x509);
5455
5456 if (x509 == nullptr) {
5457 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5458 JNI_TRACE("X509_dup(%p) => x509 == null", x509);
5459 return 0;
5460 }
5461
5462 return reinterpret_cast<uintptr_t>(X509_dup(x509));
5463 }
5464
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5465 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
5466 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5467 CONSCRYPT_UNUSED jobject holder2) {
5468 CHECK_ERROR_QUEUE_ON_RETURN;
5469 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5470 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5471 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5472
5473 if (x509_1 == nullptr) {
5474 conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
5475 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5476 return -1;
5477 }
5478
5479 if (x509_2 == nullptr) {
5480 conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
5481 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5482 return -1;
5483 }
5484
5485 int ret = X509_cmp(x509_1, x509_2);
5486 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5487 return ret;
5488 }
5489
NativeCrypto_X509_delete_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5490 static void NativeCrypto_X509_delete_ext(JNIEnv* env, jclass, jlong x509Ref,
5491 CONSCRYPT_UNUSED jobject holder, jstring oidString) {
5492 CHECK_ERROR_QUEUE_ON_RETURN;
5493 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5494 JNI_TRACE("X509_delete_ext(%p, %p)", x509, oidString);
5495
5496 if (x509 == nullptr) {
5497 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5498 JNI_TRACE("X509_delete_ext(%p, %p) => x509 == null", x509, oidString);
5499 return;
5500 }
5501
5502 ScopedUtfChars oid(env, oidString);
5503 if (oid.c_str() == nullptr) {
5504 JNI_TRACE("X509_delete_ext(%p, %p) => oidString == null", x509, oidString);
5505 return;
5506 }
5507
5508 bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
5509 if (obj.get() == nullptr) {
5510 JNI_TRACE("X509_delete_ext(%p, %s) => oid conversion failed", x509, oid.c_str());
5511 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5512 "Invalid OID.");
5513 ERR_clear_error();
5514 return;
5515 }
5516
5517 int extIndex = X509_get_ext_by_OBJ(x509, obj.get(), -1);
5518 if (extIndex == -1) {
5519 JNI_TRACE("X509_delete_ext(%p, %s) => ext not found", x509, oid.c_str());
5520 return;
5521 }
5522
5523 X509_EXTENSION* ext = X509_delete_ext(x509, extIndex);
5524 if (ext != nullptr) {
5525 X509_EXTENSION_free(ext);
5526
5527 // Invalidate the cached encoding
5528 X509_CINF_set_modified(X509_get_cert_info(x509));
5529 }
5530 }
5531
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)5532 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5533 CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
5534 jlong certflagJava) {
5535 CHECK_ERROR_QUEUE_ON_RETURN;
5536 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5537 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5538 // NOLINTNEXTLINE(runtime/int)
5539 unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
5540 // NOLINTNEXTLINE(runtime/int)
5541 unsigned long certflag = static_cast<unsigned long>(certflagJava);
5542 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5543
5544 if (bio == nullptr) {
5545 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5546 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5547 return;
5548 }
5549
5550 if (x509 == nullptr) {
5551 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5552 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5553 return;
5554 }
5555
5556 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5557 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
5558 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5559 return;
5560 }
5561 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5562 }
5563
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5564 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
5565 CONSCRYPT_UNUSED jobject holder) {
5566 CHECK_ERROR_QUEUE_ON_RETURN;
5567 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5568 JNI_TRACE("X509_get_pubkey(%p)", x509);
5569
5570 if (x509 == nullptr) {
5571 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5572 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
5573 return 0;
5574 }
5575
5576 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
5577 if (pkey.get() == nullptr) {
5578 const uint32_t last_error = ERR_peek_last_error();
5579 const uint32_t first_error = ERR_peek_error();
5580 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
5581 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
5582 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
5583 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
5584 ERR_clear_error();
5585 conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
5586 return 0;
5587 }
5588
5589 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5590 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
5591 return 0;
5592 }
5593
5594 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
5595 return reinterpret_cast<uintptr_t>(pkey.release());
5596 }
5597
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5598 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
5599 CONSCRYPT_UNUSED jobject holder) {
5600 CHECK_ERROR_QUEUE_ON_RETURN;
5601 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5602 JNI_TRACE("X509_get_issuer_name(%p)", x509);
5603 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
5604 }
5605
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5606 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
5607 CONSCRYPT_UNUSED jobject holder) {
5608 CHECK_ERROR_QUEUE_ON_RETURN;
5609 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5610 JNI_TRACE("X509_get_subject_name(%p)", x509);
5611 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
5612 }
5613
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5614 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
5615 CONSCRYPT_UNUSED jobject holder) {
5616 CHECK_ERROR_QUEUE_ON_RETURN;
5617 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5618 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
5619
5620 if (x509 == nullptr) {
5621 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5622 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
5623 return nullptr;
5624 }
5625
5626 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
5627 return ASN1_OBJECT_to_OID_string(env, pubkey->algor->algorithm);
5628 }
5629
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5630 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
5631 CONSCRYPT_UNUSED jobject holder) {
5632 CHECK_ERROR_QUEUE_ON_RETURN;
5633 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5634 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
5635
5636 if (x509 == nullptr || x509->sig_alg == nullptr) {
5637 conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
5638 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
5639 return nullptr;
5640 }
5641
5642 return ASN1_OBJECT_to_OID_string(env, x509->sig_alg->algorithm);
5643 }
5644
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5645 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
5646 CONSCRYPT_UNUSED jobject holder) {
5647 CHECK_ERROR_QUEUE_ON_RETURN;
5648 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5649 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
5650
5651 if (x509 == nullptr) {
5652 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5653 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
5654 return nullptr;
5655 }
5656
5657 if (x509->sig_alg->parameter == nullptr) {
5658 JNI_TRACE("get_X509_sig_alg_parameter(%p) => null", x509);
5659 return nullptr;
5660 }
5661
5662 return ASN1ToByteArray<ASN1_TYPE>(env, x509->sig_alg->parameter, i2d_ASN1_TYPE);
5663 }
5664
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5665 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
5666 CONSCRYPT_UNUSED jobject holder) {
5667 CHECK_ERROR_QUEUE_ON_RETURN;
5668 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5669 JNI_TRACE("get_X509_issuerUID(%p)", x509);
5670
5671 if (x509 == nullptr) {
5672 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5673 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
5674 return nullptr;
5675 }
5676
5677 if (x509->cert_info->issuerUID == nullptr) {
5678 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
5679 return nullptr;
5680 }
5681
5682 return ASN1BitStringToBooleanArray(env, x509->cert_info->issuerUID);
5683 }
5684
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5685 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
5686 CONSCRYPT_UNUSED jobject holder) {
5687 CHECK_ERROR_QUEUE_ON_RETURN;
5688 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5689 JNI_TRACE("get_X509_subjectUID(%p)", x509);
5690
5691 if (x509 == nullptr) {
5692 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5693 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
5694 return nullptr;
5695 }
5696
5697 if (x509->cert_info->subjectUID == nullptr) {
5698 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
5699 return nullptr;
5700 }
5701
5702 return ASN1BitStringToBooleanArray(env, x509->cert_info->subjectUID);
5703 }
5704
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5705 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
5706 CONSCRYPT_UNUSED jobject holder) {
5707 CHECK_ERROR_QUEUE_ON_RETURN;
5708 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5709 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
5710
5711 if (x509 == nullptr) {
5712 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5713 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
5714 return nullptr;
5715 }
5716
5717 bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
5718 static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
5719 if (bitStr.get() == nullptr) {
5720 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
5721 return nullptr;
5722 }
5723
5724 return ASN1BitStringToBooleanArray(env, bitStr.get());
5725 }
5726
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5727 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
5728 CONSCRYPT_UNUSED jobject holder) {
5729 CHECK_ERROR_QUEUE_ON_RETURN;
5730 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5731 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
5732
5733 if (x509 == nullptr) {
5734 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5735 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
5736 return nullptr;
5737 }
5738
5739 bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
5740 X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
5741 if (objArray.get() == nullptr) {
5742 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
5743 return nullptr;
5744 }
5745
5746 size_t size = sk_ASN1_OBJECT_num(objArray.get());
5747 ScopedLocalRef<jobjectArray> exKeyUsage(
5748 env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
5749 nullptr));
5750 if (exKeyUsage.get() == nullptr) {
5751 return nullptr;
5752 }
5753
5754 for (size_t i = 0; i < size; i++) {
5755 ScopedLocalRef<jstring> oidStr(
5756 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
5757 env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
5758 }
5759
5760 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
5761 return exKeyUsage.release();
5762 }
5763
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5764 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
5765 CONSCRYPT_UNUSED jobject holder) {
5766 CHECK_ERROR_QUEUE_ON_RETURN;
5767 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5768 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
5769
5770 if (x509 == nullptr) {
5771 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5772 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
5773 return 0;
5774 }
5775
5776 /* Just need to do this to cache the ex_* values. */
5777 X509_check_ca(x509);
5778
5779 JNI_TRACE("get_X509_ex_pathlen(%p) => %ld", x509, x509->ex_pathlen);
5780 return x509->ex_pathlen;
5781 }
5782
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5783 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
5784 CONSCRYPT_UNUSED jobject holder,
5785 jstring oidString) {
5786 CHECK_ERROR_QUEUE_ON_RETURN;
5787 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5788 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
5789 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
5790 }
5791
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)5792 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5793 CONSCRYPT_UNUSED jobject holder,
5794 jstring oidString) {
5795 CHECK_ERROR_QUEUE_ON_RETURN;
5796 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5797 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
5798 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
5799 oidString);
5800 }
5801
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)5802 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
5803 jstring oidString) {
5804 CHECK_ERROR_QUEUE_ON_RETURN;
5805 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5806 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
5807 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5808 env, revoked, oidString);
5809 }
5810
5811 template <typename T, typename C, C T::*member, int (*get_ext_by_critical_func)(T*, int, int),
5812 X509_EXTENSION* (*get_ext_func)(T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)5813 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
5814 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
5815 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
5816
5817 if (x509 == nullptr) {
5818 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5819 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
5820 return nullptr;
5821 }
5822 if (member != nullptr && x509->*member == nullptr) {
5823 conscrypt::jniutil::throwNullPointerException(env, "x509->*member == null");
5824 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509->*member == null", x509, critical);
5825 return nullptr;
5826 }
5827
5828 int lastPos = -1;
5829 int count = 0;
5830 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
5831 count++;
5832 }
5833
5834 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
5835
5836 ScopedLocalRef<jobjectArray> joa(
5837 env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
5838 if (joa.get() == nullptr) {
5839 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
5840 return nullptr;
5841 }
5842
5843 lastPos = -1;
5844 count = 0;
5845 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
5846 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
5847
5848 ScopedLocalRef<jstring> extOid(env, ASN1_OBJECT_to_OID_string(env, ext->object));
5849 if (extOid.get() == nullptr) {
5850 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
5851 return nullptr;
5852 }
5853
5854 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
5855 }
5856
5857 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
5858 return joa.release();
5859 }
5860
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)5861 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
5862 CONSCRYPT_UNUSED jobject holder, jint critical) {
5863 CHECK_ERROR_QUEUE_ON_RETURN;
5864 // NOLINTNEXTLINE(runtime/int)
5865 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
5866 return get_X509Type_ext_oids<X509, decltype(X509::cert_info), &X509::cert_info,
5867 X509_get_ext_by_critical, X509_get_ext>(env, x509Ref, critical);
5868 }
5869
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)5870 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
5871 CONSCRYPT_UNUSED jobject holder,
5872 jint critical) {
5873 CHECK_ERROR_QUEUE_ON_RETURN;
5874 // NOLINTNEXTLINE(runtime/int)
5875 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
5876 return get_X509Type_ext_oids<X509_CRL, decltype(X509_CRL::crl), &X509_CRL::crl,
5877 X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(env, x509CrlRef, critical);
5878 }
5879
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)5880 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
5881 jlong x509RevokedRef, jint critical) {
5882 CHECK_ERROR_QUEUE_ON_RETURN;
5883 // NOLINTNEXTLINE(runtime/int)
5884 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
5885 return get_X509Type_ext_oids<X509_REVOKED, decltype(X509_REVOKED::extensions), nullptr,
5886 X509_REVOKED_get_ext_by_critical, X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
5887 }
5888
5889 /**
5890 * Based on example logging call back from SSL_CTX_set_info_callback man page
5891 */
info_callback_LOG(const SSL * s,int where,int ret)5892 static void info_callback_LOG(const SSL* s, int where, int ret) {
5893 int w = where & ~SSL_ST_MASK;
5894 const char* str;
5895 if (w & SSL_ST_CONNECT) {
5896 str = "SSL_connect";
5897 } else if (w & SSL_ST_ACCEPT) {
5898 str = "SSL_accept";
5899 } else {
5900 str = "undefined";
5901 }
5902
5903 if (where & SSL_CB_LOOP) {
5904 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
5905 } else if (where & SSL_CB_ALERT) {
5906 str = (where & SSL_CB_READ) ? "read" : "write";
5907 JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
5908 SSL_alert_desc_string_long(ret));
5909 } else if (where & SSL_CB_EXIT) {
5910 if (ret == 0) {
5911 JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
5912 SSL_state_string_long(s));
5913 } else if (ret < 0) {
5914 JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
5915 SSL_state_string_long(s));
5916 } else if (ret == 1) {
5917 JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
5918 SSL_state_string_long(s));
5919 } else {
5920 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
5921 SSL_state_string_long(s));
5922 }
5923 } else if (where & SSL_CB_HANDSHAKE_START) {
5924 JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
5925 SSL_state_string_long(s));
5926 } else if (where & SSL_CB_HANDSHAKE_DONE) {
5927 JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
5928 SSL_state_string_long(s));
5929 } else {
5930 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
5931 SSL_state_string_long(s));
5932 }
5933 }
5934
5935 #ifdef _WIN32
5936
5937 /**
5938 * Dark magic helper function that checks, for a given SSL session, whether it
5939 * can SSL_read() or SSL_write() without blocking. Takes into account any
5940 * concurrent attempts to close the SSLSocket from the Java side. This is
5941 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
5942 * while thread #2 is sitting in a blocking read or write. The type argument
5943 * specifies whether we are waiting for readability or writability. It expects
5944 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
5945 * only need to wait in case one of these problems occurs.
5946 *
5947 * @param env
5948 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
5949 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
5950 * @param appData The application data structure with mutex info etc.
5951 * @param timeout_millis The timeout value for select call, with the special value
5952 * 0 meaning no timeout at all (wait indefinitely). Note: This is
5953 * the Java semantics of the timeout value, not the usual
5954 * select() semantics.
5955 * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
5956 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)5957 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
5958 int timeout_millis) {
5959 int result = -1;
5960
5961 NetFd fd(env, fdObject);
5962 do {
5963 if (fd.isClosed()) {
5964 result = THROWN_EXCEPTION;
5965 break;
5966 }
5967
5968 WSAEVENT events[2];
5969 events[0] = appData->interruptEvent;
5970 events[1] = WSACreateEvent();
5971 if (events[1] == WSA_INVALID_EVENT) {
5972 JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
5973 break;
5974 }
5975
5976 if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
5977 FD_CLOSE) == SOCKET_ERROR) {
5978 JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
5979 break;
5980 }
5981
5982 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
5983 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
5984 timeout_millis);
5985
5986 int rc = WSAWaitForMultipleEvents(
5987 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
5988 if (rc == WSA_WAIT_FAILED) {
5989 JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
5990 result = -1;
5991 } else if (rc == WSA_WAIT_TIMEOUT) {
5992 result = 0;
5993 } else {
5994 result = 1;
5995 }
5996 WSACloseEvent(events[1]);
5997 } while (0);
5998
5999 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
6000 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
6001 result);
6002
6003 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6004 appData->waitingThreads--;
6005
6006 return result;
6007 }
6008
6009 #else // !defined(_WIN32)
6010
6011 /**
6012 * Dark magic helper function that checks, for a given SSL session, whether it
6013 * can SSL_read() or SSL_write() without blocking. Takes into account any
6014 * concurrent attempts to close the SSLSocket from the Java side. This is
6015 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6016 * while thread #2 is sitting in a blocking read or write. The type argument
6017 * specifies whether we are waiting for readability or writability. It expects
6018 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6019 * only need to wait in case one of these problems occurs.
6020 *
6021 * @param env
6022 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6023 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
6024 * @param appData The application data structure with mutex info etc.
6025 * @param timeout_millis The timeout value for poll call, with the special value
6026 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6027 * the Java semantics of the timeout value, not the usual
6028 * poll() semantics.
6029 * @return The result of the inner poll() call,
6030 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6031 * additional errors
6032 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6033 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6034 int timeout_millis) {
6035 // This loop is an expanded version of the NET_FAILURE_RETRY
6036 // macro. It cannot simply be used in this case because poll
6037 // cannot be restarted without recreating the pollfd structure.
6038 int result;
6039 struct pollfd fds[2];
6040 do {
6041 NetFd fd(env, fdObject);
6042 if (fd.isClosed()) {
6043 result = THROWN_EXCEPTION;
6044 break;
6045 }
6046 int intFd = fd.get();
6047 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6048 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6049
6050 memset(&fds, 0, sizeof(fds));
6051 fds[0].fd = intFd;
6052 if (type == SSL_ERROR_WANT_READ) {
6053 fds[0].events = POLLIN | POLLPRI;
6054 } else {
6055 fds[0].events = POLLOUT | POLLPRI;
6056 }
6057
6058 fds[1].fd = appData->fdsEmergency[0];
6059 fds[1].events = POLLIN | POLLPRI;
6060
6061 // Converting from Java semantics to Posix semantics.
6062 if (timeout_millis <= 0) {
6063 timeout_millis = -1;
6064 }
6065
6066 CompatibilityCloseMonitor monitor(intFd);
6067
6068 result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
6069 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6070 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6071 timeout_millis, result);
6072 if (result == -1) {
6073 if (fd.isClosed()) {
6074 result = THROWN_EXCEPTION;
6075 break;
6076 }
6077 if (errno != EINTR) {
6078 break;
6079 }
6080 }
6081 } while (result == -1);
6082
6083 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6084
6085 if (result > 0) {
6086 // We have been woken up by a token in the emergency pipe. We
6087 // can't be sure the token is still in the pipe at this point
6088 // because it could have already been read by the thread that
6089 // originally wrote it if it entered sslSelect and acquired
6090 // the mutex before we did. Thus we cannot safely read from
6091 // the pipe in a blocking way (so we make the pipe
6092 // non-blocking at creation).
6093 if (fds[1].revents & POLLIN) {
6094 char token;
6095 do {
6096 (void)read(appData->fdsEmergency[0], &token, 1);
6097 } while (errno == EINTR);
6098 }
6099 }
6100
6101 // Tell the world that there is now one thread less waiting for the
6102 // underlying network.
6103 appData->waitingThreads--;
6104
6105 return result;
6106 }
6107 #endif // !defined(_WIN32)
6108
6109 /**
6110 * Helper function that wakes up a thread blocked in select(), in case there is
6111 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6112 * before closing the connection.
6113 *
6114 * @param data The application data structure with mutex info etc.
6115 */
sslNotify(AppData * appData)6116 static void sslNotify(AppData* appData) {
6117 #ifdef _WIN32
6118 SetEvent(appData->interruptEvent);
6119 #else
6120 // Write a byte to the emergency pipe, so a concurrent select() can return.
6121 // Note we have to restore the errno of the original system call, since the
6122 // caller relies on it for generating error messages.
6123 int errnoBackup = errno;
6124 char token = '*';
6125 do {
6126 errno = 0;
6127 (void)write(appData->fdsEmergency[1], &token, 1);
6128 } while (errno == EINTR);
6129 errno = errnoBackup;
6130 #endif
6131 }
6132
toAppData(const SSL * ssl)6133 static AppData* toAppData(const SSL* ssl) {
6134 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6135 }
6136
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)6137 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
6138 JNI_TRACE("ssl=%p cert_verify_callback", ssl);
6139
6140 AppData* appData = toAppData(ssl);
6141 JNIEnv* env = appData->env;
6142 if (env == nullptr) {
6143 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
6144 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6145 return ssl_verify_invalid;
6146 }
6147
6148 // Create the byte[][] array that holds all the certs
6149 ScopedLocalRef<jobjectArray> array(
6150 env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
6151 if (array.get() == nullptr) {
6152 return ssl_verify_invalid;
6153 }
6154
6155 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6156 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6157 jmethodID methodID =
6158 env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
6159
6160 const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
6161 const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
6162
6163 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
6164 authMethod);
6165 ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
6166 env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
6167
6168 ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
6169 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6170 return result;
6171 }
6172
6173 /**
6174 * Call back to watch for handshake to be completed. This is necessary for
6175 * False Start support, since SSL_do_handshake returns before the handshake is
6176 * completed in this case.
6177 */
info_callback(const SSL * ssl,int type,int value)6178 static void info_callback(const SSL* ssl, int type, int value) {
6179 JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
6180 if (conscrypt::trace::kWithJniTrace) {
6181 info_callback_LOG(ssl, type, value);
6182 }
6183 if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
6184 JNI_TRACE("ssl=%p info_callback ignored", ssl);
6185 return;
6186 }
6187
6188 AppData* appData = toAppData(ssl);
6189 JNIEnv* env = appData->env;
6190 if (env == nullptr) {
6191 CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
6192 JNI_TRACE("ssl=%p info_callback env error", ssl);
6193 return;
6194 }
6195 if (env->ExceptionCheck()) {
6196 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6197 return;
6198 }
6199
6200 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6201
6202 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6203 jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(II)V");
6204
6205 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6206 env->CallVoidMethod(sslHandshakeCallbacks, methodID, type, value);
6207
6208 if (env->ExceptionCheck()) {
6209 JNI_TRACE("ssl=%p info_callback exception", ssl);
6210 }
6211 JNI_TRACE("ssl=%p info_callback completed", ssl);
6212 }
6213
6214 /**
6215 * Call back to ask for a certificate. There are three possible exit codes:
6216 *
6217 * 1 is success.
6218 * 0 is error.
6219 * -1 is to pause the handshake to continue from the same place later.
6220 */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)6221 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
6222 JNI_TRACE("ssl=%p cert_cb", ssl);
6223
6224 // cert_cb is called for both clients and servers, but we are only
6225 // interested in client certificates.
6226 if (SSL_is_server(ssl)) {
6227 JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
6228 return 1;
6229 }
6230
6231 AppData* appData = toAppData(ssl);
6232 JNIEnv* env = appData->env;
6233 if (env == nullptr) {
6234 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
6235 JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
6236 return 0;
6237 }
6238 if (env->ExceptionCheck()) {
6239 JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
6240 return 0;
6241 }
6242 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6243
6244 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6245 jmethodID methodID = env->GetMethodID(cls, "clientCertificateRequested", "([B[I[[B)V");
6246
6247 // Call Java callback which can reconfigure the client certificate.
6248 const uint8_t* ctype = nullptr;
6249 size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
6250 const uint16_t* sigalgs = nullptr;
6251 size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
6252 ScopedLocalRef<jobjectArray> issuers(
6253 env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
6254 if (issuers.get() == nullptr) {
6255 return 0;
6256 }
6257
6258 if (conscrypt::trace::kWithJniTrace) {
6259 for (size_t i = 0; i < ctype_num; i++) {
6260 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
6261 }
6262 for (size_t i = 0; i < sigalgs_num; i++) {
6263 JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
6264 }
6265 }
6266
6267 jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
6268 if (keyTypes == nullptr) {
6269 JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
6270 return 0;
6271 }
6272 env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
6273 reinterpret_cast<const jbyte*>(ctype));
6274
6275 jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
6276 if (signatureAlgs == nullptr) {
6277 JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
6278 return 0;
6279 }
6280 {
6281 ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
6282 for (size_t i = 0; i < sigalgs_num; i++) {
6283 sigAlgsRW[i] = sigalgs[i];
6284 }
6285 }
6286
6287 JNI_TRACE(
6288 "ssl=%p clientCertificateRequested calling clientCertificateRequested "
6289 "keyTypes=%p signatureAlgs=%p issuers=%p",
6290 ssl, keyTypes, signatureAlgs, issuers.get());
6291 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
6292
6293 if (env->ExceptionCheck()) {
6294 JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
6295 return 0;
6296 }
6297
6298 JNI_TRACE("ssl=%p cert_cb => 1", ssl);
6299 return 1;
6300 }
6301
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)6302 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
6303 SSL* ssl = client_hello->ssl;
6304 JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
6305
6306 AppData* appData = toAppData(ssl);
6307 JNIEnv* env = appData->env;
6308 if (env == nullptr) {
6309 CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
6310 JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
6311 return ssl_select_cert_error;
6312 }
6313 if (env->ExceptionCheck()) {
6314 JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
6315 return ssl_select_cert_error;
6316 }
6317
6318 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6319 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6320 jmethodID methodID = env->GetMethodID(cls, "serverCertificateRequested", "()V");
6321
6322 JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
6323 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
6324
6325 if (env->ExceptionCheck()) {
6326 JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
6327 return ssl_select_cert_error;
6328 }
6329 JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
6330 return ssl_select_cert_success;
6331 }
6332
6333 /**
6334 * Pre-Shared Key (PSK) client callback.
6335 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6336 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
6337 unsigned int max_identity_len, unsigned char* psk,
6338 unsigned int max_psk_len) {
6339 JNI_TRACE("ssl=%p psk_client_callback", ssl);
6340
6341 AppData* appData = toAppData(ssl);
6342 JNIEnv* env = appData->env;
6343 if (env == nullptr) {
6344 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
6345 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6346 return 0;
6347 }
6348 if (env->ExceptionCheck()) {
6349 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6350 return 0;
6351 }
6352
6353 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6354 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6355 jmethodID methodID =
6356 env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
6357 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6358 ScopedLocalRef<jstring> identityHintJava(env,
6359 (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
6360 ScopedLocalRef<jbyteArray> identityJava(
6361 env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
6362 if (identityJava.get() == nullptr) {
6363 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6364 return 0;
6365 }
6366 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6367 if (keyJava.get() == nullptr) {
6368 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6369 return 0;
6370 }
6371 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6372 identityJava.get(), keyJava.get());
6373 if (env->ExceptionCheck()) {
6374 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6375 return 0;
6376 }
6377 if (keyLen <= 0) {
6378 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6379 return 0;
6380 } else if ((unsigned int)keyLen > max_psk_len) {
6381 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6382 return 0;
6383 }
6384 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6385 if (keyJavaRo.get() == nullptr) {
6386 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
6387 return 0;
6388 }
6389 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6390
6391 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
6392 if (identityJavaRo.get() == nullptr) {
6393 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
6394 return 0;
6395 }
6396 memcpy(identity, identityJavaRo.get(), max_identity_len);
6397
6398 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
6399 return static_cast<unsigned int>(keyLen);
6400 }
6401
6402 /**
6403 * Pre-Shared Key (PSK) server callback.
6404 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)6405 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
6406 unsigned int max_psk_len) {
6407 JNI_TRACE("ssl=%p psk_server_callback", ssl);
6408
6409 AppData* appData = toAppData(ssl);
6410 JNIEnv* env = appData->env;
6411 if (env == nullptr) {
6412 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
6413 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
6414 return 0;
6415 }
6416 if (env->ExceptionCheck()) {
6417 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
6418 return 0;
6419 }
6420
6421 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6422 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6423 jmethodID methodID = env->GetMethodID(cls, "serverPSKKeyRequested",
6424 "(Ljava/lang/String;Ljava/lang/String;[B)I");
6425 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
6426 const char* identityHint = SSL_get_psk_identity_hint(ssl);
6427 ScopedLocalRef<jstring> identityHintJava(
6428 env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
6429 ScopedLocalRef<jstring> identityJava(
6430 env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
6431 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6432 if (keyJava.get() == nullptr) {
6433 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
6434 return 0;
6435 }
6436 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6437 identityJava.get(), keyJava.get());
6438 if (env->ExceptionCheck()) {
6439 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
6440 return 0;
6441 }
6442 if (keyLen <= 0) {
6443 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
6444 return 0;
6445 } else if ((unsigned int)keyLen > max_psk_len) {
6446 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
6447 return 0;
6448 }
6449 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6450 if (keyJavaRo.get() == nullptr) {
6451 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
6452 return 0;
6453 }
6454 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6455
6456 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
6457 return static_cast<unsigned int>(keyLen);
6458 }
6459
new_session_callback(SSL * ssl,SSL_SESSION * session)6460 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
6461 JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
6462
6463 AppData* appData = toAppData(ssl);
6464 JNIEnv* env = appData->env;
6465 if (env == nullptr) {
6466 CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
6467 JNI_TRACE("ssl=%p new_session_callback env error", ssl);
6468 return 0;
6469 }
6470 if (env->ExceptionCheck()) {
6471 JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
6472 return 0;
6473 }
6474
6475 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6476 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6477 jmethodID methodID = env->GetMethodID(cls, "onNewSessionEstablished", "(J)V");
6478 JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
6479 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
6480 if (env->ExceptionCheck()) {
6481 JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
6482 env->ExceptionClear();
6483 }
6484 JNI_TRACE("ssl=%p new_session_callback completed", ssl);
6485
6486 // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
6487 // the reference count.
6488 return 0;
6489 }
6490
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)6491 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
6492 int* out_copy) {
6493 JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
6494
6495 // Always set to out_copy to zero. The Java callback will be responsible for incrementing
6496 // the reference count (and any required synchronization).
6497 *out_copy = 0;
6498
6499 AppData* appData = toAppData(ssl);
6500 JNIEnv* env = appData->env;
6501 if (env == nullptr) {
6502 CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
6503 JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
6504 return 0;
6505 }
6506 if (env->ExceptionCheck()) {
6507 JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
6508 return 0;
6509 }
6510
6511 // Copy the ID to a byte[].
6512 jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
6513 if (id_array == nullptr) {
6514 JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
6515 return 0;
6516 }
6517 env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
6518 reinterpret_cast<const jbyte*>(id));
6519
6520 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6521 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6522 jmethodID methodID = env->GetMethodID(cls, "serverSessionRequested", "([B)J");
6523 JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
6524 jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
6525 if (env->ExceptionCheck()) {
6526 JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
6527 env->ExceptionClear();
6528 }
6529 SSL_SESSION* ssl_session_ptr =
6530 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
6531 JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
6532 return ssl_session_ptr;
6533 }
6534
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)6535 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
6536 CHECK_ERROR_QUEUE_ON_RETURN;
6537 int ret = 0;
6538 ret = EVP_has_aes_hardware();
6539 JNI_TRACE("EVP_has_aes_hardware => %d", ret);
6540 return ret;
6541 }
6542
debug_print_session_key(const SSL * ssl,const char * line)6543 static void debug_print_session_key(const SSL* ssl, const char* line) {
6544 JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
6545 }
6546
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)6547 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
6548 static constexpr size_t kDataWidth = 16;
6549
6550 struct timeval tv;
6551 if (gettimeofday(&tv, NULL)) {
6552 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6553 "debug_print_packet_data: could not get time of day");
6554 return;
6555 }
6556
6557 // Packet preamble for text2pcap
6558 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
6559 tv.tv_sec, static_cast<long>(tv.tv_usec)); // NOLINT(runtime/int)
6560
6561 char out[kDataWidth * 3 + 1];
6562 for (size_t i = 0; i < len; i += kDataWidth) {
6563 size_t n = len - i < kDataWidth ? len - i : kDataWidth;
6564
6565 for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
6566 int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
6567 if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
6568 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6569 "debug_print_packet_data failed to output %d", ret);
6570 return;
6571 }
6572 }
6573
6574 // Print out packet data in format understood by text2pcap
6575 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
6576 }
6577
6578 // Conclude the packet data
6579 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
6580 }
6581
6582 /*
6583 * public static native int SSL_CTX_new();
6584 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)6585 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
6586 CHECK_ERROR_QUEUE_ON_RETURN;
6587 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
6588 if (sslCtx.get() == nullptr) {
6589 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
6590 return 0;
6591 }
6592 SSL_CTX_set_options(
6593 sslCtx.get(),
6594 SSL_OP_ALL
6595 // We also disable session tickets for better compatibility b/2682876
6596 | SSL_OP_NO_TICKET
6597 // We also disable compression for better compatibility b/2710492 b/2710497
6598 | SSL_OP_NO_COMPRESSION
6599 // Generate a fresh ECDH keypair for each key exchange.
6600 | SSL_OP_SINGLE_ECDH_USE);
6601 SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
6602 SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
6603
6604 uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
6605 /*
6606 * Turn on "partial write" mode. This means that SSL_write() will
6607 * behave like Posix write() and possibly return after only
6608 * writing a partial buffer. Note: The alternative, perhaps
6609 * surprisingly, is not that SSL_write() always does full writes
6610 * but that it will force you to retry write calls having
6611 * preserved the full state of the original call. (This is icky
6612 * and undesirable.)
6613 */
6614 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
6615
6616 // Reuse empty buffers within the SSL_CTX to save memory
6617 mode |= SSL_MODE_RELEASE_BUFFERS;
6618
6619 // Enable False Start.
6620 mode |= SSL_MODE_ENABLE_FALSE_START;
6621
6622 // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
6623 // between
6624 // calls to wrap(...).
6625 // See https://github.com/netty/netty-tcnative/issues/100
6626 mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
6627
6628 SSL_CTX_set_mode(sslCtx.get(), mode);
6629
6630 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
6631 SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
6632 SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
6633 if (conscrypt::trace::kWithJniTraceKeys) {
6634 SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
6635 }
6636
6637 // By default BoringSSL will cache in server mode, but we want to get
6638 // notified of new sessions being created in client mode. We set
6639 // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
6640 // ignore it in server mode in favor of the internal cache.
6641 SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
6642 SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
6643 SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
6644
6645 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
6646 return (jlong)sslCtx.release();
6647 }
6648
6649 /**
6650 * public static native void SSL_CTX_free(long ssl_ctx)
6651 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)6652 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
6653 CONSCRYPT_UNUSED jobject holder) {
6654 CHECK_ERROR_QUEUE_ON_RETURN;
6655 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6656 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
6657 if (ssl_ctx == nullptr) {
6658 return;
6659 }
6660 SSL_CTX_free(ssl_ctx);
6661 }
6662
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)6663 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
6664 CONSCRYPT_UNUSED jobject holder,
6665 jbyteArray sid_ctx) {
6666 CHECK_ERROR_QUEUE_ON_RETURN;
6667 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6668 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
6669 sid_ctx);
6670 if (ssl_ctx == nullptr) {
6671 return;
6672 }
6673
6674 ScopedByteArrayRO buf(env, sid_ctx);
6675 if (buf.get() == nullptr) {
6676 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
6677 ssl_ctx);
6678 return;
6679 }
6680
6681 unsigned int length = static_cast<unsigned int>(buf.size());
6682 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
6683 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
6684 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
6685 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
6686 return;
6687 }
6688 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
6689 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
6690 if (result == 0) {
6691 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6692 env, "NativeCrypto_SSL_CTX_set_session_id_context");
6693 return;
6694 }
6695 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
6696 }
6697
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)6698 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
6699 CONSCRYPT_UNUSED jobject holder, jlong seconds) {
6700 CHECK_ERROR_QUEUE_ON_RETURN;
6701 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6702 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
6703 if (ssl_ctx == nullptr) {
6704 return 0L;
6705 }
6706
6707 return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
6708 }
6709
6710 /**
6711 * public static native int SSL_new(long ssl_ctx) throws SSLException;
6712 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)6713 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
6714 CONSCRYPT_UNUSED jobject holder) {
6715 CHECK_ERROR_QUEUE_ON_RETURN;
6716 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
6717 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
6718 if (ssl_ctx == nullptr) {
6719 return 0;
6720 }
6721 bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
6722 if (ssl.get() == nullptr) {
6723 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
6724 "Unable to create SSL structure");
6725 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
6726 return 0;
6727 }
6728
6729 /*
6730 * Create our special application data.
6731 */
6732 AppData* appData = AppData::create();
6733 if (appData == nullptr) {
6734 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
6735 ERR_clear_error();
6736 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
6737 return 0;
6738 }
6739 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
6740
6741 SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
6742
6743 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
6744 return (jlong)ssl.release();
6745 }
6746
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject ssl_holder)6747 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
6748 CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject
6749 ssl_holder) {
6750 CHECK_ERROR_QUEUE_ON_RETURN;
6751 SSL* ssl = to_SSL(env, ssl_address, true);
6752 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
6753 if (ssl == nullptr) {
6754 return;
6755 }
6756
6757 // NOLINTNEXTLINE(runtime/int)
6758 long ret = SSL_enable_tls_channel_id(ssl);
6759 if (ret != 1L) {
6760 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
6761 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
6762 "Error enabling Channel ID");
6763 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
6764 return;
6765 }
6766 }
6767
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)6768 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
6769 CONSCRYPT_UNUSED jobject ssl_holder) {
6770 CHECK_ERROR_QUEUE_ON_RETURN;
6771 SSL* ssl = to_SSL(env, ssl_address, true);
6772 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
6773 if (ssl == nullptr) {
6774 return nullptr;
6775 }
6776
6777 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
6778 // as a constant anywhere.
6779 jbyteArray javaBytes = env->NewByteArray(64);
6780 ScopedByteArrayRW bytes(env, javaBytes);
6781 if (bytes.get() == nullptr) {
6782 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
6783 return nullptr;
6784 }
6785
6786 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
6787 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
6788 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
6789 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
6790 size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
6791 if (ret == 0) {
6792 // Channel ID either not set or did not verify
6793 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
6794 return nullptr;
6795 } else if (ret != 64) {
6796 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
6797 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
6798 "Error getting Channel ID");
6799 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
6800 return nullptr;
6801 }
6802
6803 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
6804 return javaBytes;
6805 }
6806
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)6807 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
6808 CONSCRYPT_UNUSED jobject ssl_holder,
6809 jobject pkeyRef) {
6810 CHECK_ERROR_QUEUE_ON_RETURN;
6811 SSL* ssl = to_SSL(env, ssl_address, true);
6812 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
6813 if (ssl == nullptr) {
6814 return;
6815 }
6816
6817 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
6818 if (pkey == nullptr) {
6819 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
6820 return;
6821 }
6822
6823 // NOLINTNEXTLINE(runtime/int)
6824 long ret = SSL_set1_tls_channel_id(ssl, pkey);
6825
6826 if (ret != 1L) {
6827 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
6828 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
6829 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
6830 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
6831 return;
6832 }
6833
6834 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
6835 }
6836
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)6837 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
6838 CONSCRYPT_UNUSED jobject ssl_holder,
6839 jobjectArray encodedCertificatesJava,
6840 jobject pkeyRef) {
6841 CHECK_ERROR_QUEUE_ON_RETURN;
6842 SSL* ssl = to_SSL(env, ssl_address, true);
6843 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
6844 encodedCertificatesJava, pkeyRef);
6845 if (ssl == nullptr) {
6846 return;
6847 }
6848 if (encodedCertificatesJava == nullptr) {
6849 conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
6850 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
6851 return;
6852 }
6853 size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
6854 if (numCerts == 0) {
6855 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
6856 "certificates.length == 0");
6857 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
6858 return;
6859 }
6860 if (pkeyRef == nullptr) {
6861 conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
6862 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
6863 return;
6864 }
6865
6866 // Get the private key.
6867 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
6868 if (pkey == nullptr) {
6869 conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
6870 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
6871 return;
6872 }
6873
6874 // Copy the certificates.
6875 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
6876 std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
6877 for (size_t i = 0; i < numCerts; ++i) {
6878 ScopedLocalRef<jbyteArray> certArray(
6879 env, reinterpret_cast<jbyteArray>(
6880 env->GetObjectArrayElement(encodedCertificatesJava, i)));
6881 certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
6882 if (!certBufferRefs[i]) {
6883 return;
6884 }
6885 certBuffers[i] = certBufferRefs[i].get();
6886 }
6887
6888 if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
6889 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
6890 "Error configuring certificate");
6891 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
6892 return;
6893 }
6894 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
6895 }
6896
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)6897 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
6898 CONSCRYPT_UNUSED jobject ssl_holder,
6899 jobjectArray principals) {
6900 CHECK_ERROR_QUEUE_ON_RETURN;
6901 SSL* ssl = to_SSL(env, ssl_address, true);
6902 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
6903 if (ssl == nullptr) {
6904 return;
6905 }
6906
6907 if (principals == nullptr) {
6908 conscrypt::jniutil::throwNullPointerException(env, "principals == null");
6909 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
6910 return;
6911 }
6912
6913 int length = env->GetArrayLength(principals);
6914 if (length == 0) {
6915 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
6916 "principals.length == 0");
6917 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
6918 return;
6919 }
6920
6921 bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
6922 if (principalsStack.get() == nullptr) {
6923 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
6924 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
6925 return;
6926 }
6927 for (int i = 0; i < length; i++) {
6928 ScopedLocalRef<jbyteArray> principal(
6929 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
6930 bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
6931 if (!buf) {
6932 return;
6933 }
6934 if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
6935 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
6936 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
6937 return;
6938 }
6939 OWNERSHIP_TRANSFERRED(buf);
6940 }
6941
6942 SSL_set0_client_CAs(ssl, principalsStack.release());
6943 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
6944 }
6945
6946 /**
6947 * public static native long SSL_set_mode(long ssl, long mode);
6948 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)6949 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
6950 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
6951 CHECK_ERROR_QUEUE_ON_RETURN;
6952 SSL* ssl = to_SSL(env, ssl_address, true);
6953 // NOLINTNEXTLINE(runtime/int)
6954 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
6955 if (ssl == nullptr) {
6956 return 0;
6957 }
6958 jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
6959 // NOLINTNEXTLINE(runtime/int)
6960 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
6961 return result;
6962 }
6963
6964 /**
6965 * public static native long SSL_set_options(long ssl, long options);
6966 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)6967 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
6968 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
6969 CHECK_ERROR_QUEUE_ON_RETURN;
6970 SSL* ssl = to_SSL(env, ssl_address, true);
6971 // NOLINTNEXTLINE(runtime/int)
6972 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
6973 if (ssl == nullptr) {
6974 return 0;
6975 }
6976 jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
6977 // NOLINTNEXTLINE(runtime/int)
6978 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
6979 return result;
6980 }
6981
6982 /**
6983 * public static native long SSL_clear_options(long ssl, long options);
6984 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)6985 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
6986 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
6987 CHECK_ERROR_QUEUE_ON_RETURN;
6988 SSL* ssl = to_SSL(env, ssl_address, true);
6989 // NOLINTNEXTLINE(runtime/int)
6990 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
6991 if (ssl == nullptr) {
6992 return 0;
6993 }
6994 jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
6995 // NOLINTNEXTLINE(runtime/int)
6996 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
6997 return result;
6998 }
6999
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)7000 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
7001 CONSCRYPT_UNUSED jobject ssl_holder,
7002 jint min_version, jint max_version) {
7003 CHECK_ERROR_QUEUE_ON_RETURN;
7004 SSL* ssl = to_SSL(env, ssl_address, true);
7005 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
7006 max_version);
7007 if (ssl == nullptr) {
7008 return 0;
7009 }
7010 int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
7011 int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
7012 // Return failure if either call failed.
7013 int result = 1;
7014 if (!min_result || !max_result) {
7015 result = 0;
7016 // The only possible error is an invalid version, so we don't need the details.
7017 ERR_clear_error();
7018 }
7019 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
7020 min_result, max_result, result);
7021 return result;
7022 }
7023
7024 /**
7025 * public static native void SSL_enable_signed_cert_timestamps(long ssl);
7026 */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7027 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
7028 CONSCRYPT_UNUSED jobject ssl_holder) {
7029 CHECK_ERROR_QUEUE_ON_RETURN;
7030 SSL* ssl = to_SSL(env, ssl_address, true);
7031 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
7032 if (ssl == nullptr) {
7033 return;
7034 }
7035
7036 SSL_enable_signed_cert_timestamps(ssl);
7037 }
7038
7039 /**
7040 * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
7041 */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7042 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
7043 JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
7044 CHECK_ERROR_QUEUE_ON_RETURN;
7045 SSL* ssl = to_SSL(env, ssl_address, true);
7046 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
7047 if (ssl == nullptr) {
7048 return nullptr;
7049 }
7050
7051 const uint8_t* data;
7052 size_t data_len;
7053 SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
7054
7055 if (data_len == 0) {
7056 JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
7057 return nullptr;
7058 }
7059
7060 jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
7061 if (result != nullptr) {
7062 env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
7063 }
7064 return result;
7065 }
7066
7067 /*
7068 * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
7069 */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)7070 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
7071 CONSCRYPT_UNUSED jobject ssl_holder,
7072 jbyteArray list) {
7073 CHECK_ERROR_QUEUE_ON_RETURN;
7074 SSL* ssl = to_SSL(env, ssl_address, true);
7075 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
7076 if (ssl == nullptr) {
7077 return;
7078 }
7079
7080 ScopedByteArrayRO listBytes(env, list);
7081 if (listBytes.get() == nullptr) {
7082 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
7083 return;
7084 }
7085
7086 if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
7087 listBytes.size())) {
7088 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
7089 } else {
7090 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
7091 }
7092 }
7093
7094 /*
7095 * public static native void SSL_enable_ocsp_stapling(long ssl);
7096 */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7097 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
7098 CONSCRYPT_UNUSED jobject ssl_holder) {
7099 CHECK_ERROR_QUEUE_ON_RETURN;
7100 SSL* ssl = to_SSL(env, ssl_address, true);
7101 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
7102 if (ssl == nullptr) {
7103 return;
7104 }
7105
7106 SSL_enable_ocsp_stapling(ssl);
7107 }
7108
7109 /*
7110 * public static native byte[] SSL_get_ocsp_response(long ssl);
7111 */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7112 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7113 CONSCRYPT_UNUSED jobject ssl_holder) {
7114 CHECK_ERROR_QUEUE_ON_RETURN;
7115 SSL* ssl = to_SSL(env, ssl_address, true);
7116 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
7117 if (ssl == nullptr) {
7118 return nullptr;
7119 }
7120
7121 const uint8_t* data;
7122 size_t data_len;
7123 SSL_get0_ocsp_response(ssl, &data, &data_len);
7124
7125 if (data_len == 0) {
7126 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
7127 return nullptr;
7128 }
7129
7130 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7131 if (byteArray.get() == nullptr) {
7132 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
7133 return nullptr;
7134 }
7135
7136 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7137 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
7138 data_len);
7139
7140 return byteArray.release();
7141 }
7142
7143 /*
7144 * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
7145 */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)7146 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7147 CONSCRYPT_UNUSED jobject ssl_holder,
7148 jbyteArray response) {
7149 CHECK_ERROR_QUEUE_ON_RETURN;
7150 SSL* ssl = to_SSL(env, ssl_address, true);
7151 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
7152 if (ssl == nullptr) {
7153 return;
7154 }
7155
7156 ScopedByteArrayRO responseBytes(env, response);
7157 if (responseBytes.get() == nullptr) {
7158 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
7159 return;
7160 }
7161
7162 if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
7163 responseBytes.size())) {
7164 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
7165 } else {
7166 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
7167 }
7168 }
7169
7170 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
7171 // to customize the length of their verify_data (with a default of 12 bytes). We accept
7172 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
7173 // tests and update this value if necessary.
7174 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
7175
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7176 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
7177 CONSCRYPT_UNUSED jobject ssl_holder) {
7178 CHECK_ERROR_QUEUE_ON_RETURN;
7179 SSL* ssl = to_SSL(env, ssl_address, true);
7180 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
7181 if (ssl == nullptr) {
7182 return nullptr;
7183 }
7184
7185 uint8_t data[MAX_TLS_UNIQUE_LENGTH];
7186 size_t data_len;
7187 int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
7188
7189 if (!ret || data_len == 0) {
7190 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
7191 return nullptr;
7192 }
7193
7194 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7195 if (byteArray.get() == nullptr) {
7196 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
7197 return nullptr;
7198 }
7199
7200 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7201 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
7202 data_len);
7203
7204 return byteArray.release();
7205 }
7206
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)7207 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
7208 CONSCRYPT_UNUSED jobject ssl_holder,
7209 jbyteArray label, jbyteArray context,
7210 jint num_bytes) {
7211 CHECK_ERROR_QUEUE_ON_RETURN;
7212 SSL* ssl = to_SSL(env, ssl_address, true);
7213 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
7214 if (ssl == nullptr) {
7215 return nullptr;
7216 }
7217 ScopedByteArrayRO labelBytes(env, label);
7218 if (labelBytes.get() == nullptr) {
7219 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
7220 return nullptr;
7221 }
7222 std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
7223 int ret;
7224 if (context == nullptr) {
7225 ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
7226 reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
7227 nullptr, 0, 0);
7228 } else {
7229 ScopedByteArrayRO contextBytes(env, context);
7230 if (contextBytes.get() == nullptr) {
7231 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
7232 ssl);
7233 return nullptr;
7234 }
7235 ret = SSL_export_keying_material(
7236 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
7237 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
7238 contextBytes.size(), 1);
7239 }
7240 if (!ret) {
7241 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
7242 conscrypt::jniutil::throwSSLExceptionStr);
7243 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
7244 return nullptr;
7245 }
7246 jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
7247 if (result == nullptr) {
7248 conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
7249 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
7250 return nullptr;
7251 }
7252 const jbyte* src = reinterpret_cast<jbyte*>(out.get());
7253 env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
7254 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
7255 return result;
7256 }
7257
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)7258 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
7259 CONSCRYPT_UNUSED jobject ssl_holder,
7260 jstring identityHintJava) {
7261 CHECK_ERROR_QUEUE_ON_RETURN;
7262 SSL* ssl = to_SSL(env, ssl_address, true);
7263 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
7264 identityHintJava);
7265 if (ssl == nullptr) {
7266 return;
7267 }
7268
7269 int ret;
7270 if (identityHintJava == nullptr) {
7271 ret = SSL_use_psk_identity_hint(ssl, nullptr);
7272 } else {
7273 ScopedUtfChars identityHint(env, identityHintJava);
7274 if (identityHint.c_str() == nullptr) {
7275 conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7276 return;
7277 }
7278 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7279 }
7280
7281 if (ret != 1) {
7282 int sslErrorCode = SSL_get_error(ssl, ret);
7283 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7284 "Failed to set PSK identity hint");
7285 }
7286 }
7287
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7288 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7289 CONSCRYPT_UNUSED jobject ssl_holder,
7290 jboolean enabled) {
7291 CHECK_ERROR_QUEUE_ON_RETURN;
7292 SSL* ssl = to_SSL(env, ssl_address, true);
7293 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
7294 if (ssl == nullptr) {
7295 return;
7296 }
7297
7298 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
7299 }
7300
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7301 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7302 CONSCRYPT_UNUSED jobject ssl_holder,
7303 jboolean enabled) {
7304 CHECK_ERROR_QUEUE_ON_RETURN;
7305 SSL* ssl = to_SSL(env, ssl_address, true);
7306 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
7307 if (ssl == nullptr) {
7308 return;
7309 }
7310
7311 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
7312 }
7313
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7314 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
7315 CONSCRYPT_UNUSED jobject ssl_holder) {
7316 CHECK_ERROR_QUEUE_ON_RETURN;
7317 SSL* ssl = to_SSL(env, ssl_address, true);
7318 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7319 if (ssl == nullptr) {
7320 return nullptr;
7321 }
7322
7323 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7324 size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7325 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
7326 ScopedLongArrayRW ciphers(env, ciphersArray.get());
7327 for (size_t i = 0; i < count; i++) {
7328 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7329 }
7330
7331 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
7332 return ciphersArray.release();
7333 }
7334
7335 /**
7336 * Sets the ciphers suites that are enabled in the SSL
7337 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)7338 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
7339 CONSCRYPT_UNUSED jobject ssl_holder,
7340 jobjectArray cipherSuites) {
7341 CHECK_ERROR_QUEUE_ON_RETURN;
7342 SSL* ssl = to_SSL(env, ssl_address, true);
7343 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7344 if (ssl == nullptr) {
7345 return;
7346 }
7347 if (cipherSuites == nullptr) {
7348 conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
7349 return;
7350 }
7351
7352 int length = env->GetArrayLength(cipherSuites);
7353
7354 /*
7355 * Special case for empty cipher list. This is considered an error by the
7356 * SSL_set_cipher_list API, but Java allows this silly configuration.
7357 * However, the SSL cipher list is still set even when SSL_set_cipher_list
7358 * returns 0 in this case. Just to make sure, we check the resulting cipher
7359 * list to make sure it's zero length.
7360 */
7361 if (length == 0) {
7362 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
7363 SSL_set_cipher_list(ssl, "");
7364 ERR_clear_error();
7365 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
7366 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
7367 conscrypt::jniutil::throwRuntimeException(
7368 env, "SSL_set_cipher_list did not update ciphers!");
7369 ERR_clear_error();
7370 }
7371 return;
7372 }
7373
7374 static const char noSSLv2[] = "!SSLv2";
7375 size_t cipherStringLen = strlen(noSSLv2);
7376
7377 for (int i = 0; i < length; i++) {
7378 ScopedLocalRef<jstring> cipherSuite(
7379 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7380 ScopedUtfChars c(env, cipherSuite.get());
7381 if (c.c_str() == nullptr) {
7382 return;
7383 }
7384
7385 if (cipherStringLen + 1 < cipherStringLen) {
7386 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7387 "Overflow in cipher suite strings");
7388 return;
7389 }
7390 cipherStringLen += 1; /* For the separating colon */
7391
7392 if (cipherStringLen + c.size() < cipherStringLen) {
7393 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7394 "Overflow in cipher suite strings");
7395 return;
7396 }
7397 cipherStringLen += c.size();
7398 }
7399
7400 if (cipherStringLen + 1 < cipherStringLen) {
7401 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7402 "Overflow in cipher suite strings");
7403 return;
7404 }
7405 cipherStringLen += 1; /* For final NUL. */
7406
7407 std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
7408 if (cipherString.get() == nullptr) {
7409 conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
7410 return;
7411 }
7412 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
7413 size_t j = strlen(noSSLv2);
7414
7415 for (int i = 0; i < length; i++) {
7416 ScopedLocalRef<jstring> cipherSuite(
7417 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7418 ScopedUtfChars c(env, cipherSuite.get());
7419
7420 cipherString[j++] = ':';
7421 memcpy(&cipherString[j], c.c_str(), c.size());
7422 j += c.size();
7423 }
7424
7425 cipherString[j++] = 0;
7426 if (j != cipherStringLen) {
7427 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7428 "Internal error");
7429 return;
7430 }
7431
7432 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
7433 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
7434 ERR_clear_error();
7435 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7436 "Illegal cipher suite strings.");
7437 return;
7438 }
7439 }
7440
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7441 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
7442 CONSCRYPT_UNUSED jobject ssl_holder) {
7443 CHECK_ERROR_QUEUE_ON_RETURN;
7444 SSL* ssl = to_SSL(env, ssl_address, true);
7445 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7446 if (ssl == nullptr) {
7447 return;
7448 }
7449 SSL_set_accept_state(ssl);
7450 }
7451
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7452 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
7453 CONSCRYPT_UNUSED jobject ssl_holder) {
7454 CHECK_ERROR_QUEUE_ON_RETURN;
7455 SSL* ssl = to_SSL(env, ssl_address, true);
7456 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7457 if (ssl == nullptr) {
7458 return;
7459 }
7460 SSL_set_connect_state(ssl);
7461 }
7462
7463 /**
7464 * Sets certificate expectations, especially for server to request client auth
7465 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)7466 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
7467 CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
7468 CHECK_ERROR_QUEUE_ON_RETURN;
7469 SSL* ssl = to_SSL(env, ssl_address, true);
7470 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7471 if (ssl == nullptr) {
7472 return;
7473 }
7474 SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
7475 }
7476
7477 /**
7478 * Sets the ciphers suites that are enabled in the SSL
7479 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)7480 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
7481 CONSCRYPT_UNUSED jobject ssl_holder,
7482 jlong ssl_session_address) {
7483 CHECK_ERROR_QUEUE_ON_RETURN;
7484 SSL* ssl = to_SSL(env, ssl_address, true);
7485 if (ssl == nullptr) {
7486 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
7487 return;
7488 }
7489
7490 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7491 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7492 if (ssl_session == nullptr) {
7493 return;
7494 }
7495
7496 int ret = SSL_set_session(ssl, ssl_session);
7497 if (ret != 1) {
7498 /*
7499 * Translate the error, and throw if it turns out to be a real
7500 * problem.
7501 */
7502 int sslErrorCode = SSL_get_error(ssl, ret);
7503 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7504 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7505 "SSL session set");
7506 }
7507 }
7508 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
7509 ret);
7510 }
7511
7512 /**
7513 * Sets the ciphers suites that are enabled in the SSL
7514 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)7515 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
7516 CONSCRYPT_UNUSED jobject ssl_holder,
7517 jboolean creation_enabled) {
7518 CHECK_ERROR_QUEUE_ON_RETURN;
7519 SSL* ssl = to_SSL(env, ssl_address, true);
7520 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
7521 creation_enabled);
7522 if (ssl == nullptr) {
7523 return;
7524 }
7525
7526 if (creation_enabled) {
7527 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7528 } else {
7529 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7530 }
7531 }
7532
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7533 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
7534 CONSCRYPT_UNUSED jobject ssl_holder) {
7535 CHECK_ERROR_QUEUE_ON_RETURN;
7536 SSL* ssl = to_SSL(env, ssl_address, true);
7537 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
7538 if (ssl == nullptr) {
7539 return JNI_FALSE;
7540 }
7541
7542 int reused = SSL_session_reused(ssl);
7543 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
7544 return static_cast<jboolean>(reused);
7545 }
7546
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7547 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
7548 CONSCRYPT_UNUSED jobject ssl_holder) {
7549 CHECK_ERROR_QUEUE_ON_RETURN;
7550 SSL* ssl = to_SSL(env, ssl_address, true);
7551 JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
7552 if (ssl == nullptr) {
7553 return;
7554 }
7555
7556 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
7557 }
7558
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)7559 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
7560 CONSCRYPT_UNUSED jobject ssl_holder,
7561 jstring hostname) {
7562 CHECK_ERROR_QUEUE_ON_RETURN;
7563 SSL* ssl = to_SSL(env, ssl_address, true);
7564 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
7565 if (ssl == nullptr) {
7566 return;
7567 }
7568
7569 ScopedUtfChars hostnameChars(env, hostname);
7570 if (hostnameChars.c_str() == nullptr) {
7571 return;
7572 }
7573 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
7574 hostnameChars.c_str());
7575
7576 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7577 if (ret != 1) {
7578 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7579 "Error setting host name");
7580 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7581 return;
7582 }
7583 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7584 }
7585
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7586 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
7587 CONSCRYPT_UNUSED jobject ssl_holder) {
7588 CHECK_ERROR_QUEUE_ON_RETURN;
7589 SSL* ssl = to_SSL(env, ssl_address, true);
7590 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7591 if (ssl == nullptr) {
7592 return nullptr;
7593 }
7594 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7595 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7596 return env->NewStringUTF(servername);
7597 }
7598
7599 /**
7600 * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
7601 * which should take precedence.
7602 */
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)7603 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
7604 const unsigned char* primary,
7605 const unsigned int primaryLength,
7606 const unsigned char* secondary,
7607 const unsigned int secondaryLength) {
7608 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
7609
7610 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
7611 secondaryLength);
7612 switch (status) {
7613 case OPENSSL_NPN_NEGOTIATED:
7614 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
7615 return SSL_TLSEXT_ERR_OK;
7616 break;
7617 case OPENSSL_NPN_UNSUPPORTED:
7618 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
7619 break;
7620 case OPENSSL_NPN_NO_OVERLAP:
7621 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
7622 break;
7623 }
7624 return SSL_TLSEXT_ERR_NOACK;
7625 }
7626
7627 /**
7628 * Calls out to an application-provided selector to choose the ALPN protocol.
7629 */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)7630 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
7631 unsigned char** out,
7632 unsigned char* outLen, const unsigned char* in,
7633 const unsigned int inLen) {
7634 // Copy the input array.
7635 ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
7636 if (protocols.get() == nullptr) {
7637 JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
7638 return SSL_TLSEXT_ERR_NOACK;
7639 }
7640 env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
7641 reinterpret_cast<const jbyte*>(in));
7642
7643 // Invoke the selection method.
7644 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7645 jmethodID methodID = env->GetMethodID(cls, "selectApplicationProtocol", "([B)I");
7646 jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
7647
7648 if (offset < 0) {
7649 JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
7650 return SSL_TLSEXT_ERR_NOACK;
7651 }
7652
7653 // Point the output to the selected protocol.
7654 *outLen = *(in + offset);
7655 *out = const_cast<unsigned char*>(in + offset + 1);
7656
7657 return SSL_TLSEXT_ERR_OK;
7658 }
7659
7660 /**
7661 * Callback for the server to select an ALPN protocol.
7662 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)7663 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
7664 const unsigned char* in, unsigned int inLen, void*) {
7665 JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
7666
7667 AppData* appData = toAppData(ssl);
7668 if (appData == nullptr) {
7669 JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
7670 return SSL_TLSEXT_ERR_NOACK;
7671 }
7672 JNIEnv* env = appData->env;
7673 if (env == nullptr) {
7674 CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
7675 JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
7676 return SSL_TLSEXT_ERR_NOACK;
7677 }
7678
7679 if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
7680 !appData->hasApplicationProtocolSelector)) {
7681 if (out != nullptr && outLen != nullptr) {
7682 *out = nullptr;
7683 *outLen = 0;
7684 }
7685 JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
7686 return SSL_TLSEXT_ERR_NOACK;
7687 }
7688
7689 if (appData->hasApplicationProtocolSelector) {
7690 return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
7691 const_cast<unsigned char**>(out), outLen, in, inLen);
7692 }
7693
7694 return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
7695 reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
7696 static_cast<unsigned int>(appData->applicationProtocolsLength),
7697 in, inLen);
7698 }
7699
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7700 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
7701 CONSCRYPT_UNUSED jobject ssl_holder) {
7702 CHECK_ERROR_QUEUE_ON_RETURN;
7703 SSL* ssl = to_SSL(env, ssl_address, true);
7704 JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
7705 if (ssl == nullptr) {
7706 return nullptr;
7707 }
7708 const jbyte* protocol;
7709 unsigned int protocolLength;
7710 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
7711 &protocolLength);
7712 if (protocolLength == 0) {
7713 return nullptr;
7714 }
7715 jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
7716 if (result != nullptr) {
7717 env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
7718 }
7719 return result;
7720 }
7721
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)7722 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
7723 CONSCRYPT_UNUSED jobject ssl_holder,
7724 jboolean client_mode, jbyteArray protocols) {
7725 CHECK_ERROR_QUEUE_ON_RETURN;
7726 SSL* ssl = to_SSL(env, ssl_address, true);
7727 if (ssl == nullptr) {
7728 return;
7729 }
7730 AppData* appData = toAppData(ssl);
7731 if (appData == nullptr) {
7732 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
7733 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
7734 return;
7735 }
7736
7737 if (protocols != nullptr) {
7738 if (client_mode) {
7739 ScopedByteArrayRO protosBytes(env, protocols);
7740 if (protosBytes.get() == nullptr) {
7741 JNI_TRACE(
7742 "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
7743 "protosBytes == null",
7744 ssl, protocols);
7745 return;
7746 }
7747
7748 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
7749 int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
7750 if (ret != 0) {
7751 conscrypt::jniutil::throwSSLExceptionStr(env,
7752 "Unable to set ALPN protocols for client");
7753 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
7754 return;
7755 }
7756 } else {
7757 // Server mode - configure the ALPN protocol selection callback.
7758 if (!appData->setApplicationProtocols(env, protocols)) {
7759 conscrypt::jniutil::throwSSLExceptionStr(env,
7760 "Unable to set ALPN protocols for server");
7761 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
7762 return;
7763 }
7764 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
7765 }
7766 }
7767 }
7768
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)7769 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
7770 CONSCRYPT_UNUSED jobject ssl_holder,
7771 jboolean hasSelector) {
7772 CHECK_ERROR_QUEUE_ON_RETURN;
7773 SSL* ssl = to_SSL(env, ssl_address, true);
7774 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
7775 hasSelector);
7776 if (ssl == nullptr) {
7777 return;
7778 }
7779 AppData* appData = toAppData(ssl);
7780 if (appData == nullptr) {
7781 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
7782 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
7783 return;
7784 }
7785
7786 appData->hasApplicationProtocolSelector = hasSelector;
7787 if (hasSelector) {
7788 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
7789 }
7790 }
7791
7792 /**
7793 * Perform SSL handshake
7794 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)7795 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
7796 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
7797 jobject shc, jint timeout_millis) {
7798 CHECK_ERROR_QUEUE_ON_RETURN;
7799 SSL* ssl = to_SSL(env, ssl_address, true);
7800 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
7801 shc, timeout_millis);
7802 if (ssl == nullptr) {
7803 return;
7804 }
7805 if (fdObject == nullptr) {
7806 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
7807 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
7808 return;
7809 }
7810 if (shc == nullptr) {
7811 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
7812 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
7813 ssl);
7814 return;
7815 }
7816
7817 NetFd fd(env, fdObject);
7818 if (fd.isClosed()) {
7819 // SocketException thrown by NetFd.isClosed
7820 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
7821 return;
7822 }
7823
7824 int ret = SSL_set_fd(ssl, fd.get());
7825 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
7826
7827 if (ret != 1) {
7828 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7829 "Error setting the file descriptor");
7830 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
7831 return;
7832 }
7833
7834 /*
7835 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
7836 * forever and we can use select() to find out if the socket is ready.
7837 */
7838 if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
7839 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
7840 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
7841 return;
7842 }
7843
7844 AppData* appData = toAppData(ssl);
7845 if (appData == nullptr) {
7846 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
7847 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
7848 return;
7849 }
7850
7851 ret = 0;
7852 SslError sslError;
7853 while (appData->aliveAndKicking) {
7854 errno = 0;
7855
7856 if (!appData->setCallbackState(env, shc, fdObject)) {
7857 // SocketException thrown by NetFd.isClosed
7858 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
7859 return;
7860 }
7861 ret = SSL_do_handshake(ssl);
7862 appData->clearCallbackState();
7863 // cert_verify_callback threw exception
7864 if (env->ExceptionCheck()) {
7865 ERR_clear_error();
7866 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
7867 return;
7868 }
7869 // success case
7870 if (ret == 1) {
7871 break;
7872 }
7873 // retry case
7874 if (errno == EINTR) {
7875 continue;
7876 }
7877 // error case
7878 sslError.reset(ssl, ret);
7879 JNI_TRACE(
7880 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
7881 "timeout_millis=%d",
7882 ssl, ret, errno, sslError.get(), timeout_millis);
7883
7884 /*
7885 * If SSL_do_handshake doesn't succeed due to the socket being
7886 * either unreadable or unwritable, we use sslSelect to
7887 * wait for it to become ready. If that doesn't happen
7888 * before the specified timeout or an error occurs, we
7889 * cancel the handshake. Otherwise we try the SSL_connect
7890 * again.
7891 */
7892 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
7893 appData->waitingThreads++;
7894 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
7895
7896 if (selectResult == THROWN_EXCEPTION) {
7897 // SocketException thrown by NetFd.isClosed
7898 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
7899 return;
7900 }
7901 if (selectResult == -1) {
7902 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7903 env, ssl, SSL_ERROR_SYSCALL, "handshake error",
7904 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
7905 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
7906 ssl);
7907 return;
7908 }
7909 if (selectResult == 0) {
7910 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
7911 ERR_clear_error();
7912 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
7913 ssl);
7914 return;
7915 }
7916 } else {
7917 // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
7918 break;
7919 }
7920 }
7921
7922 // clean error. See SSL_do_handshake(3SSL) man page.
7923 if (ret == 0) {
7924 /*
7925 * The other side closed the socket before the handshake could be
7926 * completed, but everything is within the bounds of the TLS protocol.
7927 * We still might want to find out the real reason of the failure.
7928 */
7929 if (sslError.get() == SSL_ERROR_NONE ||
7930 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
7931 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
7932 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
7933 } else {
7934 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7935 env, ssl, sslError.release(), "SSL handshake terminated",
7936 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
7937 }
7938 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
7939 return;
7940 }
7941
7942 // unclean error. See SSL_do_handshake(3SSL) man page.
7943 if (ret < 0) {
7944 /*
7945 * Translate the error and throw exception. We are sure it is an error
7946 * at this point.
7947 */
7948 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7949 env, ssl, sslError.release(), "SSL handshake aborted",
7950 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
7951 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
7952 return;
7953 }
7954 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
7955 }
7956
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7957 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
7958 CONSCRYPT_UNUSED jobject ssl_holder) {
7959 CHECK_ERROR_QUEUE_ON_RETURN;
7960 SSL* ssl = to_SSL(env, ssl_address, true);
7961 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
7962 if (ssl == nullptr) {
7963 return nullptr;
7964 }
7965 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
7966 if (cipher == nullptr) {
7967 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
7968 return nullptr;
7969 }
7970 const char* name = SSL_CIPHER_standard_name(cipher);
7971 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
7972 return env->NewStringUTF(name);
7973 }
7974
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7975 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
7976 CONSCRYPT_UNUSED jobject ssl_holder) {
7977 CHECK_ERROR_QUEUE_ON_RETURN;
7978 SSL* ssl = to_SSL(env, ssl_address, true);
7979 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
7980 if (ssl == nullptr) {
7981 return nullptr;
7982 }
7983 const char* protocol = SSL_get_version(ssl);
7984 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
7985 return env->NewStringUTF(protocol);
7986 }
7987
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7988 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
7989 CONSCRYPT_UNUSED jobject ssl_holder) {
7990 CHECK_ERROR_QUEUE_ON_RETURN;
7991 SSL* ssl = to_SSL(env, ssl_address, true);
7992 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
7993 if (ssl == nullptr) {
7994 return nullptr;
7995 }
7996
7997 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
7998 if (chain == nullptr) {
7999 return nullptr;
8000 }
8001
8002 ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
8003 if (array.get() == nullptr) {
8004 return nullptr;
8005 }
8006
8007 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
8008 return array.release();
8009 }
8010
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)8011 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8012 SslError* sslError, int read_timeout_millis) {
8013 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8014
8015 if (len == 0) {
8016 // Don't bother doing anything in this case.
8017 return 0;
8018 }
8019
8020 BIO* rbio = SSL_get_rbio(ssl);
8021 BIO* wbio = SSL_get_wbio(ssl);
8022
8023 AppData* appData = toAppData(ssl);
8024 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8025 if (appData == nullptr) {
8026 return THROW_SSLEXCEPTION;
8027 }
8028
8029 while (appData->aliveAndKicking) {
8030 errno = 0;
8031
8032 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8033
8034 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8035 !SSL_renegotiate_pending(ssl)) {
8036 JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
8037 SSL_state_string_long(ssl));
8038 return THROW_SSLEXCEPTION;
8039 }
8040
8041 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8042
8043 if (!appData->setCallbackState(env, shc, fdObject)) {
8044 return THROWN_EXCEPTION;
8045 }
8046 int result = SSL_read(ssl, buf, len);
8047 appData->clearCallbackState();
8048 // callbacks can happen if server requests renegotiation
8049 if (env->ExceptionCheck()) {
8050 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8051 return THROWN_EXCEPTION;
8052 }
8053 sslError->reset(ssl, result);
8054
8055 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
8056 if (conscrypt::trace::kWithJniTraceData) {
8057 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8058 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8059 size_t n = result - i;
8060 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8061 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8062 }
8063 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8064 }
8065 }
8066
8067 // If we have been successful in moving data around, check whether it
8068 // might make sense to wake up other blocked threads, so they can give
8069 // it a try, too.
8070 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8071 appData->waitingThreads > 0) {
8072 sslNotify(appData);
8073 }
8074
8075 // If we are blocked by the underlying socket, tell the world that
8076 // there will be one more waiting thread now.
8077 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8078 appData->waitingThreads++;
8079 }
8080
8081 appDataLock.unlock();
8082
8083 switch (sslError->get()) {
8084 // Successfully read at least one byte.
8085 case SSL_ERROR_NONE: {
8086 return result;
8087 }
8088
8089 // Read zero bytes. End of stream reached.
8090 case SSL_ERROR_ZERO_RETURN: {
8091 return -1;
8092 }
8093
8094 // Need to wait for availability of underlying layer, then retry.
8095 case SSL_ERROR_WANT_READ:
8096 case SSL_ERROR_WANT_WRITE: {
8097 int selectResult =
8098 sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
8099 if (selectResult == THROWN_EXCEPTION) {
8100 return THROWN_EXCEPTION;
8101 }
8102 if (selectResult == -1) {
8103 return THROW_SSLEXCEPTION;
8104 }
8105 if (selectResult == 0) {
8106 return THROW_SOCKETTIMEOUTEXCEPTION;
8107 }
8108
8109 break;
8110 }
8111
8112 // A problem occurred during a system call, but this is not
8113 // necessarily an error.
8114 case SSL_ERROR_SYSCALL: {
8115 // Connection closed without proper shutdown. Tell caller we
8116 // have reached end-of-stream.
8117 if (result == 0) {
8118 return -1;
8119 }
8120
8121 // System call has been interrupted. Simply retry.
8122 if (errno == EINTR) {
8123 break;
8124 }
8125
8126 // Note that for all other system call errors we fall through
8127 // to the default case, which results in an Exception.
8128 FALLTHROUGH_INTENDED;
8129 }
8130
8131 // Everything else is basically an error.
8132 default: { return THROW_SSLEXCEPTION; }
8133 }
8134 }
8135
8136 return -1;
8137 }
8138
8139 /**
8140 * OpenSSL read function (2): read into buffer at offset n chunks.
8141 * Returns the number of bytes read (success) or value <= 0 (failure).
8142 */
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)8143 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
8144 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8145 jobject shc, jbyteArray b, jint offset, jint len,
8146 jint read_timeout_millis) {
8147 CHECK_ERROR_QUEUE_ON_RETURN;
8148 SSL* ssl = to_SSL(env, ssl_address, true);
8149 JNI_TRACE(
8150 "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
8151 "read_timeout_millis=%d",
8152 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8153 if (ssl == nullptr) {
8154 return 0;
8155 }
8156 if (fdObject == nullptr) {
8157 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8158 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8159 return 0;
8160 }
8161 if (shc == nullptr) {
8162 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8163 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8164 return 0;
8165 }
8166 if (b == nullptr) {
8167 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8168 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
8169 return 0;
8170 }
8171
8172 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8173 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8174 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8175 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
8176 return 0;
8177 }
8178
8179 SslError sslError;
8180 int ret;
8181 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8182 if (len <= 1024) {
8183 // Allocate small buffers on the stack for performance.
8184 jbyte buf[1024];
8185 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
8186 read_timeout_millis);
8187 if (ret > 0) {
8188 // Don't bother applying changes if issues were encountered.
8189 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
8190 }
8191 } else {
8192 // Allocate larger buffers on the heap.
8193 // ARRAY_CHUNK_INVALID above ensures that len >= 0.
8194 jint remaining = len;
8195 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8196 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8197 // TODO(flooey): Use new(std::nothrow).
8198 if (buf.get() == nullptr) {
8199 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8200 return 0;
8201 }
8202 // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
8203 // by the number of internal calls to sslRead() below.
8204 ret = 0;
8205 while (remaining > 0) {
8206 jint temp_ret;
8207 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8208 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
8209 chunk_size, &sslError, read_timeout_millis);
8210 if (temp_ret < 0) {
8211 if (ret > 0) {
8212 // We've already read some bytes; attempt to preserve them if this is an
8213 // "expected" error.
8214 if (temp_ret == -1) {
8215 // EOF
8216 break;
8217 } else if (temp_ret == THROWN_EXCEPTION) {
8218 // FD closed. Subsequent calls to sslRead should reproduce the
8219 // exception.
8220 env->ExceptionClear();
8221 break;
8222 }
8223 }
8224 // An error was encountered. Handle below.
8225 ret = temp_ret;
8226 break;
8227 }
8228 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
8229 if (env->ExceptionCheck()) {
8230 // Error committing changes to JVM.
8231 return -1;
8232 }
8233 // Accumulate bytes read.
8234 ret += temp_ret;
8235 offset += temp_ret;
8236 remaining -= temp_ret;
8237 if (temp_ret < chunk_size) {
8238 // sslRead isn't able to fulfill our request right now.
8239 break;
8240 }
8241 }
8242 }
8243 } else {
8244 ScopedByteArrayRW bytes(env, b);
8245 if (bytes.get() == nullptr) {
8246 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8247 return 0;
8248 }
8249
8250 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8251 &sslError, read_timeout_millis);
8252 }
8253
8254 int result;
8255 switch (ret) {
8256 case THROW_SSLEXCEPTION:
8257 // See sslRead() regarding improper failure to handle normal cases.
8258 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8259 "Read error");
8260 result = -1;
8261 break;
8262 case THROW_SOCKETTIMEOUTEXCEPTION:
8263 conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
8264 result = -1;
8265 break;
8266 case THROWN_EXCEPTION:
8267 // SocketException thrown by NetFd.isClosed
8268 // or RuntimeException thrown by callback
8269 result = -1;
8270 break;
8271 default:
8272 result = ret;
8273 break;
8274 }
8275
8276 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8277 return result;
8278 }
8279
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)8280 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8281 SslError* sslError, int write_timeout_millis) {
8282 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
8283 write_timeout_millis);
8284
8285 if (len == 0) {
8286 // Don't bother doing anything in this case.
8287 return 0;
8288 }
8289
8290 BIO* rbio = SSL_get_rbio(ssl);
8291 BIO* wbio = SSL_get_wbio(ssl);
8292
8293 AppData* appData = toAppData(ssl);
8294 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8295 if (appData == nullptr) {
8296 return THROW_SSLEXCEPTION;
8297 }
8298
8299 int count = len;
8300
8301 while (appData->aliveAndKicking && len > 0) {
8302 errno = 0;
8303
8304 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8305
8306 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8307 !SSL_renegotiate_pending(ssl)) {
8308 JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
8309 SSL_state_string_long(ssl));
8310 return THROW_SSLEXCEPTION;
8311 }
8312
8313 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8314
8315 if (!appData->setCallbackState(env, shc, fdObject)) {
8316 return THROWN_EXCEPTION;
8317 }
8318 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
8319 int result = SSL_write(ssl, buf, len);
8320 appData->clearCallbackState();
8321 // callbacks can happen if server requests renegotiation
8322 if (env->ExceptionCheck()) {
8323 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8324 return THROWN_EXCEPTION;
8325 }
8326 sslError->reset(ssl, result);
8327
8328 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
8329 if (conscrypt::trace::kWithJniTraceData) {
8330 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8331 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8332 size_t n = result - i;
8333 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8334 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8335 }
8336 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8337 }
8338 }
8339
8340 // If we have been successful in moving data around, check whether it
8341 // might make sense to wake up other blocked threads, so they can give
8342 // it a try, too.
8343 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8344 appData->waitingThreads > 0) {
8345 sslNotify(appData);
8346 }
8347
8348 // If we are blocked by the underlying socket, tell the world that
8349 // there will be one more waiting thread now.
8350 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8351 appData->waitingThreads++;
8352 }
8353
8354 appDataLock.unlock();
8355
8356 switch (sslError->get()) {
8357 // Successfully wrote at least one byte.
8358 case SSL_ERROR_NONE: {
8359 buf += result;
8360 len -= result;
8361 break;
8362 }
8363
8364 // Wrote zero bytes. End of stream reached.
8365 case SSL_ERROR_ZERO_RETURN: {
8366 return -1;
8367 }
8368
8369 // Need to wait for availability of underlying layer, then retry.
8370 // The concept of a write timeout doesn't really make sense, and
8371 // it's also not standard Java behavior, so we wait forever here.
8372 case SSL_ERROR_WANT_READ:
8373 case SSL_ERROR_WANT_WRITE: {
8374 int selectResult =
8375 sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
8376 if (selectResult == THROWN_EXCEPTION) {
8377 return THROWN_EXCEPTION;
8378 }
8379 if (selectResult == -1) {
8380 return THROW_SSLEXCEPTION;
8381 }
8382 if (selectResult == 0) {
8383 return THROW_SOCKETTIMEOUTEXCEPTION;
8384 }
8385
8386 break;
8387 }
8388
8389 // A problem occurred during a system call, but this is not
8390 // necessarily an error.
8391 case SSL_ERROR_SYSCALL: {
8392 // Connection closed without proper shutdown. Tell caller we
8393 // have reached end-of-stream.
8394 if (result == 0) {
8395 return -1;
8396 }
8397
8398 // System call has been interrupted. Simply retry.
8399 if (errno == EINTR) {
8400 break;
8401 }
8402
8403 // Note that for all other system call errors we fall through
8404 // to the default case, which results in an Exception.
8405 FALLTHROUGH_INTENDED;
8406 }
8407
8408 // Everything else is basically an error.
8409 default: { return THROW_SSLEXCEPTION; }
8410 }
8411 }
8412 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8413
8414 return count;
8415 }
8416
8417 /**
8418 * OpenSSL write function (2): write into buffer at offset n chunks.
8419 */
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)8420 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
8421 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8422 jobject shc, jbyteArray b, jint offset, jint len,
8423 jint write_timeout_millis) {
8424 CHECK_ERROR_QUEUE_ON_RETURN;
8425 SSL* ssl = to_SSL(env, ssl_address, true);
8426 JNI_TRACE(
8427 "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
8428 "write_timeout_millis=%d",
8429 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8430 if (ssl == nullptr) {
8431 return;
8432 }
8433 if (fdObject == nullptr) {
8434 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8435 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8436 return;
8437 }
8438 if (shc == nullptr) {
8439 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8440 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8441 return;
8442 }
8443 if (b == nullptr) {
8444 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8445 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
8446 return;
8447 }
8448
8449 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8450 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8451 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8452 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
8453 return;
8454 }
8455
8456 SslError sslError;
8457 int ret;
8458 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8459 if (len <= 1024) {
8460 jbyte buf[1024];
8461 env->GetByteArrayRegion(b, offset, len, buf);
8462 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
8463 &sslError, write_timeout_millis);
8464 } else {
8465 // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
8466 jint remaining = len;
8467 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8468 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8469 if (buf.get() == nullptr) {
8470 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8471 return;
8472 }
8473 while (remaining > 0) {
8474 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8475 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
8476 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
8477 chunk_size, &sslError, write_timeout_millis);
8478 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
8479 ret == THROWN_EXCEPTION) {
8480 // Encountered an error. Terminate early and handle below.
8481 break;
8482 }
8483 offset += ret;
8484 remaining -= ret;
8485 }
8486 }
8487 } else {
8488 ScopedByteArrayRO bytes(env, b);
8489 if (bytes.get() == nullptr) {
8490 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8491 return;
8492 }
8493 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8494 len, &sslError, write_timeout_millis);
8495 }
8496
8497 switch (ret) {
8498 case THROW_SSLEXCEPTION:
8499 // See sslWrite() regarding improper failure to handle normal cases.
8500 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8501 "Write error");
8502 break;
8503 case THROW_SOCKETTIMEOUTEXCEPTION:
8504 conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
8505 break;
8506 case THROWN_EXCEPTION:
8507 // SocketException thrown by NetFd.isClosed
8508 break;
8509 default:
8510 break;
8511 }
8512 }
8513
8514 /**
8515 * Interrupt any pending I/O before closing the socket.
8516 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8517 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
8518 CONSCRYPT_UNUSED jobject ssl_holder) {
8519 CHECK_ERROR_QUEUE_ON_RETURN;
8520 SSL* ssl = to_SSL(env, ssl_address, false);
8521 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
8522 if (ssl == nullptr) {
8523 return;
8524 }
8525
8526 /*
8527 * Mark the connection as quasi-dead, then send something to the emergency
8528 * file descriptor, so any blocking select() calls are woken up.
8529 */
8530 AppData* appData = toAppData(ssl);
8531 if (appData != nullptr) {
8532 appData->aliveAndKicking = false;
8533
8534 // At most two threads can be waiting.
8535 sslNotify(appData);
8536 sslNotify(appData);
8537 }
8538 }
8539
8540 /**
8541 * OpenSSL close SSL socket function.
8542 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)8543 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
8544 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8545 jobject shc) {
8546 CHECK_ERROR_QUEUE_ON_RETURN;
8547 SSL* ssl = to_SSL(env, ssl_address, false);
8548 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
8549 if (ssl == nullptr) {
8550 return;
8551 }
8552 if (fdObject == nullptr) {
8553 return;
8554 }
8555 if (shc == nullptr) {
8556 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8557 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
8558 return;
8559 }
8560
8561 AppData* appData = toAppData(ssl);
8562 if (appData != nullptr) {
8563 if (!appData->setCallbackState(env, shc, fdObject)) {
8564 // SocketException thrown by NetFd.isClosed
8565 ERR_clear_error();
8566 return;
8567 }
8568
8569 /*
8570 * Try to make socket blocking again. OpenSSL literature recommends this.
8571 */
8572 int fd = SSL_get_fd(ssl);
8573 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
8574 #ifndef _WIN32
8575 if (fd != -1) {
8576 conscrypt::netutil::setBlocking(fd, true);
8577 }
8578 #endif
8579
8580 int ret = SSL_shutdown(ssl);
8581 appData->clearCallbackState();
8582 // callbacks can happen if server requests renegotiation
8583 if (env->ExceptionCheck()) {
8584 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
8585 return;
8586 }
8587 switch (ret) {
8588 case 0:
8589 /*
8590 * Shutdown was not successful (yet), but there also
8591 * is no error. Since we can't know whether the remote
8592 * server is actually still there, and we don't want to
8593 * get stuck forever in a second SSL_shutdown() call, we
8594 * simply return. This is not security a problem as long
8595 * as we close the underlying socket, which we actually
8596 * do, because that's where we are just coming from.
8597 */
8598 break;
8599 case 1:
8600 /*
8601 * Shutdown was successful. We can safely return. Hooray!
8602 */
8603 break;
8604 default:
8605 /*
8606 * Everything else is a real error condition. We should
8607 * let the Java layer know about this by throwing an
8608 * exception.
8609 */
8610 int sslError = SSL_get_error(ssl, ret);
8611 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
8612 "SSL shutdown failed");
8613 break;
8614 }
8615 }
8616
8617 ERR_clear_error();
8618 }
8619
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8620 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
8621 CONSCRYPT_UNUSED jobject ssl_holder) {
8622 CHECK_ERROR_QUEUE_ON_RETURN;
8623 const SSL* ssl = to_SSL(env, ssl_address, true);
8624 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
8625 if (ssl == nullptr) {
8626 return 0;
8627 }
8628
8629 int status = SSL_get_shutdown(ssl);
8630 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
8631 return static_cast<jint>(status);
8632 }
8633
8634 /**
8635 * public static native void SSL_free(long ssl);
8636 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8637 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
8638 CONSCRYPT_UNUSED jobject ssl_holder) {
8639 CHECK_ERROR_QUEUE_ON_RETURN;
8640 SSL* ssl = to_SSL(env, ssl_address, true);
8641 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
8642 if (ssl == nullptr) {
8643 return;
8644 }
8645
8646 AppData* appData = toAppData(ssl);
8647 SSL_set_app_data(ssl, nullptr);
8648 delete appData;
8649 SSL_free(ssl);
8650 }
8651
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)8652 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
8653 unsigned int length;
8654 const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
8655 JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
8656 if (id && length > 0) {
8657 jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
8658 if (result != nullptr) {
8659 const jbyte* src = reinterpret_cast<const jbyte*>(id);
8660 env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
8661 }
8662 return result;
8663 }
8664 return nullptr;
8665 }
8666
8667 /**
8668 * Gets and returns in a byte array the ID of the actual SSL session.
8669 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)8670 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
8671 jlong ssl_session_address) {
8672 CHECK_ERROR_QUEUE_ON_RETURN;
8673 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8674 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
8675 if (ssl_session == nullptr) {
8676 return nullptr;
8677 }
8678 jbyteArray result = get_session_id(env, ssl_session);
8679 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
8680 return result;
8681 }
8682
8683 /**
8684 * Gets and returns in a long integer the creation's time of the
8685 * actual SSL session.
8686 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)8687 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
8688 CHECK_ERROR_QUEUE_ON_RETURN;
8689 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8690 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
8691 if (ssl_session == nullptr) {
8692 return 0;
8693 }
8694 // result must be jlong, not long or *1000 will overflow
8695 jlong result = SSL_SESSION_get_time(ssl_session);
8696 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
8697 // NOLINTNEXTLINE(runtime/int)
8698 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
8699 (long long)result); // NOLINT(runtime/int)
8700 return result;
8701 }
8702
8703 /**
8704 * Gets and returns in a long integer the creation's time of the
8705 * actual SSL session.
8706 */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8707 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
8708 CONSCRYPT_UNUSED jobject ssl_holder) {
8709 CHECK_ERROR_QUEUE_ON_RETURN;
8710 SSL* ssl = to_SSL(env, ssl_address, true);
8711 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
8712 if (ssl == nullptr) {
8713 return 0;
8714 }
8715
8716 SSL_SESSION* ssl_session = SSL_get_session(ssl);
8717 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
8718 if (ssl_session == nullptr) {
8719 // BoringSSL does not protect against a NULL session.
8720 return 0;
8721 }
8722 // result must be jlong, not long or *1000 will overflow
8723 jlong result = SSL_SESSION_get_time(ssl_session);
8724 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
8725 // NOLINTNEXTLINE(runtime/int)
8726 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
8727 return result;
8728 }
8729
8730 /**
8731 * Sets the timeout on the SSL session.
8732 */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)8733 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
8734 CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
8735 CHECK_ERROR_QUEUE_ON_RETURN;
8736 SSL* ssl = to_SSL(env, ssl_address, true);
8737 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
8738 if (ssl == nullptr) {
8739 return 0;
8740 }
8741
8742 SSL_SESSION* ssl_session = SSL_get_session(ssl);
8743 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
8744 if (ssl_session == nullptr) {
8745 // BoringSSL does not protect against a NULL session.
8746 return 0;
8747 }
8748
8749 // Convert to seconds
8750 static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
8751 uint32_t timeout = static_cast<uint32_t>(
8752 std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
8753 return SSL_set_timeout(ssl_session, timeout);
8754 }
8755
8756 /**
8757 * Gets the timeout for the SSL session.
8758 */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8759 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
8760 CONSCRYPT_UNUSED jobject ssl_holder) {
8761 CHECK_ERROR_QUEUE_ON_RETURN;
8762 SSL* ssl = to_SSL(env, ssl_address, true);
8763 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
8764 if (ssl == nullptr) {
8765 return 0;
8766 }
8767
8768 SSL_SESSION* ssl_session = SSL_get_session(ssl);
8769 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
8770 if (ssl_session == nullptr) {
8771 // BoringSSL does not protect against a NULL session.
8772 return 0;
8773 }
8774
8775 jlong result = SSL_get_timeout(ssl_session);
8776 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
8777 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
8778 (long long)result) // NOLINT(runtime/int);
8779 return result;
8780 }
8781
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)8782 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
8783 jint signatureAlg) {
8784 CHECK_ERROR_QUEUE_ON_RETURN;
8785 return SSL_get_signature_algorithm_key_type(signatureAlg);
8786 }
8787
8788 /**
8789 * Gets the timeout for the SSL session.
8790 */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)8791 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
8792 CHECK_ERROR_QUEUE_ON_RETURN;
8793 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8794 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
8795 if (ssl_session == nullptr) {
8796 return 0;
8797 }
8798
8799 return SSL_get_timeout(ssl_session);
8800 }
8801
8802 /**
8803 * Gets the ID for the SSL session, or null if no session is currently available.
8804 */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8805 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
8806 CONSCRYPT_UNUSED jobject ssl_holder) {
8807 CHECK_ERROR_QUEUE_ON_RETURN;
8808 SSL* ssl = to_SSL(env, ssl_address, true);
8809 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
8810 if (ssl == nullptr) {
8811 return nullptr;
8812 }
8813
8814 SSL_SESSION* ssl_session = SSL_get_session(ssl);
8815 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
8816 if (ssl_session == nullptr) {
8817 return nullptr;
8818 }
8819 jbyteArray result = get_session_id(env, ssl_session);
8820 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
8821 return result;
8822 }
8823
8824 /**
8825 * Gets and returns in a string the version of the SSL protocol. If it
8826 * returns the string "unknown" it means that no connection is established.
8827 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)8828 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
8829 jlong ssl_session_address) {
8830 CHECK_ERROR_QUEUE_ON_RETURN;
8831 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8832 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
8833 if (ssl_session == nullptr) {
8834 return nullptr;
8835 }
8836 const char* protocol = SSL_SESSION_get_version(ssl_session);
8837 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
8838 return env->NewStringUTF(protocol);
8839 }
8840
8841 /**
8842 * Gets and returns in a string the cipher negotiated for the SSL session.
8843 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)8844 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
8845 CHECK_ERROR_QUEUE_ON_RETURN;
8846 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8847 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
8848 if (ssl_session == nullptr) {
8849 return nullptr;
8850 }
8851 const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
8852 const char* name = SSL_CIPHER_standard_name(cipher);
8853 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
8854 return env->NewStringUTF(name);
8855 }
8856
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)8857 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
8858 jlong ssl_session_address) {
8859 CHECK_ERROR_QUEUE_ON_RETURN;
8860 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8861 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
8862 if (ssl_session == nullptr) {
8863 return JNI_FALSE;
8864 }
8865 int single_use = SSL_SESSION_should_be_single_use(ssl_session);
8866 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
8867 single_use);
8868 return single_use ? JNI_TRUE : JNI_FALSE;
8869 }
8870
8871 /**
8872 * Increments the reference count of the session.
8873 */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)8874 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
8875 CHECK_ERROR_QUEUE_ON_RETURN;
8876 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8877 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
8878 if (ssl_session == nullptr) {
8879 return;
8880 }
8881 SSL_SESSION_up_ref(ssl_session);
8882 }
8883
8884 /**
8885 * Frees the SSL session.
8886 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)8887 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
8888 CHECK_ERROR_QUEUE_ON_RETURN;
8889 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8890 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
8891 if (ssl_session == nullptr) {
8892 return;
8893 }
8894 SSL_SESSION_free(ssl_session);
8895 }
8896
8897 /**
8898 * Serializes the native state of the session (ID, cipher, and keys but
8899 * not certificates). Returns a byte[] containing the DER-encoded state.
8900 * See apache mod_ssl.
8901 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)8902 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
8903 CHECK_ERROR_QUEUE_ON_RETURN;
8904 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
8905 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
8906 if (ssl_session == nullptr) {
8907 return nullptr;
8908 }
8909 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
8910 }
8911
8912 /**
8913 * Deserialize the session.
8914 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)8915 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
8916 CHECK_ERROR_QUEUE_ON_RETURN;
8917 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
8918
8919 ScopedByteArrayRO bytes(env, javaBytes);
8920 if (bytes.get() == nullptr) {
8921 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
8922 return 0;
8923 }
8924 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
8925 // NOLINTNEXTLINE(runtime/int)
8926 SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
8927
8928 if (ssl_session == nullptr ||
8929 ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
8930 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
8931 conscrypt::jniutil::throwIOException);
8932 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
8933 return 0L;
8934 }
8935
8936 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
8937 return reinterpret_cast<uintptr_t>(ssl_session);
8938 }
8939
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)8940 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
8941 CHECK_ERROR_QUEUE_ON_RETURN;
8942 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, true);
8943 const char* kx_name = nullptr;
8944
8945 kx_name = SSL_CIPHER_get_kx_name(cipher);
8946
8947 return env->NewStringUTF(kx_name);
8948 }
8949
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)8950 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
8951 CHECK_ERROR_QUEUE_ON_RETURN;
8952 ScopedUtfChars selector(env, selectorJava);
8953 if (selector.c_str() == nullptr) {
8954 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8955 "selector == null");
8956 return nullptr;
8957 }
8958
8959 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
8960
8961 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
8962 bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
8963
8964 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
8965 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8966 "Unable to set SSL cipher list");
8967 return nullptr;
8968 }
8969 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
8970
8971 size_t size = sk_SSL_CIPHER_num(ciphers);
8972 ScopedLocalRef<jobjectArray> cipherNamesArray(
8973 env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
8974 nullptr));
8975 if (cipherNamesArray.get() == nullptr) {
8976 return nullptr;
8977 }
8978
8979 // Return an array of standard and OpenSSL name pairs.
8980 for (size_t i = 0; i < size; i++) {
8981 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
8982 ScopedLocalRef<jstring> cipherName(env,
8983 env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
8984 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
8985 cipherName.get());
8986
8987 ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
8988 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
8989 opensslName.get());
8990 }
8991
8992 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
8993 2 * size);
8994 return cipherNamesArray.release();
8995 }
8996
8997 /**
8998 * Compare the given CertID with a certificate and it's issuer.
8999 * True is returned if the CertID matches.
9000 */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)9001 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
9002 // Get the hash algorithm used by this CertID
9003 CBS hash_algorithm, hash;
9004 if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
9005 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
9006 return false;
9007 }
9008
9009 // Get the issuer's name hash from the CertID
9010 CBS issuer_name_hash;
9011 if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
9012 return false;
9013 }
9014
9015 // Get the issuer's key hash from the CertID
9016 CBS issuer_key_hash;
9017 if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
9018 return false;
9019 }
9020
9021 // Get the serial number from the CertID
9022 CBS serial;
9023 if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
9024 return false;
9025 }
9026
9027 // Compare the certificate's serial number with the one from the Cert ID
9028 const uint8_t* p = CBS_data(&serial);
9029 bssl::UniquePtr<ASN1_INTEGER> serial_number(
9030 c2i_ASN1_INTEGER(nullptr, &p,
9031 static_cast<long>(CBS_len(&serial)))); // NOLINT(runtime/int)
9032 ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
9033 if (serial_number.get() == nullptr ||
9034 ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
9035 return false;
9036 }
9037
9038 // Find the hash algorithm to be used
9039 const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
9040 if (digest == nullptr) {
9041 return false;
9042 }
9043
9044 // Hash the issuer's name and compare the hash with the one from the Cert ID
9045 uint8_t md[EVP_MAX_MD_SIZE];
9046 X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
9047 if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
9048 !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
9049 return false;
9050 }
9051
9052 // Same thing with the issuer's key
9053 ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
9054 if (!EVP_Digest(issuer_key->data, static_cast<size_t>(issuer_key->length), md, nullptr, digest,
9055 nullptr) ||
9056 !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
9057 return false;
9058 }
9059
9060 return true;
9061 }
9062
9063 /**
9064 * Get a SingleResponse whose CertID matches the given certificate and issuer from a
9065 * SEQUENCE OF SingleResponse.
9066 *
9067 * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
9068 * error occured or no response matches the certificate, false is returned and |out_single_response|
9069 * is unchanged.
9070 */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)9071 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
9072 CBS* out_single_response) {
9073 // Iterate over all the SingleResponses, until one matches the certificate
9074 while (CBS_len(responses) > 0) {
9075 // Get the next available SingleResponse from the sequence
9076 CBS single_response;
9077 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
9078 return false;
9079 }
9080
9081 // Make a copy of the stream so we pass it back to the caller
9082 CBS single_response_original = single_response;
9083
9084 // Get the SingleResponse's CertID
9085 // If this fails ignore the current response and move to the next one
9086 CBS cert_id;
9087 if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
9088 continue;
9089 }
9090
9091 // Compare the CertID with the given certificate and issuer
9092 if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
9093 *out_single_response = single_response_original;
9094 return true;
9095 }
9096 }
9097
9098 return false;
9099 }
9100
9101 /**
9102 * Get the BasicOCSPResponse from an OCSPResponse.
9103 * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
9104 * returned.
9105 */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)9106 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
9107 CBS tagged_response_bytes, response_bytes, response_type, response;
9108
9109 // Get the ResponseBytes out of the OCSPResponse
9110 if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
9111 !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
9112 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9113 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
9114 return false;
9115 }
9116
9117 // Parse the response type and data out of the ResponseBytes
9118 if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
9119 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
9120 return false;
9121 }
9122
9123 // Only basic OCSP responses are supported
9124 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
9125 return false;
9126 }
9127
9128 // Parse the octet string as a BasicOCSPResponse
9129 return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
9130 }
9131
9132 /**
9133 * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
9134 * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
9135 * true is returned.
9136 */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)9137 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
9138 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
9139 CBS response_data;
9140 if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
9141 return false;
9142 }
9143
9144 // Skip the version, responderID and producedAt fields
9145 if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
9146 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9147 !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
9148 !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
9149 return false;
9150 }
9151
9152 // Extract the list of SingleResponse.
9153 return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
9154 }
9155
9156 /**
9157 * Get the SEQUENCE OF Extension from a SingleResponse.
9158 * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
9159 * returned.
9160 */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)9161 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
9162 // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
9163 if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
9164 !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
9165 !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
9166 !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
9167 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
9168 return false;
9169 }
9170
9171 // Get the list of Extension
9172 return CBS_get_asn1(single_response, extensions,
9173 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
9174 }
9175
9176 /*
9177 * X509v3_get_ext_by_OBJ and X509v3_get_ext take const arguments, unlike the other *_get_ext
9178 * functions.
9179 * This means they cannot be used with X509Type_get_ext_oid, so these wrapper functions are used
9180 * instead.
9181 */
_X509v3_get_ext_by_OBJ(X509_EXTENSIONS * exts,ASN1_OBJECT * obj,int lastpos)9182 static int _X509v3_get_ext_by_OBJ(X509_EXTENSIONS* exts, ASN1_OBJECT* obj, int lastpos) {
9183 return X509v3_get_ext_by_OBJ(exts, obj, lastpos);
9184 }
9185
_X509v3_get_ext(X509_EXTENSIONS * exts,int loc)9186 static X509_EXTENSION* _X509v3_get_ext(X509_EXTENSIONS* exts, int loc) {
9187 return X509v3_get_ext(exts, loc);
9188 }
9189
9190 /*
9191 public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
9192 long x509Ref, long issuerX509Ref);
9193 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)9194 static jbyteArray NativeCrypto_get_ocsp_single_extension(
9195 JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
9196 CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
9197 CHECK_ERROR_QUEUE_ON_RETURN;
9198 ScopedByteArrayRO ocspData(env, ocspDataBytes);
9199 if (ocspData.get() == nullptr) {
9200 return nullptr;
9201 }
9202
9203 CBS cbs;
9204 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
9205
9206 // Start parsing the OCSPResponse
9207 CBS ocsp_response;
9208 if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
9209 return nullptr;
9210 }
9211
9212 // Get the BasicOCSPResponse from the OCSP Response
9213 CBS basic_response;
9214 if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
9215 return nullptr;
9216 }
9217
9218 // Get the list of SingleResponses from the BasicOCSPResponse
9219 CBS responses;
9220 if (!get_ocsp_single_responses(&basic_response, &responses)) {
9221 return nullptr;
9222 }
9223
9224 // Find the response matching the certificate
9225 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
9226 X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
9227 CBS single_response;
9228 if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
9229 return nullptr;
9230 }
9231
9232 // Get the extensions from the SingleResponse
9233 CBS extensions;
9234 if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
9235 return nullptr;
9236 }
9237
9238 const uint8_t* ptr = CBS_data(&extensions);
9239 bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
9240 d2i_X509_EXTENSIONS(nullptr, &ptr,
9241 static_cast<long>(CBS_len(&extensions)))); // NOLINT(runtime/int)
9242 if (x509_exts.get() == nullptr) {
9243 return nullptr;
9244 }
9245
9246 return X509Type_get_ext_oid<X509_EXTENSIONS, _X509v3_get_ext_by_OBJ, _X509v3_get_ext>(
9247 env, x509_exts.get(), oid);
9248 }
9249
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)9250 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
9251 return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
9252 }
9253
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)9254 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
9255 CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
9256 CHECK_ERROR_QUEUE_ON_RETURN;
9257 SSL* ssl = to_SSL(env, ssl_address, true);
9258 if (ssl == nullptr) {
9259 return 0;
9260 }
9261 return SSL_get_error(ssl, ret);
9262 }
9263
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)9264 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
9265 ERR_clear_error();
9266 }
9267
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9268 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
9269 CONSCRYPT_UNUSED jobject ssl_holder) {
9270 CHECK_ERROR_QUEUE_ON_RETURN;
9271 SSL* ssl = to_SSL(env, ssl_address, true);
9272 if (ssl == nullptr) {
9273 return 0;
9274 }
9275 return SSL_pending(ssl);
9276 }
9277
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)9278 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
9279 CHECK_ERROR_QUEUE_ON_RETURN;
9280 BIO* bio = to_SSL_BIO(env, bio_address, true);
9281 if (bio == nullptr) {
9282 return 0;
9283 }
9284 return static_cast<jint>(BIO_ctrl_pending(bio));
9285 }
9286
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9287 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
9288 CONSCRYPT_UNUSED jobject ssl_holder) {
9289 CHECK_ERROR_QUEUE_ON_RETURN;
9290 SSL* ssl = to_SSL(env, ssl_address, true);
9291 if (ssl == nullptr) {
9292 return 0;
9293 }
9294 return (jint)SSL_max_seal_overhead(ssl);
9295 }
9296
9297 /**
9298 * public static native int SSL_new_BIO(long ssl) throws SSLException;
9299 */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9300 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
9301 CONSCRYPT_UNUSED jobject ssl_holder) {
9302 CHECK_ERROR_QUEUE_ON_RETURN;
9303 SSL* ssl = to_SSL(env, ssl_address, true);
9304 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
9305 if (ssl == nullptr) {
9306 return 0;
9307 }
9308
9309 BIO* internal_bio;
9310 BIO* network_bio;
9311 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
9312 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9313 "BIO_new_bio_pair failed");
9314 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
9315 return 0;
9316 }
9317
9318 SSL_set_bio(ssl, internal_bio, internal_bio);
9319
9320 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
9321 return reinterpret_cast<uintptr_t>(network_bio);
9322 }
9323
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9324 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9325 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9326 CHECK_ERROR_QUEUE_ON_RETURN;
9327 SSL* ssl = to_SSL(env, ssl_address, true);
9328 if (ssl == nullptr) {
9329 return 0;
9330 }
9331 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
9332
9333 if (shc == nullptr) {
9334 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9335 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
9336 ssl);
9337 return 0;
9338 }
9339
9340 AppData* appData = toAppData(ssl);
9341 if (appData == nullptr) {
9342 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9343 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
9344 return 0;
9345 }
9346
9347 errno = 0;
9348
9349 if (!appData->setCallbackState(env, shc, nullptr)) {
9350 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9351 ERR_clear_error();
9352 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9353 return 0;
9354 }
9355
9356 int ret = SSL_do_handshake(ssl);
9357 appData->clearCallbackState();
9358 if (env->ExceptionCheck()) {
9359 // cert_verify_callback threw exception
9360 ERR_clear_error();
9361 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9362 return 0;
9363 }
9364
9365 SslError sslError(ssl, ret);
9366 int code = sslError.get();
9367
9368 if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
9369 // Non-exceptional case.
9370 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
9371 return code;
9372 }
9373
9374 // Exceptional case...
9375 if (ret == 0) {
9376 // TODO(nmittler): Can this happen with memory BIOs?
9377 /*
9378 * Clean error. See SSL_do_handshake(3SSL) man page.
9379 * The other side closed the socket before the handshake could be
9380 * completed, but everything is within the bounds of the TLS protocol.
9381 * We still might want to find out the real reason of the failure.
9382 */
9383 if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
9384 (code == SSL_ERROR_ZERO_RETURN)) {
9385 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9386 } else {
9387 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9388 env, ssl, sslError.release(), "SSL handshake terminated",
9389 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9390 }
9391 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9392 return code;
9393 }
9394
9395 /*
9396 * Unclean error. See SSL_do_handshake(3SSL) man page.
9397 * Translate the error and throw exception. We are sure it is an error
9398 * at this point.
9399 */
9400 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9401 env, ssl, sslError.release(), "SSL handshake aborted",
9402 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9403 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9404 return code;
9405 }
9406
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9407 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9408 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9409 CHECK_ERROR_QUEUE_ON_RETURN;
9410 SSL* ssl = to_SSL(env, ssl_address, false);
9411 if (ssl == nullptr) {
9412 return;
9413 }
9414 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
9415
9416 if (shc == nullptr) {
9417 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9418 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9419 return;
9420 }
9421
9422 AppData* appData = toAppData(ssl);
9423 if (appData != nullptr) {
9424 if (!appData->setCallbackState(env, shc, nullptr)) {
9425 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9426 ERR_clear_error();
9427 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9428 return;
9429 }
9430 int ret = SSL_shutdown(ssl);
9431 appData->clearCallbackState();
9432 // callbacks can happen if server requests renegotiation
9433 if (env->ExceptionCheck()) {
9434 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9435 return;
9436 }
9437 switch (ret) {
9438 case 0:
9439 /*
9440 * Shutdown was not successful (yet), but there also
9441 * is no error. Since we can't know whether the remote
9442 * server is actually still there, and we don't want to
9443 * get stuck forever in a second SSL_shutdown() call, we
9444 * simply return. This is not security a problem as long
9445 * as we close the underlying socket, which we actually
9446 * do, because that's where we are just coming from.
9447 */
9448 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
9449 break;
9450 case 1:
9451 /*
9452 * Shutdown was successful. We can safely return. Hooray!
9453 */
9454 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
9455 break;
9456 default:
9457 /*
9458 * Everything else is a real error condition. We should
9459 * let the Java layer know about this by throwing an
9460 * exception.
9461 */
9462 int sslError = SSL_get_error(ssl, ret);
9463 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
9464 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9465 "SSL shutdown failed");
9466 break;
9467 }
9468 }
9469
9470 ERR_clear_error();
9471 }
9472
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)9473 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
9474 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9475 jint length, jobject shc) {
9476 CHECK_ERROR_QUEUE_ON_RETURN;
9477 SSL* ssl = to_SSL(env, ssl_address, true);
9478 char* destPtr = reinterpret_cast<char*>(address);
9479 if (ssl == nullptr) {
9480 return -1;
9481 }
9482 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
9483 destPtr, length, shc);
9484
9485 if (shc == nullptr) {
9486 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9487 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
9488 ssl);
9489 return -1;
9490 }
9491 AppData* appData = toAppData(ssl);
9492 if (appData == nullptr) {
9493 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9494 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
9495 return -1;
9496 }
9497 if (!appData->setCallbackState(env, shc, nullptr)) {
9498 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9499 ERR_clear_error();
9500 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
9501 return -1;
9502 }
9503
9504 errno = 0;
9505
9506 int result = SSL_read(ssl, destPtr, length);
9507 appData->clearCallbackState();
9508 if (env->ExceptionCheck()) {
9509 // An exception was thrown by one of the callbacks. Just propagate that exception.
9510 ERR_clear_error();
9511 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
9512 return -1;
9513 }
9514
9515 SslError sslError(ssl, result);
9516 switch (sslError.get()) {
9517 case SSL_ERROR_NONE: {
9518 // Successfully read at least one byte. Just return the result.
9519 break;
9520 }
9521 case SSL_ERROR_ZERO_RETURN: {
9522 // A close_notify was received, this stream is finished.
9523 return -SSL_ERROR_ZERO_RETURN;
9524 }
9525 case SSL_ERROR_WANT_READ:
9526 case SSL_ERROR_WANT_WRITE: {
9527 // Return the negative of these values.
9528 result = -sslError.get();
9529 break;
9530 }
9531 case SSL_ERROR_SYSCALL: {
9532 // A problem occurred during a system call, but this is not
9533 // necessarily an error.
9534 if (result == 0) {
9535 // TODO(nmittler): Can this happen with memory BIOs?
9536 // Connection closed without proper shutdown. Tell caller we
9537 // have reached end-of-stream.
9538 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
9539 break;
9540 }
9541
9542 if (errno == EINTR) {
9543 // TODO(nmittler): Can this happen with memory BIOs?
9544 // System call has been interrupted. Simply retry.
9545 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
9546 "Read error");
9547 break;
9548 }
9549
9550 // Note that for all other system call errors we fall through
9551 // to the default case, which results in an Exception.
9552 FALLTHROUGH_INTENDED;
9553 }
9554 default: {
9555 // Everything else is basically an error.
9556 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9557 "Read error");
9558 break;
9559 }
9560 }
9561
9562 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
9563 ssl, destPtr, length, shc, result);
9564 return result;
9565 }
9566
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)9567 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
9568 CONSCRYPT_UNUSED jobject ssl_holder,
9569 jlong bioRef, jlong address, jint len,
9570 jobject shc) {
9571 CHECK_ERROR_QUEUE_ON_RETURN;
9572 SSL* ssl = to_SSL(env, ssl_address, true);
9573 if (ssl == nullptr) {
9574 return -1;
9575 }
9576 if (shc == nullptr) {
9577 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9578 JNI_TRACE(
9579 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
9580 "sslHandshakeCallbacks == null",
9581 ssl);
9582 return -1;
9583 }
9584 BIO* bio = to_SSL_BIO(env, bioRef, true);
9585 if (bio == nullptr) {
9586 return -1;
9587 }
9588 if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
9589 // The network BIO couldn't handle the entire write. Don't write anything, so that we
9590 // only process one packet at a time.
9591 return 0;
9592 }
9593 const char* sourcePtr = reinterpret_cast<const char*>(address);
9594
9595 AppData* appData = toAppData(ssl);
9596 if (appData == nullptr) {
9597 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9598 ERR_clear_error();
9599 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
9600 return -1;
9601 }
9602 if (!appData->setCallbackState(env, shc, nullptr)) {
9603 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9604 ERR_clear_error();
9605 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
9606 return -1;
9607 }
9608
9609 errno = 0;
9610
9611 int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
9612 appData->clearCallbackState();
9613 JNI_TRACE(
9614 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
9615 "ret=%d",
9616 ssl, bio, sourcePtr, len, shc, result);
9617 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
9618 static_cast<size_t>(result));
9619 return result;
9620 }
9621
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)9622 static int NativeCrypto_ENGINE_SSL_write_BIO_heap(JNIEnv* env, jclass, jlong ssl_address,
9623 CONSCRYPT_UNUSED jobject ssl_holder, jlong bioRef,
9624 jbyteArray sourceJava, jint sourceOffset,
9625 jint sourceLength, jobject shc) {
9626 CHECK_ERROR_QUEUE_ON_RETURN;
9627 SSL* ssl = to_SSL(env, ssl_address, true);
9628 if (ssl == nullptr) {
9629 return -1;
9630 }
9631 if (shc == nullptr) {
9632 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9633 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap => sslHandshakeCallbacks == null",
9634 ssl);
9635 return -1;
9636 }
9637 BIO* bio = to_SSL_BIO(env, bioRef, true);
9638 if (bio == nullptr) {
9639 return -1;
9640 }
9641 if (sourceLength < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(sourceLength)) {
9642 // The network BIO couldn't handle the entire write. Don't write anything, so that we
9643 // only process one packet at a time.
9644 return 0;
9645 }
9646 ScopedByteArrayRO source(env, sourceJava);
9647 if (source.get() == nullptr) {
9648 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap => threw exception", ssl);
9649 return -1;
9650 }
9651 if (ARRAY_OFFSET_LENGTH_INVALID(source, sourceOffset, sourceLength)) {
9652 JNI_TRACE(
9653 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap => sourceOffset=%d, "
9654 "sourceLength=%d, size=%zd",
9655 ssl, sourceOffset, sourceLength, source.size());
9656 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
9657 nullptr);
9658 return -1;
9659 }
9660
9661 AppData* appData = toAppData(ssl);
9662 if (appData == nullptr) {
9663 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9664 ERR_clear_error();
9665 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap appData => null", ssl);
9666 return -1;
9667 }
9668 if (!appData->setCallbackState(env, shc, nullptr)) {
9669 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9670 ERR_clear_error();
9671 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap => exception", ssl);
9672 return -1;
9673 }
9674
9675 errno = 0;
9676
9677 int result = BIO_write(bio, reinterpret_cast<const char*>(source.get()) + sourceOffset,
9678 sourceLength);
9679 appData->clearCallbackState();
9680 JNI_TRACE(
9681 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_heap bio=%p source=%p sourceOffset=%d "
9682 "sourceLength=%d shc=%p => ret=%d",
9683 ssl, bio, source.get(), sourceOffset, sourceLength, shc, result);
9684 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(source.get()) + sourceOffset,
9685 static_cast<size_t>(result));
9686 return result;
9687 }
9688
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)9689 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
9690 CONSCRYPT_UNUSED jobject ssl_holder,
9691 jlong bioRef, jlong address, jint outputSize,
9692 jobject shc) {
9693 CHECK_ERROR_QUEUE_ON_RETURN;
9694 SSL* ssl = to_SSL(env, ssl_address, true);
9695 if (ssl == nullptr) {
9696 return -1;
9697 }
9698 if (shc == nullptr) {
9699 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9700 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
9701 ssl);
9702 return -1;
9703 }
9704 BIO* bio = to_SSL_BIO(env, bioRef, true);
9705 if (bio == nullptr) {
9706 return -1;
9707 }
9708 char* destPtr = reinterpret_cast<char*>(address);
9709 if (destPtr == nullptr) {
9710 conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
9711 return -1;
9712 }
9713
9714 AppData* appData = toAppData(ssl);
9715 if (appData == nullptr) {
9716 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9717 ERR_clear_error();
9718 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
9719 return -1;
9720 }
9721 if (!appData->setCallbackState(env, shc, nullptr)) {
9722 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9723 ERR_clear_error();
9724 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
9725 return -1;
9726 }
9727
9728 errno = 0;
9729
9730 int result = BIO_read(bio, destPtr, outputSize);
9731 appData->clearCallbackState();
9732 JNI_TRACE(
9733 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
9734 "=> ret=%d",
9735 ssl, bio, destPtr, outputSize, shc, result);
9736 JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
9737 return result;
9738 }
9739
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)9740 static int NativeCrypto_ENGINE_SSL_read_BIO_heap(JNIEnv* env, jclass, jlong ssl_address,
9741 CONSCRYPT_UNUSED jobject ssl_holder, jlong bioRef,
9742 jbyteArray destJava, jint destOffset,
9743 jint destLength, jobject shc) {
9744 CHECK_ERROR_QUEUE_ON_RETURN;
9745 SSL* ssl = to_SSL(env, ssl_address, true);
9746 if (ssl == nullptr) {
9747 return -1;
9748 }
9749 if (shc == nullptr) {
9750 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9751 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap => sslHandshakeCallbacks == null",
9752 ssl);
9753 return -1;
9754 }
9755 BIO* bio = to_SSL_BIO(env, bioRef, true);
9756 if (bio == nullptr) {
9757 return -1;
9758 }
9759 ScopedByteArrayRW dest(env, destJava);
9760 if (dest.get() == nullptr) {
9761 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap => threw exception", ssl);
9762 return -1;
9763 }
9764 if (ARRAY_OFFSET_LENGTH_INVALID(dest, destOffset, destLength)) {
9765 JNI_TRACE(
9766 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap => destOffset=%d, destLength=%d, "
9767 "size=%zd",
9768 ssl, destOffset, destLength, dest.size());
9769 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
9770 nullptr);
9771 return -1;
9772 }
9773
9774 AppData* appData = toAppData(ssl);
9775 if (appData == nullptr) {
9776 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9777 ERR_clear_error();
9778 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap appData => null", ssl);
9779 return -1;
9780 }
9781 if (!appData->setCallbackState(env, shc, nullptr)) {
9782 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9783 ERR_clear_error();
9784 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap => exception", ssl);
9785 return -1;
9786 }
9787
9788 errno = 0;
9789
9790 int result = BIO_read(bio, reinterpret_cast<char*>(dest.get()) + destOffset, destLength);
9791 appData->clearCallbackState();
9792 JNI_TRACE(
9793 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_heap bio=%p dest=%p destOffset=%d "
9794 "destLength=%d shc=%p => ret=%d",
9795 ssl, bio, dest.get(), destOffset, destLength, shc, result);
9796 JNI_TRACE_PACKET_DATA(ssl, 'I', reinterpret_cast<char*>(dest.get()) + destOffset,
9797 static_cast<size_t>(result));
9798 return result;
9799 }
9800
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9801 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
9802 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9803 CHECK_ERROR_QUEUE_ON_RETURN;
9804 SSL* ssl = to_SSL(env, ssl_address, true);
9805 if (ssl == nullptr) {
9806 return;
9807 }
9808 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
9809 if (shc == nullptr) {
9810 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9811 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
9812 ssl);
9813 return;
9814 }
9815 AppData* appData = toAppData(ssl);
9816 if (appData == nullptr) {
9817 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9818 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
9819 return;
9820 }
9821 if (!appData->setCallbackState(env, shc, nullptr)) {
9822 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9823 ERR_clear_error();
9824 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
9825 return;
9826 }
9827 char c;
9828 int result = SSL_peek(ssl, &c, 1);
9829 appData->clearCallbackState();
9830 if (env->ExceptionCheck()) {
9831 // An exception was thrown by one of the callbacks. Just propagate that exception.
9832 ERR_clear_error();
9833 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
9834 return;
9835 }
9836
9837 SslError sslError(ssl, result);
9838 switch (sslError.get()) {
9839 case SSL_ERROR_NONE:
9840 case SSL_ERROR_ZERO_RETURN:
9841 case SSL_ERROR_WANT_READ:
9842 case SSL_ERROR_WANT_WRITE: {
9843 // The call succeeded, lacked data, or the SSL is closed. All is well.
9844 break;
9845 }
9846 case SSL_ERROR_SYSCALL: {
9847 // A problem occurred during a system call, but this is not
9848 // necessarily an error.
9849 if (result == 0) {
9850 // TODO(nmittler): Can this happen with memory BIOs?
9851 // Connection closed without proper shutdown. Tell caller we
9852 // have reached end-of-stream.
9853 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
9854 break;
9855 }
9856
9857 if (errno == EINTR) {
9858 // TODO(nmittler): Can this happen with memory BIOs?
9859 // System call has been interrupted. Simply retry.
9860 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
9861 "Read error");
9862 break;
9863 }
9864
9865 // Note that for all other system call errors we fall through
9866 // to the default case, which results in an Exception.
9867 FALLTHROUGH_INTENDED;
9868 }
9869 default: {
9870 // Everything else is basically an error.
9871 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9872 "Read error");
9873 break;
9874 }
9875 }
9876
9877 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
9878 }
9879
9880 /**
9881 * OpenSSL write function (2): write into buffer at offset n chunks.
9882 */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)9883 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
9884 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9885 jint len, jobject shc) {
9886 CHECK_ERROR_QUEUE_ON_RETURN;
9887 SSL* ssl = to_SSL(env, ssl_address, true);
9888 const char* sourcePtr = reinterpret_cast<const char*>(address);
9889 if (ssl == nullptr) {
9890 return -1;
9891 }
9892 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
9893 sourcePtr, len, shc);
9894 if (shc == nullptr) {
9895 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9896 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
9897 ssl);
9898 return -1;
9899 }
9900
9901 AppData* appData = toAppData(ssl);
9902 if (appData == nullptr) {
9903 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9904 ERR_clear_error();
9905 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
9906 return -1;
9907 }
9908 if (!appData->setCallbackState(env, shc, nullptr)) {
9909 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9910 ERR_clear_error();
9911 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
9912 return -1;
9913 }
9914
9915 errno = 0;
9916
9917 int result = SSL_write(ssl, sourcePtr, len);
9918 appData->clearCallbackState();
9919 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
9920 ssl, sourcePtr, len, shc, result);
9921 return result;
9922 }
9923
9924 // TESTING METHODS BEGIN
9925
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)9926 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
9927 CHECK_ERROR_QUEUE_ON_RETURN;
9928 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
9929 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
9930
9931 if (outputJavaBytes == nullptr) {
9932 conscrypt::jniutil::throwNullPointerException(env, "output == null");
9933 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
9934 return 0;
9935 }
9936
9937 jsize outputSize = env->GetArrayLength(outputJavaBytes);
9938
9939 std::unique_ptr<unsigned char[]> buffer(
9940 new unsigned char[static_cast<unsigned int>(outputSize)]);
9941 if (buffer.get() == nullptr) {
9942 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
9943 return 0;
9944 }
9945
9946 int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
9947 if (read <= 0) {
9948 conscrypt::jniutil::throwIOException(env, "BIO_read");
9949 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
9950 return 0;
9951 }
9952
9953 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
9954 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
9955 return read;
9956 }
9957
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)9958 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
9959 jint offset, jint length) {
9960 CHECK_ERROR_QUEUE_ON_RETURN;
9961 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
9962 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
9963
9964 if (inputJavaBytes == nullptr) {
9965 conscrypt::jniutil::throwNullPointerException(env, "input == null");
9966 return;
9967 }
9968
9969 int inputSize = env->GetArrayLength(inputJavaBytes);
9970 if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
9971 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
9972 "inputJavaBytes");
9973 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
9974 return;
9975 }
9976
9977 std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
9978 if (buffer.get() == nullptr) {
9979 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
9980 return;
9981 }
9982
9983 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
9984 if (BIO_write(bio, buffer.get(), length) != length) {
9985 ERR_clear_error();
9986 conscrypt::jniutil::throwIOException(env, "BIO_write");
9987 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
9988 return;
9989 }
9990
9991 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
9992 }
9993
9994 /**
9995 * public static native long SSL_clear_mode(long ssl, long mode);
9996 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)9997 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
9998 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
9999 CHECK_ERROR_QUEUE_ON_RETURN;
10000 SSL* ssl = to_SSL(env, ssl_address, true);
10001 // NOLINTNEXTLINE(runtime/int)
10002 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10003 if (ssl == nullptr) {
10004 return 0;
10005 }
10006 jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10007 // NOLINTNEXTLINE(runtime/int)
10008 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10009 return result;
10010 }
10011
10012 /**
10013 * public static native long SSL_get_mode(long ssl);
10014 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10015 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10016 CONSCRYPT_UNUSED jobject ssl_holder) {
10017 CHECK_ERROR_QUEUE_ON_RETURN;
10018 SSL* ssl = to_SSL(env, ssl_address, true);
10019 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10020 if (ssl == nullptr) {
10021 return 0;
10022 }
10023 jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
10024 // NOLINTNEXTLINE(runtime/int)
10025 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
10026 return mode;
10027 }
10028
10029 /**
10030 * public static native long SSL_get_options(long ssl);
10031 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10032 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
10033 CONSCRYPT_UNUSED jobject ssl_holder) {
10034 CHECK_ERROR_QUEUE_ON_RETURN;
10035 SSL* ssl = to_SSL(env, ssl_address, true);
10036 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
10037 if (ssl == nullptr) {
10038 return 0;
10039 }
10040 jlong options = static_cast<jlong>(SSL_get_options(ssl));
10041 // NOLINTNEXTLINE(runtime/int)
10042 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
10043 return options;
10044 }
10045
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10046 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
10047 CONSCRYPT_UNUSED jobject ssl_holder) {
10048 CHECK_ERROR_QUEUE_ON_RETURN;
10049 SSL* ssl = to_SSL(env, ssl_address, true);
10050 if (ssl == nullptr) {
10051 return 0;
10052 }
10053 return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
10054 }
10055
10056 // TESTING METHODS END
10057
10058 #define CONSCRYPT_NATIVE_METHOD(functionName, signature) \
10059 { \
10060 /* NOLINTNEXTLINE */ \
10061 (char*)#functionName, (char*)(signature), \
10062 reinterpret_cast<void*>(NativeCrypto_##functionName) \
10063 }
10064
10065 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10066 #define SSL_CALLBACKS \
10067 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
10068 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10069 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
10070 #define REF_EVP_CIPHER_CTX \
10071 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
10072 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
10073 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
10074 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
10075 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
10076 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
10077 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
10078 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
10079 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
10080 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
10081 static JNINativeMethod sNativeCryptoMethods[] = {
10082 CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
10083 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
10084 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
10085 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10086 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10087 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10088 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
10089 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10090 CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
10091 CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
10092 CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
10093 CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
10094 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
10095 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
10096 CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10097 CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
10098 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
10099 CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
10100 CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
10101 CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10102 CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10103 CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10104 CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10105 CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10106 CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
10107 CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
10108 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
10109 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
10110 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10111 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10112 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10113 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10114 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
10115 CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
10116 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10117 CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
10118 CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
10119 CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
10120 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10121 CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
10122 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10123 CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10124 CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
10125 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10126 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10127 CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
10128 CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
10129 CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10130 CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
10131 CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
10132 CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
10133 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
10134 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
10135 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
10136 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
10137 CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
10138 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10139 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10140 CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
10141 CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10142 CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
10143 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10144 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10145 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10146 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
10147 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10148 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10149 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10150 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
10151 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
10152 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10153 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
10154 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10155 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
10156 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
10157 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
10158 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
10159 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
10160 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
10161 CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
10162 CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10163 CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10164 CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
10165 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
10166 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
10167 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10168 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
10169 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
10170 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10171 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
10172 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
10173 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
10174 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
10175 CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
10176 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
10177 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
10178 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
10179 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
10180 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
10181 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
10182 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
10183 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
10184 CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
10185 CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
10186 CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
10187 CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
10188 CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
10189 CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
10190 CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10191 CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
10192 CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
10193 CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
10194 CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
10195 CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
10196 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
10197 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
10198 CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
10199 CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
10200 CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
10201 CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
10202 CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
10203 CONSCRYPT_NATIVE_METHOD(X509_dup, "(J" REF_X509 ")J"),
10204 CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
10205 CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
10206 CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
10207 CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
10208 CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
10209 CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10210 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10211 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
10212 CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
10213 CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
10214 CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
10215 CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
10216 CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
10217 CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
10218 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
10219 CONSCRYPT_NATIVE_METHOD(X509_delete_ext, "(J" REF_X509 "Ljava/lang/String;)V"),
10220 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
10221 CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
10222 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
10223 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
10224 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10225 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
10226 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
10227 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
10228 CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
10229 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
10230 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10231 CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
10232 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
10233 CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
10234 CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
10235 CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
10236 CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
10237 CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
10238 CONSCRYPT_NATIVE_METHOD(get_X509_cert_info_enc, "(J" REF_X509 ")[B"),
10239 CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
10240 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
10241 CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
10242 CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
10243 CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
10244 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
10245 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
10246 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
10247 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
10248 CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
10249 CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
10250 CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
10251 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
10252 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
10253 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
10254 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
10255 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
10256 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10257 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
10258 CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
10259 CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
10260 CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10261 CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
10262 CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
10263 CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
10264 CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
10265 CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
10266 CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
10267 CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
10268 CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
10269 CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
10270 CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
10271 CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
10272 CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
10273 CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
10274 CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
10275 CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
10276 CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
10277 CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
10278 CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
10279 CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
10280 CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
10281 CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
10282 CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
10283 CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
10284 CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
10285 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
10286 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
10287 CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
10288 CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
10289 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
10290 CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
10291 CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
10292 CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
10293 CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
10294 CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
10295 CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
10296 CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
10297 CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
10298 CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
10299 CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
10300 CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
10301 CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
10302 CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
10303 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
10304 CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
10305 CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
10306 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
10307 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
10308 CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
10309 CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
10310 CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
10311 CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
10312 CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
10313 CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
10314 CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
10315 CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
10316 CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
10317 CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
10318 CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
10319 CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
10320 CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
10321 CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
10322 CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
10323 CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
10324 CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
10325 CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
10326 CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
10327 CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
10328 CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
10329 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
10330 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
10331 CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
10332 CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
10333 CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
10334 CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
10335 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
10336 CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
10337 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10338 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10339 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
10340 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
10341 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
10342 CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
10343 CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
10344 CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
10345 CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
10346 CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
10347 CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
10348 CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
10349 CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
10350 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
10351 CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
10352 CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
10353 CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
10354 CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
10355 CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
10356 CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
10357 CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
10358 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
10359 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10360 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10361 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10362 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10363 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_heap, "(J" REF_SSL "J[BII" SSL_CALLBACKS ")I"),
10364 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_heap, "(J" REF_SSL "J[BII" SSL_CALLBACKS ")I"),
10365 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
10366 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
10367
10368 // Used for testing only.
10369 CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
10370 CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
10371 CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
10372 CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
10373 CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
10374 CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
10375 };
10376
registerNativeMethods(JNIEnv * env)10377 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
10378 conscrypt::jniutil::jniRegisterNativeMethods(
10379 env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
10380 NELEM(sNativeCryptoMethods));
10381 }
10382
10383 /* Local Variables: */
10384 /* mode: c++ */
10385 /* tab-width: 4 */
10386 /* indent-tabs-mode: nil */
10387 /* c-basic-offset: 4 */
10388 /* End: */
10389 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
10390