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/cmac.h>
41 #include <openssl/crypto.h>
42 #include <openssl/curve25519.h>
43 #include <openssl/engine.h>
44 #include <openssl/err.h>
45 #include <openssl/evp.h>
46 #include <openssl/hmac.h>
47 #include <openssl/pkcs7.h>
48 #include <openssl/pkcs8.h>
49 #include <openssl/rand.h>
50 #include <openssl/rsa.h>
51 #include <openssl/ssl.h>
52 #include <openssl/x509v3.h>
53
54 #include <limits>
55 #include <type_traits>
56 #include <vector>
57
58 using conscrypt::AppData;
59 using conscrypt::BioInputStream;
60 using conscrypt::BioOutputStream;
61 using conscrypt::BioStream;
62 using conscrypt::CompatibilityCloseMonitor;
63 using conscrypt::NativeCrypto;
64 using conscrypt::SslError;
65
66 /**
67 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
68 * If this function returns nullptr and <code>throwIfNull</code> is
69 * passed as <code>true</code>, then this function will call
70 * <code>throwSSLExceptionStr</code> before returning, so in this case of
71 * nullptr, a caller of this function should simply return and allow JNI
72 * to do its thing.
73 *
74 * @param env the JNI environment
75 * @param ssl_address; the ssl_address pointer as an integer
76 * @param throwIfNull whether to throw if the SSL pointer is nullptr
77 * @returns the pointer, which may be nullptr
78 */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)79 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
80 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
81 if ((ssl_ctx == nullptr) && throwIfNull) {
82 JNI_TRACE("ssl_ctx == null");
83 conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
84 }
85 return ssl_ctx;
86 }
87
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)88 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
89 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
90 if ((ssl == nullptr) && throwIfNull) {
91 JNI_TRACE("ssl == null");
92 conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
93 }
94 return ssl;
95 }
96
to_BIO(JNIEnv * env,jlong bio_address)97 static BIO* to_BIO(JNIEnv* env, jlong bio_address) {
98 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
99 if (bio == nullptr) {
100 JNI_TRACE("bio == null");
101 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
102 }
103 return bio;
104 }
105
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)106 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
107 SSL_SESSION* ssl_session =
108 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
109 if ((ssl_session == nullptr) && throwIfNull) {
110 JNI_TRACE("ssl_session == null");
111 conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
112 }
113 return ssl_session;
114 }
115
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)116 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
117 SSL_CIPHER* ssl_cipher =
118 reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
119 if ((ssl_cipher == nullptr) && throwIfNull) {
120 JNI_TRACE("ssl_cipher == null");
121 conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
122 }
123 return ssl_cipher;
124 }
125
126 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)127 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
128 if (contextObject == nullptr) {
129 JNI_TRACE("contextObject == null");
130 conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
131 return nullptr;
132 }
133 T* ref = reinterpret_cast<T*>(
134 env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
135 if (ref == nullptr) {
136 JNI_TRACE("ref == null");
137 conscrypt::jniutil::throwNullPointerException(env, "ref == null");
138 return nullptr;
139 }
140 return ref;
141 }
142
143 /**
144 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
145 * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
146 * return value is false, there is a pending exception.
147 */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)148 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
149 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
150 if (dest == nullptr) {
151 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
152 conscrypt::jniutil::throwNullPointerException(env, "dest == null");
153 return false;
154 }
155 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
156
157 ScopedByteArrayRO sourceBytes(env, source);
158 if (sourceBytes.get() == nullptr) {
159 JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
160 return false;
161 }
162 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
163 size_t tmpSize = sourceBytes.size();
164
165 /* if the array is empty, it is zero. */
166 if (tmpSize == 0) {
167 if (*dest == nullptr) {
168 *dest = BN_new();
169 }
170 BN_zero(*dest);
171 return true;
172 }
173
174 std::unique_ptr<unsigned char[]> twosComplement;
175 bool negative = (tmp[0] & 0x80) != 0;
176 if (negative) {
177 // Need to convert to two's complement.
178 twosComplement.reset(new unsigned char[tmpSize]);
179 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
180 memcpy(twosBytes, tmp, tmpSize);
181 tmp = twosBytes;
182
183 bool carry = true;
184 for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
185 twosBytes[i] ^= 0xFF;
186 if (carry) {
187 carry = (++twosBytes[i]) == 0;
188 }
189 }
190 }
191 BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
192 if (ret == nullptr) {
193 conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
194 ERR_clear_error();
195 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
196 return false;
197 }
198 BN_set_negative(ret, negative ? 1 : 0);
199
200 *dest = ret;
201 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
202 return true;
203 }
204
205 /**
206 * arrayToBignumSize sets |*out_size| to the size of the big-endian number
207 * contained in |source|. It returns true on success and sets an exception and
208 * returns false otherwise.
209 */
arrayToBignumSize(JNIEnv * env,jbyteArray source,size_t * out_size)210 static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
211 JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
212
213 ScopedByteArrayRO sourceBytes(env, source);
214 if (sourceBytes.get() == nullptr) {
215 JNI_TRACE("arrayToBignum(%p, %p) => null", source, out_size);
216 return false;
217 }
218 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
219 size_t tmpSize = sourceBytes.size();
220
221 if (tmpSize == 0) {
222 *out_size = 0;
223 return true;
224 }
225
226 if ((tmp[0] & 0x80) != 0) {
227 // Negative numbers are invalid.
228 conscrypt::jniutil::throwRuntimeException(env, "Negative number");
229 return false;
230 }
231
232 while (tmpSize > 0 && tmp[0] == 0) {
233 tmp++;
234 tmpSize--;
235 }
236
237 *out_size = tmpSize;
238 return true;
239 }
240
241 /**
242 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
243 */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)244 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
245 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
246
247 if (source == nullptr) {
248 conscrypt::jniutil::throwNullPointerException(env, sourceName);
249 return nullptr;
250 }
251
252 size_t numBytes = BN_num_bytes(source) + 1;
253 jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
254 ScopedByteArrayRW bytes(env, javaBytes);
255 if (bytes.get() == nullptr) {
256 JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
257 return nullptr;
258 }
259
260 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
261 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
262 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
263 return nullptr;
264 }
265
266 // Set the sign and convert to two's complement if necessary for the Java code.
267 if (BN_is_negative(source)) {
268 bool carry = true;
269 for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
270 tmp[i] ^= 0xFF;
271 if (carry) {
272 carry = (++tmp[i]) == 0;
273 }
274 }
275 *tmp |= 0x80;
276 } else {
277 *tmp = 0x00;
278 }
279
280 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
281 return javaBytes;
282 }
283
284 /**
285 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
286 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
287 * from the OpenSSL ASN.1 API. Note i2d_func may take a const parameter, so we
288 * use a separate type parameter.
289 *
290 * TODO(https://crbug.com/boringssl/407): When all BoringSSL i2d functions are
291 * const, switch back to a single template parameter.
292 */
293 template <typename T, typename U>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(U *,unsigned char **))294 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(U*, unsigned char**)) {
295 // T and U should be the same type, but may differ in const.
296 static_assert(std::is_same<typename std::remove_const<T>::type,
297 typename std::remove_const<U>::type>::value,
298 "obj and i2d_func have incompatible types");
299
300 if (obj == nullptr) {
301 conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
302 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
303 return nullptr;
304 }
305
306 int derLen = i2d_func(obj, nullptr);
307 if (derLen < 0) {
308 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
309 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
310 return nullptr;
311 }
312
313 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
314 if (byteArray.get() == nullptr) {
315 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
316 return nullptr;
317 }
318
319 ScopedByteArrayRW bytes(env, byteArray.get());
320 if (bytes.get() == nullptr) {
321 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
322 return nullptr;
323 }
324
325 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
326 int ret = i2d_func(obj, &p);
327 if (ret < 0) {
328 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
329 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
330 return nullptr;
331 }
332
333 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
334 return byteArray.release();
335 }
336
337 /**
338 * Finishes a pending CBB and returns a jbyteArray with the contents.
339 */
CBBToByteArray(JNIEnv * env,CBB * cbb)340 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
341 uint8_t* data;
342 size_t len;
343 if (!CBB_finish(cbb, &data, &len)) {
344 conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
345 ERR_clear_error();
346 JNI_TRACE("creating byte array failed");
347 return nullptr;
348 }
349 bssl::UniquePtr<uint8_t> free_data(data);
350
351 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
352 if (byteArray.get() == nullptr) {
353 JNI_TRACE("creating byte array failed");
354 return nullptr;
355 }
356
357 ScopedByteArrayRW bytes(env, byteArray.get());
358 if (bytes.get() == nullptr) {
359 JNI_TRACE("using byte array failed");
360 return nullptr;
361 }
362
363 memcpy(bytes.get(), data, len);
364 return byteArray.release();
365 }
366
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)367 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
368 if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
369 JNI_TRACE("buffer too large");
370 conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
371 return nullptr;
372 }
373
374 int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
375 jbyteArray ret = env->NewByteArray(length);
376 if (ret == nullptr) {
377 JNI_TRACE("allocating byte array failed");
378 return nullptr;
379 }
380
381 env->SetByteArrayRegion(ret, 0, length,
382 reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
383 return ret;
384 }
385
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)386 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
387 CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
388 if (array == nullptr) {
389 JNI_TRACE("array was null");
390 conscrypt::jniutil::throwNullPointerException(env, "array == null");
391 return nullptr;
392 }
393
394 ScopedByteArrayRO arrayRo(env, array);
395 if (arrayRo.get() == nullptr) {
396 JNI_TRACE("failed to get bytes");
397 return nullptr;
398 }
399
400 bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
401 reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
402 if (!ret) {
403 JNI_TRACE("failed to allocate CRYPTO_BUFFER");
404 conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
405 return nullptr;
406 }
407
408 return ret;
409 }
410
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)411 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
412 const STACK_OF(CRYPTO_BUFFER)* buffers) {
413 size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
414 if (numBuffers > INT_MAX) {
415 JNI_TRACE("too many buffers");
416 conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
417 return nullptr;
418 }
419
420 ScopedLocalRef<jobjectArray> array(
421 env, env->NewObjectArray(static_cast<int>(numBuffers),
422 conscrypt::jniutil::byteArrayClass, nullptr));
423 if (array.get() == nullptr) {
424 JNI_TRACE("failed to allocate array");
425 return nullptr;
426 }
427
428 for (size_t i = 0; i < numBuffers; ++i) {
429 CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
430 ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
431 if (bArray.get() == nullptr) {
432 return nullptr;
433 }
434 env->SetObjectArrayElement(array.get(), i, bArray.get());
435 }
436
437 return array.release();
438 }
439
440 /**
441 * Converts ASN.1 BIT STRING to a jbooleanArray.
442 */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)443 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
444 int size = ASN1_STRING_length(bitStr) * 8;
445 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
446 size -= bitStr->flags & 0x07;
447 }
448
449 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
450 if (bitsRef.get() == nullptr) {
451 return nullptr;
452 }
453
454 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
455 for (size_t i = 0; i < bitsArray.size(); i++) {
456 bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
457 }
458
459 return bitsRef.release();
460 }
461
bio_stream_create(BIO * b)462 static int bio_stream_create(BIO* b) {
463 b->init = 1;
464 b->num = 0;
465 b->ptr = nullptr;
466 b->flags = 0;
467 return 1;
468 }
469
bio_stream_destroy(BIO * b)470 static int bio_stream_destroy(BIO* b) {
471 if (b == nullptr) {
472 return 0;
473 }
474
475 if (b->ptr != nullptr) {
476 delete static_cast<BioStream*>(b->ptr);
477 b->ptr = nullptr;
478 }
479
480 b->init = 0;
481 b->flags = 0;
482 return 1;
483 }
484
bio_stream_read(BIO * b,char * buf,int len)485 static int bio_stream_read(BIO* b, char* buf, int len) {
486 BIO_clear_retry_flags(b);
487 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
488 int ret = stream->read(buf, len);
489 if (ret == 0) {
490 if (stream->isFinite()) {
491 return 0;
492 }
493 // If the BioInputStream is not finite then EOF doesn't mean that
494 // there's nothing more coming.
495 BIO_set_retry_read(b);
496 return -1;
497 }
498 return ret;
499 }
500
bio_stream_write(BIO * b,const char * buf,int len)501 static int bio_stream_write(BIO* b, const char* buf, int len) {
502 BIO_clear_retry_flags(b);
503 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
504 return stream->write(buf, len);
505 }
506
bio_stream_puts(BIO * b,const char * buf)507 static int bio_stream_puts(BIO* b, const char* buf) {
508 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
509 return stream->write(buf, static_cast<int>(strlen(buf)));
510 }
511
bio_stream_gets(BIO * b,char * buf,int len)512 static int bio_stream_gets(BIO* b, char* buf, int len) {
513 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
514 return stream->gets(buf, len);
515 }
516
bio_stream_assign(BIO * b,BioStream * stream)517 static void bio_stream_assign(BIO* b, BioStream* stream) {
518 b->ptr = static_cast<void*>(stream);
519 }
520
521 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)522 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
523 BioStream* stream = static_cast<BioStream*>(b->ptr);
524
525 switch (cmd) {
526 case BIO_CTRL_EOF:
527 return stream->isEof() ? 1 : 0;
528 case BIO_CTRL_FLUSH:
529 return stream->flush();
530 default:
531 return 0;
532 }
533 }
534
535 static BIO_METHOD stream_bio_method = {
536 (100 | 0x0400), /* source/sink BIO */
537 "InputStream/OutputStream BIO",
538 bio_stream_write, /* bio_write */
539 bio_stream_read, /* bio_read */
540 bio_stream_puts, /* bio_puts */
541 bio_stream_gets, /* bio_gets */
542 bio_stream_ctrl, /* bio_ctrl */
543 bio_stream_create, /* bio_create */
544 bio_stream_destroy, /* bio_free */
545 nullptr, /* no bio_callback_ctrl */
546 };
547
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)548 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
549 size_t message_len) {
550 JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
551 if (message_len > std::numeric_limits<jsize>::max()) {
552 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
553 return nullptr;
554 }
555 ScopedLocalRef<jbyteArray> messageArray(env,
556 env->NewByteArray(static_cast<jsize>(message_len)));
557 if (env->ExceptionCheck()) {
558 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
559 return nullptr;
560 }
561
562 {
563 ScopedByteArrayRW messageBytes(env, messageArray.get());
564 if (messageBytes.get() == nullptr) {
565 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
566 return nullptr;
567 }
568
569 memcpy(messageBytes.get(), message, message_len);
570 }
571
572 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
573 conscrypt::jniutil::cryptoUpcallsClass,
574 conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod, privateKey, messageArray.get()));
575 }
576
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)577 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
578 const char* message, size_t message_len) {
579 if (message_len > std::numeric_limits<jsize>::max()) {
580 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
581 return nullptr;
582 }
583 ScopedLocalRef<jbyteArray> messageArray(env,
584 env->NewByteArray(static_cast<jsize>(message_len)));
585 if (env->ExceptionCheck()) {
586 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
587 return nullptr;
588 }
589
590 {
591 ScopedByteArrayRW messageBytes(env, messageArray.get());
592 if (messageBytes.get() == nullptr) {
593 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
594 return nullptr;
595 }
596
597 memcpy(messageBytes.get(), message, message_len);
598 }
599
600 return reinterpret_cast<jbyteArray>(
601 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
602 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(
617 env, 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 return reinterpret_cast<jbyteArray>(
634 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
635 conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
636 privateKey, padding, ciphertextArray.get()));
637 }
638
639 // *********************************************
640 // From keystore_openssl.cpp in Chromium source.
641 // *********************************************
642
643 namespace {
644
645 ENGINE* g_engine;
646 int g_rsa_exdata_index;
647 int g_ecdsa_exdata_index;
648 RSA_METHOD g_rsa_method;
649 ECDSA_METHOD g_ecdsa_method;
650 std::once_flag g_engine_once;
651
652 void init_engine_globals();
653
ensure_engine_globals()654 void ensure_engine_globals() {
655 std::call_once(g_engine_once, init_engine_globals);
656 }
657
658 // KeyExData contains the data that is contained in the EX_DATA of the RSA
659 // and ECDSA objects that are created to wrap Android system keys.
660 struct KeyExData {
661 // private_key contains a reference to a Java, private-key object.
662 jobject private_key;
663 // cached_size contains the "size" of the key. This is the size of the
664 // modulus (in bytes) for RSA, or the group order size for ECDSA. This
665 // avoids calling into Java to calculate the size.
666 size_t cached_size;
667 };
668
669 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
670 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)671 int ExDataDup(CRYPTO_EX_DATA* /* to */,
672 const CRYPTO_EX_DATA* /* from */,
673 void** /* from_d */,
674 int /* index */,
675 long /* argl */ /* NOLINT(runtime/int) */,
676 void* /* argp */) {
677 return 0;
678 }
679
680 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)681 void ExDataFree(void* /* parent */,
682 void* ptr,
683 CRYPTO_EX_DATA* /* ad */,
684 int /* index */,
685 long /* argl */ /* NOLINT(runtime/int) */,
686 void* /* argp */) {
687 // Ensure the global JNI reference created with this wrapper is
688 // properly destroyed with it.
689 KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
690 if (ex_data != nullptr) {
691 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
692 env->DeleteGlobalRef(ex_data->private_key);
693 delete ex_data;
694 }
695 }
696
RsaGetExData(const RSA * rsa)697 KeyExData* RsaGetExData(const RSA* rsa) {
698 return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
699 }
700
RsaMethodSize(const RSA * rsa)701 size_t RsaMethodSize(const RSA* rsa) {
702 const KeyExData* ex_data = RsaGetExData(rsa);
703 return ex_data->cached_size;
704 }
705
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)706 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
707 size_t in_len, int padding) {
708 if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
709 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
710 return 0;
711 }
712
713 // Retrieve private key JNI reference.
714 const KeyExData* ex_data = RsaGetExData(rsa);
715 if (!ex_data || !ex_data->private_key) {
716 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
717 return 0;
718 }
719
720 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
721 if (env == nullptr) {
722 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
723 return 0;
724 }
725
726 // For RSA keys, this function behaves as RSA_private_encrypt with
727 // the specified padding.
728 ScopedLocalRef<jbyteArray> signature(
729 env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
730 reinterpret_cast<const char*>(in), in_len));
731
732 if (signature.get() == nullptr) {
733 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
734 return 0;
735 }
736
737 ScopedByteArrayRO result(env, signature.get());
738
739 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
740 if (result.size() > expected_size) {
741 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
742 return 0;
743 }
744
745 if (max_out < expected_size) {
746 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
747 return 0;
748 }
749
750 // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
751 // should pad with leading 0s, but if it doesn't, pad the result.
752 size_t zero_pad = expected_size - result.size();
753 memset(out, 0, zero_pad);
754 memcpy(out + zero_pad, &result[0], result.size());
755 *out_len = expected_size;
756
757 return 1;
758 }
759
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)760 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
761 size_t in_len, int padding) {
762 // Retrieve private key JNI reference.
763 const KeyExData* ex_data = RsaGetExData(rsa);
764 if (!ex_data || !ex_data->private_key) {
765 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
766 return 0;
767 }
768
769 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
770 if (env == nullptr) {
771 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
772 return 0;
773 }
774
775 // This function behaves as RSA_private_decrypt.
776 ScopedLocalRef<jbyteArray> cleartext(
777 env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
778 reinterpret_cast<const char*>(in), in_len));
779 if (cleartext.get() == nullptr) {
780 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
781 return 0;
782 }
783
784 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
785
786 if (max_out < cleartextBytes.size()) {
787 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
788 return 0;
789 }
790
791 // Copy result to OpenSSL-provided buffer.
792 memcpy(out, cleartextBytes.get(), cleartextBytes.size());
793 *out_len = cleartextBytes.size();
794
795 return 1;
796 }
797
798 // Custom ECDSA_METHOD that uses the platform APIs.
799 // Note that for now, only signing through ECDSA_sign() is really supported.
800 // all other method pointers are either stubs returning errors, or no-ops.
801
EcKeyGetKey(const EC_KEY * ec_key)802 jobject EcKeyGetKey(const EC_KEY* ec_key) {
803 KeyExData* ex_data =
804 reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
805 return ex_data->private_key;
806 }
807
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)808 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
809 EC_KEY* ec_key) {
810 // Retrieve private key JNI reference.
811 jobject private_key = EcKeyGetKey(ec_key);
812 if (!private_key) {
813 CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
814 return 0;
815 }
816
817 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
818 if (env == nullptr) {
819 return 0;
820 }
821
822 // Sign message with it through JNI.
823 ScopedLocalRef<jbyteArray> signature(
824 env, ecSignDigestWithPrivateKey(env, private_key,
825 reinterpret_cast<const char*>(digest), digest_len));
826 if (signature.get() == nullptr) {
827 CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
828 return 0;
829 }
830
831 ScopedByteArrayRO signatureBytes(env, signature.get());
832 // Note: With ECDSA, the actual signature may be smaller than
833 // ECDSA_size().
834 size_t max_expected_size = ECDSA_size(ec_key);
835 if (signatureBytes.size() > max_expected_size) {
836 CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
837 signatureBytes.size(), max_expected_size);
838 return 0;
839 }
840
841 memcpy(sig, signatureBytes.get(), signatureBytes.size());
842 *sig_len = static_cast<unsigned int>(signatureBytes.size());
843 return 1;
844 }
845
init_engine_globals()846 void init_engine_globals() {
847 g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
848 nullptr /* new_func */, ExDataDup, ExDataFree);
849 g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
850 nullptr /* new_func */, ExDataDup, ExDataFree);
851
852 g_rsa_method.common.is_static = 1;
853 g_rsa_method.size = RsaMethodSize;
854 g_rsa_method.sign_raw = RsaMethodSignRaw;
855 g_rsa_method.decrypt = RsaMethodDecrypt;
856 g_rsa_method.flags = RSA_FLAG_OPAQUE;
857
858 g_ecdsa_method.common.is_static = 1;
859 g_ecdsa_method.sign = EcdsaMethodSign;
860 g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
861
862 g_engine = ENGINE_new();
863 ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
864 ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
865 }
866
867 } // anonymous namespace
868
869 #define THROW_SSLEXCEPTION (-2)
870 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
871 #define THROWN_EXCEPTION (-4)
872
873 /**
874 * Initialization phase for every OpenSSL job: Loads the Error strings, the
875 * crypto algorithms and reset the OpenSSL library
876 */
NativeCrypto_clinit(JNIEnv *,jclass)877 static void NativeCrypto_clinit(JNIEnv*, jclass) {
878 CRYPTO_library_init();
879 }
880
881 /**
882 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
883 */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)884 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
885 jbyteArray d, jbyteArray p, jbyteArray q,
886 jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
887 CHECK_ERROR_QUEUE_ON_RETURN;
888 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,
889 p, q, dmp1, dmq1, iqmp);
890
891 bssl::UniquePtr<RSA> rsa(RSA_new());
892 if (rsa.get() == nullptr) {
893 conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
894 return 0;
895 }
896
897 if (e == nullptr && d == nullptr) {
898 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
899 "e == null && d == null");
900 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
901 return 0;
902 }
903
904 if (!arrayToBignum(env, n, &rsa->n)) {
905 return 0;
906 }
907
908 if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
909 return 0;
910 }
911
912 if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
913 return 0;
914 }
915
916 if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
917 return 0;
918 }
919
920 if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
921 return 0;
922 }
923
924 if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
925 return 0;
926 }
927
928 if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
929 return 0;
930 }
931
932 if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
933 return 0;
934 }
935
936 if (conscrypt::trace::kWithJniTrace) {
937 if (p != nullptr && q != nullptr) {
938 int check = RSA_check_key(rsa.get());
939 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
940 }
941 }
942
943 if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
944 conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
945 return 0;
946 }
947
948 /*
949 * If the private exponent is available, there is the potential to do signing
950 * operations. However, we can only do blinding if the public exponent is also
951 * available. Disable blinding if the public exponent isn't available.
952 *
953 * TODO[kroot]: We should try to recover the public exponent by trying
954 * some common ones such 3, 17, or 65537.
955 */
956 if (rsa->d != nullptr && rsa->e == nullptr) {
957 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
958 rsa->flags |= RSA_FLAG_NO_BLINDING;
959 }
960
961 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
962 if (pkey.get() == nullptr) {
963 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
964 return 0;
965 }
966 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
967 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
968 ERR_clear_error();
969 return 0;
970 }
971 OWNERSHIP_TRANSFERRED(rsa);
972 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
973 e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
974 return reinterpret_cast<uintptr_t>(pkey.release());
975 }
976
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)977 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
978 jobject pubkeyRef, jbyteArray keyJavaBytes) {
979 CHECK_ERROR_QUEUE_ON_RETURN;
980 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
981 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
982 if (group == nullptr) {
983 return 0;
984 }
985 const EC_POINT* pubkey =
986 pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
987 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
988
989 bssl::UniquePtr<BIGNUM> key(nullptr);
990 if (keyJavaBytes != nullptr) {
991 BIGNUM* keyRef = nullptr;
992 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
993 return 0;
994 }
995 key.reset(keyRef);
996 }
997
998 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
999 if (eckey.get() == nullptr) {
1000 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1001 return 0;
1002 }
1003
1004 if (EC_KEY_set_group(eckey.get(), group) != 1) {
1005 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1006 keyJavaBytes);
1007 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1008 return 0;
1009 }
1010
1011 if (pubkey != nullptr) {
1012 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1013 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1014 pubkey, keyJavaBytes);
1015 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1016 return 0;
1017 }
1018 }
1019
1020 if (key.get() != nullptr) {
1021 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1022 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1023 pubkey, keyJavaBytes);
1024 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1025 return 0;
1026 }
1027 if (pubkey == nullptr) {
1028 bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1029 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1030 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1031 pubkey, keyJavaBytes);
1032 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1033 return 0;
1034 }
1035 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1036 }
1037 }
1038
1039 if (!EC_KEY_check_key(eckey.get())) {
1040 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1041 keyJavaBytes);
1042 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1043 return 0;
1044 }
1045
1046 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1047 if (pkey.get() == nullptr) {
1048 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1049 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1050 return 0;
1051 }
1052 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1053 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1054 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1055 ERR_clear_error();
1056 return 0;
1057 }
1058 OWNERSHIP_TRANSFERRED(eckey);
1059
1060 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1061 return reinterpret_cast<uintptr_t>(pkey.release());
1062 }
1063
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1064 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1065 CHECK_ERROR_QUEUE_ON_RETURN;
1066 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1067 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1068
1069 if (pkey == nullptr) {
1070 return -1;
1071 }
1072
1073 int result = EVP_PKEY_id(pkey);
1074 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1075 return result;
1076 }
1077
1078 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1079
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1080 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1081 const char* debug_name) {
1082 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1083 JNI_TRACE("%s(%p)", debug_name, pkey);
1084
1085 if (pkey == nullptr) {
1086 return nullptr;
1087 }
1088
1089 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1090 if (buffer.get() == nullptr) {
1091 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1092 return nullptr;
1093 }
1094
1095 if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1096 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1097 return nullptr;
1098 }
1099 // Null terminate this
1100 BIO_write(buffer.get(), "\0", 1);
1101
1102 char* tmp;
1103 BIO_get_mem_data(buffer.get(), &tmp);
1104 jstring description = env->NewStringUTF(tmp);
1105
1106 JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1107 return description;
1108 }
1109
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1110 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1111 CHECK_ERROR_QUEUE_ON_RETURN;
1112 return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1113 }
1114
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1115 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1116 CHECK_ERROR_QUEUE_ON_RETURN;
1117 return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1118 }
1119
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1120 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1121 CHECK_ERROR_QUEUE_ON_RETURN;
1122 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1123 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1124
1125 if (pkey != nullptr) {
1126 EVP_PKEY_free(pkey);
1127 }
1128 }
1129
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1130 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1131 CHECK_ERROR_QUEUE_ON_RETURN;
1132 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1133 EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1134 if (pkey1 == nullptr) {
1135 JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1136 return 0;
1137 }
1138 EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1139 if (pkey2 == nullptr) {
1140 JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1141 return 0;
1142 }
1143 JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1144
1145 int result = EVP_PKEY_cmp(pkey1, pkey2);
1146 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1147 return result;
1148 }
1149
1150 /*
1151 * static native byte[] EVP_marshal_private_key(long)
1152 */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1153 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1154 CHECK_ERROR_QUEUE_ON_RETURN;
1155 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1156 JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1157
1158 if (pkey == nullptr) {
1159 return nullptr;
1160 }
1161
1162 bssl::ScopedCBB cbb;
1163 if (!CBB_init(cbb.get(), 64)) {
1164 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1165 JNI_TRACE("CBB_init failed");
1166 return nullptr;
1167 }
1168
1169 if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1170 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1171 JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1172 return nullptr;
1173 }
1174
1175 return CBBToByteArray(env, cbb.get());
1176 }
1177
1178 /*
1179 * static native long EVP_parse_private_key(byte[])
1180 */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1181 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1182 CHECK_ERROR_QUEUE_ON_RETURN;
1183 JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1184
1185 ScopedByteArrayRO bytes(env, keyJavaBytes);
1186 if (bytes.get() == nullptr) {
1187 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1188 return 0;
1189 }
1190
1191 CBS cbs;
1192 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1193 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1194 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1195 // allow parsing keys from buffers that are larger than the contained key structure
1196 // so we do the same for compatibility.
1197 if (!pkey) {
1198 conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1199 ERR_clear_error();
1200 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1201 return 0;
1202 }
1203
1204 JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1205 return reinterpret_cast<uintptr_t>(pkey.release());
1206 }
1207
1208 /*
1209 * static native byte[] EVP_marshal_public_key(long)
1210 */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1211 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1212 CHECK_ERROR_QUEUE_ON_RETURN;
1213 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1214 JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1215
1216 if (pkey == nullptr) {
1217 return nullptr;
1218 }
1219
1220 bssl::ScopedCBB cbb;
1221 if (!CBB_init(cbb.get(), 64)) {
1222 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1223 JNI_TRACE("CBB_init failed");
1224 return nullptr;
1225 }
1226
1227 if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1228 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1229 JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1230 return nullptr;
1231 }
1232
1233 return CBBToByteArray(env, cbb.get());
1234 }
1235
1236 /*
1237 * static native long EVP_parse_public_key(byte[])
1238 */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1239 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1240 CHECK_ERROR_QUEUE_ON_RETURN;
1241 JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1242
1243 ScopedByteArrayRO bytes(env, keyJavaBytes);
1244 if (bytes.get() == nullptr) {
1245 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1246 return 0;
1247 }
1248
1249 CBS cbs;
1250 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1251 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1252 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1253 // allow parsing keys from buffers that are larger than the contained key structure
1254 // so we do the same for compatibility.
1255 if (!pkey) {
1256 conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1257 ERR_clear_error();
1258 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1259 return 0;
1260 }
1261
1262 JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1263 return reinterpret_cast<uintptr_t>(pkey.release());
1264 }
1265
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1266 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1267 jbyteArray modulusBytes) {
1268 CHECK_ERROR_QUEUE_ON_RETURN;
1269 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1270
1271 size_t cached_size;
1272 if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
1273 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1274 return 0;
1275 }
1276
1277 ensure_engine_globals();
1278
1279 bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1280 if (rsa.get() == nullptr) {
1281 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1282 return 0;
1283 }
1284
1285 // The PSS padding code needs access to the actual n, so set it even though we
1286 // don't set any other parts of the key
1287 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1288 return 0;
1289 }
1290
1291 auto ex_data = new KeyExData;
1292 ex_data->private_key = env->NewGlobalRef(javaKey);
1293 ex_data->cached_size = cached_size;
1294 RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1295
1296 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1297 if (pkey.get() == nullptr) {
1298 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1299 conscrypt::jniutil::throwRuntimeException(env,
1300 "NativeCrypto_getRSAPrivateKeyWrapper failed");
1301 ERR_clear_error();
1302 return 0;
1303 }
1304
1305 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1306 conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1307 ERR_clear_error();
1308 return 0;
1309 }
1310 OWNERSHIP_TRANSFERRED(rsa);
1311 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1312 return reinterpret_cast<uintptr_t>(pkey.release());
1313 }
1314
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1315 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1316 jobject groupRef) {
1317 CHECK_ERROR_QUEUE_ON_RETURN;
1318 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1319 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1320 if (group == nullptr) {
1321 return 0;
1322 }
1323
1324 ensure_engine_globals();
1325
1326 bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1327 if (ecKey.get() == nullptr) {
1328 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1329 return 0;
1330 }
1331
1332 if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1333 JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1334 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1335 return 0;
1336 }
1337
1338 auto ex_data = new KeyExData;
1339 ex_data->private_key = env->NewGlobalRef(javaKey);
1340
1341 if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1342 env->DeleteGlobalRef(ex_data->private_key);
1343 delete ex_data;
1344 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1345 ERR_clear_error();
1346 return 0;
1347 }
1348
1349 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1350 if (pkey.get() == nullptr) {
1351 JNI_TRACE("getECPrivateKeyWrapper failed");
1352 conscrypt::jniutil::throwRuntimeException(env,
1353 "NativeCrypto_getECPrivateKeyWrapper failed");
1354 ERR_clear_error();
1355 return 0;
1356 }
1357
1358 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1359 conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1360 ERR_clear_error();
1361 return 0;
1362 }
1363 OWNERSHIP_TRANSFERRED(ecKey);
1364 return reinterpret_cast<uintptr_t>(pkey.release());
1365 }
1366
1367 /*
1368 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1369 */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1370 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1371 jbyteArray publicExponent) {
1372 CHECK_ERROR_QUEUE_ON_RETURN;
1373 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1374
1375 BIGNUM* eRef = nullptr;
1376 if (!arrayToBignum(env, publicExponent, &eRef)) {
1377 return 0;
1378 }
1379 bssl::UniquePtr<BIGNUM> e(eRef);
1380
1381 bssl::UniquePtr<RSA> rsa(RSA_new());
1382 if (rsa.get() == nullptr) {
1383 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1384 return 0;
1385 }
1386
1387 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1388 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1389 return 0;
1390 }
1391
1392 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1393 if (pkey.get() == nullptr) {
1394 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1395 return 0;
1396 }
1397
1398 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1399 conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1400 ERR_clear_error();
1401 return 0;
1402 }
1403
1404 OWNERSHIP_TRANSFERRED(rsa);
1405 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1406 return reinterpret_cast<uintptr_t>(pkey.release());
1407 }
1408
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1409 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1410 CHECK_ERROR_QUEUE_ON_RETURN;
1411 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1412 JNI_TRACE("RSA_size(%p)", pkey);
1413
1414 if (pkey == nullptr) {
1415 return 0;
1416 }
1417
1418 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1419 if (rsa.get() == nullptr) {
1420 conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1421 ERR_clear_error();
1422 return 0;
1423 }
1424
1425 return static_cast<jint>(RSA_size(rsa.get()));
1426 }
1427
1428 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1429 int padding);
1430
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1431 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1432 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1433 jobject pkeyRef, jint padding) {
1434 CHECK_ERROR_QUEUE_ON_RETURN;
1435 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1436 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1437
1438 if (pkey == nullptr) {
1439 return -1;
1440 }
1441
1442 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1443 if (rsa.get() == nullptr) {
1444 return -1;
1445 }
1446
1447 ScopedByteArrayRO from(env, fromJavaBytes);
1448 if (from.get() == nullptr) {
1449 return -1;
1450 }
1451
1452 ScopedByteArrayRW to(env, toJavaBytes);
1453 if (to.get() == nullptr) {
1454 return -1;
1455 }
1456
1457 int resultSize =
1458 operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1459 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1460 if (resultSize == -1) {
1461 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1462 conscrypt::jniutil::throwBadPaddingException);
1463 JNI_TRACE("%s => threw error", caller);
1464 return -1;
1465 }
1466
1467 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1468 resultSize);
1469 return static_cast<jint>(resultSize);
1470 }
1471
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1472 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1473 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1474 jobject pkeyRef, jint padding) {
1475 CHECK_ERROR_QUEUE_ON_RETURN;
1476 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1477 toJavaBytes, pkeyRef, padding);
1478 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1479 static jint NativeCrypto_RSA_public_decrypt(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_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1484 toJavaBytes, pkeyRef, padding);
1485 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1486 static jint NativeCrypto_RSA_public_encrypt(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_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1491 toJavaBytes, pkeyRef, padding);
1492 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1493 static jint NativeCrypto_RSA_private_decrypt(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_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1498 toJavaBytes, pkeyRef, padding);
1499 }
1500
1501 /*
1502 * public static native byte[][] get_RSA_public_params(long);
1503 */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1504 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1505 CHECK_ERROR_QUEUE_ON_RETURN;
1506 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1507 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1508
1509 if (pkey == nullptr) {
1510 return nullptr;
1511 }
1512
1513 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1514 if (rsa.get() == nullptr) {
1515 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1516 return nullptr;
1517 }
1518
1519 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1520 if (joa == nullptr) {
1521 return nullptr;
1522 }
1523
1524 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1525 if (env->ExceptionCheck()) {
1526 return nullptr;
1527 }
1528 env->SetObjectArrayElement(joa, 0, n);
1529
1530 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1531 if (env->ExceptionCheck()) {
1532 return nullptr;
1533 }
1534 env->SetObjectArrayElement(joa, 1, e);
1535
1536 return joa;
1537 }
1538
1539 /*
1540 * public static native byte[][] get_RSA_private_params(long);
1541 */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1542 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1543 CHECK_ERROR_QUEUE_ON_RETURN;
1544 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1545 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1546
1547 if (pkey == nullptr) {
1548 return nullptr;
1549 }
1550
1551 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1552 if (rsa.get() == nullptr) {
1553 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1554 return nullptr;
1555 }
1556
1557 jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1558 if (joa == nullptr) {
1559 return nullptr;
1560 }
1561
1562 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1563 if (env->ExceptionCheck()) {
1564 return nullptr;
1565 }
1566 env->SetObjectArrayElement(joa, 0, n);
1567
1568 if (RSA_get0_e(rsa.get()) != nullptr) {
1569 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1570 if (env->ExceptionCheck()) {
1571 return nullptr;
1572 }
1573 env->SetObjectArrayElement(joa, 1, e);
1574 }
1575
1576 if (RSA_get0_d(rsa.get()) != nullptr) {
1577 jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1578 if (env->ExceptionCheck()) {
1579 return nullptr;
1580 }
1581 env->SetObjectArrayElement(joa, 2, d);
1582 }
1583
1584 if (RSA_get0_p(rsa.get()) != nullptr) {
1585 jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1586 if (env->ExceptionCheck()) {
1587 return nullptr;
1588 }
1589 env->SetObjectArrayElement(joa, 3, p);
1590 }
1591
1592 if (RSA_get0_q(rsa.get()) != nullptr) {
1593 jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1594 if (env->ExceptionCheck()) {
1595 return nullptr;
1596 }
1597 env->SetObjectArrayElement(joa, 4, q);
1598 }
1599
1600 if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1601 jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1602 if (env->ExceptionCheck()) {
1603 return nullptr;
1604 }
1605 env->SetObjectArrayElement(joa, 5, dmp1);
1606 }
1607
1608 if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1609 jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1610 if (env->ExceptionCheck()) {
1611 return nullptr;
1612 }
1613 env->SetObjectArrayElement(joa, 6, dmq1);
1614 }
1615
1616 if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1617 jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1618 if (env->ExceptionCheck()) {
1619 return nullptr;
1620 }
1621 env->SetObjectArrayElement(joa, 7, iqmp);
1622 }
1623
1624 return joa;
1625 }
1626
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1627 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1628 jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1629 jbyteArray nonceBytes, jint blockCounter) {
1630 CHECK_ERROR_QUEUE_ON_RETURN;
1631 JNI_TRACE("chacha20_encrypt_decrypt");
1632 ScopedByteArrayRO in(env, inBytes);
1633 if (in.get() == nullptr) {
1634 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1635 return;
1636 }
1637 ScopedByteArrayRW out(env, outBytes);
1638 if (out.get() == nullptr) {
1639 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1640 return;
1641 }
1642 ScopedByteArrayRO key(env, keyBytes);
1643 if (key.get() == nullptr) {
1644 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1645 return;
1646 }
1647 ScopedByteArrayRO nonce(env, nonceBytes);
1648 if (nonce.get() == nullptr) {
1649 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1650 return;
1651 }
1652
1653 CRYPTO_chacha_20(
1654 reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1655 reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1656 length,
1657 reinterpret_cast<const unsigned char*>(key.get()),
1658 reinterpret_cast<const unsigned char*>(nonce.get()),
1659 blockCounter);
1660 }
1661
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1662 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1663 CHECK_ERROR_QUEUE_ON_RETURN;
1664 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1665
1666 ScopedUtfChars curveName(env, curveNameJava);
1667 if (curveName.c_str() == nullptr) {
1668 return 0;
1669 }
1670 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1671
1672 int nid = OBJ_sn2nid(curveName.c_str());
1673 if (nid == NID_undef) {
1674 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1675 return 0;
1676 }
1677
1678 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1679 if (group == nullptr) {
1680 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1681 ERR_clear_error();
1682 return 0;
1683 }
1684
1685 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1686 return reinterpret_cast<uintptr_t>(group);
1687 }
1688
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1689 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1690 jbyteArray aBytes, jbyteArray bBytes,
1691 jbyteArray xBytes, jbyteArray yBytes,
1692 jbyteArray orderBytes, jint cofactorInt) {
1693 CHECK_ERROR_QUEUE_ON_RETURN;
1694 BIGNUM *p = nullptr, *a = nullptr, *b = nullptr, *x = nullptr, *y = nullptr;
1695 BIGNUM *order = nullptr, *cofactor = nullptr;
1696
1697 JNI_TRACE("EC_GROUP_new_arbitrary");
1698
1699 if (cofactorInt < 1) {
1700 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1701 "cofactor < 1");
1702 return 0;
1703 }
1704
1705 cofactor = BN_new();
1706 if (cofactor == nullptr) {
1707 return 0;
1708 }
1709
1710 int ok = 1;
1711
1712 if (!arrayToBignum(env, pBytes, &p) || !arrayToBignum(env, aBytes, &a) ||
1713 !arrayToBignum(env, bBytes, &b) || !arrayToBignum(env, xBytes, &x) ||
1714 !arrayToBignum(env, yBytes, &y) || !arrayToBignum(env, orderBytes, &order) ||
1715 !BN_set_word(cofactor, static_cast<uint32_t>(cofactorInt))) {
1716 ok = 0;
1717 }
1718
1719 bssl::UniquePtr<BIGNUM> pStorage(p);
1720 bssl::UniquePtr<BIGNUM> aStorage(a);
1721 bssl::UniquePtr<BIGNUM> bStorage(b);
1722 bssl::UniquePtr<BIGNUM> xStorage(x);
1723 bssl::UniquePtr<BIGNUM> yStorage(y);
1724 bssl::UniquePtr<BIGNUM> orderStorage(order);
1725 bssl::UniquePtr<BIGNUM> cofactorStorage(cofactor);
1726
1727 if (!ok) {
1728 return 0;
1729 }
1730
1731 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1732 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
1733 if (group.get() == nullptr) {
1734 JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1735 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1736 return 0;
1737 }
1738
1739 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1740 if (generator.get() == nullptr) {
1741 JNI_TRACE("EC_POINT_new => null");
1742 ERR_clear_error();
1743 return 0;
1744 }
1745
1746 if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
1747 JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1748 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1749 "EC_POINT_set_affine_coordinates_GFp");
1750 return 0;
1751 }
1752
1753 if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
1754 JNI_TRACE("EC_GROUP_set_generator => error");
1755 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1756 return 0;
1757 }
1758
1759 JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1760 return reinterpret_cast<uintptr_t>(group.release());
1761 }
1762
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1763 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1764 CHECK_ERROR_QUEUE_ON_RETURN;
1765 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1766 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1767
1768 if (group == nullptr) {
1769 JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1770 return nullptr;
1771 }
1772
1773 int nid = EC_GROUP_get_curve_name(group);
1774 if (nid == NID_undef) {
1775 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1776 return nullptr;
1777 }
1778
1779 const char* shortName = OBJ_nid2sn(nid);
1780 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1781 return env->NewStringUTF(shortName);
1782 }
1783
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1784 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1785 CHECK_ERROR_QUEUE_ON_RETURN;
1786 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1787 JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1788 if (group == nullptr) {
1789 JNI_TRACE("EC_GROUP_get_curve => group == null");
1790 return nullptr;
1791 }
1792
1793 bssl::UniquePtr<BIGNUM> p(BN_new());
1794 bssl::UniquePtr<BIGNUM> a(BN_new());
1795 bssl::UniquePtr<BIGNUM> b(BN_new());
1796
1797 int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1798 if (ret != 1) {
1799 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1800 return nullptr;
1801 }
1802
1803 jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1804 if (joa == nullptr) {
1805 return nullptr;
1806 }
1807
1808 jbyteArray pArray = bignumToArray(env, p.get(), "p");
1809 if (env->ExceptionCheck()) {
1810 return nullptr;
1811 }
1812 env->SetObjectArrayElement(joa, 0, pArray);
1813
1814 jbyteArray aArray = bignumToArray(env, a.get(), "a");
1815 if (env->ExceptionCheck()) {
1816 return nullptr;
1817 }
1818 env->SetObjectArrayElement(joa, 1, aArray);
1819
1820 jbyteArray bArray = bignumToArray(env, b.get(), "b");
1821 if (env->ExceptionCheck()) {
1822 return nullptr;
1823 }
1824 env->SetObjectArrayElement(joa, 2, bArray);
1825
1826 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1827 return joa;
1828 }
1829
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1830 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1831 CHECK_ERROR_QUEUE_ON_RETURN;
1832 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1833 JNI_TRACE("EC_GROUP_get_order(%p)", group);
1834 if (group == nullptr) {
1835 return nullptr;
1836 }
1837
1838 bssl::UniquePtr<BIGNUM> order(BN_new());
1839 if (order.get() == nullptr) {
1840 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1841 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1842 return nullptr;
1843 }
1844
1845 if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1846 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1847 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1848 return nullptr;
1849 }
1850
1851 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1852 if (env->ExceptionCheck()) {
1853 return nullptr;
1854 }
1855
1856 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1857 return orderArray;
1858 }
1859
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1860 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1861 CHECK_ERROR_QUEUE_ON_RETURN;
1862 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1863 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1864 if (group == nullptr) {
1865 return 0;
1866 }
1867
1868 jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1869 if (degree == 0) {
1870 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1871 conscrypt::jniutil::throwRuntimeException(env, "not supported");
1872 ERR_clear_error();
1873 return 0;
1874 }
1875
1876 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1877 return degree;
1878 }
1879
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1880 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1881 CHECK_ERROR_QUEUE_ON_RETURN;
1882 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1883 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1884 if (group == nullptr) {
1885 return nullptr;
1886 }
1887
1888 bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1889 if (cofactor.get() == nullptr) {
1890 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1891 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1892 return nullptr;
1893 }
1894
1895 if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1896 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1897 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1898 return nullptr;
1899 }
1900
1901 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1902 if (env->ExceptionCheck()) {
1903 return nullptr;
1904 }
1905
1906 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1907 return cofactorArray;
1908 }
1909
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1910 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1911 CHECK_ERROR_QUEUE_ON_RETURN;
1912 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1913 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1914
1915 if (group == nullptr) {
1916 JNI_TRACE("EC_GROUP_clear_free => group == null");
1917 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1918 return;
1919 }
1920
1921 EC_GROUP_free(group);
1922 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1923 }
1924
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1925 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1926 CHECK_ERROR_QUEUE_ON_RETURN;
1927 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1928 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1929
1930 if (group == nullptr) {
1931 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
1932 return 0;
1933 }
1934
1935 const EC_POINT* generator = EC_GROUP_get0_generator(group);
1936
1937 bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
1938 if (dup.get() == nullptr) {
1939 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
1940 conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
1941 return 0;
1942 }
1943
1944 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
1945 return reinterpret_cast<uintptr_t>(dup.release());
1946 }
1947
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)1948 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
1949 CHECK_ERROR_QUEUE_ON_RETURN;
1950 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1951 JNI_TRACE("EC_POINT_new(%p)", group);
1952
1953 if (group == nullptr) {
1954 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
1955 return 0;
1956 }
1957
1958 EC_POINT* point = EC_POINT_new(group);
1959 if (point == nullptr) {
1960 conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
1961 return 0;
1962 }
1963
1964 return reinterpret_cast<uintptr_t>(point);
1965 }
1966
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)1967 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1968 CHECK_ERROR_QUEUE_ON_RETURN;
1969 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
1970 JNI_TRACE("EC_POINT_clear_free(%p)", group);
1971
1972 if (group == nullptr) {
1973 JNI_TRACE("EC_POINT_clear_free => group == null");
1974 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1975 return;
1976 }
1977
1978 EC_POINT_free(group);
1979 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
1980 }
1981
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)1982 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
1983 jobject pointRef, jbyteArray xjavaBytes,
1984 jbyteArray yjavaBytes) {
1985 CHECK_ERROR_QUEUE_ON_RETURN;
1986 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
1987 yjavaBytes);
1988 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1989 if (group == nullptr) {
1990 return;
1991 }
1992 EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
1993 if (point == nullptr) {
1994 return;
1995 }
1996 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
1997 yjavaBytes);
1998
1999 BIGNUM* xRef = nullptr;
2000 if (!arrayToBignum(env, xjavaBytes, &xRef)) {
2001 return;
2002 }
2003 bssl::UniquePtr<BIGNUM> x(xRef);
2004
2005 BIGNUM* yRef = nullptr;
2006 if (!arrayToBignum(env, yjavaBytes, &yRef)) {
2007 return;
2008 }
2009 bssl::UniquePtr<BIGNUM> y(yRef);
2010
2011 int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2012 if (ret != 1) {
2013 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2014 "EC_POINT_set_affine_coordinates");
2015 return;
2016 }
2017
2018 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2019 yjavaBytes, ret);
2020 }
2021
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2022 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2023 jobject groupRef,
2024 jobject pointRef) {
2025 CHECK_ERROR_QUEUE_ON_RETURN;
2026 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2027 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2028 if (group == nullptr) {
2029 return nullptr;
2030 }
2031 const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2032 if (point == nullptr) {
2033 return nullptr;
2034 }
2035 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2036
2037 bssl::UniquePtr<BIGNUM> x(BN_new());
2038 bssl::UniquePtr<BIGNUM> y(BN_new());
2039
2040 int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2041 if (ret != 1) {
2042 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2043 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2044 "EC_POINT_get_affine_coordinates");
2045 return nullptr;
2046 }
2047
2048 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2049 if (joa == nullptr) {
2050 return nullptr;
2051 }
2052
2053 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2054 if (env->ExceptionCheck()) {
2055 return nullptr;
2056 }
2057 env->SetObjectArrayElement(joa, 0, xBytes);
2058
2059 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2060 if (env->ExceptionCheck()) {
2061 return nullptr;
2062 }
2063 env->SetObjectArrayElement(joa, 1, yBytes);
2064
2065 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2066 return joa;
2067 }
2068
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2069 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2070 CHECK_ERROR_QUEUE_ON_RETURN;
2071 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2072 JNI_TRACE("EC_KEY_generate_key(%p)", group);
2073 if (group == nullptr) {
2074 return 0;
2075 }
2076
2077 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2078 if (eckey.get() == nullptr) {
2079 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2080 conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2081 return 0;
2082 }
2083
2084 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2085 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2086 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2087 return 0;
2088 }
2089
2090 if (EC_KEY_generate_key(eckey.get()) != 1) {
2091 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2092 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2093 return 0;
2094 }
2095
2096 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2097 if (pkey.get() == nullptr) {
2098 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2099 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2100 return 0;
2101 }
2102 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2103 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2104 ERR_clear_error();
2105 return 0;
2106 }
2107 OWNERSHIP_TRANSFERRED(eckey);
2108
2109 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2110 return reinterpret_cast<uintptr_t>(pkey.release());
2111 }
2112
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2113 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2114 CHECK_ERROR_QUEUE_ON_RETURN;
2115 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2116 JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2117
2118 if (pkey == nullptr) {
2119 JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2120 return 0;
2121 }
2122
2123 if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2124 conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2125 JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2126 return 0;
2127 }
2128
2129 EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2130 JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2131 return reinterpret_cast<uintptr_t>(group);
2132 }
2133
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2134 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2135 CHECK_ERROR_QUEUE_ON_RETURN;
2136 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2137 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2138
2139 if (pkey == nullptr) {
2140 JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2141 return nullptr;
2142 }
2143
2144 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2145 if (eckey.get() == nullptr) {
2146 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2147 return nullptr;
2148 }
2149
2150 const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2151
2152 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2153 if (env->ExceptionCheck()) {
2154 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2155 return nullptr;
2156 }
2157
2158 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2159 return privBytes;
2160 }
2161
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2162 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2163 CHECK_ERROR_QUEUE_ON_RETURN;
2164 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2165 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2166
2167 if (pkey == nullptr) {
2168 JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2169 return 0;
2170 }
2171
2172 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2173 if (eckey.get() == nullptr) {
2174 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2175 return 0;
2176 }
2177
2178 bssl::UniquePtr<EC_POINT> dup(
2179 EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2180 if (dup.get() == nullptr) {
2181 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2182 conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2183 ERR_clear_error();
2184 return 0;
2185 }
2186
2187 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2188 return reinterpret_cast<uintptr_t>(dup.release());
2189 }
2190
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2191 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2192 CHECK_ERROR_QUEUE_ON_RETURN;
2193 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2194 JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2195 if (group == nullptr) {
2196 env->ExceptionClear();
2197 conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2198 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => Invalid group pointer", group);
2199 return nullptr;
2200 }
2201
2202 bssl::ScopedCBB cbb;
2203 if (!CBB_init(cbb.get(), 64)) {
2204 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2205 JNI_TRACE("CBB_init failed");
2206 return nullptr;
2207 }
2208
2209 if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2210 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2211 ERR_clear_error();
2212 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2213 return nullptr;
2214 }
2215
2216 return CBBToByteArray(env, cbb.get());
2217 }
2218
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2219 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2220 CHECK_ERROR_QUEUE_ON_RETURN;
2221 JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2222
2223 ScopedByteArrayRO bytes(env, curveNameBytes);
2224 if (bytes.get() == nullptr) {
2225 env->ExceptionClear();
2226 conscrypt::jniutil::throwIOException(env, "Null EC curve name");
2227 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => curveNameBytes == null ", curveNameBytes);
2228 return 0;
2229 }
2230
2231 CBS cbs;
2232 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2233 bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2234 if (!group || CBS_len(&cbs) != 0) {
2235 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2236 ERR_clear_error();
2237 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2238 return 0;
2239 }
2240
2241 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2242 return reinterpret_cast<uintptr_t>(group.release());
2243 }
2244
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2245 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2246 jobject pubkeyRef, jobject privkeyRef) {
2247 CHECK_ERROR_QUEUE_ON_RETURN;
2248 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2249 EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2250 if (pubPkey == nullptr) {
2251 JNI_TRACE("ECDH_compute_key => pubPkey == null");
2252 return -1;
2253 }
2254 EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2255 if (privPkey == nullptr) {
2256 JNI_TRACE("ECDH_compute_key => privPkey == null");
2257 return -1;
2258 }
2259 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2260
2261 ScopedByteArrayRW out(env, outArray);
2262 if (out.get() == nullptr) {
2263 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2264 pubPkey, privPkey);
2265 return -1;
2266 }
2267
2268 if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2269 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2270 nullptr);
2271 return -1;
2272 }
2273
2274 if (pubPkey == nullptr) {
2275 JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2276 conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2277 return -1;
2278 }
2279
2280 bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2281 if (pubkey.get() == nullptr) {
2282 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2283 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2284 conscrypt::jniutil::throwInvalidKeyException);
2285 return -1;
2286 }
2287
2288 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2289 if (pubkeyPoint == nullptr) {
2290 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2291 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2292 conscrypt::jniutil::throwInvalidKeyException);
2293 return -1;
2294 }
2295
2296 if (privPkey == nullptr) {
2297 JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2298 conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2299 return -1;
2300 }
2301
2302 bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2303 if (privkey.get() == nullptr) {
2304 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2305 conscrypt::jniutil::throwInvalidKeyException);
2306 return -1;
2307 }
2308
2309 std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2310 int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2311 privkey.get(), nullptr /* No KDF */);
2312 if (outputLength == -1) {
2313 JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2314 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2315 conscrypt::jniutil::throwInvalidKeyException);
2316 return -1;
2317 }
2318
2319 JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2320 return outputLength;
2321 }
2322
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2323 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2324 CHECK_ERROR_QUEUE_ON_RETURN;
2325 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2326 JNI_TRACE("ECDSA_size(%p)", pkey);
2327
2328 if (pkey == nullptr) {
2329 return 0;
2330 }
2331
2332 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2333 if (ec_key.get() == nullptr) {
2334 conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2335 ERR_clear_error();
2336 return 0;
2337 }
2338
2339 size_t size = ECDSA_size(ec_key.get());
2340
2341 JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2342 return static_cast<jint>(size);
2343 }
2344
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2345 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2346 jobject pkeyRef) {
2347 CHECK_ERROR_QUEUE_ON_RETURN;
2348 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2349 JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2350
2351 if (pkey == nullptr) {
2352 return -1;
2353 }
2354
2355 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2356 if (ec_key.get() == nullptr) {
2357 return -1;
2358 }
2359
2360 ScopedByteArrayRO data_array(env, data);
2361 if (data_array.get() == nullptr) {
2362 return -1;
2363 }
2364
2365 ScopedByteArrayRW sig_array(env, sig);
2366 if (sig_array.get() == nullptr) {
2367 return -1;
2368 }
2369
2370 unsigned int sig_size;
2371 int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2372 data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2373 &sig_size, ec_key.get());
2374 if (result == 0) {
2375 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2376 JNI_TRACE("ECDSA_sign => threw error");
2377 return -1;
2378 }
2379
2380 JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2381 return static_cast<jint>(sig_size);
2382 }
2383
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2384 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2385 jobject pkeyRef) {
2386 CHECK_ERROR_QUEUE_ON_RETURN;
2387 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2388 JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2389
2390 if (pkey == nullptr) {
2391 return -1;
2392 }
2393
2394 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2395 if (ec_key.get() == nullptr) {
2396 return -1;
2397 }
2398
2399 ScopedByteArrayRO data_array(env, data);
2400 if (data_array.get() == nullptr) {
2401 return -1;
2402 }
2403
2404 ScopedByteArrayRO sig_array(env, sig);
2405 if (sig_array.get() == nullptr) {
2406 return -1;
2407 }
2408
2409 int result =
2410 ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2411 data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2412 sig_array.size(), ec_key.get());
2413
2414 if (result == 0) {
2415 // NOLINTNEXTLINE(runtime/int)
2416 unsigned long error = ERR_peek_last_error();
2417 if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2418 (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2419 // This error just means the signature didn't verify, so clear the error and return
2420 // a failed verification
2421 ERR_clear_error();
2422 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2423 return 0;
2424 }
2425 if (error != 0) {
2426 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2427 JNI_TRACE("ECDSA_verify => threw error");
2428 return -1;
2429 }
2430 return 0;
2431 }
2432
2433 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2434 return static_cast<jint>(result);
2435 }
2436
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2437 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2438 jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2439 CHECK_ERROR_QUEUE_ON_RETURN;
2440 JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2441
2442 ScopedByteArrayRW out(env, outArray);
2443 if (out.get() == nullptr) {
2444 JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2445 return JNI_FALSE;
2446 }
2447
2448 ScopedByteArrayRO privkey(env, privkeyArray);
2449 if (privkey.get() == nullptr) {
2450 JNI_TRACE("X25519(%p) => privkey == null", outArray);
2451 return JNI_FALSE;
2452 }
2453
2454 ScopedByteArrayRO pubkey(env, pubkeyArray);
2455 if (pubkey.get() == nullptr) {
2456 JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2457 return JNI_FALSE;
2458 }
2459
2460 if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2461 reinterpret_cast<const uint8_t*>(privkey.get()),
2462 reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2463 JNI_TRACE("X25519(%p) => failure", outArray);
2464 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2465 conscrypt::jniutil::throwInvalidKeyException);
2466 return JNI_FALSE;
2467 }
2468
2469 JNI_TRACE("X25519(%p) => success", outArray);
2470 return JNI_TRUE;
2471 }
2472
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2473 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2474 CHECK_ERROR_QUEUE_ON_RETURN;
2475 JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2476
2477 ScopedByteArrayRW outPublic(env, outPublicArray);
2478 if (outPublic.get() == nullptr) {
2479 JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2480 return;
2481 }
2482
2483 ScopedByteArrayRW outPrivate(env, outPrivateArray);
2484 if (outPrivate.get() == nullptr) {
2485 JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2486 return;
2487 }
2488
2489 if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2490 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2491 return;
2492 }
2493
2494 X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2495 JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2496 }
2497
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2498 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2499 CHECK_ERROR_QUEUE_ON_RETURN;
2500 JNI_TRACE_MD("EVP_MD_CTX_create()");
2501
2502 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2503 if (ctx.get() == nullptr) {
2504 conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2505 return 0;
2506 }
2507
2508 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2509 return reinterpret_cast<uintptr_t>(ctx.release());
2510 }
2511
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2512 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2513 CHECK_ERROR_QUEUE_ON_RETURN;
2514 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2515 JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2516
2517 if (ctx != nullptr) {
2518 EVP_MD_CTX_cleanup(ctx);
2519 }
2520 }
2521
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2522 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2523 CHECK_ERROR_QUEUE_ON_RETURN;
2524 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2525 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2526
2527 if (ctx != nullptr) {
2528 EVP_MD_CTX_destroy(ctx);
2529 }
2530 }
2531
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2532 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2533 jobject srcCtxRef) {
2534 CHECK_ERROR_QUEUE_ON_RETURN;
2535 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2536 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2537 if (dst_ctx == nullptr) {
2538 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2539 return 0;
2540 }
2541 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2542 if (src_ctx == nullptr) {
2543 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2544 return 0;
2545 }
2546 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2547
2548 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2549 if (result == 0) {
2550 conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2551 ERR_clear_error();
2552 }
2553
2554 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2555 return result;
2556 }
2557
2558 /*
2559 * public static native int EVP_DigestFinal_ex(long, byte[], int)
2560 */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2561 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2562 jint offset) {
2563 CHECK_ERROR_QUEUE_ON_RETURN;
2564 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2565 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2566
2567 if (ctx == nullptr) {
2568 JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2569 return -1;
2570 } else if (hash == nullptr) {
2571 conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2572 return -1;
2573 }
2574
2575 ScopedByteArrayRW hashBytes(env, hash);
2576 if (hashBytes.get() == nullptr) {
2577 return -1;
2578 }
2579 unsigned int bytesWritten = static_cast<unsigned int>(-1);
2580 int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2581 &bytesWritten);
2582 if (ok == 0) {
2583 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2584 return -1;
2585 }
2586
2587 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2588 return static_cast<jint>(bytesWritten);
2589 }
2590
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2591 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2592 jlong evpMdRef) {
2593 CHECK_ERROR_QUEUE_ON_RETURN;
2594 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2595 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2596 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2597
2598 if (ctx == nullptr) {
2599 JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2600 return 0;
2601 } else if (evp_md == nullptr) {
2602 conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2603 return 0;
2604 }
2605
2606 int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2607 if (ok == 0) {
2608 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2609 JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2610 return 0;
2611 }
2612 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2613 return ok;
2614 }
2615
2616 /*
2617 * public static native int EVP_get_digestbyname(java.lang.String)
2618 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2619 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2620 CHECK_ERROR_QUEUE_ON_RETURN;
2621 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2622
2623 if (algorithm == nullptr) {
2624 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2625 return -1;
2626 }
2627
2628 ScopedUtfChars algorithmChars(env, algorithm);
2629 if (algorithmChars.c_str() == nullptr) {
2630 return 0;
2631 }
2632 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2633
2634 const char* alg = algorithmChars.c_str();
2635 const EVP_MD* md;
2636
2637 if (strcasecmp(alg, "md4") == 0) {
2638 md = EVP_md4();
2639 } else if (strcasecmp(alg, "md5") == 0) {
2640 md = EVP_md5();
2641 } else if (strcasecmp(alg, "sha1") == 0) {
2642 md = EVP_sha1();
2643 } else if (strcasecmp(alg, "sha224") == 0) {
2644 md = EVP_sha224();
2645 } else if (strcasecmp(alg, "sha256") == 0) {
2646 md = EVP_sha256();
2647 } else if (strcasecmp(alg, "sha384") == 0) {
2648 md = EVP_sha384();
2649 } else if (strcasecmp(alg, "sha512") == 0) {
2650 md = EVP_sha512();
2651 } else {
2652 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2653 conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2654 return 0;
2655 }
2656
2657 return reinterpret_cast<uintptr_t>(md);
2658 }
2659
2660 /*
2661 * public static native int EVP_MD_size(long)
2662 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2663 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2664 CHECK_ERROR_QUEUE_ON_RETURN;
2665 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2666 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2667
2668 if (evp_md == nullptr) {
2669 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2670 return -1;
2671 }
2672
2673 jint result = static_cast<jint>(EVP_MD_size(evp_md));
2674 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2675 return result;
2676 }
2677
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)2678 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2679 int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2680 ENGINE*, EVP_PKEY*),
2681 const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2682 jobject pkeyRef) {
2683 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2684 if (mdCtx == nullptr) {
2685 JNI_TRACE("%s => mdCtx == null", jniName);
2686 return 0;
2687 }
2688 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2689 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2690 if (pkey == nullptr) {
2691 JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2692 return 0;
2693 }
2694 JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2695
2696 if (md == nullptr) {
2697 JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2698 conscrypt::jniutil::throwNullPointerException(env, "md == null");
2699 return 0;
2700 }
2701
2702 EVP_PKEY_CTX* pctx = nullptr;
2703 if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2704 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2705 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2706 return 0;
2707 }
2708
2709 JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2710 return reinterpret_cast<jlong>(pctx);
2711 }
2712
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2713 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2714 const jlong evpMdRef, jobject pkeyRef) {
2715 CHECK_ERROR_QUEUE_ON_RETURN;
2716 return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2717 evpMdRef, pkeyRef);
2718 }
2719
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2720 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2721 const jlong evpMdRef, jobject pkeyRef) {
2722 CHECK_ERROR_QUEUE_ON_RETURN;
2723 return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2724 evpMdRef, pkeyRef);
2725 }
2726
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2727 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2728 const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2729 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2730 const void* p = reinterpret_cast<const void*>(inPtr);
2731 JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2732
2733 if (mdCtx == nullptr) {
2734 return;
2735 }
2736
2737 if (p == nullptr) {
2738 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2739 return;
2740 }
2741
2742 if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2743 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2744 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2745 return;
2746 }
2747
2748 JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2749 }
2750
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2751 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2752 jint inLength, const char* jniName,
2753 int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2754 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2755 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2756
2757 if (mdCtx == nullptr) {
2758 return;
2759 }
2760
2761 if (inJavaBytes == nullptr) {
2762 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2763 return;
2764 }
2765
2766 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2767 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2768 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2769 "inBytes");
2770 return;
2771 }
2772 if (inLength == 0) {
2773 return;
2774 }
2775 jint in_offset = inOffset;
2776 jint in_size = inLength;
2777
2778 int update_func_result = -1;
2779 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2780 // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2781 // avoid copying the whole array.
2782 if (in_size <= 1024) {
2783 // For small chunk, it's more efficient to use a bit more space on the stack instead of
2784 // allocating a new buffer.
2785 jbyte buf[1024];
2786 env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2787 update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2788 static_cast<size_t>(in_size));
2789 } else {
2790 // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2791 // through the buffer, stopping as soon as update_func fails.
2792 jint remaining = in_size;
2793 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2794 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2795 if (buf.get() == nullptr) {
2796 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2797 return;
2798 }
2799 while (remaining > 0) {
2800 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2801 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2802 update_func_result =
2803 update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2804 static_cast<size_t>(chunk_size));
2805 if (!update_func_result) {
2806 // update_func failed. This will be handled later in this method.
2807 break;
2808 }
2809 in_offset += chunk_size;
2810 remaining -= chunk_size;
2811 }
2812 }
2813 } else {
2814 // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2815 // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2816 // use GetByteArrayElements or another approach.
2817 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2818 if (array_elements == nullptr) {
2819 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2820 return;
2821 }
2822 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2823 update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2824 env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2825 }
2826
2827 if (!update_func_result) {
2828 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2829 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2830 return;
2831 }
2832
2833 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2834 }
2835
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2836 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2837 jlong inPtr, jint inLength) {
2838 CHECK_ERROR_QUEUE_ON_RETURN;
2839 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2840 }
2841
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2842 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2843 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2844 CHECK_ERROR_QUEUE_ON_RETURN;
2845 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2846 EVP_DigestUpdate);
2847 }
2848
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2849 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2850 jbyteArray inJavaBytes, jint inOffset,
2851 jint inLength) {
2852 CHECK_ERROR_QUEUE_ON_RETURN;
2853 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2854 EVP_DigestSignUpdate);
2855 }
2856
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2857 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2858 jlong inPtr, jint inLength) {
2859 CHECK_ERROR_QUEUE_ON_RETURN;
2860 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2861 EVP_DigestSignUpdate);
2862 }
2863
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2864 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2865 jbyteArray inJavaBytes, jint inOffset,
2866 jint inLength) {
2867 CHECK_ERROR_QUEUE_ON_RETURN;
2868 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2869 EVP_DigestVerifyUpdate);
2870 }
2871
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2872 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2873 jlong inPtr, jint inLength) {
2874 CHECK_ERROR_QUEUE_ON_RETURN;
2875 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2876 EVP_DigestVerifyUpdate);
2877 }
2878
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2879 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2880 CHECK_ERROR_QUEUE_ON_RETURN;
2881 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2882 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2883
2884 if (mdCtx == nullptr) {
2885 return nullptr;
2886 }
2887
2888 size_t maxLen;
2889 if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2890 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2891 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2892 return nullptr;
2893 }
2894
2895 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2896 if (buffer.get() == nullptr) {
2897 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2898 return nullptr;
2899 }
2900 size_t actualLen(maxLen);
2901 if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2902 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2903 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2904 return nullptr;
2905 }
2906 if (actualLen > maxLen) {
2907 JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2908 maxLen);
2909 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2910 return nullptr;
2911 }
2912
2913 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2914 if (sigJavaBytes.get() == nullptr) {
2915 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2916 return nullptr;
2917 }
2918 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2919 reinterpret_cast<jbyte*>(buffer.get()));
2920
2921 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2922 return sigJavaBytes.release();
2923 }
2924
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2925 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2926 jbyteArray signature, jint offset, jint len) {
2927 CHECK_ERROR_QUEUE_ON_RETURN;
2928 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2929 JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2930
2931 if (mdCtx == nullptr) {
2932 return 0;
2933 }
2934
2935 ScopedByteArrayRO sigBytes(env, signature);
2936 if (sigBytes.get() == nullptr) {
2937 return 0;
2938 }
2939
2940 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
2941 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2942 "signature");
2943 return 0;
2944 }
2945
2946 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
2947 int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
2948 jboolean result;
2949 if (err == 1) {
2950 // Signature verified
2951 result = 1;
2952 } else if (err == 0) {
2953 // Signature did not verify
2954 result = 0;
2955 } else {
2956 // Error while verifying signature
2957 JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
2958 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
2959 return 0;
2960 }
2961
2962 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
2963 // Clear the error queue to prevent its state from affecting future operations.
2964 ERR_clear_error();
2965
2966 JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
2967 return result;
2968 }
2969
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)2970 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
2971 int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
2972 const uint8_t*, size_t),
2973 const char* jniName, jobject evpPkeyCtxRef,
2974 jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
2975 jint inOffset, jint inLength) {
2976 EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
2977 JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
2978 inJavaBytes, inOffset, inLength);
2979
2980 if (pkeyCtx == nullptr) {
2981 return 0;
2982 }
2983
2984 ScopedByteArrayRW outBytes(env, outJavaBytes);
2985 if (outBytes.get() == nullptr) {
2986 return 0;
2987 }
2988
2989 ScopedByteArrayRO inBytes(env, inJavaBytes);
2990 if (inBytes.get() == nullptr) {
2991 return 0;
2992 }
2993
2994 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
2995 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2996 "outBytes");
2997 return 0;
2998 }
2999
3000 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3001 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3002 "inBytes");
3003 return 0;
3004 }
3005
3006 uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3007 const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3008 size_t outLength = outBytes.size() - outOffset;
3009 if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3010 static_cast<size_t>(inLength))) {
3011 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3012 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3013 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3014 return 0;
3015 }
3016
3017 JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3018 outOffset, inJavaBytes, inOffset, inLength, outLength);
3019 return static_cast<jint>(outLength);
3020 }
3021
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3022 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3023 jbyteArray out, jint outOffset, jbyteArray inBytes,
3024 jint inOffset, jint inLength) {
3025 CHECK_ERROR_QUEUE_ON_RETURN;
3026 return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3027 outOffset, inBytes, inOffset, inLength);
3028 }
3029
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3030 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3031 jbyteArray out, jint outOffset, jbyteArray inBytes,
3032 jint inOffset, jint inLength) {
3033 CHECK_ERROR_QUEUE_ON_RETURN;
3034 return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3035 outOffset, inBytes, inOffset, inLength);
3036 }
3037
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3038 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3039 int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3040 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3041 JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3042 if (pkey == nullptr) {
3043 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3044 return 0;
3045 }
3046
3047 bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3048 if (pkeyCtx.get() == nullptr) {
3049 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3050 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3051 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3052 return 0;
3053 }
3054
3055 if (!real_func(pkeyCtx.get())) {
3056 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3057 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3058 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3059 return 0;
3060 }
3061
3062 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3063 return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3064 }
3065
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3066 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3067 CHECK_ERROR_QUEUE_ON_RETURN;
3068 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3069 }
3070
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3071 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3072 CHECK_ERROR_QUEUE_ON_RETURN;
3073 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3074 }
3075
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3076 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3077 CHECK_ERROR_QUEUE_ON_RETURN;
3078 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3079 JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3080
3081 if (pkeyCtx != nullptr) {
3082 EVP_PKEY_CTX_free(pkeyCtx);
3083 }
3084 }
3085
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3086 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3087 CHECK_ERROR_QUEUE_ON_RETURN;
3088 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3089 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3090 if (pkeyCtx == nullptr) {
3091 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3092 return;
3093 }
3094
3095 int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3096 if (result <= 0) {
3097 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3098 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3099 env, "EVP_PKEY_CTX_set_rsa_padding",
3100 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3101 return;
3102 }
3103
3104 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3105 }
3106
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3107 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3108 jint len) {
3109 CHECK_ERROR_QUEUE_ON_RETURN;
3110 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3111 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3112 if (pkeyCtx == nullptr) {
3113 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3114 return;
3115 }
3116
3117 int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3118 if (result <= 0) {
3119 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3120 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3121 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3122 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3123 return;
3124 }
3125
3126 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3127 }
3128
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3129 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3130 int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3131 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3132 EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3133 JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3134 if (pkeyCtx == nullptr) {
3135 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3136 return;
3137 }
3138 if (md == nullptr) {
3139 conscrypt::jniutil::throwNullPointerException(env, "md == null");
3140 return;
3141 }
3142
3143 int result = ctrl_func(pkeyCtx, md);
3144 if (result <= 0) {
3145 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3146 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3147 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3148 return;
3149 }
3150
3151 JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3152 }
3153
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3154 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3155 jlong mdRef) {
3156 CHECK_ERROR_QUEUE_ON_RETURN;
3157 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3158 EVP_PKEY_CTX_set_rsa_mgf1_md);
3159 }
3160
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3161 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3162 jlong mdRef) {
3163 CHECK_ERROR_QUEUE_ON_RETURN;
3164 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3165 EVP_PKEY_CTX_set_rsa_oaep_md);
3166 }
3167
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3168 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3169 jbyteArray labelJava) {
3170 CHECK_ERROR_QUEUE_ON_RETURN;
3171 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3172 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3173 if (pkeyCtx == nullptr) {
3174 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3175 return;
3176 }
3177
3178 ScopedByteArrayRO labelBytes(env, labelJava);
3179 if (labelBytes.get() == nullptr) {
3180 return;
3181 }
3182
3183 bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3184 memcpy(label.get(), labelBytes.get(), labelBytes.size());
3185
3186 int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3187 if (result <= 0) {
3188 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3189 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3190 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3191 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3192 return;
3193 }
3194 OWNERSHIP_TRANSFERRED(label);
3195
3196 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3197 }
3198
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3199 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3200 CHECK_ERROR_QUEUE_ON_RETURN;
3201 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3202
3203 if (algorithm == nullptr) {
3204 conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3205 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3206 return -1;
3207 }
3208
3209 ScopedUtfChars scoped_alg(env, algorithm);
3210 const char* alg = scoped_alg.c_str();
3211 const EVP_CIPHER* cipher;
3212
3213 if (strcasecmp(alg, "rc4") == 0) {
3214 cipher = EVP_rc4();
3215 } else if (strcasecmp(alg, "des-cbc") == 0) {
3216 cipher = EVP_des_cbc();
3217 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3218 cipher = EVP_des_ede_cbc();
3219 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3220 cipher = EVP_des_ede3_cbc();
3221 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3222 cipher = EVP_aes_128_ecb();
3223 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3224 cipher = EVP_aes_128_cbc();
3225 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3226 cipher = EVP_aes_128_ctr();
3227 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3228 cipher = EVP_aes_128_gcm();
3229 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3230 cipher = EVP_aes_192_ecb();
3231 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3232 cipher = EVP_aes_192_cbc();
3233 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3234 cipher = EVP_aes_192_ctr();
3235 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3236 cipher = EVP_aes_192_gcm();
3237 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3238 cipher = EVP_aes_256_ecb();
3239 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3240 cipher = EVP_aes_256_cbc();
3241 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3242 cipher = EVP_aes_256_ctr();
3243 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3244 cipher = EVP_aes_256_gcm();
3245 } else {
3246 JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3247 return 0;
3248 }
3249
3250 return reinterpret_cast<uintptr_t>(cipher);
3251 }
3252
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3253 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3254 jbyteArray keyArray, jbyteArray ivArray,
3255 jboolean encrypting) {
3256 CHECK_ERROR_QUEUE_ON_RETURN;
3257 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3258 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3259 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3260 encrypting ? 1 : 0);
3261
3262 if (ctx == nullptr) {
3263 JNI_TRACE("EVP_CipherUpdate => ctx == null");
3264 return;
3265 }
3266
3267 // The key can be null if we need to set extra parameters.
3268 std::unique_ptr<unsigned char[]> keyPtr;
3269 if (keyArray != nullptr) {
3270 ScopedByteArrayRO keyBytes(env, keyArray);
3271 if (keyBytes.get() == nullptr) {
3272 return;
3273 }
3274
3275 keyPtr.reset(new unsigned char[keyBytes.size()]);
3276 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3277 }
3278
3279 // The IV can be null if we're using ECB.
3280 std::unique_ptr<unsigned char[]> ivPtr;
3281 if (ivArray != nullptr) {
3282 ScopedByteArrayRO ivBytes(env, ivArray);
3283 if (ivBytes.get() == nullptr) {
3284 return;
3285 }
3286
3287 ivPtr.reset(new unsigned char[ivBytes.size()]);
3288 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3289 }
3290
3291 if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3292 encrypting ? 1 : 0)) {
3293 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3294 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3295 return;
3296 }
3297
3298 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3299 encrypting ? 1 : 0);
3300 }
3301
3302 /*
3303 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3304 * int inOffset, int inLength);
3305 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3306 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3307 jint outOffset, jbyteArray inArray, jint inOffset,
3308 jint inLength) {
3309 CHECK_ERROR_QUEUE_ON_RETURN;
3310 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3311 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3312
3313 if (ctx == nullptr) {
3314 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3315 return 0;
3316 }
3317
3318 ScopedByteArrayRO inBytes(env, inArray);
3319 if (inBytes.get() == nullptr) {
3320 return 0;
3321 }
3322 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3323 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3324 "inBytes");
3325 return 0;
3326 }
3327
3328 ScopedByteArrayRW outBytes(env, outArray);
3329 if (outBytes.get() == nullptr) {
3330 return 0;
3331 }
3332 if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3333 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3334 "outBytes");
3335 return 0;
3336 }
3337
3338 JNI_TRACE(
3339 "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3340 "out.length=%zd outOffset=%d",
3341 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3342 outOffset);
3343
3344 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3345 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3346
3347 int outl;
3348 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3349 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3350 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3351 return 0;
3352 }
3353
3354 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3355 inOffset, outl);
3356 return outl;
3357 }
3358
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3359 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3360 jbyteArray outArray, jint outOffset) {
3361 CHECK_ERROR_QUEUE_ON_RETURN;
3362 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3363 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3364
3365 if (ctx == nullptr) {
3366 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3367 return 0;
3368 }
3369
3370 ScopedByteArrayRW outBytes(env, outArray);
3371 if (outBytes.get() == nullptr) {
3372 return 0;
3373 }
3374
3375 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3376
3377 int outl;
3378 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3379 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3380 conscrypt::jniutil::throwBadPaddingException);
3381 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3382 return 0;
3383 }
3384
3385 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3386 return outl;
3387 }
3388
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3389 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3390 CHECK_ERROR_QUEUE_ON_RETURN;
3391 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3392 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3393
3394 if (evpCipher == nullptr) {
3395 conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3396 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3397 return 0;
3398 }
3399
3400 jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3401 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3402 return ivLength;
3403 }
3404
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3405 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3406 CHECK_ERROR_QUEUE_ON_RETURN;
3407 JNI_TRACE("EVP_CIPHER_CTX_new()");
3408
3409 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3410 if (ctx.get() == nullptr) {
3411 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3412 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3413 return 0;
3414 }
3415
3416 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3417 return reinterpret_cast<uintptr_t>(ctx.release());
3418 }
3419
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3420 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3421 CHECK_ERROR_QUEUE_ON_RETURN;
3422 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3423 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3424
3425 if (ctx == nullptr) {
3426 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3427 return 0;
3428 }
3429
3430 jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3431 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3432 return blockSize;
3433 }
3434
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3435 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3436 CHECK_ERROR_QUEUE_ON_RETURN;
3437 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3438 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3439
3440 if (ctx == nullptr) {
3441 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3442 return 0;
3443 }
3444
3445 int buf_len = ctx->buf_len;
3446 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3447 return buf_len;
3448 }
3449
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3450 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3451 CHECK_ERROR_QUEUE_ON_RETURN;
3452 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3453 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3454
3455 if (ctx == nullptr) {
3456 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3457 return 0;
3458 }
3459
3460 bool final_used = ctx->final_used != 0;
3461 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3462 return static_cast<jboolean>(final_used);
3463 }
3464
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3465 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3466 jboolean enablePaddingBool) {
3467 CHECK_ERROR_QUEUE_ON_RETURN;
3468 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3469 jint enablePadding = enablePaddingBool ? 1 : 0;
3470 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3471
3472 if (ctx == nullptr) {
3473 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3474 return;
3475 }
3476
3477 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3478 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3479 }
3480
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3481 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3482 jint keySizeBits) {
3483 CHECK_ERROR_QUEUE_ON_RETURN;
3484 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3485 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3486
3487 if (ctx == nullptr) {
3488 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3489 return;
3490 }
3491
3492 if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3493 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3494 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3495 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3496 return;
3497 }
3498 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3499 }
3500
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3501 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3502 CHECK_ERROR_QUEUE_ON_RETURN;
3503 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3504 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3505
3506 EVP_CIPHER_CTX_free(ctx);
3507 }
3508
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3509 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3510 CHECK_ERROR_QUEUE_ON_RETURN;
3511 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3512 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3513 return reinterpret_cast<jlong>(ctx);
3514 }
3515
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3516 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3517 CHECK_ERROR_QUEUE_ON_RETURN;
3518 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3519 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3520 return reinterpret_cast<jlong>(ctx);
3521 }
3522
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3523 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3524 CHECK_ERROR_QUEUE_ON_RETURN;
3525 const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3526 JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3527 return reinterpret_cast<jlong>(ctx);
3528 }
3529
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3530 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3531 CHECK_ERROR_QUEUE_ON_RETURN;
3532 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3533 JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3534 return reinterpret_cast<jlong>(ctx);
3535 }
3536
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3537 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3538 CHECK_ERROR_QUEUE_ON_RETURN;
3539 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3540 JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3541 return reinterpret_cast<jlong>(ctx);
3542 }
3543
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3544 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3545 CHECK_ERROR_QUEUE_ON_RETURN;
3546 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3547 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3548 if (evpAead == nullptr) {
3549 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3550 return 0;
3551 }
3552 jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3553 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3554 return maxOverhead;
3555 }
3556
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3557 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3558 CHECK_ERROR_QUEUE_ON_RETURN;
3559 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3560 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3561 if (evpAead == nullptr) {
3562 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3563 return 0;
3564 }
3565 jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3566 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3567 return nonceLength;
3568 }
3569
3570 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3571 size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3572 const uint8_t* in, size_t in_len, const uint8_t* ad,
3573 size_t ad_len);
3574
evp_aead_ctx_op_common(JNIEnv * env,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,uint8_t * outBuf,jbyteArray nonceArray,const uint8_t * inBuf,jbyteArray aadArray,evp_aead_ctx_op_func realFunc,jobject inBuffer,jobject outBuffer,jint outRange,jint inRange)3575 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3576 uint8_t* outBuf, jbyteArray nonceArray,
3577 const uint8_t* inBuf, jbyteArray aadArray,
3578 evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange) {
3579 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3580
3581 ScopedByteArrayRO keyBytes(env, keyArray);
3582 if (keyBytes.get() == nullptr) {
3583 return 0;
3584 }
3585
3586 std::unique_ptr<ScopedByteArrayRO> aad;
3587 const uint8_t* aad_chars = nullptr;
3588 size_t aad_chars_size = 0;
3589 if (aadArray != nullptr) {
3590 aad.reset(new ScopedByteArrayRO(env, aadArray));
3591 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3592 if (aad_chars == nullptr) {
3593 return 0;
3594 }
3595 aad_chars_size = aad->size();
3596 }
3597
3598 ScopedByteArrayRO nonceBytes(env, nonceArray);
3599 if (nonceBytes.get() == nullptr) {
3600 return 0;
3601 }
3602
3603 bssl::ScopedEVP_AEAD_CTX aeadCtx;
3604 const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3605 if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3606 static_cast<size_t>(tagLen), nullptr)) {
3607 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3608 "failure initializing AEAD context");
3609 JNI_TRACE(
3610 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3611 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3612 aadArray);
3613 return 0;
3614 }
3615
3616 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3617 size_t actualOutLength;
3618
3619 if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3620 nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3621 aad_chars, aad_chars_size)) {
3622 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3623 return 0;
3624 }
3625
3626 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3627 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3628 aadArray, actualOutLength);
3629 return static_cast<jint>(actualOutLength);
3630 }
3631
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)3632 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3633 jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3634 jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3635 evp_aead_ctx_op_func realFunc) {
3636 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3637 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3638 outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3639
3640
3641 ScopedByteArrayRW outBytes(env, outArray);
3642 if (outBytes.get() == nullptr) {
3643 return 0;
3644 }
3645
3646 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3647 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3648 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3649 inLength, aadArray);
3650 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3651 return 0;
3652 }
3653
3654 ScopedByteArrayRO inBytes(env, inArray);
3655 if (inBytes.get() == nullptr) {
3656 return 0;
3657 }
3658
3659 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3660 JNI_TRACE(
3661 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3662 "invalid",
3663 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3664 inLength, aadArray);
3665 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3666 return 0;
3667 }
3668
3669 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3670 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3671
3672 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3673 aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3674 }
3675
evp_aead_ctx_op_buf(JNIEnv * env,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray,evp_aead_ctx_op_func realFunc)3676 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3677 jobject outBuffer, jbyteArray nonceArray,
3678 jobject inBuffer, jbyteArray aadArray,
3679 evp_aead_ctx_op_func realFunc) {
3680
3681 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3682 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3683 outBuffer, nonceArray, inBuffer, aadArray);
3684
3685 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3686 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3687 "inBuffer is not a direct ByteBuffer");
3688 return 0;
3689 }
3690
3691 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3692 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3693 "outBuffer is not a direct ByteBuffer");
3694 return 0;
3695 }
3696
3697 uint8_t* inBuf;
3698 jint in_limit;
3699 jint in_position;
3700
3701 inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3702 // limit is the index of the first element that should not be read or written
3703 in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3704 // position is the index of the next element to be read or written
3705 in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3706
3707 uint8_t* outBuf;
3708 jint out_limit;
3709 jint out_position;
3710 outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3711 // limit is the index of the first element that should not be read or written
3712 out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3713 // position is the index of the next element to be read or written
3714 out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3715
3716 // Shifting over of ByteBuffer address to start at true position
3717 inBuf += in_position;
3718 outBuf += out_position;
3719
3720 size_t inSize = in_limit - in_position;
3721 uint8_t* outBufEnd = outBuf + out_limit - out_position;
3722 uint8_t* inBufEnd = inBuf + inSize;
3723 std::unique_ptr<uint8_t[]> inCopy;
3724 if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3725 inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3726 if (inCopy.get() == nullptr) {
3727 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3728 return 0;
3729 }
3730 memcpy(inCopy.get(), inBuf, inSize);
3731 inBuf = inCopy.get();
3732 }
3733
3734 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3735 inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3736 }
3737
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)3738 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3739 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3740 jint outOffset, jbyteArray nonceArray,
3741 jbyteArray inArray, jint inOffset, jint inLength,
3742 jbyteArray aadArray) {
3743 CHECK_ERROR_QUEUE_ON_RETURN;
3744 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3745 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3746 }
3747
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)3748 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3749 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3750 jint outOffset, jbyteArray nonceArray,
3751 jbyteArray inArray, jint inOffset, jint inLength,
3752 jbyteArray aadArray) {
3753 CHECK_ERROR_QUEUE_ON_RETURN;
3754 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3755 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3756 }
3757
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3758 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3759 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3760 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3761 CHECK_ERROR_QUEUE_ON_RETURN;
3762 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3763 inBuffer, aadArray, EVP_AEAD_CTX_seal);
3764 }
3765
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3766 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3767 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3768 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3769 CHECK_ERROR_QUEUE_ON_RETURN;
3770 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3771 inBuffer, aadArray, EVP_AEAD_CTX_open);
3772 }
3773
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)3774 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
3775 CHECK_ERROR_QUEUE_ON_RETURN;
3776 JNI_TRACE("CMAC_CTX_new");
3777 auto cmacCtx = CMAC_CTX_new();
3778 if (cmacCtx == nullptr) {
3779 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
3780 return 0;
3781 }
3782
3783 return reinterpret_cast<jlong>(cmacCtx);
3784 }
3785
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)3786 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
3787 CHECK_ERROR_QUEUE_ON_RETURN;
3788 CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
3789 JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
3790 if (cmacCtx == nullptr) {
3791 conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
3792 return;
3793 }
3794 CMAC_CTX_free(cmacCtx);
3795 }
3796
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)3797 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
3798 CHECK_ERROR_QUEUE_ON_RETURN;
3799 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3800 JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
3801 if (cmacCtx == nullptr) {
3802 return;
3803 }
3804 ScopedByteArrayRO keyBytes(env, keyArray);
3805 if (keyBytes.get() == nullptr) {
3806 return;
3807 }
3808
3809 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3810
3811 const EVP_CIPHER *cipher;
3812 switch(keyBytes.size()) {
3813 case 16:
3814 cipher = EVP_aes_128_cbc();
3815 break;
3816 case 24:
3817 cipher = EVP_aes_192_cbc();
3818 break;
3819 case 32:
3820 cipher = EVP_aes_256_cbc();
3821 break;
3822 default:
3823 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3824 "CMAC_Init: Unsupported key length");
3825 return;
3826 }
3827
3828 if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
3829 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
3830 JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
3831 return;
3832 }
3833 }
3834
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)3835 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
3836 int inLength) {
3837 CHECK_ERROR_QUEUE_ON_RETURN;
3838 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3839 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3840 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
3841
3842 if (cmacCtx == nullptr) {
3843 return;
3844 }
3845
3846 if (p == nullptr) {
3847 conscrypt::jniutil::throwNullPointerException(env, nullptr);
3848 return;
3849 }
3850
3851 if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
3852 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
3853 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
3854 return;
3855 }
3856 }
3857
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3858 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
3859 jint inOffset, jint inLength) {
3860 CHECK_ERROR_QUEUE_ON_RETURN;
3861 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3862 JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
3863
3864 if (cmacCtx == nullptr) {
3865 return;
3866 }
3867
3868 ScopedByteArrayRO inBytes(env, inArray);
3869 if (inBytes.get() == nullptr) {
3870 return;
3871 }
3872
3873 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3874 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3875 "inBytes");
3876 return;
3877 }
3878
3879 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
3880
3881 if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
3882 JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
3883 inLength);
3884 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
3885 return;
3886 }
3887 }
3888
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)3889 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
3890 CHECK_ERROR_QUEUE_ON_RETURN;
3891 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3892 JNI_TRACE("CMAC_Final(%p)", cmacCtx);
3893
3894 if (cmacCtx == nullptr) {
3895 return nullptr;
3896 }
3897
3898 uint8_t result[EVP_MAX_MD_SIZE];
3899 size_t len;
3900 if (!CMAC_Final(cmacCtx, result, &len)) {
3901 JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
3902 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
3903 return nullptr;
3904 }
3905
3906 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
3907 if (resultArray.get() == nullptr) {
3908 return nullptr;
3909 }
3910 ScopedByteArrayRW resultBytes(env, resultArray.get());
3911 if (resultBytes.get() == nullptr) {
3912 return nullptr;
3913 }
3914 memcpy(resultBytes.get(), result, len);
3915 return resultArray.release();
3916 }
3917
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)3918 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
3919 CHECK_ERROR_QUEUE_ON_RETURN;
3920 JNI_TRACE("HMAC_CTX_new");
3921 auto hmacCtx = new HMAC_CTX;
3922 if (hmacCtx == nullptr) {
3923 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
3924 return 0;
3925 }
3926
3927 HMAC_CTX_init(hmacCtx);
3928 return reinterpret_cast<jlong>(hmacCtx);
3929 }
3930
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)3931 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
3932 CHECK_ERROR_QUEUE_ON_RETURN;
3933 HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
3934 JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
3935 if (hmacCtx == nullptr) {
3936 conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
3937 return;
3938 }
3939 HMAC_CTX_cleanup(hmacCtx);
3940 delete hmacCtx;
3941 }
3942
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)3943 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
3944 jobject evpMdRef) {
3945 CHECK_ERROR_QUEUE_ON_RETURN;
3946 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3947 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3948 JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
3949 if (hmacCtx == nullptr) {
3950 return;
3951 }
3952 ScopedByteArrayRO keyBytes(env, keyArray);
3953 if (keyBytes.get() == nullptr) {
3954 return;
3955 }
3956
3957 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3958 if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
3959 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
3960 JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
3961 return;
3962 }
3963 }
3964
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)3965 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
3966 int inLength) {
3967 CHECK_ERROR_QUEUE_ON_RETURN;
3968 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3969 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3970 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
3971
3972 if (hmacCtx == nullptr) {
3973 return;
3974 }
3975
3976 if (p == nullptr) {
3977 conscrypt::jniutil::throwNullPointerException(env, nullptr);
3978 return;
3979 }
3980
3981 if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
3982 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
3983 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
3984 return;
3985 }
3986 }
3987
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3988 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
3989 jint inOffset, jint inLength) {
3990 CHECK_ERROR_QUEUE_ON_RETURN;
3991 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3992 JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
3993
3994 if (hmacCtx == nullptr) {
3995 return;
3996 }
3997
3998 ScopedByteArrayRO inBytes(env, inArray);
3999 if (inBytes.get() == nullptr) {
4000 return;
4001 }
4002
4003 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4004 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4005 "inBytes");
4006 return;
4007 }
4008
4009 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4010 if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4011 JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4012 inLength);
4013 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4014 return;
4015 }
4016 }
4017
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4018 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4019 CHECK_ERROR_QUEUE_ON_RETURN;
4020 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4021 JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4022
4023 if (hmacCtx == nullptr) {
4024 return nullptr;
4025 }
4026
4027 uint8_t result[EVP_MAX_MD_SIZE];
4028 unsigned len;
4029 if (!HMAC_Final(hmacCtx, result, &len)) {
4030 JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4031 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4032 return nullptr;
4033 }
4034
4035 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4036 if (resultArray.get() == nullptr) {
4037 return nullptr;
4038 }
4039 ScopedByteArrayRW resultBytes(env, resultArray.get());
4040 if (resultBytes.get() == nullptr) {
4041 return nullptr;
4042 }
4043 memcpy(resultBytes.get(), result, len);
4044 return resultArray.release();
4045 }
4046
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4047 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4048 CHECK_ERROR_QUEUE_ON_RETURN;
4049 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4050
4051 ScopedByteArrayRW outputBytes(env, output);
4052 if (outputBytes.get() == nullptr) {
4053 return;
4054 }
4055
4056 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4057 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4058 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4059 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4060 return;
4061 }
4062
4063 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4064 }
4065
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4066 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4067 /*
4068 * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4069 * Just make a buffer that's large enough here. The documentation recommends
4070 * 80 characters.
4071 */
4072 char output[128];
4073 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4074 if (ret < 0) {
4075 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4076 return nullptr;
4077 } else if (size_t(ret) >= sizeof(output)) {
4078 conscrypt::jniutil::throwRuntimeException(env,
4079 "ASN1_OBJECT_to_OID_string buffer too small");
4080 return nullptr;
4081 }
4082
4083 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4084 return env->NewStringUTF(output);
4085 }
4086
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4087 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4088 jboolean isFinite) {
4089 CHECK_ERROR_QUEUE_ON_RETURN;
4090 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4091
4092 if (streamObj == nullptr) {
4093 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4094 return 0;
4095 }
4096
4097 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4098 if (bio.get() == nullptr) {
4099 return 0;
4100 }
4101
4102 bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4103
4104 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4105 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4106 }
4107
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4108 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4109 CHECK_ERROR_QUEUE_ON_RETURN;
4110 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4111
4112 if (streamObj == nullptr) {
4113 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4114 return 0;
4115 }
4116
4117 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4118 if (bio.get() == nullptr) {
4119 return 0;
4120 }
4121
4122 bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4123
4124 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4125 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4126 }
4127
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4128 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4129 CHECK_ERROR_QUEUE_ON_RETURN;
4130 BIO* bio = to_BIO(env, bioRef);
4131 JNI_TRACE("BIO_free_all(%p)", bio);
4132
4133 if (bio == nullptr) {
4134 return;
4135 }
4136
4137 BIO_free_all(bio);
4138 }
4139
4140 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4141 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4142 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4143
4144 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4145 if (buffer.get() == nullptr) {
4146 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4147 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4148 return nullptr;
4149 }
4150
4151 /* Don't interpret the string. */
4152 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4153
4154 /* Write in given format and null terminate. */
4155 X509_NAME_print_ex(buffer.get(), name, 0, flags);
4156 BIO_write(buffer.get(), "\0", 1);
4157
4158 char* tmp;
4159 BIO_get_mem_data(buffer.get(), &tmp);
4160 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4161 return env->NewStringUTF(tmp);
4162 }
4163
4164 /**
4165 * Converts GENERAL_NAME items to the output format expected in
4166 * X509Certificate#getSubjectAlternativeNames and
4167 * X509Certificate#getIssuerAlternativeNames return.
4168 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4169 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4170 switch (gen->type) {
4171 case GEN_EMAIL:
4172 case GEN_DNS:
4173 case GEN_URI: {
4174 // This must be a valid IA5String and must not contain NULs.
4175 // BoringSSL does not currently enforce the former (see
4176 // https://crbug.com/boringssl/427). The latter was historically an
4177 // issue for parsers that truncate at NUL.
4178 const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4179 ssize_t len = ASN1_STRING_length(gen->d.ia5);
4180 std::vector<jchar> jchars;
4181 jchars.reserve(len);
4182 for (ssize_t i = 0; i < len; i++) {
4183 if (data[i] == 0 || data[i] > 127) {
4184 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4185 return nullptr;
4186 }
4187 // Converting ASCII to UTF-16 is the identity function.
4188 jchars.push_back(data[i]);
4189 }
4190 JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4191 return env->NewString(jchars.data(), jchars.size());
4192 }
4193 case GEN_DIRNAME:
4194 /* Write in RFC 2253 format */
4195 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4196 case GEN_IPADD: {
4197 #ifdef _WIN32
4198 void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4199 #else
4200 const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4201 #endif
4202 if (gen->d.ip->length == 4) {
4203 // IPv4
4204 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4205 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4206 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4207 return env->NewStringUTF(buffer.get());
4208 } else {
4209 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4210 strerror(errno));
4211 }
4212 } else if (gen->d.ip->length == 16) {
4213 // IPv6
4214 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4215 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4216 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4217 return env->NewStringUTF(buffer.get());
4218 } else {
4219 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4220 strerror(errno));
4221 }
4222 }
4223
4224 /* Invalid IP encodings are pruned out without throwing an exception. */
4225 return nullptr;
4226 }
4227 case GEN_RID:
4228 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4229 case GEN_OTHERNAME:
4230 case GEN_X400:
4231 default:
4232 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4233 }
4234
4235 return nullptr;
4236 }
4237
4238 #define GN_STACK_SUBJECT_ALT_NAME 1
4239 #define GN_STACK_ISSUER_ALT_NAME 2
4240
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4241 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4242 CONSCRYPT_UNUSED jobject holder,
4243 jint type) {
4244 CHECK_ERROR_QUEUE_ON_RETURN;
4245 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4246 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4247
4248 if (x509 == nullptr) {
4249 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4250 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4251 return nullptr;
4252 }
4253
4254 bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4255 if (type == GN_STACK_SUBJECT_ALT_NAME) {
4256 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4257 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4258 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4259 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4260 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4261 } else {
4262 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4263 return nullptr;
4264 }
4265 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4266 // |ERR_clear_error|, and throw CertificateParsingException.
4267 if (gn_stack == nullptr) {
4268 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4269 ERR_clear_error();
4270 return nullptr;
4271 }
4272
4273 int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4274 if (count <= 0) {
4275 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4276 return nullptr;
4277 }
4278
4279 /*
4280 * Keep track of how many originally so we can ignore any invalid
4281 * values later.
4282 */
4283 const int origCount = count;
4284
4285 ScopedLocalRef<jobjectArray> joa(
4286 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4287 for (int i = 0, j = 0; i < origCount; i++, j++) {
4288 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4289 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4290 if (env->ExceptionCheck()) {
4291 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4292 x509, type);
4293 return nullptr;
4294 }
4295
4296 /*
4297 * If it's nullptr, we'll have to skip this, reduce the number of total
4298 * entries, and fix up the array later.
4299 */
4300 if (val.get() == nullptr) {
4301 j--;
4302 count--;
4303 continue;
4304 }
4305
4306 ScopedLocalRef<jobjectArray> item(
4307 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4308
4309 ScopedLocalRef<jobject> parsedType(
4310 env,
4311 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4312 conscrypt::jniutil::integer_valueOfMethod, gen->type));
4313 env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4314 env->SetObjectArrayElement(item.get(), 1, val.get());
4315
4316 env->SetObjectArrayElement(joa.get(), j, item.get());
4317 }
4318
4319 if (count == 0) {
4320 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4321 x509, type, origCount);
4322 joa.reset(nullptr);
4323 } else if (origCount != count) {
4324 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4325 count);
4326
4327 ScopedLocalRef<jobjectArray> joa_copy(
4328 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4329
4330 for (int i = 0; i < count; i++) {
4331 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4332 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4333 }
4334
4335 joa.reset(joa_copy.release());
4336 }
4337
4338 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4339 return joa.release();
4340 }
4341
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4342 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4343 CONSCRYPT_UNUSED jobject holder) {
4344 CHECK_ERROR_QUEUE_ON_RETURN;
4345 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4346 JNI_TRACE("X509_get_notBefore(%p)", x509);
4347
4348 if (x509 == nullptr) {
4349 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4350 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4351 return 0;
4352 }
4353
4354 ASN1_TIME* notBefore = X509_get_notBefore(x509);
4355 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4356 return reinterpret_cast<uintptr_t>(notBefore);
4357 }
4358
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4359 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4360 CONSCRYPT_UNUSED jobject holder) {
4361 CHECK_ERROR_QUEUE_ON_RETURN;
4362 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4363 JNI_TRACE("X509_get_notAfter(%p)", x509);
4364
4365 if (x509 == nullptr) {
4366 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4367 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4368 return 0;
4369 }
4370
4371 ASN1_TIME* notAfter = X509_get_notAfter(x509);
4372 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4373 return reinterpret_cast<uintptr_t>(notAfter);
4374 }
4375
4376 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4377 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4378 CONSCRYPT_UNUSED jobject holder) {
4379 CHECK_ERROR_QUEUE_ON_RETURN;
4380 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4381 JNI_TRACE("X509_get_version(%p)", x509);
4382
4383 if (x509 == nullptr) {
4384 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4385 JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
4386 return 0;
4387 }
4388
4389 // NOLINTNEXTLINE(runtime/int)
4390 long version = X509_get_version(x509);
4391 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4392 return version;
4393 }
4394
4395 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4396 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4397 const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4398 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4399
4400 if (x509Type == nullptr) {
4401 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4402 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4403 return nullptr;
4404 }
4405
4406 const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4407 bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4408 if (serialBn.get() == nullptr) {
4409 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4410 return nullptr;
4411 }
4412
4413 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4414 if (env->ExceptionCheck()) {
4415 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4416 return nullptr;
4417 }
4418
4419 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4420 return serialArray.release();
4421 }
4422
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4423 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4424 CONSCRYPT_UNUSED jobject holder) {
4425 CHECK_ERROR_QUEUE_ON_RETURN;
4426 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4427 JNI_TRACE("X509_get_serialNumber(%p)", x509);
4428
4429 if (x509 == nullptr) {
4430 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4431 JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
4432 return nullptr;
4433 }
4434 return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4435 }
4436
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4437 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
4438 jlong x509RevokedRef) {
4439 CHECK_ERROR_QUEUE_ON_RETURN;
4440 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4441 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4442
4443 if (revoked == nullptr) {
4444 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4445 JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
4446 return 0;
4447 }
4448 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
4449 }
4450
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4451 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
4452 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4453 CHECK_ERROR_QUEUE_ON_RETURN;
4454 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4455 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4456 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4457
4458 if (pkey == nullptr) {
4459 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4460 return;
4461 }
4462
4463 if (x509 == nullptr) {
4464 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4465 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4466 return;
4467 }
4468
4469 if (X509_verify(x509, pkey) != 1) {
4470 conscrypt::jniutil::throwExceptionFromBoringSSLError(
4471 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
4472 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4473 return;
4474 }
4475 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4476 }
4477
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4478 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
4479 CONSCRYPT_UNUSED jobject holder) {
4480 CHECK_ERROR_QUEUE_ON_RETURN;
4481 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4482 JNI_TRACE("get_X509_tbs_cert(%p)", x509);
4483 // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
4484 return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
4485 }
4486
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)4487 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
4488 CONSCRYPT_UNUSED jobject holder,
4489 jstring oidString) {
4490 CHECK_ERROR_QUEUE_ON_RETURN;
4491 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4492 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
4493
4494 if (x509 == nullptr) {
4495 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4496 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
4497 return nullptr;
4498 }
4499
4500 bssl::UniquePtr<X509> copy(X509_dup(x509));
4501 if (copy == nullptr) {
4502 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
4503 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
4504 return nullptr;
4505 }
4506
4507 ScopedUtfChars oid(env, oidString);
4508 if (oid.c_str() == nullptr) {
4509 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
4510 return nullptr;
4511 }
4512
4513 bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
4514 if (obj.get() == nullptr) {
4515 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
4516 oid.c_str());
4517 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4518 "Invalid OID.");
4519 ERR_clear_error();
4520 return nullptr;
4521 }
4522
4523 int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
4524 if (extIndex == -1) {
4525 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
4526 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4527 "Extension not found.");
4528 return nullptr;
4529 }
4530
4531 // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
4532 // cached encoding.
4533 X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
4534 return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
4535 }
4536
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4537 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
4538 CONSCRYPT_UNUSED jobject holder) {
4539 CHECK_ERROR_QUEUE_ON_RETURN;
4540 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4541 JNI_TRACE("get_X509_ex_flags(%p)", x509);
4542
4543 if (x509 == nullptr) {
4544 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4545 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4546 return 0;
4547 }
4548
4549 uint32_t flags = X509_get_extension_flags(x509);
4550 // X509_get_extension_flags sometimes leaves values in the error queue. See
4551 // https://crbug.com/boringssl/382.
4552 //
4553 // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
4554 // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
4555 // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
4556 // this JNI call to EXFLAG_CRITICAL.
4557 ERR_clear_error();
4558 return flags;
4559 }
4560
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)4561 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
4562 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
4563 CONSCRYPT_UNUSED jobject holder2) {
4564 CHECK_ERROR_QUEUE_ON_RETURN;
4565 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4566 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4567 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4568
4569 if (x509_1 == nullptr) {
4570 conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
4571 JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
4572 return 0;
4573 }
4574 if (x509_2 == nullptr) {
4575 conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
4576 JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
4577 return 0;
4578 }
4579 int ret = X509_check_issued(x509_1, x509_2);
4580 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4581 return ret;
4582 }
4583
get_X509_signature(X509 * x509)4584 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
4585 const ASN1_BIT_STRING* signature;
4586 X509_get0_signature(&signature, nullptr, x509);
4587 return signature;
4588 }
4589
get_X509_CRL_signature(X509_CRL * crl)4590 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
4591 const ASN1_BIT_STRING* signature;
4592 X509_CRL_get0_signature(crl, &signature, nullptr);
4593 return signature;
4594 }
4595
4596 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))4597 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
4598 const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
4599 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4600
4601 if (x509Type == nullptr) {
4602 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4603 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4604 return nullptr;
4605 }
4606
4607 const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
4608
4609 ScopedLocalRef<jbyteArray> signatureArray(env,
4610 env->NewByteArray(ASN1_STRING_length(signature)));
4611 if (env->ExceptionCheck()) {
4612 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4613 return nullptr;
4614 }
4615
4616 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4617 if (signatureBytes.get() == nullptr) {
4618 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4619 return nullptr;
4620 }
4621
4622 memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
4623
4624 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4625 ASN1_STRING_length(signature));
4626 return signatureArray.release();
4627 }
4628
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4629 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
4630 CONSCRYPT_UNUSED jobject holder) {
4631 CHECK_ERROR_QUEUE_ON_RETURN;
4632 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4633 JNI_TRACE("get_X509_signature(%p)", x509);
4634
4635 if (x509 == nullptr) {
4636 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4637 JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
4638 return nullptr;
4639 }
4640 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4641 }
4642
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4643 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
4644 CONSCRYPT_UNUSED jobject holder) {
4645 CHECK_ERROR_QUEUE_ON_RETURN;
4646 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4647 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4648
4649 if (crl == nullptr) {
4650 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4651 JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
4652 return nullptr;
4653 }
4654 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4655 }
4656
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)4657 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
4658 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
4659 CONSCRYPT_UNUSED jobject holder2) {
4660 CHECK_ERROR_QUEUE_ON_RETURN;
4661 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4662 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4663 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4664
4665 if (x509crl == nullptr) {
4666 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4667 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4668 return 0;
4669 } else if (x509 == nullptr) {
4670 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4671 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4672 return 0;
4673 }
4674
4675 X509_REVOKED* revoked = nullptr;
4676 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4677 if (ret == 0) {
4678 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4679 return 0;
4680 }
4681
4682 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4683 return reinterpret_cast<uintptr_t>(revoked);
4684 }
4685
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)4686 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
4687 CONSCRYPT_UNUSED jobject holder,
4688 jbyteArray serialArray) {
4689 CHECK_ERROR_QUEUE_ON_RETURN;
4690 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4691 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4692
4693 if (x509crl == nullptr) {
4694 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4695 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4696 return 0;
4697 }
4698
4699 bssl::UniquePtr<BIGNUM> serialBn(BN_new());
4700 if (serialBn.get() == nullptr) {
4701 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4702 return 0;
4703 }
4704
4705 BIGNUM* serialBare = serialBn.get();
4706 if (!arrayToBignum(env, serialArray, &serialBare)) {
4707 if (!env->ExceptionCheck()) {
4708 conscrypt::jniutil::throwNullPointerException(env, "serial == null");
4709 }
4710 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4711 return 0;
4712 }
4713
4714 bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
4715 if (serialInteger.get() == nullptr) {
4716 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4717 return 0;
4718 }
4719
4720 X509_REVOKED* revoked = nullptr;
4721 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4722 if (ret == 0) {
4723 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4724 return 0;
4725 }
4726
4727 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4728 return reinterpret_cast<uintptr_t>(revoked);
4729 }
4730
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4731 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
4732 CONSCRYPT_UNUSED jobject holder) {
4733 CHECK_ERROR_QUEUE_ON_RETURN;
4734 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4735 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4736
4737 if (crl == nullptr) {
4738 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4739 JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
4740 return nullptr;
4741 }
4742
4743 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4744 if (stack == nullptr) {
4745 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4746 return nullptr;
4747 }
4748
4749 size_t size = sk_X509_REVOKED_num(stack);
4750
4751 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
4752 ScopedLongArrayRW revoked(env, revokedArray.get());
4753 for (size_t i = 0; i < size; i++) {
4754 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4755 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4756 }
4757
4758 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
4759 return revokedArray.release();
4760 }
4761
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4762 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
4763 CONSCRYPT_UNUSED jobject holder) {
4764 CHECK_ERROR_QUEUE_ON_RETURN;
4765 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4766 JNI_TRACE("i2d_X509_CRL(%p)", crl);
4767
4768 if (crl == nullptr) {
4769 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4770 JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
4771 return nullptr;
4772 }
4773 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
4774 }
4775
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4776 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
4777 CONSCRYPT_UNUSED jobject holder) {
4778 CHECK_ERROR_QUEUE_ON_RETURN;
4779 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4780 JNI_TRACE("X509_CRL_free(%p)", crl);
4781
4782 if (crl == nullptr) {
4783 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4784 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4785 return;
4786 }
4787
4788 X509_CRL_free(crl);
4789 }
4790
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4791 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
4792 CONSCRYPT_UNUSED jobject holder) {
4793 CHECK_ERROR_QUEUE_ON_RETURN;
4794 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4795 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4796 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4797
4798 if (bio == nullptr) {
4799 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4800 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4801 return;
4802 }
4803
4804 if (crl == nullptr) {
4805 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4806 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4807 return;
4808 }
4809
4810 if (!X509_CRL_print(bio, crl)) {
4811 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
4812 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4813 return;
4814 }
4815 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4816 }
4817
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4818 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
4819 CONSCRYPT_UNUSED jobject holder) {
4820 CHECK_ERROR_QUEUE_ON_RETURN;
4821 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4822 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4823
4824 if (crl == nullptr) {
4825 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4826 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
4827 return nullptr;
4828 }
4829
4830 const X509_ALGOR* sig_alg;
4831 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4832 const ASN1_OBJECT* oid;
4833 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
4834 return ASN1_OBJECT_to_OID_string(env, oid);
4835 }
4836
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)4837 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
4838 int param_type;
4839 const void* param_value;
4840 X509_ALGOR_get0(nullptr, ¶m_type, ¶m_value, algor);
4841
4842 if (param_type == V_ASN1_UNDEF) {
4843 JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
4844 return nullptr;
4845 }
4846
4847 // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
4848 // recreate it from the returned components.
4849 bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
4850 if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
4851 conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
4852 return nullptr;
4853 }
4854
4855 return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
4856 }
4857
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4858 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
4859 CONSCRYPT_UNUSED jobject holder) {
4860 CHECK_ERROR_QUEUE_ON_RETURN;
4861 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4862 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4863
4864 if (crl == nullptr) {
4865 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4866 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4867 return nullptr;
4868 }
4869
4870 const X509_ALGOR* sig_alg;
4871 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4872 return get_X509_ALGOR_parameter(env, sig_alg);
4873 }
4874
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4875 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
4876 CONSCRYPT_UNUSED jobject holder) {
4877 CHECK_ERROR_QUEUE_ON_RETURN;
4878 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4879
4880 if (crl == nullptr) {
4881 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4882 JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
4883 return nullptr;
4884 }
4885 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4886 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
4887 }
4888
4889 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4890 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
4891 CONSCRYPT_UNUSED jobject holder) {
4892 CHECK_ERROR_QUEUE_ON_RETURN;
4893 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4894 JNI_TRACE("X509_CRL_get_version(%p)", crl);
4895
4896 if (crl == nullptr) {
4897 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4898 JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
4899 return 0;
4900 }
4901 // NOLINTNEXTLINE(runtime/int)
4902 long version = X509_CRL_get_version(crl);
4903 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4904 return version;
4905 }
4906
4907 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4908 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)4909 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
4910 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4911
4912 if (x509Type == nullptr) {
4913 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4914 return nullptr;
4915 }
4916
4917 ScopedUtfChars oid(env, oidString);
4918 if (oid.c_str() == nullptr) {
4919 return nullptr;
4920 }
4921
4922 bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
4923 if (asn1.get() == nullptr) {
4924 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4925 ERR_clear_error();
4926 return nullptr;
4927 }
4928
4929 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4930 if (extIndex == -1) {
4931 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4932 return nullptr;
4933 }
4934
4935 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4936 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4937 return ext;
4938 }
4939
4940 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4941 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)4942 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
4943 X509_EXTENSION* ext =
4944 X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
4945 if (ext == nullptr) {
4946 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4947 return nullptr;
4948 }
4949
4950 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
4951 X509_EXTENSION_get_data(ext));
4952 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
4953 i2d_ASN1_OCTET_STRING);
4954 }
4955
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)4956 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
4957 CONSCRYPT_UNUSED jobject holder, jstring oid) {
4958 CHECK_ERROR_QUEUE_ON_RETURN;
4959 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4960 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4961
4962 if (crl == nullptr) {
4963 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4964 JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
4965 return 0;
4966 }
4967 X509_EXTENSION* ext =
4968 X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
4969 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4970 return reinterpret_cast<uintptr_t>(ext);
4971 }
4972
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)4973 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4974 jstring oid) {
4975 CHECK_ERROR_QUEUE_ON_RETURN;
4976 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4977 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4978 X509_EXTENSION* ext =
4979 X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
4980 env, revoked, oid);
4981 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4982 return reinterpret_cast<uintptr_t>(ext);
4983 }
4984
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)4985 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4986 CHECK_ERROR_QUEUE_ON_RETURN;
4987 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4988 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4989
4990 if (revoked == nullptr) {
4991 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4992 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4993 return 0;
4994 }
4995
4996 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4997 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4998 return reinterpret_cast<uintptr_t>(dup);
4999 }
5000
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5001 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5002 jlong x509RevokedRef) {
5003 CHECK_ERROR_QUEUE_ON_RETURN;
5004 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5005 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5006
5007 if (revoked == nullptr) {
5008 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5009 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5010 return 0;
5011 }
5012
5013 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5014 X509_REVOKED_get0_revocationDate(revoked));
5015 return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5016 }
5017
5018 #ifdef __GNUC__
5019 #pragma GCC diagnostic push
5020 #pragma GCC diagnostic ignored "-Wwrite-strings"
5021 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5022 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5023 jlong x509RevokedRef) {
5024 CHECK_ERROR_QUEUE_ON_RETURN;
5025 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5026 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5027 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5028
5029 if (bio == nullptr) {
5030 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5031 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5032 return;
5033 }
5034
5035 if (revoked == nullptr) {
5036 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5037 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5038 return;
5039 }
5040
5041 BIO_printf(bio, "Serial Number: ");
5042 i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5043 BIO_printf(bio, "\nRevocation Date: ");
5044 ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5045 BIO_printf(bio, "\n");
5046 // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5047 // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5048 X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5049 0);
5050 }
5051 #ifndef _WIN32
5052 #pragma GCC diagnostic pop
5053 #endif
5054
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5055 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5056 CONSCRYPT_UNUSED jobject holder) {
5057 CHECK_ERROR_QUEUE_ON_RETURN;
5058 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5059 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5060
5061 if (crl == nullptr) {
5062 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5063 JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5064 return nullptr;
5065 }
5066 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5067 }
5068
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5069 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5070 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5071 CHECK_ERROR_QUEUE_ON_RETURN;
5072 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5073 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5074 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5075
5076 if (pkey == nullptr) {
5077 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5078 return;
5079 }
5080
5081 if (crl == nullptr) {
5082 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5083 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5084 return;
5085 }
5086
5087 if (X509_CRL_verify(crl, pkey) != 1) {
5088 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5089 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5090 return;
5091 }
5092 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5093 }
5094
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5095 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5096 CONSCRYPT_UNUSED jobject holder) {
5097 CHECK_ERROR_QUEUE_ON_RETURN;
5098 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5099 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5100
5101 if (crl == nullptr) {
5102 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5103 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5104 return 0;
5105 }
5106
5107 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5108 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5109 return reinterpret_cast<uintptr_t>(lastUpdate);
5110 }
5111
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5112 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5113 CONSCRYPT_UNUSED jobject holder) {
5114 CHECK_ERROR_QUEUE_ON_RETURN;
5115 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5116 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5117
5118 if (crl == nullptr) {
5119 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5120 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5121 return 0;
5122 }
5123
5124 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5125 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5126 return reinterpret_cast<uintptr_t>(nextUpdate);
5127 }
5128
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5129 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5130 CHECK_ERROR_QUEUE_ON_RETURN;
5131 X509_REVOKED* x509Revoked =
5132 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5133 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5134 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5135 }
5136
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5137 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5138 CHECK_ERROR_QUEUE_ON_RETURN;
5139 X509_EXTENSION* ext =
5140 reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5141
5142 if (ext == nullptr) {
5143 conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5144 return 0;
5145 }
5146
5147 return X509_supported_extension(ext);
5148 }
5149
decimal_to_integer(const char * data,size_t len,int * out)5150 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5151 int ret = 0;
5152 for (size_t i = 0; i < len; i++) {
5153 ret *= 10;
5154 if (data[i] < '0' || data[i] > '9') {
5155 return false;
5156 }
5157 ret += data[i] - '0';
5158 }
5159 *out = ret;
5160 return true;
5161 }
5162
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5163 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5164 jobject calendar) {
5165 CHECK_ERROR_QUEUE_ON_RETURN;
5166 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5167 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5168
5169 if (asn1Time == nullptr) {
5170 conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5171 return;
5172 }
5173
5174 if (!ASN1_TIME_check(asn1Time)) {
5175 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5176 return;
5177 }
5178
5179 bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5180 if (gen.get() == nullptr) {
5181 conscrypt::jniutil::throwParsingException(env,
5182 "ASN1_TIME_to_generalizedtime returned null");
5183 return;
5184 }
5185
5186 if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5187 conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5188 return;
5189 }
5190
5191 int year, mon, mday, hour, min, sec;
5192 const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5193 if (!decimal_to_integer(data, 4, &year) ||
5194 !decimal_to_integer(data + 4, 2, &mon) ||
5195 !decimal_to_integer(data + 6, 2, &mday) ||
5196 !decimal_to_integer(data + 8, 2, &hour) ||
5197 !decimal_to_integer(data + 10, 2, &min) ||
5198 !decimal_to_integer(data + 12, 2, &sec)) {
5199 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5200 return;
5201 }
5202
5203 env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5204 min, sec);
5205 }
5206
5207 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5208 // functions so that they can be freed properly when finished. This struct owns
5209 // all objects pointed to by its members.
5210 struct CbsHandle {
5211 // A pointer to the CBS.
5212 std::unique_ptr<CBS> cbs;
5213 // A pointer to the data held by the CBS. If the data held by the CBS
5214 // is owned by a different CbsHandle, data will be null.
5215 std::unique_ptr<unsigned char[]> data;
5216 };
5217
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5218 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5219 CHECK_ERROR_QUEUE_ON_RETURN;
5220 JNI_TRACE("asn1_read_init(%p)", data);
5221
5222 ScopedByteArrayRO bytes(env, data);
5223 if (bytes.get() == nullptr) {
5224 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5225 return 0;
5226 }
5227
5228 std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5229 cbs->data.reset(new unsigned char[bytes.size()]);
5230 memcpy(cbs->data.get(), bytes.get(), bytes.size());
5231
5232 cbs->cbs.reset(new CBS());
5233 CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5234 JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5235 return reinterpret_cast<uintptr_t>(cbs.release());
5236 }
5237
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5238 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5239 CHECK_ERROR_QUEUE_ON_RETURN;
5240 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5241 JNI_TRACE("asn1_read_sequence(%p)", cbs);
5242
5243 std::unique_ptr<CbsHandle> seq(new CbsHandle());
5244 seq->cbs.reset(new CBS());
5245 if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5246 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5247 return 0;
5248 }
5249 JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5250 return reinterpret_cast<uintptr_t>(seq.release());
5251 }
5252
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5253 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5254 jlong cbsRef, jint tag) {
5255 CHECK_ERROR_QUEUE_ON_RETURN;
5256 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5257 JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5258
5259 int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5260 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5261 JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5262 return result ? JNI_TRUE : JNI_FALSE;
5263 }
5264
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5265 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5266 CHECK_ERROR_QUEUE_ON_RETURN;
5267 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5268 JNI_TRACE("asn1_read_tagged(%p)", cbs);
5269
5270 std::unique_ptr<CbsHandle> tag(new CbsHandle());
5271 tag->cbs.reset(new CBS());
5272 if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5273 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5274 return 0;
5275 }
5276 JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5277 return reinterpret_cast<uintptr_t>(tag.release());
5278 }
5279
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5280 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5281 CHECK_ERROR_QUEUE_ON_RETURN;
5282 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5283 JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5284
5285 std::unique_ptr<CBS> str(new CBS());
5286 if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5287 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5288 return 0;
5289 }
5290 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5291 if (out.get() == nullptr) {
5292 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5293 return 0;
5294 }
5295 ScopedByteArrayRW outBytes(env, out.get());
5296 if (outBytes.get() == nullptr) {
5297 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5298 return 0;
5299 }
5300 memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5301 JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5302 return out.release();
5303 }
5304
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5305 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5306 CHECK_ERROR_QUEUE_ON_RETURN;
5307 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5308 JNI_TRACE("asn1_read_uint64(%p)", cbs);
5309
5310 // NOLINTNEXTLINE(runtime/int)
5311 uint64_t value;
5312 if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5313 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5314 return 0;
5315 }
5316 return value;
5317 }
5318
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5319 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5320 CHECK_ERROR_QUEUE_ON_RETURN;
5321 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5322 JNI_TRACE("asn1_read_null(%p)", cbs);
5323
5324 CBS null_holder;
5325 if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5326 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5327 }
5328 }
5329
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5330 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5331 CHECK_ERROR_QUEUE_ON_RETURN;
5332 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5333 JNI_TRACE("asn1_read_oid(%p)", cbs);
5334
5335 CBS oid_cbs;
5336 if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5337 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5338 return nullptr;
5339 }
5340 int nid = OBJ_cbs2nid(&oid_cbs);
5341 if (nid == NID_undef) {
5342 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5343 return nullptr;
5344 }
5345 const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5346 if (obj == nullptr) {
5347 conscrypt::jniutil::throwIOException(env,
5348 "Error reading ASN.1 encoding: "
5349 "Could not find ASN1_OBJECT for NID");
5350 return nullptr;
5351 }
5352 return ASN1_OBJECT_to_OID_string(env, obj);
5353 }
5354
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5355 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5356 jlong cbsRef) {
5357 CHECK_ERROR_QUEUE_ON_RETURN;
5358 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5359 JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5360
5361 bool empty = (CBS_len(cbs->cbs.get()) == 0);
5362 JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5363 return empty;
5364 }
5365
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5366 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5367 CHECK_ERROR_QUEUE_ON_RETURN;
5368 if (cbsRef == 0) {
5369 JNI_TRACE("asn1_read_free(0)");
5370 return;
5371 }
5372 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5373 JNI_TRACE("asn1_read_free(%p)", cbs);
5374 delete cbs;
5375 }
5376
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5377 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5378 CHECK_ERROR_QUEUE_ON_RETURN;
5379 JNI_TRACE("asn1_write_init");
5380 std::unique_ptr<CBB> cbb(new CBB());
5381 if (!CBB_init(cbb.get(), 128)) {
5382 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5383 return 0;
5384 }
5385 JNI_TRACE("asn1_write_init => %p", cbb.get());
5386 return reinterpret_cast<uintptr_t>(cbb.release());
5387 }
5388
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5389 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5390 CHECK_ERROR_QUEUE_ON_RETURN;
5391 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5392 JNI_TRACE("asn1_write_sequence(%p)", cbb);
5393
5394 std::unique_ptr<CBB> seq(new CBB());
5395 if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5396 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5397 return 0;
5398 }
5399 JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5400 return reinterpret_cast<uintptr_t>(seq.release());
5401 }
5402
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5403 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5404 CHECK_ERROR_QUEUE_ON_RETURN;
5405 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5406 JNI_TRACE("asn1_write_tag(%p)", cbb);
5407
5408 std::unique_ptr<CBB> tag_holder(new CBB());
5409 if (!CBB_add_asn1(cbb, tag_holder.get(),
5410 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5411 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5412 return 0;
5413 }
5414 JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5415 return reinterpret_cast<uintptr_t>(tag_holder.release());
5416 }
5417
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5418 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5419 jbyteArray data) {
5420 CHECK_ERROR_QUEUE_ON_RETURN;
5421 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5422 JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5423
5424 ScopedByteArrayRO bytes(env, data);
5425 if (bytes.get() == nullptr) {
5426 JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5427 return;
5428 }
5429
5430 std::unique_ptr<CBB> octetstring(new CBB());
5431 if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5432 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5433 return;
5434 }
5435 if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5436 bytes.size())) {
5437 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5438 return;
5439 }
5440 if (!CBB_flush(cbb)) {
5441 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5442 return;
5443 }
5444 }
5445
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)5446 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
5447 CHECK_ERROR_QUEUE_ON_RETURN;
5448 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5449 JNI_TRACE("asn1_write_uint64(%p)", cbb);
5450
5451 if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
5452 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5453 return;
5454 }
5455 }
5456
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)5457 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
5458 CHECK_ERROR_QUEUE_ON_RETURN;
5459 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5460 JNI_TRACE("asn1_write_null(%p)", cbb);
5461
5462 CBB null_holder;
5463 if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
5464 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5465 return;
5466 }
5467 if (!CBB_flush(cbb)) {
5468 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5469 return;
5470 }
5471 }
5472
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)5473 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
5474 CHECK_ERROR_QUEUE_ON_RETURN;
5475 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5476 JNI_TRACE("asn1_write_oid(%p)", cbb);
5477
5478 ScopedUtfChars oid_chars(env, oid);
5479 if (oid_chars.c_str() == nullptr) {
5480 return;
5481 }
5482
5483 int nid = OBJ_txt2nid(oid_chars.c_str());
5484 if (nid == NID_undef) {
5485 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5486 return;
5487 }
5488
5489 if (!OBJ_nid2cbb(cbb, nid)) {
5490 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5491 return;
5492 }
5493 }
5494
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)5495 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
5496 CHECK_ERROR_QUEUE_ON_RETURN;
5497 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5498 JNI_TRACE("asn1_write_flush(%p)", cbb);
5499
5500 if (!CBB_flush(cbb)) {
5501 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5502 return;
5503 }
5504 }
5505
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)5506 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
5507 CHECK_ERROR_QUEUE_ON_RETURN;
5508 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5509 JNI_TRACE("asn1_write_finish(%p)", cbb);
5510
5511 uint8_t* data;
5512 size_t data_len;
5513 if (!CBB_finish(cbb, &data, &data_len)) {
5514 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5515 return 0;
5516 }
5517 bssl::UniquePtr<uint8_t> data_storage(data);
5518 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
5519 if (out.get() == nullptr) {
5520 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5521 return 0;
5522 }
5523 ScopedByteArrayRW outBytes(env, out.get());
5524 if (outBytes.get() == nullptr) {
5525 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5526 return 0;
5527 }
5528 memcpy(outBytes.get(), data, data_len);
5529 return out.release();
5530 }
5531
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5532 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5533 CHECK_ERROR_QUEUE_ON_RETURN;
5534 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5535 JNI_TRACE("asn1_write_cleanup(%p)", cbb);
5536
5537 CBB_cleanup(cbb);
5538 }
5539
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5540 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5541 CHECK_ERROR_QUEUE_ON_RETURN;
5542 if (cbbRef == 0) {
5543 JNI_TRACE("asn1_write_free(0)");
5544 return;
5545 }
5546 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5547 JNI_TRACE("asn1_write_free(%p)", cbb);
5548 delete cbb;
5549 }
5550
5551 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5552 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5553 BIO* bio = to_BIO(env, bioRef);
5554 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5555
5556 if (bio == nullptr) {
5557 return 0;
5558 }
5559
5560 T* x = d2i_func(bio, nullptr);
5561 if (x == nullptr) {
5562 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
5563 return 0;
5564 }
5565
5566 return reinterpret_cast<uintptr_t>(x);
5567 }
5568
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5569 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5570 CHECK_ERROR_QUEUE_ON_RETURN;
5571 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5572 }
5573
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5574 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5575 CHECK_ERROR_QUEUE_ON_RETURN;
5576 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5577 }
5578
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5579 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5580 CHECK_ERROR_QUEUE_ON_RETURN;
5581 ScopedByteArrayRO bytes(env, certBytes);
5582 if (bytes.get() == nullptr) {
5583 JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
5584 return 0;
5585 }
5586
5587 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
5588 // NOLINTNEXTLINE(runtime/int)
5589 X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
5590 if (x == nullptr) {
5591 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5592 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
5593 return 0;
5594 }
5595 return reinterpret_cast<uintptr_t>(x);
5596 }
5597
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5598 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
5599 CONSCRYPT_UNUSED jobject holder) {
5600 CHECK_ERROR_QUEUE_ON_RETURN;
5601 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5602 JNI_TRACE("i2d_X509(%p)", x509);
5603
5604 if (x509 == nullptr) {
5605 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5606 JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
5607 return nullptr;
5608 }
5609 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
5610 }
5611
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5612 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
5613 CONSCRYPT_UNUSED jobject holder) {
5614 CHECK_ERROR_QUEUE_ON_RETURN;
5615 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5616 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5617
5618 if (x509 == nullptr) {
5619 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5620 JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
5621 return nullptr;
5622 }
5623 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
5624 }
5625
5626 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)5627 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
5628 BIO* bio = to_BIO(env, bioRef);
5629 JNI_TRACE("PEM_to_jlong(%p)", bio);
5630
5631 if (bio == nullptr) {
5632 JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
5633 return 0;
5634 }
5635
5636 T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
5637 if (x == nullptr) {
5638 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
5639 JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
5640 return 0;
5641 }
5642
5643 JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
5644 return reinterpret_cast<uintptr_t>(x);
5645 }
5646
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5647 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5648 CHECK_ERROR_QUEUE_ON_RETURN;
5649 // NOLINTNEXTLINE(runtime/int)
5650 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
5651 return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5652 }
5653
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5654 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5655 CHECK_ERROR_QUEUE_ON_RETURN;
5656 // NOLINTNEXTLINE(runtime/int)
5657 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
5658 return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5659 }
5660
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)5661 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
5662 CHECK_ERROR_QUEUE_ON_RETURN;
5663 // NOLINTNEXTLINE(runtime/int)
5664 JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
5665 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
5666 }
5667
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)5668 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
5669 CHECK_ERROR_QUEUE_ON_RETURN;
5670 // NOLINTNEXTLINE(runtime/int)
5671 JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
5672 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
5673 }
5674
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)5675 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
5676 if (certs == nullptr) {
5677 return nullptr;
5678 }
5679
5680 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5681 size_t size = sk_X509_num(certs);
5682 ref_array.reset(env->NewLongArray(size));
5683 ScopedLongArrayRW items(env, ref_array.get());
5684 for (size_t i = 0; i < size; i++) {
5685 X509* cert = sk_X509_value(certs, i);
5686 X509_up_ref(cert);
5687 items[i] = reinterpret_cast<uintptr_t>(cert);
5688 }
5689
5690 JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
5691 return ref_array.release();
5692 }
5693
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)5694 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
5695 if (crls == nullptr) {
5696 return nullptr;
5697 }
5698
5699 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5700 size_t size = sk_X509_CRL_num(crls);
5701 ref_array.reset(env->NewLongArray(size));
5702 ScopedLongArrayRW items(env, ref_array.get());
5703 for (size_t i = 0; i < size; i++) {
5704 X509_CRL* crl = sk_X509_CRL_value(crls, i);
5705 X509_CRL_up_ref(crl);
5706 items[i] = reinterpret_cast<uintptr_t>(crl);
5707 }
5708
5709 JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
5710 return ref_array.release();
5711 }
5712
5713 #define PKCS7_CERTS 1
5714 #define PKCS7_CRLS 2
5715
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5716 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5717 CHECK_ERROR_QUEUE_ON_RETURN;
5718 STACK_OF(X509)* stack = sk_X509_new_null();
5719
5720 ScopedLongArrayRO certs(env, certsArray);
5721 for (size_t i = 0; i < certs.size(); i++) {
5722 X509* item = reinterpret_cast<X509*>(certs[i]);
5723 if (sk_X509_push(stack, item) == 0) {
5724 sk_X509_free(stack);
5725 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
5726 return nullptr;
5727 }
5728 }
5729
5730 bssl::ScopedCBB out;
5731 CBB_init(out.get(), 1024 * certs.size());
5732 if (!PKCS7_bundle_certificates(out.get(), stack)) {
5733 sk_X509_free(stack);
5734 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
5735 return nullptr;
5736 }
5737
5738 sk_X509_free(stack);
5739
5740 return CBBToByteArray(env, out.get());
5741 }
5742
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5743 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5744 CHECK_ERROR_QUEUE_ON_RETURN;
5745 BIO* bio = to_BIO(env, bioRef);
5746 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5747
5748 if (bio == nullptr) {
5749 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5750 return nullptr;
5751 }
5752
5753 if (which == PKCS7_CERTS) {
5754 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5755 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
5756 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
5757 return nullptr;
5758 }
5759 return X509s_to_ItemArray(env, outCerts.get());
5760 } else if (which == PKCS7_CRLS) {
5761 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5762 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
5763 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
5764 return nullptr;
5765 }
5766 return X509_CRLs_to_ItemArray(env, outCRLs.get());
5767 } else {
5768 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5769 return nullptr;
5770 }
5771 }
5772
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5773 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5774 CHECK_ERROR_QUEUE_ON_RETURN;
5775 BIO* bio = to_BIO(env, bioRef);
5776 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5777
5778 if (bio == nullptr) {
5779 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5780 return nullptr;
5781 }
5782
5783 uint8_t* data;
5784 size_t len;
5785 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5786 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
5787 conscrypt::jniutil::throwParsingException);
5788 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
5789 return nullptr;
5790 }
5791 bssl::UniquePtr<uint8_t> data_storage(data);
5792
5793 CBS cbs;
5794 CBS_init(&cbs, data, len);
5795
5796 if (which == PKCS7_CERTS) {
5797 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5798 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
5799 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
5800 "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
5801 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
5802 return nullptr;
5803 }
5804 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
5805 return X509s_to_ItemArray(env, outCerts.get());
5806 } else if (which == PKCS7_CRLS) {
5807 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5808 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
5809 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
5810 conscrypt::jniutil::throwParsingException);
5811 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
5812 return nullptr;
5813 }
5814 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
5815 return X509_CRLs_to_ItemArray(env, outCRLs.get());
5816 } else {
5817 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5818 return nullptr;
5819 }
5820 }
5821
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)5822 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5823 CHECK_ERROR_QUEUE_ON_RETURN;
5824 BIO* bio = to_BIO(env, bioRef);
5825 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5826
5827 if (bio == nullptr) {
5828 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
5829 return nullptr;
5830 }
5831
5832 uint8_t* data;
5833 size_t len;
5834 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5835 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
5836 conscrypt::jniutil::throwParsingException);
5837 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
5838 return nullptr;
5839 }
5840 bssl::UniquePtr<uint8_t> data_storage(data);
5841
5842 bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
5843 if (path.get() == nullptr) {
5844 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
5845 return nullptr;
5846 }
5847
5848 CBS cbs, sequence;
5849 CBS_init(&cbs, data, len);
5850 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
5851 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5852 ERR_clear_error();
5853 return nullptr;
5854 }
5855
5856 while (CBS_len(&sequence) > 0) {
5857 CBS child;
5858 if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
5859 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5860 ERR_clear_error();
5861 return nullptr;
5862 }
5863
5864 const uint8_t* tmp = CBS_data(&child);
5865 // NOLINTNEXTLINE(runtime/int)
5866 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
5867 if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
5868 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5869 ERR_clear_error();
5870 return nullptr;
5871 }
5872
5873 if (!sk_X509_push(path.get(), cert.get())) {
5874 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
5875 return nullptr;
5876 }
5877 OWNERSHIP_TRANSFERRED(cert);
5878 }
5879
5880 size_t size = sk_X509_num(path.get());
5881
5882 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
5883 ScopedLongArrayRW certs(env, certArray.get());
5884 for (size_t i = 0; i < size; i++) {
5885 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5886 certs[i] = reinterpret_cast<uintptr_t>(item);
5887 }
5888
5889 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
5890 return certArray.release();
5891 }
5892
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5893 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5894 CHECK_ERROR_QUEUE_ON_RETURN;
5895 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5896 ScopedLongArrayRO certsArray(env, certs);
5897 if (certsArray.get() == nullptr) {
5898 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5899 return nullptr;
5900 }
5901
5902 bssl::ScopedCBB result;
5903 CBB seq_contents;
5904 if (!CBB_init(result.get(), 2048 * certsArray.size())) {
5905 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
5906 return nullptr;
5907 }
5908 if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
5909 return nullptr;
5910 }
5911
5912 for (size_t i = 0; i < certsArray.size(); i++) {
5913 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5914 uint8_t* buf;
5915 int len = i2d_X509(x509, nullptr);
5916
5917 if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
5918 i2d_X509(x509, &buf) < 0) {
5919 return nullptr;
5920 }
5921 }
5922
5923 return CBBToByteArray(env, result.get());
5924 }
5925
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5926 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
5927 CONSCRYPT_UNUSED jobject holder) {
5928 CHECK_ERROR_QUEUE_ON_RETURN;
5929 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5930 JNI_TRACE("X509_free(%p)", x509);
5931
5932 if (x509 == nullptr) {
5933 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5934 JNI_TRACE("X509_free(%p) => x509 == null", x509);
5935 return;
5936 }
5937
5938 X509_free(x509);
5939 }
5940
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5941 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
5942 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5943 CONSCRYPT_UNUSED jobject holder2) {
5944 CHECK_ERROR_QUEUE_ON_RETURN;
5945 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5946 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5947 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5948
5949 if (x509_1 == nullptr) {
5950 conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
5951 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5952 return -1;
5953 }
5954
5955 if (x509_2 == nullptr) {
5956 conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
5957 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5958 return -1;
5959 }
5960
5961 int ret = X509_cmp(x509_1, x509_2);
5962 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5963 return ret;
5964 }
5965
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)5966 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5967 CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
5968 jlong certflagJava) {
5969 CHECK_ERROR_QUEUE_ON_RETURN;
5970 BIO* bio = to_BIO(env, bioRef);
5971 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5972 // NOLINTNEXTLINE(runtime/int)
5973 unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
5974 // NOLINTNEXTLINE(runtime/int)
5975 unsigned long certflag = static_cast<unsigned long>(certflagJava);
5976 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5977
5978 if (bio == nullptr) {
5979 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5980 return;
5981 }
5982
5983 if (x509 == nullptr) {
5984 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5985 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5986 return;
5987 }
5988
5989 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5990 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
5991 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5992 return;
5993 }
5994 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5995 }
5996
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5997 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
5998 CONSCRYPT_UNUSED jobject holder) {
5999 CHECK_ERROR_QUEUE_ON_RETURN;
6000 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6001 JNI_TRACE("X509_get_pubkey(%p)", x509);
6002
6003 if (x509 == nullptr) {
6004 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6005 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6006 return 0;
6007 }
6008
6009 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6010 if (pkey.get() == nullptr) {
6011 const uint32_t last_error = ERR_peek_last_error();
6012 const uint32_t first_error = ERR_peek_error();
6013 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6014 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6015 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6016 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6017 ERR_clear_error();
6018 conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6019 return 0;
6020 }
6021
6022 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6023 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6024 return 0;
6025 }
6026
6027 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6028 return reinterpret_cast<uintptr_t>(pkey.release());
6029 }
6030
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6031 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6032 CONSCRYPT_UNUSED jobject holder) {
6033 CHECK_ERROR_QUEUE_ON_RETURN;
6034 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6035 JNI_TRACE("X509_get_issuer_name(%p)", x509);
6036
6037 if (x509 == nullptr) {
6038 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6039 JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6040 return nullptr;
6041 }
6042 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6043 }
6044
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6045 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6046 CONSCRYPT_UNUSED jobject holder) {
6047 CHECK_ERROR_QUEUE_ON_RETURN;
6048 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6049 JNI_TRACE("X509_get_subject_name(%p)", x509);
6050
6051 if (x509 == nullptr) {
6052 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6053 JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6054 return nullptr;
6055 }
6056 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6057 }
6058
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6059 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6060 CONSCRYPT_UNUSED jobject holder) {
6061 CHECK_ERROR_QUEUE_ON_RETURN;
6062 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6063 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6064
6065 if (x509 == nullptr) {
6066 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6067 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6068 return nullptr;
6069 }
6070
6071 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6072 ASN1_OBJECT* algorithm;
6073 X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6074 return ASN1_OBJECT_to_OID_string(env, algorithm);
6075 }
6076
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6077 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6078 CONSCRYPT_UNUSED jobject holder) {
6079 CHECK_ERROR_QUEUE_ON_RETURN;
6080 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6081 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6082
6083 if (x509 == nullptr) {
6084 conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6085 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6086 return nullptr;
6087 }
6088
6089 const X509_ALGOR* sig_alg;
6090 X509_get0_signature(nullptr, &sig_alg, x509);
6091 const ASN1_OBJECT* oid;
6092 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6093 return ASN1_OBJECT_to_OID_string(env, oid);
6094 }
6095
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6096 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6097 CONSCRYPT_UNUSED jobject holder) {
6098 CHECK_ERROR_QUEUE_ON_RETURN;
6099 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6100 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6101
6102 if (x509 == nullptr) {
6103 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6104 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6105 return nullptr;
6106 }
6107
6108 const X509_ALGOR* sig_alg;
6109 X509_get0_signature(nullptr, &sig_alg, x509);
6110 return get_X509_ALGOR_parameter(env, sig_alg);
6111 }
6112
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6113 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6114 CONSCRYPT_UNUSED jobject holder) {
6115 CHECK_ERROR_QUEUE_ON_RETURN;
6116 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6117 JNI_TRACE("get_X509_issuerUID(%p)", x509);
6118
6119 if (x509 == nullptr) {
6120 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6121 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6122 return nullptr;
6123 }
6124
6125 const ASN1_BIT_STRING* issuer_uid;
6126 X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6127 if (issuer_uid == nullptr) {
6128 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6129 return nullptr;
6130 }
6131
6132 return ASN1BitStringToBooleanArray(env, issuer_uid);
6133 }
6134
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6135 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6136 CONSCRYPT_UNUSED jobject holder) {
6137 CHECK_ERROR_QUEUE_ON_RETURN;
6138 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6139 JNI_TRACE("get_X509_subjectUID(%p)", x509);
6140
6141 if (x509 == nullptr) {
6142 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6143 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6144 return nullptr;
6145 }
6146
6147 const ASN1_BIT_STRING* subject_uid;
6148 X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6149 if (subject_uid == nullptr) {
6150 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6151 return nullptr;
6152 }
6153
6154 return ASN1BitStringToBooleanArray(env, subject_uid);
6155 }
6156
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6157 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6158 CONSCRYPT_UNUSED jobject holder) {
6159 CHECK_ERROR_QUEUE_ON_RETURN;
6160 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6161 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6162
6163 if (x509 == nullptr) {
6164 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6165 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6166 return nullptr;
6167 }
6168
6169 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6170 // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6171 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6172 bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6173 static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6174 if (bitStr.get() == nullptr) {
6175 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6176 ERR_clear_error();
6177 return nullptr;
6178 }
6179
6180 return ASN1BitStringToBooleanArray(env, bitStr.get());
6181 }
6182
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6183 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6184 CONSCRYPT_UNUSED jobject holder) {
6185 CHECK_ERROR_QUEUE_ON_RETURN;
6186 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6187 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6188
6189 if (x509 == nullptr) {
6190 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6191 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6192 return nullptr;
6193 }
6194
6195 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6196 // |ERR_clear_error|, and throw CertificateParsingException.
6197 bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6198 X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6199 if (objArray.get() == nullptr) {
6200 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6201 ERR_clear_error();
6202 return nullptr;
6203 }
6204
6205 size_t size = sk_ASN1_OBJECT_num(objArray.get());
6206 ScopedLocalRef<jobjectArray> exKeyUsage(
6207 env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6208 nullptr));
6209 if (exKeyUsage.get() == nullptr) {
6210 return nullptr;
6211 }
6212
6213 for (size_t i = 0; i < size; i++) {
6214 ScopedLocalRef<jstring> oidStr(
6215 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6216 env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6217 }
6218
6219 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6220 return exKeyUsage.release();
6221 }
6222
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6223 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6224 CONSCRYPT_UNUSED jobject holder) {
6225 CHECK_ERROR_QUEUE_ON_RETURN;
6226 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6227 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6228
6229 if (x509 == nullptr) {
6230 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6231 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6232 return 0;
6233 }
6234
6235 // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6236 // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6237 // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6238 // the constructor even if |EXFLAG_INVALID| is set.
6239 //
6240 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6241 // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6242 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6243 bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6244 X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6245 if (basic_constraints == nullptr) {
6246 JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6247 ERR_clear_error();
6248 return -1;
6249 }
6250
6251 if (basic_constraints->pathlen == nullptr) {
6252 JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6253 return -1;
6254 }
6255
6256 if (!basic_constraints->ca) {
6257 // Path length constraints are only valid for CA certificates.
6258 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6259 JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6260 return -1;
6261 }
6262
6263 if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6264 // Path length constraints may not be negative.
6265 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6266 JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6267 return -1;
6268 }
6269
6270 long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6271 if (pathlen == -1 || pathlen > INT_MAX) {
6272 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6273 // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6274 // constraint is plausible, but Chromium rejects all values above 255.
6275 JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6276 return -1;
6277 }
6278
6279 JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6280 return pathlen;
6281 }
6282
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6283 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6284 CONSCRYPT_UNUSED jobject holder,
6285 jstring oidString) {
6286 CHECK_ERROR_QUEUE_ON_RETURN;
6287 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6288 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6289 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6290 }
6291
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6292 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6293 CONSCRYPT_UNUSED jobject holder,
6294 jstring oidString) {
6295 CHECK_ERROR_QUEUE_ON_RETURN;
6296 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6297 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6298
6299 if (crl == nullptr) {
6300 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
6301 JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
6302 return nullptr;
6303 }
6304 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6305 oidString);
6306 }
6307
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6308 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6309 jstring oidString) {
6310 CHECK_ERROR_QUEUE_ON_RETURN;
6311 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6312 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6313
6314 if (revoked == nullptr) {
6315 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
6316 JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
6317 return nullptr;
6318 }
6319 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6320 env, revoked, oidString);
6321 }
6322
6323 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6324 X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6325 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6326 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6327 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6328
6329 if (x509 == nullptr) {
6330 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6331 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6332 return nullptr;
6333 }
6334
6335 int lastPos = -1;
6336 int count = 0;
6337 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6338 count++;
6339 }
6340
6341 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6342
6343 ScopedLocalRef<jobjectArray> joa(
6344 env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6345 if (joa.get() == nullptr) {
6346 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6347 return nullptr;
6348 }
6349
6350 lastPos = -1;
6351 count = 0;
6352 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6353 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6354
6355 ScopedLocalRef<jstring> extOid(
6356 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6357 if (extOid.get() == nullptr) {
6358 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6359 return nullptr;
6360 }
6361
6362 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6363 }
6364
6365 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6366 return joa.release();
6367 }
6368
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6369 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6370 CONSCRYPT_UNUSED jobject holder, jint critical) {
6371 CHECK_ERROR_QUEUE_ON_RETURN;
6372 // NOLINTNEXTLINE(runtime/int)
6373 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6374 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6375 critical);
6376 }
6377
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6378 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6379 CONSCRYPT_UNUSED jobject holder,
6380 jint critical) {
6381 CHECK_ERROR_QUEUE_ON_RETURN;
6382 // NOLINTNEXTLINE(runtime/int)
6383 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6384 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6385 env, x509CrlRef, critical);
6386 }
6387
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6388 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6389 jlong x509RevokedRef, jint critical) {
6390 CHECK_ERROR_QUEUE_ON_RETURN;
6391 // NOLINTNEXTLINE(runtime/int)
6392 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6393 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6394 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6395 }
6396
6397 /**
6398 * Based on example logging call back from SSL_CTX_set_info_callback man page
6399 */
info_callback_LOG(const SSL * s,int where,int ret)6400 static void info_callback_LOG(const SSL* s, int where, int ret) {
6401 int w = where & ~SSL_ST_MASK;
6402 const char* str;
6403 if (w & SSL_ST_CONNECT) {
6404 str = "SSL_connect";
6405 } else if (w & SSL_ST_ACCEPT) {
6406 str = "SSL_accept";
6407 } else {
6408 str = "undefined";
6409 }
6410
6411 if (where & SSL_CB_LOOP) {
6412 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6413 } else if (where & SSL_CB_ALERT) {
6414 str = (where & SSL_CB_READ) ? "read" : "write";
6415 JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6416 SSL_alert_desc_string_long(ret));
6417 } else if (where & SSL_CB_EXIT) {
6418 if (ret == 0) {
6419 JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6420 SSL_state_string_long(s));
6421 } else if (ret < 0) {
6422 JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6423 SSL_state_string_long(s));
6424 } else if (ret == 1) {
6425 JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6426 SSL_state_string_long(s));
6427 } else {
6428 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6429 SSL_state_string_long(s));
6430 }
6431 } else if (where & SSL_CB_HANDSHAKE_START) {
6432 JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6433 SSL_state_string_long(s));
6434 } else if (where & SSL_CB_HANDSHAKE_DONE) {
6435 JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6436 SSL_state_string_long(s));
6437 } else {
6438 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6439 SSL_state_string_long(s));
6440 }
6441 }
6442
6443 #ifdef _WIN32
6444
6445 /**
6446 * Dark magic helper function that checks, for a given SSL session, whether it
6447 * can SSL_read() or SSL_write() without blocking. Takes into account any
6448 * concurrent attempts to close the SSLSocket from the Java side. This is
6449 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6450 * while thread #2 is sitting in a blocking read or write. The type argument
6451 * specifies whether we are waiting for readability or writability. It expects
6452 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6453 * only need to wait in case one of these problems occurs.
6454 *
6455 * @param env
6456 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6457 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6458 * @param appData The application data structure with mutex info etc.
6459 * @param timeout_millis The timeout value for select call, with the special value
6460 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6461 * the Java semantics of the timeout value, not the usual
6462 * select() semantics.
6463 * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
6464 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6465 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6466 int timeout_millis) {
6467 int result = -1;
6468
6469 NetFd fd(env, fdObject);
6470 do {
6471 if (fd.isClosed()) {
6472 result = THROWN_EXCEPTION;
6473 break;
6474 }
6475
6476 WSAEVENT events[2];
6477 events[0] = appData->interruptEvent;
6478 events[1] = WSACreateEvent();
6479 if (events[1] == WSA_INVALID_EVENT) {
6480 JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
6481 break;
6482 }
6483
6484 if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
6485 FD_CLOSE) == SOCKET_ERROR) {
6486 JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
6487 break;
6488 }
6489
6490 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6491 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6492 timeout_millis);
6493
6494 int rc = WSAWaitForMultipleEvents(
6495 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
6496 if (rc == WSA_WAIT_FAILED) {
6497 JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
6498 result = -1;
6499 } else if (rc == WSA_WAIT_TIMEOUT) {
6500 result = 0;
6501 } else {
6502 result = 1;
6503 }
6504 WSACloseEvent(events[1]);
6505 } while (0);
6506
6507 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
6508 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
6509 result);
6510
6511 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6512 appData->waitingThreads--;
6513
6514 return result;
6515 }
6516
6517 #else // !defined(_WIN32)
6518
6519 /**
6520 * Dark magic helper function that checks, for a given SSL session, whether it
6521 * can SSL_read() or SSL_write() without blocking. Takes into account any
6522 * concurrent attempts to close the SSLSocket from the Java side. This is
6523 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6524 * while thread #2 is sitting in a blocking read or write. The type argument
6525 * specifies whether we are waiting for readability or writability. It expects
6526 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6527 * only need to wait in case one of these problems occurs.
6528 *
6529 * @param env
6530 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6531 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
6532 * @param appData The application data structure with mutex info etc.
6533 * @param timeout_millis The timeout value for poll call, with the special value
6534 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6535 * the Java semantics of the timeout value, not the usual
6536 * poll() semantics.
6537 * @return The result of the inner poll() call,
6538 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6539 * additional errors
6540 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6541 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6542 int timeout_millis) {
6543 // This loop is an expanded version of the NET_FAILURE_RETRY
6544 // macro. It cannot simply be used in this case because poll
6545 // cannot be restarted without recreating the pollfd structure.
6546 int result;
6547 struct pollfd fds[2];
6548 do {
6549 NetFd fd(env, fdObject);
6550 if (fd.isClosed()) {
6551 result = THROWN_EXCEPTION;
6552 break;
6553 }
6554 int intFd = fd.get();
6555 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6556 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6557
6558 memset(&fds, 0, sizeof(fds));
6559 fds[0].fd = intFd;
6560 if (type == SSL_ERROR_WANT_READ) {
6561 fds[0].events = POLLIN | POLLPRI;
6562 } else {
6563 fds[0].events = POLLOUT | POLLPRI;
6564 }
6565
6566 fds[1].fd = appData->fdsEmergency[0];
6567 fds[1].events = POLLIN | POLLPRI;
6568
6569 // Converting from Java semantics to Posix semantics.
6570 if (timeout_millis <= 0) {
6571 timeout_millis = -1;
6572 }
6573
6574 CompatibilityCloseMonitor monitor(intFd);
6575
6576 result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
6577 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6578 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6579 timeout_millis, result);
6580 if (result == -1) {
6581 if (fd.isClosed()) {
6582 result = THROWN_EXCEPTION;
6583 break;
6584 }
6585 if (errno != EINTR) {
6586 break;
6587 }
6588 }
6589 } while (result == -1);
6590
6591 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6592
6593 if (result > 0) {
6594 // We have been woken up by a token in the emergency pipe. We
6595 // can't be sure the token is still in the pipe at this point
6596 // because it could have already been read by the thread that
6597 // originally wrote it if it entered sslSelect and acquired
6598 // the mutex before we did. Thus we cannot safely read from
6599 // the pipe in a blocking way (so we make the pipe
6600 // non-blocking at creation).
6601 if (fds[1].revents & POLLIN) {
6602 char token;
6603 do {
6604 (void)read(appData->fdsEmergency[0], &token, 1);
6605 } while (errno == EINTR);
6606 }
6607 }
6608
6609 // Tell the world that there is now one thread less waiting for the
6610 // underlying network.
6611 appData->waitingThreads--;
6612
6613 return result;
6614 }
6615 #endif // !defined(_WIN32)
6616
6617 /**
6618 * Helper function that wakes up a thread blocked in select(), in case there is
6619 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6620 * before closing the connection.
6621 *
6622 * @param data The application data structure with mutex info etc.
6623 */
sslNotify(AppData * appData)6624 static void sslNotify(AppData* appData) {
6625 #ifdef _WIN32
6626 SetEvent(appData->interruptEvent);
6627 #else
6628 // Write a byte to the emergency pipe, so a concurrent select() can return.
6629 // Note we have to restore the errno of the original system call, since the
6630 // caller relies on it for generating error messages.
6631 int errnoBackup = errno;
6632 char token = '*';
6633 do {
6634 errno = 0;
6635 (void)write(appData->fdsEmergency[1], &token, 1);
6636 } while (errno == EINTR);
6637 errno = errnoBackup;
6638 #endif
6639 }
6640
toAppData(const SSL * ssl)6641 static AppData* toAppData(const SSL* ssl) {
6642 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6643 }
6644
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)6645 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
6646 JNI_TRACE("ssl=%p cert_verify_callback", ssl);
6647
6648 AppData* appData = toAppData(ssl);
6649 JNIEnv* env = appData->env;
6650 if (env == nullptr) {
6651 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
6652 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6653 return ssl_verify_invalid;
6654 }
6655
6656 // Create the byte[][] array that holds all the certs
6657 ScopedLocalRef<jobjectArray> array(
6658 env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
6659 if (array.get() == nullptr) {
6660 return ssl_verify_invalid;
6661 }
6662
6663 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6664 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
6665
6666 const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
6667 const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
6668
6669 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
6670 authMethod);
6671 ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
6672 env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
6673
6674 ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
6675 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6676 return result;
6677 }
6678
6679 /**
6680 * Call back to watch for handshake to be completed. This is necessary for
6681 * False Start support, since SSL_do_handshake returns before the handshake is
6682 * completed in this case.
6683 */
info_callback(const SSL * ssl,int type,int value)6684 static void info_callback(const SSL* ssl, int type, int value) {
6685 JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
6686 if (conscrypt::trace::kWithJniTrace) {
6687 info_callback_LOG(ssl, type, value);
6688 }
6689 if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
6690 JNI_TRACE("ssl=%p info_callback ignored", ssl);
6691 return;
6692 }
6693
6694 AppData* appData = toAppData(ssl);
6695 JNIEnv* env = appData->env;
6696 if (env == nullptr) {
6697 CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
6698 JNI_TRACE("ssl=%p info_callback env error", ssl);
6699 return;
6700 }
6701 if (env->ExceptionCheck()) {
6702 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6703 return;
6704 }
6705
6706 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6707
6708 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6709 env->CallVoidMethod(sslHandshakeCallbacks,
6710 conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
6711
6712 if (env->ExceptionCheck()) {
6713 JNI_TRACE("ssl=%p info_callback exception", ssl);
6714 }
6715 JNI_TRACE("ssl=%p info_callback completed", ssl);
6716 }
6717
6718 /**
6719 * Call back to ask for a certificate. There are three possible exit codes:
6720 *
6721 * 1 is success.
6722 * 0 is error.
6723 * -1 is to pause the handshake to continue from the same place later.
6724 */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)6725 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
6726 JNI_TRACE("ssl=%p cert_cb", ssl);
6727
6728 // cert_cb is called for both clients and servers, but we are only
6729 // interested in client certificates.
6730 if (SSL_is_server(ssl)) {
6731 JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
6732 return 1;
6733 }
6734
6735 AppData* appData = toAppData(ssl);
6736 JNIEnv* env = appData->env;
6737 if (env == nullptr) {
6738 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
6739 JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
6740 return 0;
6741 }
6742 if (env->ExceptionCheck()) {
6743 JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
6744 return 0;
6745 }
6746 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6747
6748 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
6749
6750 // Call Java callback which can reconfigure the client certificate.
6751 const uint8_t* ctype = nullptr;
6752 size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
6753 const uint16_t* sigalgs = nullptr;
6754 size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
6755 ScopedLocalRef<jobjectArray> issuers(
6756 env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
6757 if (issuers.get() == nullptr) {
6758 return 0;
6759 }
6760
6761 if (conscrypt::trace::kWithJniTrace) {
6762 for (size_t i = 0; i < ctype_num; i++) {
6763 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
6764 }
6765 for (size_t i = 0; i < sigalgs_num; i++) {
6766 JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
6767 }
6768 }
6769
6770 jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
6771 if (keyTypes == nullptr) {
6772 JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
6773 return 0;
6774 }
6775 env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
6776 reinterpret_cast<const jbyte*>(ctype));
6777
6778 jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
6779 if (signatureAlgs == nullptr) {
6780 JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
6781 return 0;
6782 }
6783 {
6784 ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
6785 for (size_t i = 0; i < sigalgs_num; i++) {
6786 sigAlgsRW[i] = sigalgs[i];
6787 }
6788 }
6789
6790 JNI_TRACE(
6791 "ssl=%p clientCertificateRequested calling clientCertificateRequested "
6792 "keyTypes=%p signatureAlgs=%p issuers=%p",
6793 ssl, keyTypes, signatureAlgs, issuers.get());
6794 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
6795
6796 if (env->ExceptionCheck()) {
6797 JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
6798 return 0;
6799 }
6800
6801 JNI_TRACE("ssl=%p cert_cb => 1", ssl);
6802 return 1;
6803 }
6804
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)6805 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
6806 SSL* ssl = client_hello->ssl;
6807 JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
6808
6809 AppData* appData = toAppData(ssl);
6810 JNIEnv* env = appData->env;
6811 if (env == nullptr) {
6812 CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
6813 JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
6814 return ssl_select_cert_error;
6815 }
6816 if (env->ExceptionCheck()) {
6817 JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
6818 return ssl_select_cert_error;
6819 }
6820
6821 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6822 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
6823
6824 JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
6825 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
6826
6827 if (env->ExceptionCheck()) {
6828 JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
6829 return ssl_select_cert_error;
6830 }
6831 JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
6832 return ssl_select_cert_success;
6833 }
6834
6835 /**
6836 * Pre-Shared Key (PSK) client callback.
6837 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6838 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
6839 unsigned int max_identity_len, unsigned char* psk,
6840 unsigned int max_psk_len) {
6841 JNI_TRACE("ssl=%p psk_client_callback", ssl);
6842
6843 AppData* appData = toAppData(ssl);
6844 JNIEnv* env = appData->env;
6845 if (env == nullptr) {
6846 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
6847 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6848 return 0;
6849 }
6850 if (env->ExceptionCheck()) {
6851 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6852 return 0;
6853 }
6854
6855 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6856 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
6857 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6858 ScopedLocalRef<jstring> identityHintJava(env,
6859 (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
6860 ScopedLocalRef<jbyteArray> identityJava(
6861 env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
6862 if (identityJava.get() == nullptr) {
6863 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6864 return 0;
6865 }
6866 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6867 if (keyJava.get() == nullptr) {
6868 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6869 return 0;
6870 }
6871 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6872 identityJava.get(), keyJava.get());
6873 if (env->ExceptionCheck()) {
6874 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6875 return 0;
6876 }
6877 if (keyLen <= 0) {
6878 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6879 return 0;
6880 } else if ((unsigned int)keyLen > max_psk_len) {
6881 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6882 return 0;
6883 }
6884 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6885 if (keyJavaRo.get() == nullptr) {
6886 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
6887 return 0;
6888 }
6889 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6890
6891 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
6892 if (identityJavaRo.get() == nullptr) {
6893 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
6894 return 0;
6895 }
6896 memcpy(identity, identityJavaRo.get(), max_identity_len);
6897
6898 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
6899 return static_cast<unsigned int>(keyLen);
6900 }
6901
6902 /**
6903 * Pre-Shared Key (PSK) server callback.
6904 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)6905 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
6906 unsigned int max_psk_len) {
6907 JNI_TRACE("ssl=%p psk_server_callback", ssl);
6908
6909 AppData* appData = toAppData(ssl);
6910 JNIEnv* env = appData->env;
6911 if (env == nullptr) {
6912 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
6913 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
6914 return 0;
6915 }
6916 if (env->ExceptionCheck()) {
6917 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
6918 return 0;
6919 }
6920
6921 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6922 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
6923 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
6924 const char* identityHint = SSL_get_psk_identity_hint(ssl);
6925 ScopedLocalRef<jstring> identityHintJava(
6926 env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
6927 ScopedLocalRef<jstring> identityJava(
6928 env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
6929 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6930 if (keyJava.get() == nullptr) {
6931 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
6932 return 0;
6933 }
6934 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6935 identityJava.get(), keyJava.get());
6936 if (env->ExceptionCheck()) {
6937 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
6938 return 0;
6939 }
6940 if (keyLen <= 0) {
6941 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
6942 return 0;
6943 } else if ((unsigned int)keyLen > max_psk_len) {
6944 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
6945 return 0;
6946 }
6947 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6948 if (keyJavaRo.get() == nullptr) {
6949 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
6950 return 0;
6951 }
6952 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6953
6954 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
6955 return static_cast<unsigned int>(keyLen);
6956 }
6957
new_session_callback(SSL * ssl,SSL_SESSION * session)6958 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
6959 JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
6960
6961 AppData* appData = toAppData(ssl);
6962 JNIEnv* env = appData->env;
6963 if (env == nullptr) {
6964 CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
6965 JNI_TRACE("ssl=%p new_session_callback env error", ssl);
6966 return 0;
6967 }
6968 if (env->ExceptionCheck()) {
6969 JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
6970 return 0;
6971 }
6972
6973 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6974 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
6975 JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
6976 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
6977 if (env->ExceptionCheck()) {
6978 JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
6979 env->ExceptionClear();
6980 }
6981 JNI_TRACE("ssl=%p new_session_callback completed", ssl);
6982
6983 // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
6984 // the reference count.
6985 return 0;
6986 }
6987
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)6988 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
6989 int* out_copy) {
6990 JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
6991
6992 // Always set to out_copy to zero. The Java callback will be responsible for incrementing
6993 // the reference count (and any required synchronization).
6994 *out_copy = 0;
6995
6996 AppData* appData = toAppData(ssl);
6997 JNIEnv* env = appData->env;
6998 if (env == nullptr) {
6999 CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7000 JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7001 return 0;
7002 }
7003 if (env->ExceptionCheck()) {
7004 JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7005 return 0;
7006 }
7007
7008 // Copy the ID to a byte[].
7009 jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7010 if (id_array == nullptr) {
7011 JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7012 return 0;
7013 }
7014 env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7015 reinterpret_cast<const jbyte*>(id));
7016
7017 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7018 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7019 JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7020 jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7021 if (env->ExceptionCheck()) {
7022 JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7023 env->ExceptionClear();
7024 }
7025 SSL_SESSION* ssl_session_ptr =
7026 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7027 JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7028 return ssl_session_ptr;
7029 }
7030
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7031 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7032 CHECK_ERROR_QUEUE_ON_RETURN;
7033 int ret = 0;
7034 ret = EVP_has_aes_hardware();
7035 JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7036 return ret;
7037 }
7038
debug_print_session_key(const SSL * ssl,const char * line)7039 static void debug_print_session_key(const SSL* ssl, const char* line) {
7040 JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7041 }
7042
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7043 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7044 static constexpr size_t kDataWidth = 16;
7045
7046 struct timeval tv;
7047 if (gettimeofday(&tv, NULL)) {
7048 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7049 "debug_print_packet_data: could not get time of day");
7050 return;
7051 }
7052
7053 // Packet preamble for text2pcap
7054 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7055 static_cast<long>(tv.tv_sec),
7056 static_cast<long>(tv.tv_usec)); // NOLINT(runtime/int)
7057
7058 char out[kDataWidth * 3 + 1];
7059 for (size_t i = 0; i < len; i += kDataWidth) {
7060 size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7061
7062 for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7063 int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7064 if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7065 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7066 "debug_print_packet_data failed to output %d", ret);
7067 return;
7068 }
7069 }
7070
7071 // Print out packet data in format understood by text2pcap
7072 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7073 }
7074
7075 // Conclude the packet data
7076 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7077 }
7078
7079 /*
7080 * public static native int SSL_CTX_new();
7081 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7082 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7083 CHECK_ERROR_QUEUE_ON_RETURN;
7084 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7085 if (sslCtx.get() == nullptr) {
7086 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7087 return 0;
7088 }
7089 SSL_CTX_set_options(
7090 sslCtx.get(),
7091 SSL_OP_ALL
7092 // We also disable session tickets for better compatibility b/2682876
7093 | SSL_OP_NO_TICKET
7094 // We also disable compression for better compatibility b/2710492 b/2710497
7095 | SSL_OP_NO_COMPRESSION
7096 // Generate a fresh ECDH keypair for each key exchange.
7097 | SSL_OP_SINGLE_ECDH_USE);
7098 SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7099 SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7100
7101 uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7102 /*
7103 * Turn on "partial write" mode. This means that SSL_write() will
7104 * behave like Posix write() and possibly return after only
7105 * writing a partial buffer. Note: The alternative, perhaps
7106 * surprisingly, is not that SSL_write() always does full writes
7107 * but that it will force you to retry write calls having
7108 * preserved the full state of the original call. (This is icky
7109 * and undesirable.)
7110 */
7111 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7112
7113 // Reuse empty buffers within the SSL_CTX to save memory
7114 mode |= SSL_MODE_RELEASE_BUFFERS;
7115
7116 // Enable False Start.
7117 mode |= SSL_MODE_ENABLE_FALSE_START;
7118
7119 // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7120 // between
7121 // calls to wrap(...).
7122 // See https://github.com/netty/netty-tcnative/issues/100
7123 mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7124
7125 SSL_CTX_set_mode(sslCtx.get(), mode);
7126
7127 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7128 SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7129 SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7130 if (conscrypt::trace::kWithJniTraceKeys) {
7131 SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7132 }
7133
7134 // By default BoringSSL will cache in server mode, but we want to get
7135 // notified of new sessions being created in client mode. We set
7136 // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7137 // ignore it in server mode in favor of the internal cache.
7138 SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7139 SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7140 SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7141
7142 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7143 return (jlong)sslCtx.release();
7144 }
7145
7146 /**
7147 * public static native void SSL_CTX_free(long ssl_ctx)
7148 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7149 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7150 CONSCRYPT_UNUSED jobject holder) {
7151 CHECK_ERROR_QUEUE_ON_RETURN;
7152 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7153 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7154 if (ssl_ctx == nullptr) {
7155 return;
7156 }
7157 SSL_CTX_free(ssl_ctx);
7158 }
7159
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7160 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7161 CONSCRYPT_UNUSED jobject holder,
7162 jbyteArray sid_ctx) {
7163 CHECK_ERROR_QUEUE_ON_RETURN;
7164 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7165 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7166 sid_ctx);
7167 if (ssl_ctx == nullptr) {
7168 return;
7169 }
7170
7171 ScopedByteArrayRO buf(env, sid_ctx);
7172 if (buf.get() == nullptr) {
7173 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7174 ssl_ctx);
7175 return;
7176 }
7177
7178 unsigned int length = static_cast<unsigned int>(buf.size());
7179 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7180 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7181 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7182 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7183 return;
7184 }
7185 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7186 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7187 if (result == 0) {
7188 conscrypt::jniutil::throwExceptionFromBoringSSLError(
7189 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7190 return;
7191 }
7192 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7193 }
7194
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7195 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7196 CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7197 CHECK_ERROR_QUEUE_ON_RETURN;
7198 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7199 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7200 if (ssl_ctx == nullptr) {
7201 return 0L;
7202 }
7203
7204 return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7205 }
7206
7207 /**
7208 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7209 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7210 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7211 CONSCRYPT_UNUSED jobject holder) {
7212 CHECK_ERROR_QUEUE_ON_RETURN;
7213 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7214 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7215 if (ssl_ctx == nullptr) {
7216 return 0;
7217 }
7218 bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7219 if (ssl.get() == nullptr) {
7220 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7221 "Unable to create SSL structure");
7222 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7223 return 0;
7224 }
7225
7226 /*
7227 * Create our special application data.
7228 */
7229 AppData* appData = AppData::create();
7230 if (appData == nullptr) {
7231 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7232 ERR_clear_error();
7233 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7234 return 0;
7235 }
7236 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7237
7238 SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7239
7240 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7241 return (jlong)ssl.release();
7242 }
7243
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7244 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7245 CONSCRYPT_UNUSED jobject ssl_holder) {
7246 CHECK_ERROR_QUEUE_ON_RETURN;
7247 SSL* ssl = to_SSL(env, ssl_address, true);
7248 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7249 if (ssl == nullptr) {
7250 return;
7251 }
7252
7253 // NOLINTNEXTLINE(runtime/int)
7254 long ret = SSL_enable_tls_channel_id(ssl);
7255 if (ret != 1L) {
7256 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7257 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7258 "Error enabling Channel ID");
7259 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7260 return;
7261 }
7262 }
7263
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7264 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7265 CONSCRYPT_UNUSED jobject ssl_holder) {
7266 CHECK_ERROR_QUEUE_ON_RETURN;
7267 SSL* ssl = to_SSL(env, ssl_address, true);
7268 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7269 if (ssl == nullptr) {
7270 return nullptr;
7271 }
7272
7273 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7274 // as a constant anywhere.
7275 jbyteArray javaBytes = env->NewByteArray(64);
7276 ScopedByteArrayRW bytes(env, javaBytes);
7277 if (bytes.get() == nullptr) {
7278 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7279 return nullptr;
7280 }
7281
7282 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7283 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7284 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7285 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7286 size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7287 if (ret == 0) {
7288 // Channel ID either not set or did not verify
7289 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7290 return nullptr;
7291 } else if (ret != 64) {
7292 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7293 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7294 "Error getting Channel ID");
7295 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7296 return nullptr;
7297 }
7298
7299 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7300 return javaBytes;
7301 }
7302
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7303 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7304 CONSCRYPT_UNUSED jobject ssl_holder,
7305 jobject pkeyRef) {
7306 CHECK_ERROR_QUEUE_ON_RETURN;
7307 SSL* ssl = to_SSL(env, ssl_address, true);
7308 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7309 if (ssl == nullptr) {
7310 return;
7311 }
7312
7313 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7314 if (pkey == nullptr) {
7315 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7316 return;
7317 }
7318
7319 // NOLINTNEXTLINE(runtime/int)
7320 long ret = SSL_set1_tls_channel_id(ssl, pkey);
7321
7322 if (ret != 1L) {
7323 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7324 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7325 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7326 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7327 return;
7328 }
7329
7330 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7331 }
7332
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7333 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7334 CONSCRYPT_UNUSED jobject ssl_holder,
7335 jobjectArray encodedCertificatesJava,
7336 jobject pkeyRef) {
7337 CHECK_ERROR_QUEUE_ON_RETURN;
7338 SSL* ssl = to_SSL(env, ssl_address, true);
7339 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7340 encodedCertificatesJava, pkeyRef);
7341 if (ssl == nullptr) {
7342 return;
7343 }
7344 if (encodedCertificatesJava == nullptr) {
7345 conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7346 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7347 return;
7348 }
7349 size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7350 if (numCerts == 0) {
7351 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7352 "certificates.length == 0");
7353 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7354 return;
7355 }
7356 if (pkeyRef == nullptr) {
7357 conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7358 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7359 return;
7360 }
7361
7362 // Get the private key.
7363 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7364 if (pkey == nullptr) {
7365 conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7366 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7367 return;
7368 }
7369
7370 // Copy the certificates.
7371 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7372 std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7373 for (size_t i = 0; i < numCerts; ++i) {
7374 ScopedLocalRef<jbyteArray> certArray(
7375 env, reinterpret_cast<jbyteArray>(
7376 env->GetObjectArrayElement(encodedCertificatesJava, i)));
7377 certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7378 if (!certBufferRefs[i]) {
7379 return;
7380 }
7381 certBuffers[i] = certBufferRefs[i].get();
7382 }
7383
7384 if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7385 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7386 "Error configuring certificate");
7387 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7388 return;
7389 }
7390 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7391 }
7392
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7393 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7394 CONSCRYPT_UNUSED jobject ssl_holder,
7395 jobjectArray principals) {
7396 CHECK_ERROR_QUEUE_ON_RETURN;
7397 SSL* ssl = to_SSL(env, ssl_address, true);
7398 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7399 if (ssl == nullptr) {
7400 return;
7401 }
7402
7403 if (principals == nullptr) {
7404 conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7405 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7406 return;
7407 }
7408
7409 int length = env->GetArrayLength(principals);
7410 if (length == 0) {
7411 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7412 "principals.length == 0");
7413 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7414 return;
7415 }
7416
7417 bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7418 if (principalsStack.get() == nullptr) {
7419 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7420 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7421 return;
7422 }
7423 for (int i = 0; i < length; i++) {
7424 ScopedLocalRef<jbyteArray> principal(
7425 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7426 bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7427 if (!buf) {
7428 return;
7429 }
7430 if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7431 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7432 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7433 return;
7434 }
7435 OWNERSHIP_TRANSFERRED(buf);
7436 }
7437
7438 SSL_set0_client_CAs(ssl, principalsStack.release());
7439 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7440 }
7441
7442 /**
7443 * public static native long SSL_set_mode(long ssl, long mode);
7444 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)7445 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
7446 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
7447 CHECK_ERROR_QUEUE_ON_RETURN;
7448 SSL* ssl = to_SSL(env, ssl_address, true);
7449 // NOLINTNEXTLINE(runtime/int)
7450 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
7451 if (ssl == nullptr) {
7452 return 0;
7453 }
7454 jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
7455 // NOLINTNEXTLINE(runtime/int)
7456 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
7457 return result;
7458 }
7459
7460 /**
7461 * public static native long SSL_set_options(long ssl, long options);
7462 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7463 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
7464 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7465 CHECK_ERROR_QUEUE_ON_RETURN;
7466 SSL* ssl = to_SSL(env, ssl_address, true);
7467 // NOLINTNEXTLINE(runtime/int)
7468 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
7469 if (ssl == nullptr) {
7470 return 0;
7471 }
7472 jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
7473 // NOLINTNEXTLINE(runtime/int)
7474 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
7475 return result;
7476 }
7477
7478 /**
7479 * public static native long SSL_clear_options(long ssl, long options);
7480 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7481 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
7482 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7483 CHECK_ERROR_QUEUE_ON_RETURN;
7484 SSL* ssl = to_SSL(env, ssl_address, true);
7485 // NOLINTNEXTLINE(runtime/int)
7486 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
7487 if (ssl == nullptr) {
7488 return 0;
7489 }
7490 jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
7491 // NOLINTNEXTLINE(runtime/int)
7492 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
7493 return result;
7494 }
7495
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)7496 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
7497 CONSCRYPT_UNUSED jobject ssl_holder,
7498 jint min_version, jint max_version) {
7499 CHECK_ERROR_QUEUE_ON_RETURN;
7500 SSL* ssl = to_SSL(env, ssl_address, true);
7501 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
7502 max_version);
7503 if (ssl == nullptr) {
7504 return 0;
7505 }
7506 int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
7507 int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
7508 // Return failure if either call failed.
7509 int result = 1;
7510 if (!min_result || !max_result) {
7511 result = 0;
7512 // The only possible error is an invalid version, so we don't need the details.
7513 ERR_clear_error();
7514 }
7515 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
7516 min_result, max_result, result);
7517 return result;
7518 }
7519
7520 /**
7521 * public static native void SSL_enable_signed_cert_timestamps(long ssl);
7522 */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7523 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
7524 CONSCRYPT_UNUSED jobject ssl_holder) {
7525 CHECK_ERROR_QUEUE_ON_RETURN;
7526 SSL* ssl = to_SSL(env, ssl_address, true);
7527 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
7528 if (ssl == nullptr) {
7529 return;
7530 }
7531
7532 SSL_enable_signed_cert_timestamps(ssl);
7533 }
7534
7535 /**
7536 * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
7537 */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7538 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
7539 JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
7540 CHECK_ERROR_QUEUE_ON_RETURN;
7541 SSL* ssl = to_SSL(env, ssl_address, true);
7542 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
7543 if (ssl == nullptr) {
7544 return nullptr;
7545 }
7546
7547 const uint8_t* data;
7548 size_t data_len;
7549 SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
7550
7551 if (data_len == 0) {
7552 JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
7553 return nullptr;
7554 }
7555
7556 jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
7557 if (result != nullptr) {
7558 env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
7559 }
7560 return result;
7561 }
7562
7563 /*
7564 * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
7565 */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)7566 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
7567 CONSCRYPT_UNUSED jobject ssl_holder,
7568 jbyteArray list) {
7569 CHECK_ERROR_QUEUE_ON_RETURN;
7570 SSL* ssl = to_SSL(env, ssl_address, true);
7571 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
7572 if (ssl == nullptr) {
7573 return;
7574 }
7575
7576 ScopedByteArrayRO listBytes(env, list);
7577 if (listBytes.get() == nullptr) {
7578 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
7579 return;
7580 }
7581
7582 if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
7583 listBytes.size())) {
7584 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
7585 } else {
7586 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
7587 }
7588 }
7589
7590 /*
7591 * public static native void SSL_enable_ocsp_stapling(long ssl);
7592 */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7593 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
7594 CONSCRYPT_UNUSED jobject ssl_holder) {
7595 CHECK_ERROR_QUEUE_ON_RETURN;
7596 SSL* ssl = to_SSL(env, ssl_address, true);
7597 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
7598 if (ssl == nullptr) {
7599 return;
7600 }
7601
7602 SSL_enable_ocsp_stapling(ssl);
7603 }
7604
7605 /*
7606 * public static native byte[] SSL_get_ocsp_response(long ssl);
7607 */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7608 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7609 CONSCRYPT_UNUSED jobject ssl_holder) {
7610 CHECK_ERROR_QUEUE_ON_RETURN;
7611 SSL* ssl = to_SSL(env, ssl_address, true);
7612 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
7613 if (ssl == nullptr) {
7614 return nullptr;
7615 }
7616
7617 const uint8_t* data;
7618 size_t data_len;
7619 SSL_get0_ocsp_response(ssl, &data, &data_len);
7620
7621 if (data_len == 0) {
7622 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
7623 return nullptr;
7624 }
7625
7626 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7627 if (byteArray.get() == nullptr) {
7628 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
7629 return nullptr;
7630 }
7631
7632 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7633 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
7634 data_len);
7635
7636 return byteArray.release();
7637 }
7638
7639 /*
7640 * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
7641 */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)7642 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7643 CONSCRYPT_UNUSED jobject ssl_holder,
7644 jbyteArray response) {
7645 CHECK_ERROR_QUEUE_ON_RETURN;
7646 SSL* ssl = to_SSL(env, ssl_address, true);
7647 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
7648 if (ssl == nullptr) {
7649 return;
7650 }
7651
7652 ScopedByteArrayRO responseBytes(env, response);
7653 if (responseBytes.get() == nullptr) {
7654 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
7655 return;
7656 }
7657
7658 if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
7659 responseBytes.size())) {
7660 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
7661 } else {
7662 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
7663 }
7664 }
7665
7666 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
7667 // to customize the length of their verify_data (with a default of 12 bytes). We accept
7668 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
7669 // tests and update this value if necessary.
7670 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
7671
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7672 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
7673 CONSCRYPT_UNUSED jobject ssl_holder) {
7674 CHECK_ERROR_QUEUE_ON_RETURN;
7675 SSL* ssl = to_SSL(env, ssl_address, true);
7676 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
7677 if (ssl == nullptr) {
7678 return nullptr;
7679 }
7680
7681 uint8_t data[MAX_TLS_UNIQUE_LENGTH];
7682 size_t data_len;
7683 int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
7684
7685 if (!ret || data_len == 0) {
7686 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
7687 return nullptr;
7688 }
7689
7690 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7691 if (byteArray.get() == nullptr) {
7692 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
7693 return nullptr;
7694 }
7695
7696 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7697 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
7698 data_len);
7699
7700 return byteArray.release();
7701 }
7702
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)7703 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
7704 CONSCRYPT_UNUSED jobject ssl_holder,
7705 jbyteArray label, jbyteArray context,
7706 jint num_bytes) {
7707 CHECK_ERROR_QUEUE_ON_RETURN;
7708 SSL* ssl = to_SSL(env, ssl_address, true);
7709 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
7710 if (ssl == nullptr) {
7711 return nullptr;
7712 }
7713 ScopedByteArrayRO labelBytes(env, label);
7714 if (labelBytes.get() == nullptr) {
7715 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
7716 return nullptr;
7717 }
7718 std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
7719 int ret;
7720 if (context == nullptr) {
7721 ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
7722 reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
7723 nullptr, 0, 0);
7724 } else {
7725 ScopedByteArrayRO contextBytes(env, context);
7726 if (contextBytes.get() == nullptr) {
7727 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
7728 ssl);
7729 return nullptr;
7730 }
7731 ret = SSL_export_keying_material(
7732 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
7733 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
7734 contextBytes.size(), 1);
7735 }
7736 if (!ret) {
7737 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
7738 conscrypt::jniutil::throwSSLExceptionStr);
7739 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
7740 return nullptr;
7741 }
7742 jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
7743 if (result == nullptr) {
7744 conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
7745 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
7746 return nullptr;
7747 }
7748 const jbyte* src = reinterpret_cast<jbyte*>(out.get());
7749 env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
7750 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
7751 return result;
7752 }
7753
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)7754 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
7755 CONSCRYPT_UNUSED jobject ssl_holder,
7756 jstring identityHintJava) {
7757 CHECK_ERROR_QUEUE_ON_RETURN;
7758 SSL* ssl = to_SSL(env, ssl_address, true);
7759 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
7760 identityHintJava);
7761 if (ssl == nullptr) {
7762 return;
7763 }
7764
7765 int ret;
7766 if (identityHintJava == nullptr) {
7767 ret = SSL_use_psk_identity_hint(ssl, nullptr);
7768 } else {
7769 ScopedUtfChars identityHint(env, identityHintJava);
7770 if (identityHint.c_str() == nullptr) {
7771 conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7772 return;
7773 }
7774 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7775 }
7776
7777 if (ret != 1) {
7778 int sslErrorCode = SSL_get_error(ssl, ret);
7779 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7780 "Failed to set PSK identity hint");
7781 }
7782 }
7783
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7784 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7785 CONSCRYPT_UNUSED jobject ssl_holder,
7786 jboolean enabled) {
7787 CHECK_ERROR_QUEUE_ON_RETURN;
7788 SSL* ssl = to_SSL(env, ssl_address, true);
7789 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
7790 if (ssl == nullptr) {
7791 return;
7792 }
7793
7794 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
7795 }
7796
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7797 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7798 CONSCRYPT_UNUSED jobject ssl_holder,
7799 jboolean enabled) {
7800 CHECK_ERROR_QUEUE_ON_RETURN;
7801 SSL* ssl = to_SSL(env, ssl_address, true);
7802 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
7803 if (ssl == nullptr) {
7804 return;
7805 }
7806
7807 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
7808 }
7809
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7810 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
7811 CONSCRYPT_UNUSED jobject ssl_holder) {
7812 CHECK_ERROR_QUEUE_ON_RETURN;
7813 SSL* ssl = to_SSL(env, ssl_address, true);
7814 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7815 if (ssl == nullptr) {
7816 return nullptr;
7817 }
7818
7819 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7820 size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7821 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
7822 ScopedLongArrayRW ciphers(env, ciphersArray.get());
7823 for (size_t i = 0; i < count; i++) {
7824 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7825 }
7826
7827 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
7828 return ciphersArray.release();
7829 }
7830
7831 /**
7832 * Sets the ciphers suites that are enabled in the SSL
7833 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)7834 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
7835 CONSCRYPT_UNUSED jobject ssl_holder,
7836 jobjectArray cipherSuites) {
7837 CHECK_ERROR_QUEUE_ON_RETURN;
7838 SSL* ssl = to_SSL(env, ssl_address, true);
7839 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7840 if (ssl == nullptr) {
7841 return;
7842 }
7843 if (cipherSuites == nullptr) {
7844 conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
7845 return;
7846 }
7847
7848 int length = env->GetArrayLength(cipherSuites);
7849
7850 /*
7851 * Special case for empty cipher list. This is considered an error by the
7852 * SSL_set_cipher_list API, but Java allows this silly configuration.
7853 * However, the SSL cipher list is still set even when SSL_set_cipher_list
7854 * returns 0 in this case. Just to make sure, we check the resulting cipher
7855 * list to make sure it's zero length.
7856 */
7857 if (length == 0) {
7858 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
7859 SSL_set_cipher_list(ssl, "");
7860 ERR_clear_error();
7861 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
7862 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
7863 conscrypt::jniutil::throwRuntimeException(
7864 env, "SSL_set_cipher_list did not update ciphers!");
7865 ERR_clear_error();
7866 }
7867 return;
7868 }
7869
7870 static const char noSSLv2[] = "!SSLv2";
7871 size_t cipherStringLen = strlen(noSSLv2);
7872
7873 for (int i = 0; i < length; i++) {
7874 ScopedLocalRef<jstring> cipherSuite(
7875 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7876 ScopedUtfChars c(env, cipherSuite.get());
7877 if (c.c_str() == nullptr) {
7878 return;
7879 }
7880
7881 if (cipherStringLen + 1 < cipherStringLen) {
7882 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7883 "Overflow in cipher suite strings");
7884 return;
7885 }
7886 cipherStringLen += 1; /* For the separating colon */
7887
7888 if (cipherStringLen + c.size() < cipherStringLen) {
7889 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7890 "Overflow in cipher suite strings");
7891 return;
7892 }
7893 cipherStringLen += c.size();
7894 }
7895
7896 if (cipherStringLen + 1 < cipherStringLen) {
7897 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7898 "Overflow in cipher suite strings");
7899 return;
7900 }
7901 cipherStringLen += 1; /* For final NUL. */
7902
7903 std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
7904 if (cipherString.get() == nullptr) {
7905 conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
7906 return;
7907 }
7908 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
7909 size_t j = strlen(noSSLv2);
7910
7911 for (int i = 0; i < length; i++) {
7912 ScopedLocalRef<jstring> cipherSuite(
7913 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7914 ScopedUtfChars c(env, cipherSuite.get());
7915
7916 cipherString[j++] = ':';
7917 memcpy(&cipherString[j], c.c_str(), c.size());
7918 j += c.size();
7919 }
7920
7921 cipherString[j++] = 0;
7922 if (j != cipherStringLen) {
7923 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7924 "Internal error");
7925 return;
7926 }
7927
7928 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
7929 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
7930 ERR_clear_error();
7931 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7932 "Illegal cipher suite strings.");
7933 return;
7934 }
7935 }
7936
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7937 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
7938 CONSCRYPT_UNUSED jobject ssl_holder) {
7939 CHECK_ERROR_QUEUE_ON_RETURN;
7940 SSL* ssl = to_SSL(env, ssl_address, true);
7941 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7942 if (ssl == nullptr) {
7943 return;
7944 }
7945 SSL_set_accept_state(ssl);
7946 }
7947
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7948 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
7949 CONSCRYPT_UNUSED jobject ssl_holder) {
7950 CHECK_ERROR_QUEUE_ON_RETURN;
7951 SSL* ssl = to_SSL(env, ssl_address, true);
7952 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7953 if (ssl == nullptr) {
7954 return;
7955 }
7956 SSL_set_connect_state(ssl);
7957 }
7958
7959 /**
7960 * Sets certificate expectations, especially for server to request client auth
7961 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)7962 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
7963 CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
7964 CHECK_ERROR_QUEUE_ON_RETURN;
7965 SSL* ssl = to_SSL(env, ssl_address, true);
7966 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7967 if (ssl == nullptr) {
7968 return;
7969 }
7970 SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
7971 }
7972
7973 /**
7974 * Sets the ciphers suites that are enabled in the SSL
7975 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)7976 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
7977 CONSCRYPT_UNUSED jobject ssl_holder,
7978 jlong ssl_session_address) {
7979 CHECK_ERROR_QUEUE_ON_RETURN;
7980 SSL* ssl = to_SSL(env, ssl_address, true);
7981 if (ssl == nullptr) {
7982 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
7983 return;
7984 }
7985
7986 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7987 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7988 if (ssl_session == nullptr) {
7989 return;
7990 }
7991
7992 int ret = SSL_set_session(ssl, ssl_session);
7993 if (ret != 1) {
7994 /*
7995 * Translate the error, and throw if it turns out to be a real
7996 * problem.
7997 */
7998 int sslErrorCode = SSL_get_error(ssl, ret);
7999 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8000 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8001 "SSL session set");
8002 }
8003 }
8004 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8005 ret);
8006 }
8007
8008 /**
8009 * Sets the ciphers suites that are enabled in the SSL
8010 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8011 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8012 CONSCRYPT_UNUSED jobject ssl_holder,
8013 jboolean creation_enabled) {
8014 CHECK_ERROR_QUEUE_ON_RETURN;
8015 SSL* ssl = to_SSL(env, ssl_address, true);
8016 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8017 creation_enabled);
8018 if (ssl == nullptr) {
8019 return;
8020 }
8021
8022 if (creation_enabled) {
8023 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8024 } else {
8025 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8026 }
8027 }
8028
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8029 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8030 CONSCRYPT_UNUSED jobject ssl_holder) {
8031 CHECK_ERROR_QUEUE_ON_RETURN;
8032 SSL* ssl = to_SSL(env, ssl_address, true);
8033 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8034 if (ssl == nullptr) {
8035 return JNI_FALSE;
8036 }
8037
8038 int reused = SSL_session_reused(ssl);
8039 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8040 return static_cast<jboolean>(reused);
8041 }
8042
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8043 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8044 CONSCRYPT_UNUSED jobject ssl_holder) {
8045 CHECK_ERROR_QUEUE_ON_RETURN;
8046 SSL* ssl = to_SSL(env, ssl_address, true);
8047 JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8048 if (ssl == nullptr) {
8049 return;
8050 }
8051
8052 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8053 }
8054
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8055 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8056 CONSCRYPT_UNUSED jobject ssl_holder,
8057 jstring hostname) {
8058 CHECK_ERROR_QUEUE_ON_RETURN;
8059 SSL* ssl = to_SSL(env, ssl_address, true);
8060 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8061 if (ssl == nullptr) {
8062 return;
8063 }
8064
8065 ScopedUtfChars hostnameChars(env, hostname);
8066 if (hostnameChars.c_str() == nullptr) {
8067 return;
8068 }
8069 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8070 hostnameChars.c_str());
8071
8072 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8073 if (ret != 1) {
8074 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8075 "Error setting host name");
8076 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8077 return;
8078 }
8079 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8080 }
8081
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8082 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8083 CONSCRYPT_UNUSED jobject ssl_holder) {
8084 CHECK_ERROR_QUEUE_ON_RETURN;
8085 SSL* ssl = to_SSL(env, ssl_address, true);
8086 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8087 if (ssl == nullptr) {
8088 return nullptr;
8089 }
8090 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8091 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8092 return env->NewStringUTF(servername);
8093 }
8094
8095 /**
8096 * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8097 * which should take precedence.
8098 */
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)8099 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8100 const unsigned char* primary,
8101 const unsigned int primaryLength,
8102 const unsigned char* secondary,
8103 const unsigned int secondaryLength) {
8104 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8105
8106 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8107 secondaryLength);
8108 switch (status) {
8109 case OPENSSL_NPN_NEGOTIATED:
8110 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8111 return SSL_TLSEXT_ERR_OK;
8112 break;
8113 case OPENSSL_NPN_UNSUPPORTED:
8114 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8115 break;
8116 case OPENSSL_NPN_NO_OVERLAP:
8117 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8118 break;
8119 }
8120 return SSL_TLSEXT_ERR_NOACK;
8121 }
8122
8123 /**
8124 * Calls out to an application-provided selector to choose the ALPN protocol.
8125 */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8126 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8127 unsigned char** out,
8128 unsigned char* outLen, const unsigned char* in,
8129 const unsigned int inLen) {
8130 // Copy the input array.
8131 ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8132 if (protocols.get() == nullptr) {
8133 JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8134 return SSL_TLSEXT_ERR_NOACK;
8135 }
8136 env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8137 reinterpret_cast<const jbyte*>(in));
8138
8139 // Invoke the selection method.
8140 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8141 jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8142
8143 if (offset < 0) {
8144 JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8145 return SSL_TLSEXT_ERR_NOACK;
8146 }
8147
8148 // Point the output to the selected protocol.
8149 *outLen = *(in + offset);
8150 *out = const_cast<unsigned char*>(in + offset + 1);
8151
8152 return SSL_TLSEXT_ERR_OK;
8153 }
8154
8155 /**
8156 * Callback for the server to select an ALPN protocol.
8157 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8158 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8159 const unsigned char* in, unsigned int inLen, void*) {
8160 JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8161
8162 AppData* appData = toAppData(ssl);
8163 if (appData == nullptr) {
8164 JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8165 return SSL_TLSEXT_ERR_NOACK;
8166 }
8167 JNIEnv* env = appData->env;
8168 if (env == nullptr) {
8169 CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8170 JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8171 return SSL_TLSEXT_ERR_NOACK;
8172 }
8173
8174 if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8175 !appData->hasApplicationProtocolSelector)) {
8176 if (out != nullptr && outLen != nullptr) {
8177 *out = nullptr;
8178 *outLen = 0;
8179 }
8180 JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8181 return SSL_TLSEXT_ERR_NOACK;
8182 }
8183
8184 if (appData->hasApplicationProtocolSelector) {
8185 return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8186 const_cast<unsigned char**>(out), outLen, in, inLen);
8187 }
8188
8189 return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8190 reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8191 static_cast<unsigned int>(appData->applicationProtocolsLength),
8192 in, inLen);
8193 }
8194
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8195 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8196 CONSCRYPT_UNUSED jobject ssl_holder) {
8197 CHECK_ERROR_QUEUE_ON_RETURN;
8198 SSL* ssl = to_SSL(env, ssl_address, true);
8199 JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8200 if (ssl == nullptr) {
8201 return nullptr;
8202 }
8203 const jbyte* protocol;
8204 unsigned int protocolLength;
8205 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8206 &protocolLength);
8207 if (protocolLength == 0) {
8208 return nullptr;
8209 }
8210 jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8211 if (result != nullptr) {
8212 env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8213 }
8214 return result;
8215 }
8216
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8217 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8218 CONSCRYPT_UNUSED jobject ssl_holder,
8219 jboolean client_mode, jbyteArray protocols) {
8220 CHECK_ERROR_QUEUE_ON_RETURN;
8221 SSL* ssl = to_SSL(env, ssl_address, true);
8222 if (ssl == nullptr) {
8223 return;
8224 }
8225 AppData* appData = toAppData(ssl);
8226 if (appData == nullptr) {
8227 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8228 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8229 return;
8230 }
8231
8232 if (protocols != nullptr) {
8233 if (client_mode) {
8234 ScopedByteArrayRO protosBytes(env, protocols);
8235 if (protosBytes.get() == nullptr) {
8236 JNI_TRACE(
8237 "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8238 "protosBytes == null",
8239 ssl, protocols);
8240 return;
8241 }
8242
8243 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8244 int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8245 if (ret != 0) {
8246 conscrypt::jniutil::throwSSLExceptionStr(env,
8247 "Unable to set ALPN protocols for client");
8248 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8249 return;
8250 }
8251 } else {
8252 // Server mode - configure the ALPN protocol selection callback.
8253 if (!appData->setApplicationProtocols(env, protocols)) {
8254 conscrypt::jniutil::throwSSLExceptionStr(env,
8255 "Unable to set ALPN protocols for server");
8256 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8257 return;
8258 }
8259 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8260 }
8261 }
8262 }
8263
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8264 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8265 CONSCRYPT_UNUSED jobject ssl_holder,
8266 jboolean hasSelector) {
8267 CHECK_ERROR_QUEUE_ON_RETURN;
8268 SSL* ssl = to_SSL(env, ssl_address, true);
8269 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8270 hasSelector);
8271 if (ssl == nullptr) {
8272 return;
8273 }
8274 AppData* appData = toAppData(ssl);
8275 if (appData == nullptr) {
8276 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8277 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8278 return;
8279 }
8280
8281 appData->hasApplicationProtocolSelector = hasSelector;
8282 if (hasSelector) {
8283 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8284 }
8285 }
8286
8287 /**
8288 * Perform SSL handshake
8289 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8290 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8291 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8292 jobject shc, jint timeout_millis) {
8293 CHECK_ERROR_QUEUE_ON_RETURN;
8294 SSL* ssl = to_SSL(env, ssl_address, true);
8295 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8296 shc, timeout_millis);
8297 if (ssl == nullptr) {
8298 return;
8299 }
8300 if (fdObject == nullptr) {
8301 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8302 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8303 return;
8304 }
8305 if (shc == nullptr) {
8306 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8307 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8308 ssl);
8309 return;
8310 }
8311
8312 NetFd fd(env, fdObject);
8313 if (fd.isClosed()) {
8314 // SocketException thrown by NetFd.isClosed
8315 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8316 return;
8317 }
8318
8319 int ret = SSL_set_fd(ssl, fd.get());
8320 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8321
8322 if (ret != 1) {
8323 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8324 "Error setting the file descriptor");
8325 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8326 return;
8327 }
8328
8329 /*
8330 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8331 * forever and we can use select() to find out if the socket is ready.
8332 */
8333 if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8334 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8335 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8336 return;
8337 }
8338
8339 AppData* appData = toAppData(ssl);
8340 if (appData == nullptr) {
8341 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8342 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8343 return;
8344 }
8345
8346 ret = 0;
8347 SslError sslError;
8348 while (appData->aliveAndKicking) {
8349 errno = 0;
8350
8351 if (!appData->setCallbackState(env, shc, fdObject)) {
8352 // SocketException thrown by NetFd.isClosed
8353 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8354 return;
8355 }
8356 ret = SSL_do_handshake(ssl);
8357 appData->clearCallbackState();
8358 // cert_verify_callback threw exception
8359 if (env->ExceptionCheck()) {
8360 ERR_clear_error();
8361 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8362 return;
8363 }
8364 // success case
8365 if (ret == 1) {
8366 break;
8367 }
8368 // retry case
8369 if (errno == EINTR) {
8370 continue;
8371 }
8372 // error case
8373 sslError.reset(ssl, ret);
8374 JNI_TRACE(
8375 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8376 "timeout_millis=%d",
8377 ssl, ret, errno, sslError.get(), timeout_millis);
8378
8379 /*
8380 * If SSL_do_handshake doesn't succeed due to the socket being
8381 * either unreadable or unwritable, we use sslSelect to
8382 * wait for it to become ready. If that doesn't happen
8383 * before the specified timeout or an error occurs, we
8384 * cancel the handshake. Otherwise we try the SSL_connect
8385 * again.
8386 */
8387 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8388 appData->waitingThreads++;
8389 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8390
8391 if (selectResult == THROWN_EXCEPTION) {
8392 // SocketException thrown by NetFd.isClosed
8393 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8394 return;
8395 }
8396 if (selectResult == -1) {
8397 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8398 env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8399 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8400 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8401 ssl);
8402 return;
8403 }
8404 if (selectResult == 0) {
8405 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8406 ERR_clear_error();
8407 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8408 ssl);
8409 return;
8410 }
8411 } else {
8412 // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8413 break;
8414 }
8415 }
8416
8417 // clean error. See SSL_do_handshake(3SSL) man page.
8418 if (ret == 0) {
8419 /*
8420 * The other side closed the socket before the handshake could be
8421 * completed, but everything is within the bounds of the TLS protocol.
8422 * We still might want to find out the real reason of the failure.
8423 */
8424 if (sslError.get() == SSL_ERROR_NONE ||
8425 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8426 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8427 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8428 } else {
8429 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8430 env, ssl, sslError.release(), "SSL handshake terminated",
8431 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8432 }
8433 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8434 return;
8435 }
8436
8437 // unclean error. See SSL_do_handshake(3SSL) man page.
8438 if (ret < 0) {
8439 /*
8440 * Translate the error and throw exception. We are sure it is an error
8441 * at this point.
8442 */
8443 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8444 env, ssl, sslError.release(), "SSL handshake aborted",
8445 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8446 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
8447 return;
8448 }
8449 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
8450 }
8451
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8452 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
8453 CONSCRYPT_UNUSED jobject ssl_holder) {
8454 CHECK_ERROR_QUEUE_ON_RETURN;
8455 SSL* ssl = to_SSL(env, ssl_address, true);
8456 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
8457 if (ssl == nullptr) {
8458 return nullptr;
8459 }
8460 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
8461 if (cipher == nullptr) {
8462 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
8463 return nullptr;
8464 }
8465 const char* name = SSL_CIPHER_standard_name(cipher);
8466 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
8467 return env->NewStringUTF(name);
8468 }
8469
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8470 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
8471 CONSCRYPT_UNUSED jobject ssl_holder) {
8472 CHECK_ERROR_QUEUE_ON_RETURN;
8473 SSL* ssl = to_SSL(env, ssl_address, true);
8474 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
8475 if (ssl == nullptr) {
8476 return nullptr;
8477 }
8478 const char* protocol = SSL_get_version(ssl);
8479 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
8480 return env->NewStringUTF(protocol);
8481 }
8482
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8483 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
8484 CONSCRYPT_UNUSED jobject ssl_holder) {
8485 CHECK_ERROR_QUEUE_ON_RETURN;
8486 SSL* ssl = to_SSL(env, ssl_address, true);
8487 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
8488 if (ssl == nullptr) {
8489 return nullptr;
8490 }
8491
8492 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
8493 if (chain == nullptr) {
8494 return nullptr;
8495 }
8496
8497 ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
8498 if (array.get() == nullptr) {
8499 return nullptr;
8500 }
8501
8502 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
8503 return array.release();
8504 }
8505
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)8506 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8507 SslError* sslError, int read_timeout_millis) {
8508 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8509
8510 if (len == 0) {
8511 // Don't bother doing anything in this case.
8512 return 0;
8513 }
8514
8515 BIO* rbio = SSL_get_rbio(ssl);
8516 BIO* wbio = SSL_get_wbio(ssl);
8517
8518 AppData* appData = toAppData(ssl);
8519 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8520 if (appData == nullptr) {
8521 return THROW_SSLEXCEPTION;
8522 }
8523
8524 while (appData->aliveAndKicking) {
8525 errno = 0;
8526
8527 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8528
8529 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8530 !SSL_renegotiate_pending(ssl)) {
8531 JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
8532 SSL_state_string_long(ssl));
8533 return THROW_SSLEXCEPTION;
8534 }
8535
8536 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8537
8538 if (!appData->setCallbackState(env, shc, fdObject)) {
8539 return THROWN_EXCEPTION;
8540 }
8541 int result = SSL_read(ssl, buf, len);
8542 appData->clearCallbackState();
8543 // callbacks can happen if server requests renegotiation
8544 if (env->ExceptionCheck()) {
8545 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8546 return THROWN_EXCEPTION;
8547 }
8548 sslError->reset(ssl, result);
8549
8550 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
8551 if (conscrypt::trace::kWithJniTraceData) {
8552 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8553 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8554 size_t n = result - i;
8555 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8556 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8557 }
8558 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8559 }
8560 }
8561
8562 // If we have been successful in moving data around, check whether it
8563 // might make sense to wake up other blocked threads, so they can give
8564 // it a try, too.
8565 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8566 appData->waitingThreads > 0) {
8567 sslNotify(appData);
8568 }
8569
8570 // If we are blocked by the underlying socket, tell the world that
8571 // there will be one more waiting thread now.
8572 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8573 appData->waitingThreads++;
8574 }
8575
8576 appDataLock.unlock();
8577
8578 switch (sslError->get()) {
8579 // Successfully read at least one byte.
8580 case SSL_ERROR_NONE: {
8581 return result;
8582 }
8583
8584 // Read zero bytes. End of stream reached.
8585 case SSL_ERROR_ZERO_RETURN: {
8586 return -1;
8587 }
8588
8589 // Need to wait for availability of underlying layer, then retry.
8590 case SSL_ERROR_WANT_READ:
8591 case SSL_ERROR_WANT_WRITE: {
8592 int selectResult =
8593 sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
8594 if (selectResult == THROWN_EXCEPTION) {
8595 return THROWN_EXCEPTION;
8596 }
8597 if (selectResult == -1) {
8598 return THROW_SSLEXCEPTION;
8599 }
8600 if (selectResult == 0) {
8601 return THROW_SOCKETTIMEOUTEXCEPTION;
8602 }
8603
8604 break;
8605 }
8606
8607 // A problem occurred during a system call, but this is not
8608 // necessarily an error.
8609 case SSL_ERROR_SYSCALL: {
8610 // Connection closed without proper shutdown. Tell caller we
8611 // have reached end-of-stream.
8612 if (result == 0) {
8613 return -1;
8614 }
8615
8616 // System call has been interrupted. Simply retry.
8617 if (errno == EINTR) {
8618 break;
8619 }
8620
8621 // Note that for all other system call errors we fall through
8622 // to the default case, which results in an Exception.
8623 FALLTHROUGH_INTENDED;
8624 }
8625
8626 // Everything else is basically an error.
8627 default: { return THROW_SSLEXCEPTION; }
8628 }
8629 }
8630
8631 return -1;
8632 }
8633
8634 /**
8635 * OpenSSL read function (2): read into buffer at offset n chunks.
8636 * Returns the number of bytes read (success) or value <= 0 (failure).
8637 */
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)8638 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
8639 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8640 jobject shc, jbyteArray b, jint offset, jint len,
8641 jint read_timeout_millis) {
8642 CHECK_ERROR_QUEUE_ON_RETURN;
8643 SSL* ssl = to_SSL(env, ssl_address, true);
8644 JNI_TRACE(
8645 "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
8646 "read_timeout_millis=%d",
8647 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8648 if (ssl == nullptr) {
8649 return 0;
8650 }
8651 if (fdObject == nullptr) {
8652 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8653 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8654 return 0;
8655 }
8656 if (shc == nullptr) {
8657 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8658 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8659 return 0;
8660 }
8661 if (b == nullptr) {
8662 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8663 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
8664 return 0;
8665 }
8666
8667 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8668 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8669 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8670 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
8671 return 0;
8672 }
8673
8674 SslError sslError;
8675 int ret;
8676 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8677 if (len <= 1024) {
8678 // Allocate small buffers on the stack for performance.
8679 jbyte buf[1024];
8680 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
8681 read_timeout_millis);
8682 if (ret > 0) {
8683 // Don't bother applying changes if issues were encountered.
8684 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
8685 }
8686 } else {
8687 // Allocate larger buffers on the heap.
8688 // ARRAY_CHUNK_INVALID above ensures that len >= 0.
8689 jint remaining = len;
8690 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8691 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8692 // TODO(flooey): Use new(std::nothrow).
8693 if (buf.get() == nullptr) {
8694 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8695 return 0;
8696 }
8697 // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
8698 // by the number of internal calls to sslRead() below.
8699 ret = 0;
8700 while (remaining > 0) {
8701 jint temp_ret;
8702 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8703 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
8704 chunk_size, &sslError, read_timeout_millis);
8705 if (temp_ret < 0) {
8706 if (ret > 0) {
8707 // We've already read some bytes; attempt to preserve them if this is an
8708 // "expected" error.
8709 if (temp_ret == -1) {
8710 // EOF
8711 break;
8712 } else if (temp_ret == THROWN_EXCEPTION) {
8713 // FD closed. Subsequent calls to sslRead should reproduce the
8714 // exception.
8715 env->ExceptionClear();
8716 break;
8717 }
8718 }
8719 // An error was encountered. Handle below.
8720 ret = temp_ret;
8721 break;
8722 }
8723 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
8724 if (env->ExceptionCheck()) {
8725 // Error committing changes to JVM.
8726 return -1;
8727 }
8728 // Accumulate bytes read.
8729 ret += temp_ret;
8730 offset += temp_ret;
8731 remaining -= temp_ret;
8732 if (temp_ret < chunk_size) {
8733 // sslRead isn't able to fulfill our request right now.
8734 break;
8735 }
8736 }
8737 }
8738 } else {
8739 ScopedByteArrayRW bytes(env, b);
8740 if (bytes.get() == nullptr) {
8741 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8742 return 0;
8743 }
8744
8745 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8746 &sslError, read_timeout_millis);
8747 }
8748
8749 int result;
8750 switch (ret) {
8751 case THROW_SSLEXCEPTION:
8752 // See sslRead() regarding improper failure to handle normal cases.
8753 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8754 "Read error");
8755 result = -1;
8756 break;
8757 case THROW_SOCKETTIMEOUTEXCEPTION:
8758 conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
8759 result = -1;
8760 break;
8761 case THROWN_EXCEPTION:
8762 // SocketException thrown by NetFd.isClosed
8763 // or RuntimeException thrown by callback
8764 result = -1;
8765 break;
8766 default:
8767 result = ret;
8768 break;
8769 }
8770
8771 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8772 return result;
8773 }
8774
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)8775 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8776 SslError* sslError, int write_timeout_millis) {
8777 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
8778 write_timeout_millis);
8779
8780 if (len == 0) {
8781 // Don't bother doing anything in this case.
8782 return 0;
8783 }
8784
8785 BIO* rbio = SSL_get_rbio(ssl);
8786 BIO* wbio = SSL_get_wbio(ssl);
8787
8788 AppData* appData = toAppData(ssl);
8789 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8790 if (appData == nullptr) {
8791 return THROW_SSLEXCEPTION;
8792 }
8793
8794 int count = len;
8795
8796 while (appData->aliveAndKicking && len > 0) {
8797 errno = 0;
8798
8799 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8800
8801 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8802 !SSL_renegotiate_pending(ssl)) {
8803 JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
8804 SSL_state_string_long(ssl));
8805 return THROW_SSLEXCEPTION;
8806 }
8807
8808 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8809
8810 if (!appData->setCallbackState(env, shc, fdObject)) {
8811 return THROWN_EXCEPTION;
8812 }
8813 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
8814 int result = SSL_write(ssl, buf, len);
8815 appData->clearCallbackState();
8816 // callbacks can happen if server requests renegotiation
8817 if (env->ExceptionCheck()) {
8818 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8819 return THROWN_EXCEPTION;
8820 }
8821 sslError->reset(ssl, result);
8822
8823 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
8824 if (conscrypt::trace::kWithJniTraceData) {
8825 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8826 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8827 size_t n = result - i;
8828 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8829 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8830 }
8831 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8832 }
8833 }
8834
8835 // If we have been successful in moving data around, check whether it
8836 // might make sense to wake up other blocked threads, so they can give
8837 // it a try, too.
8838 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8839 appData->waitingThreads > 0) {
8840 sslNotify(appData);
8841 }
8842
8843 // If we are blocked by the underlying socket, tell the world that
8844 // there will be one more waiting thread now.
8845 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8846 appData->waitingThreads++;
8847 }
8848
8849 appDataLock.unlock();
8850
8851 switch (sslError->get()) {
8852 // Successfully wrote at least one byte.
8853 case SSL_ERROR_NONE: {
8854 buf += result;
8855 len -= result;
8856 break;
8857 }
8858
8859 // Wrote zero bytes. End of stream reached.
8860 case SSL_ERROR_ZERO_RETURN: {
8861 return -1;
8862 }
8863
8864 // Need to wait for availability of underlying layer, then retry.
8865 // The concept of a write timeout doesn't really make sense, and
8866 // it's also not standard Java behavior, so we wait forever here.
8867 case SSL_ERROR_WANT_READ:
8868 case SSL_ERROR_WANT_WRITE: {
8869 int selectResult =
8870 sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
8871 if (selectResult == THROWN_EXCEPTION) {
8872 return THROWN_EXCEPTION;
8873 }
8874 if (selectResult == -1) {
8875 return THROW_SSLEXCEPTION;
8876 }
8877 if (selectResult == 0) {
8878 return THROW_SOCKETTIMEOUTEXCEPTION;
8879 }
8880
8881 break;
8882 }
8883
8884 // A problem occurred during a system call, but this is not
8885 // necessarily an error.
8886 case SSL_ERROR_SYSCALL: {
8887 // Connection closed without proper shutdown. Tell caller we
8888 // have reached end-of-stream.
8889 if (result == 0) {
8890 return -1;
8891 }
8892
8893 // System call has been interrupted. Simply retry.
8894 if (errno == EINTR) {
8895 break;
8896 }
8897
8898 // Note that for all other system call errors we fall through
8899 // to the default case, which results in an Exception.
8900 FALLTHROUGH_INTENDED;
8901 }
8902
8903 // Everything else is basically an error.
8904 default: { return THROW_SSLEXCEPTION; }
8905 }
8906 }
8907 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8908
8909 return count;
8910 }
8911
8912 /**
8913 * OpenSSL write function (2): write into buffer at offset n chunks.
8914 */
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)8915 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
8916 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8917 jobject shc, jbyteArray b, jint offset, jint len,
8918 jint write_timeout_millis) {
8919 CHECK_ERROR_QUEUE_ON_RETURN;
8920 SSL* ssl = to_SSL(env, ssl_address, true);
8921 JNI_TRACE(
8922 "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
8923 "write_timeout_millis=%d",
8924 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8925 if (ssl == nullptr) {
8926 return;
8927 }
8928 if (fdObject == nullptr) {
8929 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8930 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8931 return;
8932 }
8933 if (shc == nullptr) {
8934 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8935 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8936 return;
8937 }
8938 if (b == nullptr) {
8939 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8940 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
8941 return;
8942 }
8943
8944 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8945 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8946 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8947 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
8948 return;
8949 }
8950
8951 SslError sslError;
8952 int ret;
8953 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8954 if (len <= 1024) {
8955 jbyte buf[1024];
8956 env->GetByteArrayRegion(b, offset, len, buf);
8957 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
8958 &sslError, write_timeout_millis);
8959 } else {
8960 // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
8961 jint remaining = len;
8962 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8963 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8964 if (buf.get() == nullptr) {
8965 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8966 return;
8967 }
8968 while (remaining > 0) {
8969 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8970 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
8971 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
8972 chunk_size, &sslError, write_timeout_millis);
8973 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
8974 ret == THROWN_EXCEPTION) {
8975 // Encountered an error. Terminate early and handle below.
8976 break;
8977 }
8978 offset += ret;
8979 remaining -= ret;
8980 }
8981 }
8982 } else {
8983 ScopedByteArrayRO bytes(env, b);
8984 if (bytes.get() == nullptr) {
8985 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8986 return;
8987 }
8988 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8989 len, &sslError, write_timeout_millis);
8990 }
8991
8992 switch (ret) {
8993 case THROW_SSLEXCEPTION:
8994 // See sslWrite() regarding improper failure to handle normal cases.
8995 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8996 "Write error");
8997 break;
8998 case THROW_SOCKETTIMEOUTEXCEPTION:
8999 conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9000 break;
9001 case THROWN_EXCEPTION:
9002 // SocketException thrown by NetFd.isClosed
9003 break;
9004 default:
9005 break;
9006 }
9007 }
9008
9009 /**
9010 * Interrupt any pending I/O before closing the socket.
9011 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9012 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9013 CONSCRYPT_UNUSED jobject ssl_holder) {
9014 CHECK_ERROR_QUEUE_ON_RETURN;
9015 SSL* ssl = to_SSL(env, ssl_address, false);
9016 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9017 if (ssl == nullptr) {
9018 return;
9019 }
9020
9021 /*
9022 * Mark the connection as quasi-dead, then send something to the emergency
9023 * file descriptor, so any blocking select() calls are woken up.
9024 */
9025 AppData* appData = toAppData(ssl);
9026 if (appData != nullptr) {
9027 appData->aliveAndKicking = false;
9028
9029 // At most two threads can be waiting.
9030 sslNotify(appData);
9031 sslNotify(appData);
9032 }
9033 }
9034
9035 /**
9036 * OpenSSL close SSL socket function.
9037 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9038 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9039 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9040 jobject shc) {
9041 CHECK_ERROR_QUEUE_ON_RETURN;
9042 SSL* ssl = to_SSL(env, ssl_address, false);
9043 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9044 if (ssl == nullptr) {
9045 return;
9046 }
9047 if (fdObject == nullptr) {
9048 return;
9049 }
9050 if (shc == nullptr) {
9051 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9052 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9053 return;
9054 }
9055
9056 AppData* appData = toAppData(ssl);
9057 if (appData != nullptr) {
9058 if (!appData->setCallbackState(env, shc, fdObject)) {
9059 // SocketException thrown by NetFd.isClosed
9060 ERR_clear_error();
9061 return;
9062 }
9063
9064 /*
9065 * Try to make socket blocking again. OpenSSL literature recommends this.
9066 */
9067 int fd = SSL_get_fd(ssl);
9068 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9069 #ifndef _WIN32
9070 if (fd != -1) {
9071 conscrypt::netutil::setBlocking(fd, true);
9072 }
9073 #endif
9074
9075 int ret = SSL_shutdown(ssl);
9076 appData->clearCallbackState();
9077 // callbacks can happen if server requests renegotiation
9078 if (env->ExceptionCheck()) {
9079 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9080 return;
9081 }
9082 switch (ret) {
9083 case 0:
9084 /*
9085 * Shutdown was not successful (yet), but there also
9086 * is no error. Since we can't know whether the remote
9087 * server is actually still there, and we don't want to
9088 * get stuck forever in a second SSL_shutdown() call, we
9089 * simply return. This is not security a problem as long
9090 * as we close the underlying socket, which we actually
9091 * do, because that's where we are just coming from.
9092 */
9093 break;
9094 case 1:
9095 /*
9096 * Shutdown was successful. We can safely return. Hooray!
9097 */
9098 break;
9099 default:
9100 /*
9101 * Everything else is a real error condition. We should
9102 * let the Java layer know about this by throwing an
9103 * exception.
9104 */
9105 int sslError = SSL_get_error(ssl, ret);
9106 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9107 "SSL shutdown failed");
9108 break;
9109 }
9110 }
9111
9112 ERR_clear_error();
9113 }
9114
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9115 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9116 CONSCRYPT_UNUSED jobject ssl_holder) {
9117 CHECK_ERROR_QUEUE_ON_RETURN;
9118 const SSL* ssl = to_SSL(env, ssl_address, true);
9119 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9120 if (ssl == nullptr) {
9121 return 0;
9122 }
9123
9124 int status = SSL_get_shutdown(ssl);
9125 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9126 return static_cast<jint>(status);
9127 }
9128
9129 /**
9130 * public static native void SSL_free(long ssl);
9131 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9132 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9133 CONSCRYPT_UNUSED jobject ssl_holder) {
9134 CHECK_ERROR_QUEUE_ON_RETURN;
9135 SSL* ssl = to_SSL(env, ssl_address, true);
9136 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9137 if (ssl == nullptr) {
9138 return;
9139 }
9140
9141 AppData* appData = toAppData(ssl);
9142 SSL_set_app_data(ssl, nullptr);
9143 delete appData;
9144 SSL_free(ssl);
9145 }
9146
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9147 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9148 unsigned int length;
9149 const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9150 JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9151 if (id && length > 0) {
9152 jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9153 if (result != nullptr) {
9154 const jbyte* src = reinterpret_cast<const jbyte*>(id);
9155 env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9156 }
9157 return result;
9158 }
9159 return nullptr;
9160 }
9161
9162 /**
9163 * Gets and returns in a byte array the ID of the actual SSL session.
9164 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9165 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9166 jlong ssl_session_address) {
9167 CHECK_ERROR_QUEUE_ON_RETURN;
9168 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9169 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9170 if (ssl_session == nullptr) {
9171 return nullptr;
9172 }
9173 jbyteArray result = get_session_id(env, ssl_session);
9174 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9175 return result;
9176 }
9177
9178 /**
9179 * Gets and returns in a long integer the creation's time of the
9180 * actual SSL session.
9181 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9182 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9183 CHECK_ERROR_QUEUE_ON_RETURN;
9184 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9185 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9186 if (ssl_session == nullptr) {
9187 return 0;
9188 }
9189 // result must be jlong, not long or *1000 will overflow
9190 jlong result = SSL_SESSION_get_time(ssl_session);
9191 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9192 // NOLINTNEXTLINE(runtime/int)
9193 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9194 (long long)result); // NOLINT(runtime/int)
9195 return result;
9196 }
9197
9198 /**
9199 * Gets and returns in a long integer the creation's time of the
9200 * actual SSL session.
9201 */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9202 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9203 CONSCRYPT_UNUSED jobject ssl_holder) {
9204 CHECK_ERROR_QUEUE_ON_RETURN;
9205 SSL* ssl = to_SSL(env, ssl_address, true);
9206 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9207 if (ssl == nullptr) {
9208 return 0;
9209 }
9210
9211 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9212 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9213 if (ssl_session == nullptr) {
9214 // BoringSSL does not protect against a NULL session.
9215 return 0;
9216 }
9217 // result must be jlong, not long or *1000 will overflow
9218 jlong result = SSL_SESSION_get_time(ssl_session);
9219 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9220 // NOLINTNEXTLINE(runtime/int)
9221 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9222 return result;
9223 }
9224
9225 /**
9226 * Sets the timeout on the SSL session.
9227 */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9228 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9229 CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9230 CHECK_ERROR_QUEUE_ON_RETURN;
9231 SSL* ssl = to_SSL(env, ssl_address, true);
9232 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9233 if (ssl == nullptr) {
9234 return 0;
9235 }
9236
9237 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9238 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9239 if (ssl_session == nullptr) {
9240 // BoringSSL does not protect against a NULL session.
9241 return 0;
9242 }
9243
9244 // Convert to seconds
9245 static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9246 uint32_t timeout = static_cast<uint32_t>(
9247 std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9248 return SSL_set_timeout(ssl_session, timeout);
9249 }
9250
9251 /**
9252 * Gets the timeout for the SSL session.
9253 */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9254 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9255 CONSCRYPT_UNUSED jobject ssl_holder) {
9256 CHECK_ERROR_QUEUE_ON_RETURN;
9257 SSL* ssl = to_SSL(env, ssl_address, true);
9258 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9259 if (ssl == nullptr) {
9260 return 0;
9261 }
9262
9263 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9264 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9265 if (ssl_session == nullptr) {
9266 // BoringSSL does not protect against a NULL session.
9267 return 0;
9268 }
9269
9270 jlong result = SSL_get_timeout(ssl_session);
9271 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9272 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9273 (long long)result) // NOLINT(runtime/int);
9274 return result;
9275 }
9276
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9277 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9278 jint signatureAlg) {
9279 CHECK_ERROR_QUEUE_ON_RETURN;
9280 return SSL_get_signature_algorithm_key_type(signatureAlg);
9281 }
9282
9283 /**
9284 * Gets the timeout for the SSL session.
9285 */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9286 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9287 CHECK_ERROR_QUEUE_ON_RETURN;
9288 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9289 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9290 if (ssl_session == nullptr) {
9291 return 0;
9292 }
9293
9294 return SSL_get_timeout(ssl_session);
9295 }
9296
9297 /**
9298 * Gets the ID for the SSL session, or null if no session is currently available.
9299 */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9300 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9301 CONSCRYPT_UNUSED jobject ssl_holder) {
9302 CHECK_ERROR_QUEUE_ON_RETURN;
9303 SSL* ssl = to_SSL(env, ssl_address, true);
9304 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9305 if (ssl == nullptr) {
9306 return nullptr;
9307 }
9308
9309 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9310 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9311 if (ssl_session == nullptr) {
9312 return nullptr;
9313 }
9314 jbyteArray result = get_session_id(env, ssl_session);
9315 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9316 return result;
9317 }
9318
9319 /**
9320 * Gets and returns in a string the version of the SSL protocol. If it
9321 * returns the string "unknown" it means that no connection is established.
9322 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9323 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9324 jlong ssl_session_address) {
9325 CHECK_ERROR_QUEUE_ON_RETURN;
9326 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9327 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9328 if (ssl_session == nullptr) {
9329 return nullptr;
9330 }
9331 const char* protocol = SSL_SESSION_get_version(ssl_session);
9332 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9333 return env->NewStringUTF(protocol);
9334 }
9335
9336 /**
9337 * Gets and returns in a string the cipher negotiated for the SSL session.
9338 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9339 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9340 CHECK_ERROR_QUEUE_ON_RETURN;
9341 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9342 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9343 if (ssl_session == nullptr) {
9344 return nullptr;
9345 }
9346 const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9347 const char* name = SSL_CIPHER_standard_name(cipher);
9348 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9349 return env->NewStringUTF(name);
9350 }
9351
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9352 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9353 jlong ssl_session_address) {
9354 CHECK_ERROR_QUEUE_ON_RETURN;
9355 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9356 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9357 if (ssl_session == nullptr) {
9358 return JNI_FALSE;
9359 }
9360 int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9361 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9362 single_use);
9363 return single_use ? JNI_TRUE : JNI_FALSE;
9364 }
9365
9366 /**
9367 * Increments the reference count of the session.
9368 */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9369 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9370 CHECK_ERROR_QUEUE_ON_RETURN;
9371 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9372 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9373 if (ssl_session == nullptr) {
9374 return;
9375 }
9376 SSL_SESSION_up_ref(ssl_session);
9377 }
9378
9379 /**
9380 * Frees the SSL session.
9381 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9382 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9383 CHECK_ERROR_QUEUE_ON_RETURN;
9384 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9385 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9386 if (ssl_session == nullptr) {
9387 return;
9388 }
9389 SSL_SESSION_free(ssl_session);
9390 }
9391
9392 /**
9393 * Serializes the native state of the session (ID, cipher, and keys but
9394 * not certificates). Returns a byte[] containing the DER-encoded state.
9395 * See apache mod_ssl.
9396 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9397 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9398 CHECK_ERROR_QUEUE_ON_RETURN;
9399 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9400 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9401 if (ssl_session == nullptr) {
9402 return nullptr;
9403 }
9404 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9405 }
9406
9407 /**
9408 * Deserialize the session.
9409 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9410 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9411 CHECK_ERROR_QUEUE_ON_RETURN;
9412 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9413
9414 ScopedByteArrayRO bytes(env, javaBytes);
9415 if (bytes.get() == nullptr) {
9416 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9417 return 0;
9418 }
9419 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9420 // NOLINTNEXTLINE(runtime/int)
9421 SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9422
9423 if (ssl_session == nullptr ||
9424 ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9425 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9426 conscrypt::jniutil::throwIOException);
9427 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9428 return 0L;
9429 }
9430
9431 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9432 return reinterpret_cast<uintptr_t>(ssl_session);
9433 }
9434
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9435 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9436 CHECK_ERROR_QUEUE_ON_RETURN;
9437 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
9438 if (cipher == nullptr) {
9439 return nullptr;
9440 }
9441
9442 const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
9443 return env->NewStringUTF(kx_name);
9444 }
9445
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)9446 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
9447 CHECK_ERROR_QUEUE_ON_RETURN;
9448 ScopedUtfChars selector(env, selectorJava);
9449 if (selector.c_str() == nullptr) {
9450 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9451 "selector == null");
9452 return nullptr;
9453 }
9454
9455 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
9456
9457 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
9458 bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
9459
9460 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
9461 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9462 "Unable to set SSL cipher list");
9463 return nullptr;
9464 }
9465 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
9466
9467 size_t size = sk_SSL_CIPHER_num(ciphers);
9468 ScopedLocalRef<jobjectArray> cipherNamesArray(
9469 env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
9470 nullptr));
9471 if (cipherNamesArray.get() == nullptr) {
9472 return nullptr;
9473 }
9474
9475 // Return an array of standard and OpenSSL name pairs.
9476 for (size_t i = 0; i < size; i++) {
9477 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
9478 ScopedLocalRef<jstring> cipherName(env,
9479 env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
9480 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
9481 cipherName.get());
9482
9483 ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
9484 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
9485 opensslName.get());
9486 }
9487
9488 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
9489 2 * size);
9490 return cipherNamesArray.release();
9491 }
9492
9493 /**
9494 * Compare the given CertID with a certificate and it's issuer.
9495 * True is returned if the CertID matches.
9496 */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)9497 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
9498 // Get the hash algorithm used by this CertID
9499 CBS hash_algorithm, hash;
9500 if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
9501 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
9502 return false;
9503 }
9504
9505 // Get the issuer's name hash from the CertID
9506 CBS issuer_name_hash;
9507 if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
9508 return false;
9509 }
9510
9511 // Get the issuer's key hash from the CertID
9512 CBS issuer_key_hash;
9513 if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
9514 return false;
9515 }
9516
9517 // Get the serial number from the CertID
9518 CBS serial;
9519 if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
9520 return false;
9521 }
9522
9523 // Compare the certificate's serial number with the one from the Cert ID
9524 const uint8_t* p = CBS_data(&serial);
9525 bssl::UniquePtr<ASN1_INTEGER> serial_number(
9526 c2i_ASN1_INTEGER(nullptr, &p,
9527 static_cast<long>(CBS_len(&serial)))); // NOLINT(runtime/int)
9528 const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
9529 if (serial_number.get() == nullptr ||
9530 ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
9531 return false;
9532 }
9533
9534 // Find the hash algorithm to be used
9535 const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
9536 if (digest == nullptr) {
9537 return false;
9538 }
9539
9540 // Hash the issuer's name and compare the hash with the one from the Cert ID
9541 uint8_t md[EVP_MAX_MD_SIZE];
9542 const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
9543 if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
9544 !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
9545 return false;
9546 }
9547
9548 // Same thing with the issuer's key
9549 const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
9550 if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
9551 static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
9552 nullptr) ||
9553 !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
9554 return false;
9555 }
9556
9557 return true;
9558 }
9559
9560 /**
9561 * Get a SingleResponse whose CertID matches the given certificate and issuer from a
9562 * SEQUENCE OF SingleResponse.
9563 *
9564 * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
9565 * error occured or no response matches the certificate, false is returned and |out_single_response|
9566 * is unchanged.
9567 */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)9568 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
9569 CBS* out_single_response) {
9570 // Iterate over all the SingleResponses, until one matches the certificate
9571 while (CBS_len(responses) > 0) {
9572 // Get the next available SingleResponse from the sequence
9573 CBS single_response;
9574 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
9575 return false;
9576 }
9577
9578 // Make a copy of the stream so we pass it back to the caller
9579 CBS single_response_original = single_response;
9580
9581 // Get the SingleResponse's CertID
9582 // If this fails ignore the current response and move to the next one
9583 CBS cert_id;
9584 if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
9585 continue;
9586 }
9587
9588 // Compare the CertID with the given certificate and issuer
9589 if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
9590 *out_single_response = single_response_original;
9591 return true;
9592 }
9593 }
9594
9595 return false;
9596 }
9597
9598 /**
9599 * Get the BasicOCSPResponse from an OCSPResponse.
9600 * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
9601 * returned.
9602 */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)9603 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
9604 CBS tagged_response_bytes, response_bytes, response_type, response;
9605
9606 // Get the ResponseBytes out of the OCSPResponse
9607 if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
9608 !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
9609 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9610 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
9611 return false;
9612 }
9613
9614 // Parse the response type and data out of the ResponseBytes
9615 if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
9616 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
9617 return false;
9618 }
9619
9620 // Only basic OCSP responses are supported
9621 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
9622 return false;
9623 }
9624
9625 // Parse the octet string as a BasicOCSPResponse
9626 return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
9627 }
9628
9629 /**
9630 * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
9631 * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
9632 * true is returned.
9633 */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)9634 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
9635 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
9636 CBS response_data;
9637 if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
9638 return false;
9639 }
9640
9641 // Skip the version, responderID and producedAt fields
9642 if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
9643 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9644 !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
9645 !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
9646 return false;
9647 }
9648
9649 // Extract the list of SingleResponse.
9650 return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
9651 }
9652
9653 /**
9654 * Get the SEQUENCE OF Extension from a SingleResponse.
9655 * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
9656 * returned.
9657 */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)9658 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
9659 // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
9660 if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
9661 !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
9662 !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
9663 !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
9664 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
9665 return false;
9666 }
9667
9668 // Get the list of Extension
9669 return CBS_get_asn1(single_response, extensions,
9670 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
9671 }
9672
9673 /*
9674 public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
9675 long x509Ref, long issuerX509Ref);
9676 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)9677 static jbyteArray NativeCrypto_get_ocsp_single_extension(
9678 JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
9679 CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
9680 CHECK_ERROR_QUEUE_ON_RETURN;
9681 ScopedByteArrayRO ocspData(env, ocspDataBytes);
9682 if (ocspData.get() == nullptr) {
9683 return nullptr;
9684 }
9685
9686 CBS cbs;
9687 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
9688
9689 // Start parsing the OCSPResponse
9690 CBS ocsp_response;
9691 if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
9692 return nullptr;
9693 }
9694
9695 // Get the BasicOCSPResponse from the OCSP Response
9696 CBS basic_response;
9697 if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
9698 return nullptr;
9699 }
9700
9701 // Get the list of SingleResponses from the BasicOCSPResponse
9702 CBS responses;
9703 if (!get_ocsp_single_responses(&basic_response, &responses)) {
9704 return nullptr;
9705 }
9706
9707 // Find the response matching the certificate
9708 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
9709 X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
9710 CBS single_response;
9711 if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
9712 return nullptr;
9713 }
9714
9715 // Get the extensions from the SingleResponse
9716 CBS extensions;
9717 if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
9718 return nullptr;
9719 }
9720
9721 const uint8_t* ptr = CBS_data(&extensions);
9722 bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
9723 d2i_X509_EXTENSIONS(nullptr, &ptr,
9724 static_cast<long>(CBS_len(&extensions)))); // NOLINT(runtime/int)
9725 if (x509_exts.get() == nullptr) {
9726 return nullptr;
9727 }
9728
9729 return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
9730 env, x509_exts.get(), oid);
9731 }
9732
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)9733 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
9734 // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
9735 // no throwing if the buffer is null or not a direct ByteBuffer.
9736 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
9737 return 0;
9738 }
9739 return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
9740 }
9741
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)9742 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
9743 CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
9744 CHECK_ERROR_QUEUE_ON_RETURN;
9745 SSL* ssl = to_SSL(env, ssl_address, true);
9746 if (ssl == nullptr) {
9747 return 0;
9748 }
9749 return SSL_get_error(ssl, ret);
9750 }
9751
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)9752 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
9753 ERR_clear_error();
9754 }
9755
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9756 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
9757 CONSCRYPT_UNUSED jobject ssl_holder) {
9758 CHECK_ERROR_QUEUE_ON_RETURN;
9759 SSL* ssl = to_SSL(env, ssl_address, true);
9760 if (ssl == nullptr) {
9761 return 0;
9762 }
9763 return SSL_pending(ssl);
9764 }
9765
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)9766 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
9767 CHECK_ERROR_QUEUE_ON_RETURN;
9768 BIO* bio = to_BIO(env, bio_address);
9769 if (bio == nullptr) {
9770 return 0;
9771 }
9772 return static_cast<jint>(BIO_ctrl_pending(bio));
9773 }
9774
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9775 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
9776 CONSCRYPT_UNUSED jobject ssl_holder) {
9777 CHECK_ERROR_QUEUE_ON_RETURN;
9778 SSL* ssl = to_SSL(env, ssl_address, true);
9779 if (ssl == nullptr) {
9780 return 0;
9781 }
9782 return (jint)SSL_max_seal_overhead(ssl);
9783 }
9784
9785 /**
9786 * public static native int SSL_new_BIO(long ssl) throws SSLException;
9787 */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9788 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
9789 CONSCRYPT_UNUSED jobject ssl_holder) {
9790 CHECK_ERROR_QUEUE_ON_RETURN;
9791 SSL* ssl = to_SSL(env, ssl_address, true);
9792 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
9793 if (ssl == nullptr) {
9794 return 0;
9795 }
9796
9797 BIO* internal_bio;
9798 BIO* network_bio;
9799 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
9800 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9801 "BIO_new_bio_pair failed");
9802 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
9803 return 0;
9804 }
9805
9806 SSL_set_bio(ssl, internal_bio, internal_bio);
9807
9808 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
9809 return reinterpret_cast<uintptr_t>(network_bio);
9810 }
9811
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9812 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9813 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9814 CHECK_ERROR_QUEUE_ON_RETURN;
9815 SSL* ssl = to_SSL(env, ssl_address, true);
9816 if (ssl == nullptr) {
9817 return 0;
9818 }
9819 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
9820
9821 if (shc == nullptr) {
9822 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9823 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
9824 ssl);
9825 return 0;
9826 }
9827
9828 AppData* appData = toAppData(ssl);
9829 if (appData == nullptr) {
9830 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9831 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
9832 return 0;
9833 }
9834
9835 errno = 0;
9836
9837 if (!appData->setCallbackState(env, shc, nullptr)) {
9838 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9839 ERR_clear_error();
9840 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9841 return 0;
9842 }
9843
9844 int ret = SSL_do_handshake(ssl);
9845 appData->clearCallbackState();
9846 if (env->ExceptionCheck()) {
9847 // cert_verify_callback threw exception
9848 ERR_clear_error();
9849 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9850 return 0;
9851 }
9852
9853 SslError sslError(ssl, ret);
9854 int code = sslError.get();
9855
9856 if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
9857 // Non-exceptional case.
9858 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
9859 return code;
9860 }
9861
9862 // Exceptional case...
9863 if (ret == 0) {
9864 // TODO(nmittler): Can this happen with memory BIOs?
9865 /*
9866 * Clean error. See SSL_do_handshake(3SSL) man page.
9867 * The other side closed the socket before the handshake could be
9868 * completed, but everything is within the bounds of the TLS protocol.
9869 * We still might want to find out the real reason of the failure.
9870 */
9871 if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
9872 (code == SSL_ERROR_ZERO_RETURN)) {
9873 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9874 } else {
9875 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9876 env, ssl, sslError.release(), "SSL handshake terminated",
9877 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9878 }
9879 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9880 return code;
9881 }
9882
9883 /*
9884 * Unclean error. See SSL_do_handshake(3SSL) man page.
9885 * Translate the error and throw exception. We are sure it is an error
9886 * at this point.
9887 */
9888 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9889 env, ssl, sslError.release(), "SSL handshake aborted",
9890 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9891 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9892 return code;
9893 }
9894
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9895 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9896 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9897 CHECK_ERROR_QUEUE_ON_RETURN;
9898 SSL* ssl = to_SSL(env, ssl_address, false);
9899 if (ssl == nullptr) {
9900 return;
9901 }
9902 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
9903
9904 if (shc == nullptr) {
9905 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9906 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9907 return;
9908 }
9909
9910 AppData* appData = toAppData(ssl);
9911 if (appData != nullptr) {
9912 if (!appData->setCallbackState(env, shc, nullptr)) {
9913 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9914 ERR_clear_error();
9915 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9916 return;
9917 }
9918 int ret = SSL_shutdown(ssl);
9919 appData->clearCallbackState();
9920 // callbacks can happen if server requests renegotiation
9921 if (env->ExceptionCheck()) {
9922 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9923 return;
9924 }
9925 switch (ret) {
9926 case 0:
9927 /*
9928 * Shutdown was not successful (yet), but there also
9929 * is no error. Since we can't know whether the remote
9930 * server is actually still there, and we don't want to
9931 * get stuck forever in a second SSL_shutdown() call, we
9932 * simply return. This is not security a problem as long
9933 * as we close the underlying socket, which we actually
9934 * do, because that's where we are just coming from.
9935 */
9936 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
9937 break;
9938 case 1:
9939 /*
9940 * Shutdown was successful. We can safely return. Hooray!
9941 */
9942 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
9943 break;
9944 default:
9945 /*
9946 * Everything else is a real error condition. We should
9947 * let the Java layer know about this by throwing an
9948 * exception.
9949 */
9950 int sslError = SSL_get_error(ssl, ret);
9951 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
9952 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9953 "SSL shutdown failed");
9954 break;
9955 }
9956 }
9957
9958 ERR_clear_error();
9959 }
9960
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)9961 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
9962 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9963 jint length, jobject shc) {
9964 CHECK_ERROR_QUEUE_ON_RETURN;
9965 SSL* ssl = to_SSL(env, ssl_address, true);
9966 char* destPtr = reinterpret_cast<char*>(address);
9967 if (ssl == nullptr) {
9968 return -1;
9969 }
9970 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
9971 destPtr, length, shc);
9972
9973 if (shc == nullptr) {
9974 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9975 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
9976 ssl);
9977 return -1;
9978 }
9979 AppData* appData = toAppData(ssl);
9980 if (appData == nullptr) {
9981 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9982 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
9983 return -1;
9984 }
9985 if (!appData->setCallbackState(env, shc, nullptr)) {
9986 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9987 ERR_clear_error();
9988 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
9989 return -1;
9990 }
9991
9992 errno = 0;
9993
9994 int result = SSL_read(ssl, destPtr, length);
9995 appData->clearCallbackState();
9996 if (env->ExceptionCheck()) {
9997 // An exception was thrown by one of the callbacks. Just propagate that exception.
9998 ERR_clear_error();
9999 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10000 return -1;
10001 }
10002
10003 SslError sslError(ssl, result);
10004 switch (sslError.get()) {
10005 case SSL_ERROR_NONE: {
10006 // Successfully read at least one byte. Just return the result.
10007 break;
10008 }
10009 case SSL_ERROR_ZERO_RETURN: {
10010 // A close_notify was received, this stream is finished.
10011 return -SSL_ERROR_ZERO_RETURN;
10012 }
10013 case SSL_ERROR_WANT_READ:
10014 case SSL_ERROR_WANT_WRITE: {
10015 // Return the negative of these values.
10016 result = -sslError.get();
10017 break;
10018 }
10019 case SSL_ERROR_SYSCALL: {
10020 // A problem occurred during a system call, but this is not
10021 // necessarily an error.
10022 if (result == 0) {
10023 // TODO(nmittler): Can this happen with memory BIOs?
10024 // Connection closed without proper shutdown. Tell caller we
10025 // have reached end-of-stream.
10026 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10027 break;
10028 }
10029
10030 if (errno == EINTR) {
10031 // TODO(nmittler): Can this happen with memory BIOs?
10032 // System call has been interrupted. Simply retry.
10033 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10034 "Read error");
10035 break;
10036 }
10037
10038 // Note that for all other system call errors we fall through
10039 // to the default case, which results in an Exception.
10040 FALLTHROUGH_INTENDED;
10041 }
10042 default: {
10043 // Everything else is basically an error.
10044 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10045 "Read error");
10046 break;
10047 }
10048 }
10049
10050 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10051 ssl, destPtr, length, shc, result);
10052 return result;
10053 }
10054
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)10055 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10056 CONSCRYPT_UNUSED jobject ssl_holder,
10057 jlong bioRef, jlong address, jint len,
10058 jobject shc) {
10059 CHECK_ERROR_QUEUE_ON_RETURN;
10060 SSL* ssl = to_SSL(env, ssl_address, true);
10061 if (ssl == nullptr) {
10062 return -1;
10063 }
10064 if (shc == nullptr) {
10065 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10066 JNI_TRACE(
10067 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10068 "sslHandshakeCallbacks == null",
10069 ssl);
10070 return -1;
10071 }
10072 BIO* bio = to_BIO(env, bioRef);
10073 if (bio == nullptr) {
10074 return -1;
10075 }
10076 if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10077 // The network BIO couldn't handle the entire write. Don't write anything, so that we
10078 // only process one packet at a time.
10079 return 0;
10080 }
10081 const char* sourcePtr = reinterpret_cast<const char*>(address);
10082
10083 AppData* appData = toAppData(ssl);
10084 if (appData == nullptr) {
10085 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10086 ERR_clear_error();
10087 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10088 return -1;
10089 }
10090 if (!appData->setCallbackState(env, shc, nullptr)) {
10091 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10092 ERR_clear_error();
10093 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10094 return -1;
10095 }
10096
10097 errno = 0;
10098
10099 int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10100 appData->clearCallbackState();
10101 JNI_TRACE(
10102 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10103 "ret=%d",
10104 ssl, bio, sourcePtr, len, shc, result);
10105 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10106 static_cast<size_t>(result));
10107 return result;
10108 }
10109
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)10110 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10111 CONSCRYPT_UNUSED jobject ssl_holder,
10112 jlong bioRef, jlong address, jint outputSize,
10113 jobject shc) {
10114 CHECK_ERROR_QUEUE_ON_RETURN;
10115 SSL* ssl = to_SSL(env, ssl_address, true);
10116 if (ssl == nullptr) {
10117 return -1;
10118 }
10119 if (shc == nullptr) {
10120 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10121 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10122 ssl);
10123 return -1;
10124 }
10125 BIO* bio = to_BIO(env, bioRef);
10126 if (bio == nullptr) {
10127 return -1;
10128 }
10129 char* destPtr = reinterpret_cast<char*>(address);
10130 if (destPtr == nullptr) {
10131 conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10132 return -1;
10133 }
10134
10135 AppData* appData = toAppData(ssl);
10136 if (appData == nullptr) {
10137 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10138 ERR_clear_error();
10139 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10140 return -1;
10141 }
10142 if (!appData->setCallbackState(env, shc, nullptr)) {
10143 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10144 ERR_clear_error();
10145 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10146 return -1;
10147 }
10148
10149 errno = 0;
10150
10151 int result = BIO_read(bio, destPtr, outputSize);
10152 appData->clearCallbackState();
10153 JNI_TRACE(
10154 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10155 "=> ret=%d",
10156 ssl, bio, destPtr, outputSize, shc, result);
10157 JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10158 return result;
10159 }
10160
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10161 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10162 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10163 CHECK_ERROR_QUEUE_ON_RETURN;
10164 SSL* ssl = to_SSL(env, ssl_address, true);
10165 if (ssl == nullptr) {
10166 return;
10167 }
10168 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10169 if (shc == nullptr) {
10170 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10171 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10172 ssl);
10173 return;
10174 }
10175 AppData* appData = toAppData(ssl);
10176 if (appData == nullptr) {
10177 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10178 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10179 return;
10180 }
10181 if (!appData->setCallbackState(env, shc, nullptr)) {
10182 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10183 ERR_clear_error();
10184 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10185 return;
10186 }
10187 char c;
10188 int result = SSL_peek(ssl, &c, 1);
10189 appData->clearCallbackState();
10190 if (env->ExceptionCheck()) {
10191 // An exception was thrown by one of the callbacks. Just propagate that exception.
10192 ERR_clear_error();
10193 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10194 return;
10195 }
10196
10197 SslError sslError(ssl, result);
10198 switch (sslError.get()) {
10199 case SSL_ERROR_NONE:
10200 case SSL_ERROR_ZERO_RETURN:
10201 case SSL_ERROR_WANT_READ:
10202 case SSL_ERROR_WANT_WRITE: {
10203 // The call succeeded, lacked data, or the SSL is closed. All is well.
10204 break;
10205 }
10206 case SSL_ERROR_SYSCALL: {
10207 // A problem occurred during a system call, but this is not
10208 // necessarily an error.
10209 if (result == 0) {
10210 // TODO(nmittler): Can this happen with memory BIOs?
10211 // Connection closed without proper shutdown. Tell caller we
10212 // have reached end-of-stream.
10213 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10214 break;
10215 }
10216
10217 if (errno == EINTR) {
10218 // TODO(nmittler): Can this happen with memory BIOs?
10219 // System call has been interrupted. Simply retry.
10220 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10221 "Read error");
10222 break;
10223 }
10224
10225 // Note that for all other system call errors we fall through
10226 // to the default case, which results in an Exception.
10227 FALLTHROUGH_INTENDED;
10228 }
10229 default: {
10230 // Everything else is basically an error.
10231 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10232 "Read error");
10233 break;
10234 }
10235 }
10236
10237 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10238 }
10239
10240 /**
10241 * OpenSSL write function (2): write into buffer at offset n chunks.
10242 */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10243 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10244 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10245 jint len, jobject shc) {
10246 CHECK_ERROR_QUEUE_ON_RETURN;
10247 SSL* ssl = to_SSL(env, ssl_address, true);
10248 const char* sourcePtr = reinterpret_cast<const char*>(address);
10249 if (ssl == nullptr) {
10250 return -1;
10251 }
10252 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10253 sourcePtr, len, shc);
10254 if (shc == nullptr) {
10255 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10256 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10257 ssl);
10258 return -1;
10259 }
10260
10261 AppData* appData = toAppData(ssl);
10262 if (appData == nullptr) {
10263 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10264 ERR_clear_error();
10265 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10266 return -1;
10267 }
10268 if (!appData->setCallbackState(env, shc, nullptr)) {
10269 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10270 ERR_clear_error();
10271 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10272 return -1;
10273 }
10274
10275 errno = 0;
10276
10277 int result = SSL_write(ssl, sourcePtr, len);
10278 appData->clearCallbackState();
10279 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10280 ssl, sourcePtr, len, shc, result);
10281 return result;
10282 }
10283
10284 /**
10285 * public static native bool usesBoringSsl_FIPS_mode();
10286 */
NativeCrypto_usesBoringSsl_FIPS_mode()10287 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
10288 return FIPS_mode();
10289 }
10290
10291 // TESTING METHODS BEGIN
10292
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10293 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10294 CHECK_ERROR_QUEUE_ON_RETURN;
10295 BIO* bio = to_BIO(env, bioRef);
10296 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10297
10298 if (bio == nullptr) {
10299 JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10300 return 0;
10301 }
10302
10303 if (outputJavaBytes == nullptr) {
10304 conscrypt::jniutil::throwNullPointerException(env, "output == null");
10305 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10306 return 0;
10307 }
10308
10309 jsize outputSize = env->GetArrayLength(outputJavaBytes);
10310
10311 std::unique_ptr<unsigned char[]> buffer(
10312 new unsigned char[static_cast<unsigned int>(outputSize)]);
10313 if (buffer.get() == nullptr) {
10314 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10315 return 0;
10316 }
10317
10318 int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10319 if (read <= 0) {
10320 conscrypt::jniutil::throwIOException(env, "BIO_read");
10321 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10322 return 0;
10323 }
10324
10325 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10326 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10327 return read;
10328 }
10329
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10330 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10331 jint offset, jint length) {
10332 CHECK_ERROR_QUEUE_ON_RETURN;
10333 BIO* bio = to_BIO(env, bioRef);
10334 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10335
10336 if (bio == nullptr) {
10337 return;
10338 }
10339
10340 if (inputJavaBytes == nullptr) {
10341 conscrypt::jniutil::throwNullPointerException(env, "input == null");
10342 return;
10343 }
10344
10345 int inputSize = env->GetArrayLength(inputJavaBytes);
10346 if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10347 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10348 "inputJavaBytes");
10349 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10350 return;
10351 }
10352
10353 std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10354 if (buffer.get() == nullptr) {
10355 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10356 return;
10357 }
10358
10359 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10360 if (BIO_write(bio, buffer.get(), length) != length) {
10361 ERR_clear_error();
10362 conscrypt::jniutil::throwIOException(env, "BIO_write");
10363 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10364 return;
10365 }
10366
10367 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10368 }
10369
10370 /**
10371 * public static native long SSL_clear_mode(long ssl, long mode);
10372 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10373 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10374 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10375 CHECK_ERROR_QUEUE_ON_RETURN;
10376 SSL* ssl = to_SSL(env, ssl_address, true);
10377 // NOLINTNEXTLINE(runtime/int)
10378 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10379 if (ssl == nullptr) {
10380 return 0;
10381 }
10382 jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10383 // NOLINTNEXTLINE(runtime/int)
10384 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10385 return result;
10386 }
10387
10388 /**
10389 * public static native long SSL_get_mode(long ssl);
10390 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10391 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10392 CONSCRYPT_UNUSED jobject ssl_holder) {
10393 CHECK_ERROR_QUEUE_ON_RETURN;
10394 SSL* ssl = to_SSL(env, ssl_address, true);
10395 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10396 if (ssl == nullptr) {
10397 return 0;
10398 }
10399 jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
10400 // NOLINTNEXTLINE(runtime/int)
10401 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
10402 return mode;
10403 }
10404
10405 /**
10406 * public static native long SSL_get_options(long ssl);
10407 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10408 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
10409 CONSCRYPT_UNUSED jobject ssl_holder) {
10410 CHECK_ERROR_QUEUE_ON_RETURN;
10411 SSL* ssl = to_SSL(env, ssl_address, true);
10412 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
10413 if (ssl == nullptr) {
10414 return 0;
10415 }
10416 jlong options = static_cast<jlong>(SSL_get_options(ssl));
10417 // NOLINTNEXTLINE(runtime/int)
10418 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
10419 return options;
10420 }
10421
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10422 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
10423 CONSCRYPT_UNUSED jobject ssl_holder) {
10424 CHECK_ERROR_QUEUE_ON_RETURN;
10425 SSL* ssl = to_SSL(env, ssl_address, true);
10426 if (ssl == nullptr) {
10427 return 0;
10428 }
10429 return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
10430 }
10431
10432 // TESTING METHODS END
10433
10434 #define CONSCRYPT_NATIVE_METHOD(functionName, signature) \
10435 { \
10436 /* NOLINTNEXTLINE */ \
10437 (char*)#functionName, (char*)(signature), \
10438 reinterpret_cast<void*>(NativeCrypto_##functionName) \
10439 }
10440
10441 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10442 #define SSL_CALLBACKS \
10443 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
10444 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10445 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
10446 #define REF_EVP_CIPHER_CTX \
10447 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
10448 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
10449 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
10450 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
10451 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
10452 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
10453 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
10454 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
10455 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
10456 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
10457 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
10458 static JNINativeMethod sNativeCryptoMethods[] = {
10459 CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
10460 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
10461 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
10462 CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
10463 CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
10464 CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
10465 CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
10466 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
10467 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
10468 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10469 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10470 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10471 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
10472 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10473 CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
10474 CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
10475 CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
10476 CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
10477 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
10478 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
10479 CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10480 CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
10481 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
10482 CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
10483 CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
10484 CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10485 CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10486 CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10487 CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10488 CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10489 CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
10490 CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
10491 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
10492 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
10493 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10494 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10495 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10496 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10497 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
10498 CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
10499 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10500 CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
10501 CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
10502 CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
10503 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10504 CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
10505 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10506 CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10507 CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
10508 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10509 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10510 CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
10511 CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
10512 CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10513 CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
10514 CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
10515 CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
10516 CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
10517 CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
10518 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
10519 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
10520 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
10521 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
10522 CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
10523 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10524 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10525 CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
10526 CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10527 CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
10528 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10529 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10530 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10531 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
10532 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10533 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10534 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10535 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
10536 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
10537 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10538 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
10539 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10540 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
10541 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
10542 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
10543 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
10544 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
10545 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
10546 CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
10547 CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10548 CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10549 CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
10550 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
10551 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
10552 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10553 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
10554 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
10555 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10556 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
10557 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
10558 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
10559 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
10560 CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
10561 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
10562 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
10563 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
10564 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
10565 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
10566 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
10567 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10568 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10569 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
10570 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
10571 CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
10572 CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
10573 CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
10574 CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
10575 CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
10576 CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
10577 CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10578 CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
10579 CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
10580 CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
10581 CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
10582 CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
10583 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
10584 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
10585 CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
10586 CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
10587 CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
10588 CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
10589 CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
10590 CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
10591 CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
10592 CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
10593 CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
10594 CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
10595 CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10596 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10597 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
10598 CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
10599 CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
10600 CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
10601 CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
10602 CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
10603 CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
10604 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
10605 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
10606 CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
10607 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
10608 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
10609 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10610 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
10611 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
10612 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
10613 CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
10614 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
10615 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10616 CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
10617 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
10618 CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
10619 CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
10620 CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
10621 CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
10622 CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
10623 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
10624 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext, "(J" REF_X509 "Ljava/lang/String;)[B"),
10625 CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
10626 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
10627 CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
10628 CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
10629 CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
10630 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
10631 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
10632 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
10633 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
10634 CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
10635 CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
10636 CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
10637 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
10638 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
10639 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
10640 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
10641 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
10642 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10643 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
10644 CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
10645 CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
10646 CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10647 CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
10648 CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
10649 CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
10650 CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
10651 CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
10652 CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
10653 CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
10654 CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
10655 CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
10656 CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
10657 CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
10658 CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
10659 CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
10660 CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
10661 CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
10662 CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
10663 CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
10664 CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
10665 CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
10666 CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
10667 CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
10668 CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
10669 CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
10670 CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
10671 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
10672 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
10673 CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
10674 CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
10675 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
10676 CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
10677 CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
10678 CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
10679 CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
10680 CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
10681 CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
10682 CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
10683 CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
10684 CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
10685 CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
10686 CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
10687 CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
10688 CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
10689 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
10690 CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
10691 CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
10692 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
10693 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
10694 CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
10695 CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
10696 CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
10697 CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
10698 CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
10699 CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
10700 CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
10701 CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
10702 CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
10703 CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
10704 CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
10705 CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
10706 CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
10707 CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
10708 CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
10709 CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
10710 CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
10711 CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
10712 CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
10713 CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
10714 CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
10715 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
10716 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
10717 CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
10718 CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
10719 CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
10720 CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
10721 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
10722 CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
10723 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10724 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10725 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
10726 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
10727 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
10728 CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
10729 CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
10730 CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
10731 CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
10732 CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
10733 CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
10734 CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
10735 CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
10736 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
10737 CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
10738 CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
10739 CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
10740 CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
10741 CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
10742 CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
10743 CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
10744 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
10745 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10746 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10747 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10748 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10749 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
10750 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
10751 CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
10752
10753 // Used for testing only.
10754 CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
10755 CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
10756 CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
10757 CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
10758 CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
10759 CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
10760 };
10761
registerNativeMethods(JNIEnv * env)10762 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
10763 conscrypt::jniutil::jniRegisterNativeMethods(
10764 env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
10765 NELEM(sNativeCryptoMethods));
10766 }
10767
10768 /* Local Variables: */
10769 /* mode: c++ */
10770 /* tab-width: 4 */
10771 /* indent-tabs-mode: nil */
10772 /* c-basic-offset: 4 */
10773 /* End: */
10774 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
10775