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 #include <limits.h>
32 #include <nativehelper/scoped_primitive_array.h>
33 #include <nativehelper/scoped_utf_chars.h>
34 #include <openssl/aead.h>
35 #include <openssl/asn1.h>
36 #include <openssl/bn.h>
37 #include <openssl/chacha.h>
38 #include <openssl/cmac.h>
39 #include <openssl/crypto.h>
40 #include <openssl/curve25519.h>
41 #include <openssl/engine.h>
42 #include <openssl/err.h>
43 #include <openssl/evp.h>
44 #include <openssl/hmac.h>
45 #include <openssl/hpke.h>
46 #include <openssl/pkcs7.h>
47 #include <openssl/pkcs8.h>
48 #include <openssl/rand.h>
49 #include <openssl/rsa.h>
50 #include <openssl/ssl.h>
51 #include <openssl/x509v3.h>
52
53 #include <limits>
54 #include <optional>
55 #include <type_traits>
56 #include <vector>
57
58 using conscrypt::AppData;
59 using conscrypt::BioInputStream;
60 using conscrypt::BioOutputStream;
61 using conscrypt::BioStream;
62 using conscrypt::CompatibilityCloseMonitor;
63 using conscrypt::NativeCrypto;
64 using conscrypt::SslError;
65
66 /**
67 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
68 * If this function returns nullptr and <code>throwIfNull</code> is
69 * passed as <code>true</code>, then this function will call
70 * <code>throwSSLExceptionStr</code> before returning, so in this case of
71 * nullptr, a caller of this function should simply return and allow JNI
72 * to do its thing.
73 *
74 * @param env the JNI environment
75 * @param ssl_address; the ssl_address pointer as an integer
76 * @param throwIfNull whether to throw if the SSL pointer is nullptr
77 * @returns the pointer, which may be nullptr
78 */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)79 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
80 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
81 if ((ssl_ctx == nullptr) && throwIfNull) {
82 JNI_TRACE("ssl_ctx == null");
83 conscrypt::jniutil::throwNullPointerException(env, "ssl_ctx == null");
84 }
85 return ssl_ctx;
86 }
87
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)88 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
89 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
90 if ((ssl == nullptr) && throwIfNull) {
91 JNI_TRACE("ssl == null");
92 conscrypt::jniutil::throwNullPointerException(env, "ssl == null");
93 }
94 return ssl;
95 }
96
to_BIO(JNIEnv * env,jlong bio_address)97 static BIO* to_BIO(JNIEnv* env, jlong bio_address) {
98 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bio_address));
99 if (bio == nullptr) {
100 JNI_TRACE("bio == null");
101 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
102 }
103 return bio;
104 }
105
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)106 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
107 SSL_SESSION* ssl_session =
108 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
109 if ((ssl_session == nullptr) && throwIfNull) {
110 JNI_TRACE("ssl_session == null");
111 conscrypt::jniutil::throwNullPointerException(env, "ssl_session == null");
112 }
113 return ssl_session;
114 }
115
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)116 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
117 SSL_CIPHER* ssl_cipher =
118 reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
119 if ((ssl_cipher == nullptr) && throwIfNull) {
120 JNI_TRACE("ssl_cipher == null");
121 conscrypt::jniutil::throwNullPointerException(env, "ssl_cipher == null");
122 }
123 return ssl_cipher;
124 }
125
126 template <typename T>
fromContextObject(JNIEnv * env,jobject contextObject)127 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
128 if (contextObject == nullptr) {
129 JNI_TRACE("contextObject == null");
130 conscrypt::jniutil::throwNullPointerException(env, "contextObject == null");
131 return nullptr;
132 }
133 T* ref = reinterpret_cast<T*>(
134 env->GetLongField(contextObject, conscrypt::jniutil::nativeRef_address));
135 if (ref == nullptr) {
136 JNI_TRACE("ref == null");
137 conscrypt::jniutil::throwNullPointerException(env, "ref == null");
138 return nullptr;
139 }
140 return ref;
141 }
142
143 /**
144 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
145 * allocate the BIGNUM if *dest == nullptr. Returns true on success. If the
146 * return value is false, there is a pending exception.
147 */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)148 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
149 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
150 if (dest == nullptr) {
151 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
152 conscrypt::jniutil::throwNullPointerException(env, "dest == null");
153 return false;
154 }
155 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
156
157 ScopedByteArrayRO sourceBytes(env, source);
158 if (sourceBytes.get() == nullptr) {
159 JNI_TRACE("arrayToBignum(%p, %p) => null", source, dest);
160 return false;
161 }
162 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
163 size_t tmpSize = sourceBytes.size();
164
165 /* if the array is empty, it is zero. */
166 if (tmpSize == 0) {
167 if (*dest == nullptr) {
168 *dest = BN_new();
169 }
170 BN_zero(*dest);
171 return true;
172 }
173
174 std::unique_ptr<unsigned char[]> twosComplement;
175 bool negative = (tmp[0] & 0x80) != 0;
176 if (negative) {
177 // Need to convert to two's complement.
178 twosComplement.reset(new unsigned char[tmpSize]);
179 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
180 memcpy(twosBytes, tmp, tmpSize);
181 tmp = twosBytes;
182
183 bool carry = true;
184 for (ssize_t i = static_cast<ssize_t>(tmpSize - 1); i >= 0; i--) {
185 twosBytes[i] ^= 0xFF;
186 if (carry) {
187 carry = (++twosBytes[i]) == 0;
188 }
189 }
190 }
191 BIGNUM* ret = BN_bin2bn(tmp, tmpSize, *dest);
192 if (ret == nullptr) {
193 conscrypt::jniutil::throwRuntimeException(env, "Conversion to BIGNUM failed");
194 ERR_clear_error();
195 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
196 return false;
197 }
198 BN_set_negative(ret, negative ? 1 : 0);
199
200 *dest = ret;
201 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
202 return true;
203 }
204
arrayToBignum(JNIEnv * env,jbyteArray source)205 static bssl::UniquePtr<BIGNUM> arrayToBignum(JNIEnv* env, jbyteArray source) {
206 BIGNUM *bn = nullptr;
207 if (!arrayToBignum(env, source, &bn)) {
208 return nullptr;
209 }
210 return bssl::UniquePtr<BIGNUM>(bn);
211 }
212
213 /**
214 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
215 */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)216 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
217 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
218
219 if (source == nullptr) {
220 conscrypt::jniutil::throwNullPointerException(env, sourceName);
221 return nullptr;
222 }
223
224 size_t numBytes = BN_num_bytes(source) + 1;
225 jbyteArray javaBytes = env->NewByteArray(static_cast<jsize>(numBytes));
226 ScopedByteArrayRW bytes(env, javaBytes);
227 if (bytes.get() == nullptr) {
228 JNI_TRACE("bignumToArray(%p, %s) => null", source, sourceName);
229 return nullptr;
230 }
231
232 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
233 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
234 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "bignumToArray");
235 return nullptr;
236 }
237
238 // Set the sign and convert to two's complement if necessary for the Java code.
239 if (BN_is_negative(source)) {
240 bool carry = true;
241 for (ssize_t i = static_cast<ssize_t>(numBytes - 1); i >= 0; i--) {
242 tmp[i] ^= 0xFF;
243 if (carry) {
244 carry = (++tmp[i]) == 0;
245 }
246 }
247 *tmp |= 0x80;
248 } else {
249 *tmp = 0x00;
250 }
251
252 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
253 return javaBytes;
254 }
255
256 /**
257 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
258 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
259 * from the OpenSSL ASN.1 API. Note i2d_func may take a const parameter, so we
260 * use a separate type parameter.
261 *
262 * TODO(https://crbug.com/boringssl/407): When all BoringSSL i2d functions are
263 * const, switch back to a single template parameter.
264 */
265 template <typename T, typename U>
ASN1ToByteArray(JNIEnv * env,T * obj,int (* i2d_func)(U *,unsigned char **))266 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(U*, unsigned char**)) {
267 // T and U should be the same type, but may differ in const.
268 static_assert(std::is_same<typename std::remove_const<T>::type,
269 typename std::remove_const<U>::type>::value,
270 "obj and i2d_func have incompatible types");
271
272 if (obj == nullptr) {
273 conscrypt::jniutil::throwNullPointerException(env, "ASN1 input == null");
274 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
275 return nullptr;
276 }
277
278 int derLen = i2d_func(obj, nullptr);
279 if (derLen < 0) {
280 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
281 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
282 return nullptr;
283 }
284
285 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
286 if (byteArray.get() == nullptr) {
287 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
288 return nullptr;
289 }
290
291 ScopedByteArrayRW bytes(env, byteArray.get());
292 if (bytes.get() == nullptr) {
293 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
294 return nullptr;
295 }
296
297 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
298 int ret = i2d_func(obj, &p);
299 if (ret < 0) {
300 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1ToByteArray");
301 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
302 return nullptr;
303 }
304
305 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
306 return byteArray.release();
307 }
308
309 /**
310 * Finishes a pending CBB and returns a jbyteArray with the contents.
311 */
CBBToByteArray(JNIEnv * env,CBB * cbb)312 jbyteArray CBBToByteArray(JNIEnv* env, CBB* cbb) {
313 uint8_t* data;
314 size_t len;
315 if (!CBB_finish(cbb, &data, &len)) {
316 conscrypt::jniutil::throwRuntimeException(env, "CBB_finish failed");
317 ERR_clear_error();
318 JNI_TRACE("creating byte array failed");
319 return nullptr;
320 }
321 bssl::UniquePtr<uint8_t> free_data(data);
322
323 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(len)));
324 if (byteArray.get() == nullptr) {
325 JNI_TRACE("creating byte array failed");
326 return nullptr;
327 }
328
329 ScopedByteArrayRW bytes(env, byteArray.get());
330 if (bytes.get() == nullptr) {
331 JNI_TRACE("using byte array failed");
332 return nullptr;
333 }
334
335 memcpy(bytes.get(), data, len);
336 return byteArray.release();
337 }
338
CryptoBufferToByteArray(JNIEnv * env,const CRYPTO_BUFFER * buf)339 jbyteArray CryptoBufferToByteArray(JNIEnv* env, const CRYPTO_BUFFER* buf) {
340 if (CRYPTO_BUFFER_len(buf) > INT_MAX) {
341 JNI_TRACE("buffer too large");
342 conscrypt::jniutil::throwRuntimeException(env, "buffer too large");
343 return nullptr;
344 }
345
346 int length = static_cast<int>(CRYPTO_BUFFER_len(buf));
347 jbyteArray ret = env->NewByteArray(length);
348 if (ret == nullptr) {
349 JNI_TRACE("allocating byte array failed");
350 return nullptr;
351 }
352
353 env->SetByteArrayRegion(ret, 0, length,
354 reinterpret_cast<const int8_t*>(CRYPTO_BUFFER_data(buf)));
355 return ret;
356 }
357
ByteArrayToCryptoBuffer(JNIEnv * env,const jbyteArray array,CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL * pool)358 bssl::UniquePtr<CRYPTO_BUFFER> ByteArrayToCryptoBuffer(JNIEnv* env, const jbyteArray array,
359 CONSCRYPT_UNUSED CRYPTO_BUFFER_POOL* pool) {
360 if (array == nullptr) {
361 JNI_TRACE("array was null");
362 conscrypt::jniutil::throwNullPointerException(env, "array == null");
363 return nullptr;
364 }
365
366 ScopedByteArrayRO arrayRo(env, array);
367 if (arrayRo.get() == nullptr) {
368 JNI_TRACE("failed to get bytes");
369 return nullptr;
370 }
371
372 bssl::UniquePtr<CRYPTO_BUFFER> ret(CRYPTO_BUFFER_new(
373 reinterpret_cast<const uint8_t*>(arrayRo.get()), arrayRo.size(), nullptr));
374 if (!ret) {
375 JNI_TRACE("failed to allocate CRYPTO_BUFFER");
376 conscrypt::jniutil::throwOutOfMemory(env, "failed to allocate CRYPTO_BUFFER");
377 return nullptr;
378 }
379
380 return ret;
381 }
382
CryptoBuffersToObjectArray(JNIEnv * env,const STACK_OF (CRYPTO_BUFFER)* buffers)383 static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
384 const STACK_OF(CRYPTO_BUFFER)* buffers) {
385 size_t numBuffers = sk_CRYPTO_BUFFER_num(buffers);
386 if (numBuffers > INT_MAX) {
387 JNI_TRACE("too many buffers");
388 conscrypt::jniutil::throwRuntimeException(env, "too many buffers");
389 return nullptr;
390 }
391
392 ScopedLocalRef<jobjectArray> array(
393 env, env->NewObjectArray(static_cast<int>(numBuffers),
394 conscrypt::jniutil::byteArrayClass, nullptr));
395 if (array.get() == nullptr) {
396 JNI_TRACE("failed to allocate array");
397 return nullptr;
398 }
399
400 for (size_t i = 0; i < numBuffers; ++i) {
401 CRYPTO_BUFFER* buffer = sk_CRYPTO_BUFFER_value(buffers, i);
402 ScopedLocalRef<jbyteArray> bArray(env, CryptoBufferToByteArray(env, buffer));
403 if (bArray.get() == nullptr) {
404 return nullptr;
405 }
406 env->SetObjectArrayElement(array.get(), i, bArray.get());
407 }
408
409 return array.release();
410 }
411
412 /**
413 * Converts ASN.1 BIT STRING to a jbooleanArray.
414 */
ASN1BitStringToBooleanArray(JNIEnv * env,const ASN1_BIT_STRING * bitStr)415 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
416 int size = ASN1_STRING_length(bitStr) * 8;
417 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
418 size -= bitStr->flags & 0x07;
419 }
420
421 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
422 if (bitsRef.get() == nullptr) {
423 return nullptr;
424 }
425
426 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
427 for (size_t i = 0; i < bitsArray.size(); i++) {
428 bitsArray[i] = static_cast<jboolean>(ASN1_BIT_STRING_get_bit(bitStr, static_cast<int>(i)));
429 }
430
431 return bitsRef.release();
432 }
433
bio_stream_destroy(BIO * b)434 static int bio_stream_destroy(BIO* b) {
435 if (b == nullptr) {
436 return 0;
437 }
438
439 delete static_cast<BioStream*>(BIO_get_data(b));
440 BIO_set_data(b, nullptr);
441 BIO_set_init(b, 0);
442 return 1;
443 }
444
bio_stream_read(BIO * b,char * buf,int len)445 static int bio_stream_read(BIO* b, char* buf, int len) {
446 BIO_clear_retry_flags(b);
447 BioInputStream* stream = static_cast<BioInputStream*>(BIO_get_data(b));
448 int ret = stream->read(buf, len);
449 if (ret == 0) {
450 if (stream->isFinite()) {
451 return 0;
452 }
453 // If the BioInputStream is not finite then EOF doesn't mean that
454 // there's nothing more coming.
455 BIO_set_retry_read(b);
456 return -1;
457 }
458 return ret;
459 }
460
bio_stream_write(BIO * b,const char * buf,int len)461 static int bio_stream_write(BIO* b, const char* buf, int len) {
462 BIO_clear_retry_flags(b);
463 BioOutputStream* stream = static_cast<BioOutputStream*>(BIO_get_data(b));
464 return stream->write(buf, len);
465 }
466
bio_stream_gets(BIO * b,char * buf,int len)467 static int bio_stream_gets(BIO* b, char* buf, int len) {
468 BioInputStream* stream = static_cast<BioInputStream*>(BIO_get_data(b));
469 return stream->gets(buf, len);
470 }
471
bio_stream_assign(BIO * b,BioStream * stream)472 static void bio_stream_assign(BIO* b, BioStream* stream) {
473 BIO_set_data(b, stream);
474 BIO_set_init(b, 1);
475 }
476
477 // NOLINTNEXTLINE(runtime/int)
bio_stream_ctrl(BIO * b,int cmd,long,void *)478 static long bio_stream_ctrl(BIO* b, int cmd, long, void*) {
479 BioStream* stream = static_cast<BioStream*>(BIO_get_data(b));
480
481 switch (cmd) {
482 case BIO_CTRL_EOF:
483 return stream->isEof() ? 1 : 0;
484 case BIO_CTRL_FLUSH:
485 return stream->flush();
486 default:
487 return 0;
488 }
489 }
490
stream_bio_method()491 static const BIO_METHOD *stream_bio_method() {
492 static const BIO_METHOD* stream_method = []() -> const BIO_METHOD* {
493 BIO_METHOD* method = BIO_meth_new(0, nullptr);
494 if (!method || !BIO_meth_set_write(method, bio_stream_write) ||
495 !BIO_meth_set_read(method, bio_stream_read) ||
496 !BIO_meth_set_gets(method, bio_stream_gets) ||
497 !BIO_meth_set_ctrl(method, bio_stream_ctrl) ||
498 !BIO_meth_set_destroy(method, bio_stream_destroy)) {
499 BIO_meth_free(method);
500 return nullptr;
501 }
502 return method;
503 }();
504 return stream_method;
505 }
506
ecSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)507 static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, const char* message,
508 size_t message_len) {
509 JNI_TRACE("ecSignDigestWithPrivateKey(%p)", privateKey);
510 if (message_len > std::numeric_limits<jsize>::max()) {
511 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => argument too large", privateKey);
512 return nullptr;
513 }
514 ScopedLocalRef<jbyteArray> messageArray(env,
515 env->NewByteArray(static_cast<jsize>(message_len)));
516 if (env->ExceptionCheck()) {
517 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => threw exception", privateKey);
518 return nullptr;
519 }
520
521 {
522 ScopedByteArrayRW messageBytes(env, messageArray.get());
523 if (messageBytes.get() == nullptr) {
524 JNI_TRACE("ecSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
525 return nullptr;
526 }
527
528 memcpy(messageBytes.get(), message, message_len);
529 }
530
531 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
532 conscrypt::jniutil::cryptoUpcallsClass,
533 conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod, privateKey, messageArray.get()));
534 }
535
rsaSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * message,size_t message_len)536 static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
537 const char* message, size_t message_len) {
538 if (message_len > std::numeric_limits<jsize>::max()) {
539 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => argument too large", privateKey);
540 return nullptr;
541 }
542 ScopedLocalRef<jbyteArray> messageArray(env,
543 env->NewByteArray(static_cast<jsize>(message_len)));
544 if (env->ExceptionCheck()) {
545 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => threw exception", privateKey);
546 return nullptr;
547 }
548
549 {
550 ScopedByteArrayRW messageBytes(env, messageArray.get());
551 if (messageBytes.get() == nullptr) {
552 JNI_TRACE("rsaSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
553 return nullptr;
554 }
555
556 memcpy(messageBytes.get(), message, message_len);
557 }
558
559 return reinterpret_cast<jbyteArray>(
560 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
561 conscrypt::jniutil::cryptoUpcallsClass_rsaSignMethod,
562 privateKey, padding, messageArray.get()));
563 }
564
565 // rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
566 // from |ciphertext|. The ciphertext is expected to be padded using the scheme
567 // given in |padding|, which must be one of |RSA_*_PADDING| constants from
568 // OpenSSL.
rsaDecryptWithPrivateKey(JNIEnv * env,jobject privateKey,jint padding,const char * ciphertext,size_t ciphertext_len)569 static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
570 const char* ciphertext, size_t ciphertext_len) {
571 if (ciphertext_len > std::numeric_limits<jsize>::max()) {
572 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => argument too large", privateKey);
573 return nullptr;
574 }
575 ScopedLocalRef<jbyteArray> ciphertextArray(
576 env, env->NewByteArray(static_cast<jsize>(ciphertext_len)));
577 if (env->ExceptionCheck()) {
578 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
579 return nullptr;
580 }
581
582 {
583 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
584 if (ciphertextBytes.get() == nullptr) {
585 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
586 return nullptr;
587 }
588
589 memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
590 }
591
592 return reinterpret_cast<jbyteArray>(
593 env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
594 conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
595 privateKey, padding, ciphertextArray.get()));
596 }
597
598 // *********************************************
599 // From keystore_openssl.cpp in Chromium source.
600 // *********************************************
601
602 namespace {
603
604 ENGINE* g_engine;
605 int g_rsa_exdata_index;
606 int g_ecdsa_exdata_index;
607 RSA_METHOD g_rsa_method;
608 ECDSA_METHOD g_ecdsa_method;
609 std::once_flag g_engine_once;
610
611 void init_engine_globals();
612
ensure_engine_globals()613 void ensure_engine_globals() {
614 std::call_once(g_engine_once, init_engine_globals);
615 }
616
617 // KeyExData contains the data that is contained in the EX_DATA of the RSA
618 // and ECDSA objects that are created to wrap Android system keys.
619 struct KeyExData {
620 // private_key contains a reference to a Java, private-key object.
621 jobject private_key;
622 };
623
624 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
625 // don't support this and it should never happen.
ExDataDup(CRYPTO_EX_DATA *,const CRYPTO_EX_DATA *,void **,int,long,void *)626 int ExDataDup(CRYPTO_EX_DATA* /* to */,
627 const CRYPTO_EX_DATA* /* from */,
628 void** /* from_d */,
629 int /* index */,
630 long /* argl */ /* NOLINT(runtime/int) */,
631 void* /* argp */) {
632 return 0;
633 }
634
635 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA *,int,long,void *)636 void ExDataFree(void* /* parent */,
637 void* ptr,
638 CRYPTO_EX_DATA* /* ad */,
639 int /* index */,
640 long /* argl */ /* NOLINT(runtime/int) */,
641 void* /* argp */) {
642 // Ensure the global JNI reference created with this wrapper is
643 // properly destroyed with it.
644 KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr);
645 if (ex_data != nullptr) {
646 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
647 env->DeleteGlobalRef(ex_data->private_key);
648 delete ex_data;
649 }
650 }
651
RsaGetExData(const RSA * rsa)652 KeyExData* RsaGetExData(const RSA* rsa) {
653 return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
654 }
655
RsaMethodSignRaw(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)656 int RsaMethodSignRaw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
657 size_t in_len, int padding) {
658 if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) {
659 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
660 return 0;
661 }
662
663 // Retrieve private key JNI reference.
664 const KeyExData* ex_data = RsaGetExData(rsa);
665 if (!ex_data || !ex_data->private_key) {
666 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
667 return 0;
668 }
669
670 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
671 if (env == nullptr) {
672 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
673 return 0;
674 }
675
676 // For RSA keys, this function behaves as RSA_private_encrypt with
677 // the specified padding.
678 ScopedLocalRef<jbyteArray> signature(
679 env, rsaSignDigestWithPrivateKey(env, ex_data->private_key, padding,
680 reinterpret_cast<const char*>(in), in_len));
681
682 if (signature.get() == nullptr) {
683 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
684 return 0;
685 }
686
687 ScopedByteArrayRO result(env, signature.get());
688
689 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
690 if (result.size() > expected_size) {
691 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
692 return 0;
693 }
694
695 if (max_out < expected_size) {
696 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
697 return 0;
698 }
699
700 // Copy result to OpenSSL-provided buffer. rsaSignDigestWithPrivateKey
701 // should pad with leading 0s, but if it doesn't, pad the result.
702 size_t zero_pad = expected_size - result.size();
703 memset(out, 0, zero_pad);
704 memcpy(out + zero_pad, &result[0], result.size());
705 *out_len = expected_size;
706
707 return 1;
708 }
709
RsaMethodDecrypt(RSA * rsa,size_t * out_len,uint8_t * out,size_t max_out,const uint8_t * in,size_t in_len,int padding)710 int RsaMethodDecrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out, const uint8_t* in,
711 size_t in_len, int padding) {
712 // Retrieve private key JNI reference.
713 const KeyExData* ex_data = RsaGetExData(rsa);
714 if (!ex_data || !ex_data->private_key) {
715 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
716 return 0;
717 }
718
719 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
720 if (env == nullptr) {
721 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
722 return 0;
723 }
724
725 // This function behaves as RSA_private_decrypt.
726 ScopedLocalRef<jbyteArray> cleartext(
727 env, rsaDecryptWithPrivateKey(env, ex_data->private_key, padding,
728 reinterpret_cast<const char*>(in), in_len));
729 if (cleartext.get() == nullptr) {
730 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
731 return 0;
732 }
733
734 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
735
736 if (max_out < cleartextBytes.size()) {
737 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
738 return 0;
739 }
740
741 // Copy result to OpenSSL-provided buffer.
742 memcpy(out, cleartextBytes.get(), cleartextBytes.size());
743 *out_len = cleartextBytes.size();
744
745 return 1;
746 }
747
748 // Custom ECDSA_METHOD that uses the platform APIs.
749 // Note that for now, only signing through ECDSA_sign() is really supported.
750 // all other method pointers are either stubs returning errors, or no-ops.
751
EcKeyGetKey(const EC_KEY * ec_key)752 jobject EcKeyGetKey(const EC_KEY* ec_key) {
753 KeyExData* ex_data =
754 reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(ec_key, g_ecdsa_exdata_index));
755 return ex_data->private_key;
756 }
757
EcdsaMethodSign(const uint8_t * digest,size_t digest_len,uint8_t * sig,unsigned int * sig_len,EC_KEY * ec_key)758 int EcdsaMethodSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
759 EC_KEY* ec_key) {
760 // Retrieve private key JNI reference.
761 jobject private_key = EcKeyGetKey(ec_key);
762 if (!private_key) {
763 CONSCRYPT_LOG_ERROR("Null JNI reference passed to EcdsaMethodSign!");
764 return 0;
765 }
766
767 JNIEnv* env = conscrypt::jniutil::getJNIEnv();
768 if (env == nullptr) {
769 return 0;
770 }
771
772 // Sign message with it through JNI.
773 ScopedLocalRef<jbyteArray> signature(
774 env, ecSignDigestWithPrivateKey(env, private_key,
775 reinterpret_cast<const char*>(digest), digest_len));
776 if (signature.get() == nullptr) {
777 CONSCRYPT_LOG_ERROR("Could not sign message in EcdsaMethodDoSign!");
778 return 0;
779 }
780
781 ScopedByteArrayRO signatureBytes(env, signature.get());
782 // Note: With ECDSA, the actual signature may be smaller than
783 // ECDSA_size().
784 size_t max_expected_size = ECDSA_size(ec_key);
785 if (signatureBytes.size() > max_expected_size) {
786 CONSCRYPT_LOG_ERROR("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
787 signatureBytes.size(), max_expected_size);
788 return 0;
789 }
790
791 memcpy(sig, signatureBytes.get(), signatureBytes.size());
792 *sig_len = static_cast<unsigned int>(signatureBytes.size());
793 return 1;
794 }
795
init_engine_globals()796 void init_engine_globals() {
797 g_rsa_exdata_index = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */,
798 nullptr /* new_func */, ExDataDup, ExDataFree);
799 g_ecdsa_exdata_index = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
800 nullptr /* new_func */, ExDataDup, ExDataFree);
801
802 g_rsa_method.common.is_static = 1;
803 g_rsa_method.sign_raw = RsaMethodSignRaw;
804 g_rsa_method.decrypt = RsaMethodDecrypt;
805 g_rsa_method.flags = RSA_FLAG_OPAQUE;
806
807 g_ecdsa_method.common.is_static = 1;
808 g_ecdsa_method.sign = EcdsaMethodSign;
809 g_ecdsa_method.flags = ECDSA_FLAG_OPAQUE;
810
811 g_engine = ENGINE_new();
812 ENGINE_set_RSA_method(g_engine, &g_rsa_method, sizeof(g_rsa_method));
813 ENGINE_set_ECDSA_method(g_engine, &g_ecdsa_method, sizeof(g_ecdsa_method));
814 }
815
816 } // anonymous namespace
817
818 #define THROW_SSLEXCEPTION (-2)
819 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
820 #define THROWN_EXCEPTION (-4)
821
822 /**
823 * Initialization phase for every OpenSSL job: Loads the Error strings, the
824 * crypto algorithms and reset the OpenSSL library
825 */
NativeCrypto_clinit(JNIEnv *,jclass)826 static void NativeCrypto_clinit(JNIEnv*, jclass) {
827 CRYPTO_library_init();
828 }
829
830 /**
831 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
832 */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)833 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e,
834 jbyteArray d, jbyteArray p, jbyteArray q,
835 jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
836 CHECK_ERROR_QUEUE_ON_RETURN;
837 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,
838 p, q, dmp1, dmq1, iqmp);
839
840 if (e == nullptr && d == nullptr) {
841 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
842 "e == null && d == null");
843 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == null && d == null");
844 return 0;
845 }
846
847 #if BORINGSSL_API_VERSION >= 20
848 bssl::UniquePtr<BIGNUM> nBN, eBN, dBN, pBN, qBN, dmp1BN, dmq1BN, iqmpBN;
849 nBN = arrayToBignum(env, n);
850 if (!nBN) {
851 return 0;
852 }
853 if (e != nullptr) {
854 eBN = arrayToBignum(env, e);
855 if (!eBN) {
856 return 0;
857 }
858 }
859 if (d != nullptr) {
860 dBN = arrayToBignum(env, d);
861 if (!dBN) {
862 return 0;
863 }
864 }
865 if (p != nullptr) {
866 pBN = arrayToBignum(env, p);
867 if (!pBN) {
868 return 0;
869 }
870 }
871 if (q != nullptr) {
872 qBN = arrayToBignum(env, q);
873 if (!qBN) {
874 return 0;
875 }
876 }
877 if (dmp1 != nullptr) {
878 dmp1BN = arrayToBignum(env, dmp1);
879 if (!dmp1BN) {
880 return 0;
881 }
882 }
883 if (dmq1 != nullptr) {
884 dmq1BN = arrayToBignum(env, dmq1);
885 if (!dmq1BN) {
886 return 0;
887 }
888 }
889 if (iqmp != nullptr) {
890 iqmpBN = arrayToBignum(env, iqmp);
891 if (!iqmpBN) {
892 return 0;
893 }
894 }
895
896 // Determine what kind of key this is.
897 //
898 // TODO(davidben): The caller already knows what kind of key they expect. Ideally we would have
899 // separate APIs for the caller. However, we currently tolerate, say, an RSAPrivateCrtKeySpec
900 // where most fields are null and silently make a public key out of it. This is probably a
901 // mistake, but would need to be a breaking change.
902 bssl::UniquePtr<RSA> rsa;
903 if (!dBN) {
904 rsa.reset(RSA_new_public_key(nBN.get(), eBN.get()));
905 } else if (!eBN) {
906 rsa.reset(RSA_new_private_key_no_e(nBN.get(), dBN.get()));
907 } else if (!pBN || !qBN || !dmp1BN || !dmq1BN || !iqmpBN) {
908 rsa.reset(RSA_new_private_key_no_crt(nBN.get(), eBN.get(), dBN.get()));
909 } else {
910 rsa.reset(RSA_new_private_key(nBN.get(), eBN.get(), dBN.get(), pBN.get(), qBN.get(),
911 dmp1BN.get(), dmq1BN.get(), iqmpBN.get()));
912 }
913 if (rsa == nullptr) {
914 conscrypt::jniutil::throwRuntimeException(env, "Creating RSA key failed");
915 return 0;
916 }
917 #else
918 bssl::UniquePtr<RSA> rsa(RSA_new());
919 if (rsa.get() == nullptr) {
920 conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
921 return 0;
922 }
923
924 if (!arrayToBignum(env, n, &rsa->n)) {
925 return 0;
926 }
927
928 if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
929 return 0;
930 }
931
932 if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
933 return 0;
934 }
935
936 if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
937 return 0;
938 }
939
940 if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
941 return 0;
942 }
943
944 if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
945 return 0;
946 }
947
948 if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
949 return 0;
950 }
951
952 if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
953 return 0;
954 }
955
956 if (conscrypt::trace::kWithJniTrace) {
957 if (p != nullptr && q != nullptr) {
958 int check = RSA_check_key(rsa.get());
959 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
960 }
961 }
962
963 if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
964 conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
965 return 0;
966 }
967
968 /*
969 * If the private exponent is available, there is the potential to do signing
970 * operations. However, we can only do blinding if the public exponent is also
971 * available. Disable blinding if the public exponent isn't available.
972 *
973 * TODO[kroot]: We should try to recover the public exponent by trying
974 * some common ones such 3, 17, or 65537.
975 */
976 if (rsa->d != nullptr && rsa->e == nullptr) {
977 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
978 rsa->flags |= RSA_FLAG_NO_BLINDING;
979 }
980 #endif
981
982 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
983 if (pkey.get() == nullptr) {
984 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
985 return 0;
986 }
987 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
988 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_new failed");
989 ERR_clear_error();
990 return 0;
991 }
992 OWNERSHIP_TRANSFERRED(rsa);
993 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", n,
994 e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
995 return reinterpret_cast<uintptr_t>(pkey.release());
996 }
997
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jobject groupRef,jobject pubkeyRef,jbyteArray keyJavaBytes)998 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
999 jobject pubkeyRef, jbyteArray keyJavaBytes) {
1000 CHECK_ERROR_QUEUE_ON_RETURN;
1001 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
1002 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1003 if (group == nullptr) {
1004 return 0;
1005 }
1006 const EC_POINT* pubkey =
1007 pubkeyRef == nullptr ? nullptr : fromContextObject<EC_POINT>(env, pubkeyRef);
1008 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
1009
1010 bssl::UniquePtr<BIGNUM> key(nullptr);
1011 if (keyJavaBytes != nullptr) {
1012 key = arrayToBignum(env, keyJavaBytes);
1013 if (!key) {
1014 return 0;
1015 }
1016 }
1017
1018 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
1019 if (eckey.get() == nullptr) {
1020 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_new failed");
1021 return 0;
1022 }
1023
1024 if (EC_KEY_set_group(eckey.get(), group) != 1) {
1025 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
1026 keyJavaBytes);
1027 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1028 return 0;
1029 }
1030
1031 if (pubkey != nullptr) {
1032 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 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_public_key");
1036 return 0;
1037 }
1038 }
1039
1040 if (key.get() != nullptr) {
1041 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
1042 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
1043 pubkey, keyJavaBytes);
1044 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1045 return 0;
1046 }
1047 if (pubkey == nullptr) {
1048 bssl::UniquePtr<EC_POINT> calcPubkey(EC_POINT_new(group));
1049 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), nullptr, nullptr, nullptr)) {
1050 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calculate public key", group,
1051 pubkey, keyJavaBytes);
1052 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_private_key");
1053 return 0;
1054 }
1055 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
1056 }
1057 }
1058
1059 if (!EC_KEY_check_key(eckey.get())) {
1060 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey,
1061 keyJavaBytes);
1062 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_check_key");
1063 return 0;
1064 }
1065
1066 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1067 if (pkey.get() == nullptr) {
1068 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1069 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new failed");
1070 return 0;
1071 }
1072 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
1073 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
1074 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
1075 ERR_clear_error();
1076 return 0;
1077 }
1078 OWNERSHIP_TRANSFERRED(eckey);
1079
1080 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
1081 return reinterpret_cast<uintptr_t>(pkey.release());
1082 }
1083
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jobject pkeyRef)1084 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
1085 CHECK_ERROR_QUEUE_ON_RETURN;
1086 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1087 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
1088
1089 if (pkey == nullptr) {
1090 return -1;
1091 }
1092
1093 int result = EVP_PKEY_id(pkey);
1094 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
1095 return result;
1096 }
1097
1098 typedef int print_func(BIO*, const EVP_PKEY*, int, ASN1_PCTX*);
1099
evp_print_func(JNIEnv * env,jobject pkeyRef,print_func * func,const char * debug_name)1100 static jstring evp_print_func(JNIEnv* env, jobject pkeyRef, print_func* func,
1101 const char* debug_name) {
1102 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1103 JNI_TRACE("%s(%p)", debug_name, pkey);
1104
1105 if (pkey == nullptr) {
1106 return nullptr;
1107 }
1108
1109 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
1110 if (buffer.get() == nullptr) {
1111 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
1112 return nullptr;
1113 }
1114
1115 if (func(buffer.get(), pkey, 0, nullptr) != 1) {
1116 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, debug_name);
1117 return nullptr;
1118 }
1119 // Null terminate this
1120 BIO_write(buffer.get(), "\0", 1);
1121
1122 char* tmp;
1123 BIO_get_mem_data(buffer.get(), &tmp);
1124 jstring description = env->NewStringUTF(tmp);
1125
1126 JNI_TRACE("%s(%p) => \"%s\"", debug_name, pkey, tmp);
1127 return description;
1128 }
1129
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jobject pkeyRef)1130 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
1131 CHECK_ERROR_QUEUE_ON_RETURN;
1132 return evp_print_func(env, pkeyRef, EVP_PKEY_print_public, "EVP_PKEY_print_public");
1133 }
1134
NativeCrypto_EVP_PKEY_print_params(JNIEnv * env,jclass,jobject pkeyRef)1135 static jstring NativeCrypto_EVP_PKEY_print_params(JNIEnv* env, jclass, jobject pkeyRef) {
1136 CHECK_ERROR_QUEUE_ON_RETURN;
1137 return evp_print_func(env, pkeyRef, EVP_PKEY_print_params, "EVP_PKEY_print_params");
1138 }
1139
NativeCrypto_EVP_PKEY_free(JNIEnv * env,jclass,jlong pkeyRef)1140 static void NativeCrypto_EVP_PKEY_free(JNIEnv* env, jclass, jlong pkeyRef) {
1141 CHECK_ERROR_QUEUE_ON_RETURN;
1142 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
1143 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
1144
1145 if (pkey != nullptr) {
1146 EVP_PKEY_free(pkey);
1147 }
1148 }
1149
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jobject pkey1Ref,jobject pkey2Ref)1150 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
1151 CHECK_ERROR_QUEUE_ON_RETURN;
1152 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
1153 EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
1154 if (pkey1 == nullptr) {
1155 JNI_TRACE("EVP_PKEY_cmp => pkey1 == null");
1156 return 0;
1157 }
1158 EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
1159 if (pkey2 == nullptr) {
1160 JNI_TRACE("EVP_PKEY_cmp => pkey2 == null");
1161 return 0;
1162 }
1163 JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
1164
1165 int result = EVP_PKEY_cmp(pkey1, pkey2);
1166 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
1167 return result;
1168 }
1169
1170 /*
1171 * static native byte[] EVP_marshal_private_key(long)
1172 */
NativeCrypto_EVP_marshal_private_key(JNIEnv * env,jclass,jobject pkeyRef)1173 static jbyteArray NativeCrypto_EVP_marshal_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
1174 CHECK_ERROR_QUEUE_ON_RETURN;
1175 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1176 JNI_TRACE("EVP_marshal_private_key(%p)", pkey);
1177
1178 if (pkey == nullptr) {
1179 return nullptr;
1180 }
1181
1182 bssl::ScopedCBB cbb;
1183 if (!CBB_init(cbb.get(), 64)) {
1184 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1185 JNI_TRACE("CBB_init failed");
1186 return nullptr;
1187 }
1188
1189 if (!EVP_marshal_private_key(cbb.get(), pkey)) {
1190 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_private_key");
1191 JNI_TRACE("key=%p EVP_marshal_private_key => error", pkey);
1192 return nullptr;
1193 }
1194
1195 return CBBToByteArray(env, cbb.get());
1196 }
1197
1198 /*
1199 * static native long EVP_parse_private_key(byte[])
1200 */
NativeCrypto_EVP_parse_private_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1201 static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1202 CHECK_ERROR_QUEUE_ON_RETURN;
1203 JNI_TRACE("EVP_parse_private_key(%p)", keyJavaBytes);
1204
1205 ScopedByteArrayRO bytes(env, keyJavaBytes);
1206 if (bytes.get() == nullptr) {
1207 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1208 return 0;
1209 }
1210
1211 CBS cbs;
1212 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1213 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
1214 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1215 // allow parsing keys from buffers that are larger than the contained key structure
1216 // so we do the same for compatibility.
1217 if (!pkey) {
1218 conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1219 ERR_clear_error();
1220 JNI_TRACE("bytes=%p EVP_parse_private_key => threw exception", keyJavaBytes);
1221 return 0;
1222 }
1223
1224 JNI_TRACE("bytes=%p EVP_parse_private_key => %p", keyJavaBytes, pkey.get());
1225 return reinterpret_cast<uintptr_t>(pkey.release());
1226 }
1227
1228
NativeCrypto_EVP_raw_X25519_private_key(JNIEnv * env,jclass cls,jbyteArray keyJavaBytes)1229 static jbyteArray NativeCrypto_EVP_raw_X25519_private_key(
1230 JNIEnv* env, jclass cls, jbyteArray keyJavaBytes) {
1231 CHECK_ERROR_QUEUE_ON_RETURN;
1232 JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key(%p)", keyJavaBytes);
1233
1234 jlong key_ptr = NativeCrypto_EVP_parse_private_key(env, cls, keyJavaBytes);
1235 if (key_ptr == 0) {
1236 return nullptr;
1237 }
1238 bssl::UniquePtr<EVP_PKEY> pkey(reinterpret_cast<EVP_PKEY*>(key_ptr));
1239 if (EVP_PKEY_id(pkey.get()) != EVP_PKEY_X25519) {
1240 conscrypt::jniutil::throwInvalidKeyException(env, "Invalid key type");
1241 return nullptr;
1242 }
1243
1244 size_t key_length = X25519_PRIVATE_KEY_LEN;
1245 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(key_length)));
1246 if (byteArray.get() == nullptr) {
1247 conscrypt::jniutil::throwOutOfMemory(env, "Allocating byte[]");
1248 JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: byte array creation failed");
1249 return nullptr;
1250 }
1251
1252 ScopedByteArrayRW bytes(env, byteArray.get());
1253 if (bytes.get() == nullptr) {
1254 conscrypt::jniutil::throwOutOfMemory(env, "Allocating scoped byte array");
1255 JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: scoped byte array failed");
1256 return nullptr;
1257 }
1258
1259 if (EVP_PKEY_get_raw_private_key(
1260 pkey.get(), reinterpret_cast<uint8_t *>(bytes.get()), &key_length) == 0) {
1261 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_raw_private_key");
1262 return nullptr;
1263 }
1264 jbyteArray result = byteArray.release();
1265 JNI_TRACE("bytes=%p NativeCrypto_EVP_raw_X25519_private_key => %p", keyJavaBytes, result);
1266 return result;
1267 }
1268
1269 /*
1270 * static native byte[] EVP_marshal_public_key(long)
1271 */
NativeCrypto_EVP_marshal_public_key(JNIEnv * env,jclass,jobject pkeyRef)1272 static jbyteArray NativeCrypto_EVP_marshal_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
1273 CHECK_ERROR_QUEUE_ON_RETURN;
1274 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1275 JNI_TRACE("EVP_marshal_public_key(%p)", pkey);
1276
1277 if (pkey == nullptr) {
1278 return nullptr;
1279 }
1280
1281 bssl::ScopedCBB cbb;
1282 if (!CBB_init(cbb.get(), 64)) {
1283 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
1284 JNI_TRACE("CBB_init failed");
1285 return nullptr;
1286 }
1287
1288 if (!EVP_marshal_public_key(cbb.get(), pkey)) {
1289 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_marshal_public_key");
1290 JNI_TRACE("key=%p EVP_marshal_public_key => error", pkey);
1291 return nullptr;
1292 }
1293
1294 return CBBToByteArray(env, cbb.get());
1295 }
1296
1297 /*
1298 * static native long EVP_parse_public_key(byte[])
1299 */
NativeCrypto_EVP_parse_public_key(JNIEnv * env,jclass,jbyteArray keyJavaBytes)1300 static jlong NativeCrypto_EVP_parse_public_key(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
1301 CHECK_ERROR_QUEUE_ON_RETURN;
1302 JNI_TRACE("EVP_parse_public_key(%p)", keyJavaBytes);
1303
1304 ScopedByteArrayRO bytes(env, keyJavaBytes);
1305 if (bytes.get() == nullptr) {
1306 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1307 return 0;
1308 }
1309
1310 CBS cbs;
1311 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
1312 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
1313 // We intentionally do not check that cbs is exhausted, as JCA providers typically
1314 // allow parsing keys from buffers that are larger than the contained key structure
1315 // so we do the same for compatibility.
1316 if (!pkey) {
1317 conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1318 ERR_clear_error();
1319 JNI_TRACE("bytes=%p EVP_parse_public_key => threw exception", keyJavaBytes);
1320 return 0;
1321 }
1322
1323 JNI_TRACE("bytes=%p EVP_parse_public_key => %p", keyJavaBytes, pkey.get());
1324 return reinterpret_cast<uintptr_t>(pkey.release());
1325 }
1326
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)1327 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1328 jbyteArray modulusBytes) {
1329 CHECK_ERROR_QUEUE_ON_RETURN;
1330 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
1331
1332 ensure_engine_globals();
1333
1334 #if BORINGSSL_API_VERSION >= 20
1335 // The PSS padding code needs access to the actual n, so set it even though we
1336 // don't set any other parts of the key
1337 bssl::UniquePtr<BIGNUM> n = arrayToBignum(env, modulusBytes);
1338 if (n == nullptr) {
1339 return 0;
1340 }
1341
1342 // TODO(crbug.com/boringssl/602): RSA_METHOD is not the ideal abstraction to use here.
1343 bssl::UniquePtr<RSA> rsa(RSA_new_method_no_e(g_engine, n.get()));
1344 if (rsa == nullptr) {
1345 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1346 return 0;
1347 }
1348 #else
1349 bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
1350 if (rsa == nullptr) {
1351 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1352 return 0;
1353 }
1354
1355 // The PSS padding code needs access to the actual n, so set it even though we
1356 // don't set any other parts of the key
1357 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
1358 return 0;
1359 }
1360 #endif
1361
1362 auto ex_data = new KeyExData;
1363 ex_data->private_key = env->NewGlobalRef(javaKey);
1364 RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
1365
1366 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1367 if (pkey.get() == nullptr) {
1368 JNI_TRACE("getRSAPrivateKeyWrapper failed");
1369 conscrypt::jniutil::throwRuntimeException(env,
1370 "NativeCrypto_getRSAPrivateKeyWrapper failed");
1371 ERR_clear_error();
1372 return 0;
1373 }
1374
1375 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1376 conscrypt::jniutil::throwRuntimeException(env, "getRSAPrivateKeyWrapper failed");
1377 ERR_clear_error();
1378 return 0;
1379 }
1380 OWNERSHIP_TRANSFERRED(rsa);
1381 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p) => %p", javaKey, modulusBytes, pkey.get());
1382 return reinterpret_cast<uintptr_t>(pkey.release());
1383 }
1384
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jobject groupRef)1385 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
1386 jobject groupRef) {
1387 CHECK_ERROR_QUEUE_ON_RETURN;
1388 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1389 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
1390 if (group == nullptr) {
1391 return 0;
1392 }
1393
1394 ensure_engine_globals();
1395
1396 bssl::UniquePtr<EC_KEY> ecKey(EC_KEY_new_method(g_engine));
1397 if (ecKey.get() == nullptr) {
1398 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate EC key");
1399 return 0;
1400 }
1401
1402 if (EC_KEY_set_group(ecKey.get(), group) != 1) {
1403 JNI_TRACE("getECPrivateKeyWrapper(%p, %p) => EC_KEY_set_group error", javaKey, group);
1404 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
1405 return 0;
1406 }
1407
1408 auto ex_data = new KeyExData;
1409 ex_data->private_key = env->NewGlobalRef(javaKey);
1410
1411 if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
1412 env->DeleteGlobalRef(ex_data->private_key);
1413 delete ex_data;
1414 conscrypt::jniutil::throwRuntimeException(env, "EC_KEY_set_ex_data");
1415 ERR_clear_error();
1416 return 0;
1417 }
1418
1419 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1420 if (pkey.get() == nullptr) {
1421 JNI_TRACE("getECPrivateKeyWrapper failed");
1422 conscrypt::jniutil::throwRuntimeException(env,
1423 "NativeCrypto_getECPrivateKeyWrapper failed");
1424 ERR_clear_error();
1425 return 0;
1426 }
1427
1428 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1429 conscrypt::jniutil::throwRuntimeException(env, "getECPrivateKeyWrapper failed");
1430 ERR_clear_error();
1431 return 0;
1432 }
1433 OWNERSHIP_TRANSFERRED(ecKey);
1434 return reinterpret_cast<uintptr_t>(pkey.release());
1435 }
1436
1437 /*
1438 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
1439 */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)1440 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
1441 jbyteArray publicExponent) {
1442 CHECK_ERROR_QUEUE_ON_RETURN;
1443 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
1444
1445 bssl::UniquePtr<BIGNUM> e = arrayToBignum(env, publicExponent);
1446 if (e == nullptr) {
1447 return 0;
1448 }
1449
1450 bssl::UniquePtr<RSA> rsa(RSA_new());
1451 if (rsa.get() == nullptr) {
1452 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1453 return 0;
1454 }
1455
1456 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), nullptr) != 1) {
1457 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "RSA_generate_key_ex failed");
1458 return 0;
1459 }
1460
1461 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
1462 if (pkey.get() == nullptr) {
1463 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
1464 return 0;
1465 }
1466
1467 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
1468 conscrypt::jniutil::throwRuntimeException(env, "RSA_generate_key_ex failed");
1469 ERR_clear_error();
1470 return 0;
1471 }
1472
1473 OWNERSHIP_TRANSFERRED(rsa);
1474 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
1475 return reinterpret_cast<uintptr_t>(pkey.release());
1476 }
1477
NativeCrypto_RSA_size(JNIEnv * env,jclass,jobject pkeyRef)1478 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
1479 CHECK_ERROR_QUEUE_ON_RETURN;
1480 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1481 JNI_TRACE("RSA_size(%p)", pkey);
1482
1483 if (pkey == nullptr) {
1484 return 0;
1485 }
1486
1487 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1488 if (rsa.get() == nullptr) {
1489 conscrypt::jniutil::throwRuntimeException(env, "RSA_size failed");
1490 ERR_clear_error();
1491 return 0;
1492 }
1493
1494 return static_cast<jint>(RSA_size(rsa.get()));
1495 }
1496
1497 typedef int RSACryptOperation(size_t flen, const unsigned char* from, unsigned char* to, RSA* rsa,
1498 int padding);
1499
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1500 static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
1501 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1502 jobject pkeyRef, jint padding) {
1503 CHECK_ERROR_QUEUE_ON_RETURN;
1504 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1505 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
1506
1507 if (pkey == nullptr) {
1508 return -1;
1509 }
1510
1511 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1512 if (rsa.get() == nullptr) {
1513 return -1;
1514 }
1515
1516 ScopedByteArrayRO from(env, fromJavaBytes);
1517 if (from.get() == nullptr) {
1518 return -1;
1519 }
1520
1521 ScopedByteArrayRW to(env, toJavaBytes);
1522 if (to.get() == nullptr) {
1523 return -1;
1524 }
1525
1526 int resultSize =
1527 operation(static_cast<size_t>(flen), reinterpret_cast<const unsigned char*>(from.get()),
1528 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
1529 if (resultSize == -1) {
1530 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, caller,
1531 conscrypt::jniutil::throwBadPaddingException);
1532 JNI_TRACE("%s => threw error", caller);
1533 return -1;
1534 }
1535
1536 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
1537 resultSize);
1538 return static_cast<jint>(resultSize);
1539 }
1540
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1541 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
1542 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1543 jobject pkeyRef, jint padding) {
1544 CHECK_ERROR_QUEUE_ON_RETURN;
1545 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1546 toJavaBytes, pkeyRef, padding);
1547 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1548 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
1549 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1550 jobject pkeyRef, jint padding) {
1551 CHECK_ERROR_QUEUE_ON_RETURN;
1552 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1553 toJavaBytes, pkeyRef, padding);
1554 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1555 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
1556 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1557 jobject pkeyRef, jint padding) {
1558 CHECK_ERROR_QUEUE_ON_RETURN;
1559 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, env, flen, fromJavaBytes,
1560 toJavaBytes, pkeyRef, padding);
1561 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jobject pkeyRef,jint padding)1562 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
1563 jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
1564 jobject pkeyRef, jint padding) {
1565 CHECK_ERROR_QUEUE_ON_RETURN;
1566 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, env, flen, fromJavaBytes,
1567 toJavaBytes, pkeyRef, padding);
1568 }
1569
1570 /*
1571 * public static native byte[][] get_RSA_public_params(long);
1572 */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jobject pkeyRef)1573 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
1574 CHECK_ERROR_QUEUE_ON_RETURN;
1575 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1576 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1577
1578 if (pkey == nullptr) {
1579 return nullptr;
1580 }
1581
1582 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1583 if (rsa.get() == nullptr) {
1584 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1585 return nullptr;
1586 }
1587
1588 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
1589 if (joa == nullptr) {
1590 return nullptr;
1591 }
1592
1593 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1594 if (env->ExceptionCheck()) {
1595 return nullptr;
1596 }
1597 env->SetObjectArrayElement(joa, 0, n);
1598
1599 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1600 if (env->ExceptionCheck()) {
1601 return nullptr;
1602 }
1603 env->SetObjectArrayElement(joa, 1, e);
1604
1605 return joa;
1606 }
1607
1608 /*
1609 * public static native byte[][] get_RSA_private_params(long);
1610 */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jobject pkeyRef)1611 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
1612 CHECK_ERROR_QUEUE_ON_RETURN;
1613 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1614 JNI_TRACE("get_RSA_public_params(%p)", pkey);
1615
1616 if (pkey == nullptr) {
1617 return nullptr;
1618 }
1619
1620 bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey));
1621 if (rsa.get() == nullptr) {
1622 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "get_RSA_public_params failed");
1623 return nullptr;
1624 }
1625
1626 jobjectArray joa = env->NewObjectArray(8, conscrypt::jniutil::byteArrayClass, nullptr);
1627 if (joa == nullptr) {
1628 return nullptr;
1629 }
1630
1631 jbyteArray n = bignumToArray(env, RSA_get0_n(rsa.get()), "n");
1632 if (env->ExceptionCheck()) {
1633 return nullptr;
1634 }
1635 env->SetObjectArrayElement(joa, 0, n);
1636
1637 if (RSA_get0_e(rsa.get()) != nullptr) {
1638 jbyteArray e = bignumToArray(env, RSA_get0_e(rsa.get()), "e");
1639 if (env->ExceptionCheck()) {
1640 return nullptr;
1641 }
1642 env->SetObjectArrayElement(joa, 1, e);
1643 }
1644
1645 if (RSA_get0_d(rsa.get()) != nullptr) {
1646 jbyteArray d = bignumToArray(env, RSA_get0_d(rsa.get()), "d");
1647 if (env->ExceptionCheck()) {
1648 return nullptr;
1649 }
1650 env->SetObjectArrayElement(joa, 2, d);
1651 }
1652
1653 if (RSA_get0_p(rsa.get()) != nullptr) {
1654 jbyteArray p = bignumToArray(env, RSA_get0_p(rsa.get()), "p");
1655 if (env->ExceptionCheck()) {
1656 return nullptr;
1657 }
1658 env->SetObjectArrayElement(joa, 3, p);
1659 }
1660
1661 if (RSA_get0_q(rsa.get()) != nullptr) {
1662 jbyteArray q = bignumToArray(env, RSA_get0_q(rsa.get()), "q");
1663 if (env->ExceptionCheck()) {
1664 return nullptr;
1665 }
1666 env->SetObjectArrayElement(joa, 4, q);
1667 }
1668
1669 if (RSA_get0_dmp1(rsa.get()) != nullptr) {
1670 jbyteArray dmp1 = bignumToArray(env, RSA_get0_dmp1(rsa.get()), "dmp1");
1671 if (env->ExceptionCheck()) {
1672 return nullptr;
1673 }
1674 env->SetObjectArrayElement(joa, 5, dmp1);
1675 }
1676
1677 if (RSA_get0_dmq1(rsa.get()) != nullptr) {
1678 jbyteArray dmq1 = bignumToArray(env, RSA_get0_dmq1(rsa.get()), "dmq1");
1679 if (env->ExceptionCheck()) {
1680 return nullptr;
1681 }
1682 env->SetObjectArrayElement(joa, 6, dmq1);
1683 }
1684
1685 if (RSA_get0_iqmp(rsa.get()) != nullptr) {
1686 jbyteArray iqmp = bignumToArray(env, RSA_get0_iqmp(rsa.get()), "iqmp");
1687 if (env->ExceptionCheck()) {
1688 return nullptr;
1689 }
1690 env->SetObjectArrayElement(joa, 7, iqmp);
1691 }
1692
1693 return joa;
1694 }
1695
NativeCrypto_chacha20_encrypt_decrypt(JNIEnv * env,jclass,jbyteArray inBytes,jint inOffset,jbyteArray outBytes,jint outOffset,jint length,jbyteArray keyBytes,jbyteArray nonceBytes,jint blockCounter)1696 static void NativeCrypto_chacha20_encrypt_decrypt(JNIEnv* env, jclass, jbyteArray inBytes,
1697 jint inOffset, jbyteArray outBytes, jint outOffset, jint length, jbyteArray keyBytes,
1698 jbyteArray nonceBytes, jint blockCounter) {
1699 CHECK_ERROR_QUEUE_ON_RETURN;
1700 JNI_TRACE("chacha20_encrypt_decrypt");
1701 ScopedByteArrayRO in(env, inBytes);
1702 if (in.get() == nullptr) {
1703 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read input bytes");
1704 return;
1705 }
1706 ScopedByteArrayRW out(env, outBytes);
1707 if (out.get() == nullptr) {
1708 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read output bytes");
1709 return;
1710 }
1711 ScopedByteArrayRO key(env, keyBytes);
1712 if (key.get() == nullptr) {
1713 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read key bytes");
1714 return;
1715 }
1716 ScopedByteArrayRO nonce(env, nonceBytes);
1717 if (nonce.get() == nullptr) {
1718 JNI_TRACE("chacha20_encrypt_decrypt => threw exception: could not read nonce bytes");
1719 return;
1720 }
1721
1722 CRYPTO_chacha_20(
1723 reinterpret_cast<unsigned char*>(out.get()) + outOffset,
1724 reinterpret_cast<const unsigned char*>(in.get()) + inOffset,
1725 length,
1726 reinterpret_cast<const unsigned char*>(key.get()),
1727 reinterpret_cast<const unsigned char*>(nonce.get()),
1728 blockCounter);
1729 }
1730
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)1731 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) {
1732 CHECK_ERROR_QUEUE_ON_RETURN;
1733 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
1734
1735 ScopedUtfChars curveName(env, curveNameJava);
1736 if (curveName.c_str() == nullptr) {
1737 return 0;
1738 }
1739 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
1740
1741 int nid = OBJ_sn2nid(curveName.c_str());
1742 if (nid == NID_undef) {
1743 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
1744 return 0;
1745 }
1746
1747 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
1748 if (group == nullptr) {
1749 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
1750 ERR_clear_error();
1751 return 0;
1752 }
1753
1754 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
1755 return reinterpret_cast<uintptr_t>(group);
1756 }
1757
NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv * env,jclass,jbyteArray pBytes,jbyteArray aBytes,jbyteArray bBytes,jbyteArray xBytes,jbyteArray yBytes,jbyteArray orderBytes,jint cofactorInt)1758 static jlong NativeCrypto_EC_GROUP_new_arbitrary(JNIEnv* env, jclass, jbyteArray pBytes,
1759 jbyteArray aBytes, jbyteArray bBytes,
1760 jbyteArray xBytes, jbyteArray yBytes,
1761 jbyteArray orderBytes, jint cofactorInt) {
1762 CHECK_ERROR_QUEUE_ON_RETURN;
1763 JNI_TRACE("EC_GROUP_new_arbitrary");
1764
1765 if (cofactorInt < 1) {
1766 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1767 "cofactor < 1");
1768 return 0;
1769 }
1770
1771 bssl::UniquePtr<BIGNUM> p = arrayToBignum(env, pBytes);
1772 if (p == nullptr) {
1773 return 0;
1774 }
1775 bssl::UniquePtr<BIGNUM> a = arrayToBignum(env, aBytes);
1776 if (a == nullptr) {
1777 return 0;
1778 }
1779 bssl::UniquePtr<BIGNUM> b = arrayToBignum(env, bBytes);
1780 if (b == nullptr) {
1781 return 0;
1782 }
1783 bssl::UniquePtr<BIGNUM> x = arrayToBignum(env, xBytes);
1784 if (x == nullptr) {
1785 return 0;
1786 }
1787 bssl::UniquePtr<BIGNUM> y = arrayToBignum(env, yBytes);
1788 if (y == nullptr) {
1789 return 0;
1790 }
1791 bssl::UniquePtr<BIGNUM> order = arrayToBignum(env, orderBytes);
1792 if (order == nullptr) {
1793 return 0;
1794 }
1795 bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1796 if (cofactor == nullptr || !BN_set_word(cofactor.get(), static_cast<uint32_t>(cofactorInt))) {
1797 return 0;
1798 }
1799
1800 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1801 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
1802 if (group.get() == nullptr) {
1803 JNI_TRACE("EC_GROUP_new_curve_GFp => null");
1804 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_new_curve_GFp");
1805 return 0;
1806 }
1807
1808 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
1809 if (generator.get() == nullptr) {
1810 JNI_TRACE("EC_POINT_new => null");
1811 ERR_clear_error();
1812 return 0;
1813 }
1814
1815 if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x.get(), y.get(), ctx.get())) {
1816 JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
1817 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
1818 "EC_POINT_set_affine_coordinates_GFp");
1819 return 0;
1820 }
1821
1822 if (!EC_GROUP_set_generator(group.get(), generator.get(), order.get(), cofactor.get())) {
1823 JNI_TRACE("EC_GROUP_set_generator => error");
1824 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_set_generator");
1825 return 0;
1826 }
1827
1828 JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
1829 return reinterpret_cast<uintptr_t>(group.release());
1830 }
1831
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jobject groupRef)1832 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
1833 CHECK_ERROR_QUEUE_ON_RETURN;
1834 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1835 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
1836
1837 if (group == nullptr) {
1838 JNI_TRACE("EC_GROUP_get_curve_name => group == null");
1839 return nullptr;
1840 }
1841
1842 int nid = EC_GROUP_get_curve_name(group);
1843 if (nid == NID_undef) {
1844 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
1845 return nullptr;
1846 }
1847
1848 const char* shortName = OBJ_nid2sn(nid);
1849 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
1850 return env->NewStringUTF(shortName);
1851 }
1852
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jobject groupRef)1853 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef) {
1854 CHECK_ERROR_QUEUE_ON_RETURN;
1855 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1856 JNI_TRACE("EC_GROUP_get_curve(%p)", group);
1857 if (group == nullptr) {
1858 JNI_TRACE("EC_GROUP_get_curve => group == null");
1859 return nullptr;
1860 }
1861
1862 bssl::UniquePtr<BIGNUM> p(BN_new());
1863 bssl::UniquePtr<BIGNUM> a(BN_new());
1864 bssl::UniquePtr<BIGNUM> b(BN_new());
1865
1866 int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr);
1867 if (ret != 1) {
1868 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_curve");
1869 return nullptr;
1870 }
1871
1872 jobjectArray joa = env->NewObjectArray(3, conscrypt::jniutil::byteArrayClass, nullptr);
1873 if (joa == nullptr) {
1874 return nullptr;
1875 }
1876
1877 jbyteArray pArray = bignumToArray(env, p.get(), "p");
1878 if (env->ExceptionCheck()) {
1879 return nullptr;
1880 }
1881 env->SetObjectArrayElement(joa, 0, pArray);
1882
1883 jbyteArray aArray = bignumToArray(env, a.get(), "a");
1884 if (env->ExceptionCheck()) {
1885 return nullptr;
1886 }
1887 env->SetObjectArrayElement(joa, 1, aArray);
1888
1889 jbyteArray bArray = bignumToArray(env, b.get(), "b");
1890 if (env->ExceptionCheck()) {
1891 return nullptr;
1892 }
1893 env->SetObjectArrayElement(joa, 2, bArray);
1894
1895 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
1896 return joa;
1897 }
1898
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jobject groupRef)1899 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef) {
1900 CHECK_ERROR_QUEUE_ON_RETURN;
1901 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1902 JNI_TRACE("EC_GROUP_get_order(%p)", group);
1903 if (group == nullptr) {
1904 return nullptr;
1905 }
1906
1907 bssl::UniquePtr<BIGNUM> order(BN_new());
1908 if (order.get() == nullptr) {
1909 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
1910 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1911 return nullptr;
1912 }
1913
1914 if (EC_GROUP_get_order(group, order.get(), nullptr) != 1) {
1915 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
1916 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_order");
1917 return nullptr;
1918 }
1919
1920 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
1921 if (env->ExceptionCheck()) {
1922 return nullptr;
1923 }
1924
1925 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
1926 return orderArray;
1927 }
1928
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jobject groupRef)1929 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef) {
1930 CHECK_ERROR_QUEUE_ON_RETURN;
1931 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1932 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
1933 if (group == nullptr) {
1934 return 0;
1935 }
1936
1937 jint degree = static_cast<jint>(EC_GROUP_get_degree(group));
1938 if (degree == 0) {
1939 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
1940 conscrypt::jniutil::throwRuntimeException(env, "not supported");
1941 ERR_clear_error();
1942 return 0;
1943 }
1944
1945 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
1946 return degree;
1947 }
1948
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jobject groupRef)1949 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef) {
1950 CHECK_ERROR_QUEUE_ON_RETURN;
1951 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1952 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
1953 if (group == nullptr) {
1954 return nullptr;
1955 }
1956
1957 bssl::UniquePtr<BIGNUM> cofactor(BN_new());
1958 if (cofactor.get() == nullptr) {
1959 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
1960 conscrypt::jniutil::throwOutOfMemory(env, "BN_new");
1961 return nullptr;
1962 }
1963
1964 if (EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) != 1) {
1965 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
1966 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_GROUP_get_cofactor");
1967 return nullptr;
1968 }
1969
1970 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
1971 if (env->ExceptionCheck()) {
1972 return nullptr;
1973 }
1974
1975 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
1976 return cofactorArray;
1977 }
1978
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)1979 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) {
1980 CHECK_ERROR_QUEUE_ON_RETURN;
1981 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
1982 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
1983
1984 if (group == nullptr) {
1985 JNI_TRACE("EC_GROUP_clear_free => group == null");
1986 conscrypt::jniutil::throwNullPointerException(env, "group == null");
1987 return;
1988 }
1989
1990 EC_GROUP_free(group);
1991 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
1992 }
1993
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jobject groupRef)1994 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef) {
1995 CHECK_ERROR_QUEUE_ON_RETURN;
1996 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
1997 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
1998
1999 if (group == nullptr) {
2000 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
2001 return 0;
2002 }
2003
2004 const EC_POINT* generator = EC_GROUP_get0_generator(group);
2005
2006 bssl::UniquePtr<EC_POINT> dup(EC_POINT_dup(generator, group));
2007 if (dup.get() == nullptr) {
2008 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
2009 conscrypt::jniutil::throwOutOfMemory(env, "unable to dupe generator");
2010 return 0;
2011 }
2012
2013 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
2014 return reinterpret_cast<uintptr_t>(dup.release());
2015 }
2016
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jobject groupRef)2017 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef) {
2018 CHECK_ERROR_QUEUE_ON_RETURN;
2019 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2020 JNI_TRACE("EC_POINT_new(%p)", group);
2021
2022 if (group == nullptr) {
2023 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
2024 return 0;
2025 }
2026
2027 EC_POINT* point = EC_POINT_new(group);
2028 if (point == nullptr) {
2029 conscrypt::jniutil::throwOutOfMemory(env, "Unable create an EC_POINT");
2030 return 0;
2031 }
2032
2033 return reinterpret_cast<uintptr_t>(point);
2034 }
2035
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)2036 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
2037 CHECK_ERROR_QUEUE_ON_RETURN;
2038 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
2039 JNI_TRACE("EC_POINT_clear_free(%p)", group);
2040
2041 if (group == nullptr) {
2042 JNI_TRACE("EC_POINT_clear_free => group == null");
2043 conscrypt::jniutil::throwNullPointerException(env, "group == null");
2044 return;
2045 }
2046
2047 EC_POINT_free(group);
2048 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
2049 }
2050
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)2051 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, jobject groupRef,
2052 jobject pointRef, jbyteArray xjavaBytes,
2053 jbyteArray yjavaBytes) {
2054 CHECK_ERROR_QUEUE_ON_RETURN;
2055 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
2056 yjavaBytes);
2057 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2058 if (group == nullptr) {
2059 return;
2060 }
2061 EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2062 if (point == nullptr) {
2063 return;
2064 }
2065 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
2066 yjavaBytes);
2067
2068 bssl::UniquePtr<BIGNUM> x = arrayToBignum(env, xjavaBytes);
2069 if (x == nullptr) {
2070 return;
2071 }
2072
2073 bssl::UniquePtr<BIGNUM> y = arrayToBignum(env, yjavaBytes);
2074 if (y == nullptr) {
2075 return;
2076 }
2077
2078 int ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2079 if (ret != 1) {
2080 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2081 "EC_POINT_set_affine_coordinates");
2082 return;
2083 }
2084
2085 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, xjavaBytes,
2086 yjavaBytes, ret);
2087 }
2088
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jobject groupRef,jobject pointRef)2089 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
2090 jobject groupRef,
2091 jobject pointRef) {
2092 CHECK_ERROR_QUEUE_ON_RETURN;
2093 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
2094 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2095 if (group == nullptr) {
2096 return nullptr;
2097 }
2098 const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
2099 if (point == nullptr) {
2100 return nullptr;
2101 }
2102 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
2103
2104 bssl::UniquePtr<BIGNUM> x(BN_new());
2105 bssl::UniquePtr<BIGNUM> y(BN_new());
2106
2107 int ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), nullptr);
2108 if (ret != 1) {
2109 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
2110 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
2111 "EC_POINT_get_affine_coordinates");
2112 return nullptr;
2113 }
2114
2115 jobjectArray joa = env->NewObjectArray(2, conscrypt::jniutil::byteArrayClass, nullptr);
2116 if (joa == nullptr) {
2117 return nullptr;
2118 }
2119
2120 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
2121 if (env->ExceptionCheck()) {
2122 return nullptr;
2123 }
2124 env->SetObjectArrayElement(joa, 0, xBytes);
2125
2126 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
2127 if (env->ExceptionCheck()) {
2128 return nullptr;
2129 }
2130 env->SetObjectArrayElement(joa, 1, yBytes);
2131
2132 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
2133 return joa;
2134 }
2135
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jobject groupRef)2136 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef) {
2137 CHECK_ERROR_QUEUE_ON_RETURN;
2138 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2139 JNI_TRACE("EC_KEY_generate_key(%p)", group);
2140 if (group == nullptr) {
2141 return 0;
2142 }
2143
2144 bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
2145 if (eckey.get() == nullptr) {
2146 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
2147 conscrypt::jniutil::throwOutOfMemory(env, "Unable to create an EC_KEY");
2148 return 0;
2149 }
2150
2151 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2152 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
2153 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2154 return 0;
2155 }
2156
2157 if (EC_KEY_generate_key(eckey.get()) != 1) {
2158 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
2159 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_set_group");
2160 return 0;
2161 }
2162
2163 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
2164 if (pkey.get() == nullptr) {
2165 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
2166 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EC_KEY_generate_key");
2167 return 0;
2168 }
2169 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2170 conscrypt::jniutil::throwRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2171 ERR_clear_error();
2172 return 0;
2173 }
2174 OWNERSHIP_TRANSFERRED(eckey);
2175
2176 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
2177 return reinterpret_cast<uintptr_t>(pkey.release());
2178 }
2179
NativeCrypto_EC_KEY_get1_group(JNIEnv * env,jclass,jobject pkeyRef)2180 static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef) {
2181 CHECK_ERROR_QUEUE_ON_RETURN;
2182 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2183 JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
2184
2185 if (pkey == nullptr) {
2186 JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
2187 return 0;
2188 }
2189
2190 if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
2191 conscrypt::jniutil::throwRuntimeException(env, "not EC key");
2192 JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey, EVP_PKEY_id(pkey));
2193 return 0;
2194 }
2195
2196 EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)));
2197 JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
2198 return reinterpret_cast<uintptr_t>(group);
2199 }
2200
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jobject pkeyRef)2201 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef) {
2202 CHECK_ERROR_QUEUE_ON_RETURN;
2203 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2204 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
2205
2206 if (pkey == nullptr) {
2207 JNI_TRACE("EC_KEY_get_private_key => pkey == null");
2208 return nullptr;
2209 }
2210
2211 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2212 if (eckey.get() == nullptr) {
2213 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2214 return nullptr;
2215 }
2216
2217 const BIGNUM* privkey = EC_KEY_get0_private_key(eckey.get());
2218
2219 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
2220 if (env->ExceptionCheck()) {
2221 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
2222 return nullptr;
2223 }
2224
2225 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
2226 return privBytes;
2227 }
2228
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jobject pkeyRef)2229 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef) {
2230 CHECK_ERROR_QUEUE_ON_RETURN;
2231 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2232 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
2233
2234 if (pkey == nullptr) {
2235 JNI_TRACE("EC_KEY_get_public_key => pkey == null");
2236 return 0;
2237 }
2238
2239 bssl::UniquePtr<EC_KEY> eckey(EVP_PKEY_get1_EC_KEY(pkey));
2240 if (eckey.get() == nullptr) {
2241 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY");
2242 return 0;
2243 }
2244
2245 bssl::UniquePtr<EC_POINT> dup(
2246 EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), EC_KEY_get0_group(eckey.get())));
2247 if (dup.get() == nullptr) {
2248 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
2249 conscrypt::jniutil::throwRuntimeException(env, "EC_POINT_dup");
2250 ERR_clear_error();
2251 return 0;
2252 }
2253
2254 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
2255 return reinterpret_cast<uintptr_t>(dup.release());
2256 }
2257
NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv * env,jclass,jobject groupRef)2258 static jbyteArray NativeCrypto_EC_KEY_marshal_curve_name(JNIEnv* env, jclass, jobject groupRef) {
2259 CHECK_ERROR_QUEUE_ON_RETURN;
2260 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
2261 JNI_TRACE("EC_KEY_marshal_curve_name(%p)", group);
2262 if (group == nullptr) {
2263 env->ExceptionClear();
2264 conscrypt::jniutil::throwIOException(env, "Invalid group pointer");
2265 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => Invalid group pointer", group);
2266 return nullptr;
2267 }
2268
2269 bssl::ScopedCBB cbb;
2270 if (!CBB_init(cbb.get(), 64)) {
2271 conscrypt::jniutil::throwOutOfMemory(env, "CBB_init failed");
2272 JNI_TRACE("CBB_init failed");
2273 return nullptr;
2274 }
2275
2276 if (!EC_KEY_marshal_curve_name(cbb.get(), group)) {
2277 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
2278 ERR_clear_error();
2279 JNI_TRACE("group=%p EC_KEY_marshal_curve_name => error", group);
2280 return nullptr;
2281 }
2282
2283 return CBBToByteArray(env, cbb.get());
2284 }
2285
NativeCrypto_EC_KEY_parse_curve_name(JNIEnv * env,jclass,jbyteArray curveNameBytes)2286 static jlong NativeCrypto_EC_KEY_parse_curve_name(JNIEnv* env, jclass, jbyteArray curveNameBytes) {
2287 CHECK_ERROR_QUEUE_ON_RETURN;
2288 JNI_TRACE("EC_KEY_parse_curve_name(%p)", curveNameBytes);
2289
2290 ScopedByteArrayRO bytes(env, curveNameBytes);
2291 if (bytes.get() == nullptr) {
2292 env->ExceptionClear();
2293 conscrypt::jniutil::throwIOException(env, "Null EC curve name");
2294 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => curveNameBytes == null ", curveNameBytes);
2295 return 0;
2296 }
2297
2298 CBS cbs;
2299 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size());
2300 bssl::UniquePtr<EC_GROUP> group(EC_KEY_parse_curve_name(&cbs));
2301 if (!group || CBS_len(&cbs) != 0) {
2302 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
2303 ERR_clear_error();
2304 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => threw exception", curveNameBytes);
2305 return 0;
2306 }
2307
2308 JNI_TRACE("bytes=%p EC_KEY_parse_curve_name => %p", curveNameBytes, group.get());
2309 return reinterpret_cast<uintptr_t>(group.release());
2310 }
2311
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jobject pubkeyRef,jobject privkeyRef)2312 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, jbyteArray outArray, jint outOffset,
2313 jobject pubkeyRef, jobject privkeyRef) {
2314 CHECK_ERROR_QUEUE_ON_RETURN;
2315 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
2316 EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
2317 if (pubPkey == nullptr) {
2318 JNI_TRACE("ECDH_compute_key => pubPkey == null");
2319 return -1;
2320 }
2321 EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
2322 if (privPkey == nullptr) {
2323 JNI_TRACE("ECDH_compute_key => privPkey == null");
2324 return -1;
2325 }
2326 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
2327
2328 ScopedByteArrayRW out(env, outArray);
2329 if (out.get() == nullptr) {
2330 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", outArray, outOffset,
2331 pubPkey, privPkey);
2332 return -1;
2333 }
2334
2335 if (ARRAY_OFFSET_INVALID(out, outOffset)) {
2336 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2337 nullptr);
2338 return -1;
2339 }
2340
2341 if (pubPkey == nullptr) {
2342 JNI_TRACE("ECDH_compute_key(%p) => pubPkey == null", pubPkey);
2343 conscrypt::jniutil::throwNullPointerException(env, "pubPkey == null");
2344 return -1;
2345 }
2346
2347 bssl::UniquePtr<EC_KEY> pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
2348 if (pubkey.get() == nullptr) {
2349 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
2350 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2351 conscrypt::jniutil::throwInvalidKeyException);
2352 return -1;
2353 }
2354
2355 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
2356 if (pubkeyPoint == nullptr) {
2357 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
2358 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY public",
2359 conscrypt::jniutil::throwInvalidKeyException);
2360 return -1;
2361 }
2362
2363 if (privPkey == nullptr) {
2364 JNI_TRACE("ECDH_compute_key(%p) => privKey == null", pubPkey);
2365 conscrypt::jniutil::throwNullPointerException(env, "privPkey == null");
2366 return -1;
2367 }
2368
2369 bssl::UniquePtr<EC_KEY> privkey(EVP_PKEY_get1_EC_KEY(privPkey));
2370 if (privkey.get() == nullptr) {
2371 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get1_EC_KEY private",
2372 conscrypt::jniutil::throwInvalidKeyException);
2373 return -1;
2374 }
2375
2376 std::size_t stdOutOffset = static_cast<std::size_t>(outOffset);
2377 int outputLength = ECDH_compute_key(&out[stdOutOffset], out.size() - stdOutOffset, pubkeyPoint,
2378 privkey.get(), nullptr /* No KDF */);
2379 if (outputLength == -1) {
2380 JNI_TRACE("ECDH_compute_key(%p) => outputLength = -1", pubPkey);
2381 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDH_compute_key",
2382 conscrypt::jniutil::throwInvalidKeyException);
2383 return -1;
2384 }
2385
2386 JNI_TRACE("ECDH_compute_key(%p) => outputLength=%d", pubPkey, outputLength);
2387 return outputLength;
2388 }
2389
NativeCrypto_ECDSA_size(JNIEnv * env,jclass,jobject pkeyRef)2390 static jint NativeCrypto_ECDSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
2391 CHECK_ERROR_QUEUE_ON_RETURN;
2392 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2393 JNI_TRACE("ECDSA_size(%p)", pkey);
2394
2395 if (pkey == nullptr) {
2396 return 0;
2397 }
2398
2399 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2400 if (ec_key.get() == nullptr) {
2401 conscrypt::jniutil::throwRuntimeException(env, "ECDSA_size failed");
2402 ERR_clear_error();
2403 return 0;
2404 }
2405
2406 size_t size = ECDSA_size(ec_key.get());
2407
2408 JNI_TRACE("ECDSA_size(%p) => %zu", pkey, size);
2409 return static_cast<jint>(size);
2410 }
2411
NativeCrypto_ECDSA_sign(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2412 static jint NativeCrypto_ECDSA_sign(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2413 jobject pkeyRef) {
2414 CHECK_ERROR_QUEUE_ON_RETURN;
2415 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2416 JNI_TRACE("ECDSA_sign(%p, %p, %p)", data, sig, pkey);
2417
2418 if (pkey == nullptr) {
2419 return -1;
2420 }
2421
2422 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2423 if (ec_key.get() == nullptr) {
2424 return -1;
2425 }
2426
2427 ScopedByteArrayRO data_array(env, data);
2428 if (data_array.get() == nullptr) {
2429 return -1;
2430 }
2431
2432 ScopedByteArrayRW sig_array(env, sig);
2433 if (sig_array.get() == nullptr) {
2434 return -1;
2435 }
2436
2437 unsigned int sig_size;
2438 int result = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2439 data_array.size(), reinterpret_cast<unsigned char*>(sig_array.get()),
2440 &sig_size, ec_key.get());
2441 if (result == 0) {
2442 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_sign");
2443 JNI_TRACE("ECDSA_sign => threw error");
2444 return -1;
2445 }
2446
2447 JNI_TRACE("ECDSA_sign(%p, %p, %p) => %d", data, sig, pkey, sig_size);
2448 return static_cast<jint>(sig_size);
2449 }
2450
NativeCrypto_ECDSA_verify(JNIEnv * env,jclass,jbyteArray data,jbyteArray sig,jobject pkeyRef)2451 static jint NativeCrypto_ECDSA_verify(JNIEnv* env, jclass, jbyteArray data, jbyteArray sig,
2452 jobject pkeyRef) {
2453 CHECK_ERROR_QUEUE_ON_RETURN;
2454 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2455 JNI_TRACE("ECDSA_verify(%p, %p, %p)", data, sig, pkey);
2456
2457 if (pkey == nullptr) {
2458 return -1;
2459 }
2460
2461 bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey));
2462 if (ec_key.get() == nullptr) {
2463 return -1;
2464 }
2465
2466 ScopedByteArrayRO data_array(env, data);
2467 if (data_array.get() == nullptr) {
2468 return -1;
2469 }
2470
2471 ScopedByteArrayRO sig_array(env, sig);
2472 if (sig_array.get() == nullptr) {
2473 return -1;
2474 }
2475
2476 int result =
2477 ECDSA_verify(0, reinterpret_cast<const unsigned char*>(data_array.get()),
2478 data_array.size(), reinterpret_cast<const unsigned char*>(sig_array.get()),
2479 sig_array.size(), ec_key.get());
2480
2481 if (result == 0) {
2482 // NOLINTNEXTLINE(runtime/int)
2483 unsigned long error = ERR_peek_last_error();
2484 if ((ERR_GET_LIB(error) == ERR_LIB_ECDSA) &&
2485 (ERR_GET_REASON(error) == ECDSA_R_BAD_SIGNATURE)) {
2486 // This error just means the signature didn't verify, so clear the error and return
2487 // a failed verification
2488 ERR_clear_error();
2489 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2490 return 0;
2491 }
2492 if (error != 0) {
2493 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ECDSA_verify");
2494 JNI_TRACE("ECDSA_verify => threw error");
2495 return -1;
2496 }
2497 return 0;
2498 }
2499
2500 JNI_TRACE("ECDSA_verify(%p, %p, %p) => %d", data, sig, pkey, result);
2501 return static_cast<jint>(result);
2502 }
2503
NativeCrypto_X25519(JNIEnv * env,jclass,jbyteArray outArray,jbyteArray privkeyArray,jbyteArray pubkeyArray)2504 static jboolean NativeCrypto_X25519(JNIEnv* env, jclass, jbyteArray outArray,
2505 jbyteArray privkeyArray, jbyteArray pubkeyArray) {
2506 CHECK_ERROR_QUEUE_ON_RETURN;
2507 JNI_TRACE("X25519(%p, %p, %p)", outArray, privkeyArray, pubkeyArray);
2508
2509 ScopedByteArrayRW out(env, outArray);
2510 if (out.get() == nullptr) {
2511 JNI_TRACE("X25519(%p, %p, %p) can't get output buffer", outArray, privkeyArray, pubkeyArray);
2512 return JNI_FALSE;
2513 }
2514
2515 ScopedByteArrayRO privkey(env, privkeyArray);
2516 if (privkey.get() == nullptr) {
2517 JNI_TRACE("X25519(%p) => privkey == null", outArray);
2518 return JNI_FALSE;
2519 }
2520
2521 ScopedByteArrayRO pubkey(env, pubkeyArray);
2522 if (pubkey.get() == nullptr) {
2523 JNI_TRACE("X25519(%p) => pubkey == null", outArray);
2524 return JNI_FALSE;
2525 }
2526
2527 if (X25519(reinterpret_cast<uint8_t*>(out.get()),
2528 reinterpret_cast<const uint8_t*>(privkey.get()),
2529 reinterpret_cast<const uint8_t*>(pubkey.get())) != 1) {
2530 JNI_TRACE("X25519(%p) => failure", outArray);
2531 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X25519",
2532 conscrypt::jniutil::throwInvalidKeyException);
2533 return JNI_FALSE;
2534 }
2535
2536 JNI_TRACE("X25519(%p) => success", outArray);
2537 return JNI_TRUE;
2538 }
2539
NativeCrypto_X25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2540 static void NativeCrypto_X25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray, jbyteArray outPrivateArray) {
2541 CHECK_ERROR_QUEUE_ON_RETURN;
2542 JNI_TRACE("X25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2543
2544 ScopedByteArrayRW outPublic(env, outPublicArray);
2545 if (outPublic.get() == nullptr) {
2546 JNI_TRACE("X25519_keypair(%p, %p) can't get output public key buffer", outPublicArray, outPrivateArray);
2547 return;
2548 }
2549
2550 ScopedByteArrayRW outPrivate(env, outPrivateArray);
2551 if (outPrivate.get() == nullptr) {
2552 JNI_TRACE("X25519_keypair(%p, %p) can't get output private key buffer", outPublicArray, outPrivateArray);
2553 return;
2554 }
2555
2556 if (outPublic.size() != X25519_PUBLIC_VALUE_LEN || outPrivate.size() != X25519_PRIVATE_KEY_LEN) {
2557 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException", "Output key array length != 32");
2558 return;
2559 }
2560
2561 X25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()), reinterpret_cast<uint8_t*>(outPrivate.get()));
2562 JNI_TRACE("X25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2563 }
2564
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2565 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2566 CHECK_ERROR_QUEUE_ON_RETURN;
2567 JNI_TRACE_MD("EVP_MD_CTX_create()");
2568
2569 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2570 if (ctx.get() == nullptr) {
2571 conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2572 return 0;
2573 }
2574
2575 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2576 return reinterpret_cast<uintptr_t>(ctx.release());
2577 }
2578
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2579 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2580 CHECK_ERROR_QUEUE_ON_RETURN;
2581 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2582 JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2583
2584 if (ctx != nullptr) {
2585 EVP_MD_CTX_cleanup(ctx);
2586 }
2587 }
2588
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2589 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2590 CHECK_ERROR_QUEUE_ON_RETURN;
2591 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2592 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2593
2594 if (ctx != nullptr) {
2595 EVP_MD_CTX_destroy(ctx);
2596 }
2597 }
2598
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2599 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2600 jobject srcCtxRef) {
2601 CHECK_ERROR_QUEUE_ON_RETURN;
2602 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2603 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2604 if (dst_ctx == nullptr) {
2605 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2606 return 0;
2607 }
2608 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2609 if (src_ctx == nullptr) {
2610 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2611 return 0;
2612 }
2613 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2614
2615 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2616 if (result == 0) {
2617 conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2618 ERR_clear_error();
2619 }
2620
2621 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2622 return result;
2623 }
2624
2625 /*
2626 * public static native int EVP_DigestFinal_ex(long, byte[], int)
2627 */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2628 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2629 jint offset) {
2630 CHECK_ERROR_QUEUE_ON_RETURN;
2631 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2632 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2633
2634 if (ctx == nullptr) {
2635 JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2636 return -1;
2637 } else if (hash == nullptr) {
2638 conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2639 return -1;
2640 }
2641
2642 ScopedByteArrayRW hashBytes(env, hash);
2643 if (hashBytes.get() == nullptr) {
2644 return -1;
2645 }
2646 unsigned int bytesWritten = static_cast<unsigned int>(-1);
2647 int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2648 &bytesWritten);
2649 if (ok == 0) {
2650 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2651 return -1;
2652 }
2653
2654 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2655 return static_cast<jint>(bytesWritten);
2656 }
2657
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2658 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2659 jlong evpMdRef) {
2660 CHECK_ERROR_QUEUE_ON_RETURN;
2661 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2662 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2663 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2664
2665 if (ctx == nullptr) {
2666 JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2667 return 0;
2668 } else if (evp_md == nullptr) {
2669 conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2670 return 0;
2671 }
2672
2673 int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2674 if (ok == 0) {
2675 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2676 JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2677 return 0;
2678 }
2679 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2680 return ok;
2681 }
2682
2683 /*
2684 * public static native int EVP_get_digestbyname(java.lang.String)
2685 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2686 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2687 CHECK_ERROR_QUEUE_ON_RETURN;
2688 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2689
2690 if (algorithm == nullptr) {
2691 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2692 return -1;
2693 }
2694
2695 ScopedUtfChars algorithmChars(env, algorithm);
2696 if (algorithmChars.c_str() == nullptr) {
2697 return 0;
2698 }
2699 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2700
2701 const char* alg = algorithmChars.c_str();
2702 const EVP_MD* md;
2703
2704 if (strcasecmp(alg, "md4") == 0) {
2705 md = EVP_md4();
2706 } else if (strcasecmp(alg, "md5") == 0) {
2707 md = EVP_md5();
2708 } else if (strcasecmp(alg, "sha1") == 0) {
2709 md = EVP_sha1();
2710 } else if (strcasecmp(alg, "sha224") == 0) {
2711 md = EVP_sha224();
2712 } else if (strcasecmp(alg, "sha256") == 0) {
2713 md = EVP_sha256();
2714 } else if (strcasecmp(alg, "sha384") == 0) {
2715 md = EVP_sha384();
2716 } else if (strcasecmp(alg, "sha512") == 0) {
2717 md = EVP_sha512();
2718 } else {
2719 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2720 conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2721 return 0;
2722 }
2723
2724 return reinterpret_cast<uintptr_t>(md);
2725 }
2726
2727 /*
2728 * public static native int EVP_MD_size(long)
2729 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2730 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2731 CHECK_ERROR_QUEUE_ON_RETURN;
2732 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2733 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2734
2735 if (evp_md == nullptr) {
2736 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2737 return -1;
2738 }
2739
2740 jint result = static_cast<jint>(EVP_MD_size(evp_md));
2741 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2742 return result;
2743 }
2744
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)2745 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2746 int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2747 ENGINE*, EVP_PKEY*),
2748 const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2749 jobject pkeyRef) {
2750 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2751 if (mdCtx == nullptr) {
2752 JNI_TRACE("%s => mdCtx == null", jniName);
2753 return 0;
2754 }
2755 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2756 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2757 if (pkey == nullptr) {
2758 JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2759 return 0;
2760 }
2761 JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2762
2763 if (md == nullptr) {
2764 JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2765 conscrypt::jniutil::throwNullPointerException(env, "md == null");
2766 return 0;
2767 }
2768
2769 EVP_PKEY_CTX* pctx = nullptr;
2770 if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2771 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2772 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2773 return 0;
2774 }
2775
2776 JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2777 return reinterpret_cast<jlong>(pctx);
2778 }
2779
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2780 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2781 const jlong evpMdRef, jobject pkeyRef) {
2782 CHECK_ERROR_QUEUE_ON_RETURN;
2783 return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2784 evpMdRef, pkeyRef);
2785 }
2786
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2787 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2788 const jlong evpMdRef, jobject pkeyRef) {
2789 CHECK_ERROR_QUEUE_ON_RETURN;
2790 return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2791 evpMdRef, pkeyRef);
2792 }
2793
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2794 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2795 const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2796 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2797 const void* p = reinterpret_cast<const void*>(inPtr);
2798 JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2799
2800 if (mdCtx == nullptr) {
2801 return;
2802 }
2803
2804 if (p == nullptr) {
2805 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2806 return;
2807 }
2808
2809 if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2810 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2811 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2812 return;
2813 }
2814
2815 JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2816 }
2817
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2818 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2819 jint inLength, const char* jniName,
2820 int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2821 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2822 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2823
2824 if (mdCtx == nullptr) {
2825 return;
2826 }
2827
2828 if (inJavaBytes == nullptr) {
2829 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2830 return;
2831 }
2832
2833 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2834 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2835 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2836 "inBytes");
2837 return;
2838 }
2839 if (inLength == 0) {
2840 return;
2841 }
2842 jint in_offset = inOffset;
2843 jint in_size = inLength;
2844
2845 int update_func_result = -1;
2846 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2847 // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2848 // avoid copying the whole array.
2849 if (in_size <= 1024) {
2850 // For small chunk, it's more efficient to use a bit more space on the stack instead of
2851 // allocating a new buffer.
2852 jbyte buf[1024];
2853 env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2854 update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2855 static_cast<size_t>(in_size));
2856 } else {
2857 // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2858 // through the buffer, stopping as soon as update_func fails.
2859 jint remaining = in_size;
2860 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2861 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2862 if (buf.get() == nullptr) {
2863 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2864 return;
2865 }
2866 while (remaining > 0) {
2867 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2868 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2869 update_func_result =
2870 update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2871 static_cast<size_t>(chunk_size));
2872 if (!update_func_result) {
2873 // update_func failed. This will be handled later in this method.
2874 break;
2875 }
2876 in_offset += chunk_size;
2877 remaining -= chunk_size;
2878 }
2879 }
2880 } else {
2881 // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2882 // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2883 // use GetByteArrayElements or another approach.
2884 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2885 if (array_elements == nullptr) {
2886 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2887 return;
2888 }
2889 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2890 update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2891 env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2892 }
2893
2894 if (!update_func_result) {
2895 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2896 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2897 return;
2898 }
2899
2900 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2901 }
2902
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2903 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2904 jlong inPtr, jint inLength) {
2905 CHECK_ERROR_QUEUE_ON_RETURN;
2906 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2907 }
2908
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2909 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2910 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2911 CHECK_ERROR_QUEUE_ON_RETURN;
2912 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2913 EVP_DigestUpdate);
2914 }
2915
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2916 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2917 jbyteArray inJavaBytes, jint inOffset,
2918 jint inLength) {
2919 CHECK_ERROR_QUEUE_ON_RETURN;
2920 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2921 EVP_DigestSignUpdate);
2922 }
2923
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2924 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2925 jlong inPtr, jint inLength) {
2926 CHECK_ERROR_QUEUE_ON_RETURN;
2927 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2928 EVP_DigestSignUpdate);
2929 }
2930
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2931 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2932 jbyteArray inJavaBytes, jint inOffset,
2933 jint inLength) {
2934 CHECK_ERROR_QUEUE_ON_RETURN;
2935 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2936 EVP_DigestVerifyUpdate);
2937 }
2938
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2939 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2940 jlong inPtr, jint inLength) {
2941 CHECK_ERROR_QUEUE_ON_RETURN;
2942 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2943 EVP_DigestVerifyUpdate);
2944 }
2945
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2946 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2947 CHECK_ERROR_QUEUE_ON_RETURN;
2948 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2949 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2950
2951 if (mdCtx == nullptr) {
2952 return nullptr;
2953 }
2954
2955 size_t maxLen;
2956 if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2957 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2958 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2959 return nullptr;
2960 }
2961
2962 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
2963 if (buffer.get() == nullptr) {
2964 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
2965 return nullptr;
2966 }
2967 size_t actualLen(maxLen);
2968 if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
2969 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2970 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2971 return nullptr;
2972 }
2973 if (actualLen > maxLen) {
2974 JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
2975 maxLen);
2976 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
2977 return nullptr;
2978 }
2979
2980 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
2981 if (sigJavaBytes.get() == nullptr) {
2982 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
2983 return nullptr;
2984 }
2985 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
2986 reinterpret_cast<jbyte*>(buffer.get()));
2987
2988 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
2989 return sigJavaBytes.release();
2990 }
2991
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)2992 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
2993 jbyteArray signature, jint offset, jint len) {
2994 CHECK_ERROR_QUEUE_ON_RETURN;
2995 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2996 JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
2997
2998 if (mdCtx == nullptr) {
2999 return 0;
3000 }
3001
3002 ScopedByteArrayRO sigBytes(env, signature);
3003 if (sigBytes.get() == nullptr) {
3004 return 0;
3005 }
3006
3007 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
3008 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3009 "signature");
3010 return 0;
3011 }
3012
3013 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3014 int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
3015 jboolean result;
3016 if (err == 1) {
3017 // Signature verified
3018 result = 1;
3019 } else if (err == 0) {
3020 // Signature did not verify
3021 result = 0;
3022 } else {
3023 // Error while verifying signature
3024 JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
3025 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
3026 return 0;
3027 }
3028
3029 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3030 // Clear the error queue to prevent its state from affecting future operations.
3031 ERR_clear_error();
3032
3033 JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
3034 return result;
3035 }
3036
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)3037 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
3038 int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
3039 const uint8_t*, size_t),
3040 const char* jniName, jobject evpPkeyCtxRef,
3041 jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
3042 jint inOffset, jint inLength) {
3043 EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
3044 JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
3045 inJavaBytes, inOffset, inLength);
3046
3047 if (pkeyCtx == nullptr) {
3048 return 0;
3049 }
3050
3051 ScopedByteArrayRW outBytes(env, outJavaBytes);
3052 if (outBytes.get() == nullptr) {
3053 return 0;
3054 }
3055
3056 ScopedByteArrayRO inBytes(env, inJavaBytes);
3057 if (inBytes.get() == nullptr) {
3058 return 0;
3059 }
3060
3061 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3062 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3063 "outBytes");
3064 return 0;
3065 }
3066
3067 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3068 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3069 "inBytes");
3070 return 0;
3071 }
3072
3073 uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3074 const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3075 size_t outLength = outBytes.size() - outOffset;
3076 if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3077 static_cast<size_t>(inLength))) {
3078 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3079 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3080 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3081 return 0;
3082 }
3083
3084 JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3085 outOffset, inJavaBytes, inOffset, inLength, outLength);
3086 return static_cast<jint>(outLength);
3087 }
3088
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3089 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3090 jbyteArray out, jint outOffset, jbyteArray inBytes,
3091 jint inOffset, jint inLength) {
3092 CHECK_ERROR_QUEUE_ON_RETURN;
3093 return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3094 outOffset, inBytes, inOffset, inLength);
3095 }
3096
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3097 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3098 jbyteArray out, jint outOffset, jbyteArray inBytes,
3099 jint inOffset, jint inLength) {
3100 CHECK_ERROR_QUEUE_ON_RETURN;
3101 return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3102 outOffset, inBytes, inOffset, inLength);
3103 }
3104
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3105 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3106 int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3107 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3108 JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3109 if (pkey == nullptr) {
3110 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3111 return 0;
3112 }
3113
3114 bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3115 if (pkeyCtx.get() == nullptr) {
3116 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3117 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3118 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3119 return 0;
3120 }
3121
3122 if (!real_func(pkeyCtx.get())) {
3123 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3124 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3125 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3126 return 0;
3127 }
3128
3129 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3130 return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3131 }
3132
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3133 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3134 CHECK_ERROR_QUEUE_ON_RETURN;
3135 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3136 }
3137
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3138 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3139 CHECK_ERROR_QUEUE_ON_RETURN;
3140 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3141 }
3142
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3143 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3144 CHECK_ERROR_QUEUE_ON_RETURN;
3145 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3146 JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3147
3148 if (pkeyCtx != nullptr) {
3149 EVP_PKEY_CTX_free(pkeyCtx);
3150 }
3151 }
3152
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3153 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3154 CHECK_ERROR_QUEUE_ON_RETURN;
3155 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3156 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3157 if (pkeyCtx == nullptr) {
3158 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3159 return;
3160 }
3161
3162 int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3163 if (result <= 0) {
3164 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3165 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3166 env, "EVP_PKEY_CTX_set_rsa_padding",
3167 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3168 return;
3169 }
3170
3171 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3172 }
3173
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3174 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3175 jint len) {
3176 CHECK_ERROR_QUEUE_ON_RETURN;
3177 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3178 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3179 if (pkeyCtx == nullptr) {
3180 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3181 return;
3182 }
3183
3184 int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3185 if (result <= 0) {
3186 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3187 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3188 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3189 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3190 return;
3191 }
3192
3193 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3194 }
3195
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3196 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3197 int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3198 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3199 EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3200 JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3201 if (pkeyCtx == nullptr) {
3202 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3203 return;
3204 }
3205 if (md == nullptr) {
3206 conscrypt::jniutil::throwNullPointerException(env, "md == null");
3207 return;
3208 }
3209
3210 int result = ctrl_func(pkeyCtx, md);
3211 if (result <= 0) {
3212 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3213 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3214 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3215 return;
3216 }
3217
3218 JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3219 }
3220
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3221 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3222 jlong mdRef) {
3223 CHECK_ERROR_QUEUE_ON_RETURN;
3224 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3225 EVP_PKEY_CTX_set_rsa_mgf1_md);
3226 }
3227
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3228 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3229 jlong mdRef) {
3230 CHECK_ERROR_QUEUE_ON_RETURN;
3231 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3232 EVP_PKEY_CTX_set_rsa_oaep_md);
3233 }
3234
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3235 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3236 jbyteArray labelJava) {
3237 CHECK_ERROR_QUEUE_ON_RETURN;
3238 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3239 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3240 if (pkeyCtx == nullptr) {
3241 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3242 return;
3243 }
3244
3245 ScopedByteArrayRO labelBytes(env, labelJava);
3246 if (labelBytes.get() == nullptr) {
3247 return;
3248 }
3249
3250 bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3251 memcpy(label.get(), labelBytes.get(), labelBytes.size());
3252
3253 int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3254 if (result <= 0) {
3255 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3256 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3257 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3258 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3259 return;
3260 }
3261 OWNERSHIP_TRANSFERRED(label);
3262
3263 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3264 }
3265
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3266 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3267 CHECK_ERROR_QUEUE_ON_RETURN;
3268 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3269
3270 if (algorithm == nullptr) {
3271 conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3272 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3273 return -1;
3274 }
3275
3276 ScopedUtfChars scoped_alg(env, algorithm);
3277 const char* alg = scoped_alg.c_str();
3278 const EVP_CIPHER* cipher;
3279
3280 if (strcasecmp(alg, "rc4") == 0) {
3281 cipher = EVP_rc4();
3282 } else if (strcasecmp(alg, "des-cbc") == 0) {
3283 cipher = EVP_des_cbc();
3284 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3285 cipher = EVP_des_ede_cbc();
3286 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3287 cipher = EVP_des_ede3_cbc();
3288 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3289 cipher = EVP_aes_128_ecb();
3290 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3291 cipher = EVP_aes_128_cbc();
3292 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3293 cipher = EVP_aes_128_ctr();
3294 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3295 cipher = EVP_aes_128_gcm();
3296 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3297 cipher = EVP_aes_192_ecb();
3298 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3299 cipher = EVP_aes_192_cbc();
3300 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3301 cipher = EVP_aes_192_ctr();
3302 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3303 cipher = EVP_aes_192_gcm();
3304 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3305 cipher = EVP_aes_256_ecb();
3306 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3307 cipher = EVP_aes_256_cbc();
3308 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3309 cipher = EVP_aes_256_ctr();
3310 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3311 cipher = EVP_aes_256_gcm();
3312 } else {
3313 JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3314 return 0;
3315 }
3316
3317 return reinterpret_cast<uintptr_t>(cipher);
3318 }
3319
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3320 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3321 jbyteArray keyArray, jbyteArray ivArray,
3322 jboolean encrypting) {
3323 CHECK_ERROR_QUEUE_ON_RETURN;
3324 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3325 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3326 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3327 encrypting ? 1 : 0);
3328
3329 if (ctx == nullptr) {
3330 JNI_TRACE("EVP_CipherUpdate => ctx == null");
3331 return;
3332 }
3333
3334 // The key can be null if we need to set extra parameters.
3335 std::unique_ptr<unsigned char[]> keyPtr;
3336 if (keyArray != nullptr) {
3337 ScopedByteArrayRO keyBytes(env, keyArray);
3338 if (keyBytes.get() == nullptr) {
3339 return;
3340 }
3341
3342 keyPtr.reset(new unsigned char[keyBytes.size()]);
3343 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3344 }
3345
3346 // The IV can be null if we're using ECB.
3347 std::unique_ptr<unsigned char[]> ivPtr;
3348 if (ivArray != nullptr) {
3349 ScopedByteArrayRO ivBytes(env, ivArray);
3350 if (ivBytes.get() == nullptr) {
3351 return;
3352 }
3353
3354 ivPtr.reset(new unsigned char[ivBytes.size()]);
3355 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3356 }
3357
3358 if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3359 encrypting ? 1 : 0)) {
3360 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3361 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3362 return;
3363 }
3364
3365 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3366 encrypting ? 1 : 0);
3367 }
3368
3369 /*
3370 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3371 * int inOffset, int inLength);
3372 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3373 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3374 jint outOffset, jbyteArray inArray, jint inOffset,
3375 jint inLength) {
3376 CHECK_ERROR_QUEUE_ON_RETURN;
3377 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3378 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3379
3380 if (ctx == nullptr) {
3381 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3382 return 0;
3383 }
3384
3385 ScopedByteArrayRO inBytes(env, inArray);
3386 if (inBytes.get() == nullptr) {
3387 return 0;
3388 }
3389 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3390 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3391 "inBytes");
3392 return 0;
3393 }
3394
3395 ScopedByteArrayRW outBytes(env, outArray);
3396 if (outBytes.get() == nullptr) {
3397 return 0;
3398 }
3399 if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3400 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3401 "outBytes");
3402 return 0;
3403 }
3404
3405 JNI_TRACE(
3406 "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3407 "out.length=%zd outOffset=%d",
3408 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3409 outOffset);
3410
3411 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3412 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3413
3414 int outl;
3415 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3416 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3417 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3418 return 0;
3419 }
3420
3421 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3422 inOffset, outl);
3423 return outl;
3424 }
3425
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3426 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3427 jbyteArray outArray, jint outOffset) {
3428 CHECK_ERROR_QUEUE_ON_RETURN;
3429 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3430 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3431
3432 if (ctx == nullptr) {
3433 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3434 return 0;
3435 }
3436
3437 ScopedByteArrayRW outBytes(env, outArray);
3438 if (outBytes.get() == nullptr) {
3439 return 0;
3440 }
3441
3442 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3443
3444 int outl;
3445 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3446 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3447 conscrypt::jniutil::throwBadPaddingException);
3448 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3449 return 0;
3450 }
3451
3452 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3453 return outl;
3454 }
3455
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3456 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3457 CHECK_ERROR_QUEUE_ON_RETURN;
3458 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3459 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3460
3461 if (evpCipher == nullptr) {
3462 conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3463 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3464 return 0;
3465 }
3466
3467 jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3468 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3469 return ivLength;
3470 }
3471
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3472 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3473 CHECK_ERROR_QUEUE_ON_RETURN;
3474 JNI_TRACE("EVP_CIPHER_CTX_new()");
3475
3476 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3477 if (ctx.get() == nullptr) {
3478 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3479 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3480 return 0;
3481 }
3482
3483 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3484 return reinterpret_cast<uintptr_t>(ctx.release());
3485 }
3486
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3487 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3488 CHECK_ERROR_QUEUE_ON_RETURN;
3489 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3490 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3491
3492 if (ctx == nullptr) {
3493 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3494 return 0;
3495 }
3496
3497 jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3498 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3499 return blockSize;
3500 }
3501
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3502 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3503 CHECK_ERROR_QUEUE_ON_RETURN;
3504 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3505 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3506
3507 if (ctx == nullptr) {
3508 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3509 return 0;
3510 }
3511
3512 int buf_len = ctx->buf_len;
3513 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3514 return buf_len;
3515 }
3516
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3517 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3518 CHECK_ERROR_QUEUE_ON_RETURN;
3519 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3520 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3521
3522 if (ctx == nullptr) {
3523 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3524 return 0;
3525 }
3526
3527 bool final_used = ctx->final_used != 0;
3528 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3529 return static_cast<jboolean>(final_used);
3530 }
3531
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3532 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3533 jboolean enablePaddingBool) {
3534 CHECK_ERROR_QUEUE_ON_RETURN;
3535 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3536 jint enablePadding = enablePaddingBool ? 1 : 0;
3537 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3538
3539 if (ctx == nullptr) {
3540 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3541 return;
3542 }
3543
3544 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3545 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3546 }
3547
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3548 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3549 jint keySizeBits) {
3550 CHECK_ERROR_QUEUE_ON_RETURN;
3551 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3552 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3553
3554 if (ctx == nullptr) {
3555 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3556 return;
3557 }
3558
3559 if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3560 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3561 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3562 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3563 return;
3564 }
3565 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3566 }
3567
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3568 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3569 CHECK_ERROR_QUEUE_ON_RETURN;
3570 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3571 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3572
3573 EVP_CIPHER_CTX_free(ctx);
3574 }
3575
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3576 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3577 CHECK_ERROR_QUEUE_ON_RETURN;
3578 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3579 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3580 return reinterpret_cast<jlong>(ctx);
3581 }
3582
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3583 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3584 CHECK_ERROR_QUEUE_ON_RETURN;
3585 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3586 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3587 return reinterpret_cast<jlong>(ctx);
3588 }
3589
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3590 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3591 CHECK_ERROR_QUEUE_ON_RETURN;
3592 const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3593 JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3594 return reinterpret_cast<jlong>(ctx);
3595 }
3596
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3597 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3598 CHECK_ERROR_QUEUE_ON_RETURN;
3599 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3600 JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3601 return reinterpret_cast<jlong>(ctx);
3602 }
3603
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3604 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3605 CHECK_ERROR_QUEUE_ON_RETURN;
3606 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3607 JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3608 return reinterpret_cast<jlong>(ctx);
3609 }
3610
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3611 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3612 CHECK_ERROR_QUEUE_ON_RETURN;
3613 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3614 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3615 if (evpAead == nullptr) {
3616 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3617 return 0;
3618 }
3619 jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3620 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3621 return maxOverhead;
3622 }
3623
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3624 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3625 CHECK_ERROR_QUEUE_ON_RETURN;
3626 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3627 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3628 if (evpAead == nullptr) {
3629 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3630 return 0;
3631 }
3632 jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3633 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3634 return nonceLength;
3635 }
3636
3637 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3638 size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3639 const uint8_t* in, size_t in_len, const uint8_t* ad,
3640 size_t ad_len);
3641
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)3642 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3643 uint8_t* outBuf, jbyteArray nonceArray,
3644 const uint8_t* inBuf, jbyteArray aadArray,
3645 evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange) {
3646 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3647
3648 ScopedByteArrayRO keyBytes(env, keyArray);
3649 if (keyBytes.get() == nullptr) {
3650 return 0;
3651 }
3652
3653 std::unique_ptr<ScopedByteArrayRO> aad;
3654 const uint8_t* aad_chars = nullptr;
3655 size_t aad_chars_size = 0;
3656 if (aadArray != nullptr) {
3657 aad.reset(new ScopedByteArrayRO(env, aadArray));
3658 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3659 if (aad_chars == nullptr) {
3660 return 0;
3661 }
3662 aad_chars_size = aad->size();
3663 }
3664
3665 ScopedByteArrayRO nonceBytes(env, nonceArray);
3666 if (nonceBytes.get() == nullptr) {
3667 return 0;
3668 }
3669
3670 bssl::ScopedEVP_AEAD_CTX aeadCtx;
3671 const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3672 if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3673 static_cast<size_t>(tagLen), nullptr)) {
3674 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3675 "failure initializing AEAD context");
3676 JNI_TRACE(
3677 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3678 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3679 aadArray);
3680 return 0;
3681 }
3682
3683 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3684 size_t actualOutLength;
3685
3686 if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3687 nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3688 aad_chars, aad_chars_size)) {
3689 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3690 return 0;
3691 }
3692
3693 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3694 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3695 aadArray, actualOutLength);
3696 return static_cast<jint>(actualOutLength);
3697 }
3698
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)3699 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3700 jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3701 jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3702 evp_aead_ctx_op_func realFunc) {
3703 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3704 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3705 outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3706
3707
3708 ScopedByteArrayRW outBytes(env, outArray);
3709 if (outBytes.get() == nullptr) {
3710 return 0;
3711 }
3712
3713 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3714 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3715 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3716 inLength, aadArray);
3717 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3718 return 0;
3719 }
3720
3721 ScopedByteArrayRO inBytes(env, inArray);
3722 if (inBytes.get() == nullptr) {
3723 return 0;
3724 }
3725
3726 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3727 JNI_TRACE(
3728 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3729 "invalid",
3730 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3731 inLength, aadArray);
3732 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3733 return 0;
3734 }
3735
3736 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3737 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3738
3739 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3740 aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3741 }
3742
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)3743 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3744 jobject outBuffer, jbyteArray nonceArray,
3745 jobject inBuffer, jbyteArray aadArray,
3746 evp_aead_ctx_op_func realFunc) {
3747
3748 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3749 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3750 outBuffer, nonceArray, inBuffer, aadArray);
3751
3752 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3753 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3754 "inBuffer is not a direct ByteBuffer");
3755 return 0;
3756 }
3757
3758 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3759 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3760 "outBuffer is not a direct ByteBuffer");
3761 return 0;
3762 }
3763
3764 uint8_t* inBuf;
3765 jint in_limit;
3766 jint in_position;
3767
3768 inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3769 // limit is the index of the first element that should not be read or written
3770 in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3771 // position is the index of the next element to be read or written
3772 in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3773
3774 uint8_t* outBuf;
3775 jint out_limit;
3776 jint out_position;
3777 outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3778 // limit is the index of the first element that should not be read or written
3779 out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3780 // position is the index of the next element to be read or written
3781 out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3782
3783 // Shifting over of ByteBuffer address to start at true position
3784 inBuf += in_position;
3785 outBuf += out_position;
3786
3787 size_t inSize = in_limit - in_position;
3788 uint8_t* outBufEnd = outBuf + out_limit - out_position;
3789 uint8_t* inBufEnd = inBuf + inSize;
3790 std::unique_ptr<uint8_t[]> inCopy;
3791 if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3792 inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3793 if (inCopy.get() == nullptr) {
3794 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3795 return 0;
3796 }
3797 memcpy(inCopy.get(), inBuf, inSize);
3798 inBuf = inCopy.get();
3799 }
3800
3801 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3802 inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3803 }
3804
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)3805 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3806 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3807 jint outOffset, jbyteArray nonceArray,
3808 jbyteArray inArray, jint inOffset, jint inLength,
3809 jbyteArray aadArray) {
3810 CHECK_ERROR_QUEUE_ON_RETURN;
3811 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3812 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3813 }
3814
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)3815 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3816 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3817 jint outOffset, jbyteArray nonceArray,
3818 jbyteArray inArray, jint inOffset, jint inLength,
3819 jbyteArray aadArray) {
3820 CHECK_ERROR_QUEUE_ON_RETURN;
3821 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3822 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3823 }
3824
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3825 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3826 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3827 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3828 CHECK_ERROR_QUEUE_ON_RETURN;
3829 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3830 inBuffer, aadArray, EVP_AEAD_CTX_seal);
3831 }
3832
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3833 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3834 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3835 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3836 CHECK_ERROR_QUEUE_ON_RETURN;
3837 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3838 inBuffer, aadArray, EVP_AEAD_CTX_open);
3839 }
3840
NativeCrypto_EVP_HPKE_CTX_export(JNIEnv * env,jclass,jobject hpkeCtxRef,jbyteArray exporterCtxArray,jint exportedLen)3841 static jbyteArray NativeCrypto_EVP_HPKE_CTX_export(JNIEnv* env, jclass, jobject hpkeCtxRef,
3842 jbyteArray exporterCtxArray, jint exportedLen) {
3843 CHECK_ERROR_QUEUE_ON_RETURN;
3844 EVP_HPKE_CTX* hpkeCtx = fromContextObject<EVP_HPKE_CTX>(env, hpkeCtxRef);
3845 JNI_TRACE("EVP_HPKE_CTX_export(%p, %p, %d)", hpkeCtx, exporterCtxArray, exportedLen);
3846
3847 if (hpkeCtx == nullptr) {
3848 // NullPointerException thrown while calling fromContextObject
3849 return {};
3850 }
3851
3852 std::optional<ScopedByteArrayRO> optionalExporterCtx;
3853 const uint8_t* exporterCtx = nullptr;
3854 size_t exporterCtxLen = 0;
3855 if (exporterCtxArray != nullptr) {
3856 optionalExporterCtx.emplace(env, exporterCtxArray);
3857 exporterCtx = reinterpret_cast<const uint8_t*>(optionalExporterCtx->get());
3858 if (exporterCtx == nullptr) {
3859 return {};
3860 }
3861 exporterCtxLen = optionalExporterCtx->size();
3862 }
3863
3864 std::vector<uint8_t> exported(exportedLen);
3865 if (!EVP_HPKE_CTX_export(/* ctx= */ hpkeCtx,
3866 /* out= */ exported.data(),
3867 /* secret_len= */ exportedLen,
3868 /* context= */ exporterCtx,
3869 /* context_len= */ exporterCtxLen)) {
3870 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_export");
3871 return {};
3872 }
3873
3874 ScopedLocalRef<jbyteArray> exportedArray(env, env->NewByteArray(static_cast<jsize>(exportedLen)));
3875 if (exportedArray.get() == nullptr) {
3876 return {};
3877 }
3878 ScopedByteArrayRW exportedBytes(env, exportedArray.get());
3879 if (exportedBytes.get() == nullptr) {
3880 return {};
3881 }
3882 memcpy(exportedBytes.get(), reinterpret_cast<const jbyte*>(exported.data()), exportedLen);
3883 return exportedArray.release();
3884 }
3885
NativeCrypto_EVP_HPKE_CTX_free(JNIEnv * env,jclass,jlong hpkeCtxRef)3886 static void NativeCrypto_EVP_HPKE_CTX_free(JNIEnv* env, jclass, jlong hpkeCtxRef) {
3887 CHECK_ERROR_QUEUE_ON_RETURN;
3888 EVP_HPKE_CTX* ctx = reinterpret_cast<EVP_HPKE_CTX*>(hpkeCtxRef);
3889 JNI_TRACE("EVP_HPKE_CTX_free(%p)", ctx);
3890 if (ctx == nullptr) {
3891 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3892 return;
3893 }
3894 EVP_HPKE_CTX_free(ctx);
3895 }
3896
NativeCrypto_EVP_HPKE_CTX_open(JNIEnv * env,jclass,jobject recipientHpkeCtxRef,jbyteArray ciphertextArray,jbyteArray aadArray)3897 static jbyteArray NativeCrypto_EVP_HPKE_CTX_open(JNIEnv* env, jclass, jobject recipientHpkeCtxRef,
3898 jbyteArray ciphertextArray, jbyteArray aadArray) {
3899 CHECK_ERROR_QUEUE_ON_RETURN;
3900 EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, recipientHpkeCtxRef);
3901 JNI_TRACE("EVP_HPKE_CTX_open(%p, %p, %p)", ctx, ciphertextArray, aadArray);
3902
3903 if (ctx == nullptr) {
3904 // NullPointerException thrown while calling fromContextObject
3905 return {};
3906 }
3907
3908 if (ciphertextArray == nullptr) {
3909 conscrypt::jniutil::throwNullPointerException(env, "ciphertextArray == null");
3910 return {};
3911 }
3912
3913 ScopedByteArrayRO ciphertext(env, ciphertextArray);
3914 if (ciphertext.get() == nullptr) {
3915 return {};
3916 }
3917
3918 std::optional<ScopedByteArrayRO> optionalAad;
3919 const uint8_t* aad = nullptr;
3920 size_t aadLen = 0;
3921 if (aadArray != nullptr) {
3922 optionalAad.emplace(env, aadArray);
3923 aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
3924 if (aad == nullptr) {
3925 return {};
3926 }
3927 aadLen = optionalAad->size();
3928 }
3929
3930 size_t plaintextLen;
3931 std::vector<uint8_t> plaintext(ciphertext.size());
3932 if (!EVP_HPKE_CTX_open(/* ctx= */ ctx,
3933 /* out= */ plaintext.data(),
3934 /* out_len= */ &plaintextLen,
3935 /* max_out_len= */ plaintext.size(),
3936 /* in= */ reinterpret_cast<const uint8_t*>(ciphertext.get()),
3937 /* in_len= */ ciphertext.size(),
3938 /* aad= */ aad,
3939 /* aad_len= */ aadLen)) {
3940 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_open");
3941 return {};
3942 }
3943
3944 plaintext.resize(plaintextLen);
3945 ScopedLocalRef<jbyteArray> plaintextArray(env, env->NewByteArray(static_cast<jsize>(plaintextLen)));
3946 if (plaintextArray.get() == nullptr) {
3947 return {};
3948 }
3949 ScopedByteArrayRW plaintextBytes(env, plaintextArray.get());
3950 if (plaintextBytes.get() == nullptr) {
3951 return {};
3952 }
3953 memcpy(plaintextBytes.get(), reinterpret_cast<const jbyte*>(plaintext.data()), plaintextLen);
3954 return plaintextArray.release();
3955 }
3956
NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv * env,jclass,jobject senderHpkeCtxRef,jbyteArray plaintextArray,jbyteArray aadArray)3957 static jbyteArray NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv* env, jclass, jobject senderHpkeCtxRef,
3958 jbyteArray plaintextArray, jbyteArray aadArray) {
3959 CHECK_ERROR_QUEUE_ON_RETURN;
3960 EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, senderHpkeCtxRef);
3961 JNI_TRACE("EVP_HPKE_CTX_seal(%p, %p, %p)", ctx, plaintextArray, aadArray);
3962
3963 if (ctx == nullptr) {
3964 // NullPointerException thrown while calling fromContextObject
3965 return {};
3966 }
3967
3968 if (plaintextArray == nullptr) {
3969 conscrypt::jniutil::throwNullPointerException(env, "plaintextArray == null");
3970 return {};
3971 }
3972
3973 std::optional<ScopedByteArrayRO> optionalAad;
3974 const uint8_t* aad = nullptr;
3975 size_t aadLen = 0;
3976 if (aadArray != nullptr) {
3977 optionalAad.emplace(env, aadArray);
3978 aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
3979 if (aad == nullptr) {
3980 return {};
3981 }
3982 aadLen = optionalAad->size();
3983 }
3984
3985 ScopedByteArrayRO plaintext(env, plaintextArray);
3986 std::vector<uint8_t> encrypted(env->GetArrayLength(plaintextArray) +
3987 EVP_HPKE_CTX_max_overhead(ctx));
3988 size_t encryptedLen;
3989 if (!EVP_HPKE_CTX_seal(/* ctx= */ ctx,
3990 /* out= */ encrypted.data(),
3991 /* out_len= */ &encryptedLen,
3992 /* max_out_len= */ encrypted.size(),
3993 /* in= */ reinterpret_cast<const uint8_t*>(plaintext.get()),
3994 /* in_len= */ plaintext.size(),
3995 /* aad= */ aad,
3996 /* aad_len= */ aadLen)) {
3997 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_seal");
3998 return {};
3999 }
4000
4001 ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(static_cast<jsize>(encryptedLen)));
4002 if (ciphertextArray.get() == nullptr) {
4003 return {};
4004 }
4005 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
4006 if (ciphertextBytes.get() == nullptr) {
4007 return {};
4008 }
4009 memcpy(ciphertextBytes.get(), reinterpret_cast<const jbyte*>(encrypted.data()), encryptedLen);
4010 return ciphertextArray.release();
4011 }
4012
getHpkeAead(JNIEnv * env,jint aeadValue)4013 const EVP_HPKE_AEAD* getHpkeAead(JNIEnv* env, jint aeadValue) {
4014 switch (aeadValue) {
4015 case EVP_HPKE_AES_128_GCM:
4016 return EVP_hpke_aes_128_gcm();
4017 case EVP_HPKE_AES_256_GCM:
4018 return EVP_hpke_aes_256_gcm();
4019 case EVP_HPKE_CHACHA20_POLY1305:
4020 return EVP_hpke_chacha20_poly1305();
4021 default:
4022 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4023 "AEAD is not supported");
4024 return nullptr;
4025 }
4026 }
4027
getHpkeKdf(JNIEnv * env,jint kdfValue)4028 const EVP_HPKE_KDF* getHpkeKdf(JNIEnv* env, jint kdfValue) {
4029 if (kdfValue == EVP_HPKE_HKDF_SHA256) {
4030 return EVP_hpke_hkdf_sha256();
4031 } else {
4032 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4033 "KDF is not supported");
4034 return nullptr;
4035 }
4036 }
4037
getHpkeKem(JNIEnv * env,jint kemValue)4038 const EVP_HPKE_KEM* getHpkeKem(JNIEnv* env, jint kemValue) {
4039 if (kemValue == EVP_HPKE_DHKEM_X25519_HKDF_SHA256) {
4040 return EVP_hpke_x25519_hkdf_sha256();
4041 } else {
4042 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4043 "KEM is not supported");
4044 return nullptr;
4045 }
4046 }
4047
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray privateKeyArray,jbyteArray encArray,jbyteArray infoArray)4048 static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv* env, jclass,
4049 jint kemValue,jint kdfValue,
4050 jint aeadValue,
4051 jbyteArray privateKeyArray,
4052 jbyteArray encArray,
4053 jbyteArray infoArray) {
4054 CHECK_ERROR_QUEUE_ON_RETURN;
4055 JNI_TRACE("EVP_HPKE_CTX_setup_recipient(%d, %d, %d, %p, %p, %p)", kemValue, kdfValue, aeadValue,
4056 privateKeyArray, encArray, infoArray);
4057
4058 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4059 if (kem == nullptr) {
4060 return nullptr;
4061 }
4062 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4063 if (kdf == nullptr) {
4064 return nullptr;
4065 }
4066 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4067 if (aead == nullptr) {
4068 return nullptr;
4069 }
4070 if (privateKeyArray == nullptr) {
4071 conscrypt::jniutil::throwNullPointerException(env, "privateKeyArray == null");
4072 return nullptr;
4073 }
4074 if (encArray == nullptr) {
4075 conscrypt::jniutil::throwNullPointerException(env, "encArray == null");
4076 return nullptr;
4077 }
4078
4079 ScopedByteArrayRO privateKey(env, privateKeyArray);
4080
4081 bssl::ScopedEVP_HPKE_KEY key;
4082
4083 if (!EVP_HPKE_KEY_init(/* key= */ key.get(),
4084 /* kem= */ kem,
4085 /* priv_key= */ reinterpret_cast<const uint8_t*>(privateKey.get()),
4086 /* priv_key_len= */ privateKey.size())) {
4087 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4088 return nullptr;
4089 }
4090
4091 std::optional<ScopedByteArrayRO> optionalInfo;
4092 const uint8_t* info = nullptr;
4093 size_t infoLen = 0;
4094 if (infoArray != nullptr) {
4095 optionalInfo.emplace(env, infoArray);
4096 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4097 if (info == nullptr) {
4098 return {};
4099 }
4100 infoLen = optionalInfo->size();
4101 }
4102
4103 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4104 ScopedByteArrayRO enc(env, encArray);
4105 if (!EVP_HPKE_CTX_setup_recipient(/* ctx= */ ctx.get(),
4106 /* key= */ key.get(),
4107 /* kdf= */ kdf,
4108 /* aead= */ aead,
4109 /* enc= */ reinterpret_cast<const uint8_t*>(enc.get()),
4110 /* enc_len= */ enc.size(),
4111 /* info= */ info,
4112 /* info_len= */ infoLen)) {
4113 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4114 return nullptr;
4115 }
4116
4117 ScopedLocalRef<jobject> ctxObject(
4118 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4119 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4120 reinterpret_cast<jlong>(ctx.release())));
4121 return ctxObject.release();
4122 }
4123
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray)4124 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass,
4125 jint kemValue,jint kdfValue,
4126 jint aeadValue,
4127 jbyteArray publicKeyArray,
4128 jbyteArray infoArray) {
4129 CHECK_ERROR_QUEUE_ON_RETURN;
4130 JNI_TRACE("EVP_HPKE_CTX_setup_sender(%d, %d, %d, %p, %p)", kemValue, kdfValue, aeadValue,
4131 publicKeyArray, infoArray);
4132
4133 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4134 if (kem == nullptr) {
4135 return nullptr;
4136 }
4137 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4138 if (kdf == nullptr) {
4139 return nullptr;
4140 }
4141 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4142 if (aead == nullptr) {
4143 return nullptr;
4144 }
4145 if (publicKeyArray == nullptr) {
4146 conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray == null");
4147 return {};
4148 }
4149
4150 std::optional<ScopedByteArrayRO> optionalInfo;
4151 const uint8_t* info = nullptr;
4152 size_t infoLen = 0;
4153 if (infoArray != nullptr) {
4154 optionalInfo.emplace(env, infoArray);
4155 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4156 if (info == nullptr) {
4157 return {};
4158 }
4159 infoLen = optionalInfo->size();
4160 }
4161
4162 ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4163
4164 size_t encapsulatedSharedSecretLen;
4165 uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4166
4167 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4168
4169 if (!EVP_HPKE_CTX_setup_sender(/* ctx= */ ctx.get(),
4170 /* out_enc= */ encapsulatedSharedSecret,
4171 /* out_enc_len= */ &encapsulatedSharedSecretLen,
4172 /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4173 /* kem= */ kem,
4174 /* kdf= */ kdf,
4175 /* aead= */ aead,
4176 /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4177 /* peer_public_key_len= */ peer_public_key.size(),
4178 /* info= */ info,
4179 /* info_len= */ infoLen)) {
4180 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_sender");
4181 return {};
4182 }
4183
4184 ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4185 if (encArray.get() == nullptr) {
4186 return {};
4187 }
4188 ScopedByteArrayRW encBytes(env, encArray.get());
4189 if (encBytes.get() == nullptr) {
4190 return {};
4191 }
4192 memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4193
4194 ScopedLocalRef<jobjectArray> result(
4195 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4196
4197 ScopedLocalRef<jobject> ctxObject(
4198 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4199 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4200 reinterpret_cast<jlong>(ctx.release())));
4201
4202 env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4203 env->SetObjectArrayElement(result.get(), 1, encArray.release());
4204
4205 return result.release();
4206 }
4207
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray,jbyteArray seedArray)4208 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(
4209 JNIEnv* env, jclass, jint kemValue, jint kdfValue, jint aeadValue,
4210 jbyteArray publicKeyArray, jbyteArray infoArray, jbyteArray seedArray) {
4211 CHECK_ERROR_QUEUE_ON_RETURN;
4212 JNI_TRACE("EVP_HPKE_CTX_setup_sender_with_seed_for_testing(%d, %d, %d, %p, %p, %p)", kemValue,
4213 kdfValue, aeadValue, publicKeyArray, infoArray, seedArray);
4214
4215 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4216 if (kem == nullptr) {
4217 return nullptr;
4218 }
4219 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4220 if (kdf == nullptr) {
4221 return nullptr;
4222 }
4223 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4224 if (aead == nullptr) {
4225 return nullptr;
4226 }
4227 if (publicKeyArray == nullptr || seedArray == nullptr) {
4228 conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray or seedArray == null");
4229 return {};
4230 }
4231
4232 std::optional<ScopedByteArrayRO> optionalInfo;
4233 const uint8_t* info = nullptr;
4234 size_t infoLen = 0;
4235 if (infoArray != nullptr) {
4236 optionalInfo.emplace(env, infoArray);
4237 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4238 if (info == nullptr) {
4239 return {};
4240 }
4241 infoLen = optionalInfo->size();
4242 }
4243
4244 ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4245
4246 ScopedByteArrayRO seed(env, seedArray);
4247
4248 size_t encapsulatedSharedSecretLen;
4249 uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4250
4251 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4252
4253 if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
4254 /* ctx= */ ctx.get(),
4255 /* out_enc= */ encapsulatedSharedSecret,
4256 /* out_enc_len= */ &encapsulatedSharedSecretLen,
4257 /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4258 /* kem= */ kem,
4259 /* kdf= */ kdf,
4260 /* aead= */ aead,
4261 /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4262 /* peer_public_key_len= */ peer_public_key.size(),
4263 /* info= */ info,
4264 /* info_len= */ infoLen,
4265 /* seed= */ reinterpret_cast<const uint8_t*>(seed.get()),
4266 /* seed_len= */ seed.size())) {
4267 conscrypt::jniutil::throwExceptionFromBoringSSLError(
4268 env, "EVP_HPKE_CTX_setup_sender_with_seed_for_testing");
4269 return {};
4270 }
4271
4272 ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4273 if (encArray.get() == nullptr) {
4274 return {};
4275 }
4276 ScopedByteArrayRW encBytes(env, encArray.get());
4277 if (encBytes.get() == nullptr) {
4278 return {};
4279 }
4280 memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4281
4282 ScopedLocalRef<jobjectArray> result(
4283 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4284
4285 ScopedLocalRef<jobject> ctxObject(
4286 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4287 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4288 reinterpret_cast<jlong>(ctx.release())));
4289
4290 env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4291 env->SetObjectArrayElement(result.get(), 1, encArray.release());
4292
4293 return result.release();
4294 }
4295
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)4296 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
4297 CHECK_ERROR_QUEUE_ON_RETURN;
4298 JNI_TRACE("CMAC_CTX_new");
4299 auto cmacCtx = CMAC_CTX_new();
4300 if (cmacCtx == nullptr) {
4301 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
4302 return 0;
4303 }
4304
4305 return reinterpret_cast<jlong>(cmacCtx);
4306 }
4307
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)4308 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
4309 CHECK_ERROR_QUEUE_ON_RETURN;
4310 CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
4311 JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
4312 if (cmacCtx == nullptr) {
4313 conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
4314 return;
4315 }
4316 CMAC_CTX_free(cmacCtx);
4317 }
4318
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)4319 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
4320 CHECK_ERROR_QUEUE_ON_RETURN;
4321 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4322 JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
4323 if (cmacCtx == nullptr) {
4324 return;
4325 }
4326 ScopedByteArrayRO keyBytes(env, keyArray);
4327 if (keyBytes.get() == nullptr) {
4328 return;
4329 }
4330
4331 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4332
4333 const EVP_CIPHER *cipher;
4334 switch(keyBytes.size()) {
4335 case 16:
4336 cipher = EVP_aes_128_cbc();
4337 break;
4338 case 24:
4339 cipher = EVP_aes_192_cbc();
4340 break;
4341 case 32:
4342 cipher = EVP_aes_256_cbc();
4343 break;
4344 default:
4345 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4346 "CMAC_Init: Unsupported key length");
4347 return;
4348 }
4349
4350 if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
4351 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
4352 JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
4353 return;
4354 }
4355 }
4356
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)4357 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
4358 int inLength) {
4359 CHECK_ERROR_QUEUE_ON_RETURN;
4360 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4361 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4362 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
4363
4364 if (cmacCtx == nullptr) {
4365 return;
4366 }
4367
4368 if (p == nullptr) {
4369 conscrypt::jniutil::throwNullPointerException(env, nullptr);
4370 return;
4371 }
4372
4373 if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
4374 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
4375 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
4376 return;
4377 }
4378 }
4379
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4380 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
4381 jint inOffset, jint inLength) {
4382 CHECK_ERROR_QUEUE_ON_RETURN;
4383 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4384 JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
4385
4386 if (cmacCtx == nullptr) {
4387 return;
4388 }
4389
4390 ScopedByteArrayRO inBytes(env, inArray);
4391 if (inBytes.get() == nullptr) {
4392 return;
4393 }
4394
4395 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4396 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4397 "inBytes");
4398 return;
4399 }
4400
4401 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4402
4403 if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4404 JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
4405 inLength);
4406 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
4407 return;
4408 }
4409 }
4410
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)4411 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
4412 CHECK_ERROR_QUEUE_ON_RETURN;
4413 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4414 JNI_TRACE("CMAC_Final(%p)", cmacCtx);
4415
4416 if (cmacCtx == nullptr) {
4417 return nullptr;
4418 }
4419
4420 uint8_t result[EVP_MAX_MD_SIZE];
4421 size_t len;
4422 if (!CMAC_Final(cmacCtx, result, &len)) {
4423 JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
4424 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
4425 return nullptr;
4426 }
4427
4428 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4429 if (resultArray.get() == nullptr) {
4430 return nullptr;
4431 }
4432 ScopedByteArrayRW resultBytes(env, resultArray.get());
4433 if (resultBytes.get() == nullptr) {
4434 return nullptr;
4435 }
4436 memcpy(resultBytes.get(), result, len);
4437 return resultArray.release();
4438 }
4439
NativeCrypto_CMAC_Reset(JNIEnv * env,jclass,jobject cmacCtxRef)4440 static void NativeCrypto_CMAC_Reset(JNIEnv* env, jclass, jobject cmacCtxRef) {
4441 CHECK_ERROR_QUEUE_ON_RETURN;
4442 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4443 JNI_TRACE("CMAC_Reset(%p)", cmacCtx);
4444
4445 if (cmacCtx == nullptr) {
4446 return;
4447 }
4448
4449 if (!CMAC_Reset(cmacCtx)) {
4450 JNI_TRACE("CMAC_Reset(%p) => threw exception", cmacCtx);
4451 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Reset");
4452 return;
4453 }
4454 }
4455
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)4456 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
4457 CHECK_ERROR_QUEUE_ON_RETURN;
4458 JNI_TRACE("HMAC_CTX_new");
4459 auto hmacCtx = HMAC_CTX_new();
4460 if (hmacCtx == nullptr) {
4461 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
4462 return 0;
4463 }
4464
4465 return reinterpret_cast<jlong>(hmacCtx);
4466 }
4467
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)4468 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
4469 CHECK_ERROR_QUEUE_ON_RETURN;
4470 HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
4471 JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
4472 if (hmacCtx == nullptr) {
4473 conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
4474 return;
4475 }
4476 HMAC_CTX_free(hmacCtx);
4477 }
4478
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)4479 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
4480 jobject evpMdRef) {
4481 CHECK_ERROR_QUEUE_ON_RETURN;
4482 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4483 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4484 JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
4485 if (hmacCtx == nullptr) {
4486 return;
4487 }
4488 ScopedByteArrayRO keyBytes(env, keyArray);
4489 if (keyBytes.get() == nullptr) {
4490 return;
4491 }
4492
4493 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4494 if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
4495 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4496 JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
4497 return;
4498 }
4499 }
4500
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)4501 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
4502 int inLength) {
4503 CHECK_ERROR_QUEUE_ON_RETURN;
4504 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4505 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4506 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
4507
4508 if (hmacCtx == nullptr) {
4509 return;
4510 }
4511
4512 if (p == nullptr) {
4513 conscrypt::jniutil::throwNullPointerException(env, nullptr);
4514 return;
4515 }
4516
4517 if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
4518 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
4519 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
4520 return;
4521 }
4522 }
4523
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4524 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
4525 jint inOffset, jint inLength) {
4526 CHECK_ERROR_QUEUE_ON_RETURN;
4527 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4528 JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
4529
4530 if (hmacCtx == nullptr) {
4531 return;
4532 }
4533
4534 ScopedByteArrayRO inBytes(env, inArray);
4535 if (inBytes.get() == nullptr) {
4536 return;
4537 }
4538
4539 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4540 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4541 "inBytes");
4542 return;
4543 }
4544
4545 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4546 if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4547 JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4548 inLength);
4549 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4550 return;
4551 }
4552 }
4553
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4554 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4555 CHECK_ERROR_QUEUE_ON_RETURN;
4556 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4557 JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4558
4559 if (hmacCtx == nullptr) {
4560 return nullptr;
4561 }
4562
4563 uint8_t result[EVP_MAX_MD_SIZE];
4564 unsigned len;
4565 if (!HMAC_Final(hmacCtx, result, &len)) {
4566 JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4567 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4568 return nullptr;
4569 }
4570
4571 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4572 if (resultArray.get() == nullptr) {
4573 return nullptr;
4574 }
4575 ScopedByteArrayRW resultBytes(env, resultArray.get());
4576 if (resultBytes.get() == nullptr) {
4577 return nullptr;
4578 }
4579 memcpy(resultBytes.get(), result, len);
4580 return resultArray.release();
4581 }
4582
NativeCrypto_HMAC_Reset(JNIEnv * env,jclass,jobject hmacCtxRef)4583 static void NativeCrypto_HMAC_Reset(JNIEnv* env, jclass, jobject hmacCtxRef) {
4584 CHECK_ERROR_QUEUE_ON_RETURN;
4585 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4586 JNI_TRACE("HMAC_Reset(%p)", hmacCtx);
4587
4588 if (hmacCtx == nullptr) {
4589 return;
4590 }
4591
4592 // HMAC_Init_ex with all nulls will reuse the existing key. This is slightly
4593 // more efficient than re-initializing the context with the key again.
4594 if (!HMAC_Init_ex(hmacCtx, /*key=*/nullptr, /*key_len=*/0, /*md=*/nullptr, /*impl=*/nullptr)) {
4595 JNI_TRACE("HMAC_Reset(%p) => threw exception", hmacCtx);
4596 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4597 return;
4598 }
4599 }
4600
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4601 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4602 CHECK_ERROR_QUEUE_ON_RETURN;
4603 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4604
4605 ScopedByteArrayRW outputBytes(env, output);
4606 if (outputBytes.get() == nullptr) {
4607 return;
4608 }
4609
4610 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4611 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4612 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4613 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4614 return;
4615 }
4616
4617 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4618 }
4619
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4620 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4621 /*
4622 * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4623 * Just make a buffer that's large enough here. The documentation recommends
4624 * 80 characters.
4625 */
4626 char output[128];
4627 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4628 if (ret < 0) {
4629 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4630 return nullptr;
4631 } else if (size_t(ret) >= sizeof(output)) {
4632 conscrypt::jniutil::throwRuntimeException(env,
4633 "ASN1_OBJECT_to_OID_string buffer too small");
4634 return nullptr;
4635 }
4636
4637 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4638 return env->NewStringUTF(output);
4639 }
4640
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4641 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4642 jboolean isFinite) {
4643 CHECK_ERROR_QUEUE_ON_RETURN;
4644 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4645
4646 if (streamObj == nullptr) {
4647 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4648 return 0;
4649 }
4650
4651 const BIO_METHOD *method = stream_bio_method();
4652 if (!method) {
4653 return 0;
4654 }
4655 bssl::UniquePtr<BIO> bio(BIO_new(method));
4656 if (bio.get() == nullptr) {
4657 return 0;
4658 }
4659
4660 bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4661
4662 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4663 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4664 }
4665
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4666 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4667 CHECK_ERROR_QUEUE_ON_RETURN;
4668 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4669
4670 if (streamObj == nullptr) {
4671 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4672 return 0;
4673 }
4674
4675 const BIO_METHOD *method = stream_bio_method();
4676 if (!method) {
4677 return 0;
4678 }
4679 bssl::UniquePtr<BIO> bio(BIO_new(method));
4680 if (bio.get() == nullptr) {
4681 return 0;
4682 }
4683
4684 bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4685
4686 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4687 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4688 }
4689
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4690 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4691 CHECK_ERROR_QUEUE_ON_RETURN;
4692 BIO* bio = to_BIO(env, bioRef);
4693 JNI_TRACE("BIO_free_all(%p)", bio);
4694
4695 if (bio == nullptr) {
4696 return;
4697 }
4698
4699 BIO_free_all(bio);
4700 }
4701
4702 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4703 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4704 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4705
4706 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4707 if (buffer.get() == nullptr) {
4708 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4709 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4710 return nullptr;
4711 }
4712
4713 /* Don't interpret the string. */
4714 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4715
4716 /* Write in given format and null terminate. */
4717 X509_NAME_print_ex(buffer.get(), name, 0, flags);
4718 BIO_write(buffer.get(), "\0", 1);
4719
4720 char* tmp;
4721 BIO_get_mem_data(buffer.get(), &tmp);
4722 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4723 return env->NewStringUTF(tmp);
4724 }
4725
4726 /**
4727 * Converts GENERAL_NAME items to the output format expected in
4728 * X509Certificate#getSubjectAlternativeNames and
4729 * X509Certificate#getIssuerAlternativeNames return.
4730 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4731 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4732 switch (gen->type) {
4733 case GEN_EMAIL:
4734 case GEN_DNS:
4735 case GEN_URI: {
4736 // This must be a valid IA5String and must not contain NULs.
4737 // BoringSSL does not currently enforce the former (see
4738 // https://crbug.com/boringssl/427). The latter was historically an
4739 // issue for parsers that truncate at NUL.
4740 const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4741 ssize_t len = ASN1_STRING_length(gen->d.ia5);
4742 std::vector<jchar> jchars;
4743 jchars.reserve(len);
4744 for (ssize_t i = 0; i < len; i++) {
4745 if (data[i] == 0 || data[i] > 127) {
4746 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4747 return nullptr;
4748 }
4749 // Converting ASCII to UTF-16 is the identity function.
4750 jchars.push_back(data[i]);
4751 }
4752 JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4753 return env->NewString(jchars.data(), jchars.size());
4754 }
4755 case GEN_DIRNAME:
4756 /* Write in RFC 2253 format */
4757 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4758 case GEN_IPADD: {
4759 #ifdef _WIN32
4760 void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4761 #else
4762 const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4763 #endif
4764 if (gen->d.ip->length == 4) {
4765 // IPv4
4766 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4767 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4768 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4769 return env->NewStringUTF(buffer.get());
4770 } else {
4771 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4772 strerror(errno));
4773 }
4774 } else if (gen->d.ip->length == 16) {
4775 // IPv6
4776 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4777 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4778 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4779 return env->NewStringUTF(buffer.get());
4780 } else {
4781 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4782 strerror(errno));
4783 }
4784 }
4785
4786 /* Invalid IP encodings are pruned out without throwing an exception. */
4787 return nullptr;
4788 }
4789 case GEN_RID:
4790 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4791 case GEN_OTHERNAME:
4792 case GEN_X400:
4793 default:
4794 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4795 }
4796
4797 return nullptr;
4798 }
4799
4800 #define GN_STACK_SUBJECT_ALT_NAME 1
4801 #define GN_STACK_ISSUER_ALT_NAME 2
4802
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4803 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4804 CONSCRYPT_UNUSED jobject holder,
4805 jint type) {
4806 CHECK_ERROR_QUEUE_ON_RETURN;
4807 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4808 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4809
4810 if (x509 == nullptr) {
4811 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4812 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4813 return nullptr;
4814 }
4815
4816 bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4817 if (type == GN_STACK_SUBJECT_ALT_NAME) {
4818 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4819 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4820 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4821 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4822 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4823 } else {
4824 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4825 return nullptr;
4826 }
4827 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4828 // |ERR_clear_error|, and throw CertificateParsingException.
4829 if (gn_stack == nullptr) {
4830 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
4831 ERR_clear_error();
4832 return nullptr;
4833 }
4834
4835 int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
4836 if (count <= 0) {
4837 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4838 return nullptr;
4839 }
4840
4841 /*
4842 * Keep track of how many originally so we can ignore any invalid
4843 * values later.
4844 */
4845 const int origCount = count;
4846
4847 ScopedLocalRef<jobjectArray> joa(
4848 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4849 for (int i = 0, j = 0; i < origCount; i++, j++) {
4850 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
4851 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4852 if (env->ExceptionCheck()) {
4853 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4854 x509, type);
4855 return nullptr;
4856 }
4857
4858 /*
4859 * If it's nullptr, we'll have to skip this, reduce the number of total
4860 * entries, and fix up the array later.
4861 */
4862 if (val.get() == nullptr) {
4863 j--;
4864 count--;
4865 continue;
4866 }
4867
4868 ScopedLocalRef<jobjectArray> item(
4869 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4870
4871 ScopedLocalRef<jobject> parsedType(
4872 env,
4873 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
4874 conscrypt::jniutil::integer_valueOfMethod, gen->type));
4875 env->SetObjectArrayElement(item.get(), 0, parsedType.get());
4876 env->SetObjectArrayElement(item.get(), 1, val.get());
4877
4878 env->SetObjectArrayElement(joa.get(), j, item.get());
4879 }
4880
4881 if (count == 0) {
4882 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
4883 x509, type, origCount);
4884 joa.reset(nullptr);
4885 } else if (origCount != count) {
4886 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
4887 count);
4888
4889 ScopedLocalRef<jobjectArray> joa_copy(
4890 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
4891
4892 for (int i = 0; i < count; i++) {
4893 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4894 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4895 }
4896
4897 joa.reset(joa_copy.release());
4898 }
4899
4900 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4901 return joa.release();
4902 }
4903
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4904 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
4905 CONSCRYPT_UNUSED jobject holder) {
4906 CHECK_ERROR_QUEUE_ON_RETURN;
4907 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4908 JNI_TRACE("X509_get_notBefore(%p)", x509);
4909
4910 if (x509 == nullptr) {
4911 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4912 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4913 return 0;
4914 }
4915
4916 ASN1_TIME* notBefore = X509_get_notBefore(x509);
4917 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4918 return reinterpret_cast<uintptr_t>(notBefore);
4919 }
4920
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4921 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
4922 CONSCRYPT_UNUSED jobject holder) {
4923 CHECK_ERROR_QUEUE_ON_RETURN;
4924 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4925 JNI_TRACE("X509_get_notAfter(%p)", x509);
4926
4927 if (x509 == nullptr) {
4928 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4929 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
4930 return 0;
4931 }
4932
4933 ASN1_TIME* notAfter = X509_get_notAfter(x509);
4934 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4935 return reinterpret_cast<uintptr_t>(notAfter);
4936 }
4937
4938 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4939 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
4940 CONSCRYPT_UNUSED jobject holder) {
4941 CHECK_ERROR_QUEUE_ON_RETURN;
4942 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4943 JNI_TRACE("X509_get_version(%p)", x509);
4944
4945 if (x509 == nullptr) {
4946 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4947 JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
4948 return 0;
4949 }
4950
4951 // NOLINTNEXTLINE(runtime/int)
4952 long version = X509_get_version(x509);
4953 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
4954 return version;
4955 }
4956
4957 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))4958 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
4959 const ASN1_INTEGER* (*get_serial_func)(const T*)) {
4960 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
4961
4962 if (x509Type == nullptr) {
4963 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
4964 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
4965 return nullptr;
4966 }
4967
4968 const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
4969 bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
4970 if (serialBn.get() == nullptr) {
4971 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4972 return nullptr;
4973 }
4974
4975 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
4976 if (env->ExceptionCheck()) {
4977 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
4978 return nullptr;
4979 }
4980
4981 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
4982 return serialArray.release();
4983 }
4984
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)4985 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
4986 CONSCRYPT_UNUSED jobject holder) {
4987 CHECK_ERROR_QUEUE_ON_RETURN;
4988 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4989 JNI_TRACE("X509_get_serialNumber(%p)", x509);
4990
4991 if (x509 == nullptr) {
4992 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4993 JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
4994 return nullptr;
4995 }
4996 return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
4997 }
4998
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)4999 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
5000 jlong x509RevokedRef) {
5001 CHECK_ERROR_QUEUE_ON_RETURN;
5002 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5003 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5004
5005 if (revoked == nullptr) {
5006 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5007 JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
5008 return 0;
5009 }
5010 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
5011 }
5012
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5013 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
5014 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5015 CHECK_ERROR_QUEUE_ON_RETURN;
5016 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5017 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5018 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5019
5020 if (pkey == nullptr) {
5021 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5022 return;
5023 }
5024
5025 if (x509 == nullptr) {
5026 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5027 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5028 return;
5029 }
5030
5031 if (X509_verify(x509, pkey) != 1) {
5032 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5033 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
5034 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5035 return;
5036 }
5037 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5038 }
5039
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5040 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
5041 CONSCRYPT_UNUSED jobject holder) {
5042 CHECK_ERROR_QUEUE_ON_RETURN;
5043 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5044 JNI_TRACE("get_X509_tbs_cert(%p)", x509);
5045 // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
5046 return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
5047 }
5048
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5049 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
5050 CONSCRYPT_UNUSED jobject holder,
5051 jstring oidString) {
5052 CHECK_ERROR_QUEUE_ON_RETURN;
5053 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5054 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
5055
5056 if (x509 == nullptr) {
5057 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5058 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
5059 return nullptr;
5060 }
5061
5062 bssl::UniquePtr<X509> copy(X509_dup(x509));
5063 if (copy == nullptr) {
5064 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
5065 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
5066 return nullptr;
5067 }
5068
5069 ScopedUtfChars oid(env, oidString);
5070 if (oid.c_str() == nullptr) {
5071 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
5072 return nullptr;
5073 }
5074
5075 bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
5076 if (obj.get() == nullptr) {
5077 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
5078 oid.c_str());
5079 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5080 "Invalid OID.");
5081 ERR_clear_error();
5082 return nullptr;
5083 }
5084
5085 int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
5086 if (extIndex == -1) {
5087 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
5088 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5089 "Extension not found.");
5090 return nullptr;
5091 }
5092
5093 // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
5094 // cached encoding.
5095 X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
5096 return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
5097 }
5098
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5099 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
5100 CONSCRYPT_UNUSED jobject holder) {
5101 CHECK_ERROR_QUEUE_ON_RETURN;
5102 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5103 JNI_TRACE("get_X509_ex_flags(%p)", x509);
5104
5105 if (x509 == nullptr) {
5106 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5107 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5108 return 0;
5109 }
5110
5111 uint32_t flags = X509_get_extension_flags(x509);
5112 // X509_get_extension_flags sometimes leaves values in the error queue. See
5113 // https://crbug.com/boringssl/382.
5114 //
5115 // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
5116 // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
5117 // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
5118 // this JNI call to EXFLAG_CRITICAL.
5119 ERR_clear_error();
5120 return flags;
5121 }
5122
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5123 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
5124 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5125 CONSCRYPT_UNUSED jobject holder2) {
5126 CHECK_ERROR_QUEUE_ON_RETURN;
5127 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5128 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5129 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5130
5131 if (x509_1 == nullptr) {
5132 conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
5133 JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
5134 return 0;
5135 }
5136 if (x509_2 == nullptr) {
5137 conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
5138 JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
5139 return 0;
5140 }
5141 int ret = X509_check_issued(x509_1, x509_2);
5142 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5143 return ret;
5144 }
5145
get_X509_signature(X509 * x509)5146 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
5147 const ASN1_BIT_STRING* signature;
5148 X509_get0_signature(&signature, nullptr, x509);
5149 return signature;
5150 }
5151
get_X509_CRL_signature(X509_CRL * crl)5152 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
5153 const ASN1_BIT_STRING* signature;
5154 X509_CRL_get0_signature(crl, &signature, nullptr);
5155 return signature;
5156 }
5157
5158 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))5159 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
5160 const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
5161 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5162
5163 if (x509Type == nullptr) {
5164 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5165 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5166 return nullptr;
5167 }
5168
5169 const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
5170
5171 ScopedLocalRef<jbyteArray> signatureArray(env,
5172 env->NewByteArray(ASN1_STRING_length(signature)));
5173 if (env->ExceptionCheck()) {
5174 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5175 return nullptr;
5176 }
5177
5178 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5179 if (signatureBytes.get() == nullptr) {
5180 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5181 return nullptr;
5182 }
5183
5184 memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
5185
5186 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5187 ASN1_STRING_length(signature));
5188 return signatureArray.release();
5189 }
5190
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5191 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
5192 CONSCRYPT_UNUSED jobject holder) {
5193 CHECK_ERROR_QUEUE_ON_RETURN;
5194 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5195 JNI_TRACE("get_X509_signature(%p)", x509);
5196
5197 if (x509 == nullptr) {
5198 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5199 JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
5200 return nullptr;
5201 }
5202 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5203 }
5204
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5205 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef,
5206 CONSCRYPT_UNUSED jobject holder) {
5207 CHECK_ERROR_QUEUE_ON_RETURN;
5208 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5209 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
5210
5211 if (crl == nullptr) {
5212 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5213 JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
5214 return nullptr;
5215 }
5216 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5217 }
5218
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)5219 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
5220 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
5221 CONSCRYPT_UNUSED jobject holder2) {
5222 CHECK_ERROR_QUEUE_ON_RETURN;
5223 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5224 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5225 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5226
5227 if (x509crl == nullptr) {
5228 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5229 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5230 return 0;
5231 } else if (x509 == nullptr) {
5232 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5233 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5234 return 0;
5235 }
5236
5237 X509_REVOKED* revoked = nullptr;
5238 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5239 if (ret == 0) {
5240 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5241 return 0;
5242 }
5243
5244 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5245 return reinterpret_cast<uintptr_t>(revoked);
5246 }
5247
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)5248 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
5249 CONSCRYPT_UNUSED jobject holder,
5250 jbyteArray serialArray) {
5251 CHECK_ERROR_QUEUE_ON_RETURN;
5252 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5253 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5254
5255 if (x509crl == nullptr) {
5256 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5257 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5258 return 0;
5259 }
5260
5261 bssl::UniquePtr<BIGNUM> serialBn = arrayToBignum(env, serialArray);
5262 if (serialBn == nullptr) {
5263 if (!env->ExceptionCheck()) {
5264 conscrypt::jniutil::throwNullPointerException(env, "serial == null");
5265 }
5266 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5267 return 0;
5268 }
5269
5270 bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
5271 if (serialInteger.get() == nullptr) {
5272 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5273 return 0;
5274 }
5275
5276 X509_REVOKED* revoked = nullptr;
5277 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5278 if (ret == 0) {
5279 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5280 return 0;
5281 }
5282
5283 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5284 return reinterpret_cast<uintptr_t>(revoked);
5285 }
5286
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5287 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
5288 CONSCRYPT_UNUSED jobject holder) {
5289 CHECK_ERROR_QUEUE_ON_RETURN;
5290 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5291 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5292
5293 if (crl == nullptr) {
5294 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5295 JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
5296 return nullptr;
5297 }
5298
5299 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5300 if (stack == nullptr) {
5301 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5302 return nullptr;
5303 }
5304
5305 size_t size = sk_X509_REVOKED_num(stack);
5306
5307 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
5308 ScopedLongArrayRW revoked(env, revokedArray.get());
5309 for (size_t i = 0; i < size; i++) {
5310 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5311 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5312 }
5313
5314 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
5315 return revokedArray.release();
5316 }
5317
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5318 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
5319 CONSCRYPT_UNUSED jobject holder) {
5320 CHECK_ERROR_QUEUE_ON_RETURN;
5321 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5322 JNI_TRACE("i2d_X509_CRL(%p)", crl);
5323
5324 if (crl == nullptr) {
5325 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5326 JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
5327 return nullptr;
5328 }
5329 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
5330 }
5331
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5332 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
5333 CONSCRYPT_UNUSED jobject holder) {
5334 CHECK_ERROR_QUEUE_ON_RETURN;
5335 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5336 JNI_TRACE("X509_CRL_free(%p)", crl);
5337
5338 if (crl == nullptr) {
5339 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5340 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5341 return;
5342 }
5343
5344 X509_CRL_free(crl);
5345 }
5346
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5347 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
5348 CONSCRYPT_UNUSED jobject holder) {
5349 CHECK_ERROR_QUEUE_ON_RETURN;
5350 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5351 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5352 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5353
5354 if (bio == nullptr) {
5355 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5356 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5357 return;
5358 }
5359
5360 if (crl == nullptr) {
5361 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5362 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5363 return;
5364 }
5365
5366 if (!X509_CRL_print(bio, crl)) {
5367 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
5368 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5369 return;
5370 }
5371 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5372 }
5373
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5374 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5375 CONSCRYPT_UNUSED jobject holder) {
5376 CHECK_ERROR_QUEUE_ON_RETURN;
5377 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5378 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5379
5380 if (crl == nullptr) {
5381 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5382 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
5383 return nullptr;
5384 }
5385
5386 const X509_ALGOR* sig_alg;
5387 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5388 const ASN1_OBJECT* oid;
5389 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5390 return ASN1_OBJECT_to_OID_string(env, oid);
5391 }
5392
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)5393 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
5394 int param_type;
5395 const void* param_value;
5396 X509_ALGOR_get0(nullptr, ¶m_type, ¶m_value, algor);
5397
5398 if (param_type == V_ASN1_UNDEF) {
5399 JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
5400 return nullptr;
5401 }
5402
5403 // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
5404 // recreate it from the returned components.
5405 bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
5406 if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
5407 conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
5408 return nullptr;
5409 }
5410
5411 return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
5412 }
5413
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5414 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
5415 CONSCRYPT_UNUSED jobject holder) {
5416 CHECK_ERROR_QUEUE_ON_RETURN;
5417 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5418 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5419
5420 if (crl == nullptr) {
5421 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5422 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5423 return nullptr;
5424 }
5425
5426 const X509_ALGOR* sig_alg;
5427 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5428 return get_X509_ALGOR_parameter(env, sig_alg);
5429 }
5430
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5431 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
5432 CONSCRYPT_UNUSED jobject holder) {
5433 CHECK_ERROR_QUEUE_ON_RETURN;
5434 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5435
5436 if (crl == nullptr) {
5437 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5438 JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
5439 return nullptr;
5440 }
5441 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5442 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
5443 }
5444
5445 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5446 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
5447 CONSCRYPT_UNUSED jobject holder) {
5448 CHECK_ERROR_QUEUE_ON_RETURN;
5449 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5450 JNI_TRACE("X509_CRL_get_version(%p)", crl);
5451
5452 if (crl == nullptr) {
5453 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5454 JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
5455 return 0;
5456 }
5457 // NOLINTNEXTLINE(runtime/int)
5458 long version = X509_CRL_get_version(crl);
5459 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5460 return version;
5461 }
5462
5463 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5464 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)5465 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
5466 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5467
5468 if (x509Type == nullptr) {
5469 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5470 return nullptr;
5471 }
5472
5473 ScopedUtfChars oid(env, oidString);
5474 if (oid.c_str() == nullptr) {
5475 return nullptr;
5476 }
5477
5478 bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
5479 if (asn1.get() == nullptr) {
5480 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5481 ERR_clear_error();
5482 return nullptr;
5483 }
5484
5485 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5486 if (extIndex == -1) {
5487 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5488 return nullptr;
5489 }
5490
5491 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5492 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5493 return ext;
5494 }
5495
5496 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5497 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)5498 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
5499 X509_EXTENSION* ext =
5500 X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
5501 if (ext == nullptr) {
5502 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5503 return nullptr;
5504 }
5505
5506 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
5507 X509_EXTENSION_get_data(ext));
5508 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
5509 i2d_ASN1_OCTET_STRING);
5510 }
5511
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)5512 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
5513 CONSCRYPT_UNUSED jobject holder, jstring oid) {
5514 CHECK_ERROR_QUEUE_ON_RETURN;
5515 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5516 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5517
5518 if (crl == nullptr) {
5519 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5520 JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
5521 return 0;
5522 }
5523 X509_EXTENSION* ext =
5524 X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
5525 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5526 return reinterpret_cast<uintptr_t>(ext);
5527 }
5528
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)5529 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5530 jstring oid) {
5531 CHECK_ERROR_QUEUE_ON_RETURN;
5532 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5533 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5534 X509_EXTENSION* ext =
5535 X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5536 env, revoked, oid);
5537 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5538 return reinterpret_cast<uintptr_t>(ext);
5539 }
5540
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)5541 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5542 CHECK_ERROR_QUEUE_ON_RETURN;
5543 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5544 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5545
5546 if (revoked == nullptr) {
5547 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5548 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5549 return 0;
5550 }
5551
5552 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5553 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5554 return reinterpret_cast<uintptr_t>(dup);
5555 }
5556
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5557 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5558 jlong x509RevokedRef) {
5559 CHECK_ERROR_QUEUE_ON_RETURN;
5560 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5561 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5562
5563 if (revoked == nullptr) {
5564 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5565 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5566 return 0;
5567 }
5568
5569 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5570 X509_REVOKED_get0_revocationDate(revoked));
5571 return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5572 }
5573
5574 #ifdef __GNUC__
5575 #pragma GCC diagnostic push
5576 #pragma GCC diagnostic ignored "-Wwrite-strings"
5577 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5578 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5579 jlong x509RevokedRef) {
5580 CHECK_ERROR_QUEUE_ON_RETURN;
5581 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5582 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5583 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5584
5585 if (bio == nullptr) {
5586 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5587 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5588 return;
5589 }
5590
5591 if (revoked == nullptr) {
5592 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5593 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5594 return;
5595 }
5596
5597 BIO_printf(bio, "Serial Number: ");
5598 i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5599 BIO_printf(bio, "\nRevocation Date: ");
5600 ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5601 BIO_printf(bio, "\n");
5602 // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5603 // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5604 X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5605 0);
5606 }
5607 #ifndef _WIN32
5608 #pragma GCC diagnostic pop
5609 #endif
5610
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5611 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5612 CONSCRYPT_UNUSED jobject holder) {
5613 CHECK_ERROR_QUEUE_ON_RETURN;
5614 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5615 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5616
5617 if (crl == nullptr) {
5618 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5619 JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5620 return nullptr;
5621 }
5622 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5623 }
5624
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5625 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5626 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5627 CHECK_ERROR_QUEUE_ON_RETURN;
5628 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5629 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5630 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5631
5632 if (pkey == nullptr) {
5633 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5634 return;
5635 }
5636
5637 if (crl == nullptr) {
5638 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5639 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5640 return;
5641 }
5642
5643 if (X509_CRL_verify(crl, pkey) != 1) {
5644 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5645 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5646 return;
5647 }
5648 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5649 }
5650
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5651 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5652 CONSCRYPT_UNUSED jobject holder) {
5653 CHECK_ERROR_QUEUE_ON_RETURN;
5654 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5655 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5656
5657 if (crl == nullptr) {
5658 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5659 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5660 return 0;
5661 }
5662
5663 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5664 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5665 return reinterpret_cast<uintptr_t>(lastUpdate);
5666 }
5667
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5668 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5669 CONSCRYPT_UNUSED jobject holder) {
5670 CHECK_ERROR_QUEUE_ON_RETURN;
5671 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5672 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5673
5674 if (crl == nullptr) {
5675 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5676 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5677 return 0;
5678 }
5679
5680 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5681 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5682 return reinterpret_cast<uintptr_t>(nextUpdate);
5683 }
5684
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5685 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5686 CHECK_ERROR_QUEUE_ON_RETURN;
5687 X509_REVOKED* x509Revoked =
5688 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5689 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5690 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5691 }
5692
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5693 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5694 CHECK_ERROR_QUEUE_ON_RETURN;
5695 X509_EXTENSION* ext =
5696 reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5697
5698 if (ext == nullptr) {
5699 conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5700 return 0;
5701 }
5702
5703 return X509_supported_extension(ext);
5704 }
5705
decimal_to_integer(const char * data,size_t len,int * out)5706 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5707 int ret = 0;
5708 for (size_t i = 0; i < len; i++) {
5709 ret *= 10;
5710 if (data[i] < '0' || data[i] > '9') {
5711 return false;
5712 }
5713 ret += data[i] - '0';
5714 }
5715 *out = ret;
5716 return true;
5717 }
5718
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5719 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5720 jobject calendar) {
5721 CHECK_ERROR_QUEUE_ON_RETURN;
5722 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5723 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5724
5725 if (asn1Time == nullptr) {
5726 conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5727 return;
5728 }
5729
5730 if (!ASN1_TIME_check(asn1Time)) {
5731 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5732 return;
5733 }
5734
5735 bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5736 if (gen.get() == nullptr) {
5737 conscrypt::jniutil::throwParsingException(env,
5738 "ASN1_TIME_to_generalizedtime returned null");
5739 return;
5740 }
5741
5742 if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5743 conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5744 return;
5745 }
5746
5747 int year, mon, mday, hour, min, sec;
5748 const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5749 if (!decimal_to_integer(data, 4, &year) ||
5750 !decimal_to_integer(data + 4, 2, &mon) ||
5751 !decimal_to_integer(data + 6, 2, &mday) ||
5752 !decimal_to_integer(data + 8, 2, &hour) ||
5753 !decimal_to_integer(data + 10, 2, &min) ||
5754 !decimal_to_integer(data + 12, 2, &sec)) {
5755 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5756 return;
5757 }
5758
5759 env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5760 min, sec);
5761 }
5762
5763 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5764 // functions so that they can be freed properly when finished. This struct owns
5765 // all objects pointed to by its members.
5766 struct CbsHandle {
5767 // A pointer to the CBS.
5768 std::unique_ptr<CBS> cbs;
5769 // A pointer to the data held by the CBS. If the data held by the CBS
5770 // is owned by a different CbsHandle, data will be null.
5771 std::unique_ptr<unsigned char[]> data;
5772 };
5773
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5774 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5775 CHECK_ERROR_QUEUE_ON_RETURN;
5776 JNI_TRACE("asn1_read_init(%p)", data);
5777
5778 ScopedByteArrayRO bytes(env, data);
5779 if (bytes.get() == nullptr) {
5780 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5781 return 0;
5782 }
5783
5784 std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5785 cbs->data.reset(new unsigned char[bytes.size()]);
5786 memcpy(cbs->data.get(), bytes.get(), bytes.size());
5787
5788 cbs->cbs.reset(new CBS());
5789 CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5790 JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5791 return reinterpret_cast<uintptr_t>(cbs.release());
5792 }
5793
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5794 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5795 CHECK_ERROR_QUEUE_ON_RETURN;
5796 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5797 JNI_TRACE("asn1_read_sequence(%p)", cbs);
5798
5799 std::unique_ptr<CbsHandle> seq(new CbsHandle());
5800 seq->cbs.reset(new CBS());
5801 if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5802 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5803 return 0;
5804 }
5805 JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5806 return reinterpret_cast<uintptr_t>(seq.release());
5807 }
5808
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5809 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5810 jlong cbsRef, jint tag) {
5811 CHECK_ERROR_QUEUE_ON_RETURN;
5812 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5813 JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5814
5815 int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5816 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5817 JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5818 return result ? JNI_TRUE : JNI_FALSE;
5819 }
5820
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5821 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5822 CHECK_ERROR_QUEUE_ON_RETURN;
5823 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5824 JNI_TRACE("asn1_read_tagged(%p)", cbs);
5825
5826 std::unique_ptr<CbsHandle> tag(new CbsHandle());
5827 tag->cbs.reset(new CBS());
5828 if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5829 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5830 return 0;
5831 }
5832 JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
5833 return reinterpret_cast<uintptr_t>(tag.release());
5834 }
5835
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)5836 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
5837 CHECK_ERROR_QUEUE_ON_RETURN;
5838 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5839 JNI_TRACE("asn1_read_octetstring(%p)", cbs);
5840
5841 std::unique_ptr<CBS> str(new CBS());
5842 if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
5843 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5844 return 0;
5845 }
5846 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
5847 if (out.get() == nullptr) {
5848 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5849 return 0;
5850 }
5851 ScopedByteArrayRW outBytes(env, out.get());
5852 if (outBytes.get() == nullptr) {
5853 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5854 return 0;
5855 }
5856 memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
5857 JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
5858 return out.release();
5859 }
5860
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)5861 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
5862 CHECK_ERROR_QUEUE_ON_RETURN;
5863 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5864 JNI_TRACE("asn1_read_uint64(%p)", cbs);
5865
5866 // NOLINTNEXTLINE(runtime/int)
5867 uint64_t value;
5868 if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
5869 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5870 return 0;
5871 }
5872 return value;
5873 }
5874
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)5875 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
5876 CHECK_ERROR_QUEUE_ON_RETURN;
5877 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5878 JNI_TRACE("asn1_read_null(%p)", cbs);
5879
5880 CBS null_holder;
5881 if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
5882 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5883 }
5884 }
5885
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)5886 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
5887 CHECK_ERROR_QUEUE_ON_RETURN;
5888 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5889 JNI_TRACE("asn1_read_oid(%p)", cbs);
5890
5891 CBS oid_cbs;
5892 if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
5893 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5894 return nullptr;
5895 }
5896 int nid = OBJ_cbs2nid(&oid_cbs);
5897 if (nid == NID_undef) {
5898 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
5899 return nullptr;
5900 }
5901 const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
5902 if (obj == nullptr) {
5903 conscrypt::jniutil::throwIOException(env,
5904 "Error reading ASN.1 encoding: "
5905 "Could not find ASN1_OBJECT for NID");
5906 return nullptr;
5907 }
5908 return ASN1_OBJECT_to_OID_string(env, obj);
5909 }
5910
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5911 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5912 jlong cbsRef) {
5913 CHECK_ERROR_QUEUE_ON_RETURN;
5914 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5915 JNI_TRACE("asn1_read_is_empty(%p)", cbs);
5916
5917 bool empty = (CBS_len(cbs->cbs.get()) == 0);
5918 JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
5919 return empty;
5920 }
5921
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)5922 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
5923 CHECK_ERROR_QUEUE_ON_RETURN;
5924 if (cbsRef == 0) {
5925 JNI_TRACE("asn1_read_free(0)");
5926 return;
5927 }
5928 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5929 JNI_TRACE("asn1_read_free(%p)", cbs);
5930 delete cbs;
5931 }
5932
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)5933 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
5934 CHECK_ERROR_QUEUE_ON_RETURN;
5935 JNI_TRACE("asn1_write_init");
5936 std::unique_ptr<CBB> cbb(new CBB());
5937 if (!CBB_init(cbb.get(), 128)) {
5938 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5939 return 0;
5940 }
5941 JNI_TRACE("asn1_write_init => %p", cbb.get());
5942 return reinterpret_cast<uintptr_t>(cbb.release());
5943 }
5944
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)5945 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
5946 CHECK_ERROR_QUEUE_ON_RETURN;
5947 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5948 JNI_TRACE("asn1_write_sequence(%p)", cbb);
5949
5950 std::unique_ptr<CBB> seq(new CBB());
5951 if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
5952 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5953 return 0;
5954 }
5955 JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
5956 return reinterpret_cast<uintptr_t>(seq.release());
5957 }
5958
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)5959 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
5960 CHECK_ERROR_QUEUE_ON_RETURN;
5961 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5962 JNI_TRACE("asn1_write_tag(%p)", cbb);
5963
5964 std::unique_ptr<CBB> tag_holder(new CBB());
5965 if (!CBB_add_asn1(cbb, tag_holder.get(),
5966 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
5967 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5968 return 0;
5969 }
5970 JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
5971 return reinterpret_cast<uintptr_t>(tag_holder.release());
5972 }
5973
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)5974 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
5975 jbyteArray data) {
5976 CHECK_ERROR_QUEUE_ON_RETURN;
5977 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
5978 JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
5979
5980 ScopedByteArrayRO bytes(env, data);
5981 if (bytes.get() == nullptr) {
5982 JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
5983 return;
5984 }
5985
5986 std::unique_ptr<CBB> octetstring(new CBB());
5987 if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
5988 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5989 return;
5990 }
5991 if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
5992 bytes.size())) {
5993 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5994 return;
5995 }
5996 if (!CBB_flush(cbb)) {
5997 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
5998 return;
5999 }
6000 }
6001
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)6002 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
6003 CHECK_ERROR_QUEUE_ON_RETURN;
6004 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6005 JNI_TRACE("asn1_write_uint64(%p)", cbb);
6006
6007 if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
6008 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6009 return;
6010 }
6011 }
6012
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)6013 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
6014 CHECK_ERROR_QUEUE_ON_RETURN;
6015 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6016 JNI_TRACE("asn1_write_null(%p)", cbb);
6017
6018 CBB null_holder;
6019 if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
6020 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6021 return;
6022 }
6023 if (!CBB_flush(cbb)) {
6024 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6025 return;
6026 }
6027 }
6028
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)6029 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
6030 CHECK_ERROR_QUEUE_ON_RETURN;
6031 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6032 JNI_TRACE("asn1_write_oid(%p)", cbb);
6033
6034 ScopedUtfChars oid_chars(env, oid);
6035 if (oid_chars.c_str() == nullptr) {
6036 return;
6037 }
6038
6039 int nid = OBJ_txt2nid(oid_chars.c_str());
6040 if (nid == NID_undef) {
6041 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6042 return;
6043 }
6044
6045 if (!OBJ_nid2cbb(cbb, nid)) {
6046 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6047 return;
6048 }
6049 }
6050
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)6051 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
6052 CHECK_ERROR_QUEUE_ON_RETURN;
6053 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6054 JNI_TRACE("asn1_write_flush(%p)", cbb);
6055
6056 if (!CBB_flush(cbb)) {
6057 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6058 return;
6059 }
6060 }
6061
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)6062 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
6063 CHECK_ERROR_QUEUE_ON_RETURN;
6064 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6065 JNI_TRACE("asn1_write_finish(%p)", cbb);
6066
6067 uint8_t* data;
6068 size_t data_len;
6069 if (!CBB_finish(cbb, &data, &data_len)) {
6070 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6071 return 0;
6072 }
6073 bssl::UniquePtr<uint8_t> data_storage(data);
6074 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
6075 if (out.get() == nullptr) {
6076 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6077 return 0;
6078 }
6079 ScopedByteArrayRW outBytes(env, out.get());
6080 if (outBytes.get() == nullptr) {
6081 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6082 return 0;
6083 }
6084 memcpy(outBytes.get(), data, data_len);
6085 return out.release();
6086 }
6087
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6088 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6089 CHECK_ERROR_QUEUE_ON_RETURN;
6090 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6091 JNI_TRACE("asn1_write_cleanup(%p)", cbb);
6092
6093 CBB_cleanup(cbb);
6094 }
6095
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6096 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6097 CHECK_ERROR_QUEUE_ON_RETURN;
6098 if (cbbRef == 0) {
6099 JNI_TRACE("asn1_write_free(0)");
6100 return;
6101 }
6102 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6103 JNI_TRACE("asn1_write_free(%p)", cbb);
6104 delete cbb;
6105 }
6106
6107 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)6108 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6109 BIO* bio = to_BIO(env, bioRef);
6110 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
6111
6112 if (bio == nullptr) {
6113 return 0;
6114 }
6115
6116 T* x = d2i_func(bio, nullptr);
6117 if (x == nullptr) {
6118 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
6119 return 0;
6120 }
6121
6122 return reinterpret_cast<uintptr_t>(x);
6123 }
6124
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)6125 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
6126 CHECK_ERROR_QUEUE_ON_RETURN;
6127 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
6128 }
6129
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)6130 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6131 CHECK_ERROR_QUEUE_ON_RETURN;
6132 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
6133 }
6134
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)6135 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
6136 CHECK_ERROR_QUEUE_ON_RETURN;
6137 ScopedByteArrayRO bytes(env, certBytes);
6138 if (bytes.get() == nullptr) {
6139 JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
6140 return 0;
6141 }
6142
6143 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
6144 // NOLINTNEXTLINE(runtime/int)
6145 X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
6146 if (x == nullptr) {
6147 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6148 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
6149 return 0;
6150 }
6151 return reinterpret_cast<uintptr_t>(x);
6152 }
6153
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6154 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
6155 CONSCRYPT_UNUSED jobject holder) {
6156 CHECK_ERROR_QUEUE_ON_RETURN;
6157 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6158 JNI_TRACE("i2d_X509(%p)", x509);
6159
6160 if (x509 == nullptr) {
6161 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6162 JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
6163 return nullptr;
6164 }
6165 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
6166 }
6167
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6168 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
6169 CONSCRYPT_UNUSED jobject holder) {
6170 CHECK_ERROR_QUEUE_ON_RETURN;
6171 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6172 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
6173
6174 if (x509 == nullptr) {
6175 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6176 JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
6177 return nullptr;
6178 }
6179 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
6180 }
6181
6182 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)6183 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
6184 BIO* bio = to_BIO(env, bioRef);
6185 JNI_TRACE("PEM_to_jlong(%p)", bio);
6186
6187 if (bio == nullptr) {
6188 JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
6189 return 0;
6190 }
6191
6192 T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
6193 if (x == nullptr) {
6194 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
6195 JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
6196 return 0;
6197 }
6198
6199 JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
6200 return reinterpret_cast<uintptr_t>(x);
6201 }
6202
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)6203 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
6204 CHECK_ERROR_QUEUE_ON_RETURN;
6205 // NOLINTNEXTLINE(runtime/int)
6206 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
6207 return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
6208 }
6209
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)6210 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
6211 CHECK_ERROR_QUEUE_ON_RETURN;
6212 // NOLINTNEXTLINE(runtime/int)
6213 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
6214 return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
6215 }
6216
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)6217 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
6218 CHECK_ERROR_QUEUE_ON_RETURN;
6219 // NOLINTNEXTLINE(runtime/int)
6220 JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
6221 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
6222 }
6223
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)6224 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
6225 CHECK_ERROR_QUEUE_ON_RETURN;
6226 // NOLINTNEXTLINE(runtime/int)
6227 JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
6228 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
6229 }
6230
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)6231 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
6232 if (certs == nullptr) {
6233 return nullptr;
6234 }
6235
6236 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6237 size_t size = sk_X509_num(certs);
6238 ref_array.reset(env->NewLongArray(size));
6239 ScopedLongArrayRW items(env, ref_array.get());
6240 for (size_t i = 0; i < size; i++) {
6241 X509* cert = sk_X509_value(certs, i);
6242 X509_up_ref(cert);
6243 items[i] = reinterpret_cast<uintptr_t>(cert);
6244 }
6245
6246 JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
6247 return ref_array.release();
6248 }
6249
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)6250 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
6251 if (crls == nullptr) {
6252 return nullptr;
6253 }
6254
6255 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6256 size_t size = sk_X509_CRL_num(crls);
6257 ref_array.reset(env->NewLongArray(size));
6258 ScopedLongArrayRW items(env, ref_array.get());
6259 for (size_t i = 0; i < size; i++) {
6260 X509_CRL* crl = sk_X509_CRL_value(crls, i);
6261 X509_CRL_up_ref(crl);
6262 items[i] = reinterpret_cast<uintptr_t>(crl);
6263 }
6264
6265 JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
6266 return ref_array.release();
6267 }
6268
6269 #define PKCS7_CERTS 1
6270 #define PKCS7_CRLS 2
6271
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)6272 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
6273 CHECK_ERROR_QUEUE_ON_RETURN;
6274 STACK_OF(X509)* stack = sk_X509_new_null();
6275
6276 ScopedLongArrayRO certs(env, certsArray);
6277 for (size_t i = 0; i < certs.size(); i++) {
6278 X509* item = reinterpret_cast<X509*>(certs[i]);
6279 if (sk_X509_push(stack, item) == 0) {
6280 sk_X509_free(stack);
6281 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
6282 return nullptr;
6283 }
6284 }
6285
6286 bssl::ScopedCBB out;
6287 CBB_init(out.get(), 1024 * certs.size());
6288 if (!PKCS7_bundle_certificates(out.get(), stack)) {
6289 sk_X509_free(stack);
6290 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
6291 return nullptr;
6292 }
6293
6294 sk_X509_free(stack);
6295
6296 return CBBToByteArray(env, out.get());
6297 }
6298
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)6299 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
6300 CHECK_ERROR_QUEUE_ON_RETURN;
6301 BIO* bio = to_BIO(env, bioRef);
6302 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
6303
6304 if (bio == nullptr) {
6305 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
6306 return nullptr;
6307 }
6308
6309 if (which == PKCS7_CERTS) {
6310 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6311 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
6312 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
6313 return nullptr;
6314 }
6315 return X509s_to_ItemArray(env, outCerts.get());
6316 } else if (which == PKCS7_CRLS) {
6317 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6318 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
6319 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
6320 return nullptr;
6321 }
6322 return X509_CRLs_to_ItemArray(env, outCRLs.get());
6323 } else {
6324 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6325 return nullptr;
6326 }
6327 }
6328
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)6329 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
6330 CHECK_ERROR_QUEUE_ON_RETURN;
6331 BIO* bio = to_BIO(env, bioRef);
6332 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
6333
6334 if (bio == nullptr) {
6335 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
6336 return nullptr;
6337 }
6338
6339 uint8_t* data;
6340 size_t len;
6341 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6342 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
6343 conscrypt::jniutil::throwParsingException);
6344 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
6345 return nullptr;
6346 }
6347 bssl::UniquePtr<uint8_t> data_storage(data);
6348
6349 CBS cbs;
6350 CBS_init(&cbs, data, len);
6351
6352 if (which == PKCS7_CERTS) {
6353 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6354 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
6355 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
6356 "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
6357 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
6358 return nullptr;
6359 }
6360 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
6361 return X509s_to_ItemArray(env, outCerts.get());
6362 } else if (which == PKCS7_CRLS) {
6363 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6364 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
6365 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
6366 conscrypt::jniutil::throwParsingException);
6367 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
6368 return nullptr;
6369 }
6370 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
6371 return X509_CRLs_to_ItemArray(env, outCRLs.get());
6372 } else {
6373 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6374 return nullptr;
6375 }
6376 }
6377
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)6378 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6379 CHECK_ERROR_QUEUE_ON_RETURN;
6380 BIO* bio = to_BIO(env, bioRef);
6381 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
6382
6383 if (bio == nullptr) {
6384 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
6385 return nullptr;
6386 }
6387
6388 uint8_t* data;
6389 size_t len;
6390 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6391 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
6392 conscrypt::jniutil::throwParsingException);
6393 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
6394 return nullptr;
6395 }
6396 bssl::UniquePtr<uint8_t> data_storage(data);
6397
6398 bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
6399 if (path.get() == nullptr) {
6400 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
6401 return nullptr;
6402 }
6403
6404 CBS cbs, sequence;
6405 CBS_init(&cbs, data, len);
6406 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
6407 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6408 ERR_clear_error();
6409 return nullptr;
6410 }
6411
6412 while (CBS_len(&sequence) > 0) {
6413 CBS child;
6414 if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
6415 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6416 ERR_clear_error();
6417 return nullptr;
6418 }
6419
6420 const uint8_t* tmp = CBS_data(&child);
6421 // NOLINTNEXTLINE(runtime/int)
6422 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
6423 if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
6424 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6425 ERR_clear_error();
6426 return nullptr;
6427 }
6428
6429 if (!sk_X509_push(path.get(), cert.get())) {
6430 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
6431 return nullptr;
6432 }
6433 OWNERSHIP_TRANSFERRED(cert);
6434 }
6435
6436 size_t size = sk_X509_num(path.get());
6437
6438 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
6439 ScopedLongArrayRW certs(env, certArray.get());
6440 for (size_t i = 0; i < size; i++) {
6441 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
6442 certs[i] = reinterpret_cast<uintptr_t>(item);
6443 }
6444
6445 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
6446 return certArray.release();
6447 }
6448
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)6449 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
6450 CHECK_ERROR_QUEUE_ON_RETURN;
6451 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
6452 ScopedLongArrayRO certsArray(env, certs);
6453 if (certsArray.get() == nullptr) {
6454 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
6455 return nullptr;
6456 }
6457
6458 bssl::ScopedCBB result;
6459 CBB seq_contents;
6460 if (!CBB_init(result.get(), 2048 * certsArray.size())) {
6461 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
6462 return nullptr;
6463 }
6464 if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
6465 return nullptr;
6466 }
6467
6468 for (size_t i = 0; i < certsArray.size(); i++) {
6469 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
6470 uint8_t* buf;
6471 int len = i2d_X509(x509, nullptr);
6472
6473 if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
6474 i2d_X509(x509, &buf) < 0) {
6475 return nullptr;
6476 }
6477 }
6478
6479 return CBBToByteArray(env, result.get());
6480 }
6481
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6482 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
6483 CONSCRYPT_UNUSED jobject holder) {
6484 CHECK_ERROR_QUEUE_ON_RETURN;
6485 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6486 JNI_TRACE("X509_free(%p)", x509);
6487
6488 if (x509 == nullptr) {
6489 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6490 JNI_TRACE("X509_free(%p) => x509 == null", x509);
6491 return;
6492 }
6493
6494 X509_free(x509);
6495 }
6496
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)6497 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
6498 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
6499 CONSCRYPT_UNUSED jobject holder2) {
6500 CHECK_ERROR_QUEUE_ON_RETURN;
6501 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
6502 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
6503 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
6504
6505 if (x509_1 == nullptr) {
6506 conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
6507 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
6508 return -1;
6509 }
6510
6511 if (x509_2 == nullptr) {
6512 conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
6513 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
6514 return -1;
6515 }
6516
6517 int ret = X509_cmp(x509_1, x509_2);
6518 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6519 return ret;
6520 }
6521
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)6522 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6523 CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
6524 jlong certflagJava) {
6525 CHECK_ERROR_QUEUE_ON_RETURN;
6526 BIO* bio = to_BIO(env, bioRef);
6527 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6528 // NOLINTNEXTLINE(runtime/int)
6529 unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
6530 // NOLINTNEXTLINE(runtime/int)
6531 unsigned long certflag = static_cast<unsigned long>(certflagJava);
6532 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6533
6534 if (bio == nullptr) {
6535 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6536 return;
6537 }
6538
6539 if (x509 == nullptr) {
6540 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6541 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6542 return;
6543 }
6544
6545 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6546 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
6547 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6548 return;
6549 }
6550 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6551 }
6552
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6553 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
6554 CONSCRYPT_UNUSED jobject holder) {
6555 CHECK_ERROR_QUEUE_ON_RETURN;
6556 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6557 JNI_TRACE("X509_get_pubkey(%p)", x509);
6558
6559 if (x509 == nullptr) {
6560 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6561 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6562 return 0;
6563 }
6564
6565 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6566 if (pkey.get() == nullptr) {
6567 const uint32_t last_error = ERR_peek_last_error();
6568 const uint32_t first_error = ERR_peek_error();
6569 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6570 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6571 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6572 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6573 ERR_clear_error();
6574 conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6575 return 0;
6576 }
6577
6578 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6579 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6580 return 0;
6581 }
6582
6583 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6584 return reinterpret_cast<uintptr_t>(pkey.release());
6585 }
6586
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6587 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6588 CONSCRYPT_UNUSED jobject holder) {
6589 CHECK_ERROR_QUEUE_ON_RETURN;
6590 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6591 JNI_TRACE("X509_get_issuer_name(%p)", x509);
6592
6593 if (x509 == nullptr) {
6594 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6595 JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6596 return nullptr;
6597 }
6598 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6599 }
6600
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6601 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6602 CONSCRYPT_UNUSED jobject holder) {
6603 CHECK_ERROR_QUEUE_ON_RETURN;
6604 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6605 JNI_TRACE("X509_get_subject_name(%p)", x509);
6606
6607 if (x509 == nullptr) {
6608 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6609 JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6610 return nullptr;
6611 }
6612 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6613 }
6614
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6615 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6616 CONSCRYPT_UNUSED jobject holder) {
6617 CHECK_ERROR_QUEUE_ON_RETURN;
6618 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6619 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6620
6621 if (x509 == nullptr) {
6622 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6623 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6624 return nullptr;
6625 }
6626
6627 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6628 ASN1_OBJECT* algorithm;
6629 X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6630 return ASN1_OBJECT_to_OID_string(env, algorithm);
6631 }
6632
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6633 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6634 CONSCRYPT_UNUSED jobject holder) {
6635 CHECK_ERROR_QUEUE_ON_RETURN;
6636 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6637 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6638
6639 if (x509 == nullptr) {
6640 conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6641 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6642 return nullptr;
6643 }
6644
6645 const X509_ALGOR* sig_alg;
6646 X509_get0_signature(nullptr, &sig_alg, x509);
6647 const ASN1_OBJECT* oid;
6648 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6649 return ASN1_OBJECT_to_OID_string(env, oid);
6650 }
6651
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6652 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6653 CONSCRYPT_UNUSED jobject holder) {
6654 CHECK_ERROR_QUEUE_ON_RETURN;
6655 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6656 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6657
6658 if (x509 == nullptr) {
6659 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6660 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6661 return nullptr;
6662 }
6663
6664 const X509_ALGOR* sig_alg;
6665 X509_get0_signature(nullptr, &sig_alg, x509);
6666 return get_X509_ALGOR_parameter(env, sig_alg);
6667 }
6668
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6669 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6670 CONSCRYPT_UNUSED jobject holder) {
6671 CHECK_ERROR_QUEUE_ON_RETURN;
6672 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6673 JNI_TRACE("get_X509_issuerUID(%p)", x509);
6674
6675 if (x509 == nullptr) {
6676 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6677 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6678 return nullptr;
6679 }
6680
6681 const ASN1_BIT_STRING* issuer_uid;
6682 X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6683 if (issuer_uid == nullptr) {
6684 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6685 return nullptr;
6686 }
6687
6688 return ASN1BitStringToBooleanArray(env, issuer_uid);
6689 }
6690
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6691 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6692 CONSCRYPT_UNUSED jobject holder) {
6693 CHECK_ERROR_QUEUE_ON_RETURN;
6694 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6695 JNI_TRACE("get_X509_subjectUID(%p)", x509);
6696
6697 if (x509 == nullptr) {
6698 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6699 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6700 return nullptr;
6701 }
6702
6703 const ASN1_BIT_STRING* subject_uid;
6704 X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6705 if (subject_uid == nullptr) {
6706 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6707 return nullptr;
6708 }
6709
6710 return ASN1BitStringToBooleanArray(env, subject_uid);
6711 }
6712
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6713 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6714 CONSCRYPT_UNUSED jobject holder) {
6715 CHECK_ERROR_QUEUE_ON_RETURN;
6716 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6717 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6718
6719 if (x509 == nullptr) {
6720 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6721 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6722 return nullptr;
6723 }
6724
6725 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6726 // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6727 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6728 bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6729 static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6730 if (bitStr.get() == nullptr) {
6731 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6732 ERR_clear_error();
6733 return nullptr;
6734 }
6735
6736 return ASN1BitStringToBooleanArray(env, bitStr.get());
6737 }
6738
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6739 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6740 CONSCRYPT_UNUSED jobject holder) {
6741 CHECK_ERROR_QUEUE_ON_RETURN;
6742 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6743 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6744
6745 if (x509 == nullptr) {
6746 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6747 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6748 return nullptr;
6749 }
6750
6751 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6752 // |ERR_clear_error|, and throw CertificateParsingException.
6753 bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6754 X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6755 if (objArray.get() == nullptr) {
6756 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6757 ERR_clear_error();
6758 return nullptr;
6759 }
6760
6761 size_t size = sk_ASN1_OBJECT_num(objArray.get());
6762 ScopedLocalRef<jobjectArray> exKeyUsage(
6763 env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6764 nullptr));
6765 if (exKeyUsage.get() == nullptr) {
6766 return nullptr;
6767 }
6768
6769 for (size_t i = 0; i < size; i++) {
6770 ScopedLocalRef<jstring> oidStr(
6771 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6772 env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6773 }
6774
6775 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6776 return exKeyUsage.release();
6777 }
6778
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6779 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6780 CONSCRYPT_UNUSED jobject holder) {
6781 CHECK_ERROR_QUEUE_ON_RETURN;
6782 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6783 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6784
6785 if (x509 == nullptr) {
6786 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6787 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6788 return 0;
6789 }
6790
6791 // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6792 // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6793 // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6794 // the constructor even if |EXFLAG_INVALID| is set.
6795 //
6796 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6797 // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6798 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6799 bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6800 X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6801 if (basic_constraints == nullptr) {
6802 JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6803 ERR_clear_error();
6804 return -1;
6805 }
6806
6807 if (basic_constraints->pathlen == nullptr) {
6808 JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6809 return -1;
6810 }
6811
6812 if (!basic_constraints->ca) {
6813 // Path length constraints are only valid for CA certificates.
6814 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6815 JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6816 return -1;
6817 }
6818
6819 if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6820 // Path length constraints may not be negative.
6821 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6822 JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6823 return -1;
6824 }
6825
6826 long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6827 if (pathlen == -1 || pathlen > INT_MAX) {
6828 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6829 // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6830 // constraint is plausible, but Chromium rejects all values above 255.
6831 JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
6832 return -1;
6833 }
6834
6835 JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
6836 return pathlen;
6837 }
6838
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)6839 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6840 CONSCRYPT_UNUSED jobject holder,
6841 jstring oidString) {
6842 CHECK_ERROR_QUEUE_ON_RETURN;
6843 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6844 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6845 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6846 }
6847
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)6848 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6849 CONSCRYPT_UNUSED jobject holder,
6850 jstring oidString) {
6851 CHECK_ERROR_QUEUE_ON_RETURN;
6852 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6853 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6854
6855 if (crl == nullptr) {
6856 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
6857 JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
6858 return nullptr;
6859 }
6860 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6861 oidString);
6862 }
6863
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6864 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6865 jstring oidString) {
6866 CHECK_ERROR_QUEUE_ON_RETURN;
6867 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6868 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6869
6870 if (revoked == nullptr) {
6871 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
6872 JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
6873 return nullptr;
6874 }
6875 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6876 env, revoked, oidString);
6877 }
6878
6879 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
6880 X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6881 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6882 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6883 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6884
6885 if (x509 == nullptr) {
6886 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6887 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6888 return nullptr;
6889 }
6890
6891 int lastPos = -1;
6892 int count = 0;
6893 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6894 count++;
6895 }
6896
6897 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6898
6899 ScopedLocalRef<jobjectArray> joa(
6900 env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
6901 if (joa.get() == nullptr) {
6902 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6903 return nullptr;
6904 }
6905
6906 lastPos = -1;
6907 count = 0;
6908 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6909 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6910
6911 ScopedLocalRef<jstring> extOid(
6912 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
6913 if (extOid.get() == nullptr) {
6914 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6915 return nullptr;
6916 }
6917
6918 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6919 }
6920
6921 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6922 return joa.release();
6923 }
6924
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)6925 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6926 CONSCRYPT_UNUSED jobject holder, jint critical) {
6927 CHECK_ERROR_QUEUE_ON_RETURN;
6928 // NOLINTNEXTLINE(runtime/int)
6929 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
6930 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6931 critical);
6932 }
6933
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)6934 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6935 CONSCRYPT_UNUSED jobject holder,
6936 jint critical) {
6937 CHECK_ERROR_QUEUE_ON_RETURN;
6938 // NOLINTNEXTLINE(runtime/int)
6939 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
6940 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
6941 env, x509CrlRef, critical);
6942 }
6943
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6944 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
6945 jlong x509RevokedRef, jint critical) {
6946 CHECK_ERROR_QUEUE_ON_RETURN;
6947 // NOLINTNEXTLINE(runtime/int)
6948 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
6949 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6950 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6951 }
6952
6953 /**
6954 * Based on example logging call back from SSL_CTX_set_info_callback man page
6955 */
info_callback_LOG(const SSL * s,int where,int ret)6956 static void info_callback_LOG(const SSL* s, int where, int ret) {
6957 int w = where & ~SSL_ST_MASK;
6958 const char* str;
6959 if (w & SSL_ST_CONNECT) {
6960 str = "SSL_connect";
6961 } else if (w & SSL_ST_ACCEPT) {
6962 str = "SSL_accept";
6963 } else {
6964 str = "undefined";
6965 }
6966
6967 if (where & SSL_CB_LOOP) {
6968 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6969 } else if (where & SSL_CB_ALERT) {
6970 str = (where & SSL_CB_READ) ? "read" : "write";
6971 JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
6972 SSL_alert_desc_string_long(ret));
6973 } else if (where & SSL_CB_EXIT) {
6974 if (ret == 0) {
6975 JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
6976 SSL_state_string_long(s));
6977 } else if (ret < 0) {
6978 JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
6979 SSL_state_string_long(s));
6980 } else if (ret == 1) {
6981 JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
6982 SSL_state_string_long(s));
6983 } else {
6984 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
6985 SSL_state_string_long(s));
6986 }
6987 } else if (where & SSL_CB_HANDSHAKE_START) {
6988 JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
6989 SSL_state_string_long(s));
6990 } else if (where & SSL_CB_HANDSHAKE_DONE) {
6991 JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
6992 SSL_state_string_long(s));
6993 } else {
6994 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
6995 SSL_state_string_long(s));
6996 }
6997 }
6998
6999 #ifdef _WIN32
7000
7001 /**
7002 * Dark magic helper function that checks, for a given SSL session, whether it
7003 * can SSL_read() or SSL_write() without blocking. Takes into account any
7004 * concurrent attempts to close the SSLSocket from the Java side. This is
7005 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7006 * while thread #2 is sitting in a blocking read or write. The type argument
7007 * specifies whether we are waiting for readability or writability. It expects
7008 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7009 * only need to wait in case one of these problems occurs.
7010 *
7011 * @param env
7012 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7013 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
7014 * @param appData The application data structure with mutex info etc.
7015 * @param timeout_millis The timeout value for select call, with the special value
7016 * 0 meaning no timeout at all (wait indefinitely). Note: This is
7017 * the Java semantics of the timeout value, not the usual
7018 * select() semantics.
7019 * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
7020 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7021 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7022 int timeout_millis) {
7023 int result = -1;
7024
7025 NetFd fd(env, fdObject);
7026 do {
7027 if (fd.isClosed()) {
7028 result = THROWN_EXCEPTION;
7029 break;
7030 }
7031
7032 WSAEVENT events[2];
7033 events[0] = appData->interruptEvent;
7034 events[1] = WSACreateEvent();
7035 if (events[1] == WSA_INVALID_EVENT) {
7036 JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
7037 break;
7038 }
7039
7040 if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
7041 FD_CLOSE) == SOCKET_ERROR) {
7042 JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
7043 break;
7044 }
7045
7046 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7047 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7048 timeout_millis);
7049
7050 int rc = WSAWaitForMultipleEvents(
7051 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
7052 if (rc == WSA_WAIT_FAILED) {
7053 JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
7054 result = -1;
7055 } else if (rc == WSA_WAIT_TIMEOUT) {
7056 result = 0;
7057 } else {
7058 result = 1;
7059 }
7060 WSACloseEvent(events[1]);
7061 } while (0);
7062
7063 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
7064 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
7065 result);
7066
7067 std::lock_guard<std::mutex> appDataLock(appData->mutex);
7068 appData->waitingThreads--;
7069
7070 return result;
7071 }
7072
7073 #else // !defined(_WIN32)
7074
7075 /**
7076 * Dark magic helper function that checks, for a given SSL session, whether it
7077 * can SSL_read() or SSL_write() without blocking. Takes into account any
7078 * concurrent attempts to close the SSLSocket from the Java side. This is
7079 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7080 * while thread #2 is sitting in a blocking read or write. The type argument
7081 * specifies whether we are waiting for readability or writability. It expects
7082 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7083 * only need to wait in case one of these problems occurs.
7084 *
7085 * @param env
7086 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7087 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
7088 * @param appData The application data structure with mutex info etc.
7089 * @param timeout_millis The timeout value for poll call, with the special value
7090 * 0 meaning no timeout at all (wait indefinitely). Note: This is
7091 * the Java semantics of the timeout value, not the usual
7092 * poll() semantics.
7093 * @return The result of the inner poll() call,
7094 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
7095 * additional errors
7096 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7097 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7098 int timeout_millis) {
7099 // This loop is an expanded version of the NET_FAILURE_RETRY
7100 // macro. It cannot simply be used in this case because poll
7101 // cannot be restarted without recreating the pollfd structure.
7102 int result;
7103 struct pollfd fds[2];
7104 do {
7105 NetFd fd(env, fdObject);
7106 if (fd.isClosed()) {
7107 result = THROWN_EXCEPTION;
7108 break;
7109 }
7110 int intFd = fd.get();
7111 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7112 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
7113
7114 memset(&fds, 0, sizeof(fds));
7115 fds[0].fd = intFd;
7116 if (type == SSL_ERROR_WANT_READ) {
7117 fds[0].events = POLLIN | POLLPRI;
7118 } else {
7119 fds[0].events = POLLOUT | POLLPRI;
7120 }
7121
7122 fds[1].fd = appData->fdsEmergency[0];
7123 fds[1].events = POLLIN | POLLPRI;
7124
7125 // Converting from Java semantics to Posix semantics.
7126 if (timeout_millis <= 0) {
7127 timeout_millis = -1;
7128 }
7129
7130 CompatibilityCloseMonitor monitor(intFd);
7131
7132 result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
7133 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
7134 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7135 timeout_millis, result);
7136 if (result == -1) {
7137 if (fd.isClosed()) {
7138 result = THROWN_EXCEPTION;
7139 break;
7140 }
7141 if (errno != EINTR) {
7142 break;
7143 }
7144 }
7145 } while (result == -1);
7146
7147 std::lock_guard<std::mutex> appDataLock(appData->mutex);
7148
7149 if (result > 0) {
7150 // We have been woken up by a token in the emergency pipe. We
7151 // can't be sure the token is still in the pipe at this point
7152 // because it could have already been read by the thread that
7153 // originally wrote it if it entered sslSelect and acquired
7154 // the mutex before we did. Thus we cannot safely read from
7155 // the pipe in a blocking way (so we make the pipe
7156 // non-blocking at creation).
7157 if (fds[1].revents & POLLIN) {
7158 char token;
7159 do {
7160 (void)read(appData->fdsEmergency[0], &token, 1);
7161 } while (errno == EINTR);
7162 }
7163 }
7164
7165 // Tell the world that there is now one thread less waiting for the
7166 // underlying network.
7167 appData->waitingThreads--;
7168
7169 return result;
7170 }
7171 #endif // !defined(_WIN32)
7172
7173 /**
7174 * Helper function that wakes up a thread blocked in select(), in case there is
7175 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
7176 * before closing the connection.
7177 *
7178 * @param data The application data structure with mutex info etc.
7179 */
sslNotify(AppData * appData)7180 static void sslNotify(AppData* appData) {
7181 #ifdef _WIN32
7182 SetEvent(appData->interruptEvent);
7183 #else
7184 // Write a byte to the emergency pipe, so a concurrent select() can return.
7185 // Note we have to restore the errno of the original system call, since the
7186 // caller relies on it for generating error messages.
7187 int errnoBackup = errno;
7188 char token = '*';
7189 do {
7190 errno = 0;
7191 (void)write(appData->fdsEmergency[1], &token, 1);
7192 } while (errno == EINTR);
7193 errno = errnoBackup;
7194 #endif
7195 }
7196
toAppData(const SSL * ssl)7197 static AppData* toAppData(const SSL* ssl) {
7198 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
7199 }
7200
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)7201 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
7202 JNI_TRACE("ssl=%p cert_verify_callback", ssl);
7203
7204 AppData* appData = toAppData(ssl);
7205 JNIEnv* env = appData->env;
7206 if (env == nullptr) {
7207 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
7208 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
7209 return ssl_verify_invalid;
7210 }
7211
7212 // Create the byte[][] array that holds all the certs
7213 ScopedLocalRef<jobjectArray> array(
7214 env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
7215 if (array.get() == nullptr) {
7216 return ssl_verify_invalid;
7217 }
7218
7219 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7220 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
7221
7222 const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
7223 const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
7224
7225 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
7226 authMethod);
7227 ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
7228 env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
7229
7230 ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
7231 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
7232 return result;
7233 }
7234
7235 /**
7236 * Call back to watch for handshake to be completed. This is necessary for
7237 * False Start support, since SSL_do_handshake returns before the handshake is
7238 * completed in this case.
7239 */
info_callback(const SSL * ssl,int type,int value)7240 static void info_callback(const SSL* ssl, int type, int value) {
7241 JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
7242 if (conscrypt::trace::kWithJniTrace) {
7243 info_callback_LOG(ssl, type, value);
7244 }
7245 if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
7246 JNI_TRACE("ssl=%p info_callback ignored", ssl);
7247 return;
7248 }
7249
7250 AppData* appData = toAppData(ssl);
7251 JNIEnv* env = appData->env;
7252 if (env == nullptr) {
7253 CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
7254 JNI_TRACE("ssl=%p info_callback env error", ssl);
7255 return;
7256 }
7257 if (env->ExceptionCheck()) {
7258 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
7259 return;
7260 }
7261
7262 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7263
7264 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
7265 env->CallVoidMethod(sslHandshakeCallbacks,
7266 conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
7267
7268 if (env->ExceptionCheck()) {
7269 JNI_TRACE("ssl=%p info_callback exception", ssl);
7270 }
7271 JNI_TRACE("ssl=%p info_callback completed", ssl);
7272 }
7273
7274 /**
7275 * Call back to ask for a certificate. There are three possible exit codes:
7276 *
7277 * 1 is success.
7278 * 0 is error.
7279 * -1 is to pause the handshake to continue from the same place later.
7280 */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)7281 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
7282 JNI_TRACE("ssl=%p cert_cb", ssl);
7283
7284 // cert_cb is called for both clients and servers, but we are only
7285 // interested in client certificates.
7286 if (SSL_is_server(ssl)) {
7287 JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
7288 return 1;
7289 }
7290
7291 AppData* appData = toAppData(ssl);
7292 JNIEnv* env = appData->env;
7293 if (env == nullptr) {
7294 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
7295 JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
7296 return 0;
7297 }
7298 if (env->ExceptionCheck()) {
7299 JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
7300 return 0;
7301 }
7302 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7303
7304 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
7305
7306 // Call Java callback which can reconfigure the client certificate.
7307 const uint8_t* ctype = nullptr;
7308 size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
7309 const uint16_t* sigalgs = nullptr;
7310 size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
7311 ScopedLocalRef<jobjectArray> issuers(
7312 env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
7313 if (issuers.get() == nullptr) {
7314 return 0;
7315 }
7316
7317 if (conscrypt::trace::kWithJniTrace) {
7318 for (size_t i = 0; i < ctype_num; i++) {
7319 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
7320 }
7321 for (size_t i = 0; i < sigalgs_num; i++) {
7322 JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
7323 }
7324 }
7325
7326 jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
7327 if (keyTypes == nullptr) {
7328 JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
7329 return 0;
7330 }
7331 env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
7332 reinterpret_cast<const jbyte*>(ctype));
7333
7334 jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
7335 if (signatureAlgs == nullptr) {
7336 JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
7337 return 0;
7338 }
7339 {
7340 ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
7341 for (size_t i = 0; i < sigalgs_num; i++) {
7342 sigAlgsRW[i] = sigalgs[i];
7343 }
7344 }
7345
7346 JNI_TRACE(
7347 "ssl=%p clientCertificateRequested calling clientCertificateRequested "
7348 "keyTypes=%p signatureAlgs=%p issuers=%p",
7349 ssl, keyTypes, signatureAlgs, issuers.get());
7350 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
7351
7352 if (env->ExceptionCheck()) {
7353 JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
7354 return 0;
7355 }
7356
7357 JNI_TRACE("ssl=%p cert_cb => 1", ssl);
7358 return 1;
7359 }
7360
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)7361 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
7362 SSL* ssl = client_hello->ssl;
7363 JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
7364
7365 AppData* appData = toAppData(ssl);
7366 JNIEnv* env = appData->env;
7367 if (env == nullptr) {
7368 CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
7369 JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
7370 return ssl_select_cert_error;
7371 }
7372 if (env->ExceptionCheck()) {
7373 JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
7374 return ssl_select_cert_error;
7375 }
7376
7377 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7378 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
7379
7380 JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
7381 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
7382
7383 if (env->ExceptionCheck()) {
7384 JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
7385 return ssl_select_cert_error;
7386 }
7387 JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
7388 return ssl_select_cert_success;
7389 }
7390
7391 /**
7392 * Pre-Shared Key (PSK) client callback.
7393 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)7394 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
7395 unsigned int max_identity_len, unsigned char* psk,
7396 unsigned int max_psk_len) {
7397 JNI_TRACE("ssl=%p psk_client_callback", ssl);
7398
7399 AppData* appData = toAppData(ssl);
7400 JNIEnv* env = appData->env;
7401 if (env == nullptr) {
7402 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
7403 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
7404 return 0;
7405 }
7406 if (env->ExceptionCheck()) {
7407 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
7408 return 0;
7409 }
7410
7411 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7412 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
7413 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
7414 ScopedLocalRef<jstring> identityHintJava(env,
7415 (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
7416 ScopedLocalRef<jbyteArray> identityJava(
7417 env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
7418 if (identityJava.get() == nullptr) {
7419 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
7420 return 0;
7421 }
7422 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7423 if (keyJava.get() == nullptr) {
7424 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
7425 return 0;
7426 }
7427 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7428 identityJava.get(), keyJava.get());
7429 if (env->ExceptionCheck()) {
7430 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
7431 return 0;
7432 }
7433 if (keyLen <= 0) {
7434 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
7435 return 0;
7436 } else if ((unsigned int)keyLen > max_psk_len) {
7437 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
7438 return 0;
7439 }
7440 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7441 if (keyJavaRo.get() == nullptr) {
7442 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7443 return 0;
7444 }
7445 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7446
7447 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7448 if (identityJavaRo.get() == nullptr) {
7449 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7450 return 0;
7451 }
7452 memcpy(identity, identityJavaRo.get(), max_identity_len);
7453
7454 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7455 return static_cast<unsigned int>(keyLen);
7456 }
7457
7458 /**
7459 * Pre-Shared Key (PSK) server callback.
7460 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)7461 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
7462 unsigned int max_psk_len) {
7463 JNI_TRACE("ssl=%p psk_server_callback", ssl);
7464
7465 AppData* appData = toAppData(ssl);
7466 JNIEnv* env = appData->env;
7467 if (env == nullptr) {
7468 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
7469 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7470 return 0;
7471 }
7472 if (env->ExceptionCheck()) {
7473 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7474 return 0;
7475 }
7476
7477 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7478 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
7479 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7480 const char* identityHint = SSL_get_psk_identity_hint(ssl);
7481 ScopedLocalRef<jstring> identityHintJava(
7482 env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
7483 ScopedLocalRef<jstring> identityJava(
7484 env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
7485 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7486 if (keyJava.get() == nullptr) {
7487 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7488 return 0;
7489 }
7490 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7491 identityJava.get(), keyJava.get());
7492 if (env->ExceptionCheck()) {
7493 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7494 return 0;
7495 }
7496 if (keyLen <= 0) {
7497 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7498 return 0;
7499 } else if ((unsigned int)keyLen > max_psk_len) {
7500 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7501 return 0;
7502 }
7503 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7504 if (keyJavaRo.get() == nullptr) {
7505 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7506 return 0;
7507 }
7508 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7509
7510 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7511 return static_cast<unsigned int>(keyLen);
7512 }
7513
new_session_callback(SSL * ssl,SSL_SESSION * session)7514 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
7515 JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
7516
7517 AppData* appData = toAppData(ssl);
7518 JNIEnv* env = appData->env;
7519 if (env == nullptr) {
7520 CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
7521 JNI_TRACE("ssl=%p new_session_callback env error", ssl);
7522 return 0;
7523 }
7524 if (env->ExceptionCheck()) {
7525 JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
7526 return 0;
7527 }
7528
7529 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7530 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
7531 JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
7532 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
7533 if (env->ExceptionCheck()) {
7534 JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
7535 env->ExceptionClear();
7536 }
7537 JNI_TRACE("ssl=%p new_session_callback completed", ssl);
7538
7539 // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
7540 // the reference count.
7541 return 0;
7542 }
7543
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)7544 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
7545 int* out_copy) {
7546 JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
7547
7548 // Always set to out_copy to zero. The Java callback will be responsible for incrementing
7549 // the reference count (and any required synchronization).
7550 *out_copy = 0;
7551
7552 AppData* appData = toAppData(ssl);
7553 JNIEnv* env = appData->env;
7554 if (env == nullptr) {
7555 CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7556 JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7557 return 0;
7558 }
7559 if (env->ExceptionCheck()) {
7560 JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7561 return 0;
7562 }
7563
7564 // Copy the ID to a byte[].
7565 jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7566 if (id_array == nullptr) {
7567 JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7568 return 0;
7569 }
7570 env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7571 reinterpret_cast<const jbyte*>(id));
7572
7573 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7574 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7575 JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7576 jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7577 if (env->ExceptionCheck()) {
7578 JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7579 env->ExceptionClear();
7580 }
7581 SSL_SESSION* ssl_session_ptr =
7582 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7583 JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7584 return ssl_session_ptr;
7585 }
7586
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7587 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7588 CHECK_ERROR_QUEUE_ON_RETURN;
7589 int ret = 0;
7590 ret = EVP_has_aes_hardware();
7591 JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7592 return ret;
7593 }
7594
debug_print_session_key(const SSL * ssl,const char * line)7595 static void debug_print_session_key(const SSL* ssl, const char* line) {
7596 JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7597 }
7598
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7599 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7600 static constexpr size_t kDataWidth = 16;
7601
7602 struct timeval tv;
7603 if (gettimeofday(&tv, NULL)) {
7604 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7605 "debug_print_packet_data: could not get time of day");
7606 return;
7607 }
7608
7609 // Packet preamble for text2pcap
7610 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7611 static_cast<long>(tv.tv_sec),
7612 static_cast<long>(tv.tv_usec)); // NOLINT(runtime/int)
7613
7614 char out[kDataWidth * 3 + 1];
7615 for (size_t i = 0; i < len; i += kDataWidth) {
7616 size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7617
7618 for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7619 int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7620 if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7621 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7622 "debug_print_packet_data failed to output %d", ret);
7623 return;
7624 }
7625 }
7626
7627 // Print out packet data in format understood by text2pcap
7628 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7629 }
7630
7631 // Conclude the packet data
7632 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7633 }
7634
7635 /*
7636 * public static native int SSL_CTX_new();
7637 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7638 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7639 CHECK_ERROR_QUEUE_ON_RETURN;
7640 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7641 if (sslCtx.get() == nullptr) {
7642 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7643 return 0;
7644 }
7645 SSL_CTX_set_options(
7646 sslCtx.get(),
7647 SSL_OP_ALL
7648 // We also disable session tickets for better compatibility b/2682876
7649 | SSL_OP_NO_TICKET
7650 // We also disable compression for better compatibility b/2710492 b/2710497
7651 | SSL_OP_NO_COMPRESSION
7652 // Generate a fresh ECDH keypair for each key exchange.
7653 | SSL_OP_SINGLE_ECDH_USE);
7654 SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7655 SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7656
7657 uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7658 /*
7659 * Turn on "partial write" mode. This means that SSL_write() will
7660 * behave like Posix write() and possibly return after only
7661 * writing a partial buffer. Note: The alternative, perhaps
7662 * surprisingly, is not that SSL_write() always does full writes
7663 * but that it will force you to retry write calls having
7664 * preserved the full state of the original call. (This is icky
7665 * and undesirable.)
7666 */
7667 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7668
7669 // Reuse empty buffers within the SSL_CTX to save memory
7670 mode |= SSL_MODE_RELEASE_BUFFERS;
7671
7672 // Enable False Start.
7673 mode |= SSL_MODE_ENABLE_FALSE_START;
7674
7675 // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7676 // between
7677 // calls to wrap(...).
7678 // See https://github.com/netty/netty-tcnative/issues/100
7679 mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7680
7681 SSL_CTX_set_mode(sslCtx.get(), mode);
7682
7683 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7684 SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7685 SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7686 if (conscrypt::trace::kWithJniTraceKeys) {
7687 SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7688 }
7689
7690 // By default BoringSSL will cache in server mode, but we want to get
7691 // notified of new sessions being created in client mode. We set
7692 // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7693 // ignore it in server mode in favor of the internal cache.
7694 SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7695 SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7696 SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7697
7698 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7699 return (jlong)sslCtx.release();
7700 }
7701
7702 /**
7703 * public static native void SSL_CTX_free(long ssl_ctx)
7704 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7705 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7706 CONSCRYPT_UNUSED jobject holder) {
7707 CHECK_ERROR_QUEUE_ON_RETURN;
7708 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7709 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7710 if (ssl_ctx == nullptr) {
7711 return;
7712 }
7713 SSL_CTX_free(ssl_ctx);
7714 }
7715
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7716 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7717 CONSCRYPT_UNUSED jobject holder,
7718 jbyteArray sid_ctx) {
7719 CHECK_ERROR_QUEUE_ON_RETURN;
7720 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7721 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7722 sid_ctx);
7723 if (ssl_ctx == nullptr) {
7724 return;
7725 }
7726
7727 ScopedByteArrayRO buf(env, sid_ctx);
7728 if (buf.get() == nullptr) {
7729 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7730 ssl_ctx);
7731 return;
7732 }
7733
7734 unsigned int length = static_cast<unsigned int>(buf.size());
7735 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7736 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7737 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7738 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7739 return;
7740 }
7741 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7742 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7743 if (result == 0) {
7744 conscrypt::jniutil::throwExceptionFromBoringSSLError(
7745 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7746 return;
7747 }
7748 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7749 }
7750
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7751 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7752 CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7753 CHECK_ERROR_QUEUE_ON_RETURN;
7754 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7755 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7756 if (ssl_ctx == nullptr) {
7757 return 0L;
7758 }
7759
7760 return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7761 }
7762
7763 /**
7764 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7765 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7766 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7767 CONSCRYPT_UNUSED jobject holder) {
7768 CHECK_ERROR_QUEUE_ON_RETURN;
7769 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7770 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7771 if (ssl_ctx == nullptr) {
7772 return 0;
7773 }
7774 bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7775 if (ssl.get() == nullptr) {
7776 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7777 "Unable to create SSL structure");
7778 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7779 return 0;
7780 }
7781
7782 /*
7783 * Create our special application data.
7784 */
7785 AppData* appData = AppData::create();
7786 if (appData == nullptr) {
7787 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7788 ERR_clear_error();
7789 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7790 return 0;
7791 }
7792 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7793
7794 SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7795
7796 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7797 return (jlong)ssl.release();
7798 }
7799
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7800 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7801 CONSCRYPT_UNUSED jobject ssl_holder) {
7802 CHECK_ERROR_QUEUE_ON_RETURN;
7803 SSL* ssl = to_SSL(env, ssl_address, true);
7804 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7805 if (ssl == nullptr) {
7806 return;
7807 }
7808
7809 // NOLINTNEXTLINE(runtime/int)
7810 long ret = SSL_enable_tls_channel_id(ssl);
7811 if (ret != 1L) {
7812 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7813 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7814 "Error enabling Channel ID");
7815 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7816 return;
7817 }
7818 }
7819
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7820 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7821 CONSCRYPT_UNUSED jobject ssl_holder) {
7822 CHECK_ERROR_QUEUE_ON_RETURN;
7823 SSL* ssl = to_SSL(env, ssl_address, true);
7824 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7825 if (ssl == nullptr) {
7826 return nullptr;
7827 }
7828
7829 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7830 // as a constant anywhere.
7831 jbyteArray javaBytes = env->NewByteArray(64);
7832 ScopedByteArrayRW bytes(env, javaBytes);
7833 if (bytes.get() == nullptr) {
7834 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
7835 return nullptr;
7836 }
7837
7838 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7839 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7840 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7841 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7842 size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7843 if (ret == 0) {
7844 // Channel ID either not set or did not verify
7845 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7846 return nullptr;
7847 } else if (ret != 64) {
7848 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7849 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7850 "Error getting Channel ID");
7851 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
7852 return nullptr;
7853 }
7854
7855 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7856 return javaBytes;
7857 }
7858
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)7859 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7860 CONSCRYPT_UNUSED jobject ssl_holder,
7861 jobject pkeyRef) {
7862 CHECK_ERROR_QUEUE_ON_RETURN;
7863 SSL* ssl = to_SSL(env, ssl_address, true);
7864 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
7865 if (ssl == nullptr) {
7866 return;
7867 }
7868
7869 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7870 if (pkey == nullptr) {
7871 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7872 return;
7873 }
7874
7875 // NOLINTNEXTLINE(runtime/int)
7876 long ret = SSL_set1_tls_channel_id(ssl, pkey);
7877
7878 if (ret != 1L) {
7879 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7880 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
7881 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7882 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7883 return;
7884 }
7885
7886 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7887 }
7888
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)7889 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
7890 CONSCRYPT_UNUSED jobject ssl_holder,
7891 jobjectArray encodedCertificatesJava,
7892 jobject pkeyRef) {
7893 CHECK_ERROR_QUEUE_ON_RETURN;
7894 SSL* ssl = to_SSL(env, ssl_address, true);
7895 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
7896 encodedCertificatesJava, pkeyRef);
7897 if (ssl == nullptr) {
7898 return;
7899 }
7900 if (encodedCertificatesJava == nullptr) {
7901 conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
7902 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
7903 return;
7904 }
7905 size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
7906 if (numCerts == 0) {
7907 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7908 "certificates.length == 0");
7909 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
7910 return;
7911 }
7912 if (pkeyRef == nullptr) {
7913 conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
7914 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
7915 return;
7916 }
7917
7918 // Get the private key.
7919 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
7920 if (pkey == nullptr) {
7921 conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
7922 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
7923 return;
7924 }
7925
7926 // Copy the certificates.
7927 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
7928 std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
7929 for (size_t i = 0; i < numCerts; ++i) {
7930 ScopedLocalRef<jbyteArray> certArray(
7931 env, reinterpret_cast<jbyteArray>(
7932 env->GetObjectArrayElement(encodedCertificatesJava, i)));
7933 certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
7934 if (!certBufferRefs[i]) {
7935 return;
7936 }
7937 certBuffers[i] = certBufferRefs[i].get();
7938 }
7939
7940 if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
7941 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7942 "Error configuring certificate");
7943 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
7944 return;
7945 }
7946 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
7947 }
7948
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)7949 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
7950 CONSCRYPT_UNUSED jobject ssl_holder,
7951 jobjectArray principals) {
7952 CHECK_ERROR_QUEUE_ON_RETURN;
7953 SSL* ssl = to_SSL(env, ssl_address, true);
7954 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7955 if (ssl == nullptr) {
7956 return;
7957 }
7958
7959 if (principals == nullptr) {
7960 conscrypt::jniutil::throwNullPointerException(env, "principals == null");
7961 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7962 return;
7963 }
7964
7965 int length = env->GetArrayLength(principals);
7966 if (length == 0) {
7967 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7968 "principals.length == 0");
7969 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7970 return;
7971 }
7972
7973 bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
7974 if (principalsStack.get() == nullptr) {
7975 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
7976 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7977 return;
7978 }
7979 for (int i = 0; i < length; i++) {
7980 ScopedLocalRef<jbyteArray> principal(
7981 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7982 bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
7983 if (!buf) {
7984 return;
7985 }
7986 if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
7987 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
7988 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7989 return;
7990 }
7991 OWNERSHIP_TRANSFERRED(buf);
7992 }
7993
7994 SSL_set0_client_CAs(ssl, principalsStack.release());
7995 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7996 }
7997
7998 /**
7999 * public static native long SSL_set_mode(long ssl, long mode);
8000 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)8001 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
8002 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
8003 CHECK_ERROR_QUEUE_ON_RETURN;
8004 SSL* ssl = to_SSL(env, ssl_address, true);
8005 // NOLINTNEXTLINE(runtime/int)
8006 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
8007 if (ssl == nullptr) {
8008 return 0;
8009 }
8010 jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
8011 // NOLINTNEXTLINE(runtime/int)
8012 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
8013 return result;
8014 }
8015
8016 /**
8017 * public static native long SSL_set_options(long ssl, long options);
8018 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8019 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
8020 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8021 CHECK_ERROR_QUEUE_ON_RETURN;
8022 SSL* ssl = to_SSL(env, ssl_address, true);
8023 // NOLINTNEXTLINE(runtime/int)
8024 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
8025 if (ssl == nullptr) {
8026 return 0;
8027 }
8028 jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
8029 // NOLINTNEXTLINE(runtime/int)
8030 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
8031 return result;
8032 }
8033
8034 /**
8035 * public static native long SSL_clear_options(long ssl, long options);
8036 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8037 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
8038 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8039 CHECK_ERROR_QUEUE_ON_RETURN;
8040 SSL* ssl = to_SSL(env, ssl_address, true);
8041 // NOLINTNEXTLINE(runtime/int)
8042 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
8043 if (ssl == nullptr) {
8044 return 0;
8045 }
8046 jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
8047 // NOLINTNEXTLINE(runtime/int)
8048 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
8049 return result;
8050 }
8051
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)8052 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
8053 CONSCRYPT_UNUSED jobject ssl_holder,
8054 jint min_version, jint max_version) {
8055 CHECK_ERROR_QUEUE_ON_RETURN;
8056 SSL* ssl = to_SSL(env, ssl_address, true);
8057 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
8058 max_version);
8059 if (ssl == nullptr) {
8060 return 0;
8061 }
8062 int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
8063 int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
8064 // Return failure if either call failed.
8065 int result = 1;
8066 if (!min_result || !max_result) {
8067 result = 0;
8068 // The only possible error is an invalid version, so we don't need the details.
8069 ERR_clear_error();
8070 }
8071 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
8072 min_result, max_result, result);
8073 return result;
8074 }
8075
8076 /**
8077 * public static native void SSL_enable_signed_cert_timestamps(long ssl);
8078 */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8079 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
8080 CONSCRYPT_UNUSED jobject ssl_holder) {
8081 CHECK_ERROR_QUEUE_ON_RETURN;
8082 SSL* ssl = to_SSL(env, ssl_address, true);
8083 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
8084 if (ssl == nullptr) {
8085 return;
8086 }
8087
8088 SSL_enable_signed_cert_timestamps(ssl);
8089 }
8090
8091 /**
8092 * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
8093 */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8094 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
8095 JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
8096 CHECK_ERROR_QUEUE_ON_RETURN;
8097 SSL* ssl = to_SSL(env, ssl_address, true);
8098 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
8099 if (ssl == nullptr) {
8100 return nullptr;
8101 }
8102
8103 const uint8_t* data;
8104 size_t data_len;
8105 SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
8106
8107 if (data_len == 0) {
8108 JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
8109 return nullptr;
8110 }
8111
8112 jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
8113 if (result != nullptr) {
8114 env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
8115 }
8116 return result;
8117 }
8118
8119 /*
8120 * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
8121 */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)8122 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
8123 CONSCRYPT_UNUSED jobject ssl_holder,
8124 jbyteArray list) {
8125 CHECK_ERROR_QUEUE_ON_RETURN;
8126 SSL* ssl = to_SSL(env, ssl_address, true);
8127 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
8128 if (ssl == nullptr) {
8129 return;
8130 }
8131
8132 ScopedByteArrayRO listBytes(env, list);
8133 if (listBytes.get() == nullptr) {
8134 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
8135 return;
8136 }
8137
8138 if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
8139 listBytes.size())) {
8140 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
8141 } else {
8142 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
8143 }
8144 }
8145
8146 /*
8147 * public static native void SSL_enable_ocsp_stapling(long ssl);
8148 */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8149 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
8150 CONSCRYPT_UNUSED jobject ssl_holder) {
8151 CHECK_ERROR_QUEUE_ON_RETURN;
8152 SSL* ssl = to_SSL(env, ssl_address, true);
8153 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
8154 if (ssl == nullptr) {
8155 return;
8156 }
8157
8158 SSL_enable_ocsp_stapling(ssl);
8159 }
8160
8161 /*
8162 * public static native byte[] SSL_get_ocsp_response(long ssl);
8163 */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8164 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8165 CONSCRYPT_UNUSED jobject ssl_holder) {
8166 CHECK_ERROR_QUEUE_ON_RETURN;
8167 SSL* ssl = to_SSL(env, ssl_address, true);
8168 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
8169 if (ssl == nullptr) {
8170 return nullptr;
8171 }
8172
8173 const uint8_t* data;
8174 size_t data_len;
8175 SSL_get0_ocsp_response(ssl, &data, &data_len);
8176
8177 if (data_len == 0) {
8178 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
8179 return nullptr;
8180 }
8181
8182 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8183 if (byteArray.get() == nullptr) {
8184 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
8185 return nullptr;
8186 }
8187
8188 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8189 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
8190 data_len);
8191
8192 return byteArray.release();
8193 }
8194
8195 /*
8196 * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
8197 */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)8198 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8199 CONSCRYPT_UNUSED jobject ssl_holder,
8200 jbyteArray response) {
8201 CHECK_ERROR_QUEUE_ON_RETURN;
8202 SSL* ssl = to_SSL(env, ssl_address, true);
8203 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
8204 if (ssl == nullptr) {
8205 return;
8206 }
8207
8208 ScopedByteArrayRO responseBytes(env, response);
8209 if (responseBytes.get() == nullptr) {
8210 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
8211 return;
8212 }
8213
8214 if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
8215 responseBytes.size())) {
8216 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
8217 } else {
8218 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
8219 }
8220 }
8221
8222 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
8223 // to customize the length of their verify_data (with a default of 12 bytes). We accept
8224 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
8225 // tests and update this value if necessary.
8226 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
8227
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8228 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
8229 CONSCRYPT_UNUSED jobject ssl_holder) {
8230 CHECK_ERROR_QUEUE_ON_RETURN;
8231 SSL* ssl = to_SSL(env, ssl_address, true);
8232 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
8233 if (ssl == nullptr) {
8234 return nullptr;
8235 }
8236
8237 uint8_t data[MAX_TLS_UNIQUE_LENGTH];
8238 size_t data_len;
8239 int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
8240
8241 if (!ret || data_len == 0) {
8242 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
8243 return nullptr;
8244 }
8245
8246 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8247 if (byteArray.get() == nullptr) {
8248 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
8249 return nullptr;
8250 }
8251
8252 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8253 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
8254 data_len);
8255
8256 return byteArray.release();
8257 }
8258
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)8259 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
8260 CONSCRYPT_UNUSED jobject ssl_holder,
8261 jbyteArray label, jbyteArray context,
8262 jint num_bytes) {
8263 CHECK_ERROR_QUEUE_ON_RETURN;
8264 SSL* ssl = to_SSL(env, ssl_address, true);
8265 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
8266 if (ssl == nullptr) {
8267 return nullptr;
8268 }
8269 ScopedByteArrayRO labelBytes(env, label);
8270 if (labelBytes.get() == nullptr) {
8271 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
8272 return nullptr;
8273 }
8274 std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
8275 int ret;
8276 if (context == nullptr) {
8277 ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
8278 reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
8279 nullptr, 0, 0);
8280 } else {
8281 ScopedByteArrayRO contextBytes(env, context);
8282 if (contextBytes.get() == nullptr) {
8283 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
8284 ssl);
8285 return nullptr;
8286 }
8287 ret = SSL_export_keying_material(
8288 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
8289 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
8290 contextBytes.size(), 1);
8291 }
8292 if (!ret) {
8293 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
8294 conscrypt::jniutil::throwSSLExceptionStr);
8295 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
8296 return nullptr;
8297 }
8298 jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
8299 if (result == nullptr) {
8300 conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
8301 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
8302 return nullptr;
8303 }
8304 const jbyte* src = reinterpret_cast<jbyte*>(out.get());
8305 env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
8306 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
8307 return result;
8308 }
8309
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)8310 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
8311 CONSCRYPT_UNUSED jobject ssl_holder,
8312 jstring identityHintJava) {
8313 CHECK_ERROR_QUEUE_ON_RETURN;
8314 SSL* ssl = to_SSL(env, ssl_address, true);
8315 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
8316 identityHintJava);
8317 if (ssl == nullptr) {
8318 return;
8319 }
8320
8321 int ret;
8322 if (identityHintJava == nullptr) {
8323 ret = SSL_use_psk_identity_hint(ssl, nullptr);
8324 } else {
8325 ScopedUtfChars identityHint(env, identityHintJava);
8326 if (identityHint.c_str() == nullptr) {
8327 conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
8328 return;
8329 }
8330 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
8331 }
8332
8333 if (ret != 1) {
8334 int sslErrorCode = SSL_get_error(ssl, ret);
8335 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8336 "Failed to set PSK identity hint");
8337 }
8338 }
8339
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8340 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8341 CONSCRYPT_UNUSED jobject ssl_holder,
8342 jboolean enabled) {
8343 CHECK_ERROR_QUEUE_ON_RETURN;
8344 SSL* ssl = to_SSL(env, ssl_address, true);
8345 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
8346 if (ssl == nullptr) {
8347 return;
8348 }
8349
8350 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
8351 }
8352
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8353 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8354 CONSCRYPT_UNUSED jobject ssl_holder,
8355 jboolean enabled) {
8356 CHECK_ERROR_QUEUE_ON_RETURN;
8357 SSL* ssl = to_SSL(env, ssl_address, true);
8358 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
8359 if (ssl == nullptr) {
8360 return;
8361 }
8362
8363 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
8364 }
8365
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8366 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
8367 CONSCRYPT_UNUSED jobject ssl_holder) {
8368 CHECK_ERROR_QUEUE_ON_RETURN;
8369 SSL* ssl = to_SSL(env, ssl_address, true);
8370 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
8371 if (ssl == nullptr) {
8372 return nullptr;
8373 }
8374
8375 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
8376 size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
8377 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
8378 ScopedLongArrayRW ciphers(env, ciphersArray.get());
8379 for (size_t i = 0; i < count; i++) {
8380 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
8381 }
8382
8383 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
8384 return ciphersArray.release();
8385 }
8386
8387 /**
8388 * Sets the ciphers suites that are enabled in the SSL
8389 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)8390 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
8391 CONSCRYPT_UNUSED jobject ssl_holder,
8392 jobjectArray cipherSuites) {
8393 CHECK_ERROR_QUEUE_ON_RETURN;
8394 SSL* ssl = to_SSL(env, ssl_address, true);
8395 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
8396 if (ssl == nullptr) {
8397 return;
8398 }
8399 if (cipherSuites == nullptr) {
8400 conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
8401 return;
8402 }
8403
8404 int length = env->GetArrayLength(cipherSuites);
8405
8406 /*
8407 * Special case for empty cipher list. This is considered an error by the
8408 * SSL_set_cipher_list API, but Java allows this silly configuration.
8409 * However, the SSL cipher list is still set even when SSL_set_cipher_list
8410 * returns 0 in this case. Just to make sure, we check the resulting cipher
8411 * list to make sure it's zero length.
8412 */
8413 if (length == 0) {
8414 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
8415 SSL_set_cipher_list(ssl, "");
8416 ERR_clear_error();
8417 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
8418 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
8419 conscrypt::jniutil::throwRuntimeException(
8420 env, "SSL_set_cipher_list did not update ciphers!");
8421 ERR_clear_error();
8422 }
8423 return;
8424 }
8425
8426 static const char noSSLv2[] = "!SSLv2";
8427 size_t cipherStringLen = strlen(noSSLv2);
8428
8429 for (int i = 0; i < length; i++) {
8430 ScopedLocalRef<jstring> cipherSuite(
8431 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8432 ScopedUtfChars c(env, cipherSuite.get());
8433 if (c.c_str() == nullptr) {
8434 return;
8435 }
8436
8437 if (cipherStringLen + 1 < cipherStringLen) {
8438 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8439 "Overflow in cipher suite strings");
8440 return;
8441 }
8442 cipherStringLen += 1; /* For the separating colon */
8443
8444 if (cipherStringLen + c.size() < cipherStringLen) {
8445 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8446 "Overflow in cipher suite strings");
8447 return;
8448 }
8449 cipherStringLen += c.size();
8450 }
8451
8452 if (cipherStringLen + 1 < cipherStringLen) {
8453 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8454 "Overflow in cipher suite strings");
8455 return;
8456 }
8457 cipherStringLen += 1; /* For final NUL. */
8458
8459 std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
8460 if (cipherString.get() == nullptr) {
8461 conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
8462 return;
8463 }
8464 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
8465 size_t j = strlen(noSSLv2);
8466
8467 for (int i = 0; i < length; i++) {
8468 ScopedLocalRef<jstring> cipherSuite(
8469 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8470 ScopedUtfChars c(env, cipherSuite.get());
8471
8472 cipherString[j++] = ':';
8473 memcpy(&cipherString[j], c.c_str(), c.size());
8474 j += c.size();
8475 }
8476
8477 cipherString[j++] = 0;
8478 if (j != cipherStringLen) {
8479 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8480 "Internal error");
8481 return;
8482 }
8483
8484 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
8485 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
8486 ERR_clear_error();
8487 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8488 "Illegal cipher suite strings.");
8489 return;
8490 }
8491 }
8492
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8493 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
8494 CONSCRYPT_UNUSED jobject ssl_holder) {
8495 CHECK_ERROR_QUEUE_ON_RETURN;
8496 SSL* ssl = to_SSL(env, ssl_address, true);
8497 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
8498 if (ssl == nullptr) {
8499 return;
8500 }
8501 SSL_set_accept_state(ssl);
8502 }
8503
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8504 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
8505 CONSCRYPT_UNUSED jobject ssl_holder) {
8506 CHECK_ERROR_QUEUE_ON_RETURN;
8507 SSL* ssl = to_SSL(env, ssl_address, true);
8508 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
8509 if (ssl == nullptr) {
8510 return;
8511 }
8512 SSL_set_connect_state(ssl);
8513 }
8514
8515 /**
8516 * Sets certificate expectations, especially for server to request client auth
8517 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)8518 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
8519 CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
8520 CHECK_ERROR_QUEUE_ON_RETURN;
8521 SSL* ssl = to_SSL(env, ssl_address, true);
8522 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
8523 if (ssl == nullptr) {
8524 return;
8525 }
8526 SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
8527 }
8528
8529 /**
8530 * Sets the ciphers suites that are enabled in the SSL
8531 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)8532 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
8533 CONSCRYPT_UNUSED jobject ssl_holder,
8534 jlong ssl_session_address) {
8535 CHECK_ERROR_QUEUE_ON_RETURN;
8536 SSL* ssl = to_SSL(env, ssl_address, true);
8537 if (ssl == nullptr) {
8538 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
8539 return;
8540 }
8541
8542 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
8543 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
8544 if (ssl_session == nullptr) {
8545 return;
8546 }
8547
8548 int ret = SSL_set_session(ssl, ssl_session);
8549 if (ret != 1) {
8550 /*
8551 * Translate the error, and throw if it turns out to be a real
8552 * problem.
8553 */
8554 int sslErrorCode = SSL_get_error(ssl, ret);
8555 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8556 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8557 "SSL session set");
8558 }
8559 }
8560 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8561 ret);
8562 }
8563
8564 /**
8565 * Sets the ciphers suites that are enabled in the SSL
8566 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8567 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8568 CONSCRYPT_UNUSED jobject ssl_holder,
8569 jboolean creation_enabled) {
8570 CHECK_ERROR_QUEUE_ON_RETURN;
8571 SSL* ssl = to_SSL(env, ssl_address, true);
8572 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8573 creation_enabled);
8574 if (ssl == nullptr) {
8575 return;
8576 }
8577
8578 if (creation_enabled) {
8579 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8580 } else {
8581 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8582 }
8583 }
8584
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8585 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8586 CONSCRYPT_UNUSED jobject ssl_holder) {
8587 CHECK_ERROR_QUEUE_ON_RETURN;
8588 SSL* ssl = to_SSL(env, ssl_address, true);
8589 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8590 if (ssl == nullptr) {
8591 return JNI_FALSE;
8592 }
8593
8594 int reused = SSL_session_reused(ssl);
8595 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8596 return static_cast<jboolean>(reused);
8597 }
8598
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8599 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8600 CONSCRYPT_UNUSED jobject ssl_holder) {
8601 CHECK_ERROR_QUEUE_ON_RETURN;
8602 SSL* ssl = to_SSL(env, ssl_address, true);
8603 JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8604 if (ssl == nullptr) {
8605 return;
8606 }
8607
8608 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8609 }
8610
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8611 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8612 CONSCRYPT_UNUSED jobject ssl_holder,
8613 jstring hostname) {
8614 CHECK_ERROR_QUEUE_ON_RETURN;
8615 SSL* ssl = to_SSL(env, ssl_address, true);
8616 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8617 if (ssl == nullptr) {
8618 return;
8619 }
8620
8621 ScopedUtfChars hostnameChars(env, hostname);
8622 if (hostnameChars.c_str() == nullptr) {
8623 return;
8624 }
8625 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8626 hostnameChars.c_str());
8627
8628 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8629 if (ret != 1) {
8630 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8631 "Error setting host name");
8632 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8633 return;
8634 }
8635 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8636 }
8637
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8638 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8639 CONSCRYPT_UNUSED jobject ssl_holder) {
8640 CHECK_ERROR_QUEUE_ON_RETURN;
8641 SSL* ssl = to_SSL(env, ssl_address, true);
8642 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8643 if (ssl == nullptr) {
8644 return nullptr;
8645 }
8646 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8647 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8648 return env->NewStringUTF(servername);
8649 }
8650
8651 /**
8652 * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8653 * which should take precedence.
8654 */
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)8655 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8656 const unsigned char* primary,
8657 const unsigned int primaryLength,
8658 const unsigned char* secondary,
8659 const unsigned int secondaryLength) {
8660 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8661
8662 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8663 secondaryLength);
8664 switch (status) {
8665 case OPENSSL_NPN_NEGOTIATED:
8666 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8667 return SSL_TLSEXT_ERR_OK;
8668 break;
8669 case OPENSSL_NPN_UNSUPPORTED:
8670 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8671 break;
8672 case OPENSSL_NPN_NO_OVERLAP:
8673 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8674 break;
8675 }
8676 return SSL_TLSEXT_ERR_NOACK;
8677 }
8678
8679 /**
8680 * Calls out to an application-provided selector to choose the ALPN protocol.
8681 */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8682 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8683 unsigned char** out,
8684 unsigned char* outLen, const unsigned char* in,
8685 const unsigned int inLen) {
8686 // Copy the input array.
8687 ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8688 if (protocols.get() == nullptr) {
8689 JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8690 return SSL_TLSEXT_ERR_NOACK;
8691 }
8692 env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8693 reinterpret_cast<const jbyte*>(in));
8694
8695 // Invoke the selection method.
8696 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8697 jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8698
8699 if (offset < 0) {
8700 JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8701 return SSL_TLSEXT_ERR_NOACK;
8702 }
8703
8704 // Point the output to the selected protocol.
8705 *outLen = *(in + offset);
8706 *out = const_cast<unsigned char*>(in + offset + 1);
8707
8708 return SSL_TLSEXT_ERR_OK;
8709 }
8710
8711 /**
8712 * Callback for the server to select an ALPN protocol.
8713 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8714 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8715 const unsigned char* in, unsigned int inLen, void*) {
8716 JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8717
8718 AppData* appData = toAppData(ssl);
8719 if (appData == nullptr) {
8720 JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8721 return SSL_TLSEXT_ERR_NOACK;
8722 }
8723 JNIEnv* env = appData->env;
8724 if (env == nullptr) {
8725 CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8726 JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8727 return SSL_TLSEXT_ERR_NOACK;
8728 }
8729
8730 if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8731 !appData->hasApplicationProtocolSelector)) {
8732 if (out != nullptr && outLen != nullptr) {
8733 *out = nullptr;
8734 *outLen = 0;
8735 }
8736 JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8737 return SSL_TLSEXT_ERR_NOACK;
8738 }
8739
8740 if (appData->hasApplicationProtocolSelector) {
8741 return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8742 const_cast<unsigned char**>(out), outLen, in, inLen);
8743 }
8744
8745 return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8746 reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8747 static_cast<unsigned int>(appData->applicationProtocolsLength),
8748 in, inLen);
8749 }
8750
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8751 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8752 CONSCRYPT_UNUSED jobject ssl_holder) {
8753 CHECK_ERROR_QUEUE_ON_RETURN;
8754 SSL* ssl = to_SSL(env, ssl_address, true);
8755 JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8756 if (ssl == nullptr) {
8757 return nullptr;
8758 }
8759 const jbyte* protocol;
8760 unsigned int protocolLength;
8761 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8762 &protocolLength);
8763 if (protocolLength == 0) {
8764 return nullptr;
8765 }
8766 jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8767 if (result != nullptr) {
8768 env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8769 }
8770 return result;
8771 }
8772
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8773 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8774 CONSCRYPT_UNUSED jobject ssl_holder,
8775 jboolean client_mode, jbyteArray protocols) {
8776 CHECK_ERROR_QUEUE_ON_RETURN;
8777 SSL* ssl = to_SSL(env, ssl_address, true);
8778 if (ssl == nullptr) {
8779 return;
8780 }
8781 AppData* appData = toAppData(ssl);
8782 if (appData == nullptr) {
8783 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8784 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8785 return;
8786 }
8787
8788 if (protocols != nullptr) {
8789 if (client_mode) {
8790 ScopedByteArrayRO protosBytes(env, protocols);
8791 if (protosBytes.get() == nullptr) {
8792 JNI_TRACE(
8793 "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8794 "protosBytes == null",
8795 ssl, protocols);
8796 return;
8797 }
8798
8799 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8800 int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8801 if (ret != 0) {
8802 conscrypt::jniutil::throwSSLExceptionStr(env,
8803 "Unable to set ALPN protocols for client");
8804 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8805 return;
8806 }
8807 } else {
8808 // Server mode - configure the ALPN protocol selection callback.
8809 if (!appData->setApplicationProtocols(env, protocols)) {
8810 conscrypt::jniutil::throwSSLExceptionStr(env,
8811 "Unable to set ALPN protocols for server");
8812 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8813 return;
8814 }
8815 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8816 }
8817 }
8818 }
8819
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8820 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8821 CONSCRYPT_UNUSED jobject ssl_holder,
8822 jboolean hasSelector) {
8823 CHECK_ERROR_QUEUE_ON_RETURN;
8824 SSL* ssl = to_SSL(env, ssl_address, true);
8825 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8826 hasSelector);
8827 if (ssl == nullptr) {
8828 return;
8829 }
8830 AppData* appData = toAppData(ssl);
8831 if (appData == nullptr) {
8832 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8833 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
8834 return;
8835 }
8836
8837 appData->hasApplicationProtocolSelector = hasSelector;
8838 if (hasSelector) {
8839 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8840 }
8841 }
8842
8843 /**
8844 * Perform SSL handshake
8845 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)8846 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
8847 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
8848 jobject shc, jint timeout_millis) {
8849 CHECK_ERROR_QUEUE_ON_RETURN;
8850 SSL* ssl = to_SSL(env, ssl_address, true);
8851 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
8852 shc, timeout_millis);
8853 if (ssl == nullptr) {
8854 return;
8855 }
8856 if (fdObject == nullptr) {
8857 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
8858 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
8859 return;
8860 }
8861 if (shc == nullptr) {
8862 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
8863 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
8864 ssl);
8865 return;
8866 }
8867
8868 NetFd fd(env, fdObject);
8869 if (fd.isClosed()) {
8870 // SocketException thrown by NetFd.isClosed
8871 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
8872 return;
8873 }
8874
8875 int ret = SSL_set_fd(ssl, fd.get());
8876 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8877
8878 if (ret != 1) {
8879 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8880 "Error setting the file descriptor");
8881 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
8882 return;
8883 }
8884
8885 /*
8886 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8887 * forever and we can use select() to find out if the socket is ready.
8888 */
8889 if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
8890 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
8891 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
8892 return;
8893 }
8894
8895 AppData* appData = toAppData(ssl);
8896 if (appData == nullptr) {
8897 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8898 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
8899 return;
8900 }
8901
8902 ret = 0;
8903 SslError sslError;
8904 while (appData->aliveAndKicking) {
8905 errno = 0;
8906
8907 if (!appData->setCallbackState(env, shc, fdObject)) {
8908 // SocketException thrown by NetFd.isClosed
8909 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
8910 return;
8911 }
8912 ret = SSL_do_handshake(ssl);
8913 appData->clearCallbackState();
8914 // cert_verify_callback threw exception
8915 if (env->ExceptionCheck()) {
8916 ERR_clear_error();
8917 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
8918 return;
8919 }
8920 // success case
8921 if (ret == 1) {
8922 break;
8923 }
8924 // retry case
8925 if (errno == EINTR) {
8926 continue;
8927 }
8928 // error case
8929 sslError.reset(ssl, ret);
8930 JNI_TRACE(
8931 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
8932 "timeout_millis=%d",
8933 ssl, ret, errno, sslError.get(), timeout_millis);
8934
8935 /*
8936 * If SSL_do_handshake doesn't succeed due to the socket being
8937 * either unreadable or unwritable, we use sslSelect to
8938 * wait for it to become ready. If that doesn't happen
8939 * before the specified timeout or an error occurs, we
8940 * cancel the handshake. Otherwise we try the SSL_connect
8941 * again.
8942 */
8943 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8944 appData->waitingThreads++;
8945 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8946
8947 if (selectResult == THROWN_EXCEPTION) {
8948 // SocketException thrown by NetFd.isClosed
8949 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
8950 return;
8951 }
8952 if (selectResult == -1) {
8953 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8954 env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8955 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8956 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
8957 ssl);
8958 return;
8959 }
8960 if (selectResult == 0) {
8961 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
8962 ERR_clear_error();
8963 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
8964 ssl);
8965 return;
8966 }
8967 } else {
8968 // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
8969 break;
8970 }
8971 }
8972
8973 // clean error. See SSL_do_handshake(3SSL) man page.
8974 if (ret == 0) {
8975 /*
8976 * The other side closed the socket before the handshake could be
8977 * completed, but everything is within the bounds of the TLS protocol.
8978 * We still might want to find out the real reason of the failure.
8979 */
8980 if (sslError.get() == SSL_ERROR_NONE ||
8981 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8982 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8983 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8984 } else {
8985 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8986 env, ssl, sslError.release(), "SSL handshake terminated",
8987 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
8988 }
8989 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
8990 return;
8991 }
8992
8993 // unclean error. See SSL_do_handshake(3SSL) man page.
8994 if (ret < 0) {
8995 /*
8996 * Translate the error and throw exception. We are sure it is an error
8997 * at this point.
8998 */
8999 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9000 env, ssl, sslError.release(), "SSL handshake aborted",
9001 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9002 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9003 return;
9004 }
9005 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
9006 }
9007
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9008 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
9009 CONSCRYPT_UNUSED jobject ssl_holder) {
9010 CHECK_ERROR_QUEUE_ON_RETURN;
9011 SSL* ssl = to_SSL(env, ssl_address, true);
9012 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
9013 if (ssl == nullptr) {
9014 return nullptr;
9015 }
9016 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
9017 if (cipher == nullptr) {
9018 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
9019 return nullptr;
9020 }
9021 const char* name = SSL_CIPHER_standard_name(cipher);
9022 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
9023 return env->NewStringUTF(name);
9024 }
9025
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9026 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
9027 CONSCRYPT_UNUSED jobject ssl_holder) {
9028 CHECK_ERROR_QUEUE_ON_RETURN;
9029 SSL* ssl = to_SSL(env, ssl_address, true);
9030 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
9031 if (ssl == nullptr) {
9032 return nullptr;
9033 }
9034 const char* protocol = SSL_get_version(ssl);
9035 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
9036 return env->NewStringUTF(protocol);
9037 }
9038
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9039 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
9040 CONSCRYPT_UNUSED jobject ssl_holder) {
9041 CHECK_ERROR_QUEUE_ON_RETURN;
9042 SSL* ssl = to_SSL(env, ssl_address, true);
9043 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
9044 if (ssl == nullptr) {
9045 return nullptr;
9046 }
9047
9048 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
9049 if (chain == nullptr) {
9050 return nullptr;
9051 }
9052
9053 ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
9054 if (array.get() == nullptr) {
9055 return nullptr;
9056 }
9057
9058 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
9059 return array.release();
9060 }
9061
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)9062 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
9063 SslError* sslError, int read_timeout_millis) {
9064 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
9065
9066 if (len == 0) {
9067 // Don't bother doing anything in this case.
9068 return 0;
9069 }
9070
9071 BIO* rbio = SSL_get_rbio(ssl);
9072 BIO* wbio = SSL_get_wbio(ssl);
9073
9074 AppData* appData = toAppData(ssl);
9075 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
9076 if (appData == nullptr) {
9077 return THROW_SSLEXCEPTION;
9078 }
9079
9080 while (appData->aliveAndKicking) {
9081 errno = 0;
9082
9083 std::unique_lock<std::mutex> appDataLock(appData->mutex);
9084
9085 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9086 !SSL_renegotiate_pending(ssl)) {
9087 JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
9088 SSL_state_string_long(ssl));
9089 return THROW_SSLEXCEPTION;
9090 }
9091
9092 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9093
9094 if (!appData->setCallbackState(env, shc, fdObject)) {
9095 return THROWN_EXCEPTION;
9096 }
9097 int result = SSL_read(ssl, buf, len);
9098 appData->clearCallbackState();
9099 // callbacks can happen if server requests renegotiation
9100 if (env->ExceptionCheck()) {
9101 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
9102 return THROWN_EXCEPTION;
9103 }
9104 sslError->reset(ssl, result);
9105
9106 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
9107 if (conscrypt::trace::kWithJniTraceData) {
9108 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9109 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9110 size_t n = result - i;
9111 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9112 n = conscrypt::trace::kWithJniTraceDataChunkSize;
9113 }
9114 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9115 }
9116 }
9117
9118 // If we have been successful in moving data around, check whether it
9119 // might make sense to wake up other blocked threads, so they can give
9120 // it a try, too.
9121 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9122 appData->waitingThreads > 0) {
9123 sslNotify(appData);
9124 }
9125
9126 // If we are blocked by the underlying socket, tell the world that
9127 // there will be one more waiting thread now.
9128 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9129 appData->waitingThreads++;
9130 }
9131
9132 appDataLock.unlock();
9133
9134 switch (sslError->get()) {
9135 // Successfully read at least one byte.
9136 case SSL_ERROR_NONE: {
9137 return result;
9138 }
9139
9140 // Read zero bytes. End of stream reached.
9141 case SSL_ERROR_ZERO_RETURN: {
9142 return -1;
9143 }
9144
9145 // Need to wait for availability of underlying layer, then retry.
9146 case SSL_ERROR_WANT_READ:
9147 case SSL_ERROR_WANT_WRITE: {
9148 int selectResult =
9149 sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
9150 if (selectResult == THROWN_EXCEPTION) {
9151 return THROWN_EXCEPTION;
9152 }
9153 if (selectResult == -1) {
9154 return THROW_SSLEXCEPTION;
9155 }
9156 if (selectResult == 0) {
9157 return THROW_SOCKETTIMEOUTEXCEPTION;
9158 }
9159
9160 break;
9161 }
9162
9163 // A problem occurred during a system call, but this is not
9164 // necessarily an error.
9165 case SSL_ERROR_SYSCALL: {
9166 // Connection closed without proper shutdown. Tell caller we
9167 // have reached end-of-stream.
9168 if (result == 0) {
9169 return -1;
9170 }
9171
9172 // System call has been interrupted. Simply retry.
9173 if (errno == EINTR) {
9174 break;
9175 }
9176
9177 // Note that for all other system call errors we fall through
9178 // to the default case, which results in an Exception.
9179 FALLTHROUGH_INTENDED;
9180 }
9181
9182 // Everything else is basically an error.
9183 default: { return THROW_SSLEXCEPTION; }
9184 }
9185 }
9186
9187 return -1;
9188 }
9189
9190 /**
9191 * OpenSSL read function (2): read into buffer at offset n chunks.
9192 * Returns the number of bytes read (success) or value <= 0 (failure).
9193 */
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)9194 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
9195 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9196 jobject shc, jbyteArray b, jint offset, jint len,
9197 jint read_timeout_millis) {
9198 CHECK_ERROR_QUEUE_ON_RETURN;
9199 SSL* ssl = to_SSL(env, ssl_address, true);
9200 JNI_TRACE(
9201 "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
9202 "read_timeout_millis=%d",
9203 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
9204 if (ssl == nullptr) {
9205 return 0;
9206 }
9207 if (fdObject == nullptr) {
9208 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9209 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
9210 return 0;
9211 }
9212 if (shc == nullptr) {
9213 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9214 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
9215 return 0;
9216 }
9217 if (b == nullptr) {
9218 conscrypt::jniutil::throwNullPointerException(env, "b == null");
9219 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
9220 return 0;
9221 }
9222
9223 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9224 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9225 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9226 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
9227 return 0;
9228 }
9229
9230 SslError sslError;
9231 int ret;
9232 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9233 if (len <= 1024) {
9234 // Allocate small buffers on the stack for performance.
9235 jbyte buf[1024];
9236 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
9237 read_timeout_millis);
9238 if (ret > 0) {
9239 // Don't bother applying changes if issues were encountered.
9240 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
9241 }
9242 } else {
9243 // Allocate larger buffers on the heap.
9244 // ARRAY_CHUNK_INVALID above ensures that len >= 0.
9245 jint remaining = len;
9246 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9247 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9248 // TODO(flooey): Use new(std::nothrow).
9249 if (buf.get() == nullptr) {
9250 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9251 return 0;
9252 }
9253 // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
9254 // by the number of internal calls to sslRead() below.
9255 ret = 0;
9256 while (remaining > 0) {
9257 jint temp_ret;
9258 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9259 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
9260 chunk_size, &sslError, read_timeout_millis);
9261 if (temp_ret < 0) {
9262 if (ret > 0) {
9263 // We've already read some bytes; attempt to preserve them if this is an
9264 // "expected" error.
9265 if (temp_ret == -1) {
9266 // EOF
9267 break;
9268 } else if (temp_ret == THROWN_EXCEPTION) {
9269 // FD closed. Subsequent calls to sslRead should reproduce the
9270 // exception.
9271 env->ExceptionClear();
9272 break;
9273 }
9274 }
9275 // An error was encountered. Handle below.
9276 ret = temp_ret;
9277 break;
9278 }
9279 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
9280 if (env->ExceptionCheck()) {
9281 // Error committing changes to JVM.
9282 return -1;
9283 }
9284 // Accumulate bytes read.
9285 ret += temp_ret;
9286 offset += temp_ret;
9287 remaining -= temp_ret;
9288 if (temp_ret < chunk_size) {
9289 // sslRead isn't able to fulfill our request right now.
9290 break;
9291 }
9292 }
9293 }
9294 } else {
9295 ScopedByteArrayRW bytes(env, b);
9296 if (bytes.get() == nullptr) {
9297 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
9298 return 0;
9299 }
9300
9301 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
9302 &sslError, read_timeout_millis);
9303 }
9304
9305 int result;
9306 switch (ret) {
9307 case THROW_SSLEXCEPTION:
9308 // See sslRead() regarding improper failure to handle normal cases.
9309 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9310 "Read error");
9311 result = -1;
9312 break;
9313 case THROW_SOCKETTIMEOUTEXCEPTION:
9314 conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
9315 result = -1;
9316 break;
9317 case THROWN_EXCEPTION:
9318 // SocketException thrown by NetFd.isClosed
9319 // or RuntimeException thrown by callback
9320 result = -1;
9321 break;
9322 default:
9323 result = ret;
9324 break;
9325 }
9326
9327 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
9328 return result;
9329 }
9330
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)9331 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
9332 SslError* sslError, int write_timeout_millis) {
9333 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
9334 write_timeout_millis);
9335
9336 if (len == 0) {
9337 // Don't bother doing anything in this case.
9338 return 0;
9339 }
9340
9341 BIO* rbio = SSL_get_rbio(ssl);
9342 BIO* wbio = SSL_get_wbio(ssl);
9343
9344 AppData* appData = toAppData(ssl);
9345 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
9346 if (appData == nullptr) {
9347 return THROW_SSLEXCEPTION;
9348 }
9349
9350 int count = len;
9351
9352 while (appData->aliveAndKicking && len > 0) {
9353 errno = 0;
9354
9355 std::unique_lock<std::mutex> appDataLock(appData->mutex);
9356
9357 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9358 !SSL_renegotiate_pending(ssl)) {
9359 JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
9360 SSL_state_string_long(ssl));
9361 return THROW_SSLEXCEPTION;
9362 }
9363
9364 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9365
9366 if (!appData->setCallbackState(env, shc, fdObject)) {
9367 return THROWN_EXCEPTION;
9368 }
9369 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
9370 int result = SSL_write(ssl, buf, len);
9371 appData->clearCallbackState();
9372 // callbacks can happen if server requests renegotiation
9373 if (env->ExceptionCheck()) {
9374 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
9375 return THROWN_EXCEPTION;
9376 }
9377 sslError->reset(ssl, result);
9378
9379 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
9380 if (conscrypt::trace::kWithJniTraceData) {
9381 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9382 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9383 size_t n = result - i;
9384 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9385 n = conscrypt::trace::kWithJniTraceDataChunkSize;
9386 }
9387 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9388 }
9389 }
9390
9391 // If we have been successful in moving data around, check whether it
9392 // might make sense to wake up other blocked threads, so they can give
9393 // it a try, too.
9394 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9395 appData->waitingThreads > 0) {
9396 sslNotify(appData);
9397 }
9398
9399 // If we are blocked by the underlying socket, tell the world that
9400 // there will be one more waiting thread now.
9401 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9402 appData->waitingThreads++;
9403 }
9404
9405 appDataLock.unlock();
9406
9407 switch (sslError->get()) {
9408 // Successfully wrote at least one byte.
9409 case SSL_ERROR_NONE: {
9410 buf += result;
9411 len -= result;
9412 break;
9413 }
9414
9415 // Wrote zero bytes. End of stream reached.
9416 case SSL_ERROR_ZERO_RETURN: {
9417 return -1;
9418 }
9419
9420 // Need to wait for availability of underlying layer, then retry.
9421 // The concept of a write timeout doesn't really make sense, and
9422 // it's also not standard Java behavior, so we wait forever here.
9423 case SSL_ERROR_WANT_READ:
9424 case SSL_ERROR_WANT_WRITE: {
9425 int selectResult =
9426 sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
9427 if (selectResult == THROWN_EXCEPTION) {
9428 return THROWN_EXCEPTION;
9429 }
9430 if (selectResult == -1) {
9431 return THROW_SSLEXCEPTION;
9432 }
9433 if (selectResult == 0) {
9434 return THROW_SOCKETTIMEOUTEXCEPTION;
9435 }
9436
9437 break;
9438 }
9439
9440 // A problem occurred during a system call, but this is not
9441 // necessarily an error.
9442 case SSL_ERROR_SYSCALL: {
9443 // Connection closed without proper shutdown. Tell caller we
9444 // have reached end-of-stream.
9445 if (result == 0) {
9446 return -1;
9447 }
9448
9449 // System call has been interrupted. Simply retry.
9450 if (errno == EINTR) {
9451 break;
9452 }
9453
9454 // Note that for all other system call errors we fall through
9455 // to the default case, which results in an Exception.
9456 FALLTHROUGH_INTENDED;
9457 }
9458
9459 // Everything else is basically an error.
9460 default: { return THROW_SSLEXCEPTION; }
9461 }
9462 }
9463 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9464
9465 return count;
9466 }
9467
9468 /**
9469 * OpenSSL write function (2): write into buffer at offset n chunks.
9470 */
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)9471 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
9472 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9473 jobject shc, jbyteArray b, jint offset, jint len,
9474 jint write_timeout_millis) {
9475 CHECK_ERROR_QUEUE_ON_RETURN;
9476 SSL* ssl = to_SSL(env, ssl_address, true);
9477 JNI_TRACE(
9478 "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
9479 "write_timeout_millis=%d",
9480 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9481 if (ssl == nullptr) {
9482 return;
9483 }
9484 if (fdObject == nullptr) {
9485 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9486 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9487 return;
9488 }
9489 if (shc == nullptr) {
9490 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9491 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9492 return;
9493 }
9494 if (b == nullptr) {
9495 conscrypt::jniutil::throwNullPointerException(env, "b == null");
9496 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
9497 return;
9498 }
9499
9500 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9501 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9502 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9503 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
9504 return;
9505 }
9506
9507 SslError sslError;
9508 int ret;
9509 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9510 if (len <= 1024) {
9511 jbyte buf[1024];
9512 env->GetByteArrayRegion(b, offset, len, buf);
9513 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
9514 &sslError, write_timeout_millis);
9515 } else {
9516 // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
9517 jint remaining = len;
9518 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9519 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9520 if (buf.get() == nullptr) {
9521 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9522 return;
9523 }
9524 while (remaining > 0) {
9525 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9526 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
9527 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
9528 chunk_size, &sslError, write_timeout_millis);
9529 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
9530 ret == THROWN_EXCEPTION) {
9531 // Encountered an error. Terminate early and handle below.
9532 break;
9533 }
9534 offset += ret;
9535 remaining -= ret;
9536 }
9537 }
9538 } else {
9539 ScopedByteArrayRO bytes(env, b);
9540 if (bytes.get() == nullptr) {
9541 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9542 return;
9543 }
9544 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9545 len, &sslError, write_timeout_millis);
9546 }
9547
9548 switch (ret) {
9549 case THROW_SSLEXCEPTION:
9550 // See sslWrite() regarding improper failure to handle normal cases.
9551 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9552 "Write error");
9553 break;
9554 case THROW_SOCKETTIMEOUTEXCEPTION:
9555 conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9556 break;
9557 case THROWN_EXCEPTION:
9558 // SocketException thrown by NetFd.isClosed
9559 break;
9560 default:
9561 break;
9562 }
9563 }
9564
9565 /**
9566 * Interrupt any pending I/O before closing the socket.
9567 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9568 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9569 CONSCRYPT_UNUSED jobject ssl_holder) {
9570 CHECK_ERROR_QUEUE_ON_RETURN;
9571 SSL* ssl = to_SSL(env, ssl_address, false);
9572 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9573 if (ssl == nullptr) {
9574 return;
9575 }
9576
9577 /*
9578 * Mark the connection as quasi-dead, then send something to the emergency
9579 * file descriptor, so any blocking select() calls are woken up.
9580 */
9581 AppData* appData = toAppData(ssl);
9582 if (appData != nullptr) {
9583 appData->aliveAndKicking = false;
9584
9585 // At most two threads can be waiting.
9586 sslNotify(appData);
9587 sslNotify(appData);
9588 }
9589 }
9590
9591 /**
9592 * OpenSSL close SSL socket function.
9593 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9594 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9595 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9596 jobject shc) {
9597 CHECK_ERROR_QUEUE_ON_RETURN;
9598 SSL* ssl = to_SSL(env, ssl_address, false);
9599 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9600 if (ssl == nullptr) {
9601 return;
9602 }
9603 if (fdObject == nullptr) {
9604 return;
9605 }
9606 if (shc == nullptr) {
9607 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9608 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9609 return;
9610 }
9611
9612 AppData* appData = toAppData(ssl);
9613 if (appData != nullptr) {
9614 if (!appData->setCallbackState(env, shc, fdObject)) {
9615 // SocketException thrown by NetFd.isClosed
9616 ERR_clear_error();
9617 return;
9618 }
9619
9620 /*
9621 * Try to make socket blocking again. OpenSSL literature recommends this.
9622 */
9623 int fd = SSL_get_fd(ssl);
9624 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9625 #ifndef _WIN32
9626 if (fd != -1) {
9627 conscrypt::netutil::setBlocking(fd, true);
9628 }
9629 #endif
9630
9631 int ret = SSL_shutdown(ssl);
9632 appData->clearCallbackState();
9633 // callbacks can happen if server requests renegotiation
9634 if (env->ExceptionCheck()) {
9635 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9636 return;
9637 }
9638 switch (ret) {
9639 case 0:
9640 /*
9641 * Shutdown was not successful (yet), but there also
9642 * is no error. Since we can't know whether the remote
9643 * server is actually still there, and we don't want to
9644 * get stuck forever in a second SSL_shutdown() call, we
9645 * simply return. This is not security a problem as long
9646 * as we close the underlying socket, which we actually
9647 * do, because that's where we are just coming from.
9648 */
9649 break;
9650 case 1:
9651 /*
9652 * Shutdown was successful. We can safely return. Hooray!
9653 */
9654 break;
9655 default:
9656 /*
9657 * Everything else is a real error condition. We should
9658 * let the Java layer know about this by throwing an
9659 * exception.
9660 */
9661 int sslError = SSL_get_error(ssl, ret);
9662 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9663 "SSL shutdown failed");
9664 break;
9665 }
9666 }
9667
9668 ERR_clear_error();
9669 }
9670
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9671 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9672 CONSCRYPT_UNUSED jobject ssl_holder) {
9673 CHECK_ERROR_QUEUE_ON_RETURN;
9674 const SSL* ssl = to_SSL(env, ssl_address, true);
9675 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9676 if (ssl == nullptr) {
9677 return 0;
9678 }
9679
9680 int status = SSL_get_shutdown(ssl);
9681 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9682 return static_cast<jint>(status);
9683 }
9684
9685 /**
9686 * public static native void SSL_free(long ssl);
9687 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9688 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9689 CONSCRYPT_UNUSED jobject ssl_holder) {
9690 CHECK_ERROR_QUEUE_ON_RETURN;
9691 SSL* ssl = to_SSL(env, ssl_address, true);
9692 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9693 if (ssl == nullptr) {
9694 return;
9695 }
9696
9697 AppData* appData = toAppData(ssl);
9698 SSL_set_app_data(ssl, nullptr);
9699 delete appData;
9700 SSL_free(ssl);
9701 }
9702
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9703 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9704 unsigned int length;
9705 const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9706 JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9707 if (id && length > 0) {
9708 jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9709 if (result != nullptr) {
9710 const jbyte* src = reinterpret_cast<const jbyte*>(id);
9711 env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9712 }
9713 return result;
9714 }
9715 return nullptr;
9716 }
9717
9718 /**
9719 * Gets and returns in a byte array the ID of the actual SSL session.
9720 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9721 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9722 jlong ssl_session_address) {
9723 CHECK_ERROR_QUEUE_ON_RETURN;
9724 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9725 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9726 if (ssl_session == nullptr) {
9727 return nullptr;
9728 }
9729 jbyteArray result = get_session_id(env, ssl_session);
9730 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9731 return result;
9732 }
9733
9734 /**
9735 * Gets and returns in a long integer the creation's time of the
9736 * actual SSL session.
9737 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9738 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9739 CHECK_ERROR_QUEUE_ON_RETURN;
9740 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9741 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9742 if (ssl_session == nullptr) {
9743 return 0;
9744 }
9745 // result must be jlong, not long or *1000 will overflow
9746 jlong result = SSL_SESSION_get_time(ssl_session);
9747 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9748 // NOLINTNEXTLINE(runtime/int)
9749 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9750 (long long)result); // NOLINT(runtime/int)
9751 return result;
9752 }
9753
9754 /**
9755 * Gets and returns in a long integer the creation's time of the
9756 * actual SSL session.
9757 */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9758 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9759 CONSCRYPT_UNUSED jobject ssl_holder) {
9760 CHECK_ERROR_QUEUE_ON_RETURN;
9761 SSL* ssl = to_SSL(env, ssl_address, true);
9762 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9763 if (ssl == nullptr) {
9764 return 0;
9765 }
9766
9767 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9768 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9769 if (ssl_session == nullptr) {
9770 // BoringSSL does not protect against a NULL session.
9771 return 0;
9772 }
9773 // result must be jlong, not long or *1000 will overflow
9774 jlong result = SSL_SESSION_get_time(ssl_session);
9775 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9776 // NOLINTNEXTLINE(runtime/int)
9777 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9778 return result;
9779 }
9780
9781 /**
9782 * Sets the timeout on the SSL session.
9783 */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9784 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9785 CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9786 CHECK_ERROR_QUEUE_ON_RETURN;
9787 SSL* ssl = to_SSL(env, ssl_address, true);
9788 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9789 if (ssl == nullptr) {
9790 return 0;
9791 }
9792
9793 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9794 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9795 if (ssl_session == nullptr) {
9796 // BoringSSL does not protect against a NULL session.
9797 return 0;
9798 }
9799
9800 // Convert to seconds
9801 static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9802 uint32_t timeout = static_cast<uint32_t>(
9803 std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9804 return SSL_set_timeout(ssl_session, timeout);
9805 }
9806
9807 /**
9808 * Gets the timeout for the SSL session.
9809 */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9810 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9811 CONSCRYPT_UNUSED jobject ssl_holder) {
9812 CHECK_ERROR_QUEUE_ON_RETURN;
9813 SSL* ssl = to_SSL(env, ssl_address, true);
9814 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9815 if (ssl == nullptr) {
9816 return 0;
9817 }
9818
9819 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9820 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9821 if (ssl_session == nullptr) {
9822 // BoringSSL does not protect against a NULL session.
9823 return 0;
9824 }
9825
9826 jlong result = SSL_get_timeout(ssl_session);
9827 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9828 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9829 (long long)result) // NOLINT(runtime/int);
9830 return result;
9831 }
9832
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)9833 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
9834 jint signatureAlg) {
9835 CHECK_ERROR_QUEUE_ON_RETURN;
9836 return SSL_get_signature_algorithm_key_type(signatureAlg);
9837 }
9838
9839 /**
9840 * Gets the timeout for the SSL session.
9841 */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)9842 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
9843 CHECK_ERROR_QUEUE_ON_RETURN;
9844 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9845 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
9846 if (ssl_session == nullptr) {
9847 return 0;
9848 }
9849
9850 return SSL_get_timeout(ssl_session);
9851 }
9852
9853 /**
9854 * Gets the ID for the SSL session, or null if no session is currently available.
9855 */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9856 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
9857 CONSCRYPT_UNUSED jobject ssl_holder) {
9858 CHECK_ERROR_QUEUE_ON_RETURN;
9859 SSL* ssl = to_SSL(env, ssl_address, true);
9860 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
9861 if (ssl == nullptr) {
9862 return nullptr;
9863 }
9864
9865 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9866 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
9867 if (ssl_session == nullptr) {
9868 return nullptr;
9869 }
9870 jbyteArray result = get_session_id(env, ssl_session);
9871 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
9872 return result;
9873 }
9874
9875 /**
9876 * Gets and returns in a string the version of the SSL protocol. If it
9877 * returns the string "unknown" it means that no connection is established.
9878 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9879 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
9880 jlong ssl_session_address) {
9881 CHECK_ERROR_QUEUE_ON_RETURN;
9882 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9883 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9884 if (ssl_session == nullptr) {
9885 return nullptr;
9886 }
9887 const char* protocol = SSL_SESSION_get_version(ssl_session);
9888 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9889 return env->NewStringUTF(protocol);
9890 }
9891
9892 /**
9893 * Gets and returns in a string the cipher negotiated for the SSL session.
9894 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9895 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9896 CHECK_ERROR_QUEUE_ON_RETURN;
9897 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9898 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9899 if (ssl_session == nullptr) {
9900 return nullptr;
9901 }
9902 const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
9903 const char* name = SSL_CIPHER_standard_name(cipher);
9904 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9905 return env->NewStringUTF(name);
9906 }
9907
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)9908 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
9909 jlong ssl_session_address) {
9910 CHECK_ERROR_QUEUE_ON_RETURN;
9911 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9912 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
9913 if (ssl_session == nullptr) {
9914 return JNI_FALSE;
9915 }
9916 int single_use = SSL_SESSION_should_be_single_use(ssl_session);
9917 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
9918 single_use);
9919 return single_use ? JNI_TRUE : JNI_FALSE;
9920 }
9921
9922 /**
9923 * Increments the reference count of the session.
9924 */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)9925 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
9926 CHECK_ERROR_QUEUE_ON_RETURN;
9927 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9928 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
9929 if (ssl_session == nullptr) {
9930 return;
9931 }
9932 SSL_SESSION_up_ref(ssl_session);
9933 }
9934
9935 /**
9936 * Frees the SSL session.
9937 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9938 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9939 CHECK_ERROR_QUEUE_ON_RETURN;
9940 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9941 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9942 if (ssl_session == nullptr) {
9943 return;
9944 }
9945 SSL_SESSION_free(ssl_session);
9946 }
9947
9948 /**
9949 * Serializes the native state of the session (ID, cipher, and keys but
9950 * not certificates). Returns a byte[] containing the DER-encoded state.
9951 * See apache mod_ssl.
9952 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9953 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9954 CHECK_ERROR_QUEUE_ON_RETURN;
9955 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9956 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9957 if (ssl_session == nullptr) {
9958 return nullptr;
9959 }
9960 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
9961 }
9962
9963 /**
9964 * Deserialize the session.
9965 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9966 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9967 CHECK_ERROR_QUEUE_ON_RETURN;
9968 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9969
9970 ScopedByteArrayRO bytes(env, javaBytes);
9971 if (bytes.get() == nullptr) {
9972 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9973 return 0;
9974 }
9975 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9976 // NOLINTNEXTLINE(runtime/int)
9977 SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
9978
9979 if (ssl_session == nullptr ||
9980 ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
9981 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
9982 conscrypt::jniutil::throwIOException);
9983 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
9984 return 0L;
9985 }
9986
9987 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9988 return reinterpret_cast<uintptr_t>(ssl_session);
9989 }
9990
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)9991 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
9992 CHECK_ERROR_QUEUE_ON_RETURN;
9993 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
9994 if (cipher == nullptr) {
9995 return nullptr;
9996 }
9997
9998 const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
9999 return env->NewStringUTF(kx_name);
10000 }
10001
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)10002 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
10003 CHECK_ERROR_QUEUE_ON_RETURN;
10004 ScopedUtfChars selector(env, selectorJava);
10005 if (selector.c_str() == nullptr) {
10006 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10007 "selector == null");
10008 return nullptr;
10009 }
10010
10011 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
10012
10013 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
10014 bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
10015
10016 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
10017 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10018 "Unable to set SSL cipher list");
10019 return nullptr;
10020 }
10021 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
10022
10023 size_t size = sk_SSL_CIPHER_num(ciphers);
10024 ScopedLocalRef<jobjectArray> cipherNamesArray(
10025 env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
10026 nullptr));
10027 if (cipherNamesArray.get() == nullptr) {
10028 return nullptr;
10029 }
10030
10031 // Return an array of standard and OpenSSL name pairs.
10032 for (size_t i = 0; i < size; i++) {
10033 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
10034 ScopedLocalRef<jstring> cipherName(env,
10035 env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
10036 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
10037 cipherName.get());
10038
10039 ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
10040 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
10041 opensslName.get());
10042 }
10043
10044 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
10045 2 * size);
10046 return cipherNamesArray.release();
10047 }
10048
10049 /**
10050 * Compare the given CertID with a certificate and it's issuer.
10051 * True is returned if the CertID matches.
10052 */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)10053 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
10054 // Get the hash algorithm used by this CertID
10055 CBS hash_algorithm, hash;
10056 if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
10057 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
10058 return false;
10059 }
10060
10061 // Get the issuer's name hash from the CertID
10062 CBS issuer_name_hash;
10063 if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
10064 return false;
10065 }
10066
10067 // Get the issuer's key hash from the CertID
10068 CBS issuer_key_hash;
10069 if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
10070 return false;
10071 }
10072
10073 // Get the serial number from the CertID
10074 CBS serial;
10075 if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
10076 return false;
10077 }
10078
10079 // Compare the certificate's serial number with the one from the Cert ID
10080 const uint8_t* p = CBS_data(&serial);
10081 bssl::UniquePtr<ASN1_INTEGER> serial_number(
10082 c2i_ASN1_INTEGER(nullptr, &p,
10083 static_cast<long>(CBS_len(&serial)))); // NOLINT(runtime/int)
10084 const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
10085 if (serial_number.get() == nullptr ||
10086 ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
10087 return false;
10088 }
10089
10090 // Find the hash algorithm to be used
10091 const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
10092 if (digest == nullptr) {
10093 return false;
10094 }
10095
10096 // Hash the issuer's name and compare the hash with the one from the Cert ID
10097 uint8_t md[EVP_MAX_MD_SIZE];
10098 const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
10099 if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
10100 !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
10101 return false;
10102 }
10103
10104 // Same thing with the issuer's key
10105 const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
10106 if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
10107 static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
10108 nullptr) ||
10109 !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
10110 return false;
10111 }
10112
10113 return true;
10114 }
10115
10116 /**
10117 * Get a SingleResponse whose CertID matches the given certificate and issuer from a
10118 * SEQUENCE OF SingleResponse.
10119 *
10120 * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
10121 * error occured or no response matches the certificate, false is returned and |out_single_response|
10122 * is unchanged.
10123 */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)10124 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
10125 CBS* out_single_response) {
10126 // Iterate over all the SingleResponses, until one matches the certificate
10127 while (CBS_len(responses) > 0) {
10128 // Get the next available SingleResponse from the sequence
10129 CBS single_response;
10130 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
10131 return false;
10132 }
10133
10134 // Make a copy of the stream so we pass it back to the caller
10135 CBS single_response_original = single_response;
10136
10137 // Get the SingleResponse's CertID
10138 // If this fails ignore the current response and move to the next one
10139 CBS cert_id;
10140 if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
10141 continue;
10142 }
10143
10144 // Compare the CertID with the given certificate and issuer
10145 if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
10146 *out_single_response = single_response_original;
10147 return true;
10148 }
10149 }
10150
10151 return false;
10152 }
10153
10154 /**
10155 * Get the BasicOCSPResponse from an OCSPResponse.
10156 * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
10157 * returned.
10158 */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)10159 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
10160 CBS tagged_response_bytes, response_bytes, response_type, response;
10161
10162 // Get the ResponseBytes out of the OCSPResponse
10163 if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
10164 !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
10165 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10166 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
10167 return false;
10168 }
10169
10170 // Parse the response type and data out of the ResponseBytes
10171 if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
10172 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
10173 return false;
10174 }
10175
10176 // Only basic OCSP responses are supported
10177 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
10178 return false;
10179 }
10180
10181 // Parse the octet string as a BasicOCSPResponse
10182 return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
10183 }
10184
10185 /**
10186 * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
10187 * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
10188 * true is returned.
10189 */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)10190 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
10191 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
10192 CBS response_data;
10193 if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
10194 return false;
10195 }
10196
10197 // Skip the version, responderID and producedAt fields
10198 if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
10199 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10200 !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
10201 !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
10202 return false;
10203 }
10204
10205 // Extract the list of SingleResponse.
10206 return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
10207 }
10208
10209 /**
10210 * Get the SEQUENCE OF Extension from a SingleResponse.
10211 * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
10212 * returned.
10213 */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)10214 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
10215 // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
10216 if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
10217 !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
10218 !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
10219 !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
10220 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
10221 return false;
10222 }
10223
10224 // Get the list of Extension
10225 return CBS_get_asn1(single_response, extensions,
10226 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
10227 }
10228
10229 /*
10230 public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
10231 long x509Ref, long issuerX509Ref);
10232 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)10233 static jbyteArray NativeCrypto_get_ocsp_single_extension(
10234 JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
10235 CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
10236 CHECK_ERROR_QUEUE_ON_RETURN;
10237 ScopedByteArrayRO ocspData(env, ocspDataBytes);
10238 if (ocspData.get() == nullptr) {
10239 return nullptr;
10240 }
10241
10242 CBS cbs;
10243 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
10244
10245 // Start parsing the OCSPResponse
10246 CBS ocsp_response;
10247 if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
10248 return nullptr;
10249 }
10250
10251 // Get the BasicOCSPResponse from the OCSP Response
10252 CBS basic_response;
10253 if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
10254 return nullptr;
10255 }
10256
10257 // Get the list of SingleResponses from the BasicOCSPResponse
10258 CBS responses;
10259 if (!get_ocsp_single_responses(&basic_response, &responses)) {
10260 return nullptr;
10261 }
10262
10263 // Find the response matching the certificate
10264 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
10265 X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
10266 CBS single_response;
10267 if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
10268 return nullptr;
10269 }
10270
10271 // Get the extensions from the SingleResponse
10272 CBS extensions;
10273 if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
10274 return nullptr;
10275 }
10276
10277 const uint8_t* ptr = CBS_data(&extensions);
10278 bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
10279 d2i_X509_EXTENSIONS(nullptr, &ptr,
10280 static_cast<long>(CBS_len(&extensions)))); // NOLINT(runtime/int)
10281 if (x509_exts.get() == nullptr) {
10282 return nullptr;
10283 }
10284
10285 return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
10286 env, x509_exts.get(), oid);
10287 }
10288
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)10289 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
10290 // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
10291 // no throwing if the buffer is null or not a direct ByteBuffer.
10292 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
10293 return 0;
10294 }
10295 return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
10296 }
10297
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)10298 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
10299 CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
10300 CHECK_ERROR_QUEUE_ON_RETURN;
10301 SSL* ssl = to_SSL(env, ssl_address, true);
10302 if (ssl == nullptr) {
10303 return 0;
10304 }
10305 return SSL_get_error(ssl, ret);
10306 }
10307
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)10308 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
10309 ERR_clear_error();
10310 }
10311
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10312 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
10313 CONSCRYPT_UNUSED jobject ssl_holder) {
10314 CHECK_ERROR_QUEUE_ON_RETURN;
10315 SSL* ssl = to_SSL(env, ssl_address, true);
10316 if (ssl == nullptr) {
10317 return 0;
10318 }
10319 return SSL_pending(ssl);
10320 }
10321
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)10322 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
10323 CHECK_ERROR_QUEUE_ON_RETURN;
10324 BIO* bio = to_BIO(env, bio_address);
10325 if (bio == nullptr) {
10326 return 0;
10327 }
10328 return static_cast<jint>(BIO_ctrl_pending(bio));
10329 }
10330
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10331 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
10332 CONSCRYPT_UNUSED jobject ssl_holder) {
10333 CHECK_ERROR_QUEUE_ON_RETURN;
10334 SSL* ssl = to_SSL(env, ssl_address, true);
10335 if (ssl == nullptr) {
10336 return 0;
10337 }
10338 return (jint)SSL_max_seal_overhead(ssl);
10339 }
10340
10341 /**
10342 * public static native int SSL_new_BIO(long ssl) throws SSLException;
10343 */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10344 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
10345 CONSCRYPT_UNUSED jobject ssl_holder) {
10346 CHECK_ERROR_QUEUE_ON_RETURN;
10347 SSL* ssl = to_SSL(env, ssl_address, true);
10348 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
10349 if (ssl == nullptr) {
10350 return 0;
10351 }
10352
10353 BIO* internal_bio;
10354 BIO* network_bio;
10355 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
10356 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
10357 "BIO_new_bio_pair failed");
10358 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
10359 return 0;
10360 }
10361
10362 SSL_set_bio(ssl, internal_bio, internal_bio);
10363
10364 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
10365 return reinterpret_cast<uintptr_t>(network_bio);
10366 }
10367
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10368 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
10369 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10370 CHECK_ERROR_QUEUE_ON_RETURN;
10371 SSL* ssl = to_SSL(env, ssl_address, true);
10372 if (ssl == nullptr) {
10373 return 0;
10374 }
10375 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
10376
10377 if (shc == nullptr) {
10378 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10379 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
10380 ssl);
10381 return 0;
10382 }
10383
10384 AppData* appData = toAppData(ssl);
10385 if (appData == nullptr) {
10386 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10387 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
10388 return 0;
10389 }
10390
10391 errno = 0;
10392
10393 if (!appData->setCallbackState(env, shc, nullptr)) {
10394 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10395 ERR_clear_error();
10396 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10397 return 0;
10398 }
10399
10400 int ret = SSL_do_handshake(ssl);
10401 appData->clearCallbackState();
10402 if (env->ExceptionCheck()) {
10403 // cert_verify_callback threw exception
10404 ERR_clear_error();
10405 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10406 return 0;
10407 }
10408
10409 SslError sslError(ssl, ret);
10410 int code = sslError.get();
10411
10412 if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
10413 // Non-exceptional case.
10414 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
10415 return code;
10416 }
10417
10418 // Exceptional case...
10419 if (ret == 0) {
10420 // TODO(nmittler): Can this happen with memory BIOs?
10421 /*
10422 * Clean error. See SSL_do_handshake(3SSL) man page.
10423 * The other side closed the socket before the handshake could be
10424 * completed, but everything is within the bounds of the TLS protocol.
10425 * We still might want to find out the real reason of the failure.
10426 */
10427 if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
10428 (code == SSL_ERROR_ZERO_RETURN)) {
10429 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
10430 } else {
10431 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10432 env, ssl, sslError.release(), "SSL handshake terminated",
10433 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10434 }
10435 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
10436 return code;
10437 }
10438
10439 /*
10440 * Unclean error. See SSL_do_handshake(3SSL) man page.
10441 * Translate the error and throw exception. We are sure it is an error
10442 * at this point.
10443 */
10444 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10445 env, ssl, sslError.release(), "SSL handshake aborted",
10446 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10447 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
10448 return code;
10449 }
10450
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10451 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
10452 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10453 CHECK_ERROR_QUEUE_ON_RETURN;
10454 SSL* ssl = to_SSL(env, ssl_address, false);
10455 if (ssl == nullptr) {
10456 return;
10457 }
10458 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
10459
10460 if (shc == nullptr) {
10461 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10462 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10463 return;
10464 }
10465
10466 AppData* appData = toAppData(ssl);
10467 if (appData != nullptr) {
10468 if (!appData->setCallbackState(env, shc, nullptr)) {
10469 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10470 ERR_clear_error();
10471 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10472 return;
10473 }
10474 int ret = SSL_shutdown(ssl);
10475 appData->clearCallbackState();
10476 // callbacks can happen if server requests renegotiation
10477 if (env->ExceptionCheck()) {
10478 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10479 return;
10480 }
10481 switch (ret) {
10482 case 0:
10483 /*
10484 * Shutdown was not successful (yet), but there also
10485 * is no error. Since we can't know whether the remote
10486 * server is actually still there, and we don't want to
10487 * get stuck forever in a second SSL_shutdown() call, we
10488 * simply return. This is not security a problem as long
10489 * as we close the underlying socket, which we actually
10490 * do, because that's where we are just coming from.
10491 */
10492 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
10493 break;
10494 case 1:
10495 /*
10496 * Shutdown was successful. We can safely return. Hooray!
10497 */
10498 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
10499 break;
10500 default:
10501 /*
10502 * Everything else is a real error condition. We should
10503 * let the Java layer know about this by throwing an
10504 * exception.
10505 */
10506 int sslError = SSL_get_error(ssl, ret);
10507 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
10508 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
10509 "SSL shutdown failed");
10510 break;
10511 }
10512 }
10513
10514 ERR_clear_error();
10515 }
10516
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)10517 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
10518 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10519 jint length, jobject shc) {
10520 CHECK_ERROR_QUEUE_ON_RETURN;
10521 SSL* ssl = to_SSL(env, ssl_address, true);
10522 char* destPtr = reinterpret_cast<char*>(address);
10523 if (ssl == nullptr) {
10524 return -1;
10525 }
10526 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
10527 destPtr, length, shc);
10528
10529 if (shc == nullptr) {
10530 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10531 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
10532 ssl);
10533 return -1;
10534 }
10535 AppData* appData = toAppData(ssl);
10536 if (appData == nullptr) {
10537 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10538 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
10539 return -1;
10540 }
10541 if (!appData->setCallbackState(env, shc, nullptr)) {
10542 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10543 ERR_clear_error();
10544 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
10545 return -1;
10546 }
10547
10548 errno = 0;
10549
10550 int result = SSL_read(ssl, destPtr, length);
10551 appData->clearCallbackState();
10552 if (env->ExceptionCheck()) {
10553 // An exception was thrown by one of the callbacks. Just propagate that exception.
10554 ERR_clear_error();
10555 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10556 return -1;
10557 }
10558
10559 SslError sslError(ssl, result);
10560 switch (sslError.get()) {
10561 case SSL_ERROR_NONE: {
10562 // Successfully read at least one byte. Just return the result.
10563 break;
10564 }
10565 case SSL_ERROR_ZERO_RETURN: {
10566 // A close_notify was received, this stream is finished.
10567 return -SSL_ERROR_ZERO_RETURN;
10568 }
10569 case SSL_ERROR_WANT_READ:
10570 case SSL_ERROR_WANT_WRITE: {
10571 // Return the negative of these values.
10572 result = -sslError.get();
10573 break;
10574 }
10575 case SSL_ERROR_SYSCALL: {
10576 // A problem occurred during a system call, but this is not
10577 // necessarily an error.
10578 if (result == 0) {
10579 // TODO(nmittler): Can this happen with memory BIOs?
10580 // Connection closed without proper shutdown. Tell caller we
10581 // have reached end-of-stream.
10582 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10583 break;
10584 }
10585
10586 if (errno == EINTR) {
10587 // TODO(nmittler): Can this happen with memory BIOs?
10588 // System call has been interrupted. Simply retry.
10589 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10590 "Read error");
10591 break;
10592 }
10593
10594 // Note that for all other system call errors we fall through
10595 // to the default case, which results in an Exception.
10596 FALLTHROUGH_INTENDED;
10597 }
10598 default: {
10599 // Everything else is basically an error.
10600 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10601 "Read error");
10602 break;
10603 }
10604 }
10605
10606 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10607 ssl, destPtr, length, shc, result);
10608 return result;
10609 }
10610
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)10611 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10612 CONSCRYPT_UNUSED jobject ssl_holder,
10613 jlong bioRef, jlong address, jint len,
10614 jobject shc) {
10615 CHECK_ERROR_QUEUE_ON_RETURN;
10616 SSL* ssl = to_SSL(env, ssl_address, true);
10617 if (ssl == nullptr) {
10618 return -1;
10619 }
10620 if (shc == nullptr) {
10621 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10622 JNI_TRACE(
10623 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10624 "sslHandshakeCallbacks == null",
10625 ssl);
10626 return -1;
10627 }
10628 BIO* bio = to_BIO(env, bioRef);
10629 if (bio == nullptr) {
10630 return -1;
10631 }
10632 if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10633 // The network BIO couldn't handle the entire write. Don't write anything, so that we
10634 // only process one packet at a time.
10635 return 0;
10636 }
10637 const char* sourcePtr = reinterpret_cast<const char*>(address);
10638
10639 AppData* appData = toAppData(ssl);
10640 if (appData == nullptr) {
10641 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10642 ERR_clear_error();
10643 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10644 return -1;
10645 }
10646 if (!appData->setCallbackState(env, shc, nullptr)) {
10647 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10648 ERR_clear_error();
10649 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10650 return -1;
10651 }
10652
10653 errno = 0;
10654
10655 int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10656 appData->clearCallbackState();
10657 JNI_TRACE(
10658 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10659 "ret=%d",
10660 ssl, bio, sourcePtr, len, shc, result);
10661 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10662 static_cast<size_t>(result));
10663 return result;
10664 }
10665
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)10666 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10667 CONSCRYPT_UNUSED jobject ssl_holder,
10668 jlong bioRef, jlong address, jint outputSize,
10669 jobject shc) {
10670 CHECK_ERROR_QUEUE_ON_RETURN;
10671 SSL* ssl = to_SSL(env, ssl_address, true);
10672 if (ssl == nullptr) {
10673 return -1;
10674 }
10675 if (shc == nullptr) {
10676 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10677 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10678 ssl);
10679 return -1;
10680 }
10681 BIO* bio = to_BIO(env, bioRef);
10682 if (bio == nullptr) {
10683 return -1;
10684 }
10685 char* destPtr = reinterpret_cast<char*>(address);
10686 if (destPtr == nullptr) {
10687 conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10688 return -1;
10689 }
10690
10691 AppData* appData = toAppData(ssl);
10692 if (appData == nullptr) {
10693 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10694 ERR_clear_error();
10695 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10696 return -1;
10697 }
10698 if (!appData->setCallbackState(env, shc, nullptr)) {
10699 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10700 ERR_clear_error();
10701 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10702 return -1;
10703 }
10704
10705 errno = 0;
10706
10707 int result = BIO_read(bio, destPtr, outputSize);
10708 appData->clearCallbackState();
10709 JNI_TRACE(
10710 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10711 "=> ret=%d",
10712 ssl, bio, destPtr, outputSize, shc, result);
10713 JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10714 return result;
10715 }
10716
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10717 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10718 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10719 CHECK_ERROR_QUEUE_ON_RETURN;
10720 SSL* ssl = to_SSL(env, ssl_address, true);
10721 if (ssl == nullptr) {
10722 return;
10723 }
10724 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10725 if (shc == nullptr) {
10726 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10727 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10728 ssl);
10729 return;
10730 }
10731 AppData* appData = toAppData(ssl);
10732 if (appData == nullptr) {
10733 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10734 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10735 return;
10736 }
10737 if (!appData->setCallbackState(env, shc, nullptr)) {
10738 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10739 ERR_clear_error();
10740 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10741 return;
10742 }
10743 char c;
10744 int result = SSL_peek(ssl, &c, 1);
10745 appData->clearCallbackState();
10746 if (env->ExceptionCheck()) {
10747 // An exception was thrown by one of the callbacks. Just propagate that exception.
10748 ERR_clear_error();
10749 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10750 return;
10751 }
10752
10753 SslError sslError(ssl, result);
10754 switch (sslError.get()) {
10755 case SSL_ERROR_NONE:
10756 case SSL_ERROR_ZERO_RETURN:
10757 case SSL_ERROR_WANT_READ:
10758 case SSL_ERROR_WANT_WRITE: {
10759 // The call succeeded, lacked data, or the SSL is closed. All is well.
10760 break;
10761 }
10762 case SSL_ERROR_SYSCALL: {
10763 // A problem occurred during a system call, but this is not
10764 // necessarily an error.
10765 if (result == 0) {
10766 // TODO(nmittler): Can this happen with memory BIOs?
10767 // Connection closed without proper shutdown. Tell caller we
10768 // have reached end-of-stream.
10769 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10770 break;
10771 }
10772
10773 if (errno == EINTR) {
10774 // TODO(nmittler): Can this happen with memory BIOs?
10775 // System call has been interrupted. Simply retry.
10776 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10777 "Read error");
10778 break;
10779 }
10780
10781 // Note that for all other system call errors we fall through
10782 // to the default case, which results in an Exception.
10783 FALLTHROUGH_INTENDED;
10784 }
10785 default: {
10786 // Everything else is basically an error.
10787 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10788 "Read error");
10789 break;
10790 }
10791 }
10792
10793 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10794 }
10795
10796 /**
10797 * OpenSSL write function (2): write into buffer at offset n chunks.
10798 */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10799 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10800 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10801 jint len, jobject shc) {
10802 CHECK_ERROR_QUEUE_ON_RETURN;
10803 SSL* ssl = to_SSL(env, ssl_address, true);
10804 const char* sourcePtr = reinterpret_cast<const char*>(address);
10805 if (ssl == nullptr) {
10806 return -1;
10807 }
10808 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10809 sourcePtr, len, shc);
10810 if (shc == nullptr) {
10811 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10812 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10813 ssl);
10814 return -1;
10815 }
10816
10817 AppData* appData = toAppData(ssl);
10818 if (appData == nullptr) {
10819 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10820 ERR_clear_error();
10821 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10822 return -1;
10823 }
10824 if (!appData->setCallbackState(env, shc, nullptr)) {
10825 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10826 ERR_clear_error();
10827 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10828 return -1;
10829 }
10830
10831 errno = 0;
10832
10833 int result = SSL_write(ssl, sourcePtr, len);
10834 appData->clearCallbackState();
10835 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
10836 ssl, sourcePtr, len, shc, result);
10837 return result;
10838 }
10839
10840 /**
10841 * public static native bool usesBoringSsl_FIPS_mode();
10842 */
NativeCrypto_usesBoringSsl_FIPS_mode()10843 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
10844 return FIPS_mode();
10845 }
10846
10847 /**
10848 * Scrypt support
10849 */
10850
NativeCrypto_Scrypt_generate_key(JNIEnv * env,jclass,jbyteArray password,jbyteArray salt,jint n,jint r,jint p,jint key_len)10851 static jbyteArray NativeCrypto_Scrypt_generate_key(JNIEnv* env, jclass, jbyteArray password, jbyteArray salt,
10852 jint n, jint r, jint p, jint key_len) {
10853 CHECK_ERROR_QUEUE_ON_RETURN;
10854 JNI_TRACE("Scrypt_generate_key(%p, %p, %d, %d, %d, %d)", password, salt, n, r, p, key_len);
10855
10856 if (password == nullptr) {
10857 conscrypt::jniutil::throwNullPointerException(env, "password == null");
10858 JNI_TRACE("Scrypt_generate_key() => password == null");
10859 return nullptr;
10860 }
10861 if (salt == nullptr) {
10862 conscrypt::jniutil::throwNullPointerException(env, "salt == null");
10863 JNI_TRACE("Scrypt_generate_key() => salt == null");
10864 return nullptr;
10865 }
10866
10867 jbyteArray key_bytes = env->NewByteArray(static_cast<jsize>(key_len));
10868 ScopedByteArrayRW out_key(env, key_bytes);
10869 if (out_key.get() == nullptr) {
10870 conscrypt::jniutil::throwNullPointerException(env, "out_key == null");
10871 JNI_TRACE("Scrypt_generate_key() => out_key == null");
10872 return nullptr;
10873 }
10874
10875 size_t memory_limit = 1u << 29;
10876 ScopedByteArrayRO password_bytes(env, password);
10877 ScopedByteArrayRO salt_bytes(env, salt);
10878
10879 int result = EVP_PBE_scrypt(reinterpret_cast<const char*>(password_bytes.get()), password_bytes.size(),
10880 reinterpret_cast<const uint8_t*>(salt_bytes.get()), salt_bytes.size(),
10881 n, r, p, memory_limit,
10882 reinterpret_cast<uint8_t*>(out_key.get()), key_len);
10883
10884 if (result <= 0) {
10885 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Scrypt_generate_key");
10886 return nullptr;
10887 }
10888 return key_bytes;
10889 }
10890
10891 // TESTING METHODS BEGIN
10892
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)10893 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
10894 CHECK_ERROR_QUEUE_ON_RETURN;
10895 BIO* bio = to_BIO(env, bioRef);
10896 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
10897
10898 if (bio == nullptr) {
10899 JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
10900 return 0;
10901 }
10902
10903 if (outputJavaBytes == nullptr) {
10904 conscrypt::jniutil::throwNullPointerException(env, "output == null");
10905 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
10906 return 0;
10907 }
10908
10909 jsize outputSize = env->GetArrayLength(outputJavaBytes);
10910
10911 std::unique_ptr<unsigned char[]> buffer(
10912 new unsigned char[static_cast<unsigned int>(outputSize)]);
10913 if (buffer.get() == nullptr) {
10914 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
10915 return 0;
10916 }
10917
10918 int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
10919 if (read <= 0) {
10920 conscrypt::jniutil::throwIOException(env, "BIO_read");
10921 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
10922 return 0;
10923 }
10924
10925 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
10926 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
10927 return read;
10928 }
10929
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)10930 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
10931 jint offset, jint length) {
10932 CHECK_ERROR_QUEUE_ON_RETURN;
10933 BIO* bio = to_BIO(env, bioRef);
10934 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
10935
10936 if (bio == nullptr) {
10937 return;
10938 }
10939
10940 if (inputJavaBytes == nullptr) {
10941 conscrypt::jniutil::throwNullPointerException(env, "input == null");
10942 return;
10943 }
10944
10945 int inputSize = env->GetArrayLength(inputJavaBytes);
10946 if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
10947 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
10948 "inputJavaBytes");
10949 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
10950 return;
10951 }
10952
10953 std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
10954 if (buffer.get() == nullptr) {
10955 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
10956 return;
10957 }
10958
10959 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
10960 if (BIO_write(bio, buffer.get(), length) != length) {
10961 ERR_clear_error();
10962 conscrypt::jniutil::throwIOException(env, "BIO_write");
10963 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
10964 return;
10965 }
10966
10967 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
10968 }
10969
10970 /**
10971 * public static native long SSL_clear_mode(long ssl, long mode);
10972 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)10973 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
10974 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
10975 CHECK_ERROR_QUEUE_ON_RETURN;
10976 SSL* ssl = to_SSL(env, ssl_address, true);
10977 // NOLINTNEXTLINE(runtime/int)
10978 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
10979 if (ssl == nullptr) {
10980 return 0;
10981 }
10982 jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
10983 // NOLINTNEXTLINE(runtime/int)
10984 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
10985 return result;
10986 }
10987
10988 /**
10989 * public static native long SSL_get_mode(long ssl);
10990 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10991 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
10992 CONSCRYPT_UNUSED jobject ssl_holder) {
10993 CHECK_ERROR_QUEUE_ON_RETURN;
10994 SSL* ssl = to_SSL(env, ssl_address, true);
10995 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
10996 if (ssl == nullptr) {
10997 return 0;
10998 }
10999 jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
11000 // NOLINTNEXTLINE(runtime/int)
11001 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
11002 return mode;
11003 }
11004
11005 /**
11006 * public static native long SSL_get_options(long ssl);
11007 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11008 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
11009 CONSCRYPT_UNUSED jobject ssl_holder) {
11010 CHECK_ERROR_QUEUE_ON_RETURN;
11011 SSL* ssl = to_SSL(env, ssl_address, true);
11012 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
11013 if (ssl == nullptr) {
11014 return 0;
11015 }
11016 jlong options = static_cast<jlong>(SSL_get_options(ssl));
11017 // NOLINTNEXTLINE(runtime/int)
11018 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
11019 return options;
11020 }
11021
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11022 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
11023 CONSCRYPT_UNUSED jobject ssl_holder) {
11024 CHECK_ERROR_QUEUE_ON_RETURN;
11025 SSL* ssl = to_SSL(env, ssl_address, true);
11026 if (ssl == nullptr) {
11027 return 0;
11028 }
11029 return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
11030 }
11031
11032 // TESTING METHODS END
11033
11034 #define CONSCRYPT_NATIVE_METHOD(functionName, signature) \
11035 { \
11036 /* NOLINTNEXTLINE */ \
11037 (char*)#functionName, (char*)(signature), \
11038 reinterpret_cast<void*>(NativeCrypto_##functionName) \
11039 }
11040
11041 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
11042 #define SSL_CALLBACKS \
11043 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
11044 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
11045 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
11046 #define REF_EVP_CIPHER_CTX \
11047 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
11048 #define REF_EVP_HPKE_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_CTX;"
11049 #define REF_EVP_HPKE_KEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_KEY;"
11050 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
11051 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
11052 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
11053 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
11054 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
11055 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
11056 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
11057 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
11058 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
11059 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
11060 static JNINativeMethod sNativeCryptoMethods[] = {
11061 CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
11062 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
11063 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
11064 CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
11065 CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
11066 CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
11067 CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
11068 CONSCRYPT_NATIVE_METHOD(CMAC_Reset, "(" REF_CMAC_CTX ")V"),
11069 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
11070 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
11071 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
11072 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11073 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11074 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
11075 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11076 CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
11077 CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
11078 CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"),
11079 CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
11080 CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
11081 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
11082 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
11083 CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
11084 CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
11085 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
11086 CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
11087 CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
11088 CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11089 CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11090 CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11091 CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11092 CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
11093 CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
11094 CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
11095 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
11096 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
11097 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
11098 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
11099 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
11100 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
11101 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
11102 CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
11103 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
11104 CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
11105 CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
11106 CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
11107 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
11108 CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
11109 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
11110 CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
11111 CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
11112 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
11113 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
11114 CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
11115 CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
11116 CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11117 CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
11118 CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
11119 CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
11120 CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
11121 CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
11122 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
11123 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
11124 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
11125 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
11126 CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
11127 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11128 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11129 CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
11130 CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
11131 CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
11132 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11133 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11134 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11135 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
11136 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11137 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11138 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11139 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
11140 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
11141 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11142 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
11143 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11144 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
11145 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
11146 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
11147 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
11148 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
11149 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
11150 CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
11151 CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
11152 CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
11153 CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
11154 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
11155 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
11156 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
11157 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
11158 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
11159 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
11160 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
11161 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
11162 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
11163 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
11164 CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
11165 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
11166 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
11167 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
11168 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
11169 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
11170 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
11171 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf,
11172 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11173 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf,
11174 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11175 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_export, "(" REF_EVP_HPKE_CTX "[BI)[B"),
11176 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_free, "(J)V"),
11177 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_open, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11178 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_seal, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11179 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_recipient, "(III[B[B[B)Ljava/lang/Object;"),
11180 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender, "(III[B[B)[Ljava/lang/Object;"),
11181 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing,
11182 "(III[B[B[B)[Ljava/lang/Object;"),
11183 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
11184 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
11185 CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
11186 CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
11187 CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
11188 CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
11189 CONSCRYPT_NATIVE_METHOD(HMAC_Reset, "(" REF_HMAC_CTX ")V"),
11190 CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
11191 CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
11192 CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
11193 CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
11194 CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
11195 CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
11196 CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
11197 CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
11198 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
11199 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
11200 CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
11201 CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
11202 CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
11203 CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
11204 CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
11205 CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
11206 CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
11207 CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
11208 CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
11209 CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
11210 CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11211 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11212 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
11213 CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
11214 CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
11215 CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
11216 CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
11217 CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
11218 CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
11219 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
11220 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
11221 CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
11222 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
11223 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
11224 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
11225 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
11226 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
11227 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
11228 CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
11229 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
11230 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
11231 CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
11232 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
11233 CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
11234 CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
11235 CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
11236 CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
11237 CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
11238 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
11239 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext,
11240 "(J" REF_X509 "Ljava/lang/String;)[B"),
11241 CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
11242 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
11243 CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
11244 CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
11245 CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
11246 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
11247 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
11248 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
11249 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
11250 CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
11251 CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
11252 CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
11253 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
11254 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
11255 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
11256 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
11257 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
11258 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
11259 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
11260 CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
11261 CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
11262 CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
11263 CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
11264 CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
11265 CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
11266 CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
11267 CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
11268 CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
11269 CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
11270 CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
11271 CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
11272 CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
11273 CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
11274 CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
11275 CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
11276 CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
11277 CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
11278 CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
11279 CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
11280 CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
11281 CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
11282 CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
11283 CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
11284 CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
11285 CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
11286 CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
11287 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
11288 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
11289 CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
11290 CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
11291 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
11292 CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
11293 CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
11294 CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
11295 CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
11296 CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
11297 CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
11298 CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
11299 CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
11300 CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
11301 CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
11302 CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
11303 CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
11304 CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
11305 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
11306 CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
11307 CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
11308 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
11309 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
11310 CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
11311 CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
11312 CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
11313 CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
11314 CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
11315 CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
11316 CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
11317 CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
11318 CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
11319 CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
11320 CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
11321 CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
11322 CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
11323 CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
11324 CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
11325 CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
11326 CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
11327 CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
11328 CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
11329 CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
11330 CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
11331 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
11332 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
11333 CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
11334 CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
11335 CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
11336 CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
11337 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
11338 CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
11339 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
11340 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
11341 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
11342 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
11343 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
11344 CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
11345 CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
11346 CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
11347 CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
11348 CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
11349 CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
11350 CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
11351 CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
11352 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
11353 CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
11354 CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
11355 CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
11356 CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
11357 CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
11358 CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
11359 CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
11360 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
11361 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11362 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11363 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11364 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11365 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
11366 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
11367 CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
11368 CONSCRYPT_NATIVE_METHOD(Scrypt_generate_key, "([B[BIIII)[B"),
11369
11370 // Used for testing only.
11371 CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
11372 CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
11373 CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
11374 CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
11375 CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
11376 CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
11377 };
11378
registerNativeMethods(JNIEnv * env)11379 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
11380 conscrypt::jniutil::jniRegisterNativeMethods(
11381 env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
11382 NELEM(sNativeCryptoMethods));
11383 }
11384
11385 /* Local Variables: */
11386 /* mode: c++ */
11387 /* tab-width: 4 */
11388 /* indent-tabs-mode: nil */
11389 /* c-basic-offset: 4 */
11390 /* End: */
11391 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
11392