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/curve25519.h>
41 #include <openssl/cmac.h>
42 #include <openssl/crypto.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 <vector>
56
57 using conscrypt::AppData;
58 using conscrypt::BioInputStream;
59 using conscrypt::BioOutputStream;
60 using conscrypt::BioStream;
61 using conscrypt::CompatibilityCloseMonitor;
62 using conscrypt::NativeCrypto;
63 using conscrypt::SslError;
64
65 /**
66 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
67 * If this function returns nullptr and <code>throwIfNull</code> is
68 * passed as <code>true</code>, then this function will call
69 * <code>throwSSLExceptionStr</code> before returning, so in this case of
70 * nullptr, a caller of this function should simply return and allow JNI
71 * to do its thing.
72 *
73 * @param env the JNI environment
74 * @param ssl_address; the ssl_address pointer as an integer
75 * @param throwIfNull whether to throw if the SSL pointer is nullptr
76 * @returns the pointer, which may be nullptr
77 */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)78 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
79 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
80 if ((ssl_ctx == nullptr) && throwIfNull) {
81 JNI_TRACE("ssl_ctx == null");
82 conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
83 }
84 return ssl_ctx;
85 }
86
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)87 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
88 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
89 if ((ssl == nullptr) && throwIfNull) {
90 JNI_TRACE("ssl == null");
91 conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
92 }
93 return ssl;
94 }
95
to_BIO(JNIEnv * env,jlong bio_address)96 static BIO* to_BIO(JNIEnv* env, jlong bio_address) {
97 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
98 if (bio == nullptr) {
99 JNI_TRACE("bio == null");
100 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
101 }
102 return bio;
103 }
104
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)105 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
106 SSL_SESSION* ssl_session =
107 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
108 if ((ssl_session == nullptr) && throwIfNull) {
109 JNI_TRACE("ssl_session == null");
110 conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
111 }
112 return ssl_session;
113 }
114
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)115 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
116 SSL_CIPHER* ssl_cipher =
117 reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
118 if ((ssl_cipher == nullptr) && throwIfNull) {
119 JNI_TRACE("ssl_cipher == null");
120 conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
121 }
122 return ssl_cipher;
123 }
124
125 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)126 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
127 if (contextObject == nullptr) {
128 JNI_TRACE("contextObject == null");
129 conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
130 return nullptr;
131 }
132 T* ref = reinterpret_cast<T*>(
133 env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
134 if (ref == nullptr) {
135 JNI_TRACE("ref == null");
136 conscrypt::jniutil::throwNullPointerException(env, "ref == null");
137 return nullptr;
138 }
139 return ref;
140 }
141
142 /**
143 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
144 * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
145 * return value is false, there is a pending exception.
146 */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)147 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
148 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
149 if (dest == nullptr) {
150 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
151 conscrypt::jniutil::throwNullPointerException(env, "dest == null");
152 return false;
153 }
154 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
155
156 ScopedByteArrayRO sourceBytes(env, source);
157 if (sourceBytes.get() == nullptr) {
158 JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
159 return false;
160 }
161 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
162 size_t tmpSize = sourceBytes.size();
163
164 /* if the array is empty, it is zero. */
165 if (tmpSize == 0) {
166 if (*dest == nullptr) {
167 *dest = BN_new();
168 }
169 BN_zero(*dest);
170 return true;
171 }
172
173 std::unique_ptr<unsigned char[]> twosComplement;
174 bool negative = (tmp[0] & 0x80) != 0;
175 if (negative) {
176 // Need to convert to two's complement.
177 twosComplement.reset(new unsigned char[tmpSize]);
178 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
179 memcpy(twosBytes, tmp, tmpSize);
180 tmp = twosBytes;
181
182 bool carry = true;
183 for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
184 twosBytes[i] ^= 0xFF;
185 if (carry) {
186 carry = (++twosBytes[i]) == 0;
187 }
188 }
189 }
190 BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
191 if (ret == nullptr) {
192 conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
193 ERR_clear_error();
194 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
195 return false;
196 }
197 BN_set_negative(ret, negative ? 1 : 0);
198
199 *dest = ret;
200 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
201 return true;
202 }
203
204 /**
205 * arrayToBignumSize sets |*out_size| to the size of the big-endian number
206 * contained in |source|. It returns true on success and sets an exception and
207 * returns false otherwise.
208 */
arrayToBignumSize(JNIEnv * env,jbyteArray source,size_t * out_size)209 static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
210 JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
211
212 ScopedByteArrayRO sourceBytes(env, source);
213 if (sourceBytes.get() == nullptr) {
214 JNI_TRACE("arrayToBignum(%p, %p) => null", source, out_size);
215 return false;
216 }
217 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
218 size_t tmpSize = sourceBytes.size();
219
220 if (tmpSize == 0) {
221 *out_size = 0;
222 return true;
223 }
224
225 if ((tmp[0] & 0x80) != 0) {
226 // Negative numbers are invalid.
227 conscrypt::jniutil::throwRuntimeException(env, "Negative number");
228 return false;
229 }
230
231 while (tmpSize > 0 && tmp[0] == 0) {
232 tmp++;
233 tmpSize--;
234 }
235
236 *out_size = tmpSize;
237 return true;
238 }
239
240 /**
241 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
242 */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)243 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
244 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
245
246 if (source == nullptr) {
247 conscrypt::jniutil::throwNullPointerException(env, sourceName);
248 return nullptr;
249 }
250
251 size_t numBytes = BN_num_bytes(source) + 1;
252 jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
253 ScopedByteArrayRW bytes(env, javaBytes);
254 if (bytes.get() == nullptr) {
255 JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
256 return nullptr;
257 }
258
259 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
260 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
261 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
262 return nullptr;
263 }
264
265 // Set the sign and convert to two's complement if necessary for the Java code.
266 if (BN_is_negative(source)) {
267 bool carry = true;
268 for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
269 tmp[i] ^= 0xFF;
270 if (carry) {
271 carry = (++tmp[i]) == 0;
272 }
273 }
274 *tmp |= 0x80;
275 } else {
276 *tmp = 0x00;
277 }
278
279 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
280 return javaBytes;
281 }
282
283 /**
284 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
285 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
286 * from the OpenSSL ASN.1 API.
287 */
288 template <typename T>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(T *,unsigned char **))289 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(T*, unsigned char**)) {
290 if (obj == nullptr) {
291 conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
292 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
293 return nullptr;
294 }
295
296 int derLen = i2d_func(obj, nullptr);
297 if (derLen < 0) {
298 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
299 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
300 return nullptr;
301 }
302
303 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
304 if (byteArray.get() == nullptr) {
305 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
306 return nullptr;
307 }
308
309 ScopedByteArrayRW bytes(env, byteArray.get());
310 if (bytes.get() == nullptr) {
311 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
312 return nullptr;
313 }
314
315 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
316 int ret = i2d_func(obj, &p);
317 if (ret < 0) {
318 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
319 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
320 return nullptr;
321 }
322
323 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
324 return byteArray.release();
325 }
326
327 /**
328 * Finishes a pending CBB and returns a jbyteArray with the contents.
329 */
CBBToByteArray(JNIEnv * env,CBB * cbb)330 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
331 uint8_t* data;
332 size_t len;
333 if (!CBB_finish(cbb, &data, &len)) {
334 conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
335 ERR_clear_error();
336 JNI_TRACE("creating byte array failed");
337 return nullptr;
338 }
339 bssl::UniquePtr<uint8_t> free_data(data);
340
341 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
342 if (byteArray.get() == nullptr) {
343 JNI_TRACE("creating byte array failed");
344 return nullptr;
345 }
346
347 ScopedByteArrayRW bytes(env, byteArray.get());
348 if (bytes.get() == nullptr) {
349 JNI_TRACE("using byte array failed");
350 return nullptr;
351 }
352
353 memcpy(bytes.get(), data, len);
354 return byteArray.release();
355 }
356
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)357 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
358 if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
359 JNI_TRACE("buffer too large");
360 conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
361 return nullptr;
362 }
363
364 int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
365 jbyteArray ret = env->NewByteArray(length);
366 if (ret == nullptr) {
367 JNI_TRACE("allocating byte array failed");
368 return nullptr;
369 }
370
371 env->SetByteArrayRegion(ret, 0, length,
372 reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
373 return ret;
374 }
375
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)376 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
377 CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
378 if (array == nullptr) {
379 JNI_TRACE("array was null");
380 conscrypt::jniutil::throwNullPointerException(env, "array == null");
381 return nullptr;
382 }
383
384 ScopedByteArrayRO arrayRo(env, array);
385 if (arrayRo.get() == nullptr) {
386 JNI_TRACE("failed to get bytes");
387 return nullptr;
388 }
389
390 bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
391 reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
392 if (!ret) {
393 JNI_TRACE("failed to allocate CRYPTO_BUFFER");
394 conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
395 return nullptr;
396 }
397
398 return ret;
399 }
400
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)401 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
402 const STACK_OF(CRYPTO_BUFFER) * buffers) {
403 size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
404 if (numBuffers > INT_MAX) {
405 JNI_TRACE("too many buffers");
406 conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
407 return nullptr;
408 }
409
410 ScopedLocalRef<jobjectArray> array(
411 env, env->NewObjectArray(static_cast<int>(numBuffers),
412 conscrypt::jniutil::byteArrayClass, nullptr));
413 if (array.get() == nullptr) {
414 JNI_TRACE("failed to allocate array");
415 return nullptr;
416 }
417
418 for (size_t i = 0; i < numBuffers; ++i) {
419 CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
420 ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
421 if (bArray.get() == nullptr) {
422 return nullptr;
423 }
424 env->SetObjectArrayElement(array.get(), i, bArray.get());
425 }
426
427 return array.release();
428 }
429
430 /**
431 * Converts ASN.1 BIT STRING to a jbooleanArray.
432 */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)433 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
434 int size = ASN1_STRING_length(bitStr) * 8;
435 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
436 size -= bitStr->flags & 0x07;
437 }
438
439 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
440 if (bitsRef.get() == nullptr) {
441 return nullptr;
442 }
443
444 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
445 for (size_t i = 0; i < bitsArray.size(); i++) {
446 bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
447 }
448
449 return bitsRef.release();
450 }
451
bio_stream_create(BIO * b)452 static int bio_stream_create(BIO* b) {
453 b->init = 1;
454 b->num = 0;
455 b->ptr = nullptr;
456 b->flags = 0;
457 return 1;
458 }
459
bio_stream_destroy(BIO * b)460 static int bio_stream_destroy(BIO* b) {
461 if (b == nullptr) {
462 return 0;
463 }
464
465 if (b->ptr != nullptr) {
466 delete static_cast<BioStream*>(b->ptr);
467 b->ptr = nullptr;
468 }
469
470 b->init = 0;
471 b->flags = 0;
472 return 1;
473 }
474
bio_stream_read(BIO * b,char * buf,int len)475 static int bio_stream_read(BIO* b, char* buf, int len) {
476 BIO_clear_retry_flags(b);
477 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
478 int ret = stream->read(buf, len);
479 if (ret == 0) {
480 if (stream->isFinite()) {
481 return 0;
482 }
483 // If the BioInputStream is not finite then EOF doesn't mean that
484 // there's nothing more coming.
485 BIO_set_retry_read(b);
486 return -1;
487 }
488 return ret;
489 }
490
bio_stream_write(BIO * b,const char * buf,int len)491 static int bio_stream_write(BIO* b, const char* buf, int len) {
492 BIO_clear_retry_flags(b);
493 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
494 return stream->write(buf, len);
495 }
496
bio_stream_puts(BIO * b,const char * buf)497 static int bio_stream_puts(BIO* b, const char* buf) {
498 BioOutputStream* stream = static_cast<BioOutputStream*>(b->ptr);
499 return stream->write(buf, static_cast<int>(strlen(buf)));
500 }
501
bio_stream_gets(BIO * b,char * buf,int len)502 static int bio_stream_gets(BIO* b, char* buf, int len) {
503 BioInputStream* stream = static_cast<BioInputStream*>(b->ptr);
504 return stream->gets(buf, len);
505 }
506
bio_stream_assign(BIO * b,BioStream * stream)507 static void bio_stream_assign(BIO* b, BioStream* stream) {
508 b->ptr = static_cast<void*>(stream);
509 }
510
511 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)512 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
513 BioStream* stream = static_cast<BioStream*>(b->ptr);
514
515 switch (cmd) {
516 case BIO_CTRL_EOF:
517 return stream->isEof() ? 1 : 0;
518 case BIO_CTRL_FLUSH:
519 return stream->flush();
520 default:
521 return 0;
522 }
523 }
524
525 static BIO_METHOD stream_bio_method = {
526 (100 | 0x0400), /* source/sink BIO */
527 "InputStream/OutputStream BIO",
528 bio_stream_write, /* bio_write */
529 bio_stream_read, /* bio_read */
530 bio_stream_puts, /* bio_puts */
531 bio_stream_gets, /* bio_gets */
532 bio_stream_ctrl, /* bio_ctrl */
533 bio_stream_create, /* bio_create */
534 bio_stream_destroy, /* bio_free */
535 nullptr, /* no bio_callback_ctrl */
536 };
537
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)538 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
539 size_t message_len) {
540 JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
541 if (message_len > std::numeric_limits<jsize>::max()) {
542 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
543 return nullptr;
544 }
545 ScopedLocalRef<jbyteArray> messageArray(env,
546 env->NewByteArray(static_cast<jsize>(message_len)));
547 if (env->ExceptionCheck()) {
548 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
549 return nullptr;
550 }
551
552 {
553 ScopedByteArrayRW messageBytes(env, messageArray.get());
554 if (messageBytes.get() == nullptr) {
555 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
556 return nullptr;
557 }
558
559 memcpy(messageBytes.get(), message, message_len);
560 }
561
562 jmethodID rawSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
563 "ecSignDigestWithPrivateKey",
564 "(Ljava/security/PrivateKey;[B)[B");
565 if (rawSignMethod == nullptr) {
566 CONSCRYPT_LOG_ERROR("Could not find ecSignDigestWithPrivateKey");
567 return nullptr;
568 }
569
570 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
571 conscrypt::jniutil::cryptoUpcallsClass, rawSignMethod, privateKey, messageArray.get()));
572 }
573
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)574 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
575 const char* message, size_t message_len) {
576 if (message_len > std::numeric_limits<jsize>::max()) {
577 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
578 return nullptr;
579 }
580 ScopedLocalRef<jbyteArray> messageArray(env,
581 env->NewByteArray(static_cast<jsize>(message_len)));
582 if (env->ExceptionCheck()) {
583 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
584 return nullptr;
585 }
586
587 {
588 ScopedByteArrayRW messageBytes(env, messageArray.get());
589 if (messageBytes.get() == nullptr) {
590 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
591 return nullptr;
592 }
593
594 memcpy(messageBytes.get(), message, message_len);
595 }
596
597 jmethodID rsaSignMethod = env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
598 "rsaSignDigestWithPrivateKey",
599 "(Ljava/security/PrivateKey;I[B)[B");
600 if (rsaSignMethod == nullptr) {
601 CONSCRYPT_LOG_ERROR("Could not find rsaSignDigestWithPrivateKey");
602 return nullptr;
603 }
604
605 return reinterpret_cast<jbyteArray>(
606 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaSignMethod,
607 privateKey, padding, messageArray.get()));
608 }
609
610 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
611 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
612 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
613 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)614 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
615 const char* ciphertext, size_t ciphertext_len) {
616 if (ciphertext_len > std::numeric_limits<jsize>::max()) {
617 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
618 return nullptr;
619 }
620 ScopedLocalRef<jbyteArray> ciphertextArray(
621 env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
622 if (env->ExceptionCheck()) {
623 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
624 return nullptr;
625 }
626
627 {
628 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
629 if (ciphertextBytes.get() == nullptr) {
630 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
631 return nullptr;
632 }
633
634 memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
635 }
636
637 jmethodID rsaDecryptMethod =
638 env->GetStaticMethodID(conscrypt::jniutil::cryptoUpcallsClass,
639 "rsaDecryptWithPrivateKey", "(Ljava/security/PrivateKey;I[B)[B");
640 if (rsaDecryptMethod == nullptr) {
641 CONSCRYPT_LOG_ERROR("Could not find rsaDecryptWithPrivateKey");
642 return nullptr;
643 }
644
645 return reinterpret_cast<jbyteArray>(
646 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass, rsaDecryptMethod,
647 privateKey, padding, ciphertextArray.get()));
648 }
649
650 // *********************************************
651 // From keystore_openssl.cpp in Chromium source.
652 // *********************************************
653
654 namespace {
655
656 ENGINE* g_engine;
657 int g_rsa_exdata_index;
658 int g_ecdsa_exdata_index;
659 RSA_METHOD g_rsa_method;
660 ECDSA_METHOD g_ecdsa_method;
661 std::once_flag g_engine_once;
662
663 void init_engine_globals();
664
ensure_engine_globals()665 void ensure_engine_globals() {
666 std::call_once(g_engine_once, init_engine_globals);
667 }
668
669 // KeyExData contains the data that is contained in the EX_DATA of the RSA
670 // and ECDSA objects that are created to wrap Android system keys.
671 struct KeyExData {
672 // private_key contains a reference to a Java, private-key object.
673 jobject private_key;
674 // cached_size contains the "size" of the key. This is the size of the
675 // modulus (in bytes) for RSA, or the group order size for ECDSA. This
676 // avoids calling into Java to calculate the size.
677 size_t cached_size;
678 };
679
680 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
681 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)682 int ExDataDup(CRYPTO_EX_DATA* /* to */,
683 const CRYPTO_EX_DATA* /* from */,
684 void** /* from_d */,
685 int /* index */,
686 long /* argl */ /* NOLINT(runtime/int) */,
687 void* /* argp */) {
688 return 0;
689 }
690
691 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)692 void ExDataFree(void* /* parent */,
693 void* ptr,
694 CRYPTO_EX_DATA* /* ad */,
695 int /* index */,
696 long /* argl */ /* NOLINT(runtime/int) */,
697 void* /* argp */) {
698 // Ensure the global JNI reference created with this wrapper is
699 // properly destroyed with it.
700 KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
701 if (ex_data != nullptr) {
702 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
703 env->DeleteGlobalRef(ex_data->private_key);
704 delete ex_data;
705 }
706 }
707
RsaGetExData(const RSA * rsa)708 KeyExData* RsaGetExData(const RSA* rsa) {
709 return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
710 }
711
RsaMethodSize(const RSA * rsa)712 size_t RsaMethodSize(const RSA* rsa) {
713 const KeyExData* ex_data = RsaGetExData(rsa);
714 return ex_data->cached_size;
715 }
716
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)717 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
718 size_t in_len, int padding) {
719 if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
720 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
721 return 0;
722 }
723
724 // Retrieve private key JNI reference.
725 const KeyExData* ex_data = RsaGetExData(rsa);
726 if (!ex_data || !ex_data->private_key) {
727 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
728 return 0;
729 }
730
731 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
732 if (env == nullptr) {
733 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
734 return 0;
735 }
736
737 // For RSA keys, this function behaves as RSA_private_encrypt with
738 // the specified padding.
739 ScopedLocalRef<jbyteArray> signature(
740 env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
741 reinterpret_cast<const char*>(in), in_len));
742
743 if (signature.get() == nullptr) {
744 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
745 return 0;
746 }
747
748 ScopedByteArrayRO result(env, signature.get());
749
750 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
751 if (result.size() > expected_size) {
752 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
753 return 0;
754 }
755
756 if (max_out < expected_size) {
757 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
758 return 0;
759 }
760
761 // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
762 // should pad with leading 0s, but if it doesn't, pad the result.
763 size_t zero_pad = expected_size - result.size();
764 memset(out, 0, zero_pad);
765 memcpy(out + zero_pad, &result[0], result.size());
766 *out_len = expected_size;
767
768 return 1;
769 }
770
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)771 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
772 size_t in_len, int padding) {
773 // Retrieve private key JNI reference.
774 const KeyExData* ex_data = RsaGetExData(rsa);
775 if (!ex_data || !ex_data->private_key) {
776 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
777 return 0;
778 }
779
780 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
781 if (env == nullptr) {
782 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
783 return 0;
784 }
785
786 // This function behaves as RSA_private_decrypt.
787 ScopedLocalRef<jbyteArray> cleartext(
788 env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
789 reinterpret_cast<const char*>(in), in_len));
790 if (cleartext.get() == nullptr) {
791 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
792 return 0;
793 }
794
795 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
796
797 if (max_out < cleartextBytes.size()) {
798 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
799 return 0;
800 }
801
802 // Copy result to OpenSSL-provided buffer.
803 memcpy(out, cleartextBytes.get(), cleartextBytes.size());
804 *out_len = cleartextBytes.size();
805
806 return 1;
807 }
808
809 // Custom ECDSA_METHOD that uses the platform APIs.
810 // Note that for now, only signing through ECDSA_sign() is really supported.
811 // all other method pointers are either stubs returning errors, or no-ops.
812
EcKeyGetKey(const EC_KEY * ec_key)813 jobject EcKeyGetKey(const EC_KEY* ec_key) {
814 KeyExData* ex_data =
815 reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
816 return ex_data->private_key;
817 }
818
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)819 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
820 EC_KEY* ec_key) {
821 // Retrieve private key JNI reference.
822 jobject private_key = EcKeyGetKey(ec_key);
823 if (!private_key) {
824 CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
825 return 0;
826 }
827
828 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
829 if (env == nullptr) {
830 return 0;
831 }
832
833 // Sign message with it through JNI.
834 ScopedLocalRef<jbyteArray> signature(
835 env, ecSignDigestWithPrivateKey(env, private_key,
836 reinterpret_cast<const char*>(digest), digest_len));
837 if (signature.get() == nullptr) {
838 CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
839 return 0;
840 }
841
842 ScopedByteArrayRO signatureBytes(env, signature.get());
843 // Note: With ECDSA, the actual signature may be smaller than
844 // ECDSA_size().
845 size_t max_expected_size = ECDSA_size(ec_key);
846 if (signatureBytes.size() > max_expected_size) {
847 CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
848 signatureBytes.size(), max_expected_size);
849 return 0;
850 }
851
852 memcpy(sig, signatureBytes.get(), signatureBytes.size());
853 *sig_len = static_cast<unsigned int>(signatureBytes.size());
854 return 1;
855 }
856
init_engine_globals()857 void init_engine_globals() {
858 g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
859 nullptr /* new_func */, ExDataDup, ExDataFree);
860 g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
861 nullptr /* new_func */, ExDataDup, ExDataFree);
862
863 g_rsa_method.common.is_static = 1;
864 g_rsa_method.size = RsaMethodSize;
865 g_rsa_method.sign_raw = RsaMethodSignRaw;
866 g_rsa_method.decrypt = RsaMethodDecrypt;
867 g_rsa_method.flags = RSA_FLAG_OPAQUE;
868
869 g_ecdsa_method.common.is_static = 1;
870 g_ecdsa_method.sign = EcdsaMethodSign;
871 g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
872
873 g_engine = ENGINE_new();
874 ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
875 ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
876 }
877
878 } // anonymous namespace
879
880 #define THROW_SSLEXCEPTION (-2)
881 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
882 #define THROWN_EXCEPTION (-4)
883
884 /**
885 * Initialization phase for every OpenSSL job: Loads the Error strings, the
886 * crypto algorithms and reset the OpenSSL library
887 */
NativeCrypto_clinit(JNIEnv *,jclass)888 static void NativeCrypto_clinit(JNIEnv*, jclass) {
889 CRYPTO_library_init();
890 }
891
892 /**
893 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
894 */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)895 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
896 jbyteArray d, jbyteArray p, jbyteArray q,
897 jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
898 CHECK_ERROR_QUEUE_ON_RETURN;
899 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,
900 p, q, dmp1, dmq1, iqmp);
901
902 bssl::UniquePtr<RSA> rsa(RSA_new());
903 if (rsa.get() == nullptr) {
904 conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
905 return 0;
906 }
907
908 if (e == nullptr && d == nullptr) {
909 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
910 "e == null && d == null");
911 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
912 return 0;
913 }
914
915 if (!arrayToBignum(env, n, &rsa->n)) {
916 return 0;
917 }
918
919 if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
920 return 0;
921 }
922
923 if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
924 return 0;
925 }
926
927 if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
928 return 0;
929 }
930
931 if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
932 return 0;
933 }
934
935 if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
936 return 0;
937 }
938
939 if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
940 return 0;
941 }
942
943 if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
944 return 0;
945 }
946
947 if (conscrypt::trace::kWithJniTrace) {
948 if (p != nullptr && q != nullptr) {
949 int check = RSA_check_key(rsa.get());
950 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
951 }
952 }
953
954 if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
955 conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
956 return 0;
957 }
958
959 /*
960 * If the private exponent is available, there is the potential to do signing
961 * operations. However, we can only do blinding if the public exponent is also
962 * available. Disable blinding if the public exponent isn't available.
963 *
964 * TODO[kroot]: We should try to recover the public exponent by trying
965 * some common ones such 3, 17, or 65537.
966 */
967 if (rsa->d != nullptr && rsa->e == nullptr) {
968 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
969 rsa->flags |= RSA_FLAG_NO_BLINDING;
970 }
971
972 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
973 if (pkey.get() == nullptr) {
974 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
975 return 0;
976 }
977 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
978 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
979 ERR_clear_error();
980 return 0;
981 }
982 OWNERSHIP_TRANSFERRED(rsa);
983 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
984 e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
985 return reinterpret_cast<uintptr_t>(pkey.release());
986 }
987
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)988 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
989 jobject pubkeyRef, jbyteArray keyJavaBytes) {
990 CHECK_ERROR_QUEUE_ON_RETURN;
991 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
992 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
993 if (group == nullptr) {
994 return 0;
995 }
996 const EC_POINT* pubkey =
997 pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
998 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
999
1000 bssl::UniquePtr<BIGNUM> key(nullptr);
1001 if (keyJavaBytes != nullptr) {
1002 BIGNUM* keyRef = nullptr;
1003 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
1004 return 0;
1005 }
1006 key.reset(keyRef);
1007 }
1008
1009 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
1010 if (eckey.get() == nullptr) {
1011 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1012 return 0;
1013 }
1014
1015 if (EC_KEY_set_group(eckey.get(), group) != 1) {
1016 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1017 keyJavaBytes);
1018 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1019 return 0;
1020 }
1021
1022 if (pubkey != nullptr) {
1023 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
1024 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1025 pubkey, keyJavaBytes);
1026 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_public_key");
1027 return 0;
1028 }
1029 }
1030
1031 if (key.get() != nullptr) {
1032 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1033 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1034 pubkey, keyJavaBytes);
1035 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1036 return 0;
1037 }
1038 if (pubkey == nullptr) {
1039 bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1040 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1041 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1042 pubkey, keyJavaBytes);
1043 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1044 return 0;
1045 }
1046 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1047 }
1048 }
1049
1050 if (!EC_KEY_check_key(eckey.get())) {
1051 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1052 keyJavaBytes);
1053 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1054 return 0;
1055 }
1056
1057 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1058 if (pkey.get() == nullptr) {
1059 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1060 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1061 return 0;
1062 }
1063 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1064 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1065 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1066 ERR_clear_error();
1067 return 0;
1068 }
1069 OWNERSHIP_TRANSFERRED(eckey);
1070
1071 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1072 return reinterpret_cast<uintptr_t>(pkey.release());
1073 }
1074
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1075 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1076 CHECK_ERROR_QUEUE_ON_RETURN;
1077 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1078 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1079
1080 if (pkey == nullptr) {
1081 return -1;
1082 }
1083
1084 int result = EVP_PKEY_id(pkey);
1085 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1086 return result;
1087 }
1088
1089 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1090
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1091 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1092 const char* debug_name) {
1093 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1094 JNI_TRACE("%s(%p)", debug_name, pkey);
1095
1096 if (pkey == nullptr) {
1097 return nullptr;
1098 }
1099
1100 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1101 if (buffer.get() == nullptr) {
1102 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1103 return nullptr;
1104 }
1105
1106 if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1107 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1108 return nullptr;
1109 }
1110 // Null terminate this
1111 BIO_write(buffer.get(), "\0", 1);
1112
1113 char* tmp;
1114 BIO_get_mem_data(buffer.get(), &tmp);
1115 jstring description = env->NewStringUTF(tmp);
1116
1117 JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1118 return description;
1119 }
1120
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1121 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1122 CHECK_ERROR_QUEUE_ON_RETURN;
1123 return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1124 }
1125
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1126 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1127 CHECK_ERROR_QUEUE_ON_RETURN;
1128 return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1129 }
1130
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1131 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1132 CHECK_ERROR_QUEUE_ON_RETURN;
1133 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1134 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1135
1136 if (pkey != nullptr) {
1137 EVP_PKEY_free(pkey);
1138 }
1139 }
1140
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1141 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1142 CHECK_ERROR_QUEUE_ON_RETURN;
1143 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1144 EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1145 if (pkey1 == nullptr) {
1146 JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1147 return 0;
1148 }
1149 EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1150 if (pkey2 == nullptr) {
1151 JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1152 return 0;
1153 }
1154 JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1155
1156 int result = EVP_PKEY_cmp(pkey1, pkey2);
1157 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1158 return result;
1159 }
1160
1161 /*
1162 * static native byte[] EVP_marshal_private_key(long)
1163 */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1164 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1165 CHECK_ERROR_QUEUE_ON_RETURN;
1166 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1167 JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1168
1169 if (pkey == nullptr) {
1170 return nullptr;
1171 }
1172
1173 bssl::ScopedCBB cbb;
1174 if (!CBB_init(cbb.get(), 64)) {
1175 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1176 JNI_TRACE("CBB_init failed");
1177 return nullptr;
1178 }
1179
1180 if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1181 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1182 JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1183 return nullptr;
1184 }
1185
1186 return CBBToByteArray(env, cbb.get());
1187 }
1188
1189 /*
1190 * static native long EVP_parse_private_key(byte[])
1191 */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1192 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1193 CHECK_ERROR_QUEUE_ON_RETURN;
1194 JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1195
1196 ScopedByteArrayRO bytes(env, keyJavaBytes);
1197 if (bytes.get() == nullptr) {
1198 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1199 return 0;
1200 }
1201
1202 CBS cbs;
1203 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1204 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1205 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1206 // allow parsing keys from buffers that are larger than the contained key structure
1207 // so we do the same for compatibility.
1208 if (!pkey) {
1209 conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1210 ERR_clear_error();
1211 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1212 return 0;
1213 }
1214
1215 JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1216 return reinterpret_cast<uintptr_t>(pkey.release());
1217 }
1218
1219 /*
1220 * static native byte[] EVP_marshal_public_key(long)
1221 */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1222 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1223 CHECK_ERROR_QUEUE_ON_RETURN;
1224 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1225 JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1226
1227 if (pkey == nullptr) {
1228 return nullptr;
1229 }
1230
1231 bssl::ScopedCBB cbb;
1232 if (!CBB_init(cbb.get(), 64)) {
1233 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1234 JNI_TRACE("CBB_init failed");
1235 return nullptr;
1236 }
1237
1238 if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1239 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1240 JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1241 return nullptr;
1242 }
1243
1244 return CBBToByteArray(env, cbb.get());
1245 }
1246
1247 /*
1248 * static native long EVP_parse_public_key(byte[])
1249 */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1250 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1251 CHECK_ERROR_QUEUE_ON_RETURN;
1252 JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1253
1254 ScopedByteArrayRO bytes(env, keyJavaBytes);
1255 if (bytes.get() == nullptr) {
1256 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1257 return 0;
1258 }
1259
1260 CBS cbs;
1261 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1262 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1263 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1264 // allow parsing keys from buffers that are larger than the contained key structure
1265 // so we do the same for compatibility.
1266 if (!pkey) {
1267 conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1268 ERR_clear_error();
1269 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1270 return 0;
1271 }
1272
1273 JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1274 return reinterpret_cast<uintptr_t>(pkey.release());
1275 }
1276
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1277 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1278 jbyteArray modulusBytes) {
1279 CHECK_ERROR_QUEUE_ON_RETURN;
1280 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1281
1282 size_t cached_size;
1283 if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
1284 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1285 return 0;
1286 }
1287
1288 ensure_engine_globals();
1289
1290 bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1291 if (rsa.get() == nullptr) {
1292 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1293 return 0;
1294 }
1295
1296 // The PSS padding code needs access to the actual n, so set it even though we
1297 // don't set any other parts of the key
1298 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1299 return 0;
1300 }
1301
1302 auto ex_data = new KeyExData;
1303 ex_data->private_key = env->NewGlobalRef(javaKey);
1304 ex_data->cached_size = cached_size;
1305 RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1306
1307 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1308 if (pkey.get() == nullptr) {
1309 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1310 conscrypt::jniutil::throwRuntimeException(env,
1311 "NativeCrypto_getRSAPrivateKeyWrapper failed");
1312 ERR_clear_error();
1313 return 0;
1314 }
1315
1316 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1317 conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1318 ERR_clear_error();
1319 return 0;
1320 }
1321 OWNERSHIP_TRANSFERRED(rsa);
1322 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1323 return reinterpret_cast<uintptr_t>(pkey.release());
1324 }
1325
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1326 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1327 jobject groupRef) {
1328 CHECK_ERROR_QUEUE_ON_RETURN;
1329 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1330 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1331 if (group == nullptr) {
1332 return 0;
1333 }
1334
1335 ensure_engine_globals();
1336
1337 bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1338 if (ecKey.get() == nullptr) {
1339 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1340 return 0;
1341 }
1342
1343 if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1344 JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1345 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1346 return 0;
1347 }
1348
1349 auto ex_data = new KeyExData;
1350 ex_data->private_key = env->NewGlobalRef(javaKey);
1351
1352 if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1353 env->DeleteGlobalRef(ex_data->private_key);
1354 delete ex_data;
1355 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1356 ERR_clear_error();
1357 return 0;
1358 }
1359
1360 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1361 if (pkey.get() == nullptr) {
1362 JNI_TRACE("getECPrivateKeyWrapper failed");
1363 conscrypt::jniutil::throwRuntimeException(env,
1364 "NativeCrypto_getECPrivateKeyWrapper failed");
1365 ERR_clear_error();
1366 return 0;
1367 }
1368
1369 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1370 conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1371 ERR_clear_error();
1372 return 0;
1373 }
1374 OWNERSHIP_TRANSFERRED(ecKey);
1375 return reinterpret_cast<uintptr_t>(pkey.release());
1376 }
1377
1378 /*
1379 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1380 */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1381 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1382 jbyteArray publicExponent) {
1383 CHECK_ERROR_QUEUE_ON_RETURN;
1384 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1385
1386 BIGNUM* eRef = nullptr;
1387 if (!arrayToBignum(env, publicExponent, &eRef)) {
1388 return 0;
1389 }
1390 bssl::UniquePtr<BIGNUM> e(eRef);
1391
1392 bssl::UniquePtr<RSA> rsa(RSA_new());
1393 if (rsa.get() == nullptr) {
1394 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1395 return 0;
1396 }
1397
1398 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1399 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1400 return 0;
1401 }
1402
1403 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1404 if (pkey.get() == nullptr) {
1405 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1406 return 0;
1407 }
1408
1409 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1410 conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1411 ERR_clear_error();
1412 return 0;
1413 }
1414
1415 OWNERSHIP_TRANSFERRED(rsa);
1416 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1417 return reinterpret_cast<uintptr_t>(pkey.release());
1418 }
1419
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1420 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1421 CHECK_ERROR_QUEUE_ON_RETURN;
1422 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1423 JNI_TRACE("RSA_size(%p)", pkey);
1424
1425 if (pkey == nullptr) {
1426 return 0;
1427 }
1428
1429 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1430 if (rsa.get() == nullptr) {
1431 conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1432 ERR_clear_error();
1433 return 0;
1434 }
1435
1436 return static_cast<jint>(RSA_size(rsa.get()));
1437 }
1438
1439 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1440 int padding);
1441
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1442 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1443 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1444 jobject pkeyRef, jint padding) {
1445 CHECK_ERROR_QUEUE_ON_RETURN;
1446 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1447 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1448
1449 if (pkey == nullptr) {
1450 return -1;
1451 }
1452
1453 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1454 if (rsa.get() == nullptr) {
1455 return -1;
1456 }
1457
1458 ScopedByteArrayRO from(env, fromJavaBytes);
1459 if (from.get() == nullptr) {
1460 return -1;
1461 }
1462
1463 ScopedByteArrayRW to(env, toJavaBytes);
1464 if (to.get() == nullptr) {
1465 return -1;
1466 }
1467
1468 int resultSize =
1469 operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1470 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1471 if (resultSize == -1) {
1472 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1473 conscrypt::jniutil::throwBadPaddingException);
1474 JNI_TRACE("%s => threw error", caller);
1475 return -1;
1476 }
1477
1478 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1479 resultSize);
1480 return static_cast<jint>(resultSize);
1481 }
1482
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1483 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1484 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1485 jobject pkeyRef, jint padding) {
1486 CHECK_ERROR_QUEUE_ON_RETURN;
1487 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1488 toJavaBytes, pkeyRef, padding);
1489 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1490 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1491 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1492 jobject pkeyRef, jint padding) {
1493 CHECK_ERROR_QUEUE_ON_RETURN;
1494 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1495 toJavaBytes, pkeyRef, padding);
1496 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1497 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1498 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1499 jobject pkeyRef, jint padding) {
1500 CHECK_ERROR_QUEUE_ON_RETURN;
1501 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1502 toJavaBytes, pkeyRef, padding);
1503 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1504 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1505 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1506 jobject pkeyRef, jint padding) {
1507 CHECK_ERROR_QUEUE_ON_RETURN;
1508 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1509 toJavaBytes, pkeyRef, padding);
1510 }
1511
1512 /*
1513 * public static native byte[][] get_RSA_public_params(long);
1514 */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1515 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1516 CHECK_ERROR_QUEUE_ON_RETURN;
1517 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1518 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1519
1520 if (pkey == nullptr) {
1521 return nullptr;
1522 }
1523
1524 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1525 if (rsa.get() == nullptr) {
1526 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1527 return nullptr;
1528 }
1529
1530 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1531 if (joa == nullptr) {
1532 return nullptr;
1533 }
1534
1535 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1536 if (env->ExceptionCheck()) {
1537 return nullptr;
1538 }
1539 env->SetObjectArrayElement(joa, 0, n);
1540
1541 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1542 if (env->ExceptionCheck()) {
1543 return nullptr;
1544 }
1545 env->SetObjectArrayElement(joa, 1, e);
1546
1547 return joa;
1548 }
1549
1550 /*
1551 * public static native byte[][] get_RSA_private_params(long);
1552 */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1553 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1554 CHECK_ERROR_QUEUE_ON_RETURN;
1555 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1556 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1557
1558 if (pkey == nullptr) {
1559 return nullptr;
1560 }
1561
1562 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1563 if (rsa.get() == nullptr) {
1564 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1565 return nullptr;
1566 }
1567
1568 jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1569 if (joa == nullptr) {
1570 return nullptr;
1571 }
1572
1573 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1574 if (env->ExceptionCheck()) {
1575 return nullptr;
1576 }
1577 env->SetObjectArrayElement(joa, 0, n);
1578
1579 if (RSA_get0_e(rsa.get()) != nullptr) {
1580 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1581 if (env->ExceptionCheck()) {
1582 return nullptr;
1583 }
1584 env->SetObjectArrayElement(joa, 1, e);
1585 }
1586
1587 if (RSA_get0_d(rsa.get()) != nullptr) {
1588 jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1589 if (env->ExceptionCheck()) {
1590 return nullptr;
1591 }
1592 env->SetObjectArrayElement(joa, 2, d);
1593 }
1594
1595 if (RSA_get0_p(rsa.get()) != nullptr) {
1596 jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1597 if (env->ExceptionCheck()) {
1598 return nullptr;
1599 }
1600 env->SetObjectArrayElement(joa, 3, p);
1601 }
1602
1603 if (RSA_get0_q(rsa.get()) != nullptr) {
1604 jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1605 if (env->ExceptionCheck()) {
1606 return nullptr;
1607 }
1608 env->SetObjectArrayElement(joa, 4, q);
1609 }
1610
1611 if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1612 jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1613 if (env->ExceptionCheck()) {
1614 return nullptr;
1615 }
1616 env->SetObjectArrayElement(joa, 5, dmp1);
1617 }
1618
1619 if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1620 jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1621 if (env->ExceptionCheck()) {
1622 return nullptr;
1623 }
1624 env->SetObjectArrayElement(joa, 6, dmq1);
1625 }
1626
1627 if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1628 jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1629 if (env->ExceptionCheck()) {
1630 return nullptr;
1631 }
1632 env->SetObjectArrayElement(joa, 7, iqmp);
1633 }
1634
1635 return joa;
1636 }
1637
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1638 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1639 jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1640 jbyteArray nonceBytes, jint blockCounter) {
1641 CHECK_ERROR_QUEUE_ON_RETURN;
1642 JNI_TRACE("chacha20_encrypt_decrypt");
1643 ScopedByteArrayRO in(env, inBytes);
1644 if (in.get() == nullptr) {
1645 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1646 return;
1647 }
1648 ScopedByteArrayRW out(env, outBytes);
1649 if (out.get() == nullptr) {
1650 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1651 return;
1652 }
1653 ScopedByteArrayRO key(env, keyBytes);
1654 if (key.get() == nullptr) {
1655 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1656 return;
1657 }
1658 ScopedByteArrayRO nonce(env, nonceBytes);
1659 if (nonce.get() == nullptr) {
1660 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1661 return;
1662 }
1663
1664 CRYPTO_chacha_20(
1665 reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1666 reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1667 length,
1668 reinterpret_cast<const unsigned char*>(key.get()),
1669 reinterpret_cast<const unsigned char*>(nonce.get()),
1670 blockCounter);
1671 }
1672
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1673 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1674 CHECK_ERROR_QUEUE_ON_RETURN;
1675 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1676
1677 ScopedUtfChars curveName(env, curveNameJava);
1678 if (curveName.c_str() == nullptr) {
1679 return 0;
1680 }
1681 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1682
1683 int nid = OBJ_sn2nid(curveName.c_str());
1684 if (nid == NID_undef) {
1685 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1686 return 0;
1687 }
1688
1689 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1690 if (group == nullptr) {
1691 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1692 ERR_clear_error();
1693 return 0;
1694 }
1695
1696 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1697 return reinterpret_cast<uintptr_t>(group);
1698 }
1699
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1700 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1701 jbyteArray aBytes, jbyteArray bBytes,
1702 jbyteArray xBytes, jbyteArray yBytes,
1703 jbyteArray orderBytes, jint cofactorInt) {
1704 CHECK_ERROR_QUEUE_ON_RETURN;
1705 BIGNUM *p = nullptr, *a = nullptr, *b = nullptr, *x = nullptr, *y = nullptr;
1706 BIGNUM *order = nullptr, *cofactor = nullptr;
1707
1708 JNI_TRACE("EC_GROUP_new_arbitrary");
1709
1710 if (cofactorInt < 1) {
1711 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1712 "cofactor < 1");
1713 return 0;
1714 }
1715
1716 cofactor = BN_new();
1717 if (cofactor == nullptr) {
1718 return 0;
1719 }
1720
1721 int ok = 1;
1722
1723 if (!arrayToBignum(env, pBytes, &p) || !arrayToBignum(env, aBytes, &a) ||
1724 !arrayToBignum(env, bBytes, &b) || !arrayToBignum(env, xBytes, &x) ||
1725 !arrayToBignum(env, yBytes, &y) || !arrayToBignum(env, orderBytes, &order) ||
1726 !BN_set_word(cofactor, static_cast<uint32_t>(cofactorInt))) {
1727 ok = 0;
1728 }
1729
1730 bssl::UniquePtr<BIGNUM> pStorage(p);
1731 bssl::UniquePtr<BIGNUM> aStorage(a);
1732 bssl::UniquePtr<BIGNUM> bStorage(b);
1733 bssl::UniquePtr<BIGNUM> xStorage(x);
1734 bssl::UniquePtr<BIGNUM> yStorage(y);
1735 bssl::UniquePtr<BIGNUM> orderStorage(order);
1736 bssl::UniquePtr<BIGNUM> cofactorStorage(cofactor);
1737
1738 if (!ok) {
1739 return 0;
1740 }
1741
1742 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1743 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
1744 if (group.get() == nullptr) {
1745 JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1746 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1747 return 0;
1748 }
1749
1750 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1751 if (generator.get() == nullptr) {
1752 JNI_TRACE("EC_POINT_new => null");
1753 ERR_clear_error();
1754 return 0;
1755 }
1756
1757 if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
1758 JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1759 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1760 "EC_POINT_set_affine_coordinates_GFp");
1761 return 0;
1762 }
1763
1764 if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
1765 JNI_TRACE("EC_GROUP_set_generator => error");
1766 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1767 return 0;
1768 }
1769
1770 JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1771 return reinterpret_cast<uintptr_t>(group.release());
1772 }
1773
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1774 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1775 CHECK_ERROR_QUEUE_ON_RETURN;
1776 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1777 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1778
1779 if (group == nullptr) {
1780 JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1781 return nullptr;
1782 }
1783
1784 int nid = EC_GROUP_get_curve_name(group);
1785 if (nid == NID_undef) {
1786 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1787 return nullptr;
1788 }
1789
1790 const char* shortName = OBJ_nid2sn(nid);
1791 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1792 return env->NewStringUTF(shortName);
1793 }
1794
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1795 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1796 CHECK_ERROR_QUEUE_ON_RETURN;
1797 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1798 JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1799 if (group == nullptr) {
1800 JNI_TRACE("EC_GROUP_get_curve => group == null");
1801 return nullptr;
1802 }
1803
1804 bssl::UniquePtr<BIGNUM> p(BN_new());
1805 bssl::UniquePtr<BIGNUM> a(BN_new());
1806 bssl::UniquePtr<BIGNUM> b(BN_new());
1807
1808 int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1809 if (ret != 1) {
1810 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1811 return nullptr;
1812 }
1813
1814 jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1815 if (joa == nullptr) {
1816 return nullptr;
1817 }
1818
1819 jbyteArray pArray = bignumToArray(env, p.get(), "p");
1820 if (env->ExceptionCheck()) {
1821 return nullptr;
1822 }
1823 env->SetObjectArrayElement(joa, 0, pArray);
1824
1825 jbyteArray aArray = bignumToArray(env, a.get(), "a");
1826 if (env->ExceptionCheck()) {
1827 return nullptr;
1828 }
1829 env->SetObjectArrayElement(joa, 1, aArray);
1830
1831 jbyteArray bArray = bignumToArray(env, b.get(), "b");
1832 if (env->ExceptionCheck()) {
1833 return nullptr;
1834 }
1835 env->SetObjectArrayElement(joa, 2, bArray);
1836
1837 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1838 return joa;
1839 }
1840
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1841 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1842 CHECK_ERROR_QUEUE_ON_RETURN;
1843 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1844 JNI_TRACE("EC_GROUP_get_order(%p)", group);
1845 if (group == nullptr) {
1846 return nullptr;
1847 }
1848
1849 bssl::UniquePtr<BIGNUM> order(BN_new());
1850 if (order.get() == nullptr) {
1851 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1852 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1853 return nullptr;
1854 }
1855
1856 if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1857 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1858 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1859 return nullptr;
1860 }
1861
1862 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1863 if (env->ExceptionCheck()) {
1864 return nullptr;
1865 }
1866
1867 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1868 return orderArray;
1869 }
1870
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1871 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1872 CHECK_ERROR_QUEUE_ON_RETURN;
1873 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1874 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1875 if (group == nullptr) {
1876 return 0;
1877 }
1878
1879 jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1880 if (degree == 0) {
1881 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1882 conscrypt::jniutil::throwRuntimeException(env, "not supported");
1883 ERR_clear_error();
1884 return 0;
1885 }
1886
1887 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1888 return degree;
1889 }
1890
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1891 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1892 CHECK_ERROR_QUEUE_ON_RETURN;
1893 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1894 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1895 if (group == nullptr) {
1896 return nullptr;
1897 }
1898
1899 bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1900 if (cofactor.get() == nullptr) {
1901 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1902 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1903 return nullptr;
1904 }
1905
1906 if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1907 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1908 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1909 return nullptr;
1910 }
1911
1912 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1913 if (env->ExceptionCheck()) {
1914 return nullptr;
1915 }
1916
1917 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1918 return cofactorArray;
1919 }
1920
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1921 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1922 CHECK_ERROR_QUEUE_ON_RETURN;
1923 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1924 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1925
1926 if (group == nullptr) {
1927 JNI_TRACE("EC_GROUP_clear_free => group == null");
1928 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1929 return;
1930 }
1931
1932 EC_GROUP_free(group);
1933 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1934 }
1935
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1936 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1937 CHECK_ERROR_QUEUE_ON_RETURN;
1938 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1939 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1940
1941 if (group == nullptr) {
1942 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
1943 return 0;
1944 }
1945
1946 const EC_POINT* generator = EC_GROUP_get0_generator(group);
1947
1948 bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
1949 if (dup.get() == nullptr) {
1950 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
1951 conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
1952 return 0;
1953 }
1954
1955 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
1956 return reinterpret_cast<uintptr_t>(dup.release());
1957 }
1958
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)1959 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
1960 CHECK_ERROR_QUEUE_ON_RETURN;
1961 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1962 JNI_TRACE("EC_POINT_new(%p)", group);
1963
1964 if (group == nullptr) {
1965 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
1966 return 0;
1967 }
1968
1969 EC_POINT* point = EC_POINT_new(group);
1970 if (point == nullptr) {
1971 conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
1972 return 0;
1973 }
1974
1975 return reinterpret_cast<uintptr_t>(point);
1976 }
1977
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)1978 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1979 CHECK_ERROR_QUEUE_ON_RETURN;
1980 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
1981 JNI_TRACE("EC_POINT_clear_free(%p)", group);
1982
1983 if (group == nullptr) {
1984 JNI_TRACE("EC_POINT_clear_free => group == null");
1985 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1986 return;
1987 }
1988
1989 EC_POINT_free(group);
1990 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
1991 }
1992
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)1993 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
1994 jobject pointRef, jbyteArray xjavaBytes,
1995 jbyteArray yjavaBytes) {
1996 CHECK_ERROR_QUEUE_ON_RETURN;
1997 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
1998 yjavaBytes);
1999 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2000 if (group == nullptr) {
2001 return;
2002 }
2003 EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2004 if (point == nullptr) {
2005 return;
2006 }
2007 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
2008 yjavaBytes);
2009
2010 BIGNUM* xRef = nullptr;
2011 if (!arrayToBignum(env, xjavaBytes, &xRef)) {
2012 return;
2013 }
2014 bssl::UniquePtr<BIGNUM> x(xRef);
2015
2016 BIGNUM* yRef = nullptr;
2017 if (!arrayToBignum(env, yjavaBytes, &yRef)) {
2018 return;
2019 }
2020 bssl::UniquePtr<BIGNUM> y(yRef);
2021
2022 int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2023 if (ret != 1) {
2024 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2025 "EC_POINT_set_affine_coordinates");
2026 return;
2027 }
2028
2029 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2030 yjavaBytes, ret);
2031 }
2032
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2033 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2034 jobject groupRef,
2035 jobject pointRef) {
2036 CHECK_ERROR_QUEUE_ON_RETURN;
2037 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2038 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2039 if (group == nullptr) {
2040 return nullptr;
2041 }
2042 const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2043 if (point == nullptr) {
2044 return nullptr;
2045 }
2046 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2047
2048 bssl::UniquePtr<BIGNUM> x(BN_new());
2049 bssl::UniquePtr<BIGNUM> y(BN_new());
2050
2051 int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2052 if (ret != 1) {
2053 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2054 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2055 "EC_POINT_get_affine_coordinates");
2056 return nullptr;
2057 }
2058
2059 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2060 if (joa == nullptr) {
2061 return nullptr;
2062 }
2063
2064 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2065 if (env->ExceptionCheck()) {
2066 return nullptr;
2067 }
2068 env->SetObjectArrayElement(joa, 0, xBytes);
2069
2070 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2071 if (env->ExceptionCheck()) {
2072 return nullptr;
2073 }
2074 env->SetObjectArrayElement(joa, 1, yBytes);
2075
2076 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2077 return joa;
2078 }
2079
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2080 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2081 CHECK_ERROR_QUEUE_ON_RETURN;
2082 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2083 JNI_TRACE("EC_KEY_generate_key(%p)", group);
2084 if (group == nullptr) {
2085 return 0;
2086 }
2087
2088 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2089 if (eckey.get() == nullptr) {
2090 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2091 conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2092 return 0;
2093 }
2094
2095 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2096 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2097 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2098 return 0;
2099 }
2100
2101 if (EC_KEY_generate_key(eckey.get()) != 1) {
2102 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2103 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2104 return 0;
2105 }
2106
2107 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2108 if (pkey.get() == nullptr) {
2109 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2110 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2111 return 0;
2112 }
2113 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2114 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2115 ERR_clear_error();
2116 return 0;
2117 }
2118 OWNERSHIP_TRANSFERRED(eckey);
2119
2120 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2121 return reinterpret_cast<uintptr_t>(pkey.release());
2122 }
2123
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2124 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2125 CHECK_ERROR_QUEUE_ON_RETURN;
2126 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2127 JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2128
2129 if (pkey == nullptr) {
2130 JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2131 return 0;
2132 }
2133
2134 if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2135 conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2136 JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2137 return 0;
2138 }
2139
2140 EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2141 JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2142 return reinterpret_cast<uintptr_t>(group);
2143 }
2144
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2145 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2146 CHECK_ERROR_QUEUE_ON_RETURN;
2147 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2148 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2149
2150 if (pkey == nullptr) {
2151 JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2152 return nullptr;
2153 }
2154
2155 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2156 if (eckey.get() == nullptr) {
2157 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2158 return nullptr;
2159 }
2160
2161 const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2162
2163 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2164 if (env->ExceptionCheck()) {
2165 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2166 return nullptr;
2167 }
2168
2169 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2170 return privBytes;
2171 }
2172
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2173 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2174 CHECK_ERROR_QUEUE_ON_RETURN;
2175 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2176 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2177
2178 if (pkey == nullptr) {
2179 JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2180 return 0;
2181 }
2182
2183 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2184 if (eckey.get() == nullptr) {
2185 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2186 return 0;
2187 }
2188
2189 bssl::UniquePtr<EC_POINT> dup(
2190 EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2191 if (dup.get() == nullptr) {
2192 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2193 conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2194 ERR_clear_error();
2195 return 0;
2196 }
2197
2198 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2199 return reinterpret_cast<uintptr_t>(dup.release());
2200 }
2201
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2202 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2203 CHECK_ERROR_QUEUE_ON_RETURN;
2204 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2205 JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2206 if (group == nullptr) {
2207 conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2208 return nullptr;
2209 }
2210
2211 bssl::ScopedCBB cbb;
2212 if (!CBB_init(cbb.get(), 64)) {
2213 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2214 JNI_TRACE("CBB_init failed");
2215 return nullptr;
2216 }
2217
2218 if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2219 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2220 ERR_clear_error();
2221 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2222 return nullptr;
2223 }
2224
2225 return CBBToByteArray(env, cbb.get());
2226 }
2227
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2228 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2229 CHECK_ERROR_QUEUE_ON_RETURN;
2230 JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2231
2232 ScopedByteArrayRO bytes(env, curveNameBytes);
2233 if (bytes.get() == nullptr) {
2234 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2235 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2236 return 0;
2237 }
2238
2239 CBS cbs;
2240 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2241 bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2242 if (!group || CBS_len(&cbs) != 0) {
2243 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2244 ERR_clear_error();
2245 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2246 return 0;
2247 }
2248
2249 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2250 return reinterpret_cast<uintptr_t>(group.release());
2251 }
2252
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2253 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2254 jobject pubkeyRef, jobject privkeyRef) {
2255 CHECK_ERROR_QUEUE_ON_RETURN;
2256 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2257 EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2258 if (pubPkey == nullptr) {
2259 JNI_TRACE("ECDH_compute_key => pubPkey == null");
2260 return -1;
2261 }
2262 EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2263 if (privPkey == nullptr) {
2264 JNI_TRACE("ECDH_compute_key => privPkey == null");
2265 return -1;
2266 }
2267 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2268
2269 ScopedByteArrayRW out(env, outArray);
2270 if (out.get() == nullptr) {
2271 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2272 pubPkey, privPkey);
2273 return -1;
2274 }
2275
2276 if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2277 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2278 nullptr);
2279 return -1;
2280 }
2281
2282 if (pubPkey == nullptr) {
2283 JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2284 conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2285 return -1;
2286 }
2287
2288 bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2289 if (pubkey.get() == nullptr) {
2290 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2291 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2292 conscrypt::jniutil::throwInvalidKeyException);
2293 return -1;
2294 }
2295
2296 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2297 if (pubkeyPoint == nullptr) {
2298 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2299 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2300 conscrypt::jniutil::throwInvalidKeyException);
2301 return -1;
2302 }
2303
2304 if (privPkey == nullptr) {
2305 JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2306 conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2307 return -1;
2308 }
2309
2310 bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2311 if (privkey.get() == nullptr) {
2312 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2313 conscrypt::jniutil::throwInvalidKeyException);
2314 return -1;
2315 }
2316
2317 std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2318 int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2319 privkey.get(), nullptr /* No KDF */);
2320 if (outputLength == -1) {
2321 JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2322 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2323 conscrypt::jniutil::throwInvalidKeyException);
2324 return -1;
2325 }
2326
2327 JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2328 return outputLength;
2329 }
2330
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2331 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2332 CHECK_ERROR_QUEUE_ON_RETURN;
2333 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2334 JNI_TRACE("ECDSA_size(%p)", pkey);
2335
2336 if (pkey == nullptr) {
2337 return 0;
2338 }
2339
2340 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2341 if (ec_key.get() == nullptr) {
2342 conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2343 ERR_clear_error();
2344 return 0;
2345 }
2346
2347 size_t size = ECDSA_size(ec_key.get());
2348
2349 JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2350 return static_cast<jint>(size);
2351 }
2352
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2353 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2354 jobject pkeyRef) {
2355 CHECK_ERROR_QUEUE_ON_RETURN;
2356 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2357 JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2358
2359 if (pkey == nullptr) {
2360 return -1;
2361 }
2362
2363 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2364 if (ec_key.get() == nullptr) {
2365 return -1;
2366 }
2367
2368 ScopedByteArrayRO data_array(env, data);
2369 if (data_array.get() == nullptr) {
2370 return -1;
2371 }
2372
2373 ScopedByteArrayRW sig_array(env, sig);
2374 if (sig_array.get() == nullptr) {
2375 return -1;
2376 }
2377
2378 unsigned int sig_size;
2379 int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2380 data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2381 &sig_size, ec_key.get());
2382 if (result == 0) {
2383 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2384 JNI_TRACE("ECDSA_sign => threw error");
2385 return -1;
2386 }
2387
2388 JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2389 return static_cast<jint>(sig_size);
2390 }
2391
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2392 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2393 jobject pkeyRef) {
2394 CHECK_ERROR_QUEUE_ON_RETURN;
2395 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2396 JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2397
2398 if (pkey == nullptr) {
2399 return -1;
2400 }
2401
2402 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2403 if (ec_key.get() == nullptr) {
2404 return -1;
2405 }
2406
2407 ScopedByteArrayRO data_array(env, data);
2408 if (data_array.get() == nullptr) {
2409 return -1;
2410 }
2411
2412 ScopedByteArrayRO sig_array(env, sig);
2413 if (sig_array.get() == nullptr) {
2414 return -1;
2415 }
2416
2417 int result =
2418 ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2419 data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2420 sig_array.size(), ec_key.get());
2421
2422 if (result == 0) {
2423 // NOLINTNEXTLINE(runtime/int)
2424 unsigned long error = ERR_peek_last_error();
2425 if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2426 (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2427 // This error just means the signature didn't verify, so clear the error and return
2428 // a failed verification
2429 ERR_clear_error();
2430 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2431 return 0;
2432 }
2433 if (error != 0) {
2434 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2435 JNI_TRACE("ECDSA_verify => threw error");
2436 return -1;
2437 }
2438 return 0;
2439 }
2440
2441 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2442 return static_cast<jint>(result);
2443 }
2444
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2445 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2446 jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2447 CHECK_ERROR_QUEUE_ON_RETURN;
2448 JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2449
2450 ScopedByteArrayRW out(env, outArray);
2451 if (out.get() == nullptr) {
2452 JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2453 return JNI_FALSE;
2454 }
2455
2456 ScopedByteArrayRO privkey(env, privkeyArray);
2457 if (privkey.get() == nullptr) {
2458 JNI_TRACE("X25519(%p) => privkey == null", outArray);
2459 return JNI_FALSE;
2460 }
2461
2462 ScopedByteArrayRO pubkey(env, pubkeyArray);
2463 if (pubkey.get() == nullptr) {
2464 JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2465 return JNI_FALSE;
2466 }
2467
2468 if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2469 reinterpret_cast<const uint8_t*>(privkey.get()),
2470 reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2471 JNI_TRACE("X25519(%p) => failure", outArray);
2472 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2473 conscrypt::jniutil::throwInvalidKeyException);
2474 return JNI_FALSE;
2475 }
2476
2477 JNI_TRACE("X25519(%p) => success", outArray);
2478 return JNI_TRUE;
2479 }
2480
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2481 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2482 CHECK_ERROR_QUEUE_ON_RETURN;
2483 JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2484
2485 ScopedByteArrayRW outPublic(env, outPublicArray);
2486 if (outPublic.get() == nullptr) {
2487 JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2488 return;
2489 }
2490
2491 ScopedByteArrayRW outPrivate(env, outPrivateArray);
2492 if (outPrivate.get() == nullptr) {
2493 JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2494 return;
2495 }
2496
2497 if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2498 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2499 return;
2500 }
2501
2502 X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2503 JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2504 }
2505
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2506 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2507 CHECK_ERROR_QUEUE_ON_RETURN;
2508 JNI_TRACE_MD("EVP_MD_CTX_create()");
2509
2510 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2511 if (ctx.get() == nullptr) {
2512 conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2513 return 0;
2514 }
2515
2516 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2517 return reinterpret_cast<uintptr_t>(ctx.release());
2518 }
2519
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2520 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2521 CHECK_ERROR_QUEUE_ON_RETURN;
2522 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2523 JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2524
2525 if (ctx != nullptr) {
2526 EVP_MD_CTX_cleanup(ctx);
2527 }
2528 }
2529
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2530 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2531 CHECK_ERROR_QUEUE_ON_RETURN;
2532 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2533 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2534
2535 if (ctx != nullptr) {
2536 EVP_MD_CTX_destroy(ctx);
2537 }
2538 }
2539
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2540 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2541 jobject srcCtxRef) {
2542 CHECK_ERROR_QUEUE_ON_RETURN;
2543 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2544 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2545 if (dst_ctx == nullptr) {
2546 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2547 return 0;
2548 }
2549 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2550 if (src_ctx == nullptr) {
2551 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2552 return 0;
2553 }
2554 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2555
2556 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2557 if (result == 0) {
2558 conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2559 ERR_clear_error();
2560 }
2561
2562 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2563 return result;
2564 }
2565
2566 /*
2567 * public static native int EVP_DigestFinal_ex(long, byte[], int)
2568 */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2569 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2570 jint offset) {
2571 CHECK_ERROR_QUEUE_ON_RETURN;
2572 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2573 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2574
2575 if (ctx == nullptr) {
2576 JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2577 return -1;
2578 } else if (hash == nullptr) {
2579 conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2580 return -1;
2581 }
2582
2583 ScopedByteArrayRW hashBytes(env, hash);
2584 if (hashBytes.get() == nullptr) {
2585 return -1;
2586 }
2587 unsigned int bytesWritten = static_cast<unsigned int>(-1);
2588 int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2589 &bytesWritten);
2590 if (ok == 0) {
2591 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2592 return -1;
2593 }
2594
2595 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2596 return static_cast<jint>(bytesWritten);
2597 }
2598
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2599 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2600 jlong evpMdRef) {
2601 CHECK_ERROR_QUEUE_ON_RETURN;
2602 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2603 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2604 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2605
2606 if (ctx == nullptr) {
2607 JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2608 return 0;
2609 } else if (evp_md == nullptr) {
2610 conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2611 return 0;
2612 }
2613
2614 int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2615 if (ok == 0) {
2616 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2617 JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2618 return 0;
2619 }
2620 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2621 return ok;
2622 }
2623
2624 /*
2625 * public static native int EVP_get_digestbyname(java.lang.String)
2626 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2627 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2628 CHECK_ERROR_QUEUE_ON_RETURN;
2629 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2630
2631 if (algorithm == nullptr) {
2632 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2633 return -1;
2634 }
2635
2636 ScopedUtfChars algorithmChars(env, algorithm);
2637 if (algorithmChars.c_str() == nullptr) {
2638 return 0;
2639 }
2640 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2641
2642 const char* alg = algorithmChars.c_str();
2643 const EVP_MD* md;
2644
2645 if (strcasecmp(alg, "md4") == 0) {
2646 md = EVP_md4();
2647 } else if (strcasecmp(alg, "md5") == 0) {
2648 md = EVP_md5();
2649 } else if (strcasecmp(alg, "sha1") == 0) {
2650 md = EVP_sha1();
2651 } else if (strcasecmp(alg, "sha224") == 0) {
2652 md = EVP_sha224();
2653 } else if (strcasecmp(alg, "sha256") == 0) {
2654 md = EVP_sha256();
2655 } else if (strcasecmp(alg, "sha384") == 0) {
2656 md = EVP_sha384();
2657 } else if (strcasecmp(alg, "sha512") == 0) {
2658 md = EVP_sha512();
2659 } else {
2660 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2661 conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2662 return 0;
2663 }
2664
2665 return reinterpret_cast<uintptr_t>(md);
2666 }
2667
2668 /*
2669 * public static native int EVP_MD_size(long)
2670 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2671 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2672 CHECK_ERROR_QUEUE_ON_RETURN;
2673 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2674 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2675
2676 if (evp_md == nullptr) {
2677 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2678 return -1;
2679 }
2680
2681 jint result = static_cast<jint>(EVP_MD_size(evp_md));
2682 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2683 return result;
2684 }
2685
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)2686 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2687 int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2688 ENGINE*, EVP_PKEY*),
2689 const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2690 jobject pkeyRef) {
2691 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2692 if (mdCtx == nullptr) {
2693 JNI_TRACE("%s => mdCtx == null", jniName);
2694 return 0;
2695 }
2696 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2697 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2698 if (pkey == nullptr) {
2699 JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2700 return 0;
2701 }
2702 JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2703
2704 if (md == nullptr) {
2705 JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2706 conscrypt::jniutil::throwNullPointerException(env, "md == null");
2707 return 0;
2708 }
2709
2710 EVP_PKEY_CTX* pctx = nullptr;
2711 if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2712 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2713 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2714 return 0;
2715 }
2716
2717 JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2718 return reinterpret_cast<jlong>(pctx);
2719 }
2720
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2721 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2722 const jlong evpMdRef, jobject pkeyRef) {
2723 CHECK_ERROR_QUEUE_ON_RETURN;
2724 return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2725 evpMdRef, pkeyRef);
2726 }
2727
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2728 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2729 const jlong evpMdRef, jobject pkeyRef) {
2730 CHECK_ERROR_QUEUE_ON_RETURN;
2731 return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2732 evpMdRef, pkeyRef);
2733 }
2734
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2735 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2736 const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2737 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2738 const void* p = reinterpret_cast<const void*>(inPtr);
2739 JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2740
2741 if (mdCtx == nullptr) {
2742 return;
2743 }
2744
2745 if (p == nullptr) {
2746 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2747 return;
2748 }
2749
2750 if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2751 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2752 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2753 return;
2754 }
2755
2756 JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2757 }
2758
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2759 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2760 jint inLength, const char* jniName,
2761 int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2762 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2763 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2764
2765 if (mdCtx == nullptr) {
2766 return;
2767 }
2768
2769 if (inJavaBytes == nullptr) {
2770 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2771 return;
2772 }
2773
2774 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2775 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2776 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2777 "inBytes");
2778 return;
2779 }
2780 if (inLength == 0) {
2781 return;
2782 }
2783 jint in_offset = inOffset;
2784 jint in_size = inLength;
2785
2786 int update_func_result = -1;
2787 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2788 // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2789 // avoid copying the whole array.
2790 if (in_size <= 1024) {
2791 // For small chunk, it's more efficient to use a bit more space on the stack instead of
2792 // allocating a new buffer.
2793 jbyte buf[1024];
2794 env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2795 update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2796 static_cast<size_t>(in_size));
2797 } else {
2798 // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2799 // through the buffer, stopping as soon as update_func fails.
2800 jint remaining = in_size;
2801 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2802 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2803 if (buf.get() == nullptr) {
2804 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2805 return;
2806 }
2807 while (remaining > 0) {
2808 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2809 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2810 update_func_result =
2811 update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2812 static_cast<size_t>(chunk_size));
2813 if (!update_func_result) {
2814 // update_func failed. This will be handled later in this method.
2815 break;
2816 }
2817 in_offset += chunk_size;
2818 remaining -= chunk_size;
2819 }
2820 }
2821 } else {
2822 // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2823 // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2824 // use GetByteArrayElements or another approach.
2825 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2826 if (array_elements == nullptr) {
2827 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2828 return;
2829 }
2830 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2831 update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2832 env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2833 }
2834
2835 if (!update_func_result) {
2836 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2837 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2838 return;
2839 }
2840
2841 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2842 }
2843
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2844 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2845 jlong inPtr, jint inLength) {
2846 CHECK_ERROR_QUEUE_ON_RETURN;
2847 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2848 }
2849
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2850 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2851 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2852 CHECK_ERROR_QUEUE_ON_RETURN;
2853 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2854 EVP_DigestUpdate);
2855 }
2856
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2857 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2858 jbyteArray inJavaBytes, jint inOffset,
2859 jint inLength) {
2860 CHECK_ERROR_QUEUE_ON_RETURN;
2861 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2862 EVP_DigestSignUpdate);
2863 }
2864
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2865 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2866 jlong inPtr, jint inLength) {
2867 CHECK_ERROR_QUEUE_ON_RETURN;
2868 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2869 EVP_DigestSignUpdate);
2870 }
2871
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2872 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2873 jbyteArray inJavaBytes, jint inOffset,
2874 jint inLength) {
2875 CHECK_ERROR_QUEUE_ON_RETURN;
2876 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2877 EVP_DigestVerifyUpdate);
2878 }
2879
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2880 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2881 jlong inPtr, jint inLength) {
2882 CHECK_ERROR_QUEUE_ON_RETURN;
2883 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2884 EVP_DigestVerifyUpdate);
2885 }
2886
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2887 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2888 CHECK_ERROR_QUEUE_ON_RETURN;
2889 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2890 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2891
2892 if (mdCtx == nullptr) {
2893 return nullptr;
2894 }
2895
2896 size_t maxLen;
2897 if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2898 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2899 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2900 return nullptr;
2901 }
2902
2903 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2904 if (buffer.get() == nullptr) {
2905 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2906 return nullptr;
2907 }
2908 size_t actualLen(maxLen);
2909 if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2910 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2911 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2912 return nullptr;
2913 }
2914 if (actualLen > maxLen) {
2915 JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2916 maxLen);
2917 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2918 return nullptr;
2919 }
2920
2921 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2922 if (sigJavaBytes.get() == nullptr) {
2923 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2924 return nullptr;
2925 }
2926 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2927 reinterpret_cast<jbyte*>(buffer.get()));
2928
2929 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2930 return sigJavaBytes.release();
2931 }
2932
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2933 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2934 jbyteArray signature, jint offset, jint len) {
2935 CHECK_ERROR_QUEUE_ON_RETURN;
2936 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2937 JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2938
2939 if (mdCtx == nullptr) {
2940 return 0;
2941 }
2942
2943 ScopedByteArrayRO sigBytes(env, signature);
2944 if (sigBytes.get() == nullptr) {
2945 return 0;
2946 }
2947
2948 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
2949 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2950 "signature");
2951 return 0;
2952 }
2953
2954 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
2955 int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
2956 jboolean result;
2957 if (err == 1) {
2958 // Signature verified
2959 result = 1;
2960 } else if (err == 0) {
2961 // Signature did not verify
2962 result = 0;
2963 } else {
2964 // Error while verifying signature
2965 JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
2966 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
2967 return 0;
2968 }
2969
2970 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
2971 // Clear the error queue to prevent its state from affecting future operations.
2972 ERR_clear_error();
2973
2974 JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
2975 return result;
2976 }
2977
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)2978 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
2979 int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
2980 const uint8_t*, size_t),
2981 const char* jniName, jobject evpPkeyCtxRef,
2982 jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
2983 jint inOffset, jint inLength) {
2984 EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
2985 JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
2986 inJavaBytes, inOffset, inLength);
2987
2988 if (pkeyCtx == nullptr) {
2989 return 0;
2990 }
2991
2992 ScopedByteArrayRW outBytes(env, outJavaBytes);
2993 if (outBytes.get() == nullptr) {
2994 return 0;
2995 }
2996
2997 ScopedByteArrayRO inBytes(env, inJavaBytes);
2998 if (inBytes.get() == nullptr) {
2999 return 0;
3000 }
3001
3002 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3003 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3004 "outBytes");
3005 return 0;
3006 }
3007
3008 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3009 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3010 "inBytes");
3011 return 0;
3012 }
3013
3014 uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3015 const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3016 size_t outLength = outBytes.size() - outOffset;
3017 if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3018 static_cast<size_t>(inLength))) {
3019 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3020 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3021 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3022 return 0;
3023 }
3024
3025 JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3026 outOffset, inJavaBytes, inOffset, inLength, outLength);
3027 return static_cast<jint>(outLength);
3028 }
3029
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3030 static jint NativeCrypto_EVP_PKEY_encrypt(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_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3035 outOffset, inBytes, inOffset, inLength);
3036 }
3037
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3038 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3039 jbyteArray out, jint outOffset, jbyteArray inBytes,
3040 jint inOffset, jint inLength) {
3041 CHECK_ERROR_QUEUE_ON_RETURN;
3042 return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3043 outOffset, inBytes, inOffset, inLength);
3044 }
3045
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3046 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3047 int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3048 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3049 JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3050 if (pkey == nullptr) {
3051 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3052 return 0;
3053 }
3054
3055 bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3056 if (pkeyCtx.get() == nullptr) {
3057 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3058 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3059 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3060 return 0;
3061 }
3062
3063 if (!real_func(pkeyCtx.get())) {
3064 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3065 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3066 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3067 return 0;
3068 }
3069
3070 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3071 return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3072 }
3073
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3074 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3075 CHECK_ERROR_QUEUE_ON_RETURN;
3076 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3077 }
3078
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3079 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3080 CHECK_ERROR_QUEUE_ON_RETURN;
3081 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3082 }
3083
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3084 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3085 CHECK_ERROR_QUEUE_ON_RETURN;
3086 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3087 JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3088
3089 if (pkeyCtx != nullptr) {
3090 EVP_PKEY_CTX_free(pkeyCtx);
3091 }
3092 }
3093
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3094 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3095 CHECK_ERROR_QUEUE_ON_RETURN;
3096 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3097 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3098 if (pkeyCtx == nullptr) {
3099 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3100 return;
3101 }
3102
3103 int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3104 if (result <= 0) {
3105 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3106 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3107 env, "EVP_PKEY_CTX_set_rsa_padding",
3108 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3109 return;
3110 }
3111
3112 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3113 }
3114
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3115 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3116 jint len) {
3117 CHECK_ERROR_QUEUE_ON_RETURN;
3118 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3119 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3120 if (pkeyCtx == nullptr) {
3121 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3122 return;
3123 }
3124
3125 int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3126 if (result <= 0) {
3127 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3128 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3129 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3130 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3131 return;
3132 }
3133
3134 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3135 }
3136
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3137 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3138 int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3139 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3140 EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3141 JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3142 if (pkeyCtx == nullptr) {
3143 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3144 return;
3145 }
3146 if (md == nullptr) {
3147 conscrypt::jniutil::throwNullPointerException(env, "md == null");
3148 return;
3149 }
3150
3151 int result = ctrl_func(pkeyCtx, md);
3152 if (result <= 0) {
3153 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3154 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3155 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3156 return;
3157 }
3158
3159 JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3160 }
3161
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3162 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3163 jlong mdRef) {
3164 CHECK_ERROR_QUEUE_ON_RETURN;
3165 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3166 EVP_PKEY_CTX_set_rsa_mgf1_md);
3167 }
3168
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3169 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3170 jlong mdRef) {
3171 CHECK_ERROR_QUEUE_ON_RETURN;
3172 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3173 EVP_PKEY_CTX_set_rsa_oaep_md);
3174 }
3175
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3176 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3177 jbyteArray labelJava) {
3178 CHECK_ERROR_QUEUE_ON_RETURN;
3179 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3180 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3181 if (pkeyCtx == nullptr) {
3182 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3183 return;
3184 }
3185
3186 ScopedByteArrayRO labelBytes(env, labelJava);
3187 if (labelBytes.get() == nullptr) {
3188 return;
3189 }
3190
3191 bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3192 memcpy(label.get(), labelBytes.get(), labelBytes.size());
3193
3194 int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3195 if (result <= 0) {
3196 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3197 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3198 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3199 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3200 return;
3201 }
3202 OWNERSHIP_TRANSFERRED(label);
3203
3204 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3205 }
3206
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3207 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3208 CHECK_ERROR_QUEUE_ON_RETURN;
3209 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3210
3211 ScopedUtfChars scoped_alg(env, algorithm);
3212 const char* alg = scoped_alg.c_str();
3213 const EVP_CIPHER* cipher;
3214
3215 if (strcasecmp(alg, "rc4") == 0) {
3216 cipher = EVP_rc4();
3217 } else if (strcasecmp(alg, "des-cbc") == 0) {
3218 cipher = EVP_des_cbc();
3219 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3220 cipher = EVP_des_ede_cbc();
3221 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3222 cipher = EVP_des_ede3_cbc();
3223 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3224 cipher = EVP_aes_128_ecb();
3225 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3226 cipher = EVP_aes_128_cbc();
3227 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3228 cipher = EVP_aes_128_ctr();
3229 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3230 cipher = EVP_aes_128_gcm();
3231 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3232 cipher = EVP_aes_192_ecb();
3233 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3234 cipher = EVP_aes_192_cbc();
3235 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3236 cipher = EVP_aes_192_ctr();
3237 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3238 cipher = EVP_aes_192_gcm();
3239 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3240 cipher = EVP_aes_256_ecb();
3241 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3242 cipher = EVP_aes_256_cbc();
3243 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3244 cipher = EVP_aes_256_ctr();
3245 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3246 cipher = EVP_aes_256_gcm();
3247 } else {
3248 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
3249 return 0;
3250 }
3251
3252 return reinterpret_cast<uintptr_t>(cipher);
3253 }
3254
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3255 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3256 jbyteArray keyArray, jbyteArray ivArray,
3257 jboolean encrypting) {
3258 CHECK_ERROR_QUEUE_ON_RETURN;
3259 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3260 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3261 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3262 encrypting ? 1 : 0);
3263
3264 if (ctx == nullptr) {
3265 JNI_TRACE("EVP_CipherUpdate => ctx == null");
3266 return;
3267 }
3268
3269 // The key can be null if we need to set extra parameters.
3270 std::unique_ptr<unsigned char[]> keyPtr;
3271 if (keyArray != nullptr) {
3272 ScopedByteArrayRO keyBytes(env, keyArray);
3273 if (keyBytes.get() == nullptr) {
3274 return;
3275 }
3276
3277 keyPtr.reset(new unsigned char[keyBytes.size()]);
3278 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3279 }
3280
3281 // The IV can be null if we're using ECB.
3282 std::unique_ptr<unsigned char[]> ivPtr;
3283 if (ivArray != nullptr) {
3284 ScopedByteArrayRO ivBytes(env, ivArray);
3285 if (ivBytes.get() == nullptr) {
3286 return;
3287 }
3288
3289 ivPtr.reset(new unsigned char[ivBytes.size()]);
3290 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3291 }
3292
3293 if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3294 encrypting ? 1 : 0)) {
3295 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3296 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3297 return;
3298 }
3299
3300 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3301 encrypting ? 1 : 0);
3302 }
3303
3304 /*
3305 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3306 * int inOffset, int inLength);
3307 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3308 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3309 jint outOffset, jbyteArray inArray, jint inOffset,
3310 jint inLength) {
3311 CHECK_ERROR_QUEUE_ON_RETURN;
3312 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3313 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3314
3315 if (ctx == nullptr) {
3316 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3317 return 0;
3318 }
3319
3320 ScopedByteArrayRO inBytes(env, inArray);
3321 if (inBytes.get() == nullptr) {
3322 return 0;
3323 }
3324 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3325 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3326 "inBytes");
3327 return 0;
3328 }
3329
3330 ScopedByteArrayRW outBytes(env, outArray);
3331 if (outBytes.get() == nullptr) {
3332 return 0;
3333 }
3334 if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3335 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3336 "outBytes");
3337 return 0;
3338 }
3339
3340 JNI_TRACE(
3341 "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3342 "out.length=%zd outOffset=%d",
3343 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3344 outOffset);
3345
3346 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3347 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3348
3349 int outl;
3350 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3351 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3352 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3353 return 0;
3354 }
3355
3356 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3357 inOffset, outl);
3358 return outl;
3359 }
3360
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3361 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3362 jbyteArray outArray, jint outOffset) {
3363 CHECK_ERROR_QUEUE_ON_RETURN;
3364 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3365 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3366
3367 if (ctx == nullptr) {
3368 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3369 return 0;
3370 }
3371
3372 ScopedByteArrayRW outBytes(env, outArray);
3373 if (outBytes.get() == nullptr) {
3374 return 0;
3375 }
3376
3377 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3378
3379 int outl;
3380 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3381 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3382 conscrypt::jniutil::throwBadPaddingException);
3383 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3384 return 0;
3385 }
3386
3387 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3388 return outl;
3389 }
3390
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3391 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3392 CHECK_ERROR_QUEUE_ON_RETURN;
3393 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3394 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3395
3396 if (evpCipher == nullptr) {
3397 conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3398 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3399 return 0;
3400 }
3401
3402 jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3403 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3404 return ivLength;
3405 }
3406
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3407 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3408 CHECK_ERROR_QUEUE_ON_RETURN;
3409 JNI_TRACE("EVP_CIPHER_CTX_new()");
3410
3411 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3412 if (ctx.get() == nullptr) {
3413 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3414 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3415 return 0;
3416 }
3417
3418 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3419 return reinterpret_cast<uintptr_t>(ctx.release());
3420 }
3421
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3422 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3423 CHECK_ERROR_QUEUE_ON_RETURN;
3424 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3425 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3426
3427 if (ctx == nullptr) {
3428 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3429 return 0;
3430 }
3431
3432 jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3433 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3434 return blockSize;
3435 }
3436
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3437 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3438 CHECK_ERROR_QUEUE_ON_RETURN;
3439 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3440 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3441
3442 if (ctx == nullptr) {
3443 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3444 return 0;
3445 }
3446
3447 int buf_len = ctx->buf_len;
3448 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3449 return buf_len;
3450 }
3451
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3452 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3453 CHECK_ERROR_QUEUE_ON_RETURN;
3454 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3455 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3456
3457 if (ctx == nullptr) {
3458 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3459 return 0;
3460 }
3461
3462 bool final_used = ctx->final_used != 0;
3463 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3464 return static_cast<jboolean>(final_used);
3465 }
3466
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3467 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3468 jboolean enablePaddingBool) {
3469 CHECK_ERROR_QUEUE_ON_RETURN;
3470 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3471 jint enablePadding = enablePaddingBool ? 1 : 0;
3472 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3473
3474 if (ctx == nullptr) {
3475 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3476 return;
3477 }
3478
3479 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3480 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3481 }
3482
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3483 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3484 jint keySizeBits) {
3485 CHECK_ERROR_QUEUE_ON_RETURN;
3486 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3487 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3488
3489 if (ctx == nullptr) {
3490 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3491 return;
3492 }
3493
3494 if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3495 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3496 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3497 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3498 return;
3499 }
3500 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3501 }
3502
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3503 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3504 CHECK_ERROR_QUEUE_ON_RETURN;
3505 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3506 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3507
3508 EVP_CIPHER_CTX_free(ctx);
3509 }
3510
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3511 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3512 CHECK_ERROR_QUEUE_ON_RETURN;
3513 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3514 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3515 return reinterpret_cast<jlong>(ctx);
3516 }
3517
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3518 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3519 CHECK_ERROR_QUEUE_ON_RETURN;
3520 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3521 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3522 return reinterpret_cast<jlong>(ctx);
3523 }
3524
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3525 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3526 CHECK_ERROR_QUEUE_ON_RETURN;
3527 const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3528 JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3529 return reinterpret_cast<jlong>(ctx);
3530 }
3531
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3532 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3533 CHECK_ERROR_QUEUE_ON_RETURN;
3534 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3535 JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3536 return reinterpret_cast<jlong>(ctx);
3537 }
3538
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3539 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3540 CHECK_ERROR_QUEUE_ON_RETURN;
3541 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3542 JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3543 return reinterpret_cast<jlong>(ctx);
3544 }
3545
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3546 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3547 CHECK_ERROR_QUEUE_ON_RETURN;
3548 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3549 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3550 if (evpAead == nullptr) {
3551 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3552 return 0;
3553 }
3554 jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3555 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3556 return maxOverhead;
3557 }
3558
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3559 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3560 CHECK_ERROR_QUEUE_ON_RETURN;
3561 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3562 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3563 if (evpAead == nullptr) {
3564 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3565 return 0;
3566 }
3567 jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3568 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3569 return nonceLength;
3570 }
3571
3572 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3573 size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3574 const uint8_t* in, size_t in_len, const uint8_t* ad,
3575 size_t ad_len);
3576
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)3577 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3578 uint8_t* outBuf, jbyteArray nonceArray,
3579 const uint8_t* inBuf, jbyteArray aadArray,
3580 evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange) {
3581 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3582
3583 ScopedByteArrayRO keyBytes(env, keyArray);
3584 if (keyBytes.get() == nullptr) {
3585 return 0;
3586 }
3587
3588 std::unique_ptr<ScopedByteArrayRO> aad;
3589 const uint8_t* aad_chars = nullptr;
3590 size_t aad_chars_size = 0;
3591 if (aadArray != nullptr) {
3592 aad.reset(new ScopedByteArrayRO(env, aadArray));
3593 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3594 if (aad_chars == nullptr) {
3595 return 0;
3596 }
3597 aad_chars_size = aad->size();
3598 }
3599
3600 ScopedByteArrayRO nonceBytes(env, nonceArray);
3601 if (nonceBytes.get() == nullptr) {
3602 return 0;
3603 }
3604
3605 bssl::ScopedEVP_AEAD_CTX aeadCtx;
3606 const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3607 if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3608 static_cast<size_t>(tagLen), nullptr)) {
3609 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3610 "failure initializing AEAD context");
3611 JNI_TRACE(
3612 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3613 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3614 aadArray);
3615 return 0;
3616 }
3617
3618 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3619 size_t actualOutLength;
3620
3621 if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3622 nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3623 aad_chars, aad_chars_size)) {
3624 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3625 return 0;
3626 }
3627
3628 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3629 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3630 aadArray, actualOutLength);
3631 return static_cast<jint>(actualOutLength);
3632 }
3633
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)3634 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3635 jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3636 jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3637 evp_aead_ctx_op_func realFunc) {
3638 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3639 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3640 outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3641
3642
3643 ScopedByteArrayRW outBytes(env, outArray);
3644 if (outBytes.get() == nullptr) {
3645 return 0;
3646 }
3647
3648 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3649 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3650 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3651 inLength, aadArray);
3652 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3653 return 0;
3654 }
3655
3656 ScopedByteArrayRO inBytes(env, inArray);
3657 if (inBytes.get() == nullptr) {
3658 return 0;
3659 }
3660
3661 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3662 JNI_TRACE(
3663 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3664 "invalid",
3665 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3666 inLength, aadArray);
3667 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3668 return 0;
3669 }
3670
3671 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3672 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3673
3674 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3675 aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3676 }
3677
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)3678 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3679 jobject outBuffer, jbyteArray nonceArray,
3680 jobject inBuffer, jbyteArray aadArray,
3681 evp_aead_ctx_op_func realFunc) {
3682
3683 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3684 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3685 outBuffer, nonceArray, inBuffer, aadArray);
3686
3687 if (env->IsInstanceOf(inBuffer, conscrypt::jniutil::byteBufferClass) != JNI_TRUE ||
3688 env->IsInstanceOf(outBuffer, conscrypt::jniutil::byteBufferClass) != JNI_TRUE ) {
3689 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "ByteBuffer Class Error");
3690 return 0;
3691 }
3692
3693 uint8_t* inBuf;
3694 jint in_limit;
3695 jint in_position;
3696 jint inCapacity = env->GetDirectBufferCapacity(inBuffer);
3697 if (inCapacity == -1) {
3698 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Non Direct ByteBuffer Error");
3699 return 0;
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 jint outCapacity = env->GetDirectBufferCapacity(outBuffer);
3711 if (outCapacity == -1) {
3712 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Non Direct ByteBuffer Error");
3713 return 0;
3714 }
3715 outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3716 // limit is the index of the first element that should not be read or written
3717 out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3718 // position is the index of the next element to be read or written
3719 out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3720
3721 // Shifting over of ByteBuffer address to start at true position
3722 inBuf += in_position;
3723 outBuf += out_position;
3724
3725 size_t inSize = in_limit - in_position;
3726 uint8_t* outBufEnd = outBuf + out_limit - out_position;
3727 uint8_t* inBufEnd = inBuf + inSize;
3728 std::unique_ptr<uint8_t[]> inCopy;
3729 if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3730 inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3731 if (inCopy.get() == nullptr) {
3732 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3733 return 0;
3734 }
3735 memcpy(inCopy.get(), inBuf, inSize);
3736 inBuf = inCopy.get();
3737 }
3738
3739 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3740 inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3741 }
3742
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)3743 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3744 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3745 jint outOffset, jbyteArray nonceArray,
3746 jbyteArray inArray, jint inOffset, jint inLength,
3747 jbyteArray aadArray) {
3748 CHECK_ERROR_QUEUE_ON_RETURN;
3749 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3750 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3751 }
3752
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)3753 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3754 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3755 jint outOffset, jbyteArray nonceArray,
3756 jbyteArray inArray, jint inOffset, jint inLength,
3757 jbyteArray aadArray) {
3758 CHECK_ERROR_QUEUE_ON_RETURN;
3759 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3760 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3761 }
3762
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3763 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3764 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3765 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3766 CHECK_ERROR_QUEUE_ON_RETURN;
3767 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3768 inBuffer, aadArray, EVP_AEAD_CTX_seal);
3769 }
3770
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3771 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3772 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3773 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3774 CHECK_ERROR_QUEUE_ON_RETURN;
3775 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3776 inBuffer, aadArray, EVP_AEAD_CTX_open);
3777 }
3778
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)3779 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
3780 CHECK_ERROR_QUEUE_ON_RETURN;
3781 JNI_TRACE("CMAC_CTX_new");
3782 auto cmacCtx = CMAC_CTX_new();
3783 if (cmacCtx == nullptr) {
3784 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
3785 return 0;
3786 }
3787
3788 return reinterpret_cast<jlong>(cmacCtx);
3789 }
3790
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)3791 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
3792 CHECK_ERROR_QUEUE_ON_RETURN;
3793 CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
3794 JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
3795 if (cmacCtx == nullptr) {
3796 conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
3797 return;
3798 }
3799 CMAC_CTX_free(cmacCtx);
3800 }
3801
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)3802 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
3803 CHECK_ERROR_QUEUE_ON_RETURN;
3804 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3805 JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
3806 if (cmacCtx == nullptr) {
3807 return;
3808 }
3809 ScopedByteArrayRO keyBytes(env, keyArray);
3810 if (keyBytes.get() == nullptr) {
3811 return;
3812 }
3813
3814 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3815
3816 const EVP_CIPHER *cipher;
3817 switch(keyBytes.size()) {
3818 case 16:
3819 cipher = EVP_aes_128_cbc();
3820 break;
3821 case 24:
3822 cipher = EVP_aes_192_cbc();
3823 break;
3824 case 32:
3825 cipher = EVP_aes_256_cbc();
3826 break;
3827 default:
3828 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3829 "CMAC_Init: Unsupported key length");
3830 return;
3831 }
3832
3833 if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
3834 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
3835 JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
3836 return;
3837 }
3838 }
3839
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)3840 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
3841 int inLength) {
3842 CHECK_ERROR_QUEUE_ON_RETURN;
3843 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3844 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3845 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
3846
3847 if (cmacCtx == nullptr) {
3848 return;
3849 }
3850
3851 if (p == nullptr) {
3852 conscrypt::jniutil::throwNullPointerException(env, nullptr);
3853 return;
3854 }
3855
3856 if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
3857 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
3858 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
3859 return;
3860 }
3861 }
3862
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3863 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
3864 jint inOffset, jint inLength) {
3865 CHECK_ERROR_QUEUE_ON_RETURN;
3866 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3867 JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
3868
3869 if (cmacCtx == nullptr) {
3870 return;
3871 }
3872
3873 ScopedByteArrayRO inBytes(env, inArray);
3874 if (inBytes.get() == nullptr) {
3875 return;
3876 }
3877
3878 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3879 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3880 "inBytes");
3881 return;
3882 }
3883
3884 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
3885
3886 if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
3887 JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
3888 inLength);
3889 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
3890 return;
3891 }
3892 }
3893
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)3894 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
3895 CHECK_ERROR_QUEUE_ON_RETURN;
3896 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
3897 JNI_TRACE("CMAC_Final(%p)", cmacCtx);
3898
3899 if (cmacCtx == nullptr) {
3900 return nullptr;
3901 }
3902
3903 uint8_t result[EVP_MAX_MD_SIZE];
3904 size_t len;
3905 if (!CMAC_Final(cmacCtx, result, &len)) {
3906 JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
3907 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
3908 return nullptr;
3909 }
3910
3911 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
3912 if (resultArray.get() == nullptr) {
3913 return nullptr;
3914 }
3915 ScopedByteArrayRW resultBytes(env, resultArray.get());
3916 if (resultBytes.get() == nullptr) {
3917 return nullptr;
3918 }
3919 memcpy(resultBytes.get(), result, len);
3920 return resultArray.release();
3921 }
3922
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)3923 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
3924 CHECK_ERROR_QUEUE_ON_RETURN;
3925 JNI_TRACE("HMAC_CTX_new");
3926 auto hmacCtx = new HMAC_CTX;
3927 if (hmacCtx == nullptr) {
3928 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
3929 return 0;
3930 }
3931
3932 HMAC_CTX_init(hmacCtx);
3933 return reinterpret_cast<jlong>(hmacCtx);
3934 }
3935
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)3936 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
3937 CHECK_ERROR_QUEUE_ON_RETURN;
3938 HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
3939 JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
3940 if (hmacCtx == nullptr) {
3941 conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
3942 return;
3943 }
3944 HMAC_CTX_cleanup(hmacCtx);
3945 delete hmacCtx;
3946 }
3947
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)3948 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
3949 jobject evpMdRef) {
3950 CHECK_ERROR_QUEUE_ON_RETURN;
3951 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3952 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
3953 JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
3954 if (hmacCtx == nullptr) {
3955 return;
3956 }
3957 ScopedByteArrayRO keyBytes(env, keyArray);
3958 if (keyBytes.get() == nullptr) {
3959 return;
3960 }
3961
3962 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
3963 if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
3964 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
3965 JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
3966 return;
3967 }
3968 }
3969
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)3970 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
3971 int inLength) {
3972 CHECK_ERROR_QUEUE_ON_RETURN;
3973 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3974 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
3975 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
3976
3977 if (hmacCtx == nullptr) {
3978 return;
3979 }
3980
3981 if (p == nullptr) {
3982 conscrypt::jniutil::throwNullPointerException(env, nullptr);
3983 return;
3984 }
3985
3986 if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
3987 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
3988 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
3989 return;
3990 }
3991 }
3992
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)3993 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
3994 jint inOffset, jint inLength) {
3995 CHECK_ERROR_QUEUE_ON_RETURN;
3996 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
3997 JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
3998
3999 if (hmacCtx == nullptr) {
4000 return;
4001 }
4002
4003 ScopedByteArrayRO inBytes(env, inArray);
4004 if (inBytes.get() == nullptr) {
4005 return;
4006 }
4007
4008 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4009 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4010 "inBytes");
4011 return;
4012 }
4013
4014 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4015 if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4016 JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4017 inLength);
4018 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4019 return;
4020 }
4021 }
4022
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4023 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4024 CHECK_ERROR_QUEUE_ON_RETURN;
4025 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4026 JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4027
4028 if (hmacCtx == nullptr) {
4029 return nullptr;
4030 }
4031
4032 uint8_t result[EVP_MAX_MD_SIZE];
4033 unsigned len;
4034 if (!HMAC_Final(hmacCtx, result, &len)) {
4035 JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4036 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4037 return nullptr;
4038 }
4039
4040 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4041 if (resultArray.get() == nullptr) {
4042 return nullptr;
4043 }
4044 ScopedByteArrayRW resultBytes(env, resultArray.get());
4045 if (resultBytes.get() == nullptr) {
4046 return nullptr;
4047 }
4048 memcpy(resultBytes.get(), result, len);
4049 return resultArray.release();
4050 }
4051
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4052 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4053 CHECK_ERROR_QUEUE_ON_RETURN;
4054 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4055
4056 ScopedByteArrayRW outputBytes(env, output);
4057 if (outputBytes.get() == nullptr) {
4058 return;
4059 }
4060
4061 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4062 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4063 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4064 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4065 return;
4066 }
4067
4068 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4069 }
4070
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4071 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4072 /*
4073 * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4074 * Just make a buffer that's large enough here. The documentation recommends
4075 * 80 characters.
4076 */
4077 char output[128];
4078 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4079 if (ret < 0) {
4080 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4081 return nullptr;
4082 } else if (size_t(ret) >= sizeof(output)) {
4083 conscrypt::jniutil::throwRuntimeException(env,
4084 "ASN1_OBJECT_to_OID_string buffer too small");
4085 return nullptr;
4086 }
4087
4088 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4089 return env->NewStringUTF(output);
4090 }
4091
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4092 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4093 jboolean isFinite) {
4094 CHECK_ERROR_QUEUE_ON_RETURN;
4095 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4096
4097 if (streamObj == nullptr) {
4098 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4099 return 0;
4100 }
4101
4102 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4103 if (bio.get() == nullptr) {
4104 return 0;
4105 }
4106
4107 bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4108
4109 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4110 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4111 }
4112
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4113 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4114 CHECK_ERROR_QUEUE_ON_RETURN;
4115 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4116
4117 if (streamObj == nullptr) {
4118 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4119 return 0;
4120 }
4121
4122 bssl::UniquePtr<BIO> bio(BIO_new(&stream_bio_method));
4123 if (bio.get() == nullptr) {
4124 return 0;
4125 }
4126
4127 bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4128
4129 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4130 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4131 }
4132
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4133 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4134 CHECK_ERROR_QUEUE_ON_RETURN;
4135 BIO* bio = to_BIO(env, bioRef);
4136 JNI_TRACE("BIO_free_all(%p)", bio);
4137
4138 if (bio == nullptr) {
4139 return;
4140 }
4141
4142 BIO_free_all(bio);
4143 }
4144
4145 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4146 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4147 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4148
4149 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4150 if (buffer.get() == nullptr) {
4151 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4152 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4153 return nullptr;
4154 }
4155
4156 /* Don't interpret the string. */
4157 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4158
4159 /* Write in given format and null terminate. */
4160 X509_NAME_print_ex(buffer.get(), name, 0, flags);
4161 BIO_write(buffer.get(), "\0", 1);
4162
4163 char* tmp;
4164 BIO_get_mem_data(buffer.get(), &tmp);
4165 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4166 return env->NewStringUTF(tmp);
4167 }
4168
4169 /**
4170 * Converts GENERAL_NAME items to the output format expected in
4171 * X509Certificate#getSubjectAlternativeNames and
4172 * X509Certificate#getIssuerAlternativeNames return.
4173 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4174 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4175 switch (gen->type) {
4176 case GEN_EMAIL:
4177 case GEN_DNS:
4178 case GEN_URI: {
4179 // This must not be a T61String and must not contain NULs.
4180 const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
4181 ssize_t len = ASN1_STRING_length(gen->d.ia5);
4182 if ((len == static_cast<ssize_t>(strlen(data))) &&
4183 (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
4184 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
4185 return env->NewStringUTF(data);
4186 } else {
4187 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4188 return nullptr;
4189 }
4190 }
4191 case GEN_DIRNAME:
4192 /* Write in RFC 2253 format */
4193 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4194 case GEN_IPADD: {
4195 #ifdef _WIN32
4196 void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4197 #else
4198 const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4199 #endif
4200 if (gen->d.ip->length == 4) {
4201 // IPv4
4202 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4203 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4204 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4205 return env->NewStringUTF(buffer.get());
4206 } else {
4207 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4208 strerror(errno));
4209 }
4210 } else if (gen->d.ip->length == 16) {
4211 // IPv6
4212 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4213 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4214 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4215 return env->NewStringUTF(buffer.get());
4216 } else {
4217 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4218 strerror(errno));
4219 }
4220 }
4221
4222 /* Invalid IP encodings are pruned out without throwing an exception. */
4223 return nullptr;
4224 }
4225 case GEN_RID:
4226 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4227 case GEN_OTHERNAME:
4228 case GEN_X400:
4229 default:
4230 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4231 }
4232
4233 return nullptr;
4234 }
4235
4236 #define GN_STACK_SUBJECT_ALT_NAME 1
4237 #define GN_STACK_ISSUER_ALT_NAME 2
4238
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4239 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4240 CONSCRYPT_UNUSED jobject holder,
4241 jint type) {
4242 CHECK_ERROR_QUEUE_ON_RETURN;
4243 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4244 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4245
4246 if (x509 == nullptr) {
4247 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4248 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4249 return nullptr;
4250 }
4251
4252 bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4253 if (type == GN_STACK_SUBJECT_ALT_NAME) {
4254 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4255 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4256 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4257 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4258 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4259 } else {
4260 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4261 return nullptr;
4262 }
4263 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4264 // |ERR_clear_error|, and throw CertificateParsingException.
4265 if (gn_stack == nullptr) {
4266 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4267 ERR_clear_error();
4268 return nullptr;
4269 }
4270
4271 int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4272 if (count <= 0) {
4273 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4274 return nullptr;
4275 }
4276
4277 /*
4278 * Keep track of how many originally so we can ignore any invalid
4279 * values later.
4280 */
4281 const int origCount = count;
4282
4283 ScopedLocalRef<jobjectArray> joa(
4284 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4285 for (int i = 0, j = 0; i < origCount; i++, j++) {
4286 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4287 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4288 if (env->ExceptionCheck()) {
4289 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4290 x509, type);
4291 return nullptr;
4292 }
4293
4294 /*
4295 * If it's nullptr, we'll have to skip this, reduce the number of total
4296 * entries, and fix up the array later.
4297 */
4298 if (val.get() == nullptr) {
4299 j--;
4300 count--;
4301 continue;
4302 }
4303
4304 ScopedLocalRef<jobjectArray> item(
4305 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4306
4307 ScopedLocalRef<jobject> parsedType(
4308 env,
4309 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4310 conscrypt::jniutil::integer_valueOfMethod, gen->type));
4311 env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4312 env->SetObjectArrayElement(item.get(), 1, val.get());
4313
4314 env->SetObjectArrayElement(joa.get(), j, item.get());
4315 }
4316
4317 if (count == 0) {
4318 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4319 x509, type, origCount);
4320 joa.reset(nullptr);
4321 } else if (origCount != count) {
4322 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4323 count);
4324
4325 ScopedLocalRef<jobjectArray> joa_copy(
4326 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4327
4328 for (int i = 0; i < count; i++) {
4329 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4330 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4331 }
4332
4333 joa.reset(joa_copy.release());
4334 }
4335
4336 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4337 return joa.release();
4338 }
4339
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4340 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4341 CONSCRYPT_UNUSED jobject holder) {
4342 CHECK_ERROR_QUEUE_ON_RETURN;
4343 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4344 JNI_TRACE("X509_get_notBefore(%p)", x509);
4345
4346 if (x509 == nullptr) {
4347 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4348 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4349 return 0;
4350 }
4351
4352 ASN1_TIME* notBefore = X509_get_notBefore(x509);
4353 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4354 return reinterpret_cast<uintptr_t>(notBefore);
4355 }
4356
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4357 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4358 CONSCRYPT_UNUSED jobject holder) {
4359 CHECK_ERROR_QUEUE_ON_RETURN;
4360 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4361 JNI_TRACE("X509_get_notAfter(%p)", x509);
4362
4363 if (x509 == nullptr) {
4364 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4365 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4366 return 0;
4367 }
4368
4369 ASN1_TIME* notAfter = X509_get_notAfter(x509);
4370 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4371 return reinterpret_cast<uintptr_t>(notAfter);
4372 }
4373
4374 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4375 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4376 CONSCRYPT_UNUSED jobject holder) {
4377 CHECK_ERROR_QUEUE_ON_RETURN;
4378 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4379 JNI_TRACE("X509_get_version(%p)", x509);
4380
4381 // NOLINTNEXTLINE(runtime/int)
4382 long version = X509_get_version(x509);
4383 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4384 return version;
4385 }
4386
4387 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4388 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4389 const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4390 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4391
4392 if (x509Type == nullptr) {
4393 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4394 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4395 return nullptr;
4396 }
4397
4398 const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4399 bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4400 if (serialBn.get() == nullptr) {
4401 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4402 return nullptr;
4403 }
4404
4405 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4406 if (env->ExceptionCheck()) {
4407 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4408 return nullptr;
4409 }
4410
4411 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4412 return serialArray.release();
4413 }
4414
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4415 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4416 CONSCRYPT_UNUSED jobject holder) {
4417 CHECK_ERROR_QUEUE_ON_RETURN;
4418 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4419 JNI_TRACE("X509_get_serialNumber(%p)", x509);
4420 return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4421 }
4422
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4423 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
4424 jlong x509RevokedRef) {
4425 CHECK_ERROR_QUEUE_ON_RETURN;
4426 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4427 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
4428 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
4429 }
4430
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4431 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
4432 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4433 CHECK_ERROR_QUEUE_ON_RETURN;
4434 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4435 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4436 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
4437
4438 if (pkey == nullptr) {
4439 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
4440 return;
4441 }
4442
4443 if (x509 == nullptr) {
4444 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4445 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
4446 return;
4447 }
4448
4449 if (X509_verify(x509, pkey) != 1) {
4450 conscrypt::jniutil::throwExceptionFromBoringSSLError(
4451 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
4452 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
4453 return;
4454 }
4455 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
4456 }
4457
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4458 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
4459 CONSCRYPT_UNUSED jobject holder) {
4460 CHECK_ERROR_QUEUE_ON_RETURN;
4461 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4462 JNI_TRACE("get_X509_tbs_cert(%p)", x509);
4463 // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
4464 return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
4465 }
4466
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)4467 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
4468 CONSCRYPT_UNUSED jobject holder,
4469 jstring oidString) {
4470 CHECK_ERROR_QUEUE_ON_RETURN;
4471 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4472 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
4473
4474 if (x509 == nullptr) {
4475 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4476 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
4477 return nullptr;
4478 }
4479
4480 bssl::UniquePtr<X509> copy(X509_dup(x509));
4481 if (copy == nullptr) {
4482 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
4483 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
4484 return nullptr;
4485 }
4486
4487 ScopedUtfChars oid(env, oidString);
4488 if (oid.c_str() == nullptr) {
4489 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
4490 return nullptr;
4491 }
4492
4493 bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
4494 if (obj.get() == nullptr) {
4495 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
4496 oid.c_str());
4497 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4498 "Invalid OID.");
4499 ERR_clear_error();
4500 return nullptr;
4501 }
4502
4503 int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
4504 if (extIndex == -1) {
4505 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
4506 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4507 "Extension not found.");
4508 return nullptr;
4509 }
4510
4511 // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
4512 // cached encoding.
4513 X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
4514 return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
4515 }
4516
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4517 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
4518 CONSCRYPT_UNUSED jobject holder) {
4519 CHECK_ERROR_QUEUE_ON_RETURN;
4520 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4521 JNI_TRACE("get_X509_ex_flags(%p)", x509);
4522
4523 if (x509 == nullptr) {
4524 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4525 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
4526 return 0;
4527 }
4528
4529 uint32_t flags = X509_get_extension_flags(x509);
4530 // X509_get_extension_flags sometimes leaves values in the error queue. See
4531 // https://crbug.com/boringssl/382.
4532 //
4533 // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
4534 // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
4535 // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
4536 // this JNI call to EXFLAG_CRITICAL.
4537 ERR_clear_error();
4538 return flags;
4539 }
4540
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)4541 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
4542 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
4543 CONSCRYPT_UNUSED jobject holder2) {
4544 CHECK_ERROR_QUEUE_ON_RETURN;
4545 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
4546 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
4547 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
4548
4549 int ret = X509_check_issued(x509_1, x509_2);
4550 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
4551 return ret;
4552 }
4553
get_X509_signature(X509 * x509)4554 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
4555 const ASN1_BIT_STRING* signature;
4556 X509_get0_signature(&signature, nullptr, x509);
4557 return signature;
4558 }
4559
get_X509_CRL_signature(X509_CRL * crl)4560 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
4561 const ASN1_BIT_STRING* signature;
4562 X509_CRL_get0_signature(crl, &signature, nullptr);
4563 return signature;
4564 }
4565
4566 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))4567 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
4568 const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
4569 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
4570
4571 if (x509Type == nullptr) {
4572 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4573 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
4574 return nullptr;
4575 }
4576
4577 const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
4578
4579 ScopedLocalRef<jbyteArray> signatureArray(env,
4580 env->NewByteArray(ASN1_STRING_length(signature)));
4581 if (env->ExceptionCheck()) {
4582 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
4583 return nullptr;
4584 }
4585
4586 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
4587 if (signatureBytes.get() == nullptr) {
4588 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
4589 return nullptr;
4590 }
4591
4592 memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
4593
4594 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
4595 ASN1_STRING_length(signature));
4596 return signatureArray.release();
4597 }
4598
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4599 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
4600 CONSCRYPT_UNUSED jobject holder) {
4601 CHECK_ERROR_QUEUE_ON_RETURN;
4602 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4603 JNI_TRACE("get_X509_signature(%p)", x509);
4604 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
4605 }
4606
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4607 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
4608 CONSCRYPT_UNUSED jobject holder) {
4609 CHECK_ERROR_QUEUE_ON_RETURN;
4610 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4611 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
4612 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
4613 }
4614
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)4615 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
4616 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
4617 CONSCRYPT_UNUSED jobject holder2) {
4618 CHECK_ERROR_QUEUE_ON_RETURN;
4619 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4620 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4621 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
4622
4623 if (x509crl == nullptr) {
4624 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4625 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
4626 return 0;
4627 } else if (x509 == nullptr) {
4628 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4629 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
4630 return 0;
4631 }
4632
4633 X509_REVOKED* revoked = nullptr;
4634 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
4635 if (ret == 0) {
4636 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
4637 return 0;
4638 }
4639
4640 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
4641 return reinterpret_cast<uintptr_t>(revoked);
4642 }
4643
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)4644 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
4645 CONSCRYPT_UNUSED jobject holder,
4646 jbyteArray serialArray) {
4647 CHECK_ERROR_QUEUE_ON_RETURN;
4648 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
4649 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
4650
4651 if (x509crl == nullptr) {
4652 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
4653 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
4654 return 0;
4655 }
4656
4657 bssl::UniquePtr<BIGNUM> serialBn(BN_new());
4658 if (serialBn.get() == nullptr) {
4659 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
4660 return 0;
4661 }
4662
4663 BIGNUM* serialBare = serialBn.get();
4664 if (!arrayToBignum(env, serialArray, &serialBare)) {
4665 if (!env->ExceptionCheck()) {
4666 conscrypt::jniutil::throwNullPointerException(env, "serial == null");
4667 }
4668 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4669 return 0;
4670 }
4671
4672 bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
4673 if (serialInteger.get() == nullptr) {
4674 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
4675 return 0;
4676 }
4677
4678 X509_REVOKED* revoked = nullptr;
4679 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
4680 if (ret == 0) {
4681 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
4682 return 0;
4683 }
4684
4685 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
4686 return reinterpret_cast<uintptr_t>(revoked);
4687 }
4688
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4689 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
4690 CONSCRYPT_UNUSED jobject holder) {
4691 CHECK_ERROR_QUEUE_ON_RETURN;
4692 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4693 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
4694
4695 if (crl == nullptr) {
4696 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4697 return nullptr;
4698 }
4699
4700 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
4701 if (stack == nullptr) {
4702 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
4703 return nullptr;
4704 }
4705
4706 size_t size = sk_X509_REVOKED_num(stack);
4707
4708 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
4709 ScopedLongArrayRW revoked(env, revokedArray.get());
4710 for (size_t i = 0; i < size; i++) {
4711 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
4712 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
4713 }
4714
4715 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
4716 return revokedArray.release();
4717 }
4718
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4719 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
4720 CONSCRYPT_UNUSED jobject holder) {
4721 CHECK_ERROR_QUEUE_ON_RETURN;
4722 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4723 JNI_TRACE("i2d_X509_CRL(%p)", crl);
4724 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
4725 }
4726
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4727 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
4728 CONSCRYPT_UNUSED jobject holder) {
4729 CHECK_ERROR_QUEUE_ON_RETURN;
4730 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4731 JNI_TRACE("X509_CRL_free(%p)", crl);
4732
4733 if (crl == nullptr) {
4734 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4735 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
4736 return;
4737 }
4738
4739 X509_CRL_free(crl);
4740 }
4741
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4742 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
4743 CONSCRYPT_UNUSED jobject holder) {
4744 CHECK_ERROR_QUEUE_ON_RETURN;
4745 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4746 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4747 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
4748
4749 if (bio == nullptr) {
4750 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4751 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
4752 return;
4753 }
4754
4755 if (crl == nullptr) {
4756 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4757 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
4758 return;
4759 }
4760
4761 if (!X509_CRL_print(bio, crl)) {
4762 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
4763 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
4764 return;
4765 }
4766 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
4767 }
4768
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4769 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
4770 CONSCRYPT_UNUSED jobject holder) {
4771 CHECK_ERROR_QUEUE_ON_RETURN;
4772 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4773 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
4774
4775 if (crl == nullptr) {
4776 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4777 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
4778 return nullptr;
4779 }
4780
4781 const X509_ALGOR *sig_alg;
4782 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4783 const ASN1_OBJECT *oid;
4784 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
4785 return ASN1_OBJECT_to_OID_string(env, oid);
4786 }
4787
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)4788 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR *algor) {
4789 int param_type;
4790 const void* param_value;
4791 X509_ALGOR_get0(nullptr, ¶m_type, ¶m_value, algor);
4792
4793 if (param_type == V_ASN1_UNDEF) {
4794 JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
4795 return nullptr;
4796 }
4797
4798 // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
4799 // recreate it from the returned components.
4800 bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
4801 if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
4802 conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
4803 return nullptr;
4804 }
4805
4806 return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
4807 }
4808
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4809 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
4810 CONSCRYPT_UNUSED jobject holder) {
4811 CHECK_ERROR_QUEUE_ON_RETURN;
4812 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4813 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
4814
4815 if (crl == nullptr) {
4816 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
4817 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
4818 return nullptr;
4819 }
4820
4821 const X509_ALGOR *sig_alg;
4822 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
4823 return get_X509_ALGOR_parameter(env, sig_alg);
4824 }
4825
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4826 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
4827 CONSCRYPT_UNUSED jobject holder) {
4828 CHECK_ERROR_QUEUE_ON_RETURN;
4829 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4830 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
4831 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
4832 }
4833
4834 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4835 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
4836 CONSCRYPT_UNUSED jobject holder) {
4837 CHECK_ERROR_QUEUE_ON_RETURN;
4838 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4839 JNI_TRACE("X509_CRL_get_version(%p)", crl);
4840
4841 // NOLINTNEXTLINE(runtime/int)
4842 long version = X509_CRL_get_version(crl);
4843 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
4844 return version;
4845 }
4846
4847 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4848 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)4849 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
4850 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
4851
4852 if (x509Type == nullptr) {
4853 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4854 return nullptr;
4855 }
4856
4857 ScopedUtfChars oid(env, oidString);
4858 if (oid.c_str() == nullptr) {
4859 return nullptr;
4860 }
4861
4862 bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
4863 if (asn1.get() == nullptr) {
4864 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
4865 ERR_clear_error();
4866 return nullptr;
4867 }
4868
4869 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
4870 if (extIndex == -1) {
4871 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
4872 return nullptr;
4873 }
4874
4875 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
4876 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
4877 return ext;
4878 }
4879
4880 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
4881 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)4882 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
4883 X509_EXTENSION* ext =
4884 X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
4885 if (ext == nullptr) {
4886 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
4887 return nullptr;
4888 }
4889
4890 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
4891 X509_EXTENSION_get_data(ext));
4892 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
4893 i2d_ASN1_OCTET_STRING);
4894 }
4895
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)4896 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
4897 CONSCRYPT_UNUSED jobject holder, jstring oid) {
4898 CHECK_ERROR_QUEUE_ON_RETURN;
4899 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4900 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
4901 X509_EXTENSION* ext =
4902 X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
4903 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
4904 return reinterpret_cast<uintptr_t>(ext);
4905 }
4906
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)4907 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
4908 jstring oid) {
4909 CHECK_ERROR_QUEUE_ON_RETURN;
4910 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4911 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
4912 X509_EXTENSION* ext =
4913 X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
4914 env, revoked, oid);
4915 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
4916 return reinterpret_cast<uintptr_t>(ext);
4917 }
4918
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)4919 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
4920 CHECK_ERROR_QUEUE_ON_RETURN;
4921 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4922 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
4923
4924 if (revoked == nullptr) {
4925 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4926 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
4927 return 0;
4928 }
4929
4930 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
4931 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
4932 return reinterpret_cast<uintptr_t>(dup);
4933 }
4934
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)4935 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
4936 jlong x509RevokedRef) {
4937 CHECK_ERROR_QUEUE_ON_RETURN;
4938 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4939 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
4940
4941 if (revoked == nullptr) {
4942 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4943 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
4944 return 0;
4945 }
4946
4947 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
4948 X509_REVOKED_get0_revocationDate(revoked));
4949 return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
4950 }
4951
4952 #ifdef __GNUC__
4953 #pragma GCC diagnostic push
4954 #pragma GCC diagnostic ignored "-Wwrite-strings"
4955 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)4956 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
4957 jlong x509RevokedRef) {
4958 CHECK_ERROR_QUEUE_ON_RETURN;
4959 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4960 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
4961 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
4962
4963 if (bio == nullptr) {
4964 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
4965 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
4966 return;
4967 }
4968
4969 if (revoked == nullptr) {
4970 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
4971 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
4972 return;
4973 }
4974
4975 BIO_printf(bio, "Serial Number: ");
4976 i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
4977 BIO_printf(bio, "\nRevocation Date: ");
4978 ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
4979 BIO_printf(bio, "\n");
4980 // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
4981 // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
4982 X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
4983 0);
4984 }
4985 #ifndef _WIN32
4986 #pragma GCC diagnostic pop
4987 #endif
4988
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)4989 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
4990 CONSCRYPT_UNUSED jobject holder) {
4991 CHECK_ERROR_QUEUE_ON_RETURN;
4992 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
4993 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
4994 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
4995 }
4996
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)4997 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
4998 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
4999 CHECK_ERROR_QUEUE_ON_RETURN;
5000 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5001 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5002 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5003
5004 if (pkey == nullptr) {
5005 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5006 return;
5007 }
5008
5009 if (crl == nullptr) {
5010 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5011 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5012 return;
5013 }
5014
5015 if (X509_CRL_verify(crl, pkey) != 1) {
5016 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5017 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5018 return;
5019 }
5020 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5021 }
5022
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5023 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5024 CONSCRYPT_UNUSED jobject holder) {
5025 CHECK_ERROR_QUEUE_ON_RETURN;
5026 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5027 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5028
5029 if (crl == nullptr) {
5030 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5031 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5032 return 0;
5033 }
5034
5035 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5036 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5037 return reinterpret_cast<uintptr_t>(lastUpdate);
5038 }
5039
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5040 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5041 CONSCRYPT_UNUSED jobject holder) {
5042 CHECK_ERROR_QUEUE_ON_RETURN;
5043 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5044 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5045
5046 if (crl == nullptr) {
5047 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5048 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5049 return 0;
5050 }
5051
5052 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5053 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5054 return reinterpret_cast<uintptr_t>(nextUpdate);
5055 }
5056
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5057 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5058 CHECK_ERROR_QUEUE_ON_RETURN;
5059 X509_REVOKED* x509Revoked =
5060 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5061 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5062 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5063 }
5064
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5065 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5066 CHECK_ERROR_QUEUE_ON_RETURN;
5067 X509_EXTENSION* ext =
5068 reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5069
5070 if (ext == nullptr) {
5071 conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5072 return 0;
5073 }
5074
5075 return X509_supported_extension(ext);
5076 }
5077
decimal_to_integer(const char * data,size_t len,int * out)5078 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5079 int ret = 0;
5080 for (size_t i = 0; i < len; i++) {
5081 ret *= 10;
5082 if (data[i] < '0' || data[i] > '9') {
5083 return false;
5084 }
5085 ret += data[i] - '0';
5086 }
5087 *out = ret;
5088 return true;
5089 }
5090
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5091 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5092 jobject calendar) {
5093 CHECK_ERROR_QUEUE_ON_RETURN;
5094 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5095 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5096
5097 if (asn1Time == nullptr) {
5098 conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5099 return;
5100 }
5101
5102 if (!ASN1_TIME_check(asn1Time)) {
5103 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5104 return;
5105 }
5106
5107 bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5108 if (gen.get() == nullptr) {
5109 conscrypt::jniutil::throwParsingException(env,
5110 "ASN1_TIME_to_generalizedtime returned null");
5111 return;
5112 }
5113
5114 if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5115 conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5116 return;
5117 }
5118
5119 int year, mon, mday, hour, min, sec;
5120 const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5121 if (!decimal_to_integer(data, 4, &year) ||
5122 !decimal_to_integer(data + 4, 2, &mon) ||
5123 !decimal_to_integer(data + 6, 2, &mday) ||
5124 !decimal_to_integer(data + 8, 2, &hour) ||
5125 !decimal_to_integer(data + 10, 2, &min) ||
5126 !decimal_to_integer(data + 12, 2, &sec)) {
5127 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5128 return;
5129 }
5130
5131 env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5132 min, sec);
5133 }
5134
5135 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5136 // functions so that they can be freed properly when finished. This struct owns
5137 // all objects pointed to by its members.
5138 struct CbsHandle {
5139 // A pointer to the CBS.
5140 std::unique_ptr<CBS> cbs;
5141 // A pointer to the data held by the CBS. If the data held by the CBS
5142 // is owned by a different CbsHandle, data will be null.
5143 std::unique_ptr<unsigned char[]> data;
5144 };
5145
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5146 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5147 CHECK_ERROR_QUEUE_ON_RETURN;
5148 JNI_TRACE("asn1_read_init(%p)", data);
5149
5150 ScopedByteArrayRO bytes(env, data);
5151 if (bytes.get() == nullptr) {
5152 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5153 return 0;
5154 }
5155
5156 std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5157 cbs->data.reset(new unsigned char[bytes.size()]);
5158 memcpy(cbs->data.get(), bytes.get(), bytes.size());
5159
5160 cbs->cbs.reset(new CBS());
5161 CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5162 JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5163 return reinterpret_cast<uintptr_t>(cbs.release());
5164 }
5165
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5166 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5167 CHECK_ERROR_QUEUE_ON_RETURN;
5168 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5169 JNI_TRACE("asn1_read_sequence(%p)", cbs);
5170
5171 std::unique_ptr<CbsHandle> seq(new CbsHandle());
5172 seq->cbs.reset(new CBS());
5173 if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5174 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5175 return 0;
5176 }
5177 JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5178 return reinterpret_cast<uintptr_t>(seq.release());
5179 }
5180
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5181 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5182 jlong cbsRef, jint tag) {
5183 CHECK_ERROR_QUEUE_ON_RETURN;
5184 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5185 JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5186
5187 int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5188 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5189 JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5190 return result ? JNI_TRUE : JNI_FALSE;
5191 }
5192
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5193 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5194 CHECK_ERROR_QUEUE_ON_RETURN;
5195 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5196 JNI_TRACE("asn1_read_tagged(%p)", cbs);
5197
5198 std::unique_ptr<CbsHandle> tag(new CbsHandle());
5199 tag->cbs.reset(new CBS());
5200 if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5201 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5202 return 0;
5203 }
5204 JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5205 return reinterpret_cast<uintptr_t>(tag.release());
5206 }
5207
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5208 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5209 CHECK_ERROR_QUEUE_ON_RETURN;
5210 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5211 JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5212
5213 std::unique_ptr<CBS> str(new CBS());
5214 if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5215 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5216 return 0;
5217 }
5218 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5219 if (out.get() == nullptr) {
5220 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5221 return 0;
5222 }
5223 ScopedByteArrayRW outBytes(env, out.get());
5224 if (outBytes.get() == nullptr) {
5225 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5226 return 0;
5227 }
5228 memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5229 JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5230 return out.release();
5231 }
5232
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5233 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5234 CHECK_ERROR_QUEUE_ON_RETURN;
5235 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5236 JNI_TRACE("asn1_read_uint64(%p)", cbs);
5237
5238 // NOLINTNEXTLINE(runtime/int)
5239 uint64_t value;
5240 if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5241 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5242 return 0;
5243 }
5244 return value;
5245 }
5246
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5247 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5248 CHECK_ERROR_QUEUE_ON_RETURN;
5249 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5250 JNI_TRACE("asn1_read_null(%p)", cbs);
5251
5252 CBS null_holder;
5253 if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5254 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5255 }
5256 }
5257
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5258 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5259 CHECK_ERROR_QUEUE_ON_RETURN;
5260 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5261 JNI_TRACE("asn1_read_oid(%p)", cbs);
5262
5263 CBS oid_cbs;
5264 if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5265 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5266 return nullptr;
5267 }
5268 int nid = OBJ_cbs2nid(&oid_cbs);
5269 if (nid == NID_undef) {
5270 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5271 return nullptr;
5272 }
5273 const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5274 if (obj == nullptr) {
5275 conscrypt::jniutil::throwIOException(env,
5276 "Error reading ASN.1 encoding: "
5277 "Could not find ASN1_OBJECT for NID");
5278 return nullptr;
5279 }
5280 return ASN1_OBJECT_to_OID_string(env, obj);
5281 }
5282
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5283 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5284 jlong cbsRef) {
5285 CHECK_ERROR_QUEUE_ON_RETURN;
5286 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5287 JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5288
5289 bool empty = (CBS_len(cbs->cbs.get()) == 0);
5290 JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5291 return empty;
5292 }
5293
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5294 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5295 CHECK_ERROR_QUEUE_ON_RETURN;
5296 if (cbsRef == 0) {
5297 JNI_TRACE("asn1_read_free(0)");
5298 return;
5299 }
5300 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5301 JNI_TRACE("asn1_read_free(%p)", cbs);
5302 delete cbs;
5303 }
5304
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5305 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5306 CHECK_ERROR_QUEUE_ON_RETURN;
5307 JNI_TRACE("asn1_write_init");
5308 std::unique_ptr<CBB> cbb(new CBB());
5309 if (!CBB_init(cbb.get(), 128)) {
5310 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5311 return 0;
5312 }
5313 JNI_TRACE("asn1_write_init => %p", cbb.get());
5314 return reinterpret_cast<uintptr_t>(cbb.release());
5315 }
5316
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5317 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5318 CHECK_ERROR_QUEUE_ON_RETURN;
5319 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5320 JNI_TRACE("asn1_write_sequence(%p)", cbb);
5321
5322 std::unique_ptr<CBB> seq(new CBB());
5323 if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5324 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5325 return 0;
5326 }
5327 JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5328 return reinterpret_cast<uintptr_t>(seq.release());
5329 }
5330
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5331 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5332 CHECK_ERROR_QUEUE_ON_RETURN;
5333 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5334 JNI_TRACE("asn1_write_tag(%p)", cbb);
5335
5336 std::unique_ptr<CBB> tag_holder(new CBB());
5337 if (!CBB_add_asn1(cbb, tag_holder.get(),
5338 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5339 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5340 return 0;
5341 }
5342 JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5343 return reinterpret_cast<uintptr_t>(tag_holder.release());
5344 }
5345
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5346 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5347 jbyteArray data) {
5348 CHECK_ERROR_QUEUE_ON_RETURN;
5349 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5350 JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5351
5352 ScopedByteArrayRO bytes(env, data);
5353 if (bytes.get() == nullptr) {
5354 JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5355 return;
5356 }
5357
5358 std::unique_ptr<CBB> octetstring(new CBB());
5359 if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5360 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5361 return;
5362 }
5363 if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5364 bytes.size())) {
5365 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5366 return;
5367 }
5368 if (!CBB_flush(cbb)) {
5369 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5370 return;
5371 }
5372 }
5373
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)5374 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
5375 CHECK_ERROR_QUEUE_ON_RETURN;
5376 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5377 JNI_TRACE("asn1_write_uint64(%p)", cbb);
5378
5379 if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
5380 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5381 return;
5382 }
5383 }
5384
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)5385 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
5386 CHECK_ERROR_QUEUE_ON_RETURN;
5387 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5388 JNI_TRACE("asn1_write_null(%p)", cbb);
5389
5390 CBB null_holder;
5391 if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
5392 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5393 return;
5394 }
5395 if (!CBB_flush(cbb)) {
5396 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5397 return;
5398 }
5399 }
5400
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)5401 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
5402 CHECK_ERROR_QUEUE_ON_RETURN;
5403 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5404 JNI_TRACE("asn1_write_oid(%p)", cbb);
5405
5406 ScopedUtfChars oid_chars(env, oid);
5407 if (oid_chars.c_str() == nullptr) {
5408 return;
5409 }
5410
5411 int nid = OBJ_txt2nid(oid_chars.c_str());
5412 if (nid == NID_undef) {
5413 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5414 return;
5415 }
5416
5417 if (!OBJ_nid2cbb(cbb, nid)) {
5418 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5419 return;
5420 }
5421 }
5422
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)5423 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
5424 CHECK_ERROR_QUEUE_ON_RETURN;
5425 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5426 JNI_TRACE("asn1_write_flush(%p)", cbb);
5427
5428 if (!CBB_flush(cbb)) {
5429 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5430 return;
5431 }
5432 }
5433
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)5434 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
5435 CHECK_ERROR_QUEUE_ON_RETURN;
5436 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5437 JNI_TRACE("asn1_write_finish(%p)", cbb);
5438
5439 uint8_t* data;
5440 size_t data_len;
5441 if (!CBB_finish(cbb, &data, &data_len)) {
5442 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5443 return 0;
5444 }
5445 bssl::UniquePtr<uint8_t> data_storage(data);
5446 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
5447 if (out.get() == nullptr) {
5448 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5449 return 0;
5450 }
5451 ScopedByteArrayRW outBytes(env, out.get());
5452 if (outBytes.get() == nullptr) {
5453 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5454 return 0;
5455 }
5456 memcpy(outBytes.get(), data, data_len);
5457 return out.release();
5458 }
5459
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5460 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5461 CHECK_ERROR_QUEUE_ON_RETURN;
5462 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5463 JNI_TRACE("asn1_write_cleanup(%p)", cbb);
5464
5465 CBB_cleanup(cbb);
5466 }
5467
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)5468 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
5469 CHECK_ERROR_QUEUE_ON_RETURN;
5470 if (cbbRef == 0) {
5471 JNI_TRACE("asn1_write_free(0)");
5472 return;
5473 }
5474 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5475 JNI_TRACE("asn1_write_free(%p)", cbb);
5476 delete cbb;
5477 }
5478
5479 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5480 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5481 BIO* bio = to_BIO(env, bioRef);
5482 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5483
5484 if (bio == nullptr) {
5485 return 0;
5486 }
5487
5488 T* x = d2i_func(bio, nullptr);
5489 if (x == nullptr) {
5490 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
5491 return 0;
5492 }
5493
5494 return reinterpret_cast<uintptr_t>(x);
5495 }
5496
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5497 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5498 CHECK_ERROR_QUEUE_ON_RETURN;
5499 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5500 }
5501
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5502 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5503 CHECK_ERROR_QUEUE_ON_RETURN;
5504 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5505 }
5506
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5507 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5508 CHECK_ERROR_QUEUE_ON_RETURN;
5509 ScopedByteArrayRO bytes(env, certBytes);
5510 if (bytes.get() == nullptr) {
5511 JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
5512 return 0;
5513 }
5514
5515 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
5516 // NOLINTNEXTLINE(runtime/int)
5517 X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
5518 if (x == nullptr) {
5519 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5520 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
5521 return 0;
5522 }
5523 return reinterpret_cast<uintptr_t>(x);
5524 }
5525
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5526 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
5527 CONSCRYPT_UNUSED jobject holder) {
5528 CHECK_ERROR_QUEUE_ON_RETURN;
5529 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5530 JNI_TRACE("i2d_X509(%p)", x509);
5531 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
5532 }
5533
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5534 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
5535 CONSCRYPT_UNUSED jobject holder) {
5536 CHECK_ERROR_QUEUE_ON_RETURN;
5537 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5538 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5539 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
5540 }
5541
5542 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)5543 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
5544 BIO* bio = to_BIO(env, bioRef);
5545 JNI_TRACE("PEM_to_jlong(%p)", bio);
5546
5547 if (bio == nullptr) {
5548 JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
5549 return 0;
5550 }
5551
5552 T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
5553 if (x == nullptr) {
5554 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
5555 JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
5556 return 0;
5557 }
5558
5559 JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
5560 return reinterpret_cast<uintptr_t>(x);
5561 }
5562
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5563 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5564 CHECK_ERROR_QUEUE_ON_RETURN;
5565 // NOLINTNEXTLINE(runtime/int)
5566 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
5567 return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5568 }
5569
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5570 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5571 CHECK_ERROR_QUEUE_ON_RETURN;
5572 // NOLINTNEXTLINE(runtime/int)
5573 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
5574 return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5575 }
5576
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)5577 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
5578 CHECK_ERROR_QUEUE_ON_RETURN;
5579 // NOLINTNEXTLINE(runtime/int)
5580 JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
5581 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
5582 }
5583
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)5584 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
5585 CHECK_ERROR_QUEUE_ON_RETURN;
5586 // NOLINTNEXTLINE(runtime/int)
5587 JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
5588 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
5589 }
5590
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)5591 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509) *certs) {
5592 if (certs == nullptr) {
5593 return nullptr;
5594 }
5595
5596 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5597 size_t size = sk_X509_num(certs);
5598 ref_array.reset(env->NewLongArray(size));
5599 ScopedLongArrayRW items(env, ref_array.get());
5600 for (size_t i = 0; i < size; i++) {
5601 X509* cert = sk_X509_value(certs, i);
5602 X509_up_ref(cert);
5603 items[i] = reinterpret_cast<uintptr_t>(cert);
5604 }
5605
5606 JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
5607 return ref_array.release();
5608 }
5609
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)5610 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL) *crls) {
5611 if (crls == nullptr) {
5612 return nullptr;
5613 }
5614
5615 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
5616 size_t size = sk_X509_CRL_num(crls);
5617 ref_array.reset(env->NewLongArray(size));
5618 ScopedLongArrayRW items(env, ref_array.get());
5619 for (size_t i = 0; i < size; i++) {
5620 X509_CRL* crl = sk_X509_CRL_value(crls, i);
5621 X509_CRL_up_ref(crl);
5622 items[i] = reinterpret_cast<uintptr_t>(crl);
5623 }
5624
5625 JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
5626 return ref_array.release();
5627 }
5628
5629 #define PKCS7_CERTS 1
5630 #define PKCS7_CRLS 2
5631
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5632 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5633 CHECK_ERROR_QUEUE_ON_RETURN;
5634 STACK_OF(X509)* stack = sk_X509_new_null();
5635
5636 ScopedLongArrayRO certs(env, certsArray);
5637 for (size_t i = 0; i < certs.size(); i++) {
5638 X509* item = reinterpret_cast<X509*>(certs[i]);
5639 if (sk_X509_push(stack, item) == 0) {
5640 sk_X509_free(stack);
5641 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
5642 return nullptr;
5643 }
5644 }
5645
5646 bssl::ScopedCBB out;
5647 CBB_init(out.get(), 1024 * certs.size());
5648 if (!PKCS7_bundle_certificates(out.get(), stack)) {
5649 sk_X509_free(stack);
5650 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
5651 return nullptr;
5652 }
5653
5654 sk_X509_free(stack);
5655
5656 return CBBToByteArray(env, out.get());
5657 }
5658
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5659 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5660 CHECK_ERROR_QUEUE_ON_RETURN;
5661 BIO* bio = to_BIO(env, bioRef);
5662 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5663
5664 if (bio == nullptr) {
5665 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5666 return nullptr;
5667 }
5668
5669 if (which == PKCS7_CERTS) {
5670 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5671 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
5672 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
5673 return nullptr;
5674 }
5675 return X509s_to_ItemArray(env, outCerts.get());
5676 } else if (which == PKCS7_CRLS) {
5677 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5678 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
5679 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
5680 return nullptr;
5681 }
5682 return X509_CRLs_to_ItemArray(env, outCRLs.get());
5683 } else {
5684 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5685 return nullptr;
5686 }
5687 }
5688
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5689 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5690 CHECK_ERROR_QUEUE_ON_RETURN;
5691 BIO* bio = to_BIO(env, bioRef);
5692 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5693
5694 if (bio == nullptr) {
5695 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5696 return nullptr;
5697 }
5698
5699 uint8_t* data;
5700 size_t len;
5701 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5702 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
5703 conscrypt::jniutil::throwParsingException);
5704 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
5705 return nullptr;
5706 }
5707 bssl::UniquePtr<uint8_t> data_storage(data);
5708
5709 CBS cbs;
5710 CBS_init(&cbs, data, len);
5711
5712 if (which == PKCS7_CERTS) {
5713 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
5714 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
5715 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
5716 "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
5717 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
5718 return nullptr;
5719 }
5720 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
5721 return X509s_to_ItemArray(env, outCerts.get());
5722 } else if (which == PKCS7_CRLS) {
5723 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
5724 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
5725 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
5726 conscrypt::jniutil::throwParsingException);
5727 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
5728 return nullptr;
5729 }
5730 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
5731 return X509_CRLs_to_ItemArray(env, outCRLs.get());
5732 } else {
5733 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
5734 return nullptr;
5735 }
5736 }
5737
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)5738 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5739 CHECK_ERROR_QUEUE_ON_RETURN;
5740 BIO* bio = to_BIO(env, bioRef);
5741 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5742
5743 if (bio == nullptr) {
5744 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
5745 return nullptr;
5746 }
5747
5748 uint8_t* data;
5749 size_t len;
5750 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
5751 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
5752 conscrypt::jniutil::throwParsingException);
5753 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
5754 return nullptr;
5755 }
5756 bssl::UniquePtr<uint8_t> data_storage(data);
5757
5758 bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
5759 if (path.get() == nullptr) {
5760 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
5761 return nullptr;
5762 }
5763
5764 CBS cbs, sequence;
5765 CBS_init(&cbs, data, len);
5766 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
5767 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5768 ERR_clear_error();
5769 return nullptr;
5770 }
5771
5772 while (CBS_len(&sequence) > 0) {
5773 CBS child;
5774 if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
5775 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5776 ERR_clear_error();
5777 return nullptr;
5778 }
5779
5780 const uint8_t* tmp = CBS_data(&child);
5781 // NOLINTNEXTLINE(runtime/int)
5782 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
5783 if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
5784 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
5785 ERR_clear_error();
5786 return nullptr;
5787 }
5788
5789 if (!sk_X509_push(path.get(), cert.get())) {
5790 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
5791 return nullptr;
5792 }
5793 OWNERSHIP_TRANSFERRED(cert);
5794 }
5795
5796 size_t size = sk_X509_num(path.get());
5797
5798 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
5799 ScopedLongArrayRW certs(env, certArray.get());
5800 for (size_t i = 0; i < size; i++) {
5801 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5802 certs[i] = reinterpret_cast<uintptr_t>(item);
5803 }
5804
5805 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
5806 return certArray.release();
5807 }
5808
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5809 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5810 CHECK_ERROR_QUEUE_ON_RETURN;
5811 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5812 ScopedLongArrayRO certsArray(env, certs);
5813 if (certsArray.get() == nullptr) {
5814 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5815 return nullptr;
5816 }
5817
5818 bssl::ScopedCBB result;
5819 CBB seq_contents;
5820 if (!CBB_init(result.get(), 2048 * certsArray.size())) {
5821 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
5822 return nullptr;
5823 }
5824 if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
5825 return nullptr;
5826 }
5827
5828 for (size_t i = 0; i < certsArray.size(); i++) {
5829 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5830 uint8_t* buf;
5831 int len = i2d_X509(x509, nullptr);
5832
5833 if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
5834 i2d_X509(x509, &buf) < 0) {
5835 return nullptr;
5836 }
5837 }
5838
5839 return CBBToByteArray(env, result.get());
5840 }
5841
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5842 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
5843 CONSCRYPT_UNUSED jobject holder) {
5844 CHECK_ERROR_QUEUE_ON_RETURN;
5845 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5846 JNI_TRACE("X509_free(%p)", x509);
5847
5848 if (x509 == nullptr) {
5849 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5850 JNI_TRACE("X509_free(%p) => x509 == null", x509);
5851 return;
5852 }
5853
5854 X509_free(x509);
5855 }
5856
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5857 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
5858 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5859 CONSCRYPT_UNUSED jobject holder2) {
5860 CHECK_ERROR_QUEUE_ON_RETURN;
5861 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5862 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5863 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5864
5865 if (x509_1 == nullptr) {
5866 conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
5867 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5868 return -1;
5869 }
5870
5871 if (x509_2 == nullptr) {
5872 conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
5873 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5874 return -1;
5875 }
5876
5877 int ret = X509_cmp(x509_1, x509_2);
5878 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
5879 return ret;
5880 }
5881
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)5882 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
5883 CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
5884 jlong certflagJava) {
5885 CHECK_ERROR_QUEUE_ON_RETURN;
5886 BIO* bio = to_BIO(env, bioRef);
5887 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5888 // NOLINTNEXTLINE(runtime/int)
5889 unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
5890 // NOLINTNEXTLINE(runtime/int)
5891 unsigned long certflag = static_cast<unsigned long>(certflagJava);
5892 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
5893
5894 if (bio == nullptr) {
5895 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
5896 return;
5897 }
5898
5899 if (x509 == nullptr) {
5900 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5901 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
5902 return;
5903 }
5904
5905 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
5906 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
5907 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
5908 return;
5909 }
5910 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
5911 }
5912
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5913 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
5914 CONSCRYPT_UNUSED jobject holder) {
5915 CHECK_ERROR_QUEUE_ON_RETURN;
5916 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5917 JNI_TRACE("X509_get_pubkey(%p)", x509);
5918
5919 if (x509 == nullptr) {
5920 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5921 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
5922 return 0;
5923 }
5924
5925 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
5926 if (pkey.get() == nullptr) {
5927 const uint32_t last_error = ERR_peek_last_error();
5928 const uint32_t first_error = ERR_peek_error();
5929 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
5930 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
5931 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
5932 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
5933 ERR_clear_error();
5934 conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
5935 return 0;
5936 }
5937
5938 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5939 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
5940 return 0;
5941 }
5942
5943 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
5944 return reinterpret_cast<uintptr_t>(pkey.release());
5945 }
5946
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5947 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
5948 CONSCRYPT_UNUSED jobject holder) {
5949 CHECK_ERROR_QUEUE_ON_RETURN;
5950 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5951 JNI_TRACE("X509_get_issuer_name(%p)", x509);
5952 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
5953 }
5954
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5955 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
5956 CONSCRYPT_UNUSED jobject holder) {
5957 CHECK_ERROR_QUEUE_ON_RETURN;
5958 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5959 JNI_TRACE("X509_get_subject_name(%p)", x509);
5960 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
5961 }
5962
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5963 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
5964 CONSCRYPT_UNUSED jobject holder) {
5965 CHECK_ERROR_QUEUE_ON_RETURN;
5966 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5967 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
5968
5969 if (x509 == nullptr) {
5970 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5971 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
5972 return nullptr;
5973 }
5974
5975 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
5976 ASN1_OBJECT* algorithm;
5977 X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
5978 return ASN1_OBJECT_to_OID_string(env, algorithm);
5979 }
5980
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5981 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
5982 CONSCRYPT_UNUSED jobject holder) {
5983 CHECK_ERROR_QUEUE_ON_RETURN;
5984 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5985 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
5986
5987 if (x509 == nullptr) {
5988 conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
5989 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
5990 return nullptr;
5991 }
5992
5993 const X509_ALGOR *sig_alg;
5994 X509_get0_signature(nullptr, &sig_alg, x509);
5995 const ASN1_OBJECT *oid;
5996 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5997 return ASN1_OBJECT_to_OID_string(env, oid);
5998 }
5999
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6000 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6001 CONSCRYPT_UNUSED jobject holder) {
6002 CHECK_ERROR_QUEUE_ON_RETURN;
6003 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6004 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6005
6006 if (x509 == nullptr) {
6007 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6008 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6009 return nullptr;
6010 }
6011
6012 const X509_ALGOR *sig_alg;
6013 X509_get0_signature(nullptr, &sig_alg, x509);
6014 return get_X509_ALGOR_parameter(env, sig_alg);
6015 }
6016
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6017 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6018 CONSCRYPT_UNUSED jobject holder) {
6019 CHECK_ERROR_QUEUE_ON_RETURN;
6020 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6021 JNI_TRACE("get_X509_issuerUID(%p)", x509);
6022
6023 if (x509 == nullptr) {
6024 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6025 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6026 return nullptr;
6027 }
6028
6029 const ASN1_BIT_STRING *issuer_uid;
6030 X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6031 if (issuer_uid == nullptr) {
6032 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6033 return nullptr;
6034 }
6035
6036 return ASN1BitStringToBooleanArray(env, issuer_uid);
6037 }
6038
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6039 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6040 CONSCRYPT_UNUSED jobject holder) {
6041 CHECK_ERROR_QUEUE_ON_RETURN;
6042 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6043 JNI_TRACE("get_X509_subjectUID(%p)", x509);
6044
6045 if (x509 == nullptr) {
6046 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6047 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6048 return nullptr;
6049 }
6050
6051 const ASN1_BIT_STRING *subject_uid;
6052 X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6053 if (subject_uid == nullptr) {
6054 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6055 return nullptr;
6056 }
6057
6058 return ASN1BitStringToBooleanArray(env, subject_uid);
6059 }
6060
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6061 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6062 CONSCRYPT_UNUSED jobject holder) {
6063 CHECK_ERROR_QUEUE_ON_RETURN;
6064 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6065 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6066
6067 if (x509 == nullptr) {
6068 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6069 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6070 return nullptr;
6071 }
6072
6073 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6074 // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6075 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6076 bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6077 static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6078 if (bitStr.get() == nullptr) {
6079 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6080 ERR_clear_error();
6081 return nullptr;
6082 }
6083
6084 return ASN1BitStringToBooleanArray(env, bitStr.get());
6085 }
6086
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6087 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6088 CONSCRYPT_UNUSED jobject holder) {
6089 CHECK_ERROR_QUEUE_ON_RETURN;
6090 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6091 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6092
6093 if (x509 == nullptr) {
6094 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6095 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6096 return nullptr;
6097 }
6098
6099 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6100 // |ERR_clear_error|, and throw CertificateParsingException.
6101 bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6102 X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6103 if (objArray.get() == nullptr) {
6104 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6105 ERR_clear_error();
6106 return nullptr;
6107 }
6108
6109 size_t size = sk_ASN1_OBJECT_num(objArray.get());
6110 ScopedLocalRef<jobjectArray> exKeyUsage(
6111 env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6112 nullptr));
6113 if (exKeyUsage.get() == nullptr) {
6114 return nullptr;
6115 }
6116
6117 for (size_t i = 0; i < size; i++) {
6118 ScopedLocalRef<jstring> oidStr(
6119 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6120 env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6121 }
6122
6123 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6124 return exKeyUsage.release();
6125 }
6126
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6127 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6128 CONSCRYPT_UNUSED jobject holder) {
6129 CHECK_ERROR_QUEUE_ON_RETURN;
6130 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6131 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6132
6133 if (x509 == nullptr) {
6134 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6135 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6136 return 0;
6137 }
6138
6139 // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6140 // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6141 // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6142 // the constructor even if |EXFLAG_INVALID| is set.
6143 //
6144 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6145 // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6146 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6147 bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6148 X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6149 if (basic_constraints == nullptr) {
6150 JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6151 ERR_clear_error();
6152 return -1;
6153 }
6154
6155 if (basic_constraints->pathlen == nullptr) {
6156 JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6157 return -1;
6158 }
6159
6160 if (!basic_constraints->ca) {
6161 // Path length constraints are only valid for CA certificates.
6162 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6163 JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6164 return -1;
6165 }
6166
6167 if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6168 // Path length constraints may not be negative.
6169 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6170 JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6171 return -1;
6172 }
6173
6174 long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6175 if (pathlen == -1 || pathlen > INT_MAX) {
6176 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6177 // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6178 // constraint is plausible, but Chromium rejects all values above 255.
6179 JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6180 return -1;
6181 }
6182
6183 JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6184 return pathlen;
6185 }
6186
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6187 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6188 CONSCRYPT_UNUSED jobject holder,
6189 jstring oidString) {
6190 CHECK_ERROR_QUEUE_ON_RETURN;
6191 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6192 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6193 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6194 }
6195
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6196 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6197 CONSCRYPT_UNUSED jobject holder,
6198 jstring oidString) {
6199 CHECK_ERROR_QUEUE_ON_RETURN;
6200 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6201 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6202 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6203 oidString);
6204 }
6205
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6206 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6207 jstring oidString) {
6208 CHECK_ERROR_QUEUE_ON_RETURN;
6209 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6210 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6211 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6212 env, revoked, oidString);
6213 }
6214
6215 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6216 X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6217 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6218 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6219 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6220
6221 if (x509 == nullptr) {
6222 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6223 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6224 return nullptr;
6225 }
6226
6227 int lastPos = -1;
6228 int count = 0;
6229 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6230 count++;
6231 }
6232
6233 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6234
6235 ScopedLocalRef<jobjectArray> joa(
6236 env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6237 if (joa.get() == nullptr) {
6238 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6239 return nullptr;
6240 }
6241
6242 lastPos = -1;
6243 count = 0;
6244 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6245 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6246
6247 ScopedLocalRef<jstring> extOid(
6248 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6249 if (extOid.get() == nullptr) {
6250 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6251 return nullptr;
6252 }
6253
6254 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6255 }
6256
6257 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6258 return joa.release();
6259 }
6260
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6261 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6262 CONSCRYPT_UNUSED jobject holder, jint critical) {
6263 CHECK_ERROR_QUEUE_ON_RETURN;
6264 // NOLINTNEXTLINE(runtime/int)
6265 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6266 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6267 critical);
6268 }
6269
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6270 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6271 CONSCRYPT_UNUSED jobject holder,
6272 jint critical) {
6273 CHECK_ERROR_QUEUE_ON_RETURN;
6274 // NOLINTNEXTLINE(runtime/int)
6275 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6276 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6277 env, x509CrlRef, critical);
6278 }
6279
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6280 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6281 jlong x509RevokedRef, jint critical) {
6282 CHECK_ERROR_QUEUE_ON_RETURN;
6283 // NOLINTNEXTLINE(runtime/int)
6284 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6285 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6286 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6287 }
6288
6289 /**
6290 * Based on example logging call back from SSL_CTX_set_info_callback man page
6291 */
info_callback_LOG(const SSL * s,int where,int ret)6292 static void info_callback_LOG(const SSL* s, int where, int ret) {
6293 int w = where & ~SSL_ST_MASK;
6294 const char* str;
6295 if (w & SSL_ST_CONNECT) {
6296 str = "SSL_connect";
6297 } else if (w & SSL_ST_ACCEPT) {
6298 str = "SSL_accept";
6299 } else {
6300 str = "undefined";
6301 }
6302
6303 if (where & SSL_CB_LOOP) {
6304 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6305 } else if (where & SSL_CB_ALERT) {
6306 str = (where & SSL_CB_READ) ? "read" : "write";
6307 JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6308 SSL_alert_desc_string_long(ret));
6309 } else if (where & SSL_CB_EXIT) {
6310 if (ret == 0) {
6311 JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6312 SSL_state_string_long(s));
6313 } else if (ret < 0) {
6314 JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6315 SSL_state_string_long(s));
6316 } else if (ret == 1) {
6317 JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6318 SSL_state_string_long(s));
6319 } else {
6320 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6321 SSL_state_string_long(s));
6322 }
6323 } else if (where & SSL_CB_HANDSHAKE_START) {
6324 JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6325 SSL_state_string_long(s));
6326 } else if (where & SSL_CB_HANDSHAKE_DONE) {
6327 JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6328 SSL_state_string_long(s));
6329 } else {
6330 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6331 SSL_state_string_long(s));
6332 }
6333 }
6334
6335 #ifdef _WIN32
6336
6337 /**
6338 * Dark magic helper function that checks, for a given SSL session, whether it
6339 * can SSL_read() or SSL_write() without blocking. Takes into account any
6340 * concurrent attempts to close the SSLSocket from the Java side. This is
6341 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6342 * while thread #2 is sitting in a blocking read or write. The type argument
6343 * specifies whether we are waiting for readability or writability. It expects
6344 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6345 * only need to wait in case one of these problems occurs.
6346 *
6347 * @param env
6348 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6349 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6350 * @param appData The application data structure with mutex info etc.
6351 * @param timeout_millis The timeout value for select call, with the special value
6352 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6353 * the Java semantics of the timeout value, not the usual
6354 * select() semantics.
6355 * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
6356 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6357 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6358 int timeout_millis) {
6359 int result = -1;
6360
6361 NetFd fd(env, fdObject);
6362 do {
6363 if (fd.isClosed()) {
6364 result = THROWN_EXCEPTION;
6365 break;
6366 }
6367
6368 WSAEVENT events[2];
6369 events[0] = appData->interruptEvent;
6370 events[1] = WSACreateEvent();
6371 if (events[1] == WSA_INVALID_EVENT) {
6372 JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
6373 break;
6374 }
6375
6376 if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
6377 FD_CLOSE) == SOCKET_ERROR) {
6378 JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
6379 break;
6380 }
6381
6382 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6383 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6384 timeout_millis);
6385
6386 int rc = WSAWaitForMultipleEvents(
6387 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
6388 if (rc == WSA_WAIT_FAILED) {
6389 JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
6390 result = -1;
6391 } else if (rc == WSA_WAIT_TIMEOUT) {
6392 result = 0;
6393 } else {
6394 result = 1;
6395 }
6396 WSACloseEvent(events[1]);
6397 } while (0);
6398
6399 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
6400 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
6401 result);
6402
6403 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6404 appData->waitingThreads--;
6405
6406 return result;
6407 }
6408
6409 #else // !defined(_WIN32)
6410
6411 /**
6412 * Dark magic helper function that checks, for a given SSL session, whether it
6413 * can SSL_read() or SSL_write() without blocking. Takes into account any
6414 * concurrent attempts to close the SSLSocket from the Java side. This is
6415 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6416 * while thread #2 is sitting in a blocking read or write. The type argument
6417 * specifies whether we are waiting for readability or writability. It expects
6418 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6419 * only need to wait in case one of these problems occurs.
6420 *
6421 * @param env
6422 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6423 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
6424 * @param appData The application data structure with mutex info etc.
6425 * @param timeout_millis The timeout value for poll call, with the special value
6426 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6427 * the Java semantics of the timeout value, not the usual
6428 * poll() semantics.
6429 * @return The result of the inner poll() call,
6430 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6431 * additional errors
6432 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6433 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
6434 int timeout_millis) {
6435 // This loop is an expanded version of the NET_FAILURE_RETRY
6436 // macro. It cannot simply be used in this case because poll
6437 // cannot be restarted without recreating the pollfd structure.
6438 int result;
6439 struct pollfd fds[2];
6440 do {
6441 NetFd fd(env, fdObject);
6442 if (fd.isClosed()) {
6443 result = THROWN_EXCEPTION;
6444 break;
6445 }
6446 int intFd = fd.get();
6447 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6448 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6449
6450 memset(&fds, 0, sizeof(fds));
6451 fds[0].fd = intFd;
6452 if (type == SSL_ERROR_WANT_READ) {
6453 fds[0].events = POLLIN | POLLPRI;
6454 } else {
6455 fds[0].events = POLLOUT | POLLPRI;
6456 }
6457
6458 fds[1].fd = appData->fdsEmergency[0];
6459 fds[1].events = POLLIN | POLLPRI;
6460
6461 // Converting from Java semantics to Posix semantics.
6462 if (timeout_millis <= 0) {
6463 timeout_millis = -1;
6464 }
6465
6466 CompatibilityCloseMonitor monitor(intFd);
6467
6468 result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
6469 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6470 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
6471 timeout_millis, result);
6472 if (result == -1) {
6473 if (fd.isClosed()) {
6474 result = THROWN_EXCEPTION;
6475 break;
6476 }
6477 if (errno != EINTR) {
6478 break;
6479 }
6480 }
6481 } while (result == -1);
6482
6483 std::lock_guard<std::mutex> appDataLock(appData->mutex);
6484
6485 if (result > 0) {
6486 // We have been woken up by a token in the emergency pipe. We
6487 // can't be sure the token is still in the pipe at this point
6488 // because it could have already been read by the thread that
6489 // originally wrote it if it entered sslSelect and acquired
6490 // the mutex before we did. Thus we cannot safely read from
6491 // the pipe in a blocking way (so we make the pipe
6492 // non-blocking at creation).
6493 if (fds[1].revents & POLLIN) {
6494 char token;
6495 do {
6496 (void)read(appData->fdsEmergency[0], &token, 1);
6497 } while (errno == EINTR);
6498 }
6499 }
6500
6501 // Tell the world that there is now one thread less waiting for the
6502 // underlying network.
6503 appData->waitingThreads--;
6504
6505 return result;
6506 }
6507 #endif // !defined(_WIN32)
6508
6509 /**
6510 * Helper function that wakes up a thread blocked in select(), in case there is
6511 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6512 * before closing the connection.
6513 *
6514 * @param data The application data structure with mutex info etc.
6515 */
sslNotify(AppData * appData)6516 static void sslNotify(AppData* appData) {
6517 #ifdef _WIN32
6518 SetEvent(appData->interruptEvent);
6519 #else
6520 // Write a byte to the emergency pipe, so a concurrent select() can return.
6521 // Note we have to restore the errno of the original system call, since the
6522 // caller relies on it for generating error messages.
6523 int errnoBackup = errno;
6524 char token = '*';
6525 do {
6526 errno = 0;
6527 (void)write(appData->fdsEmergency[1], &token, 1);
6528 } while (errno == EINTR);
6529 errno = errnoBackup;
6530 #endif
6531 }
6532
toAppData(const SSL * ssl)6533 static AppData* toAppData(const SSL* ssl) {
6534 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6535 }
6536
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)6537 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
6538 JNI_TRACE("ssl=%p cert_verify_callback", ssl);
6539
6540 AppData* appData = toAppData(ssl);
6541 JNIEnv* env = appData->env;
6542 if (env == nullptr) {
6543 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
6544 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6545 return ssl_verify_invalid;
6546 }
6547
6548 // Create the byte[][] array that holds all the certs
6549 ScopedLocalRef<jobjectArray> array(
6550 env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
6551 if (array.get() == nullptr) {
6552 return ssl_verify_invalid;
6553 }
6554
6555 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6556 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6557 jmethodID methodID =
6558 env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
6559
6560 const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
6561 const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
6562
6563 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
6564 authMethod);
6565 ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
6566 env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
6567
6568 ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
6569 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6570 return result;
6571 }
6572
6573 /**
6574 * Call back to watch for handshake to be completed. This is necessary for
6575 * False Start support, since SSL_do_handshake returns before the handshake is
6576 * completed in this case.
6577 */
info_callback(const SSL * ssl,int type,int value)6578 static void info_callback(const SSL* ssl, int type, int value) {
6579 JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
6580 if (conscrypt::trace::kWithJniTrace) {
6581 info_callback_LOG(ssl, type, value);
6582 }
6583 if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
6584 JNI_TRACE("ssl=%p info_callback ignored", ssl);
6585 return;
6586 }
6587
6588 AppData* appData = toAppData(ssl);
6589 JNIEnv* env = appData->env;
6590 if (env == nullptr) {
6591 CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
6592 JNI_TRACE("ssl=%p info_callback env error", ssl);
6593 return;
6594 }
6595 if (env->ExceptionCheck()) {
6596 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6597 return;
6598 }
6599
6600 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6601
6602 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6603 jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(II)V");
6604
6605 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6606 env->CallVoidMethod(sslHandshakeCallbacks, methodID, type, value);
6607
6608 if (env->ExceptionCheck()) {
6609 JNI_TRACE("ssl=%p info_callback exception", ssl);
6610 }
6611 JNI_TRACE("ssl=%p info_callback completed", ssl);
6612 }
6613
6614 /**
6615 * Call back to ask for a certificate. There are three possible exit codes:
6616 *
6617 * 1 is success.
6618 * 0 is error.
6619 * -1 is to pause the handshake to continue from the same place later.
6620 */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)6621 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
6622 JNI_TRACE("ssl=%p cert_cb", ssl);
6623
6624 // cert_cb is called for both clients and servers, but we are only
6625 // interested in client certificates.
6626 if (SSL_is_server(ssl)) {
6627 JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
6628 return 1;
6629 }
6630
6631 AppData* appData = toAppData(ssl);
6632 JNIEnv* env = appData->env;
6633 if (env == nullptr) {
6634 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
6635 JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
6636 return 0;
6637 }
6638 if (env->ExceptionCheck()) {
6639 JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
6640 return 0;
6641 }
6642 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6643
6644 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6645 jmethodID methodID = env->GetMethodID(cls, "clientCertificateRequested", "([B[I[[B)V");
6646
6647 // Call Java callback which can reconfigure the client certificate.
6648 const uint8_t* ctype = nullptr;
6649 size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
6650 const uint16_t* sigalgs = nullptr;
6651 size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
6652 ScopedLocalRef<jobjectArray> issuers(
6653 env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
6654 if (issuers.get() == nullptr) {
6655 return 0;
6656 }
6657
6658 if (conscrypt::trace::kWithJniTrace) {
6659 for (size_t i = 0; i < ctype_num; i++) {
6660 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
6661 }
6662 for (size_t i = 0; i < sigalgs_num; i++) {
6663 JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
6664 }
6665 }
6666
6667 jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
6668 if (keyTypes == nullptr) {
6669 JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
6670 return 0;
6671 }
6672 env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
6673 reinterpret_cast<const jbyte*>(ctype));
6674
6675 jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
6676 if (signatureAlgs == nullptr) {
6677 JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
6678 return 0;
6679 }
6680 {
6681 ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
6682 for (size_t i = 0; i < sigalgs_num; i++) {
6683 sigAlgsRW[i] = sigalgs[i];
6684 }
6685 }
6686
6687 JNI_TRACE(
6688 "ssl=%p clientCertificateRequested calling clientCertificateRequested "
6689 "keyTypes=%p signatureAlgs=%p issuers=%p",
6690 ssl, keyTypes, signatureAlgs, issuers.get());
6691 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
6692
6693 if (env->ExceptionCheck()) {
6694 JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
6695 return 0;
6696 }
6697
6698 JNI_TRACE("ssl=%p cert_cb => 1", ssl);
6699 return 1;
6700 }
6701
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)6702 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
6703 SSL* ssl = client_hello->ssl;
6704 JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
6705
6706 AppData* appData = toAppData(ssl);
6707 JNIEnv* env = appData->env;
6708 if (env == nullptr) {
6709 CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
6710 JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
6711 return ssl_select_cert_error;
6712 }
6713 if (env->ExceptionCheck()) {
6714 JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
6715 return ssl_select_cert_error;
6716 }
6717
6718 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6719 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6720 jmethodID methodID = env->GetMethodID(cls, "serverCertificateRequested", "()V");
6721
6722 JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
6723 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
6724
6725 if (env->ExceptionCheck()) {
6726 JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
6727 return ssl_select_cert_error;
6728 }
6729 JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
6730 return ssl_select_cert_success;
6731 }
6732
6733 /**
6734 * Pre-Shared Key (PSK) client callback.
6735 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6736 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
6737 unsigned int max_identity_len, unsigned char* psk,
6738 unsigned int max_psk_len) {
6739 JNI_TRACE("ssl=%p psk_client_callback", ssl);
6740
6741 AppData* appData = toAppData(ssl);
6742 JNIEnv* env = appData->env;
6743 if (env == nullptr) {
6744 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
6745 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6746 return 0;
6747 }
6748 if (env->ExceptionCheck()) {
6749 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6750 return 0;
6751 }
6752
6753 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6754 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6755 jmethodID methodID =
6756 env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
6757 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6758 ScopedLocalRef<jstring> identityHintJava(env,
6759 (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
6760 ScopedLocalRef<jbyteArray> identityJava(
6761 env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
6762 if (identityJava.get() == nullptr) {
6763 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6764 return 0;
6765 }
6766 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6767 if (keyJava.get() == nullptr) {
6768 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6769 return 0;
6770 }
6771 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6772 identityJava.get(), keyJava.get());
6773 if (env->ExceptionCheck()) {
6774 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6775 return 0;
6776 }
6777 if (keyLen <= 0) {
6778 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6779 return 0;
6780 } else if ((unsigned int)keyLen > max_psk_len) {
6781 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6782 return 0;
6783 }
6784 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6785 if (keyJavaRo.get() == nullptr) {
6786 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
6787 return 0;
6788 }
6789 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6790
6791 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
6792 if (identityJavaRo.get() == nullptr) {
6793 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
6794 return 0;
6795 }
6796 memcpy(identity, identityJavaRo.get(), max_identity_len);
6797
6798 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
6799 return static_cast<unsigned int>(keyLen);
6800 }
6801
6802 /**
6803 * Pre-Shared Key (PSK) server callback.
6804 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)6805 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
6806 unsigned int max_psk_len) {
6807 JNI_TRACE("ssl=%p psk_server_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 psk_server_callback");
6813 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
6814 return 0;
6815 }
6816 if (env->ExceptionCheck()) {
6817 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
6818 return 0;
6819 }
6820
6821 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6822 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6823 jmethodID methodID = env->GetMethodID(cls, "serverPSKKeyRequested",
6824 "(Ljava/lang/String;Ljava/lang/String;[B)I");
6825 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
6826 const char* identityHint = SSL_get_psk_identity_hint(ssl);
6827 ScopedLocalRef<jstring> identityHintJava(
6828 env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
6829 ScopedLocalRef<jstring> identityJava(
6830 env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
6831 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
6832 if (keyJava.get() == nullptr) {
6833 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
6834 return 0;
6835 }
6836 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
6837 identityJava.get(), keyJava.get());
6838 if (env->ExceptionCheck()) {
6839 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
6840 return 0;
6841 }
6842 if (keyLen <= 0) {
6843 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
6844 return 0;
6845 } else if ((unsigned int)keyLen > max_psk_len) {
6846 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
6847 return 0;
6848 }
6849 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
6850 if (keyJavaRo.get() == nullptr) {
6851 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
6852 return 0;
6853 }
6854 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
6855
6856 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
6857 return static_cast<unsigned int>(keyLen);
6858 }
6859
new_session_callback(SSL * ssl,SSL_SESSION * session)6860 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
6861 JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
6862
6863 AppData* appData = toAppData(ssl);
6864 JNIEnv* env = appData->env;
6865 if (env == nullptr) {
6866 CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
6867 JNI_TRACE("ssl=%p new_session_callback env error", ssl);
6868 return 0;
6869 }
6870 if (env->ExceptionCheck()) {
6871 JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
6872 return 0;
6873 }
6874
6875 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6876 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6877 jmethodID methodID = env->GetMethodID(cls, "onNewSessionEstablished", "(J)V");
6878 JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
6879 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
6880 if (env->ExceptionCheck()) {
6881 JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
6882 env->ExceptionClear();
6883 }
6884 JNI_TRACE("ssl=%p new_session_callback completed", ssl);
6885
6886 // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
6887 // the reference count.
6888 return 0;
6889 }
6890
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)6891 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
6892 int* out_copy) {
6893 JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
6894
6895 // Always set to out_copy to zero. The Java callback will be responsible for incrementing
6896 // the reference count (and any required synchronization).
6897 *out_copy = 0;
6898
6899 AppData* appData = toAppData(ssl);
6900 JNIEnv* env = appData->env;
6901 if (env == nullptr) {
6902 CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
6903 JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
6904 return 0;
6905 }
6906 if (env->ExceptionCheck()) {
6907 JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
6908 return 0;
6909 }
6910
6911 // Copy the ID to a byte[].
6912 jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
6913 if (id_array == nullptr) {
6914 JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
6915 return 0;
6916 }
6917 env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
6918 reinterpret_cast<const jbyte*>(id));
6919
6920 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6921 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6922 jmethodID methodID = env->GetMethodID(cls, "serverSessionRequested", "([B)J");
6923 JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
6924 jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
6925 if (env->ExceptionCheck()) {
6926 JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
6927 env->ExceptionClear();
6928 }
6929 SSL_SESSION* ssl_session_ptr =
6930 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
6931 JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
6932 return ssl_session_ptr;
6933 }
6934
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)6935 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
6936 CHECK_ERROR_QUEUE_ON_RETURN;
6937 int ret = 0;
6938 ret = EVP_has_aes_hardware();
6939 JNI_TRACE("EVP_has_aes_hardware => %d", ret);
6940 return ret;
6941 }
6942
debug_print_session_key(const SSL * ssl,const char * line)6943 static void debug_print_session_key(const SSL* ssl, const char* line) {
6944 JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
6945 }
6946
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)6947 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
6948 static constexpr size_t kDataWidth = 16;
6949
6950 struct timeval tv;
6951 if (gettimeofday(&tv, NULL)) {
6952 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6953 "debug_print_packet_data: could not get time of day");
6954 return;
6955 }
6956
6957 // Packet preamble for text2pcap
6958 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
6959 tv.tv_sec, static_cast<long>(tv.tv_usec)); // NOLINT(runtime/int)
6960
6961 char out[kDataWidth * 3 + 1];
6962 for (size_t i = 0; i < len; i += kDataWidth) {
6963 size_t n = len - i < kDataWidth ? len - i : kDataWidth;
6964
6965 for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
6966 int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
6967 if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
6968 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
6969 "debug_print_packet_data failed to output %d", ret);
6970 return;
6971 }
6972 }
6973
6974 // Print out packet data in format understood by text2pcap
6975 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
6976 }
6977
6978 // Conclude the packet data
6979 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
6980 }
6981
6982 /*
6983 * public static native int SSL_CTX_new();
6984 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)6985 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
6986 CHECK_ERROR_QUEUE_ON_RETURN;
6987 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
6988 if (sslCtx.get() == nullptr) {
6989 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
6990 return 0;
6991 }
6992 SSL_CTX_set_options(
6993 sslCtx.get(),
6994 SSL_OP_ALL
6995 // We also disable session tickets for better compatibility b/2682876
6996 | SSL_OP_NO_TICKET
6997 // We also disable compression for better compatibility b/2710492 b/2710497
6998 | SSL_OP_NO_COMPRESSION
6999 // Generate a fresh ECDH keypair for each key exchange.
7000 | SSL_OP_SINGLE_ECDH_USE);
7001 SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7002 SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7003
7004 uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7005 /*
7006 * Turn on "partial write" mode. This means that SSL_write() will
7007 * behave like Posix write() and possibly return after only
7008 * writing a partial buffer. Note: The alternative, perhaps
7009 * surprisingly, is not that SSL_write() always does full writes
7010 * but that it will force you to retry write calls having
7011 * preserved the full state of the original call. (This is icky
7012 * and undesirable.)
7013 */
7014 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7015
7016 // Reuse empty buffers within the SSL_CTX to save memory
7017 mode |= SSL_MODE_RELEASE_BUFFERS;
7018
7019 // Enable False Start.
7020 mode |= SSL_MODE_ENABLE_FALSE_START;
7021
7022 // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7023 // between
7024 // calls to wrap(...).
7025 // See https://github.com/netty/netty-tcnative/issues/100
7026 mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7027
7028 SSL_CTX_set_mode(sslCtx.get(), mode);
7029
7030 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7031 SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7032 SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7033 if (conscrypt::trace::kWithJniTraceKeys) {
7034 SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7035 }
7036
7037 // By default BoringSSL will cache in server mode, but we want to get
7038 // notified of new sessions being created in client mode. We set
7039 // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7040 // ignore it in server mode in favor of the internal cache.
7041 SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7042 SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7043 SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7044
7045 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7046 return (jlong)sslCtx.release();
7047 }
7048
7049 /**
7050 * public static native void SSL_CTX_free(long ssl_ctx)
7051 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7052 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7053 CONSCRYPT_UNUSED jobject holder) {
7054 CHECK_ERROR_QUEUE_ON_RETURN;
7055 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7056 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7057 if (ssl_ctx == nullptr) {
7058 return;
7059 }
7060 SSL_CTX_free(ssl_ctx);
7061 }
7062
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7063 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7064 CONSCRYPT_UNUSED jobject holder,
7065 jbyteArray sid_ctx) {
7066 CHECK_ERROR_QUEUE_ON_RETURN;
7067 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7068 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7069 sid_ctx);
7070 if (ssl_ctx == nullptr) {
7071 return;
7072 }
7073
7074 ScopedByteArrayRO buf(env, sid_ctx);
7075 if (buf.get() == nullptr) {
7076 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7077 ssl_ctx);
7078 return;
7079 }
7080
7081 unsigned int length = static_cast<unsigned int>(buf.size());
7082 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7083 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7084 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7085 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7086 return;
7087 }
7088 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7089 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7090 if (result == 0) {
7091 conscrypt::jniutil::throwExceptionFromBoringSSLError(
7092 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7093 return;
7094 }
7095 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7096 }
7097
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7098 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7099 CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7100 CHECK_ERROR_QUEUE_ON_RETURN;
7101 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7102 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7103 if (ssl_ctx == nullptr) {
7104 return 0L;
7105 }
7106
7107 return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7108 }
7109
7110 /**
7111 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7112 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7113 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7114 CONSCRYPT_UNUSED jobject holder) {
7115 CHECK_ERROR_QUEUE_ON_RETURN;
7116 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7117 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7118 if (ssl_ctx == nullptr) {
7119 return 0;
7120 }
7121 bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7122 if (ssl.get() == nullptr) {
7123 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7124 "Unable to create SSL structure");
7125 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7126 return 0;
7127 }
7128
7129 /*
7130 * Create our special application data.
7131 */
7132 AppData* appData = AppData::create();
7133 if (appData == nullptr) {
7134 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7135 ERR_clear_error();
7136 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7137 return 0;
7138 }
7139 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7140
7141 SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7142
7143 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7144 return (jlong)ssl.release();
7145 }
7146
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject ssl_holder)7147 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7148 CONSCRYPT_UNUSED CONSCRYPT_UNUSED jobject
7149 ssl_holder) {
7150 CHECK_ERROR_QUEUE_ON_RETURN;
7151 SSL* ssl = to_SSL(env, ssl_address, true);
7152 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7153 if (ssl == nullptr) {
7154 return;
7155 }
7156
7157 // NOLINTNEXTLINE(runtime/int)
7158 long ret = SSL_enable_tls_channel_id(ssl);
7159 if (ret != 1L) {
7160 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7161 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7162 "Error enabling Channel ID");
7163 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7164 return;
7165 }
7166 }
7167
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7168 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7169 CONSCRYPT_UNUSED jobject ssl_holder) {
7170 CHECK_ERROR_QUEUE_ON_RETURN;
7171 SSL* ssl = to_SSL(env, ssl_address, true);
7172 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7173 if (ssl == nullptr) {
7174 return nullptr;
7175 }
7176
7177 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7178 // as a constant anywhere.
7179 jbyteArray javaBytes = env->NewByteArray(64);
7180 ScopedByteArrayRW bytes(env, javaBytes);
7181 if (bytes.get() == nullptr) {
7182 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7183 return nullptr;
7184 }
7185
7186 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7187 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7188 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7189 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7190 size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7191 if (ret == 0) {
7192 // Channel ID either not set or did not verify
7193 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7194 return nullptr;
7195 } else if (ret != 64) {
7196 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7197 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7198 "Error getting Channel ID");
7199 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7200 return nullptr;
7201 }
7202
7203 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7204 return javaBytes;
7205 }
7206
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7207 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7208 CONSCRYPT_UNUSED jobject ssl_holder,
7209 jobject pkeyRef) {
7210 CHECK_ERROR_QUEUE_ON_RETURN;
7211 SSL* ssl = to_SSL(env, ssl_address, true);
7212 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7213 if (ssl == nullptr) {
7214 return;
7215 }
7216
7217 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7218 if (pkey == nullptr) {
7219 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7220 return;
7221 }
7222
7223 // NOLINTNEXTLINE(runtime/int)
7224 long ret = SSL_set1_tls_channel_id(ssl, pkey);
7225
7226 if (ret != 1L) {
7227 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7228 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7229 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7230 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7231 return;
7232 }
7233
7234 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7235 }
7236
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7237 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7238 CONSCRYPT_UNUSED jobject ssl_holder,
7239 jobjectArray encodedCertificatesJava,
7240 jobject pkeyRef) {
7241 CHECK_ERROR_QUEUE_ON_RETURN;
7242 SSL* ssl = to_SSL(env, ssl_address, true);
7243 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7244 encodedCertificatesJava, pkeyRef);
7245 if (ssl == nullptr) {
7246 return;
7247 }
7248 if (encodedCertificatesJava == nullptr) {
7249 conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7250 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7251 return;
7252 }
7253 size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7254 if (numCerts == 0) {
7255 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7256 "certificates.length == 0");
7257 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7258 return;
7259 }
7260 if (pkeyRef == nullptr) {
7261 conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7262 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7263 return;
7264 }
7265
7266 // Get the private key.
7267 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7268 if (pkey == nullptr) {
7269 conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7270 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7271 return;
7272 }
7273
7274 // Copy the certificates.
7275 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7276 std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7277 for (size_t i = 0; i < numCerts; ++i) {
7278 ScopedLocalRef<jbyteArray> certArray(
7279 env, reinterpret_cast<jbyteArray>(
7280 env->GetObjectArrayElement(encodedCertificatesJava, i)));
7281 certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7282 if (!certBufferRefs[i]) {
7283 return;
7284 }
7285 certBuffers[i] = certBufferRefs[i].get();
7286 }
7287
7288 if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7289 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7290 "Error configuring certificate");
7291 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7292 return;
7293 }
7294 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7295 }
7296
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7297 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7298 CONSCRYPT_UNUSED jobject ssl_holder,
7299 jobjectArray principals) {
7300 CHECK_ERROR_QUEUE_ON_RETURN;
7301 SSL* ssl = to_SSL(env, ssl_address, true);
7302 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7303 if (ssl == nullptr) {
7304 return;
7305 }
7306
7307 if (principals == nullptr) {
7308 conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7309 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7310 return;
7311 }
7312
7313 int length = env->GetArrayLength(principals);
7314 if (length == 0) {
7315 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7316 "principals.length == 0");
7317 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7318 return;
7319 }
7320
7321 bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7322 if (principalsStack.get() == nullptr) {
7323 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7324 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7325 return;
7326 }
7327 for (int i = 0; i < length; i++) {
7328 ScopedLocalRef<jbyteArray> principal(
7329 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7330 bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7331 if (!buf) {
7332 return;
7333 }
7334 if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7335 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7336 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7337 return;
7338 }
7339 OWNERSHIP_TRANSFERRED(buf);
7340 }
7341
7342 SSL_set0_client_CAs(ssl, principalsStack.release());
7343 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7344 }
7345
7346 /**
7347 * public static native long SSL_set_mode(long ssl, long mode);
7348 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)7349 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
7350 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
7351 CHECK_ERROR_QUEUE_ON_RETURN;
7352 SSL* ssl = to_SSL(env, ssl_address, true);
7353 // NOLINTNEXTLINE(runtime/int)
7354 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
7355 if (ssl == nullptr) {
7356 return 0;
7357 }
7358 jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
7359 // NOLINTNEXTLINE(runtime/int)
7360 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
7361 return result;
7362 }
7363
7364 /**
7365 * public static native long SSL_set_options(long ssl, long options);
7366 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7367 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
7368 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7369 CHECK_ERROR_QUEUE_ON_RETURN;
7370 SSL* ssl = to_SSL(env, ssl_address, true);
7371 // NOLINTNEXTLINE(runtime/int)
7372 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
7373 if (ssl == nullptr) {
7374 return 0;
7375 }
7376 jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
7377 // NOLINTNEXTLINE(runtime/int)
7378 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
7379 return result;
7380 }
7381
7382 /**
7383 * public static native long SSL_clear_options(long ssl, long options);
7384 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)7385 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
7386 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
7387 CHECK_ERROR_QUEUE_ON_RETURN;
7388 SSL* ssl = to_SSL(env, ssl_address, true);
7389 // NOLINTNEXTLINE(runtime/int)
7390 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
7391 if (ssl == nullptr) {
7392 return 0;
7393 }
7394 jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
7395 // NOLINTNEXTLINE(runtime/int)
7396 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
7397 return result;
7398 }
7399
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)7400 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
7401 CONSCRYPT_UNUSED jobject ssl_holder,
7402 jint min_version, jint max_version) {
7403 CHECK_ERROR_QUEUE_ON_RETURN;
7404 SSL* ssl = to_SSL(env, ssl_address, true);
7405 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
7406 max_version);
7407 if (ssl == nullptr) {
7408 return 0;
7409 }
7410 int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
7411 int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
7412 // Return failure if either call failed.
7413 int result = 1;
7414 if (!min_result || !max_result) {
7415 result = 0;
7416 // The only possible error is an invalid version, so we don't need the details.
7417 ERR_clear_error();
7418 }
7419 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
7420 min_result, max_result, result);
7421 return result;
7422 }
7423
7424 /**
7425 * public static native void SSL_enable_signed_cert_timestamps(long ssl);
7426 */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7427 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
7428 CONSCRYPT_UNUSED jobject ssl_holder) {
7429 CHECK_ERROR_QUEUE_ON_RETURN;
7430 SSL* ssl = to_SSL(env, ssl_address, true);
7431 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
7432 if (ssl == nullptr) {
7433 return;
7434 }
7435
7436 SSL_enable_signed_cert_timestamps(ssl);
7437 }
7438
7439 /**
7440 * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
7441 */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7442 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
7443 JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
7444 CHECK_ERROR_QUEUE_ON_RETURN;
7445 SSL* ssl = to_SSL(env, ssl_address, true);
7446 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
7447 if (ssl == nullptr) {
7448 return nullptr;
7449 }
7450
7451 const uint8_t* data;
7452 size_t data_len;
7453 SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
7454
7455 if (data_len == 0) {
7456 JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
7457 return nullptr;
7458 }
7459
7460 jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
7461 if (result != nullptr) {
7462 env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
7463 }
7464 return result;
7465 }
7466
7467 /*
7468 * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
7469 */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)7470 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
7471 CONSCRYPT_UNUSED jobject ssl_holder,
7472 jbyteArray list) {
7473 CHECK_ERROR_QUEUE_ON_RETURN;
7474 SSL* ssl = to_SSL(env, ssl_address, true);
7475 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
7476 if (ssl == nullptr) {
7477 return;
7478 }
7479
7480 ScopedByteArrayRO listBytes(env, list);
7481 if (listBytes.get() == nullptr) {
7482 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
7483 return;
7484 }
7485
7486 if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
7487 listBytes.size())) {
7488 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
7489 } else {
7490 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
7491 }
7492 }
7493
7494 /*
7495 * public static native void SSL_enable_ocsp_stapling(long ssl);
7496 */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7497 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
7498 CONSCRYPT_UNUSED jobject ssl_holder) {
7499 CHECK_ERROR_QUEUE_ON_RETURN;
7500 SSL* ssl = to_SSL(env, ssl_address, true);
7501 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
7502 if (ssl == nullptr) {
7503 return;
7504 }
7505
7506 SSL_enable_ocsp_stapling(ssl);
7507 }
7508
7509 /*
7510 * public static native byte[] SSL_get_ocsp_response(long ssl);
7511 */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7512 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7513 CONSCRYPT_UNUSED jobject ssl_holder) {
7514 CHECK_ERROR_QUEUE_ON_RETURN;
7515 SSL* ssl = to_SSL(env, ssl_address, true);
7516 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
7517 if (ssl == nullptr) {
7518 return nullptr;
7519 }
7520
7521 const uint8_t* data;
7522 size_t data_len;
7523 SSL_get0_ocsp_response(ssl, &data, &data_len);
7524
7525 if (data_len == 0) {
7526 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
7527 return nullptr;
7528 }
7529
7530 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7531 if (byteArray.get() == nullptr) {
7532 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
7533 return nullptr;
7534 }
7535
7536 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7537 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
7538 data_len);
7539
7540 return byteArray.release();
7541 }
7542
7543 /*
7544 * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
7545 */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)7546 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
7547 CONSCRYPT_UNUSED jobject ssl_holder,
7548 jbyteArray response) {
7549 CHECK_ERROR_QUEUE_ON_RETURN;
7550 SSL* ssl = to_SSL(env, ssl_address, true);
7551 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
7552 if (ssl == nullptr) {
7553 return;
7554 }
7555
7556 ScopedByteArrayRO responseBytes(env, response);
7557 if (responseBytes.get() == nullptr) {
7558 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
7559 return;
7560 }
7561
7562 if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
7563 responseBytes.size())) {
7564 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
7565 } else {
7566 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
7567 }
7568 }
7569
7570 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
7571 // to customize the length of their verify_data (with a default of 12 bytes). We accept
7572 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
7573 // tests and update this value if necessary.
7574 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
7575
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7576 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
7577 CONSCRYPT_UNUSED jobject ssl_holder) {
7578 CHECK_ERROR_QUEUE_ON_RETURN;
7579 SSL* ssl = to_SSL(env, ssl_address, true);
7580 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
7581 if (ssl == nullptr) {
7582 return nullptr;
7583 }
7584
7585 uint8_t data[MAX_TLS_UNIQUE_LENGTH];
7586 size_t data_len;
7587 int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
7588
7589 if (!ret || data_len == 0) {
7590 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
7591 return nullptr;
7592 }
7593
7594 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
7595 if (byteArray.get() == nullptr) {
7596 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
7597 return nullptr;
7598 }
7599
7600 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
7601 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
7602 data_len);
7603
7604 return byteArray.release();
7605 }
7606
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)7607 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
7608 CONSCRYPT_UNUSED jobject ssl_holder,
7609 jbyteArray label, jbyteArray context,
7610 jint num_bytes) {
7611 CHECK_ERROR_QUEUE_ON_RETURN;
7612 SSL* ssl = to_SSL(env, ssl_address, true);
7613 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
7614 if (ssl == nullptr) {
7615 return nullptr;
7616 }
7617 ScopedByteArrayRO labelBytes(env, label);
7618 if (labelBytes.get() == nullptr) {
7619 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
7620 return nullptr;
7621 }
7622 std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
7623 int ret;
7624 if (context == nullptr) {
7625 ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
7626 reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
7627 nullptr, 0, 0);
7628 } else {
7629 ScopedByteArrayRO contextBytes(env, context);
7630 if (contextBytes.get() == nullptr) {
7631 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
7632 ssl);
7633 return nullptr;
7634 }
7635 ret = SSL_export_keying_material(
7636 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
7637 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
7638 contextBytes.size(), 1);
7639 }
7640 if (!ret) {
7641 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
7642 conscrypt::jniutil::throwSSLExceptionStr);
7643 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
7644 return nullptr;
7645 }
7646 jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
7647 if (result == nullptr) {
7648 conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
7649 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
7650 return nullptr;
7651 }
7652 const jbyte* src = reinterpret_cast<jbyte*>(out.get());
7653 env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
7654 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
7655 return result;
7656 }
7657
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)7658 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
7659 CONSCRYPT_UNUSED jobject ssl_holder,
7660 jstring identityHintJava) {
7661 CHECK_ERROR_QUEUE_ON_RETURN;
7662 SSL* ssl = to_SSL(env, ssl_address, true);
7663 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
7664 identityHintJava);
7665 if (ssl == nullptr) {
7666 return;
7667 }
7668
7669 int ret;
7670 if (identityHintJava == nullptr) {
7671 ret = SSL_use_psk_identity_hint(ssl, nullptr);
7672 } else {
7673 ScopedUtfChars identityHint(env, identityHintJava);
7674 if (identityHint.c_str() == nullptr) {
7675 conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7676 return;
7677 }
7678 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7679 }
7680
7681 if (ret != 1) {
7682 int sslErrorCode = SSL_get_error(ssl, ret);
7683 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7684 "Failed to set PSK identity hint");
7685 }
7686 }
7687
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7688 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7689 CONSCRYPT_UNUSED jobject ssl_holder,
7690 jboolean enabled) {
7691 CHECK_ERROR_QUEUE_ON_RETURN;
7692 SSL* ssl = to_SSL(env, ssl_address, true);
7693 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
7694 if (ssl == nullptr) {
7695 return;
7696 }
7697
7698 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
7699 }
7700
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)7701 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
7702 CONSCRYPT_UNUSED jobject ssl_holder,
7703 jboolean enabled) {
7704 CHECK_ERROR_QUEUE_ON_RETURN;
7705 SSL* ssl = to_SSL(env, ssl_address, true);
7706 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
7707 if (ssl == nullptr) {
7708 return;
7709 }
7710
7711 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
7712 }
7713
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7714 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
7715 CONSCRYPT_UNUSED jobject ssl_holder) {
7716 CHECK_ERROR_QUEUE_ON_RETURN;
7717 SSL* ssl = to_SSL(env, ssl_address, true);
7718 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7719 if (ssl == nullptr) {
7720 return nullptr;
7721 }
7722
7723 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7724 size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7725 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
7726 ScopedLongArrayRW ciphers(env, ciphersArray.get());
7727 for (size_t i = 0; i < count; i++) {
7728 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7729 }
7730
7731 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
7732 return ciphersArray.release();
7733 }
7734
7735 /**
7736 * Sets the ciphers suites that are enabled in the SSL
7737 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)7738 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
7739 CONSCRYPT_UNUSED jobject ssl_holder,
7740 jobjectArray cipherSuites) {
7741 CHECK_ERROR_QUEUE_ON_RETURN;
7742 SSL* ssl = to_SSL(env, ssl_address, true);
7743 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7744 if (ssl == nullptr) {
7745 return;
7746 }
7747 if (cipherSuites == nullptr) {
7748 conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
7749 return;
7750 }
7751
7752 int length = env->GetArrayLength(cipherSuites);
7753
7754 /*
7755 * Special case for empty cipher list. This is considered an error by the
7756 * SSL_set_cipher_list API, but Java allows this silly configuration.
7757 * However, the SSL cipher list is still set even when SSL_set_cipher_list
7758 * returns 0 in this case. Just to make sure, we check the resulting cipher
7759 * list to make sure it's zero length.
7760 */
7761 if (length == 0) {
7762 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
7763 SSL_set_cipher_list(ssl, "");
7764 ERR_clear_error();
7765 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
7766 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
7767 conscrypt::jniutil::throwRuntimeException(
7768 env, "SSL_set_cipher_list did not update ciphers!");
7769 ERR_clear_error();
7770 }
7771 return;
7772 }
7773
7774 static const char noSSLv2[] = "!SSLv2";
7775 size_t cipherStringLen = strlen(noSSLv2);
7776
7777 for (int i = 0; i < length; i++) {
7778 ScopedLocalRef<jstring> cipherSuite(
7779 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7780 ScopedUtfChars c(env, cipherSuite.get());
7781 if (c.c_str() == nullptr) {
7782 return;
7783 }
7784
7785 if (cipherStringLen + 1 < cipherStringLen) {
7786 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7787 "Overflow in cipher suite strings");
7788 return;
7789 }
7790 cipherStringLen += 1; /* For the separating colon */
7791
7792 if (cipherStringLen + c.size() < cipherStringLen) {
7793 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7794 "Overflow in cipher suite strings");
7795 return;
7796 }
7797 cipherStringLen += c.size();
7798 }
7799
7800 if (cipherStringLen + 1 < cipherStringLen) {
7801 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7802 "Overflow in cipher suite strings");
7803 return;
7804 }
7805 cipherStringLen += 1; /* For final NUL. */
7806
7807 std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
7808 if (cipherString.get() == nullptr) {
7809 conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
7810 return;
7811 }
7812 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
7813 size_t j = strlen(noSSLv2);
7814
7815 for (int i = 0; i < length; i++) {
7816 ScopedLocalRef<jstring> cipherSuite(
7817 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7818 ScopedUtfChars c(env, cipherSuite.get());
7819
7820 cipherString[j++] = ':';
7821 memcpy(&cipherString[j], c.c_str(), c.size());
7822 j += c.size();
7823 }
7824
7825 cipherString[j++] = 0;
7826 if (j != cipherStringLen) {
7827 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7828 "Internal error");
7829 return;
7830 }
7831
7832 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
7833 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
7834 ERR_clear_error();
7835 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7836 "Illegal cipher suite strings.");
7837 return;
7838 }
7839 }
7840
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7841 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
7842 CONSCRYPT_UNUSED jobject ssl_holder) {
7843 CHECK_ERROR_QUEUE_ON_RETURN;
7844 SSL* ssl = to_SSL(env, ssl_address, true);
7845 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7846 if (ssl == nullptr) {
7847 return;
7848 }
7849 SSL_set_accept_state(ssl);
7850 }
7851
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7852 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
7853 CONSCRYPT_UNUSED jobject ssl_holder) {
7854 CHECK_ERROR_QUEUE_ON_RETURN;
7855 SSL* ssl = to_SSL(env, ssl_address, true);
7856 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7857 if (ssl == nullptr) {
7858 return;
7859 }
7860 SSL_set_connect_state(ssl);
7861 }
7862
7863 /**
7864 * Sets certificate expectations, especially for server to request client auth
7865 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)7866 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
7867 CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
7868 CHECK_ERROR_QUEUE_ON_RETURN;
7869 SSL* ssl = to_SSL(env, ssl_address, true);
7870 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7871 if (ssl == nullptr) {
7872 return;
7873 }
7874 SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
7875 }
7876
7877 /**
7878 * Sets the ciphers suites that are enabled in the SSL
7879 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)7880 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
7881 CONSCRYPT_UNUSED jobject ssl_holder,
7882 jlong ssl_session_address) {
7883 CHECK_ERROR_QUEUE_ON_RETURN;
7884 SSL* ssl = to_SSL(env, ssl_address, true);
7885 if (ssl == nullptr) {
7886 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
7887 return;
7888 }
7889
7890 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7891 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7892 if (ssl_session == nullptr) {
7893 return;
7894 }
7895
7896 int ret = SSL_set_session(ssl, ssl_session);
7897 if (ret != 1) {
7898 /*
7899 * Translate the error, and throw if it turns out to be a real
7900 * problem.
7901 */
7902 int sslErrorCode = SSL_get_error(ssl, ret);
7903 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7904 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
7905 "SSL session set");
7906 }
7907 }
7908 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
7909 ret);
7910 }
7911
7912 /**
7913 * Sets the ciphers suites that are enabled in the SSL
7914 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)7915 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
7916 CONSCRYPT_UNUSED jobject ssl_holder,
7917 jboolean creation_enabled) {
7918 CHECK_ERROR_QUEUE_ON_RETURN;
7919 SSL* ssl = to_SSL(env, ssl_address, true);
7920 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
7921 creation_enabled);
7922 if (ssl == nullptr) {
7923 return;
7924 }
7925
7926 if (creation_enabled) {
7927 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7928 } else {
7929 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
7930 }
7931 }
7932
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7933 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
7934 CONSCRYPT_UNUSED jobject ssl_holder) {
7935 CHECK_ERROR_QUEUE_ON_RETURN;
7936 SSL* ssl = to_SSL(env, ssl_address, true);
7937 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
7938 if (ssl == nullptr) {
7939 return JNI_FALSE;
7940 }
7941
7942 int reused = SSL_session_reused(ssl);
7943 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
7944 return static_cast<jboolean>(reused);
7945 }
7946
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7947 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
7948 CONSCRYPT_UNUSED jobject ssl_holder) {
7949 CHECK_ERROR_QUEUE_ON_RETURN;
7950 SSL* ssl = to_SSL(env, ssl_address, true);
7951 JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
7952 if (ssl == nullptr) {
7953 return;
7954 }
7955
7956 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
7957 }
7958
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)7959 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
7960 CONSCRYPT_UNUSED jobject ssl_holder,
7961 jstring hostname) {
7962 CHECK_ERROR_QUEUE_ON_RETURN;
7963 SSL* ssl = to_SSL(env, ssl_address, true);
7964 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
7965 if (ssl == nullptr) {
7966 return;
7967 }
7968
7969 ScopedUtfChars hostnameChars(env, hostname);
7970 if (hostnameChars.c_str() == nullptr) {
7971 return;
7972 }
7973 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
7974 hostnameChars.c_str());
7975
7976 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7977 if (ret != 1) {
7978 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7979 "Error setting host name");
7980 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7981 return;
7982 }
7983 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7984 }
7985
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7986 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
7987 CONSCRYPT_UNUSED jobject ssl_holder) {
7988 CHECK_ERROR_QUEUE_ON_RETURN;
7989 SSL* ssl = to_SSL(env, ssl_address, true);
7990 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7991 if (ssl == nullptr) {
7992 return nullptr;
7993 }
7994 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7995 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7996 return env->NewStringUTF(servername);
7997 }
7998
7999 /**
8000 * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8001 * which should take precedence.
8002 */
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)8003 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8004 const unsigned char* primary,
8005 const unsigned int primaryLength,
8006 const unsigned char* secondary,
8007 const unsigned int secondaryLength) {
8008 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8009
8010 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8011 secondaryLength);
8012 switch (status) {
8013 case OPENSSL_NPN_NEGOTIATED:
8014 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8015 return SSL_TLSEXT_ERR_OK;
8016 break;
8017 case OPENSSL_NPN_UNSUPPORTED:
8018 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8019 break;
8020 case OPENSSL_NPN_NO_OVERLAP:
8021 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8022 break;
8023 }
8024 return SSL_TLSEXT_ERR_NOACK;
8025 }
8026
8027 /**
8028 * Calls out to an application-provided selector to choose the ALPN protocol.
8029 */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8030 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8031 unsigned char** out,
8032 unsigned char* outLen, const unsigned char* in,
8033 const unsigned int inLen) {
8034 // Copy the input array.
8035 ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8036 if (protocols.get() == nullptr) {
8037 JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8038 return SSL_TLSEXT_ERR_NOACK;
8039 }
8040 env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8041 reinterpret_cast<const jbyte*>(in));
8042
8043 // Invoke the selection method.
8044 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
8045 jmethodID methodID = env->GetMethodID(cls, "selectApplicationProtocol", "([B)I");
8046 jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8047
8048 if (offset < 0) {
8049 JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8050 return SSL_TLSEXT_ERR_NOACK;
8051 }
8052
8053 // Point the output to the selected protocol.
8054 *outLen = *(in + offset);
8055 *out = const_cast<unsigned char*>(in + offset + 1);
8056
8057 return SSL_TLSEXT_ERR_OK;
8058 }
8059
8060 /**
8061 * Callback for the server to select an ALPN protocol.
8062 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8063 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8064 const unsigned char* in, unsigned int inLen, void*) {
8065 JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8066
8067 AppData* appData = toAppData(ssl);
8068 if (appData == nullptr) {
8069 JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8070 return SSL_TLSEXT_ERR_NOACK;
8071 }
8072 JNIEnv* env = appData->env;
8073 if (env == nullptr) {
8074 CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8075 JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8076 return SSL_TLSEXT_ERR_NOACK;
8077 }
8078
8079 if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8080 !appData->hasApplicationProtocolSelector)) {
8081 if (out != nullptr && outLen != nullptr) {
8082 *out = nullptr;
8083 *outLen = 0;
8084 }
8085 JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8086 return SSL_TLSEXT_ERR_NOACK;
8087 }
8088
8089 if (appData->hasApplicationProtocolSelector) {
8090 return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8091 const_cast<unsigned char**>(out), outLen, in, inLen);
8092 }
8093
8094 return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8095 reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8096 static_cast<unsigned int>(appData->applicationProtocolsLength),
8097 in, inLen);
8098 }
8099
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8100 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8101 CONSCRYPT_UNUSED jobject ssl_holder) {
8102 CHECK_ERROR_QUEUE_ON_RETURN;
8103 SSL* ssl = to_SSL(env, ssl_address, true);
8104 JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8105 if (ssl == nullptr) {
8106 return nullptr;
8107 }
8108 const jbyte* protocol;
8109 unsigned int protocolLength;
8110 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8111 &protocolLength);
8112 if (protocolLength == 0) {
8113 return nullptr;
8114 }
8115 jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8116 if (result != nullptr) {
8117 env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8118 }
8119 return result;
8120 }
8121
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8122 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8123 CONSCRYPT_UNUSED jobject ssl_holder,
8124 jboolean client_mode, jbyteArray protocols) {
8125 CHECK_ERROR_QUEUE_ON_RETURN;
8126 SSL* ssl = to_SSL(env, ssl_address, true);
8127 if (ssl == nullptr) {
8128 return;
8129 }
8130 AppData* appData = toAppData(ssl);
8131 if (appData == nullptr) {
8132 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8133 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8134 return;
8135 }
8136
8137 if (protocols != nullptr) {
8138 if (client_mode) {
8139 ScopedByteArrayRO protosBytes(env, protocols);
8140 if (protosBytes.get() == nullptr) {
8141 JNI_TRACE(
8142 "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8143 "protosBytes == null",
8144 ssl, protocols);
8145 return;
8146 }
8147
8148 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8149 int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8150 if (ret != 0) {
8151 conscrypt::jniutil::throwSSLExceptionStr(env,
8152 "Unable to set ALPN protocols for client");
8153 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8154 return;
8155 }
8156 } else {
8157 // Server mode - configure the ALPN protocol selection callback.
8158 if (!appData->setApplicationProtocols(env, protocols)) {
8159 conscrypt::jniutil::throwSSLExceptionStr(env,
8160 "Unable to set ALPN protocols for server");
8161 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8162 return;
8163 }
8164 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8165 }
8166 }
8167 }
8168
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8169 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8170 CONSCRYPT_UNUSED jobject ssl_holder,
8171 jboolean hasSelector) {
8172 CHECK_ERROR_QUEUE_ON_RETURN;
8173 SSL* ssl = to_SSL(env, ssl_address, true);
8174 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8175 hasSelector);
8176 if (ssl == nullptr) {
8177 return;
8178 }
8179 AppData* appData = toAppData(ssl);
8180 if (appData == nullptr) {
8181 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8182 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8183 return;
8184 }
8185
8186 appData->hasApplicationProtocolSelector = hasSelector;
8187 if (hasSelector) {
8188 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8189 }
8190 }
8191
8192 /**
8193 * Perform SSL handshake
8194 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8195 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8196 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8197 jobject shc, jint timeout_millis) {
8198 CHECK_ERROR_QUEUE_ON_RETURN;
8199 SSL* ssl = to_SSL(env, ssl_address, true);
8200 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8201 shc, timeout_millis);
8202 if (ssl == nullptr) {
8203 return;
8204 }
8205 if (fdObject == nullptr) {
8206 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8207 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8208 return;
8209 }
8210 if (shc == nullptr) {
8211 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8212 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8213 ssl);
8214 return;
8215 }
8216
8217 NetFd fd(env, fdObject);
8218 if (fd.isClosed()) {
8219 // SocketException thrown by NetFd.isClosed
8220 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8221 return;
8222 }
8223
8224 int ret = SSL_set_fd(ssl, fd.get());
8225 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8226
8227 if (ret != 1) {
8228 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8229 "Error setting the file descriptor");
8230 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8231 return;
8232 }
8233
8234 /*
8235 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8236 * forever and we can use select() to find out if the socket is ready.
8237 */
8238 if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8239 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8240 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8241 return;
8242 }
8243
8244 AppData* appData = toAppData(ssl);
8245 if (appData == nullptr) {
8246 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8247 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8248 return;
8249 }
8250
8251 ret = 0;
8252 SslError sslError;
8253 while (appData->aliveAndKicking) {
8254 errno = 0;
8255
8256 if (!appData->setCallbackState(env, shc, fdObject)) {
8257 // SocketException thrown by NetFd.isClosed
8258 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8259 return;
8260 }
8261 ret = SSL_do_handshake(ssl);
8262 appData->clearCallbackState();
8263 // cert_verify_callback threw exception
8264 if (env->ExceptionCheck()) {
8265 ERR_clear_error();
8266 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8267 return;
8268 }
8269 // success case
8270 if (ret == 1) {
8271 break;
8272 }
8273 // retry case
8274 if (errno == EINTR) {
8275 continue;
8276 }
8277 // error case
8278 sslError.reset(ssl, ret);
8279 JNI_TRACE(
8280 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8281 "timeout_millis=%d",
8282 ssl, ret, errno, sslError.get(), timeout_millis);
8283
8284 /*
8285 * If SSL_do_handshake doesn't succeed due to the socket being
8286 * either unreadable or unwritable, we use sslSelect to
8287 * wait for it to become ready. If that doesn't happen
8288 * before the specified timeout or an error occurs, we
8289 * cancel the handshake. Otherwise we try the SSL_connect
8290 * again.
8291 */
8292 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8293 appData->waitingThreads++;
8294 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8295
8296 if (selectResult == THROWN_EXCEPTION) {
8297 // SocketException thrown by NetFd.isClosed
8298 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8299 return;
8300 }
8301 if (selectResult == -1) {
8302 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8303 env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8304 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8305 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8306 ssl);
8307 return;
8308 }
8309 if (selectResult == 0) {
8310 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8311 ERR_clear_error();
8312 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8313 ssl);
8314 return;
8315 }
8316 } else {
8317 // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8318 break;
8319 }
8320 }
8321
8322 // clean error. See SSL_do_handshake(3SSL) man page.
8323 if (ret == 0) {
8324 /*
8325 * The other side closed the socket before the handshake could be
8326 * completed, but everything is within the bounds of the TLS protocol.
8327 * We still might want to find out the real reason of the failure.
8328 */
8329 if (sslError.get() == SSL_ERROR_NONE ||
8330 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8331 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8332 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8333 } else {
8334 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8335 env, ssl, sslError.release(), "SSL handshake terminated",
8336 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8337 }
8338 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8339 return;
8340 }
8341
8342 // unclean error. See SSL_do_handshake(3SSL) man page.
8343 if (ret < 0) {
8344 /*
8345 * Translate the error and throw exception. We are sure it is an error
8346 * at this point.
8347 */
8348 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8349 env, ssl, sslError.release(), "SSL handshake aborted",
8350 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8351 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
8352 return;
8353 }
8354 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
8355 }
8356
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8357 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
8358 CONSCRYPT_UNUSED jobject ssl_holder) {
8359 CHECK_ERROR_QUEUE_ON_RETURN;
8360 SSL* ssl = to_SSL(env, ssl_address, true);
8361 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
8362 if (ssl == nullptr) {
8363 return nullptr;
8364 }
8365 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
8366 if (cipher == nullptr) {
8367 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
8368 return nullptr;
8369 }
8370 const char* name = SSL_CIPHER_standard_name(cipher);
8371 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
8372 return env->NewStringUTF(name);
8373 }
8374
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8375 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
8376 CONSCRYPT_UNUSED jobject ssl_holder) {
8377 CHECK_ERROR_QUEUE_ON_RETURN;
8378 SSL* ssl = to_SSL(env, ssl_address, true);
8379 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
8380 if (ssl == nullptr) {
8381 return nullptr;
8382 }
8383 const char* protocol = SSL_get_version(ssl);
8384 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
8385 return env->NewStringUTF(protocol);
8386 }
8387
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8388 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
8389 CONSCRYPT_UNUSED jobject ssl_holder) {
8390 CHECK_ERROR_QUEUE_ON_RETURN;
8391 SSL* ssl = to_SSL(env, ssl_address, true);
8392 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
8393 if (ssl == nullptr) {
8394 return nullptr;
8395 }
8396
8397 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
8398 if (chain == nullptr) {
8399 return nullptr;
8400 }
8401
8402 ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
8403 if (array.get() == nullptr) {
8404 return nullptr;
8405 }
8406
8407 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
8408 return array.release();
8409 }
8410
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)8411 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8412 SslError* sslError, int read_timeout_millis) {
8413 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8414
8415 if (len == 0) {
8416 // Don't bother doing anything in this case.
8417 return 0;
8418 }
8419
8420 BIO* rbio = SSL_get_rbio(ssl);
8421 BIO* wbio = SSL_get_wbio(ssl);
8422
8423 AppData* appData = toAppData(ssl);
8424 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8425 if (appData == nullptr) {
8426 return THROW_SSLEXCEPTION;
8427 }
8428
8429 while (appData->aliveAndKicking) {
8430 errno = 0;
8431
8432 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8433
8434 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8435 !SSL_renegotiate_pending(ssl)) {
8436 JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
8437 SSL_state_string_long(ssl));
8438 return THROW_SSLEXCEPTION;
8439 }
8440
8441 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8442
8443 if (!appData->setCallbackState(env, shc, fdObject)) {
8444 return THROWN_EXCEPTION;
8445 }
8446 int result = SSL_read(ssl, buf, len);
8447 appData->clearCallbackState();
8448 // callbacks can happen if server requests renegotiation
8449 if (env->ExceptionCheck()) {
8450 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8451 return THROWN_EXCEPTION;
8452 }
8453 sslError->reset(ssl, result);
8454
8455 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
8456 if (conscrypt::trace::kWithJniTraceData) {
8457 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8458 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8459 size_t n = result - i;
8460 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8461 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8462 }
8463 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8464 }
8465 }
8466
8467 // If we have been successful in moving data around, check whether it
8468 // might make sense to wake up other blocked threads, so they can give
8469 // it a try, too.
8470 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8471 appData->waitingThreads > 0) {
8472 sslNotify(appData);
8473 }
8474
8475 // If we are blocked by the underlying socket, tell the world that
8476 // there will be one more waiting thread now.
8477 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8478 appData->waitingThreads++;
8479 }
8480
8481 appDataLock.unlock();
8482
8483 switch (sslError->get()) {
8484 // Successfully read at least one byte.
8485 case SSL_ERROR_NONE: {
8486 return result;
8487 }
8488
8489 // Read zero bytes. End of stream reached.
8490 case SSL_ERROR_ZERO_RETURN: {
8491 return -1;
8492 }
8493
8494 // Need to wait for availability of underlying layer, then retry.
8495 case SSL_ERROR_WANT_READ:
8496 case SSL_ERROR_WANT_WRITE: {
8497 int selectResult =
8498 sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
8499 if (selectResult == THROWN_EXCEPTION) {
8500 return THROWN_EXCEPTION;
8501 }
8502 if (selectResult == -1) {
8503 return THROW_SSLEXCEPTION;
8504 }
8505 if (selectResult == 0) {
8506 return THROW_SOCKETTIMEOUTEXCEPTION;
8507 }
8508
8509 break;
8510 }
8511
8512 // A problem occurred during a system call, but this is not
8513 // necessarily an error.
8514 case SSL_ERROR_SYSCALL: {
8515 // Connection closed without proper shutdown. Tell caller we
8516 // have reached end-of-stream.
8517 if (result == 0) {
8518 return -1;
8519 }
8520
8521 // System call has been interrupted. Simply retry.
8522 if (errno == EINTR) {
8523 break;
8524 }
8525
8526 // Note that for all other system call errors we fall through
8527 // to the default case, which results in an Exception.
8528 FALLTHROUGH_INTENDED;
8529 }
8530
8531 // Everything else is basically an error.
8532 default: { return THROW_SSLEXCEPTION; }
8533 }
8534 }
8535
8536 return -1;
8537 }
8538
8539 /**
8540 * OpenSSL read function (2): read into buffer at offset n chunks.
8541 * Returns the number of bytes read (success) or value <= 0 (failure).
8542 */
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)8543 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
8544 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8545 jobject shc, jbyteArray b, jint offset, jint len,
8546 jint read_timeout_millis) {
8547 CHECK_ERROR_QUEUE_ON_RETURN;
8548 SSL* ssl = to_SSL(env, ssl_address, true);
8549 JNI_TRACE(
8550 "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
8551 "read_timeout_millis=%d",
8552 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8553 if (ssl == nullptr) {
8554 return 0;
8555 }
8556 if (fdObject == nullptr) {
8557 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8558 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8559 return 0;
8560 }
8561 if (shc == nullptr) {
8562 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8563 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8564 return 0;
8565 }
8566 if (b == nullptr) {
8567 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8568 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
8569 return 0;
8570 }
8571
8572 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8573 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8574 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8575 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
8576 return 0;
8577 }
8578
8579 SslError sslError;
8580 int ret;
8581 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8582 if (len <= 1024) {
8583 // Allocate small buffers on the stack for performance.
8584 jbyte buf[1024];
8585 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
8586 read_timeout_millis);
8587 if (ret > 0) {
8588 // Don't bother applying changes if issues were encountered.
8589 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
8590 }
8591 } else {
8592 // Allocate larger buffers on the heap.
8593 // ARRAY_CHUNK_INVALID above ensures that len >= 0.
8594 jint remaining = len;
8595 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8596 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8597 // TODO(flooey): Use new(std::nothrow).
8598 if (buf.get() == nullptr) {
8599 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8600 return 0;
8601 }
8602 // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
8603 // by the number of internal calls to sslRead() below.
8604 ret = 0;
8605 while (remaining > 0) {
8606 jint temp_ret;
8607 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8608 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
8609 chunk_size, &sslError, read_timeout_millis);
8610 if (temp_ret < 0) {
8611 if (ret > 0) {
8612 // We've already read some bytes; attempt to preserve them if this is an
8613 // "expected" error.
8614 if (temp_ret == -1) {
8615 // EOF
8616 break;
8617 } else if (temp_ret == THROWN_EXCEPTION) {
8618 // FD closed. Subsequent calls to sslRead should reproduce the
8619 // exception.
8620 env->ExceptionClear();
8621 break;
8622 }
8623 }
8624 // An error was encountered. Handle below.
8625 ret = temp_ret;
8626 break;
8627 }
8628 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
8629 if (env->ExceptionCheck()) {
8630 // Error committing changes to JVM.
8631 return -1;
8632 }
8633 // Accumulate bytes read.
8634 ret += temp_ret;
8635 offset += temp_ret;
8636 remaining -= temp_ret;
8637 if (temp_ret < chunk_size) {
8638 // sslRead isn't able to fulfill our request right now.
8639 break;
8640 }
8641 }
8642 }
8643 } else {
8644 ScopedByteArrayRW bytes(env, b);
8645 if (bytes.get() == nullptr) {
8646 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8647 return 0;
8648 }
8649
8650 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8651 &sslError, read_timeout_millis);
8652 }
8653
8654 int result;
8655 switch (ret) {
8656 case THROW_SSLEXCEPTION:
8657 // See sslRead() regarding improper failure to handle normal cases.
8658 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8659 "Read error");
8660 result = -1;
8661 break;
8662 case THROW_SOCKETTIMEOUTEXCEPTION:
8663 conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
8664 result = -1;
8665 break;
8666 case THROWN_EXCEPTION:
8667 // SocketException thrown by NetFd.isClosed
8668 // or RuntimeException thrown by callback
8669 result = -1;
8670 break;
8671 default:
8672 result = ret;
8673 break;
8674 }
8675
8676 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8677 return result;
8678 }
8679
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)8680 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8681 SslError* sslError, int write_timeout_millis) {
8682 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
8683 write_timeout_millis);
8684
8685 if (len == 0) {
8686 // Don't bother doing anything in this case.
8687 return 0;
8688 }
8689
8690 BIO* rbio = SSL_get_rbio(ssl);
8691 BIO* wbio = SSL_get_wbio(ssl);
8692
8693 AppData* appData = toAppData(ssl);
8694 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8695 if (appData == nullptr) {
8696 return THROW_SSLEXCEPTION;
8697 }
8698
8699 int count = len;
8700
8701 while (appData->aliveAndKicking && len > 0) {
8702 errno = 0;
8703
8704 std::unique_lock<std::mutex> appDataLock(appData->mutex);
8705
8706 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
8707 !SSL_renegotiate_pending(ssl)) {
8708 JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
8709 SSL_state_string_long(ssl));
8710 return THROW_SSLEXCEPTION;
8711 }
8712
8713 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8714
8715 if (!appData->setCallbackState(env, shc, fdObject)) {
8716 return THROWN_EXCEPTION;
8717 }
8718 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
8719 int result = SSL_write(ssl, buf, len);
8720 appData->clearCallbackState();
8721 // callbacks can happen if server requests renegotiation
8722 if (env->ExceptionCheck()) {
8723 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8724 return THROWN_EXCEPTION;
8725 }
8726 sslError->reset(ssl, result);
8727
8728 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
8729 if (conscrypt::trace::kWithJniTraceData) {
8730 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
8731 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
8732 size_t n = result - i;
8733 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
8734 n = conscrypt::trace::kWithJniTraceDataChunkSize;
8735 }
8736 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
8737 }
8738 }
8739
8740 // If we have been successful in moving data around, check whether it
8741 // might make sense to wake up other blocked threads, so they can give
8742 // it a try, too.
8743 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
8744 appData->waitingThreads > 0) {
8745 sslNotify(appData);
8746 }
8747
8748 // If we are blocked by the underlying socket, tell the world that
8749 // there will be one more waiting thread now.
8750 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
8751 appData->waitingThreads++;
8752 }
8753
8754 appDataLock.unlock();
8755
8756 switch (sslError->get()) {
8757 // Successfully wrote at least one byte.
8758 case SSL_ERROR_NONE: {
8759 buf += result;
8760 len -= result;
8761 break;
8762 }
8763
8764 // Wrote zero bytes. End of stream reached.
8765 case SSL_ERROR_ZERO_RETURN: {
8766 return -1;
8767 }
8768
8769 // Need to wait for availability of underlying layer, then retry.
8770 // The concept of a write timeout doesn't really make sense, and
8771 // it's also not standard Java behavior, so we wait forever here.
8772 case SSL_ERROR_WANT_READ:
8773 case SSL_ERROR_WANT_WRITE: {
8774 int selectResult =
8775 sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
8776 if (selectResult == THROWN_EXCEPTION) {
8777 return THROWN_EXCEPTION;
8778 }
8779 if (selectResult == -1) {
8780 return THROW_SSLEXCEPTION;
8781 }
8782 if (selectResult == 0) {
8783 return THROW_SOCKETTIMEOUTEXCEPTION;
8784 }
8785
8786 break;
8787 }
8788
8789 // A problem occurred during a system call, but this is not
8790 // necessarily an error.
8791 case SSL_ERROR_SYSCALL: {
8792 // Connection closed without proper shutdown. Tell caller we
8793 // have reached end-of-stream.
8794 if (result == 0) {
8795 return -1;
8796 }
8797
8798 // System call has been interrupted. Simply retry.
8799 if (errno == EINTR) {
8800 break;
8801 }
8802
8803 // Note that for all other system call errors we fall through
8804 // to the default case, which results in an Exception.
8805 FALLTHROUGH_INTENDED;
8806 }
8807
8808 // Everything else is basically an error.
8809 default: { return THROW_SSLEXCEPTION; }
8810 }
8811 }
8812 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
8813
8814 return count;
8815 }
8816
8817 /**
8818 * OpenSSL write function (2): write into buffer at offset n chunks.
8819 */
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)8820 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
8821 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8822 jobject shc, jbyteArray b, jint offset, jint len,
8823 jint write_timeout_millis) {
8824 CHECK_ERROR_QUEUE_ON_RETURN;
8825 SSL* ssl = to_SSL(env, ssl_address, true);
8826 JNI_TRACE(
8827 "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
8828 "write_timeout_millis=%d",
8829 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
8830 if (ssl == nullptr) {
8831 return;
8832 }
8833 if (fdObject == nullptr) {
8834 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8835 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
8836 return;
8837 }
8838 if (shc == nullptr) {
8839 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8840 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
8841 return;
8842 }
8843 if (b == nullptr) {
8844 conscrypt::jniutil::throwNullPointerException(env, "b == null");
8845 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
8846 return;
8847 }
8848
8849 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
8850 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
8851 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
8852 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
8853 return;
8854 }
8855
8856 SslError sslError;
8857 int ret;
8858 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
8859 if (len <= 1024) {
8860 jbyte buf[1024];
8861 env->GetByteArrayRegion(b, offset, len, buf);
8862 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
8863 &sslError, write_timeout_millis);
8864 } else {
8865 // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
8866 jint remaining = len;
8867 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
8868 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
8869 if (buf.get() == nullptr) {
8870 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
8871 return;
8872 }
8873 while (remaining > 0) {
8874 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
8875 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
8876 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
8877 chunk_size, &sslError, write_timeout_millis);
8878 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
8879 ret == THROWN_EXCEPTION) {
8880 // Encountered an error. Terminate early and handle below.
8881 break;
8882 }
8883 offset += ret;
8884 remaining -= ret;
8885 }
8886 }
8887 } else {
8888 ScopedByteArrayRO bytes(env, b);
8889 if (bytes.get() == nullptr) {
8890 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
8891 return;
8892 }
8893 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
8894 len, &sslError, write_timeout_millis);
8895 }
8896
8897 switch (ret) {
8898 case THROW_SSLEXCEPTION:
8899 // See sslWrite() regarding improper failure to handle normal cases.
8900 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8901 "Write error");
8902 break;
8903 case THROW_SOCKETTIMEOUTEXCEPTION:
8904 conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
8905 break;
8906 case THROWN_EXCEPTION:
8907 // SocketException thrown by NetFd.isClosed
8908 break;
8909 default:
8910 break;
8911 }
8912 }
8913
8914 /**
8915 * Interrupt any pending I/O before closing the socket.
8916 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8917 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
8918 CONSCRYPT_UNUSED jobject ssl_holder) {
8919 CHECK_ERROR_QUEUE_ON_RETURN;
8920 SSL* ssl = to_SSL(env, ssl_address, false);
8921 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
8922 if (ssl == nullptr) {
8923 return;
8924 }
8925
8926 /*
8927 * Mark the connection as quasi-dead, then send something to the emergency
8928 * file descriptor, so any blocking select() calls are woken up.
8929 */
8930 AppData* appData = toAppData(ssl);
8931 if (appData != nullptr) {
8932 appData->aliveAndKicking = false;
8933
8934 // At most two threads can be waiting.
8935 sslNotify(appData);
8936 sslNotify(appData);
8937 }
8938 }
8939
8940 /**
8941 * OpenSSL close SSL socket function.
8942 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)8943 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
8944 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8945 jobject shc) {
8946 CHECK_ERROR_QUEUE_ON_RETURN;
8947 SSL* ssl = to_SSL(env, ssl_address, false);
8948 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
8949 if (ssl == nullptr) {
8950 return;
8951 }
8952 if (fdObject == nullptr) {
8953 return;
8954 }
8955 if (shc == nullptr) {
8956 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8957 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
8958 return;
8959 }
8960
8961 AppData* appData = toAppData(ssl);
8962 if (appData != nullptr) {
8963 if (!appData->setCallbackState(env, shc, fdObject)) {
8964 // SocketException thrown by NetFd.isClosed
8965 ERR_clear_error();
8966 return;
8967 }
8968
8969 /*
8970 * Try to make socket blocking again. OpenSSL literature recommends this.
8971 */
8972 int fd = SSL_get_fd(ssl);
8973 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
8974 #ifndef _WIN32
8975 if (fd != -1) {
8976 conscrypt::netutil::setBlocking(fd, true);
8977 }
8978 #endif
8979
8980 int ret = SSL_shutdown(ssl);
8981 appData->clearCallbackState();
8982 // callbacks can happen if server requests renegotiation
8983 if (env->ExceptionCheck()) {
8984 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
8985 return;
8986 }
8987 switch (ret) {
8988 case 0:
8989 /*
8990 * Shutdown was not successful (yet), but there also
8991 * is no error. Since we can't know whether the remote
8992 * server is actually still there, and we don't want to
8993 * get stuck forever in a second SSL_shutdown() call, we
8994 * simply return. This is not security a problem as long
8995 * as we close the underlying socket, which we actually
8996 * do, because that's where we are just coming from.
8997 */
8998 break;
8999 case 1:
9000 /*
9001 * Shutdown was successful. We can safely return. Hooray!
9002 */
9003 break;
9004 default:
9005 /*
9006 * Everything else is a real error condition. We should
9007 * let the Java layer know about this by throwing an
9008 * exception.
9009 */
9010 int sslError = SSL_get_error(ssl, ret);
9011 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9012 "SSL shutdown failed");
9013 break;
9014 }
9015 }
9016
9017 ERR_clear_error();
9018 }
9019
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9020 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9021 CONSCRYPT_UNUSED jobject ssl_holder) {
9022 CHECK_ERROR_QUEUE_ON_RETURN;
9023 const SSL* ssl = to_SSL(env, ssl_address, true);
9024 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9025 if (ssl == nullptr) {
9026 return 0;
9027 }
9028
9029 int status = SSL_get_shutdown(ssl);
9030 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9031 return static_cast<jint>(status);
9032 }
9033
9034 /**
9035 * public static native void SSL_free(long ssl);
9036 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9037 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9038 CONSCRYPT_UNUSED jobject ssl_holder) {
9039 CHECK_ERROR_QUEUE_ON_RETURN;
9040 SSL* ssl = to_SSL(env, ssl_address, true);
9041 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9042 if (ssl == nullptr) {
9043 return;
9044 }
9045
9046 AppData* appData = toAppData(ssl);
9047 SSL_set_app_data(ssl, nullptr);
9048 delete appData;
9049 SSL_free(ssl);
9050 }
9051
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9052 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9053 unsigned int length;
9054 const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9055 JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9056 if (id && length > 0) {
9057 jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9058 if (result != nullptr) {
9059 const jbyte* src = reinterpret_cast<const jbyte*>(id);
9060 env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9061 }
9062 return result;
9063 }
9064 return nullptr;
9065 }
9066
9067 /**
9068 * Gets and returns in a byte array the ID of the actual SSL session.
9069 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9070 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9071 jlong ssl_session_address) {
9072 CHECK_ERROR_QUEUE_ON_RETURN;
9073 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9074 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9075 if (ssl_session == nullptr) {
9076 return nullptr;
9077 }
9078 jbyteArray result = get_session_id(env, ssl_session);
9079 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9080 return result;
9081 }
9082
9083 /**
9084 * Gets and returns in a long integer the creation's time of the
9085 * actual SSL session.
9086 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9087 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9088 CHECK_ERROR_QUEUE_ON_RETURN;
9089 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9090 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9091 if (ssl_session == nullptr) {
9092 return 0;
9093 }
9094 // result must be jlong, not long or *1000 will overflow
9095 jlong result = SSL_SESSION_get_time(ssl_session);
9096 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9097 // NOLINTNEXTLINE(runtime/int)
9098 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9099 (long long)result); // NOLINT(runtime/int)
9100 return result;
9101 }
9102
9103 /**
9104 * Gets and returns in a long integer the creation's time of the
9105 * actual SSL session.
9106 */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9107 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9108 CONSCRYPT_UNUSED jobject ssl_holder) {
9109 CHECK_ERROR_QUEUE_ON_RETURN;
9110 SSL* ssl = to_SSL(env, ssl_address, true);
9111 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9112 if (ssl == nullptr) {
9113 return 0;
9114 }
9115
9116 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9117 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9118 if (ssl_session == nullptr) {
9119 // BoringSSL does not protect against a NULL session.
9120 return 0;
9121 }
9122 // result must be jlong, not long or *1000 will overflow
9123 jlong result = SSL_SESSION_get_time(ssl_session);
9124 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9125 // NOLINTNEXTLINE(runtime/int)
9126 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9127 return result;
9128 }
9129
9130 /**
9131 * Sets the timeout on the SSL session.
9132 */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9133 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9134 CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9135 CHECK_ERROR_QUEUE_ON_RETURN;
9136 SSL* ssl = to_SSL(env, ssl_address, true);
9137 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9138 if (ssl == nullptr) {
9139 return 0;
9140 }
9141
9142 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9143 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9144 if (ssl_session == nullptr) {
9145 // BoringSSL does not protect against a NULL session.
9146 return 0;
9147 }
9148
9149 // Convert to seconds
9150 static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9151 uint32_t timeout = static_cast<uint32_t>(
9152 std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9153 return SSL_set_timeout(ssl_session, timeout);
9154 }
9155
9156 /**
9157 * Gets the timeout for the SSL session.
9158 */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9159 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9160 CONSCRYPT_UNUSED jobject ssl_holder) {
9161 CHECK_ERROR_QUEUE_ON_RETURN;
9162 SSL* ssl = to_SSL(env, ssl_address, true);
9163 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9164 if (ssl == nullptr) {
9165 return 0;
9166 }
9167
9168 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9169 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9170 if (ssl_session == nullptr) {
9171 // BoringSSL does not protect against a NULL session.
9172 return 0;
9173 }
9174
9175 jlong result = SSL_get_timeout(ssl_session);
9176 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9177 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9178 (long long)result) // NOLINT(runtime/int);
9179 return result;
9180 }
9181
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9182 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9183 jint signatureAlg) {
9184 CHECK_ERROR_QUEUE_ON_RETURN;
9185 return SSL_get_signature_algorithm_key_type(signatureAlg);
9186 }
9187
9188 /**
9189 * Gets the timeout for the SSL session.
9190 */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9191 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9192 CHECK_ERROR_QUEUE_ON_RETURN;
9193 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9194 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9195 if (ssl_session == nullptr) {
9196 return 0;
9197 }
9198
9199 return SSL_get_timeout(ssl_session);
9200 }
9201
9202 /**
9203 * Gets the ID for the SSL session, or null if no session is currently available.
9204 */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9205 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9206 CONSCRYPT_UNUSED jobject ssl_holder) {
9207 CHECK_ERROR_QUEUE_ON_RETURN;
9208 SSL* ssl = to_SSL(env, ssl_address, true);
9209 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9210 if (ssl == nullptr) {
9211 return nullptr;
9212 }
9213
9214 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9215 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9216 if (ssl_session == nullptr) {
9217 return nullptr;
9218 }
9219 jbyteArray result = get_session_id(env, ssl_session);
9220 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9221 return result;
9222 }
9223
9224 /**
9225 * Gets and returns in a string the version of the SSL protocol. If it
9226 * returns the string "unknown" it means that no connection is established.
9227 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9228 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9229 jlong ssl_session_address) {
9230 CHECK_ERROR_QUEUE_ON_RETURN;
9231 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9232 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9233 if (ssl_session == nullptr) {
9234 return nullptr;
9235 }
9236 const char* protocol = SSL_SESSION_get_version(ssl_session);
9237 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9238 return env->NewStringUTF(protocol);
9239 }
9240
9241 /**
9242 * Gets and returns in a string the cipher negotiated for the SSL session.
9243 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9244 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9245 CHECK_ERROR_QUEUE_ON_RETURN;
9246 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9247 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9248 if (ssl_session == nullptr) {
9249 return nullptr;
9250 }
9251 const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9252 const char* name = SSL_CIPHER_standard_name(cipher);
9253 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9254 return env->NewStringUTF(name);
9255 }
9256
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9257 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9258 jlong ssl_session_address) {
9259 CHECK_ERROR_QUEUE_ON_RETURN;
9260 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9261 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9262 if (ssl_session == nullptr) {
9263 return JNI_FALSE;
9264 }
9265 int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9266 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9267 single_use);
9268 return single_use ? JNI_TRUE : JNI_FALSE;
9269 }
9270
9271 /**
9272 * Increments the reference count of the session.
9273 */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9274 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9275 CHECK_ERROR_QUEUE_ON_RETURN;
9276 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9277 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9278 if (ssl_session == nullptr) {
9279 return;
9280 }
9281 SSL_SESSION_up_ref(ssl_session);
9282 }
9283
9284 /**
9285 * Frees the SSL session.
9286 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9287 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9288 CHECK_ERROR_QUEUE_ON_RETURN;
9289 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9290 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9291 if (ssl_session == nullptr) {
9292 return;
9293 }
9294 SSL_SESSION_free(ssl_session);
9295 }
9296
9297 /**
9298 * Serializes the native state of the session (ID, cipher, and keys but
9299 * not certificates). Returns a byte[] containing the DER-encoded state.
9300 * See apache mod_ssl.
9301 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9302 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9303 CHECK_ERROR_QUEUE_ON_RETURN;
9304 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9305 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9306 if (ssl_session == nullptr) {
9307 return nullptr;
9308 }
9309 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9310 }
9311
9312 /**
9313 * Deserialize the session.
9314 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9315 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9316 CHECK_ERROR_QUEUE_ON_RETURN;
9317 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9318
9319 ScopedByteArrayRO bytes(env, javaBytes);
9320 if (bytes.get() == nullptr) {
9321 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9322 return 0;
9323 }
9324 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9325 // NOLINTNEXTLINE(runtime/int)
9326 SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9327
9328 if (ssl_session == nullptr ||
9329 ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9330 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9331 conscrypt::jniutil::throwIOException);
9332 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9333 return 0L;
9334 }
9335
9336 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9337 return reinterpret_cast<uintptr_t>(ssl_session);
9338 }
9339
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9340 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9341 CHECK_ERROR_QUEUE_ON_RETURN;
9342 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, true);
9343 const char* kx_name = nullptr;
9344
9345 kx_name = SSL_CIPHER_get_kx_name(cipher);
9346
9347 return env->NewStringUTF(kx_name);
9348 }
9349
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)9350 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
9351 CHECK_ERROR_QUEUE_ON_RETURN;
9352 ScopedUtfChars selector(env, selectorJava);
9353 if (selector.c_str() == nullptr) {
9354 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9355 "selector == null");
9356 return nullptr;
9357 }
9358
9359 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
9360
9361 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
9362 bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
9363
9364 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
9365 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
9366 "Unable to set SSL cipher list");
9367 return nullptr;
9368 }
9369 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
9370
9371 size_t size = sk_SSL_CIPHER_num(ciphers);
9372 ScopedLocalRef<jobjectArray> cipherNamesArray(
9373 env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
9374 nullptr));
9375 if (cipherNamesArray.get() == nullptr) {
9376 return nullptr;
9377 }
9378
9379 // Return an array of standard and OpenSSL name pairs.
9380 for (size_t i = 0; i < size; i++) {
9381 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
9382 ScopedLocalRef<jstring> cipherName(env,
9383 env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
9384 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
9385 cipherName.get());
9386
9387 ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
9388 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
9389 opensslName.get());
9390 }
9391
9392 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
9393 2 * size);
9394 return cipherNamesArray.release();
9395 }
9396
9397 /**
9398 * Compare the given CertID with a certificate and it's issuer.
9399 * True is returned if the CertID matches.
9400 */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)9401 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
9402 // Get the hash algorithm used by this CertID
9403 CBS hash_algorithm, hash;
9404 if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
9405 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
9406 return false;
9407 }
9408
9409 // Get the issuer's name hash from the CertID
9410 CBS issuer_name_hash;
9411 if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
9412 return false;
9413 }
9414
9415 // Get the issuer's key hash from the CertID
9416 CBS issuer_key_hash;
9417 if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
9418 return false;
9419 }
9420
9421 // Get the serial number from the CertID
9422 CBS serial;
9423 if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
9424 return false;
9425 }
9426
9427 // Compare the certificate's serial number with the one from the Cert ID
9428 const uint8_t* p = CBS_data(&serial);
9429 bssl::UniquePtr<ASN1_INTEGER> serial_number(
9430 c2i_ASN1_INTEGER(nullptr, &p,
9431 static_cast<long>(CBS_len(&serial)))); // NOLINT(runtime/int)
9432 const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
9433 if (serial_number.get() == nullptr ||
9434 ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
9435 return false;
9436 }
9437
9438 // Find the hash algorithm to be used
9439 const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
9440 if (digest == nullptr) {
9441 return false;
9442 }
9443
9444 // Hash the issuer's name and compare the hash with the one from the Cert ID
9445 uint8_t md[EVP_MAX_MD_SIZE];
9446 const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
9447 if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
9448 !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
9449 return false;
9450 }
9451
9452 // Same thing with the issuer's key
9453 const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
9454 if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
9455 static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
9456 nullptr) ||
9457 !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
9458 return false;
9459 }
9460
9461 return true;
9462 }
9463
9464 /**
9465 * Get a SingleResponse whose CertID matches the given certificate and issuer from a
9466 * SEQUENCE OF SingleResponse.
9467 *
9468 * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
9469 * error occured or no response matches the certificate, false is returned and |out_single_response|
9470 * is unchanged.
9471 */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)9472 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
9473 CBS* out_single_response) {
9474 // Iterate over all the SingleResponses, until one matches the certificate
9475 while (CBS_len(responses) > 0) {
9476 // Get the next available SingleResponse from the sequence
9477 CBS single_response;
9478 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
9479 return false;
9480 }
9481
9482 // Make a copy of the stream so we pass it back to the caller
9483 CBS single_response_original = single_response;
9484
9485 // Get the SingleResponse's CertID
9486 // If this fails ignore the current response and move to the next one
9487 CBS cert_id;
9488 if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
9489 continue;
9490 }
9491
9492 // Compare the CertID with the given certificate and issuer
9493 if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
9494 *out_single_response = single_response_original;
9495 return true;
9496 }
9497 }
9498
9499 return false;
9500 }
9501
9502 /**
9503 * Get the BasicOCSPResponse from an OCSPResponse.
9504 * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
9505 * returned.
9506 */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)9507 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
9508 CBS tagged_response_bytes, response_bytes, response_type, response;
9509
9510 // Get the ResponseBytes out of the OCSPResponse
9511 if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
9512 !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
9513 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9514 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
9515 return false;
9516 }
9517
9518 // Parse the response type and data out of the ResponseBytes
9519 if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
9520 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
9521 return false;
9522 }
9523
9524 // Only basic OCSP responses are supported
9525 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
9526 return false;
9527 }
9528
9529 // Parse the octet string as a BasicOCSPResponse
9530 return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
9531 }
9532
9533 /**
9534 * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
9535 * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
9536 * true is returned.
9537 */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)9538 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
9539 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
9540 CBS response_data;
9541 if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
9542 return false;
9543 }
9544
9545 // Skip the version, responderID and producedAt fields
9546 if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
9547 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
9548 !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
9549 !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
9550 return false;
9551 }
9552
9553 // Extract the list of SingleResponse.
9554 return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
9555 }
9556
9557 /**
9558 * Get the SEQUENCE OF Extension from a SingleResponse.
9559 * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
9560 * returned.
9561 */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)9562 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
9563 // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
9564 if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
9565 !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
9566 !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
9567 !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
9568 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
9569 return false;
9570 }
9571
9572 // Get the list of Extension
9573 return CBS_get_asn1(single_response, extensions,
9574 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
9575 }
9576
9577 /*
9578 public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
9579 long x509Ref, long issuerX509Ref);
9580 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)9581 static jbyteArray NativeCrypto_get_ocsp_single_extension(
9582 JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
9583 CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
9584 CHECK_ERROR_QUEUE_ON_RETURN;
9585 ScopedByteArrayRO ocspData(env, ocspDataBytes);
9586 if (ocspData.get() == nullptr) {
9587 return nullptr;
9588 }
9589
9590 CBS cbs;
9591 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
9592
9593 // Start parsing the OCSPResponse
9594 CBS ocsp_response;
9595 if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
9596 return nullptr;
9597 }
9598
9599 // Get the BasicOCSPResponse from the OCSP Response
9600 CBS basic_response;
9601 if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
9602 return nullptr;
9603 }
9604
9605 // Get the list of SingleResponses from the BasicOCSPResponse
9606 CBS responses;
9607 if (!get_ocsp_single_responses(&basic_response, &responses)) {
9608 return nullptr;
9609 }
9610
9611 // Find the response matching the certificate
9612 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
9613 X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
9614 CBS single_response;
9615 if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
9616 return nullptr;
9617 }
9618
9619 // Get the extensions from the SingleResponse
9620 CBS extensions;
9621 if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
9622 return nullptr;
9623 }
9624
9625 const uint8_t* ptr = CBS_data(&extensions);
9626 bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
9627 d2i_X509_EXTENSIONS(nullptr, &ptr,
9628 static_cast<long>(CBS_len(&extensions)))); // NOLINT(runtime/int)
9629 if (x509_exts.get() == nullptr) {
9630 return nullptr;
9631 }
9632
9633 return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
9634 env, x509_exts.get(), oid);
9635 }
9636
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)9637 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
9638 return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
9639 }
9640
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)9641 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
9642 CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
9643 CHECK_ERROR_QUEUE_ON_RETURN;
9644 SSL* ssl = to_SSL(env, ssl_address, true);
9645 if (ssl == nullptr) {
9646 return 0;
9647 }
9648 return SSL_get_error(ssl, ret);
9649 }
9650
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)9651 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
9652 ERR_clear_error();
9653 }
9654
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9655 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
9656 CONSCRYPT_UNUSED jobject ssl_holder) {
9657 CHECK_ERROR_QUEUE_ON_RETURN;
9658 SSL* ssl = to_SSL(env, ssl_address, true);
9659 if (ssl == nullptr) {
9660 return 0;
9661 }
9662 return SSL_pending(ssl);
9663 }
9664
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)9665 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
9666 CHECK_ERROR_QUEUE_ON_RETURN;
9667 BIO* bio = to_BIO(env, bio_address);
9668 if (bio == nullptr) {
9669 return 0;
9670 }
9671 return static_cast<jint>(BIO_ctrl_pending(bio));
9672 }
9673
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9674 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
9675 CONSCRYPT_UNUSED jobject ssl_holder) {
9676 CHECK_ERROR_QUEUE_ON_RETURN;
9677 SSL* ssl = to_SSL(env, ssl_address, true);
9678 if (ssl == nullptr) {
9679 return 0;
9680 }
9681 return (jint)SSL_max_seal_overhead(ssl);
9682 }
9683
9684 /**
9685 * public static native int SSL_new_BIO(long ssl) throws SSLException;
9686 */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9687 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
9688 CONSCRYPT_UNUSED jobject ssl_holder) {
9689 CHECK_ERROR_QUEUE_ON_RETURN;
9690 SSL* ssl = to_SSL(env, ssl_address, true);
9691 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
9692 if (ssl == nullptr) {
9693 return 0;
9694 }
9695
9696 BIO* internal_bio;
9697 BIO* network_bio;
9698 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
9699 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9700 "BIO_new_bio_pair failed");
9701 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
9702 return 0;
9703 }
9704
9705 SSL_set_bio(ssl, internal_bio, internal_bio);
9706
9707 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
9708 return reinterpret_cast<uintptr_t>(network_bio);
9709 }
9710
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9711 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9712 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9713 CHECK_ERROR_QUEUE_ON_RETURN;
9714 SSL* ssl = to_SSL(env, ssl_address, true);
9715 if (ssl == nullptr) {
9716 return 0;
9717 }
9718 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
9719
9720 if (shc == nullptr) {
9721 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9722 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
9723 ssl);
9724 return 0;
9725 }
9726
9727 AppData* appData = toAppData(ssl);
9728 if (appData == nullptr) {
9729 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9730 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
9731 return 0;
9732 }
9733
9734 errno = 0;
9735
9736 if (!appData->setCallbackState(env, shc, nullptr)) {
9737 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9738 ERR_clear_error();
9739 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9740 return 0;
9741 }
9742
9743 int ret = SSL_do_handshake(ssl);
9744 appData->clearCallbackState();
9745 if (env->ExceptionCheck()) {
9746 // cert_verify_callback threw exception
9747 ERR_clear_error();
9748 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
9749 return 0;
9750 }
9751
9752 SslError sslError(ssl, ret);
9753 int code = sslError.get();
9754
9755 if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
9756 // Non-exceptional case.
9757 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
9758 return code;
9759 }
9760
9761 // Exceptional case...
9762 if (ret == 0) {
9763 // TODO(nmittler): Can this happen with memory BIOs?
9764 /*
9765 * Clean error. See SSL_do_handshake(3SSL) man page.
9766 * The other side closed the socket before the handshake could be
9767 * completed, but everything is within the bounds of the TLS protocol.
9768 * We still might want to find out the real reason of the failure.
9769 */
9770 if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
9771 (code == SSL_ERROR_ZERO_RETURN)) {
9772 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9773 } else {
9774 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9775 env, ssl, sslError.release(), "SSL handshake terminated",
9776 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9777 }
9778 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9779 return code;
9780 }
9781
9782 /*
9783 * Unclean error. See SSL_do_handshake(3SSL) man page.
9784 * Translate the error and throw exception. We are sure it is an error
9785 * at this point.
9786 */
9787 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9788 env, ssl, sslError.release(), "SSL handshake aborted",
9789 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9790 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9791 return code;
9792 }
9793
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)9794 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9795 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
9796 CHECK_ERROR_QUEUE_ON_RETURN;
9797 SSL* ssl = to_SSL(env, ssl_address, false);
9798 if (ssl == nullptr) {
9799 return;
9800 }
9801 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
9802
9803 if (shc == nullptr) {
9804 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9805 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9806 return;
9807 }
9808
9809 AppData* appData = toAppData(ssl);
9810 if (appData != nullptr) {
9811 if (!appData->setCallbackState(env, shc, nullptr)) {
9812 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9813 ERR_clear_error();
9814 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9815 return;
9816 }
9817 int ret = SSL_shutdown(ssl);
9818 appData->clearCallbackState();
9819 // callbacks can happen if server requests renegotiation
9820 if (env->ExceptionCheck()) {
9821 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
9822 return;
9823 }
9824 switch (ret) {
9825 case 0:
9826 /*
9827 * Shutdown was not successful (yet), but there also
9828 * is no error. Since we can't know whether the remote
9829 * server is actually still there, and we don't want to
9830 * get stuck forever in a second SSL_shutdown() call, we
9831 * simply return. This is not security a problem as long
9832 * as we close the underlying socket, which we actually
9833 * do, because that's where we are just coming from.
9834 */
9835 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
9836 break;
9837 case 1:
9838 /*
9839 * Shutdown was successful. We can safely return. Hooray!
9840 */
9841 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
9842 break;
9843 default:
9844 /*
9845 * Everything else is a real error condition. We should
9846 * let the Java layer know about this by throwing an
9847 * exception.
9848 */
9849 int sslError = SSL_get_error(ssl, ret);
9850 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
9851 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9852 "SSL shutdown failed");
9853 break;
9854 }
9855 }
9856
9857 ERR_clear_error();
9858 }
9859
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)9860 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
9861 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
9862 jint length, jobject shc) {
9863 CHECK_ERROR_QUEUE_ON_RETURN;
9864 SSL* ssl = to_SSL(env, ssl_address, true);
9865 char* destPtr = reinterpret_cast<char*>(address);
9866 if (ssl == nullptr) {
9867 return -1;
9868 }
9869 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
9870 destPtr, length, shc);
9871
9872 if (shc == nullptr) {
9873 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9874 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
9875 ssl);
9876 return -1;
9877 }
9878 AppData* appData = toAppData(ssl);
9879 if (appData == nullptr) {
9880 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9881 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
9882 return -1;
9883 }
9884 if (!appData->setCallbackState(env, shc, nullptr)) {
9885 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9886 ERR_clear_error();
9887 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
9888 return -1;
9889 }
9890
9891 errno = 0;
9892
9893 int result = SSL_read(ssl, destPtr, length);
9894 appData->clearCallbackState();
9895 if (env->ExceptionCheck()) {
9896 // An exception was thrown by one of the callbacks. Just propagate that exception.
9897 ERR_clear_error();
9898 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
9899 return -1;
9900 }
9901
9902 SslError sslError(ssl, result);
9903 switch (sslError.get()) {
9904 case SSL_ERROR_NONE: {
9905 // Successfully read at least one byte. Just return the result.
9906 break;
9907 }
9908 case SSL_ERROR_ZERO_RETURN: {
9909 // A close_notify was received, this stream is finished.
9910 return -SSL_ERROR_ZERO_RETURN;
9911 }
9912 case SSL_ERROR_WANT_READ:
9913 case SSL_ERROR_WANT_WRITE: {
9914 // Return the negative of these values.
9915 result = -sslError.get();
9916 break;
9917 }
9918 case SSL_ERROR_SYSCALL: {
9919 // A problem occurred during a system call, but this is not
9920 // necessarily an error.
9921 if (result == 0) {
9922 // TODO(nmittler): Can this happen with memory BIOs?
9923 // Connection closed without proper shutdown. Tell caller we
9924 // have reached end-of-stream.
9925 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
9926 break;
9927 }
9928
9929 if (errno == EINTR) {
9930 // TODO(nmittler): Can this happen with memory BIOs?
9931 // System call has been interrupted. Simply retry.
9932 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
9933 "Read error");
9934 break;
9935 }
9936
9937 // Note that for all other system call errors we fall through
9938 // to the default case, which results in an Exception.
9939 FALLTHROUGH_INTENDED;
9940 }
9941 default: {
9942 // Everything else is basically an error.
9943 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9944 "Read error");
9945 break;
9946 }
9947 }
9948
9949 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
9950 ssl, destPtr, length, shc, result);
9951 return result;
9952 }
9953
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)9954 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
9955 CONSCRYPT_UNUSED jobject ssl_holder,
9956 jlong bioRef, jlong address, jint len,
9957 jobject shc) {
9958 CHECK_ERROR_QUEUE_ON_RETURN;
9959 SSL* ssl = to_SSL(env, ssl_address, true);
9960 if (ssl == nullptr) {
9961 return -1;
9962 }
9963 if (shc == nullptr) {
9964 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9965 JNI_TRACE(
9966 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
9967 "sslHandshakeCallbacks == null",
9968 ssl);
9969 return -1;
9970 }
9971 BIO* bio = to_BIO(env, bioRef);
9972 if (bio == nullptr) {
9973 return -1;
9974 }
9975 if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
9976 // The network BIO couldn't handle the entire write. Don't write anything, so that we
9977 // only process one packet at a time.
9978 return 0;
9979 }
9980 const char* sourcePtr = reinterpret_cast<const char*>(address);
9981
9982 AppData* appData = toAppData(ssl);
9983 if (appData == nullptr) {
9984 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9985 ERR_clear_error();
9986 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
9987 return -1;
9988 }
9989 if (!appData->setCallbackState(env, shc, nullptr)) {
9990 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
9991 ERR_clear_error();
9992 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
9993 return -1;
9994 }
9995
9996 errno = 0;
9997
9998 int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
9999 appData->clearCallbackState();
10000 JNI_TRACE(
10001 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10002 "ret=%d",
10003 ssl, bio, sourcePtr, len, shc, result);
10004 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10005 static_cast<size_t>(result));
10006 return result;
10007 }
10008
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)10009 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10010 CONSCRYPT_UNUSED jobject ssl_holder,
10011 jlong bioRef, jlong address, jint outputSize,
10012 jobject shc) {
10013 CHECK_ERROR_QUEUE_ON_RETURN;
10014 SSL* ssl = to_SSL(env, ssl_address, true);
10015 if (ssl == nullptr) {
10016 return -1;
10017 }
10018 if (shc == nullptr) {
10019 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10020 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10021 ssl);
10022 return -1;
10023 }
10024 BIO* bio = to_BIO(env, bioRef);
10025 if (bio == nullptr) {
10026 return -1;
10027 }
10028 char* destPtr = reinterpret_cast<char*>(address);
10029 if (destPtr == nullptr) {
10030 conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10031 return -1;
10032 }
10033
10034 AppData* appData = toAppData(ssl);
10035 if (appData == nullptr) {
10036 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10037 ERR_clear_error();
10038 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10039 return -1;
10040 }
10041 if (!appData->setCallbackState(env, shc, nullptr)) {
10042 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10043 ERR_clear_error();
10044 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10045 return -1;
10046 }
10047
10048 errno = 0;
10049
10050 int result = BIO_read(bio, destPtr, outputSize);
10051 appData->clearCallbackState();
10052 JNI_TRACE(
10053 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10054 "=> ret=%d",
10055 ssl, bio, destPtr, outputSize, shc, result);
10056 JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10057 return result;
10058 }
10059
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10060 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10061 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10062 CHECK_ERROR_QUEUE_ON_RETURN;
10063 SSL* ssl = to_SSL(env, ssl_address, true);
10064 if (ssl == nullptr) {
10065 return;
10066 }
10067 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10068 if (shc == nullptr) {
10069 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10070 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10071 ssl);
10072 return;
10073 }
10074 AppData* appData = toAppData(ssl);
10075 if (appData == nullptr) {
10076 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10077 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10078 return;
10079 }
10080 if (!appData->setCallbackState(env, shc, nullptr)) {
10081 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10082 ERR_clear_error();
10083 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10084 return;
10085 }
10086 char c;
10087 int result = SSL_peek(ssl, &c, 1);
10088 appData->clearCallbackState();
10089 if (env->ExceptionCheck()) {
10090 // An exception was thrown by one of the callbacks. Just propagate that exception.
10091 ERR_clear_error();
10092 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10093 return;
10094 }
10095
10096 SslError sslError(ssl, result);
10097 switch (sslError.get()) {
10098 case SSL_ERROR_NONE:
10099 case SSL_ERROR_ZERO_RETURN:
10100 case SSL_ERROR_WANT_READ:
10101 case SSL_ERROR_WANT_WRITE: {
10102 // The call succeeded, lacked data, or the SSL is closed. All is well.
10103 break;
10104 }
10105 case SSL_ERROR_SYSCALL: {
10106 // A problem occurred during a system call, but this is not
10107 // necessarily an error.
10108 if (result == 0) {
10109 // TODO(nmittler): Can this happen with memory BIOs?
10110 // Connection closed without proper shutdown. Tell caller we
10111 // have reached end-of-stream.
10112 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10113 break;
10114 }
10115
10116 if (errno == EINTR) {
10117 // TODO(nmittler): Can this happen with memory BIOs?
10118 // System call has been interrupted. Simply retry.
10119 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10120 "Read error");
10121 break;
10122 }
10123
10124 // Note that for all other system call errors we fall through
10125 // to the default case, which results in an Exception.
10126 FALLTHROUGH_INTENDED;
10127 }
10128 default: {
10129 // Everything else is basically an error.
10130 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10131 "Read error");
10132 break;
10133 }
10134 }
10135
10136 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10137 }
10138
10139 /**
10140 * OpenSSL write function (2): write into buffer at offset n chunks.
10141 */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10142 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10143 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10144 jint len, jobject shc) {
10145 CHECK_ERROR_QUEUE_ON_RETURN;
10146 SSL* ssl = to_SSL(env, ssl_address, true);
10147 const char* sourcePtr = reinterpret_cast<const char*>(address);
10148 if (ssl == nullptr) {
10149 return -1;
10150 }
10151 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10152 sourcePtr, len, shc);
10153 if (shc == nullptr) {
10154 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10155 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10156 ssl);
10157 return -1;
10158 }
10159
10160 AppData* appData = toAppData(ssl);
10161 if (appData == nullptr) {
10162 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10163 ERR_clear_error();
10164 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10165 return -1;
10166 }
10167 if (!appData->setCallbackState(env, shc, nullptr)) {
10168 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10169 ERR_clear_error();
10170 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10171 return -1;
10172 }
10173
10174 errno = 0;
10175
10176 int result = SSL_write(ssl, sourcePtr, len);
10177 appData->clearCallbackState();
10178 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10179 ssl, sourcePtr, len, shc, result);
10180 return result;
10181 }
10182
10183 /**
10184 * public static native bool BoringSSL_FIPS_mode();
10185 */
NativeCrypto_usesBoringSSL_FIPS_mode()10186 static jboolean NativeCrypto_usesBoringSSL_FIPS_mode() {
10187 return FIPS_mode();
10188 }
10189
10190 // TESTING METHODS BEGIN
10191
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10192 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10193 CHECK_ERROR_QUEUE_ON_RETURN;
10194 BIO* bio = to_BIO(env, bioRef);
10195 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10196
10197 if (bio == nullptr) {
10198 JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10199 return 0;
10200 }
10201
10202 if (outputJavaBytes == nullptr) {
10203 conscrypt::jniutil::throwNullPointerException(env, "output == null");
10204 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10205 return 0;
10206 }
10207
10208 jsize outputSize = env->GetArrayLength(outputJavaBytes);
10209
10210 std::unique_ptr<unsigned char[]> buffer(
10211 new unsigned char[static_cast<unsigned int>(outputSize)]);
10212 if (buffer.get() == nullptr) {
10213 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10214 return 0;
10215 }
10216
10217 int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10218 if (read <= 0) {
10219 conscrypt::jniutil::throwIOException(env, "BIO_read");
10220 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10221 return 0;
10222 }
10223
10224 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10225 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10226 return read;
10227 }
10228
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10229 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10230 jint offset, jint length) {
10231 CHECK_ERROR_QUEUE_ON_RETURN;
10232 BIO* bio = to_BIO(env, bioRef);
10233 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10234
10235 if (bio == nullptr) {
10236 return;
10237 }
10238
10239 if (inputJavaBytes == nullptr) {
10240 conscrypt::jniutil::throwNullPointerException(env, "input == null");
10241 return;
10242 }
10243
10244 int inputSize = env->GetArrayLength(inputJavaBytes);
10245 if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10246 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10247 "inputJavaBytes");
10248 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10249 return;
10250 }
10251
10252 std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10253 if (buffer.get() == nullptr) {
10254 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10255 return;
10256 }
10257
10258 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10259 if (BIO_write(bio, buffer.get(), length) != length) {
10260 ERR_clear_error();
10261 conscrypt::jniutil::throwIOException(env, "BIO_write");
10262 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10263 return;
10264 }
10265
10266 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10267 }
10268
10269 /**
10270 * public static native long SSL_clear_mode(long ssl, long mode);
10271 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10272 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10273 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10274 CHECK_ERROR_QUEUE_ON_RETURN;
10275 SSL* ssl = to_SSL(env, ssl_address, true);
10276 // NOLINTNEXTLINE(runtime/int)
10277 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10278 if (ssl == nullptr) {
10279 return 0;
10280 }
10281 jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10282 // NOLINTNEXTLINE(runtime/int)
10283 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10284 return result;
10285 }
10286
10287 /**
10288 * public static native long SSL_get_mode(long ssl);
10289 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10290 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10291 CONSCRYPT_UNUSED jobject ssl_holder) {
10292 CHECK_ERROR_QUEUE_ON_RETURN;
10293 SSL* ssl = to_SSL(env, ssl_address, true);
10294 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10295 if (ssl == nullptr) {
10296 return 0;
10297 }
10298 jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
10299 // NOLINTNEXTLINE(runtime/int)
10300 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
10301 return mode;
10302 }
10303
10304 /**
10305 * public static native long SSL_get_options(long ssl);
10306 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10307 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
10308 CONSCRYPT_UNUSED jobject ssl_holder) {
10309 CHECK_ERROR_QUEUE_ON_RETURN;
10310 SSL* ssl = to_SSL(env, ssl_address, true);
10311 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
10312 if (ssl == nullptr) {
10313 return 0;
10314 }
10315 jlong options = static_cast<jlong>(SSL_get_options(ssl));
10316 // NOLINTNEXTLINE(runtime/int)
10317 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
10318 return options;
10319 }
10320
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10321 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
10322 CONSCRYPT_UNUSED jobject ssl_holder) {
10323 CHECK_ERROR_QUEUE_ON_RETURN;
10324 SSL* ssl = to_SSL(env, ssl_address, true);
10325 if (ssl == nullptr) {
10326 return 0;
10327 }
10328 return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
10329 }
10330
10331 // TESTING METHODS END
10332
10333 #define CONSCRYPT_NATIVE_METHOD(functionName, signature) \
10334 { \
10335 /* NOLINTNEXTLINE */ \
10336 (char*)#functionName, (char*)(signature), \
10337 reinterpret_cast<void*>(NativeCrypto_##functionName) \
10338 }
10339
10340 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10341 #define SSL_CALLBACKS \
10342 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
10343 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10344 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
10345 #define REF_EVP_CIPHER_CTX \
10346 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
10347 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
10348 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
10349 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
10350 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
10351 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
10352 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
10353 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
10354 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
10355 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
10356 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
10357 static JNINativeMethod sNativeCryptoMethods[] = {
10358 CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
10359 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
10360 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
10361 CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
10362 CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
10363 CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
10364 CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
10365 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
10366 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
10367 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10368 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10369 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10370 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
10371 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10372 CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
10373 CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
10374 CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
10375 CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
10376 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
10377 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
10378 CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10379 CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
10380 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
10381 CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
10382 CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
10383 CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10384 CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10385 CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10386 CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10387 CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10388 CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
10389 CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
10390 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
10391 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
10392 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10393 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10394 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10395 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10396 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
10397 CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
10398 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10399 CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
10400 CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
10401 CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
10402 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10403 CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
10404 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10405 CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10406 CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
10407 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10408 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10409 CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
10410 CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
10411 CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10412 CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
10413 CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
10414 CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
10415 CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
10416 CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
10417 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
10418 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
10419 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
10420 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
10421 CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
10422 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10423 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10424 CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
10425 CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10426 CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
10427 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10428 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10429 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10430 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
10431 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
10432 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
10433 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
10434 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
10435 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
10436 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10437 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
10438 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
10439 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
10440 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
10441 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
10442 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
10443 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
10444 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
10445 CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
10446 CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10447 CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10448 CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
10449 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
10450 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
10451 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10452 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
10453 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
10454 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10455 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
10456 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
10457 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
10458 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
10459 CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
10460 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
10461 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
10462 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
10463 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
10464 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
10465 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
10466 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10467 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf, "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
10468 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
10469 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
10470 CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
10471 CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
10472 CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
10473 CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
10474 CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
10475 CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
10476 CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10477 CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
10478 CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
10479 CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
10480 CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
10481 CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
10482 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
10483 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
10484 CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
10485 CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
10486 CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
10487 CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
10488 CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
10489 CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
10490 CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
10491 CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
10492 CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
10493 CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
10494 CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10495 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
10496 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
10497 CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
10498 CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
10499 CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
10500 CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
10501 CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
10502 CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
10503 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
10504 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
10505 CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
10506 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
10507 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
10508 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10509 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
10510 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
10511 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
10512 CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
10513 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
10514 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10515 CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
10516 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
10517 CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
10518 CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
10519 CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
10520 CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
10521 CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
10522 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
10523 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext, "(J" REF_X509 "Ljava/lang/String;)[B"),
10524 CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
10525 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
10526 CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
10527 CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
10528 CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
10529 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
10530 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
10531 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
10532 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
10533 CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
10534 CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
10535 CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
10536 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
10537 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
10538 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
10539 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
10540 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
10541 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10542 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
10543 CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
10544 CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
10545 CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10546 CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
10547 CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
10548 CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
10549 CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
10550 CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
10551 CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
10552 CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
10553 CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
10554 CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
10555 CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
10556 CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
10557 CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
10558 CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
10559 CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
10560 CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
10561 CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
10562 CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
10563 CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
10564 CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
10565 CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
10566 CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
10567 CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
10568 CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
10569 CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
10570 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
10571 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
10572 CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
10573 CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
10574 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
10575 CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
10576 CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
10577 CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
10578 CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
10579 CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
10580 CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
10581 CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
10582 CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
10583 CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
10584 CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
10585 CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
10586 CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
10587 CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
10588 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
10589 CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
10590 CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
10591 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
10592 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
10593 CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
10594 CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
10595 CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
10596 CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
10597 CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
10598 CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
10599 CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
10600 CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
10601 CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
10602 CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
10603 CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
10604 CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
10605 CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
10606 CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
10607 CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
10608 CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
10609 CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
10610 CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
10611 CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
10612 CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
10613 CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
10614 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
10615 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
10616 CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
10617 CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
10618 CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
10619 CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
10620 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
10621 CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
10622 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10623 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10624 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
10625 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
10626 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
10627 CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
10628 CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
10629 CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
10630 CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
10631 CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
10632 CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
10633 CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
10634 CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
10635 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
10636 CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
10637 CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
10638 CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
10639 CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
10640 CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
10641 CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
10642 CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
10643 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
10644 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10645 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
10646 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10647 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
10648 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
10649 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
10650 CONSCRYPT_NATIVE_METHOD(usesBoringSSL_FIPS_mode, "()Z"),
10651
10652 // Used for testing only.
10653 CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
10654 CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
10655 CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
10656 CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
10657 CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
10658 CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
10659 };
10660
registerNativeMethods(JNIEnv * env)10661 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
10662 conscrypt::jniutil::jniRegisterNativeMethods(
10663 env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
10664 NELEM(sNativeCryptoMethods));
10665 }
10666
10667 /* Local Variables: */
10668 /* mode: c++ */
10669 /* tab-width: 4 */
10670 /* indent-tabs-mode: nil */
10671 /* c-basic-offset: 4 */
10672 /* End: */
10673 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
10674