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