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_ED25519_keypair(JNIEnv * env,jclass,jbyteArray outPublicArray,jbyteArray outPrivateArray)2565 static void NativeCrypto_ED25519_keypair(JNIEnv* env, jclass, jbyteArray outPublicArray,
2566 jbyteArray outPrivateArray) {
2567 CHECK_ERROR_QUEUE_ON_RETURN;
2568 JNI_TRACE("ED25519_keypair(%p, %p)", outPublicArray, outPrivateArray);
2569
2570 ScopedByteArrayRW outPublic(env, outPublicArray);
2571 if (outPublic.get() == nullptr) {
2572 JNI_TRACE("ED25519_keypair(%p, %p) can't get output public key buffer", outPublicArray,
2573 outPrivateArray);
2574 return;
2575 }
2576
2577 ScopedByteArrayRW outPrivate(env, outPrivateArray);
2578 if (outPrivate.get() == nullptr) {
2579 JNI_TRACE("ED25519_keypair(%p, %p) can't get output private key buffer", outPublicArray,
2580 outPrivateArray);
2581 return;
2582 }
2583
2584 if (outPublic.size() != ED25519_PUBLIC_KEY_LEN) {
2585 conscrypt::jniutil::throwIllegalArgumentException(env,
2586 "Output public key array length != 32");
2587 return;
2588 }
2589
2590 if (outPrivate.size() != ED25519_PRIVATE_KEY_LEN) {
2591 conscrypt::jniutil::throwIllegalArgumentException(env,
2592 "Output private key array length != 64");
2593 return;
2594 }
2595
2596 ED25519_keypair(reinterpret_cast<uint8_t*>(outPublic.get()),
2597 reinterpret_cast<uint8_t*>(outPrivate.get()));
2598 JNI_TRACE("ED25519_keypair(%p, %p) => success", outPublicArray, outPrivateArray);
2599 }
2600
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)2601 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
2602 CHECK_ERROR_QUEUE_ON_RETURN;
2603 JNI_TRACE_MD("EVP_MD_CTX_create()");
2604
2605 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_create());
2606 if (ctx.get() == nullptr) {
2607 conscrypt::jniutil::throwOutOfMemory(env, "Unable create a EVP_MD_CTX");
2608 return 0;
2609 }
2610
2611 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
2612 return reinterpret_cast<uintptr_t>(ctx.release());
2613 }
2614
NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv * env,jclass,jobject ctxRef)2615 static void NativeCrypto_EVP_MD_CTX_cleanup(JNIEnv* env, jclass, jobject ctxRef) {
2616 CHECK_ERROR_QUEUE_ON_RETURN;
2617 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2618 JNI_TRACE_MD("EVP_MD_CTX_cleanup(%p)", ctx);
2619
2620 if (ctx != nullptr) {
2621 EVP_MD_CTX_cleanup(ctx);
2622 }
2623 }
2624
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv * env,jclass,jlong ctxRef)2625 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv* env, jclass, jlong ctxRef) {
2626 CHECK_ERROR_QUEUE_ON_RETURN;
2627 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
2628 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
2629
2630 if (ctx != nullptr) {
2631 EVP_MD_CTX_destroy(ctx);
2632 }
2633 }
2634
NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)2635 static jint NativeCrypto_EVP_MD_CTX_copy_ex(JNIEnv* env, jclass, jobject dstCtxRef,
2636 jobject srcCtxRef) {
2637 CHECK_ERROR_QUEUE_ON_RETURN;
2638 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p)", dstCtxRef, srcCtxRef);
2639 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
2640 if (dst_ctx == nullptr) {
2641 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => dst_ctx == null");
2642 return 0;
2643 }
2644 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
2645 if (src_ctx == nullptr) {
2646 JNI_TRACE_MD("EVP_MD_CTX_copy_ex => src_ctx == null");
2647 return 0;
2648 }
2649 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p. %p) <- ptr", dst_ctx, src_ctx);
2650
2651 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
2652 if (result == 0) {
2653 conscrypt::jniutil::throwRuntimeException(env, "Unable to copy EVP_MD_CTX");
2654 ERR_clear_error();
2655 }
2656
2657 JNI_TRACE_MD("EVP_MD_CTX_copy_ex(%p, %p) => %d", dst_ctx, src_ctx, result);
2658 return result;
2659 }
2660
2661 /*
2662 * public static native int EVP_DigestFinal_ex(long, byte[], int)
2663 */
NativeCrypto_EVP_DigestFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)2664 static jint NativeCrypto_EVP_DigestFinal_ex(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
2665 jint offset) {
2666 CHECK_ERROR_QUEUE_ON_RETURN;
2667 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
2668 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d)", ctx, hash, offset);
2669
2670 if (ctx == nullptr) {
2671 JNI_TRACE("EVP_DigestFinal_ex => ctx == null");
2672 return -1;
2673 } else if (hash == nullptr) {
2674 conscrypt::jniutil::throwNullPointerException(env, "hash == null");
2675 return -1;
2676 }
2677
2678 ScopedByteArrayRW hashBytes(env, hash);
2679 if (hashBytes.get() == nullptr) {
2680 return -1;
2681 }
2682 unsigned int bytesWritten = static_cast<unsigned int>(-1);
2683 int ok = EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
2684 &bytesWritten);
2685 if (ok == 0) {
2686 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestFinal_ex");
2687 return -1;
2688 }
2689
2690 JNI_TRACE_MD("EVP_DigestFinal_ex(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
2691 return static_cast<jint>(bytesWritten);
2692 }
2693
NativeCrypto_EVP_DigestInit_ex(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)2694 static jint NativeCrypto_EVP_DigestInit_ex(JNIEnv* env, jclass, jobject evpMdCtxRef,
2695 jlong evpMdRef) {
2696 CHECK_ERROR_QUEUE_ON_RETURN;
2697 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2698 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2699 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p)", ctx, evp_md);
2700
2701 if (ctx == nullptr) {
2702 JNI_TRACE("EVP_DigestInit_ex(%p) => ctx == null", evp_md);
2703 return 0;
2704 } else if (evp_md == nullptr) {
2705 conscrypt::jniutil::throwNullPointerException(env, "evp_md == null");
2706 return 0;
2707 }
2708
2709 int ok = EVP_DigestInit_ex(ctx, evp_md, nullptr);
2710 if (ok == 0) {
2711 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestInit_ex");
2712 JNI_TRACE("EVP_DigestInit_ex(%p) => threw exception", evp_md);
2713 return 0;
2714 }
2715 JNI_TRACE_MD("EVP_DigestInit_ex(%p, %p) => %d", ctx, evp_md, ok);
2716 return ok;
2717 }
2718
2719 /*
2720 * public static native int EVP_get_digestbyname(java.lang.String)
2721 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)2722 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
2723 CHECK_ERROR_QUEUE_ON_RETURN;
2724 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
2725
2726 if (algorithm == nullptr) {
2727 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2728 return -1;
2729 }
2730
2731 ScopedUtfChars algorithmChars(env, algorithm);
2732 if (algorithmChars.c_str() == nullptr) {
2733 return 0;
2734 }
2735 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
2736
2737 const char* alg = algorithmChars.c_str();
2738 const EVP_MD* md;
2739
2740 if (strcasecmp(alg, "md4") == 0) {
2741 md = EVP_md4();
2742 } else if (strcasecmp(alg, "md5") == 0) {
2743 md = EVP_md5();
2744 } else if (strcasecmp(alg, "sha1") == 0) {
2745 md = EVP_sha1();
2746 } else if (strcasecmp(alg, "sha224") == 0) {
2747 md = EVP_sha224();
2748 } else if (strcasecmp(alg, "sha256") == 0) {
2749 md = EVP_sha256();
2750 } else if (strcasecmp(alg, "sha384") == 0) {
2751 md = EVP_sha384();
2752 } else if (strcasecmp(alg, "sha512") == 0) {
2753 md = EVP_sha512();
2754 } else {
2755 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
2756 conscrypt::jniutil::throwRuntimeException(env, "Hash algorithm not found");
2757 return 0;
2758 }
2759
2760 return reinterpret_cast<uintptr_t>(md);
2761 }
2762
2763 /*
2764 * public static native int EVP_MD_size(long)
2765 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)2766 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
2767 CHECK_ERROR_QUEUE_ON_RETURN;
2768 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
2769 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
2770
2771 if (evp_md == nullptr) {
2772 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2773 return -1;
2774 }
2775
2776 jint result = static_cast<jint>(EVP_MD_size(evp_md));
2777 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
2778 return result;
2779 }
2780
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)2781 static jlong evpDigestSignVerifyInit(JNIEnv* env,
2782 int (*init_func)(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*,
2783 ENGINE*, EVP_PKEY*),
2784 const char* jniName, jobject evpMdCtxRef, jlong evpMdRef,
2785 jobject pkeyRef) {
2786 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2787 if (mdCtx == nullptr) {
2788 JNI_TRACE("%s => mdCtx == null", jniName);
2789 return 0;
2790 }
2791 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
2792 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
2793 if (pkey == nullptr) {
2794 JNI_TRACE("ctx=%p %s => pkey == null", mdCtx, jniName);
2795 return 0;
2796 }
2797 JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
2798
2799 // For ED25519, md must be null, see
2800 // https://github.com/google/boringssl/blob/master/include/openssl/evp.h
2801 if (md == nullptr && (EVP_PKEY_id(pkey) != EVP_PKEY_ED25519)) {
2802 JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
2803 conscrypt::jniutil::throwNullPointerException(env, "md == null");
2804 return 0;
2805 }
2806
2807 EVP_PKEY_CTX* pctx = nullptr;
2808 if (init_func(mdCtx, &pctx, md, nullptr, pkey) <= 0) {
2809 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2810 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2811 return 0;
2812 }
2813
2814 JNI_TRACE("%s(%p, %p, %p) => success", jniName, mdCtx, md, pkey);
2815 return reinterpret_cast<jlong>(pctx);
2816 }
2817
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2818 static jlong NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2819 const jlong evpMdRef, jobject pkeyRef) {
2820 CHECK_ERROR_QUEUE_ON_RETURN;
2821 return evpDigestSignVerifyInit(env, EVP_DigestSignInit, "EVP_DigestSignInit", evpMdCtxRef,
2822 evpMdRef, pkeyRef);
2823 }
2824
NativeCrypto_EVP_DigestVerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jobject pkeyRef)2825 static jlong NativeCrypto_EVP_DigestVerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
2826 const jlong evpMdRef, jobject pkeyRef) {
2827 CHECK_ERROR_QUEUE_ON_RETURN;
2828 return evpDigestSignVerifyInit(env, EVP_DigestVerifyInit, "EVP_DigestVerifyInit", evpMdCtxRef,
2829 evpMdRef, pkeyRef);
2830 }
2831
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jlong inPtr,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2832 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jlong inPtr, jint inLength,
2833 const char* jniName, int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2834 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2835 const void* p = reinterpret_cast<const void*>(inPtr);
2836 JNI_TRACE_MD("%s(%p, %p, %d)", jniName, mdCtx, p, inLength);
2837
2838 if (mdCtx == nullptr) {
2839 return;
2840 }
2841
2842 if (p == nullptr) {
2843 conscrypt::jniutil::throwNullPointerException(env, nullptr);
2844 return;
2845 }
2846
2847 if (!update_func(mdCtx, p, static_cast<std::size_t>(inLength))) {
2848 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2849 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2850 return;
2851 }
2852
2853 JNI_TRACE_MD("%s(%p, %p, %d) => success", jniName, mdCtx, p, inLength);
2854 }
2855
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))2856 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
2857 jint inLength, const char* jniName,
2858 int (*update_func)(EVP_MD_CTX*, const void*, size_t)) {
2859 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2860 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2861
2862 if (mdCtx == nullptr) {
2863 return;
2864 }
2865
2866 if (inJavaBytes == nullptr) {
2867 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
2868 return;
2869 }
2870
2871 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
2872 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
2873 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
2874 "inBytes");
2875 return;
2876 }
2877 if (inLength == 0) {
2878 return;
2879 }
2880 jint in_offset = inOffset;
2881 jint in_size = inLength;
2882
2883 int update_func_result = -1;
2884 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
2885 // GetByteArrayElements is expected to return a copy. Use GetByteArrayRegion instead, to
2886 // avoid copying the whole array.
2887 if (in_size <= 1024) {
2888 // For small chunk, it's more efficient to use a bit more space on the stack instead of
2889 // allocating a new buffer.
2890 jbyte buf[1024];
2891 env->GetByteArrayRegion(inJavaBytes, in_offset, in_size, buf);
2892 update_func_result = update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf),
2893 static_cast<size_t>(in_size));
2894 } else {
2895 // For large chunk, allocate a 64 kB buffer and stream the chunk into update_func
2896 // through the buffer, stopping as soon as update_func fails.
2897 jint remaining = in_size;
2898 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
2899 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
2900 if (buf.get() == nullptr) {
2901 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
2902 return;
2903 }
2904 while (remaining > 0) {
2905 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
2906 env->GetByteArrayRegion(inJavaBytes, in_offset, chunk_size, buf.get());
2907 update_func_result =
2908 update_func(mdCtx, reinterpret_cast<const unsigned char*>(buf.get()),
2909 static_cast<size_t>(chunk_size));
2910 if (!update_func_result) {
2911 // update_func failed. This will be handled later in this method.
2912 break;
2913 }
2914 in_offset += chunk_size;
2915 remaining -= chunk_size;
2916 }
2917 }
2918 } else {
2919 // GetByteArrayElements is expected to not return a copy. Use GetByteArrayElements.
2920 // We're not using ScopedByteArrayRO here because its an implementation detail whether it'll
2921 // use GetByteArrayElements or another approach.
2922 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
2923 if (array_elements == nullptr) {
2924 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
2925 return;
2926 }
2927 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
2928 update_func_result = update_func(mdCtx, buf + in_offset, static_cast<size_t>(in_size));
2929 env->ReleaseByteArrayElements(inJavaBytes, array_elements, JNI_ABORT);
2930 }
2931
2932 if (!update_func_result) {
2933 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
2934 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, jniName);
2935 return;
2936 }
2937
2938 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
2939 }
2940
NativeCrypto_EVP_DigestUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2941 static void NativeCrypto_EVP_DigestUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2942 jlong inPtr, jint inLength) {
2943 CHECK_ERROR_QUEUE_ON_RETURN;
2944 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestUpdateDirect", EVP_DigestUpdate);
2945 }
2946
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2947 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2948 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
2949 CHECK_ERROR_QUEUE_ON_RETURN;
2950 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
2951 EVP_DigestUpdate);
2952 }
2953
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2954 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2955 jbyteArray inJavaBytes, jint inOffset,
2956 jint inLength) {
2957 CHECK_ERROR_QUEUE_ON_RETURN;
2958 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
2959 EVP_DigestSignUpdate);
2960 }
2961
NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2962 static void NativeCrypto_EVP_DigestSignUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2963 jlong inPtr, jint inLength) {
2964 CHECK_ERROR_QUEUE_ON_RETURN;
2965 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestSignUpdateDirect",
2966 EVP_DigestSignUpdate);
2967 }
2968
NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)2969 static void NativeCrypto_EVP_DigestVerifyUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
2970 jbyteArray inJavaBytes, jint inOffset,
2971 jint inLength) {
2972 CHECK_ERROR_QUEUE_ON_RETURN;
2973 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestVerifyUpdate",
2974 EVP_DigestVerifyUpdate);
2975 }
2976
NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong inPtr,jint inLength)2977 static void NativeCrypto_EVP_DigestVerifyUpdateDirect(JNIEnv* env, jclass, jobject evpMdCtxRef,
2978 jlong inPtr, jint inLength) {
2979 CHECK_ERROR_QUEUE_ON_RETURN;
2980 evpUpdate(env, evpMdCtxRef, inPtr, inLength, "EVP_DigestVerifyUpdateDirect",
2981 EVP_DigestVerifyUpdate);
2982 }
2983
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)2984 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef) {
2985 CHECK_ERROR_QUEUE_ON_RETURN;
2986 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
2987 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
2988
2989 if (mdCtx == nullptr) {
2990 return nullptr;
2991 }
2992
2993 size_t maxLen;
2994 if (EVP_DigestSignFinal(mdCtx, nullptr, &maxLen) != 1) {
2995 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
2996 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
2997 return nullptr;
2998 }
2999
3000 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
3001 if (buffer.get() == nullptr) {
3002 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
3003 return nullptr;
3004 }
3005 size_t actualLen(maxLen);
3006 if (EVP_DigestSignFinal(mdCtx, buffer.get(), &actualLen) != 1) {
3007 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
3008 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSignFinal");
3009 return nullptr;
3010 }
3011 if (actualLen > maxLen) {
3012 JNI_TRACE("ctx=%p EVP_DigestSignFinal => signature too long: %zd vs %zd", mdCtx, actualLen,
3013 maxLen);
3014 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSignFinal signature too long");
3015 return nullptr;
3016 }
3017
3018 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
3019 if (sigJavaBytes.get() == nullptr) {
3020 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
3021 return nullptr;
3022 }
3023 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
3024 reinterpret_cast<jbyte*>(buffer.get()));
3025
3026 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, sigJavaBytes.get());
3027 return sigJavaBytes.release();
3028 }
3029
NativeCrypto_EVP_DigestVerifyFinal(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint offset,jint len)3030 static jboolean NativeCrypto_EVP_DigestVerifyFinal(JNIEnv* env, jclass, jobject evpMdCtxRef,
3031 jbyteArray signature, jint offset, jint len) {
3032 CHECK_ERROR_QUEUE_ON_RETURN;
3033 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3034 JNI_TRACE("EVP_DigestVerifyFinal(%p)", mdCtx);
3035
3036 if (mdCtx == nullptr) {
3037 return 0;
3038 }
3039
3040 ScopedByteArrayRO sigBytes(env, signature);
3041 if (sigBytes.get() == nullptr) {
3042 return 0;
3043 }
3044
3045 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, offset, len)) {
3046 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3047 "signature");
3048 return 0;
3049 }
3050
3051 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3052 int err = EVP_DigestVerifyFinal(mdCtx, sigBuf + offset, static_cast<size_t>(len));
3053 jboolean result;
3054 if (err == 1) {
3055 // Signature verified
3056 result = 1;
3057 } else if (err == 0) {
3058 // Signature did not verify
3059 result = 0;
3060 } else {
3061 // Error while verifying signature
3062 JNI_TRACE("ctx=%p EVP_DigestVerifyFinal => threw exception", mdCtx);
3063 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerifyFinal");
3064 return 0;
3065 }
3066
3067 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3068 // Clear the error queue to prevent its state from affecting future operations.
3069 ERR_clear_error();
3070
3071 JNI_TRACE("EVP_DigestVerifyFinal(%p) => %d", mdCtx, result);
3072 return result;
3073 }
3074
NativeCrypto_EVP_DigestSign(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)3075 static jbyteArray NativeCrypto_EVP_DigestSign(JNIEnv* env, jclass, jobject evpMdCtxRef,
3076 jbyteArray inJavaBytes, jint inOffset,
3077 jint inLength) {
3078 CHECK_ERROR_QUEUE_ON_RETURN;
3079
3080 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3081 JNI_TRACE_MD("%s(%p, %p, %d, %d)", "EVP_DigestSign", mdCtx, inJavaBytes, inOffset, inLength);
3082
3083 if (mdCtx == nullptr) {
3084 return nullptr;
3085 }
3086
3087 if (inJavaBytes == nullptr) {
3088 conscrypt::jniutil::throwNullPointerException(env, "inBytes");
3089 return nullptr;
3090 }
3091
3092 size_t array_size = static_cast<size_t>(env->GetArrayLength(inJavaBytes));
3093 if (ARRAY_CHUNK_INVALID(array_size, inOffset, inLength)) {
3094 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3095 "inBytes");
3096 return nullptr;
3097 }
3098
3099 jint in_offset = inOffset;
3100 jint in_size = inLength;
3101
3102 jbyte* array_elements = env->GetByteArrayElements(inJavaBytes, nullptr);
3103 if (array_elements == nullptr) {
3104 conscrypt::jniutil::throwOutOfMemory(env, "Unable to obtain elements of inBytes");
3105 return nullptr;
3106 }
3107 const unsigned char* buf = reinterpret_cast<const unsigned char*>(array_elements);
3108 const unsigned char* inStart = buf + in_offset;
3109 size_t inLen = static_cast<size_t>(in_size);
3110
3111 size_t maxLen;
3112 if (EVP_DigestSign(mdCtx, nullptr, &maxLen, inStart, inLen) != 1) {
3113 JNI_TRACE("ctx=%p EVP_DigestSign => threw exception", mdCtx);
3114 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSign");
3115 return nullptr;
3116 }
3117
3118 std::unique_ptr<unsigned char[]> buffer(new unsigned char[maxLen]);
3119 if (buffer.get() == nullptr) {
3120 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate signature buffer");
3121 return nullptr;
3122 }
3123 size_t actualLen(maxLen);
3124 if (EVP_DigestSign(mdCtx, buffer.get(), &actualLen, inStart, inLen) != 1) {
3125 JNI_TRACE("ctx=%p EVP_DigestSign => threw exception", mdCtx);
3126 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestSign");
3127 return nullptr;
3128 }
3129 if (actualLen > maxLen) {
3130 JNI_TRACE("ctx=%p EVP_DigestSign => signature too long: %zd vs %zd", mdCtx, actualLen,
3131 maxLen);
3132 conscrypt::jniutil::throwRuntimeException(env, "EVP_DigestSign signature too long");
3133 return nullptr;
3134 }
3135
3136 ScopedLocalRef<jbyteArray> sigJavaBytes(env, env->NewByteArray(static_cast<jint>(actualLen)));
3137 if (sigJavaBytes.get() == nullptr) {
3138 conscrypt::jniutil::throwOutOfMemory(env, "Failed to allocate signature byte[]");
3139 return nullptr;
3140 }
3141 env->SetByteArrayRegion(sigJavaBytes.get(), 0, static_cast<jint>(actualLen),
3142 reinterpret_cast<jbyte*>(buffer.get()));
3143
3144 JNI_TRACE("EVP_DigestSign(%p) => %p", mdCtx, sigJavaBytes.get());
3145 return sigJavaBytes.release();
3146 }
3147
NativeCrypto_EVP_DigestVerify(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray signature,jint sigOffset,jint sigLen,jbyteArray data,jint dataOffset,jint dataLen)3148 static jboolean NativeCrypto_EVP_DigestVerify(JNIEnv* env, jclass, jobject evpMdCtxRef,
3149 jbyteArray signature, jint sigOffset, jint sigLen,
3150 jbyteArray data, jint dataOffset, jint dataLen) {
3151 CHECK_ERROR_QUEUE_ON_RETURN;
3152 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
3153 JNI_TRACE("EVP_DigestVerify(%p)", mdCtx);
3154
3155 if (mdCtx == nullptr) {
3156 return 0;
3157 }
3158
3159 ScopedByteArrayRO sigBytes(env, signature);
3160 if (sigBytes.get() == nullptr) {
3161 return 0;
3162 }
3163
3164 if (ARRAY_OFFSET_LENGTH_INVALID(sigBytes, sigOffset, sigLen)) {
3165 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3166 "signature");
3167 return 0;
3168 }
3169
3170 ScopedByteArrayRO dataBytes(env, data);
3171 if (dataBytes.get() == nullptr) {
3172 return 0;
3173 }
3174
3175 if (ARRAY_OFFSET_LENGTH_INVALID(dataBytes, dataOffset, dataLen)) {
3176 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "data");
3177 return 0;
3178 }
3179
3180 const unsigned char* sigBuf = reinterpret_cast<const unsigned char*>(sigBytes.get());
3181 const unsigned char* dataBuf = reinterpret_cast<const unsigned char*>(dataBytes.get());
3182 int err = EVP_DigestVerify(mdCtx, sigBuf + sigOffset, static_cast<size_t>(sigLen),
3183 dataBuf + dataOffset, static_cast<size_t>(dataLen));
3184 jboolean result;
3185 if (err == 1) {
3186 // Signature verified
3187 result = 1;
3188 } else if (err == 0) {
3189 // Signature did not verify
3190 result = 0;
3191 } else {
3192 // Error while verifying signature
3193 JNI_TRACE("ctx=%p EVP_DigestVerify => threw exception", mdCtx);
3194 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_DigestVerify");
3195 return 0;
3196 }
3197
3198 // If the signature did not verify, BoringSSL error queue contains an error (BAD_SIGNATURE).
3199 // Clear the error queue to prevent its state from affecting future operations.
3200 ERR_clear_error();
3201
3202 JNI_TRACE("EVP_DigestVerify(%p) => %d", mdCtx, result);
3203 return result;
3204 }
3205
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)3206 static jint evpPkeyEncryptDecrypt(JNIEnv* env,
3207 int (*encrypt_decrypt_func)(EVP_PKEY_CTX*, uint8_t*, size_t*,
3208 const uint8_t*, size_t),
3209 const char* jniName, jobject evpPkeyCtxRef,
3210 jbyteArray outJavaBytes, jint outOffset, jbyteArray inJavaBytes,
3211 jint inOffset, jint inLength) {
3212 EVP_PKEY_CTX* pkeyCtx = fromContextObject<EVP_PKEY_CTX>(env, evpPkeyCtxRef);
3213 JNI_TRACE_MD("%s(%p, %p, %d, %p, %d, %d)", jniName, pkeyCtx, outJavaBytes, outOffset,
3214 inJavaBytes, inOffset, inLength);
3215
3216 if (pkeyCtx == nullptr) {
3217 return 0;
3218 }
3219
3220 ScopedByteArrayRW outBytes(env, outJavaBytes);
3221 if (outBytes.get() == nullptr) {
3222 return 0;
3223 }
3224
3225 ScopedByteArrayRO inBytes(env, inJavaBytes);
3226 if (inBytes.get() == nullptr) {
3227 return 0;
3228 }
3229
3230 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3231 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3232 "outBytes");
3233 return 0;
3234 }
3235
3236 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3237 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3238 "inBytes");
3239 return 0;
3240 }
3241
3242 uint8_t* outBuf = reinterpret_cast<uint8_t*>(outBytes.get());
3243 const uint8_t* inBuf = reinterpret_cast<const uint8_t*>(inBytes.get());
3244 size_t outLength = outBytes.size() - outOffset;
3245 if (!encrypt_decrypt_func(pkeyCtx, outBuf + outOffset, &outLength, inBuf + inOffset,
3246 static_cast<size_t>(inLength))) {
3247 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3248 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3249 env, jniName, conscrypt::jniutil::throwBadPaddingException);
3250 return 0;
3251 }
3252
3253 JNI_TRACE("%s(%p, %p, %d, %p, %d, %d) => success (%zd bytes)", jniName, pkeyCtx, outJavaBytes,
3254 outOffset, inJavaBytes, inOffset, inLength, outLength);
3255 return static_cast<jint>(outLength);
3256 }
3257
NativeCrypto_EVP_PKEY_encrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3258 static jint NativeCrypto_EVP_PKEY_encrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3259 jbyteArray out, jint outOffset, jbyteArray inBytes,
3260 jint inOffset, jint inLength) {
3261 CHECK_ERROR_QUEUE_ON_RETURN;
3262 return evpPkeyEncryptDecrypt(env, EVP_PKEY_encrypt, "EVP_PKEY_encrypt", evpPkeyCtxRef, out,
3263 outOffset, inBytes, inOffset, inLength);
3264 }
3265
NativeCrypto_EVP_PKEY_decrypt(JNIEnv * env,jclass,jobject evpPkeyCtxRef,jbyteArray out,jint outOffset,jbyteArray inBytes,jint inOffset,jint inLength)3266 static jint NativeCrypto_EVP_PKEY_decrypt(JNIEnv* env, jclass, jobject evpPkeyCtxRef,
3267 jbyteArray out, jint outOffset, jbyteArray inBytes,
3268 jint inOffset, jint inLength) {
3269 CHECK_ERROR_QUEUE_ON_RETURN;
3270 return evpPkeyEncryptDecrypt(env, EVP_PKEY_decrypt, "EVP_PKEY_decrypt", evpPkeyCtxRef, out,
3271 outOffset, inBytes, inOffset, inLength);
3272 }
3273
evpPkeyEcryptDecryptInit(JNIEnv * env,jobject evpPkeyRef,int (* real_func)(EVP_PKEY_CTX *),const char * opType)3274 static jlong evpPkeyEcryptDecryptInit(JNIEnv* env, jobject evpPkeyRef,
3275 int (*real_func)(EVP_PKEY_CTX*), const char* opType) {
3276 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, evpPkeyRef);
3277 JNI_TRACE("EVP_PKEY_%s_init(%p)", opType, pkey);
3278 if (pkey == nullptr) {
3279 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkey == null", opType, pkey);
3280 return 0;
3281 }
3282
3283 bssl::UniquePtr<EVP_PKEY_CTX> pkeyCtx(EVP_PKEY_CTX_new(pkey, nullptr));
3284 if (pkeyCtx.get() == nullptr) {
3285 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3286 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3287 env, "EVP_PKEY_CTX_new", conscrypt::jniutil::throwInvalidKeyException);
3288 return 0;
3289 }
3290
3291 if (!real_func(pkeyCtx.get())) {
3292 JNI_TRACE("EVP_PKEY_%s_init(%p) => threw exception", opType, pkey);
3293 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3294 env, opType, conscrypt::jniutil::throwInvalidKeyException);
3295 return 0;
3296 }
3297
3298 JNI_TRACE("EVP_PKEY_%s_init(%p) => pkeyCtx=%p", opType, pkey, pkeyCtx.get());
3299 return reinterpret_cast<uintptr_t>(pkeyCtx.release());
3300 }
3301
NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3302 static jlong NativeCrypto_EVP_PKEY_encrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3303 CHECK_ERROR_QUEUE_ON_RETURN;
3304 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_encrypt_init, "encrypt");
3305 }
3306
NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv * env,jclass,jobject evpPkeyRef)3307 static jlong NativeCrypto_EVP_PKEY_decrypt_init(JNIEnv* env, jclass, jobject evpPkeyRef) {
3308 CHECK_ERROR_QUEUE_ON_RETURN;
3309 return evpPkeyEcryptDecryptInit(env, evpPkeyRef, EVP_PKEY_decrypt_init, "decrypt");
3310 }
3311
NativeCrypto_EVP_PKEY_CTX_free(JNIEnv * env,jclass,jlong pkeyCtxRef)3312 static void NativeCrypto_EVP_PKEY_CTX_free(JNIEnv* env, jclass, jlong pkeyCtxRef) {
3313 CHECK_ERROR_QUEUE_ON_RETURN;
3314 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3315 JNI_TRACE("EVP_PKEY_CTX_free(%p)", pkeyCtx);
3316
3317 if (pkeyCtx != nullptr) {
3318 EVP_PKEY_CTX_free(pkeyCtx);
3319 }
3320 }
3321
NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv * env,jclass,jlong ctx,jint pad)3322 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_padding(JNIEnv* env, jclass, jlong ctx, jint pad) {
3323 CHECK_ERROR_QUEUE_ON_RETURN;
3324 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3325 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d)", pkeyCtx, pad);
3326 if (pkeyCtx == nullptr) {
3327 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3328 return;
3329 }
3330
3331 int result = EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, static_cast<int>(pad));
3332 if (result <= 0) {
3333 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_padding => threw exception", pkeyCtx);
3334 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3335 env, "EVP_PKEY_CTX_set_rsa_padding",
3336 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3337 return;
3338 }
3339
3340 JNI_TRACE("EVP_PKEY_CTX_set_rsa_padding(%p, %d) => success", pkeyCtx, pad);
3341 }
3342
NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv * env,jclass,jlong ctx,jint len)3343 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(JNIEnv* env, jclass, jlong ctx,
3344 jint len) {
3345 CHECK_ERROR_QUEUE_ON_RETURN;
3346 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(ctx);
3347 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d)", pkeyCtx, len);
3348 if (pkeyCtx == nullptr) {
3349 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
3350 return;
3351 }
3352
3353 int result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, static_cast<int>(len));
3354 if (result <= 0) {
3355 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_pss_saltlen => threw exception", pkeyCtx);
3356 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3357 env, "EVP_PKEY_CTX_set_rsa_pss_saltlen",
3358 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3359 return;
3360 }
3361
3362 JNI_TRACE("EVP_PKEY_CTX_set_rsa_pss_saltlen(%p, %d) => success", pkeyCtx, len);
3363 }
3364
evpPkeyCtxCtrlMdOp(JNIEnv * env,jlong pkeyCtxRef,jlong mdRef,const char * jniName,int (* ctrl_func)(EVP_PKEY_CTX *,const EVP_MD *))3365 static void evpPkeyCtxCtrlMdOp(JNIEnv* env, jlong pkeyCtxRef, jlong mdRef, const char* jniName,
3366 int (*ctrl_func)(EVP_PKEY_CTX*, const EVP_MD*)) {
3367 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3368 EVP_MD* md = reinterpret_cast<EVP_MD*>(mdRef);
3369 JNI_TRACE("%s(%p, %p)", jniName, pkeyCtx, md);
3370 if (pkeyCtx == nullptr) {
3371 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3372 return;
3373 }
3374 if (md == nullptr) {
3375 conscrypt::jniutil::throwNullPointerException(env, "md == null");
3376 return;
3377 }
3378
3379 int result = ctrl_func(pkeyCtx, md);
3380 if (result <= 0) {
3381 JNI_TRACE("ctx=%p %s => threw exception", pkeyCtx, jniName);
3382 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3383 env, jniName, conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3384 return;
3385 }
3386
3387 JNI_TRACE("%s(%p, %p) => success", jniName, pkeyCtx, md);
3388 }
3389
NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3390 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3391 jlong mdRef) {
3392 CHECK_ERROR_QUEUE_ON_RETURN;
3393 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_mgf1_md",
3394 EVP_PKEY_CTX_set_rsa_mgf1_md);
3395 }
3396
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv * env,jclass,jlong pkeyCtxRef,jlong mdRef)3397 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_md(JNIEnv* env, jclass, jlong pkeyCtxRef,
3398 jlong mdRef) {
3399 CHECK_ERROR_QUEUE_ON_RETURN;
3400 evpPkeyCtxCtrlMdOp(env, pkeyCtxRef, mdRef, "EVP_PKEY_CTX_set_rsa_oaep_md",
3401 EVP_PKEY_CTX_set_rsa_oaep_md);
3402 }
3403
NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv * env,jclass,jlong pkeyCtxRef,jbyteArray labelJava)3404 static void NativeCrypto_EVP_PKEY_CTX_set_rsa_oaep_label(JNIEnv* env, jclass, jlong pkeyCtxRef,
3405 jbyteArray labelJava) {
3406 CHECK_ERROR_QUEUE_ON_RETURN;
3407 EVP_PKEY_CTX* pkeyCtx = reinterpret_cast<EVP_PKEY_CTX*>(pkeyCtxRef);
3408 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p)", pkeyCtx, labelJava);
3409 if (pkeyCtx == nullptr) {
3410 conscrypt::jniutil::throwNullPointerException(env, "pkeyCtx == null");
3411 return;
3412 }
3413
3414 ScopedByteArrayRO labelBytes(env, labelJava);
3415 if (labelBytes.get() == nullptr) {
3416 return;
3417 }
3418
3419 bssl::UniquePtr<uint8_t> label(reinterpret_cast<uint8_t*>(OPENSSL_malloc(labelBytes.size())));
3420 memcpy(label.get(), labelBytes.get(), labelBytes.size());
3421
3422 int result = EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, label.get(), labelBytes.size());
3423 if (result <= 0) {
3424 JNI_TRACE("ctx=%p EVP_PKEY_CTX_set_rsa_oaep_label => threw exception", pkeyCtx);
3425 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3426 env, "EVP_PKEY_CTX_set_rsa_oaep_label",
3427 conscrypt::jniutil::throwInvalidAlgorithmParameterException);
3428 return;
3429 }
3430 OWNERSHIP_TRANSFERRED(label);
3431
3432 JNI_TRACE("EVP_PKEY_CTX_set_rsa_oaep_label(%p, %p) => success", pkeyCtx, labelJava);
3433 }
3434
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)3435 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
3436 CHECK_ERROR_QUEUE_ON_RETURN;
3437 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
3438
3439 if (algorithm == nullptr) {
3440 conscrypt::jniutil::throwNullPointerException(env, "algorithm == null");
3441 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm == null", algorithm);
3442 return -1;
3443 }
3444
3445 ScopedUtfChars scoped_alg(env, algorithm);
3446 const char* alg = scoped_alg.c_str();
3447 const EVP_CIPHER* cipher;
3448
3449 if (strcasecmp(alg, "rc4") == 0) {
3450 cipher = EVP_rc4();
3451 } else if (strcasecmp(alg, "des-cbc") == 0) {
3452 cipher = EVP_des_cbc();
3453 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
3454 cipher = EVP_des_ede_cbc();
3455 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
3456 cipher = EVP_des_ede3_cbc();
3457 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
3458 cipher = EVP_aes_128_ecb();
3459 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
3460 cipher = EVP_aes_128_cbc();
3461 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
3462 cipher = EVP_aes_128_ctr();
3463 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
3464 cipher = EVP_aes_128_gcm();
3465 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
3466 cipher = EVP_aes_192_ecb();
3467 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
3468 cipher = EVP_aes_192_cbc();
3469 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
3470 cipher = EVP_aes_192_ctr();
3471 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
3472 cipher = EVP_aes_192_gcm();
3473 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
3474 cipher = EVP_aes_256_ecb();
3475 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
3476 cipher = EVP_aes_256_cbc();
3477 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
3478 cipher = EVP_aes_256_ctr();
3479 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
3480 cipher = EVP_aes_256_gcm();
3481 } else {
3482 JNI_TRACE("NativeCrypto_EVP_get_cipherbyname(%s) => error", alg);
3483 return 0;
3484 }
3485
3486 return reinterpret_cast<uintptr_t>(cipher);
3487 }
3488
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jobject ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)3489 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
3490 jbyteArray keyArray, jbyteArray ivArray,
3491 jboolean encrypting) {
3492 CHECK_ERROR_QUEUE_ON_RETURN;
3493 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3494 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3495 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
3496 encrypting ? 1 : 0);
3497
3498 if (ctx == nullptr) {
3499 JNI_TRACE("EVP_CipherUpdate => ctx == null");
3500 return;
3501 }
3502
3503 // The key can be null if we need to set extra parameters.
3504 std::unique_ptr<unsigned char[]> keyPtr;
3505 if (keyArray != nullptr) {
3506 ScopedByteArrayRO keyBytes(env, keyArray);
3507 if (keyBytes.get() == nullptr) {
3508 return;
3509 }
3510
3511 keyPtr.reset(new unsigned char[keyBytes.size()]);
3512 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
3513 }
3514
3515 // The IV can be null if we're using ECB.
3516 std::unique_ptr<unsigned char[]> ivPtr;
3517 if (ivArray != nullptr) {
3518 ScopedByteArrayRO ivBytes(env, ivArray);
3519 if (ivBytes.get() == nullptr) {
3520 return;
3521 }
3522
3523 ivPtr.reset(new unsigned char[ivBytes.size()]);
3524 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
3525 }
3526
3527 if (!EVP_CipherInit_ex(ctx, evpCipher, nullptr, keyPtr.get(), ivPtr.get(),
3528 encrypting ? 1 : 0)) {
3529 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherInit_ex");
3530 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
3531 return;
3532 }
3533
3534 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
3535 encrypting ? 1 : 0);
3536 }
3537
3538 /*
3539 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
3540 * int inOffset, int inLength);
3541 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)3542 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
3543 jint outOffset, jbyteArray inArray, jint inOffset,
3544 jint inLength) {
3545 CHECK_ERROR_QUEUE_ON_RETURN;
3546 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3547 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
3548
3549 if (ctx == nullptr) {
3550 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
3551 return 0;
3552 }
3553
3554 ScopedByteArrayRO inBytes(env, inArray);
3555 if (inBytes.get() == nullptr) {
3556 return 0;
3557 }
3558 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3559 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3560 "inBytes");
3561 return 0;
3562 }
3563
3564 ScopedByteArrayRW outBytes(env, outArray);
3565 if (outBytes.get() == nullptr) {
3566 return 0;
3567 }
3568 if (ARRAY_OFFSET_LENGTH_INVALID(outBytes, outOffset, inLength)) {
3569 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
3570 "outBytes");
3571 return 0;
3572 }
3573
3574 JNI_TRACE(
3575 "ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%d inLength=%d out=%p "
3576 "out.length=%zd outOffset=%d",
3577 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(),
3578 outOffset);
3579
3580 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3581 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
3582
3583 int outl;
3584 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
3585 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherUpdate");
3586 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
3587 return 0;
3588 }
3589
3590 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
3591 inOffset, outl);
3592 return outl;
3593 }
3594
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jobject ctxRef,jbyteArray outArray,jint outOffset)3595 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
3596 jbyteArray outArray, jint outOffset) {
3597 CHECK_ERROR_QUEUE_ON_RETURN;
3598 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3599 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
3600
3601 if (ctx == nullptr) {
3602 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
3603 return 0;
3604 }
3605
3606 ScopedByteArrayRW outBytes(env, outArray);
3607 if (outBytes.get() == nullptr) {
3608 return 0;
3609 }
3610
3611 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
3612
3613 int outl;
3614 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
3615 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_CipherFinal_ex",
3616 conscrypt::jniutil::throwBadPaddingException);
3617 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
3618 return 0;
3619 }
3620
3621 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
3622 return outl;
3623 }
3624
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)3625 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
3626 CHECK_ERROR_QUEUE_ON_RETURN;
3627 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
3628 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
3629
3630 if (evpCipher == nullptr) {
3631 conscrypt::jniutil::throwNullPointerException(env, "evpCipher == null");
3632 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
3633 return 0;
3634 }
3635
3636 jint ivLength = static_cast<jint>(EVP_CIPHER_iv_length(evpCipher));
3637 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
3638 return ivLength;
3639 }
3640
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)3641 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
3642 CHECK_ERROR_QUEUE_ON_RETURN;
3643 JNI_TRACE("EVP_CIPHER_CTX_new()");
3644
3645 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
3646 if (ctx.get() == nullptr) {
3647 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate cipher context");
3648 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
3649 return 0;
3650 }
3651
3652 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
3653 return reinterpret_cast<uintptr_t>(ctx.release());
3654 }
3655
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jobject ctxRef)3656 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
3657 CHECK_ERROR_QUEUE_ON_RETURN;
3658 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3659 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
3660
3661 if (ctx == nullptr) {
3662 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
3663 return 0;
3664 }
3665
3666 jint blockSize = static_cast<jint>(EVP_CIPHER_CTX_block_size(ctx));
3667 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
3668 return blockSize;
3669 }
3670
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jobject ctxRef)3671 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
3672 CHECK_ERROR_QUEUE_ON_RETURN;
3673 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3674 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
3675
3676 if (ctx == nullptr) {
3677 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
3678 return 0;
3679 }
3680
3681 int buf_len = ctx->buf_len;
3682 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
3683 return buf_len;
3684 }
3685
NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv * env,jclass,jobject ctxRef)3686 static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
3687 CHECK_ERROR_QUEUE_ON_RETURN;
3688 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3689 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
3690
3691 if (ctx == nullptr) {
3692 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
3693 return 0;
3694 }
3695
3696 bool final_used = ctx->final_used != 0;
3697 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
3698 return static_cast<jboolean>(final_used);
3699 }
3700
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jobject ctxRef,jboolean enablePaddingBool)3701 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
3702 jboolean enablePaddingBool) {
3703 CHECK_ERROR_QUEUE_ON_RETURN;
3704 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3705 jint enablePadding = enablePaddingBool ? 1 : 0;
3706 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
3707
3708 if (ctx == nullptr) {
3709 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
3710 return;
3711 }
3712
3713 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
3714 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
3715 }
3716
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jobject ctxRef,jint keySizeBits)3717 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
3718 jint keySizeBits) {
3719 CHECK_ERROR_QUEUE_ON_RETURN;
3720 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
3721 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
3722
3723 if (ctx == nullptr) {
3724 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
3725 return;
3726 }
3727
3728 if (!EVP_CIPHER_CTX_set_key_length(ctx, static_cast<unsigned int>(keySizeBits))) {
3729 conscrypt::jniutil::throwExceptionFromBoringSSLError(
3730 env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
3731 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
3732 return;
3733 }
3734 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
3735 }
3736
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv * env,jclass,jlong ctxRef)3737 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv* env, jclass, jlong ctxRef) {
3738 CHECK_ERROR_QUEUE_ON_RETURN;
3739 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
3740 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
3741
3742 EVP_CIPHER_CTX_free(ctx);
3743 }
3744
NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv * env,jclass)3745 static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
3746 CHECK_ERROR_QUEUE_ON_RETURN;
3747 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
3748 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
3749 return reinterpret_cast<jlong>(ctx);
3750 }
3751
NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv * env,jclass)3752 static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
3753 CHECK_ERROR_QUEUE_ON_RETURN;
3754 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
3755 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
3756 return reinterpret_cast<jlong>(ctx);
3757 }
3758
NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv * env,jclass)3759 static jlong NativeCrypto_EVP_aead_chacha20_poly1305(JNIEnv* env, jclass) {
3760 CHECK_ERROR_QUEUE_ON_RETURN;
3761 const EVP_AEAD* ctx = EVP_aead_chacha20_poly1305();
3762 JNI_TRACE("EVP_aead_chacha20_poly1305 => ctx=%p", ctx);
3763 return reinterpret_cast<jlong>(ctx);
3764 }
3765
NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv * env,jclass)3766 static jlong NativeCrypto_EVP_aead_aes_128_gcm_siv(JNIEnv* env, jclass) {
3767 CHECK_ERROR_QUEUE_ON_RETURN;
3768 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm_siv();
3769 JNI_TRACE("EVP_aead_aes_128_gcm_siv => ctx=%p", ctx);
3770 return reinterpret_cast<jlong>(ctx);
3771 }
3772
NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv * env,jclass)3773 static jlong NativeCrypto_EVP_aead_aes_256_gcm_siv(JNIEnv* env, jclass) {
3774 CHECK_ERROR_QUEUE_ON_RETURN;
3775 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm_siv();
3776 JNI_TRACE("EVP_aead_aes_256_gcm_siv => ctx=%p", ctx);
3777 return reinterpret_cast<jlong>(ctx);
3778 }
3779
NativeCrypto_EVP_AEAD_max_overhead(JNIEnv * env,jclass,jlong evpAeadRef)3780 static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
3781 CHECK_ERROR_QUEUE_ON_RETURN;
3782 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3783 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
3784 if (evpAead == nullptr) {
3785 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3786 return 0;
3787 }
3788 jint maxOverhead = static_cast<jint>(EVP_AEAD_max_overhead(evpAead));
3789 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
3790 return maxOverhead;
3791 }
3792
NativeCrypto_EVP_AEAD_nonce_length(JNIEnv * env,jclass,jlong evpAeadRef)3793 static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
3794 CHECK_ERROR_QUEUE_ON_RETURN;
3795 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3796 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
3797 if (evpAead == nullptr) {
3798 conscrypt::jniutil::throwNullPointerException(env, "evpAead == null");
3799 return 0;
3800 }
3801 jint nonceLength = static_cast<jint>(EVP_AEAD_nonce_length(evpAead));
3802 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
3803 return nonceLength;
3804 }
3805
3806 typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX* ctx, uint8_t* out, size_t* out_len,
3807 size_t max_out_len, const uint8_t* nonce, size_t nonce_len,
3808 const uint8_t* in, size_t in_len, const uint8_t* ad,
3809 size_t ad_len);
3810
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)3811 static jint evp_aead_ctx_op_common(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3812 uint8_t* outBuf, jbyteArray nonceArray,
3813 const uint8_t* inBuf, jbyteArray aadArray,
3814 evp_aead_ctx_op_func realFunc, jobject inBuffer, jobject outBuffer, jint outRange, jint inRange) {
3815 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3816
3817 ScopedByteArrayRO keyBytes(env, keyArray);
3818 if (keyBytes.get() == nullptr) {
3819 return 0;
3820 }
3821
3822 std::unique_ptr<ScopedByteArrayRO> aad;
3823 const uint8_t* aad_chars = nullptr;
3824 size_t aad_chars_size = 0;
3825 if (aadArray != nullptr) {
3826 aad.reset(new ScopedByteArrayRO(env, aadArray));
3827 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
3828 if (aad_chars == nullptr) {
3829 return 0;
3830 }
3831 aad_chars_size = aad->size();
3832 }
3833
3834 ScopedByteArrayRO nonceBytes(env, nonceArray);
3835 if (nonceBytes.get() == nullptr) {
3836 return 0;
3837 }
3838
3839 bssl::ScopedEVP_AEAD_CTX aeadCtx;
3840 const uint8_t* keyTmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
3841 if (!EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, keyTmp, keyBytes.size(),
3842 static_cast<size_t>(tagLen), nullptr)) {
3843 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
3844 "failure initializing AEAD context");
3845 JNI_TRACE(
3846 "evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => fail EVP_AEAD_CTX_init",
3847 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3848 aadArray);
3849 return 0;
3850 }
3851
3852 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
3853 size_t actualOutLength;
3854
3855 if (!realFunc(aeadCtx.get(), outBuf, &actualOutLength, outRange,
3856 nonceTmp, nonceBytes.size(), inBuf, static_cast<size_t>(inRange),
3857 aad_chars, aad_chars_size)) {
3858 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "evp_aead_ctx_op");
3859 return 0;
3860 }
3861
3862 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p) => success outlength=%zd",
3863 evpAead, keyArray, tagLen, outBuffer, nonceArray, inBuffer,
3864 aadArray, actualOutLength);
3865 return static_cast<jint>(actualOutLength);
3866 }
3867
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)3868 static jint evp_aead_ctx_op(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3869 jbyteArray outArray, jint outOffset, jbyteArray nonceArray,
3870 jbyteArray inArray, jint inOffset, jint inLength, jbyteArray aadArray,
3871 evp_aead_ctx_op_func realFunc) {
3872 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3873 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p)", evpAead, keyArray, tagLen,
3874 outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray);
3875
3876
3877 ScopedByteArrayRW outBytes(env, outArray);
3878 if (outBytes.get() == nullptr) {
3879 return 0;
3880 }
3881
3882 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
3883 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => out offset invalid",
3884 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3885 inLength, aadArray);
3886 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
3887 return 0;
3888 }
3889
3890 ScopedByteArrayRO inBytes(env, inArray);
3891 if (inBytes.get() == nullptr) {
3892 return 0;
3893 }
3894
3895 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
3896 JNI_TRACE(
3897 "evp_aead_ctx_op(%p, %p, %d, %p, %d, %p, %p, %d, %d, %p) => in offset/length "
3898 "invalid",
3899 evpAead, keyArray, tagLen, outArray, outOffset, nonceArray, inArray, inOffset,
3900 inLength, aadArray);
3901 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
3902 return 0;
3903 }
3904
3905 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
3906 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
3907
3908 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outTmp + outOffset, nonceArray, inTmp + inOffset,
3909 aadArray, realFunc, inArray, outArray, outBytes.size() - outOffset, inLength);
3910 }
3911
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)3912 static jint evp_aead_ctx_op_buf(JNIEnv* env, jlong evpAeadRef, jbyteArray keyArray, jint tagLen,
3913 jobject outBuffer, jbyteArray nonceArray,
3914 jobject inBuffer, jbyteArray aadArray,
3915 evp_aead_ctx_op_func realFunc) {
3916
3917 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
3918 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %p, %p)", evpAead, keyArray, tagLen,
3919 outBuffer, nonceArray, inBuffer, aadArray);
3920
3921 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, inBuffer)) {
3922 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3923 "inBuffer is not a direct ByteBuffer");
3924 return 0;
3925 }
3926
3927 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, outBuffer)) {
3928 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
3929 "outBuffer is not a direct ByteBuffer");
3930 return 0;
3931 }
3932
3933 uint8_t* inBuf;
3934 jint in_limit;
3935 jint in_position;
3936
3937 inBuf = (uint8_t*)(env->GetDirectBufferAddress(inBuffer));
3938 // limit is the index of the first element that should not be read or written
3939 in_limit = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_limitMethod);
3940 // position is the index of the next element to be read or written
3941 in_position = env->CallIntMethod(inBuffer,conscrypt::jniutil::buffer_positionMethod);
3942
3943 uint8_t* outBuf;
3944 jint out_limit;
3945 jint out_position;
3946 outBuf = (uint8_t*)(env->GetDirectBufferAddress(outBuffer));
3947 // limit is the index of the first element that should not be read or written
3948 out_limit = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_limitMethod);
3949 // position is the index of the next element to be read or written
3950 out_position = env->CallIntMethod(outBuffer,conscrypt::jniutil::buffer_positionMethod);
3951
3952 // Shifting over of ByteBuffer address to start at true position
3953 inBuf += in_position;
3954 outBuf += out_position;
3955
3956 size_t inSize = in_limit - in_position;
3957 uint8_t* outBufEnd = outBuf + out_limit - out_position;
3958 uint8_t* inBufEnd = inBuf + inSize;
3959 std::unique_ptr<uint8_t[]> inCopy;
3960 if (outBufEnd >= inBuf && inBufEnd >= outBuf) { // We have an overlap
3961 inCopy.reset((new(std::nothrow) uint8_t[inSize]));
3962 if (inCopy.get() == nullptr) {
3963 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate new buffer for overlap");
3964 return 0;
3965 }
3966 memcpy(inCopy.get(), inBuf, inSize);
3967 inBuf = inCopy.get();
3968 }
3969
3970 return evp_aead_ctx_op_common(env, evpAeadRef, keyArray, tagLen, outBuf, nonceArray, inBuf, aadArray, realFunc,
3971 inBuffer, outBuffer, out_limit-out_position, in_limit-in_position);
3972 }
3973
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)3974 static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jlong evpAeadRef,
3975 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3976 jint outOffset, jbyteArray nonceArray,
3977 jbyteArray inArray, jint inOffset, jint inLength,
3978 jbyteArray aadArray) {
3979 CHECK_ERROR_QUEUE_ON_RETURN;
3980 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3981 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_seal);
3982 }
3983
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)3984 static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jlong evpAeadRef,
3985 jbyteArray keyArray, jint tagLen, jbyteArray outArray,
3986 jint outOffset, jbyteArray nonceArray,
3987 jbyteArray inArray, jint inOffset, jint inLength,
3988 jbyteArray aadArray) {
3989 CHECK_ERROR_QUEUE_ON_RETURN;
3990 return evp_aead_ctx_op(env, evpAeadRef, keyArray, tagLen, outArray, outOffset, nonceArray,
3991 inArray, inOffset, inLength, aadArray, EVP_AEAD_CTX_open);
3992 }
3993
NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)3994 static jint NativeCrypto_EVP_AEAD_CTX_seal_buf(JNIEnv* env, jclass, jlong evpAeadRef,
3995 jbyteArray keyArray, jint tagLen, jobject outBuffer,
3996 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
3997 CHECK_ERROR_QUEUE_ON_RETURN;
3998 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
3999 inBuffer, aadArray, EVP_AEAD_CTX_seal);
4000 }
4001
NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv * env,jclass,jlong evpAeadRef,jbyteArray keyArray,jint tagLen,jobject outBuffer,jbyteArray nonceArray,jobject inBuffer,jbyteArray aadArray)4002 static jint NativeCrypto_EVP_AEAD_CTX_open_buf(JNIEnv* env, jclass, jlong evpAeadRef,
4003 jbyteArray keyArray, jint tagLen, jobject outBuffer,
4004 jbyteArray nonceArray, jobject inBuffer, jbyteArray aadArray) {
4005 CHECK_ERROR_QUEUE_ON_RETURN;
4006 return evp_aead_ctx_op_buf(env, evpAeadRef, keyArray, tagLen, outBuffer, nonceArray,
4007 inBuffer, aadArray, EVP_AEAD_CTX_open);
4008 }
4009
NativeCrypto_EVP_HPKE_CTX_export(JNIEnv * env,jclass,jobject hpkeCtxRef,jbyteArray exporterCtxArray,jint exportedLen)4010 static jbyteArray NativeCrypto_EVP_HPKE_CTX_export(JNIEnv* env, jclass, jobject hpkeCtxRef,
4011 jbyteArray exporterCtxArray, jint exportedLen) {
4012 CHECK_ERROR_QUEUE_ON_RETURN;
4013 EVP_HPKE_CTX* hpkeCtx = fromContextObject<EVP_HPKE_CTX>(env, hpkeCtxRef);
4014 JNI_TRACE("EVP_HPKE_CTX_export(%p, %p, %d)", hpkeCtx, exporterCtxArray, exportedLen);
4015
4016 if (hpkeCtx == nullptr) {
4017 // NullPointerException thrown while calling fromContextObject
4018 return {};
4019 }
4020
4021 std::optional<ScopedByteArrayRO> optionalExporterCtx;
4022 const uint8_t* exporterCtx = nullptr;
4023 size_t exporterCtxLen = 0;
4024 if (exporterCtxArray != nullptr) {
4025 optionalExporterCtx.emplace(env, exporterCtxArray);
4026 exporterCtx = reinterpret_cast<const uint8_t*>(optionalExporterCtx->get());
4027 if (exporterCtx == nullptr) {
4028 return {};
4029 }
4030 exporterCtxLen = optionalExporterCtx->size();
4031 }
4032
4033 std::vector<uint8_t> exported(exportedLen);
4034 if (!EVP_HPKE_CTX_export(/* ctx= */ hpkeCtx,
4035 /* out= */ exported.data(),
4036 /* secret_len= */ exportedLen,
4037 /* context= */ exporterCtx,
4038 /* context_len= */ exporterCtxLen)) {
4039 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_export");
4040 return {};
4041 }
4042
4043 ScopedLocalRef<jbyteArray> exportedArray(env, env->NewByteArray(static_cast<jsize>(exportedLen)));
4044 if (exportedArray.get() == nullptr) {
4045 return {};
4046 }
4047 ScopedByteArrayRW exportedBytes(env, exportedArray.get());
4048 if (exportedBytes.get() == nullptr) {
4049 return {};
4050 }
4051 memcpy(exportedBytes.get(), reinterpret_cast<const jbyte*>(exported.data()), exportedLen);
4052 return exportedArray.release();
4053 }
4054
NativeCrypto_EVP_HPKE_CTX_free(JNIEnv * env,jclass,jlong hpkeCtxRef)4055 static void NativeCrypto_EVP_HPKE_CTX_free(JNIEnv* env, jclass, jlong hpkeCtxRef) {
4056 CHECK_ERROR_QUEUE_ON_RETURN;
4057 EVP_HPKE_CTX* ctx = reinterpret_cast<EVP_HPKE_CTX*>(hpkeCtxRef);
4058 JNI_TRACE("EVP_HPKE_CTX_free(%p)", ctx);
4059 if (ctx == nullptr) {
4060 conscrypt::jniutil::throwNullPointerException(env, "ctx == null");
4061 return;
4062 }
4063 EVP_HPKE_CTX_free(ctx);
4064 }
4065
NativeCrypto_EVP_HPKE_CTX_open(JNIEnv * env,jclass,jobject recipientHpkeCtxRef,jbyteArray ciphertextArray,jbyteArray aadArray)4066 static jbyteArray NativeCrypto_EVP_HPKE_CTX_open(JNIEnv* env, jclass, jobject recipientHpkeCtxRef,
4067 jbyteArray ciphertextArray, jbyteArray aadArray) {
4068 CHECK_ERROR_QUEUE_ON_RETURN;
4069 EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, recipientHpkeCtxRef);
4070 JNI_TRACE("EVP_HPKE_CTX_open(%p, %p, %p)", ctx, ciphertextArray, aadArray);
4071
4072 if (ctx == nullptr) {
4073 // NullPointerException thrown while calling fromContextObject
4074 return {};
4075 }
4076
4077 if (ciphertextArray == nullptr) {
4078 conscrypt::jniutil::throwNullPointerException(env, "ciphertextArray == null");
4079 return {};
4080 }
4081
4082 ScopedByteArrayRO ciphertext(env, ciphertextArray);
4083 if (ciphertext.get() == nullptr) {
4084 return {};
4085 }
4086
4087 std::optional<ScopedByteArrayRO> optionalAad;
4088 const uint8_t* aad = nullptr;
4089 size_t aadLen = 0;
4090 if (aadArray != nullptr) {
4091 optionalAad.emplace(env, aadArray);
4092 aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
4093 if (aad == nullptr) {
4094 return {};
4095 }
4096 aadLen = optionalAad->size();
4097 }
4098
4099 size_t plaintextLen;
4100 std::vector<uint8_t> plaintext(ciphertext.size());
4101 if (!EVP_HPKE_CTX_open(/* ctx= */ ctx,
4102 /* out= */ plaintext.data(),
4103 /* out_len= */ &plaintextLen,
4104 /* max_out_len= */ plaintext.size(),
4105 /* in= */ reinterpret_cast<const uint8_t*>(ciphertext.get()),
4106 /* in_len= */ ciphertext.size(),
4107 /* aad= */ aad,
4108 /* aad_len= */ aadLen)) {
4109 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_open");
4110 return {};
4111 }
4112
4113 plaintext.resize(plaintextLen);
4114 ScopedLocalRef<jbyteArray> plaintextArray(env, env->NewByteArray(static_cast<jsize>(plaintextLen)));
4115 if (plaintextArray.get() == nullptr) {
4116 return {};
4117 }
4118 ScopedByteArrayRW plaintextBytes(env, plaintextArray.get());
4119 if (plaintextBytes.get() == nullptr) {
4120 return {};
4121 }
4122 memcpy(plaintextBytes.get(), reinterpret_cast<const jbyte*>(plaintext.data()), plaintextLen);
4123 return plaintextArray.release();
4124 }
4125
NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv * env,jclass,jobject senderHpkeCtxRef,jbyteArray plaintextArray,jbyteArray aadArray)4126 static jbyteArray NativeCrypto_EVP_HPKE_CTX_seal(JNIEnv* env, jclass, jobject senderHpkeCtxRef,
4127 jbyteArray plaintextArray, jbyteArray aadArray) {
4128 CHECK_ERROR_QUEUE_ON_RETURN;
4129 EVP_HPKE_CTX* ctx = fromContextObject<EVP_HPKE_CTX>(env, senderHpkeCtxRef);
4130 JNI_TRACE("EVP_HPKE_CTX_seal(%p, %p, %p)", ctx, plaintextArray, aadArray);
4131
4132 if (ctx == nullptr) {
4133 // NullPointerException thrown while calling fromContextObject
4134 return {};
4135 }
4136
4137 if (plaintextArray == nullptr) {
4138 conscrypt::jniutil::throwNullPointerException(env, "plaintextArray == null");
4139 return {};
4140 }
4141
4142 std::optional<ScopedByteArrayRO> optionalAad;
4143 const uint8_t* aad = nullptr;
4144 size_t aadLen = 0;
4145 if (aadArray != nullptr) {
4146 optionalAad.emplace(env, aadArray);
4147 aad = reinterpret_cast<const uint8_t*>(optionalAad->get());
4148 if (aad == nullptr) {
4149 return {};
4150 }
4151 aadLen = optionalAad->size();
4152 }
4153
4154 ScopedByteArrayRO plaintext(env, plaintextArray);
4155 std::vector<uint8_t> encrypted(env->GetArrayLength(plaintextArray) +
4156 EVP_HPKE_CTX_max_overhead(ctx));
4157 size_t encryptedLen;
4158 if (!EVP_HPKE_CTX_seal(/* ctx= */ ctx,
4159 /* out= */ encrypted.data(),
4160 /* out_len= */ &encryptedLen,
4161 /* max_out_len= */ encrypted.size(),
4162 /* in= */ reinterpret_cast<const uint8_t*>(plaintext.get()),
4163 /* in_len= */ plaintext.size(),
4164 /* aad= */ aad,
4165 /* aad_len= */ aadLen)) {
4166 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_seal");
4167 return {};
4168 }
4169
4170 ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(static_cast<jsize>(encryptedLen)));
4171 if (ciphertextArray.get() == nullptr) {
4172 return {};
4173 }
4174 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
4175 if (ciphertextBytes.get() == nullptr) {
4176 return {};
4177 }
4178 memcpy(ciphertextBytes.get(), reinterpret_cast<const jbyte*>(encrypted.data()), encryptedLen);
4179 return ciphertextArray.release();
4180 }
4181
getHpkeAead(JNIEnv * env,jint aeadValue)4182 const EVP_HPKE_AEAD* getHpkeAead(JNIEnv* env, jint aeadValue) {
4183 switch (aeadValue) {
4184 case EVP_HPKE_AES_128_GCM:
4185 return EVP_hpke_aes_128_gcm();
4186 case EVP_HPKE_AES_256_GCM:
4187 return EVP_hpke_aes_256_gcm();
4188 case EVP_HPKE_CHACHA20_POLY1305:
4189 return EVP_hpke_chacha20_poly1305();
4190 default:
4191 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4192 "AEAD is not supported");
4193 return nullptr;
4194 }
4195 }
4196
getHpkeKdf(JNIEnv * env,jint kdfValue)4197 const EVP_HPKE_KDF* getHpkeKdf(JNIEnv* env, jint kdfValue) {
4198 if (kdfValue == EVP_HPKE_HKDF_SHA256) {
4199 return EVP_hpke_hkdf_sha256();
4200 } else {
4201 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4202 "KDF is not supported");
4203 return nullptr;
4204 }
4205 }
4206
getHpkeKem(JNIEnv * env,jint kemValue)4207 const EVP_HPKE_KEM* getHpkeKem(JNIEnv* env, jint kemValue) {
4208 if (kemValue == EVP_HPKE_DHKEM_X25519_HKDF_SHA256) {
4209 return EVP_hpke_x25519_hkdf_sha256();
4210 } else {
4211 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4212 "KEM is not supported");
4213 return nullptr;
4214 }
4215 }
4216
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray privateKeyArray,jbyteArray encArray,jbyteArray infoArray)4217 static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv* env, jclass,
4218 jint kemValue,jint kdfValue,
4219 jint aeadValue,
4220 jbyteArray privateKeyArray,
4221 jbyteArray encArray,
4222 jbyteArray infoArray) {
4223 CHECK_ERROR_QUEUE_ON_RETURN;
4224 JNI_TRACE("EVP_HPKE_CTX_setup_recipient(%d, %d, %d, %p, %p, %p)", kemValue, kdfValue, aeadValue,
4225 privateKeyArray, encArray, infoArray);
4226
4227 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4228 if (kem == nullptr) {
4229 return nullptr;
4230 }
4231 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4232 if (kdf == nullptr) {
4233 return nullptr;
4234 }
4235 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4236 if (aead == nullptr) {
4237 return nullptr;
4238 }
4239 if (privateKeyArray == nullptr) {
4240 conscrypt::jniutil::throwNullPointerException(env, "privateKeyArray == null");
4241 return nullptr;
4242 }
4243 if (encArray == nullptr) {
4244 conscrypt::jniutil::throwNullPointerException(env, "encArray == null");
4245 return nullptr;
4246 }
4247
4248 ScopedByteArrayRO privateKey(env, privateKeyArray);
4249
4250 bssl::ScopedEVP_HPKE_KEY key;
4251
4252 if (!EVP_HPKE_KEY_init(/* key= */ key.get(),
4253 /* kem= */ kem,
4254 /* priv_key= */ reinterpret_cast<const uint8_t*>(privateKey.get()),
4255 /* priv_key_len= */ privateKey.size())) {
4256 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4257 return nullptr;
4258 }
4259
4260 std::optional<ScopedByteArrayRO> optionalInfo;
4261 const uint8_t* info = nullptr;
4262 size_t infoLen = 0;
4263 if (infoArray != nullptr) {
4264 optionalInfo.emplace(env, infoArray);
4265 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4266 if (info == nullptr) {
4267 return {};
4268 }
4269 infoLen = optionalInfo->size();
4270 }
4271
4272 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4273 ScopedByteArrayRO enc(env, encArray);
4274 if (!EVP_HPKE_CTX_setup_recipient(/* ctx= */ ctx.get(),
4275 /* key= */ key.get(),
4276 /* kdf= */ kdf,
4277 /* aead= */ aead,
4278 /* enc= */ reinterpret_cast<const uint8_t*>(enc.get()),
4279 /* enc_len= */ enc.size(),
4280 /* info= */ info,
4281 /* info_len= */ infoLen)) {
4282 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_recipient");
4283 return nullptr;
4284 }
4285
4286 ScopedLocalRef<jobject> ctxObject(
4287 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4288 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4289 reinterpret_cast<jlong>(ctx.release())));
4290 return ctxObject.release();
4291 }
4292
NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv * env,jclass,jint kemValue,jint kdfValue,jint aeadValue,jbyteArray publicKeyArray,jbyteArray infoArray)4293 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass,
4294 jint kemValue,jint kdfValue,
4295 jint aeadValue,
4296 jbyteArray publicKeyArray,
4297 jbyteArray infoArray) {
4298 CHECK_ERROR_QUEUE_ON_RETURN;
4299 JNI_TRACE("EVP_HPKE_CTX_setup_sender(%d, %d, %d, %p, %p)", kemValue, kdfValue, aeadValue,
4300 publicKeyArray, infoArray);
4301
4302 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4303 if (kem == nullptr) {
4304 return nullptr;
4305 }
4306 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4307 if (kdf == nullptr) {
4308 return nullptr;
4309 }
4310 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4311 if (aead == nullptr) {
4312 return nullptr;
4313 }
4314 if (publicKeyArray == nullptr) {
4315 conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray == null");
4316 return {};
4317 }
4318
4319 std::optional<ScopedByteArrayRO> optionalInfo;
4320 const uint8_t* info = nullptr;
4321 size_t infoLen = 0;
4322 if (infoArray != nullptr) {
4323 optionalInfo.emplace(env, infoArray);
4324 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4325 if (info == nullptr) {
4326 return {};
4327 }
4328 infoLen = optionalInfo->size();
4329 }
4330
4331 ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4332
4333 size_t encapsulatedSharedSecretLen;
4334 uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4335
4336 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4337
4338 if (!EVP_HPKE_CTX_setup_sender(/* ctx= */ ctx.get(),
4339 /* out_enc= */ encapsulatedSharedSecret,
4340 /* out_enc_len= */ &encapsulatedSharedSecretLen,
4341 /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4342 /* kem= */ kem,
4343 /* kdf= */ kdf,
4344 /* aead= */ aead,
4345 /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4346 /* peer_public_key_len= */ peer_public_key.size(),
4347 /* info= */ info,
4348 /* info_len= */ infoLen)) {
4349 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_HPKE_CTX_setup_sender");
4350 return {};
4351 }
4352
4353 ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4354 if (encArray.get() == nullptr) {
4355 return {};
4356 }
4357 ScopedByteArrayRW encBytes(env, encArray.get());
4358 if (encBytes.get() == nullptr) {
4359 return {};
4360 }
4361 memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4362
4363 ScopedLocalRef<jobjectArray> result(
4364 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4365
4366 ScopedLocalRef<jobject> ctxObject(
4367 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4368 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4369 reinterpret_cast<jlong>(ctx.release())));
4370
4371 env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4372 env->SetObjectArrayElement(result.get(), 1, encArray.release());
4373
4374 return result.release();
4375 }
4376
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)4377 static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(
4378 JNIEnv* env, jclass, jint kemValue, jint kdfValue, jint aeadValue,
4379 jbyteArray publicKeyArray, jbyteArray infoArray, jbyteArray seedArray) {
4380 CHECK_ERROR_QUEUE_ON_RETURN;
4381 JNI_TRACE("EVP_HPKE_CTX_setup_sender_with_seed_for_testing(%d, %d, %d, %p, %p, %p)", kemValue,
4382 kdfValue, aeadValue, publicKeyArray, infoArray, seedArray);
4383
4384 const EVP_HPKE_KEM* kem = getHpkeKem(env, kemValue);
4385 if (kem == nullptr) {
4386 return nullptr;
4387 }
4388 const EVP_HPKE_KDF* kdf = getHpkeKdf(env, kdfValue);
4389 if (kdf == nullptr) {
4390 return nullptr;
4391 }
4392 const EVP_HPKE_AEAD* aead = getHpkeAead(env, aeadValue);
4393 if (aead == nullptr) {
4394 return nullptr;
4395 }
4396 if (publicKeyArray == nullptr || seedArray == nullptr) {
4397 conscrypt::jniutil::throwNullPointerException(env, "publicKeyArray or seedArray == null");
4398 return {};
4399 }
4400
4401 std::optional<ScopedByteArrayRO> optionalInfo;
4402 const uint8_t* info = nullptr;
4403 size_t infoLen = 0;
4404 if (infoArray != nullptr) {
4405 optionalInfo.emplace(env, infoArray);
4406 info = reinterpret_cast<const uint8_t*>(optionalInfo->get());
4407 if (info == nullptr) {
4408 return {};
4409 }
4410 infoLen = optionalInfo->size();
4411 }
4412
4413 ScopedByteArrayRO peer_public_key(env, publicKeyArray);
4414
4415 ScopedByteArrayRO seed(env, seedArray);
4416
4417 size_t encapsulatedSharedSecretLen;
4418 uint8_t encapsulatedSharedSecret[EVP_HPKE_MAX_ENC_LENGTH];
4419
4420 bssl::UniquePtr<EVP_HPKE_CTX> ctx(EVP_HPKE_CTX_new());
4421
4422 if (!EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
4423 /* ctx= */ ctx.get(),
4424 /* out_enc= */ encapsulatedSharedSecret,
4425 /* out_enc_len= */ &encapsulatedSharedSecretLen,
4426 /* max_enc= */ EVP_HPKE_MAX_ENC_LENGTH,
4427 /* kem= */ kem,
4428 /* kdf= */ kdf,
4429 /* aead= */ aead,
4430 /* peer_public_key= */ reinterpret_cast<const uint8_t*>(peer_public_key.get()),
4431 /* peer_public_key_len= */ peer_public_key.size(),
4432 /* info= */ info,
4433 /* info_len= */ infoLen,
4434 /* seed= */ reinterpret_cast<const uint8_t*>(seed.get()),
4435 /* seed_len= */ seed.size())) {
4436 conscrypt::jniutil::throwExceptionFromBoringSSLError(
4437 env, "EVP_HPKE_CTX_setup_sender_with_seed_for_testing");
4438 return {};
4439 }
4440
4441 ScopedLocalRef<jbyteArray> encArray(env, env->NewByteArray(static_cast<jsize>(encapsulatedSharedSecretLen)));
4442 if (encArray.get() == nullptr) {
4443 return {};
4444 }
4445 ScopedByteArrayRW encBytes(env, encArray.get());
4446 if (encBytes.get() == nullptr) {
4447 return {};
4448 }
4449 memcpy(encBytes.get(), reinterpret_cast<const jbyte*>(encapsulatedSharedSecret), encapsulatedSharedSecretLen);
4450
4451 ScopedLocalRef<jobjectArray> result(
4452 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
4453
4454 ScopedLocalRef<jobject> ctxObject(
4455 env, env->NewObject(conscrypt::jniutil::nativeRefHpkeCtxClass,
4456 conscrypt::jniutil::nativeRefHpkeCtxClass_constructor,
4457 reinterpret_cast<jlong>(ctx.release())));
4458
4459 env->SetObjectArrayElement(result.get(), 0, ctxObject.release());
4460 env->SetObjectArrayElement(result.get(), 1, encArray.release());
4461
4462 return result.release();
4463 }
4464
NativeCrypto_CMAC_CTX_new(JNIEnv * env,jclass)4465 static jlong NativeCrypto_CMAC_CTX_new(JNIEnv* env, jclass) {
4466 CHECK_ERROR_QUEUE_ON_RETURN;
4467 JNI_TRACE("CMAC_CTX_new");
4468 auto cmacCtx = CMAC_CTX_new();
4469 if (cmacCtx == nullptr) {
4470 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate CMAC_CTX");
4471 return 0;
4472 }
4473
4474 return reinterpret_cast<jlong>(cmacCtx);
4475 }
4476
NativeCrypto_CMAC_CTX_free(JNIEnv * env,jclass,jlong cmacCtxRef)4477 static void NativeCrypto_CMAC_CTX_free(JNIEnv* env, jclass, jlong cmacCtxRef) {
4478 CHECK_ERROR_QUEUE_ON_RETURN;
4479 CMAC_CTX* cmacCtx = reinterpret_cast<CMAC_CTX*>(cmacCtxRef);
4480 JNI_TRACE("CMAC_CTX_free(%p)", cmacCtx);
4481 if (cmacCtx == nullptr) {
4482 conscrypt::jniutil::throwNullPointerException(env, "cmacCtx == null");
4483 return;
4484 }
4485 CMAC_CTX_free(cmacCtx);
4486 }
4487
NativeCrypto_CMAC_Init(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray keyArray)4488 static void NativeCrypto_CMAC_Init(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray keyArray) {
4489 CHECK_ERROR_QUEUE_ON_RETURN;
4490 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4491 JNI_TRACE("CMAC_Init(%p, %p)", cmacCtx, keyArray);
4492 if (cmacCtx == nullptr) {
4493 return;
4494 }
4495 ScopedByteArrayRO keyBytes(env, keyArray);
4496 if (keyBytes.get() == nullptr) {
4497 return;
4498 }
4499
4500 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4501
4502 const EVP_CIPHER *cipher;
4503 switch(keyBytes.size()) {
4504 case 16:
4505 cipher = EVP_aes_128_cbc();
4506 break;
4507 case 24:
4508 cipher = EVP_aes_192_cbc();
4509 break;
4510 case 32:
4511 cipher = EVP_aes_256_cbc();
4512 break;
4513 default:
4514 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
4515 "CMAC_Init: Unsupported key length");
4516 return;
4517 }
4518
4519 if (!CMAC_Init(cmacCtx, keyPtr, keyBytes.size(), cipher, nullptr)) {
4520 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Init");
4521 JNI_TRACE("CMAC_Init(%p, %p) => fail CMAC_Init_ex", cmacCtx, keyArray);
4522 return;
4523 }
4524 }
4525
NativeCrypto_CMAC_UpdateDirect(JNIEnv * env,jclass,jobject cmacCtxRef,jlong inPtr,int inLength)4526 static void NativeCrypto_CMAC_UpdateDirect(JNIEnv* env, jclass, jobject cmacCtxRef, jlong inPtr,
4527 int inLength) {
4528 CHECK_ERROR_QUEUE_ON_RETURN;
4529 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4530 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4531 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d)", cmacCtx, p, inLength);
4532
4533 if (cmacCtx == nullptr) {
4534 return;
4535 }
4536
4537 if (p == nullptr) {
4538 conscrypt::jniutil::throwNullPointerException(env, nullptr);
4539 return;
4540 }
4541
4542 if (!CMAC_Update(cmacCtx, p, static_cast<size_t>(inLength))) {
4543 JNI_TRACE("CMAC_UpdateDirect(%p, %p, %d) => threw exception", cmacCtx, p, inLength);
4544 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_UpdateDirect");
4545 return;
4546 }
4547 }
4548
NativeCrypto_CMAC_Update(JNIEnv * env,jclass,jobject cmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4549 static void NativeCrypto_CMAC_Update(JNIEnv* env, jclass, jobject cmacCtxRef, jbyteArray inArray,
4550 jint inOffset, jint inLength) {
4551 CHECK_ERROR_QUEUE_ON_RETURN;
4552 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4553 JNI_TRACE("CMAC_Update(%p, %p, %d, %d)", cmacCtx, inArray, inOffset, inLength);
4554
4555 if (cmacCtx == nullptr) {
4556 return;
4557 }
4558
4559 ScopedByteArrayRO inBytes(env, inArray);
4560 if (inBytes.get() == nullptr) {
4561 return;
4562 }
4563
4564 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4565 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4566 "inBytes");
4567 return;
4568 }
4569
4570 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4571
4572 if (!CMAC_Update(cmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4573 JNI_TRACE("CMAC_Update(%p, %p, %d, %d) => threw exception", cmacCtx, inArray, inOffset,
4574 inLength);
4575 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Update");
4576 return;
4577 }
4578 }
4579
NativeCrypto_CMAC_Final(JNIEnv * env,jclass,jobject cmacCtxRef)4580 static jbyteArray NativeCrypto_CMAC_Final(JNIEnv* env, jclass, jobject cmacCtxRef) {
4581 CHECK_ERROR_QUEUE_ON_RETURN;
4582 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4583 JNI_TRACE("CMAC_Final(%p)", cmacCtx);
4584
4585 if (cmacCtx == nullptr) {
4586 return nullptr;
4587 }
4588
4589 uint8_t result[EVP_MAX_MD_SIZE];
4590 size_t len;
4591 if (!CMAC_Final(cmacCtx, result, &len)) {
4592 JNI_TRACE("CMAC_Final(%p) => threw exception", cmacCtx);
4593 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Final");
4594 return nullptr;
4595 }
4596
4597 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4598 if (resultArray.get() == nullptr) {
4599 return nullptr;
4600 }
4601 ScopedByteArrayRW resultBytes(env, resultArray.get());
4602 if (resultBytes.get() == nullptr) {
4603 return nullptr;
4604 }
4605 memcpy(resultBytes.get(), result, len);
4606 return resultArray.release();
4607 }
4608
NativeCrypto_CMAC_Reset(JNIEnv * env,jclass,jobject cmacCtxRef)4609 static void NativeCrypto_CMAC_Reset(JNIEnv* env, jclass, jobject cmacCtxRef) {
4610 CHECK_ERROR_QUEUE_ON_RETURN;
4611 CMAC_CTX* cmacCtx = fromContextObject<CMAC_CTX>(env, cmacCtxRef);
4612 JNI_TRACE("CMAC_Reset(%p)", cmacCtx);
4613
4614 if (cmacCtx == nullptr) {
4615 return;
4616 }
4617
4618 if (!CMAC_Reset(cmacCtx)) {
4619 JNI_TRACE("CMAC_Reset(%p) => threw exception", cmacCtx);
4620 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "CMAC_Reset");
4621 return;
4622 }
4623 }
4624
NativeCrypto_HMAC_CTX_new(JNIEnv * env,jclass)4625 static jlong NativeCrypto_HMAC_CTX_new(JNIEnv* env, jclass) {
4626 CHECK_ERROR_QUEUE_ON_RETURN;
4627 JNI_TRACE("HMAC_CTX_new");
4628 auto hmacCtx = HMAC_CTX_new();
4629 if (hmacCtx == nullptr) {
4630 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate HMAC_CTX");
4631 return 0;
4632 }
4633
4634 return reinterpret_cast<jlong>(hmacCtx);
4635 }
4636
NativeCrypto_HMAC_CTX_free(JNIEnv * env,jclass,jlong hmacCtxRef)4637 static void NativeCrypto_HMAC_CTX_free(JNIEnv* env, jclass, jlong hmacCtxRef) {
4638 CHECK_ERROR_QUEUE_ON_RETURN;
4639 HMAC_CTX* hmacCtx = reinterpret_cast<HMAC_CTX*>(hmacCtxRef);
4640 JNI_TRACE("HMAC_CTX_free(%p)", hmacCtx);
4641 if (hmacCtx == nullptr) {
4642 conscrypt::jniutil::throwNullPointerException(env, "hmacCtx == null");
4643 return;
4644 }
4645 HMAC_CTX_free(hmacCtx);
4646 }
4647
NativeCrypto_HMAC_Init_ex(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray keyArray,jobject evpMdRef)4648 static void NativeCrypto_HMAC_Init_ex(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray keyArray,
4649 jobject evpMdRef) {
4650 CHECK_ERROR_QUEUE_ON_RETURN;
4651 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4652 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4653 JNI_TRACE("HMAC_Init_ex(%p, %p, %p)", hmacCtx, keyArray, md);
4654 if (hmacCtx == nullptr) {
4655 return;
4656 }
4657 ScopedByteArrayRO keyBytes(env, keyArray);
4658 if (keyBytes.get() == nullptr) {
4659 return;
4660 }
4661
4662 const uint8_t* keyPtr = reinterpret_cast<const uint8_t*>(keyBytes.get());
4663 if (!HMAC_Init_ex(hmacCtx, keyPtr, keyBytes.size(), md, nullptr)) {
4664 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4665 JNI_TRACE("HMAC_Init_ex(%p, %p, %p) => fail HMAC_Init_ex", hmacCtx, keyArray, md);
4666 return;
4667 }
4668 }
4669
NativeCrypto_HMAC_UpdateDirect(JNIEnv * env,jclass,jobject hmacCtxRef,jlong inPtr,int inLength)4670 static void NativeCrypto_HMAC_UpdateDirect(JNIEnv* env, jclass, jobject hmacCtxRef, jlong inPtr,
4671 int inLength) {
4672 CHECK_ERROR_QUEUE_ON_RETURN;
4673 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4674 const uint8_t* p = reinterpret_cast<const uint8_t*>(inPtr);
4675 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d)", hmacCtx, p, inLength);
4676
4677 if (hmacCtx == nullptr) {
4678 return;
4679 }
4680
4681 if (p == nullptr) {
4682 conscrypt::jniutil::throwNullPointerException(env, nullptr);
4683 return;
4684 }
4685
4686 if (!HMAC_Update(hmacCtx, p, static_cast<size_t>(inLength))) {
4687 JNI_TRACE("HMAC_UpdateDirect(%p, %p, %d) => threw exception", hmacCtx, p, inLength);
4688 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_UpdateDirect");
4689 return;
4690 }
4691 }
4692
NativeCrypto_HMAC_Update(JNIEnv * env,jclass,jobject hmacCtxRef,jbyteArray inArray,jint inOffset,jint inLength)4693 static void NativeCrypto_HMAC_Update(JNIEnv* env, jclass, jobject hmacCtxRef, jbyteArray inArray,
4694 jint inOffset, jint inLength) {
4695 CHECK_ERROR_QUEUE_ON_RETURN;
4696 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4697 JNI_TRACE("HMAC_Update(%p, %p, %d, %d)", hmacCtx, inArray, inOffset, inLength);
4698
4699 if (hmacCtx == nullptr) {
4700 return;
4701 }
4702
4703 ScopedByteArrayRO inBytes(env, inArray);
4704 if (inBytes.get() == nullptr) {
4705 return;
4706 }
4707
4708 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
4709 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
4710 "inBytes");
4711 return;
4712 }
4713
4714 const uint8_t* inPtr = reinterpret_cast<const uint8_t*>(inBytes.get());
4715 if (!HMAC_Update(hmacCtx, inPtr + inOffset, static_cast<size_t>(inLength))) {
4716 JNI_TRACE("HMAC_Update(%p, %p, %d, %d) => threw exception", hmacCtx, inArray, inOffset,
4717 inLength);
4718 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Update");
4719 return;
4720 }
4721 }
4722
NativeCrypto_HMAC_Final(JNIEnv * env,jclass,jobject hmacCtxRef)4723 static jbyteArray NativeCrypto_HMAC_Final(JNIEnv* env, jclass, jobject hmacCtxRef) {
4724 CHECK_ERROR_QUEUE_ON_RETURN;
4725 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4726 JNI_TRACE("HMAC_Final(%p)", hmacCtx);
4727
4728 if (hmacCtx == nullptr) {
4729 return nullptr;
4730 }
4731
4732 uint8_t result[EVP_MAX_MD_SIZE];
4733 unsigned len;
4734 if (!HMAC_Final(hmacCtx, result, &len)) {
4735 JNI_TRACE("HMAC_Final(%p) => threw exception", hmacCtx);
4736 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Final");
4737 return nullptr;
4738 }
4739
4740 ScopedLocalRef<jbyteArray> resultArray(env, env->NewByteArray(static_cast<jsize>(len)));
4741 if (resultArray.get() == nullptr) {
4742 return nullptr;
4743 }
4744 ScopedByteArrayRW resultBytes(env, resultArray.get());
4745 if (resultBytes.get() == nullptr) {
4746 return nullptr;
4747 }
4748 memcpy(resultBytes.get(), result, len);
4749 return resultArray.release();
4750 }
4751
NativeCrypto_HMAC_Reset(JNIEnv * env,jclass,jobject hmacCtxRef)4752 static void NativeCrypto_HMAC_Reset(JNIEnv* env, jclass, jobject hmacCtxRef) {
4753 CHECK_ERROR_QUEUE_ON_RETURN;
4754 HMAC_CTX* hmacCtx = fromContextObject<HMAC_CTX>(env, hmacCtxRef);
4755 JNI_TRACE("HMAC_Reset(%p)", hmacCtx);
4756
4757 if (hmacCtx == nullptr) {
4758 return;
4759 }
4760
4761 // HMAC_Init_ex with all nulls will reuse the existing key. This is slightly
4762 // more efficient than re-initializing the context with the key again.
4763 if (!HMAC_Init_ex(hmacCtx, /*key=*/nullptr, /*key_len=*/0, /*md=*/nullptr, /*impl=*/nullptr)) {
4764 JNI_TRACE("HMAC_Reset(%p) => threw exception", hmacCtx);
4765 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "HMAC_Init_ex");
4766 return;
4767 }
4768 }
4769
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4770 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4771 CHECK_ERROR_QUEUE_ON_RETURN;
4772 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4773
4774 ScopedByteArrayRW outputBytes(env, output);
4775 if (outputBytes.get() == nullptr) {
4776 return;
4777 }
4778
4779 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4780 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4781 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "NativeCrypto_RAND_bytes");
4782 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4783 return;
4784 }
4785
4786 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4787 }
4788
ASN1_OBJECT_to_OID_string(JNIEnv * env,const ASN1_OBJECT * obj)4789 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
4790 /*
4791 * The OBJ_obj2txt API doesn't "measure" if you pass in nullptr as the buffer.
4792 * Just make a buffer that's large enough here. The documentation recommends
4793 * 80 characters.
4794 */
4795 char output[128];
4796 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4797 if (ret < 0) {
4798 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "ASN1_OBJECT_to_OID_string");
4799 return nullptr;
4800 } else if (size_t(ret) >= sizeof(output)) {
4801 conscrypt::jniutil::throwRuntimeException(env,
4802 "ASN1_OBJECT_to_OID_string buffer too small");
4803 return nullptr;
4804 }
4805
4806 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4807 return env->NewStringUTF(output);
4808 }
4809
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj,jboolean isFinite)4810 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj,
4811 jboolean isFinite) {
4812 CHECK_ERROR_QUEUE_ON_RETURN;
4813 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4814
4815 if (streamObj == nullptr) {
4816 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4817 return 0;
4818 }
4819
4820 const BIO_METHOD *method = stream_bio_method();
4821 if (!method) {
4822 return 0;
4823 }
4824 bssl::UniquePtr<BIO> bio(BIO_new(method));
4825 if (bio.get() == nullptr) {
4826 return 0;
4827 }
4828
4829 bio_stream_assign(bio.get(), new BioInputStream(streamObj, isFinite == JNI_TRUE));
4830
4831 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4832 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4833 }
4834
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4835 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4836 CHECK_ERROR_QUEUE_ON_RETURN;
4837 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4838
4839 if (streamObj == nullptr) {
4840 conscrypt::jniutil::throwNullPointerException(env, "stream == null");
4841 return 0;
4842 }
4843
4844 const BIO_METHOD *method = stream_bio_method();
4845 if (!method) {
4846 return 0;
4847 }
4848 bssl::UniquePtr<BIO> bio(BIO_new(method));
4849 if (bio.get() == nullptr) {
4850 return 0;
4851 }
4852
4853 bio_stream_assign(bio.get(), new BioOutputStream(streamObj));
4854
4855 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4856 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4857 }
4858
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4859 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4860 CHECK_ERROR_QUEUE_ON_RETURN;
4861 BIO* bio = to_BIO(env, bioRef);
4862 JNI_TRACE("BIO_free_all(%p)", bio);
4863
4864 if (bio == nullptr) {
4865 return;
4866 }
4867
4868 BIO_free_all(bio);
4869 }
4870
4871 // NOLINTNEXTLINE(runtime/int)
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4872 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4873 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4874
4875 bssl::UniquePtr<BIO> buffer(BIO_new(BIO_s_mem()));
4876 if (buffer.get() == nullptr) {
4877 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate BIO");
4878 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4879 return nullptr;
4880 }
4881
4882 /* Don't interpret the string. */
4883 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4884
4885 /* Write in given format and null terminate. */
4886 X509_NAME_print_ex(buffer.get(), name, 0, flags);
4887 BIO_write(buffer.get(), "\0", 1);
4888
4889 char* tmp;
4890 BIO_get_mem_data(buffer.get(), &tmp);
4891 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4892 return env->NewStringUTF(tmp);
4893 }
4894
4895 /**
4896 * Converts GENERAL_NAME items to the output format expected in
4897 * X509Certificate#getSubjectAlternativeNames and
4898 * X509Certificate#getIssuerAlternativeNames return.
4899 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4900 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4901 switch (gen->type) {
4902 case GEN_EMAIL:
4903 case GEN_DNS:
4904 case GEN_URI: {
4905 // This must be a valid IA5String and must not contain NULs.
4906 // BoringSSL does not currently enforce the former (see
4907 // https://crbug.com/boringssl/427). The latter was historically an
4908 // issue for parsers that truncate at NUL.
4909 const uint8_t* data = ASN1_STRING_get0_data(gen->d.ia5);
4910 ssize_t len = ASN1_STRING_length(gen->d.ia5);
4911 std::vector<jchar> jchars;
4912 jchars.reserve(len);
4913 for (ssize_t i = 0; i < len; i++) {
4914 if (data[i] == 0 || data[i] > 127) {
4915 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4916 return nullptr;
4917 }
4918 // Converting ASCII to UTF-16 is the identity function.
4919 jchars.push_back(data[i]);
4920 }
4921 JNI_TRACE("GENERAL_NAME_to_jobject(%p)=> Email/DNS/URI \"%.*s\"", gen, (int) len, data);
4922 return env->NewString(jchars.data(), jchars.size());
4923 }
4924 case GEN_DIRNAME:
4925 /* Write in RFC 2253 format */
4926 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4927 case GEN_IPADD: {
4928 #ifdef _WIN32
4929 void* ip = reinterpret_cast<void*>(gen->d.ip->data);
4930 #else
4931 const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
4932 #endif
4933 if (gen->d.ip->length == 4) {
4934 // IPv4
4935 std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4936 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
4937 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4938 return env->NewStringUTF(buffer.get());
4939 } else {
4940 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
4941 strerror(errno));
4942 }
4943 } else if (gen->d.ip->length == 16) {
4944 // IPv6
4945 std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4946 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
4947 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4948 return env->NewStringUTF(buffer.get());
4949 } else {
4950 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen,
4951 strerror(errno));
4952 }
4953 }
4954
4955 /* Invalid IP encodings are pruned out without throwing an exception. */
4956 return nullptr;
4957 }
4958 case GEN_RID:
4959 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4960 case GEN_OTHERNAME:
4961 case GEN_X400:
4962 default:
4963 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
4964 }
4965
4966 return nullptr;
4967 }
4968
4969 #define GN_STACK_SUBJECT_ALT_NAME 1
4970 #define GN_STACK_ISSUER_ALT_NAME 2
4971
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint type)4972 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4973 CONSCRYPT_UNUSED jobject holder,
4974 jint type) {
4975 CHECK_ERROR_QUEUE_ON_RETURN;
4976 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4977 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4978
4979 if (x509 == nullptr) {
4980 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
4981 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4982 return nullptr;
4983 }
4984
4985 bssl::UniquePtr<STACK_OF(GENERAL_NAME)> gn_stack;
4986 if (type == GN_STACK_SUBJECT_ALT_NAME) {
4987 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4988 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)));
4989 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4990 gn_stack.reset(static_cast<STACK_OF(GENERAL_NAME)*>(
4991 X509_get_ext_d2i(x509, NID_issuer_alt_name, nullptr, nullptr)));
4992 } else {
4993 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4994 return nullptr;
4995 }
4996 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
4997 // |ERR_clear_error|, and throw CertificateParsingException.
4998 if (gn_stack == nullptr) {
4999 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no extension or error)", x509, type);
5000 ERR_clear_error();
5001 return nullptr;
5002 }
5003
5004 int count = static_cast<int>(sk_GENERAL_NAME_num(gn_stack.get()));
5005 if (count <= 0) {
5006 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
5007 return nullptr;
5008 }
5009
5010 /*
5011 * Keep track of how many originally so we can ignore any invalid
5012 * values later.
5013 */
5014 const int origCount = count;
5015
5016 ScopedLocalRef<jobjectArray> joa(
5017 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
5018 for (int i = 0, j = 0; i < origCount; i++, j++) {
5019 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack.get(), static_cast<size_t>(i));
5020 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
5021 if (env->ExceptionCheck()) {
5022 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
5023 x509, type);
5024 return nullptr;
5025 }
5026
5027 /*
5028 * If it's nullptr, we'll have to skip this, reduce the number of total
5029 * entries, and fix up the array later.
5030 */
5031 if (val.get() == nullptr) {
5032 j--;
5033 count--;
5034 continue;
5035 }
5036
5037 ScopedLocalRef<jobjectArray> item(
5038 env, env->NewObjectArray(2, conscrypt::jniutil::objectClass, nullptr));
5039
5040 ScopedLocalRef<jobject> parsedType(
5041 env,
5042 env->CallStaticObjectMethod(conscrypt::jniutil::integerClass,
5043 conscrypt::jniutil::integer_valueOfMethod, gen->type));
5044 env->SetObjectArrayElement(item.get(), 0, parsedType.get());
5045 env->SetObjectArrayElement(item.get(), 1, val.get());
5046
5047 env->SetObjectArrayElement(joa.get(), j, item.get());
5048 }
5049
5050 if (count == 0) {
5051 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning nullptr",
5052 x509, type, origCount);
5053 joa.reset(nullptr);
5054 } else if (origCount != count) {
5055 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, origCount,
5056 count);
5057
5058 ScopedLocalRef<jobjectArray> joa_copy(
5059 env, env->NewObjectArray(count, conscrypt::jniutil::objectArrayClass, nullptr));
5060
5061 for (int i = 0; i < count; i++) {
5062 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
5063 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
5064 }
5065
5066 joa.reset(joa_copy.release());
5067 }
5068
5069 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
5070 return joa.release();
5071 }
5072
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5073 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
5074 CONSCRYPT_UNUSED jobject holder) {
5075 CHECK_ERROR_QUEUE_ON_RETURN;
5076 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5077 JNI_TRACE("X509_get_notBefore(%p)", x509);
5078
5079 if (x509 == nullptr) {
5080 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5081 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
5082 return 0;
5083 }
5084
5085 ASN1_TIME* notBefore = X509_get_notBefore(x509);
5086 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
5087 return reinterpret_cast<uintptr_t>(notBefore);
5088 }
5089
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5090 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
5091 CONSCRYPT_UNUSED jobject holder) {
5092 CHECK_ERROR_QUEUE_ON_RETURN;
5093 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5094 JNI_TRACE("X509_get_notAfter(%p)", x509);
5095
5096 if (x509 == nullptr) {
5097 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5098 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
5099 return 0;
5100 }
5101
5102 ASN1_TIME* notAfter = X509_get_notAfter(x509);
5103 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
5104 return reinterpret_cast<uintptr_t>(notAfter);
5105 }
5106
5107 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_get_version(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5108 static long NativeCrypto_X509_get_version(JNIEnv* env, jclass, jlong x509Ref,
5109 CONSCRYPT_UNUSED jobject holder) {
5110 CHECK_ERROR_QUEUE_ON_RETURN;
5111 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5112 JNI_TRACE("X509_get_version(%p)", x509);
5113
5114 if (x509 == nullptr) {
5115 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5116 JNI_TRACE("X509_get_version(%p) => x509 == null", x509);
5117 return 0;
5118 }
5119
5120 // NOLINTNEXTLINE(runtime/int)
5121 long version = X509_get_version(x509);
5122 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
5123 return version;
5124 }
5125
5126 template <typename T>
get_X509Type_serialNumber(JNIEnv * env,const T * x509Type,const ASN1_INTEGER * (* get_serial_func)(const T *))5127 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, const T* x509Type,
5128 const ASN1_INTEGER* (*get_serial_func)(const T*)) {
5129 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
5130
5131 if (x509Type == nullptr) {
5132 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5133 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
5134 return nullptr;
5135 }
5136
5137 const ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
5138 bssl::UniquePtr<BIGNUM> serialBn(ASN1_INTEGER_to_BN(serialNumber, nullptr));
5139 if (serialBn.get() == nullptr) {
5140 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5141 return nullptr;
5142 }
5143
5144 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
5145 if (env->ExceptionCheck()) {
5146 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5147 return nullptr;
5148 }
5149
5150 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
5151 return serialArray.release();
5152 }
5153
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5154 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref,
5155 CONSCRYPT_UNUSED jobject holder) {
5156 CHECK_ERROR_QUEUE_ON_RETURN;
5157 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5158 JNI_TRACE("X509_get_serialNumber(%p)", x509);
5159
5160 if (x509 == nullptr) {
5161 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5162 JNI_TRACE("X509_get_serialNumber(%p) => x509 == null", x509);
5163 return nullptr;
5164 }
5165 return get_X509Type_serialNumber<X509>(env, x509, X509_get0_serialNumber);
5166 }
5167
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)5168 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass,
5169 jlong x509RevokedRef) {
5170 CHECK_ERROR_QUEUE_ON_RETURN;
5171 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5172 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5173
5174 if (revoked == nullptr) {
5175 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5176 JNI_TRACE("X509_REVOKED_get_serialNumber(%p) => revoked == null", revoked);
5177 return 0;
5178 }
5179 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get0_serialNumber);
5180 }
5181
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5182 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref,
5183 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5184 CHECK_ERROR_QUEUE_ON_RETURN;
5185 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5186 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5187 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5188
5189 if (pkey == nullptr) {
5190 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5191 return;
5192 }
5193
5194 if (x509 == nullptr) {
5195 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5196 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5197 return;
5198 }
5199
5200 if (X509_verify(x509, pkey) != 1) {
5201 conscrypt::jniutil::throwExceptionFromBoringSSLError(
5202 env, "X509_verify", conscrypt::jniutil::throwCertificateException);
5203 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5204 return;
5205 }
5206 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5207 }
5208
NativeCrypto_get_X509_tbs_cert(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5209 static jbyteArray NativeCrypto_get_X509_tbs_cert(JNIEnv* env, jclass, jlong x509Ref,
5210 CONSCRYPT_UNUSED jobject holder) {
5211 CHECK_ERROR_QUEUE_ON_RETURN;
5212 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5213 JNI_TRACE("get_X509_tbs_cert(%p)", x509);
5214 // Note |i2d_X509_tbs| preserves the original encoding of the TBSCertificate.
5215 return ASN1ToByteArray<X509>(env, x509, i2d_X509_tbs);
5216 }
5217
NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)5218 static jbyteArray NativeCrypto_get_X509_tbs_cert_without_ext(JNIEnv* env, jclass, jlong x509Ref,
5219 CONSCRYPT_UNUSED jobject holder,
5220 jstring oidString) {
5221 CHECK_ERROR_QUEUE_ON_RETURN;
5222 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5223 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p)", x509, oidString);
5224
5225 if (x509 == nullptr) {
5226 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5227 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => x509 == null", x509, oidString);
5228 return nullptr;
5229 }
5230
5231 bssl::UniquePtr<X509> copy(X509_dup(x509));
5232 if (copy == nullptr) {
5233 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_dup");
5234 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => threw error", x509, oidString);
5235 return nullptr;
5236 }
5237
5238 ScopedUtfChars oid(env, oidString);
5239 if (oid.c_str() == nullptr) {
5240 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %p) => oidString == null", x509, oidString);
5241 return nullptr;
5242 }
5243
5244 bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(oid.c_str(), 1 /* allow numerical form only */));
5245 if (obj.get() == nullptr) {
5246 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => oid conversion failed", x509,
5247 oid.c_str());
5248 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5249 "Invalid OID.");
5250 ERR_clear_error();
5251 return nullptr;
5252 }
5253
5254 int extIndex = X509_get_ext_by_OBJ(copy.get(), obj.get(), -1);
5255 if (extIndex == -1) {
5256 JNI_TRACE("get_X509_tbs_cert_without_ext(%p, %s) => ext not found", x509, oid.c_str());
5257 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
5258 "Extension not found.");
5259 return nullptr;
5260 }
5261
5262 // Remove the extension and re-encode the TBSCertificate. Note |i2d_re_X509_tbs| ignores the
5263 // cached encoding.
5264 X509_EXTENSION_free(X509_delete_ext(copy.get(), extIndex));
5265 return ASN1ToByteArray<X509>(env, copy.get(), i2d_re_X509_tbs);
5266 }
5267
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5268 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref,
5269 CONSCRYPT_UNUSED jobject holder) {
5270 CHECK_ERROR_QUEUE_ON_RETURN;
5271 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5272 JNI_TRACE("get_X509_ex_flags(%p)", x509);
5273
5274 if (x509 == nullptr) {
5275 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5276 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5277 return 0;
5278 }
5279
5280 uint32_t flags = X509_get_extension_flags(x509);
5281 // X509_get_extension_flags sometimes leaves values in the error queue. See
5282 // https://crbug.com/boringssl/382.
5283 //
5284 // TODO(https://github.com/google/conscrypt/issues/916): This function is used to check
5285 // EXFLAG_CA, but does not check EXFLAG_INVALID. Fold the two JNI calls in getBasicConstraints()
5286 // together and handle errors. (See also NativeCrypto_get_X509_ex_pathlen.) From there, limit
5287 // this JNI call to EXFLAG_CRITICAL.
5288 ERR_clear_error();
5289 return flags;
5290 }
5291
NativeCrypto_X509_check_issued(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)5292 static jint NativeCrypto_X509_check_issued(JNIEnv* env, jclass, jlong x509Ref1,
5293 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
5294 CONSCRYPT_UNUSED jobject holder2) {
5295 CHECK_ERROR_QUEUE_ON_RETURN;
5296 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5297 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5298 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5299
5300 if (x509_1 == nullptr) {
5301 conscrypt::jniutil::throwNullPointerException(env, "x509Ref1 == null");
5302 JNI_TRACE("X509_check_issued(%p, %p) => x509_1 == null", x509_1, x509_2);
5303 return 0;
5304 }
5305 if (x509_2 == nullptr) {
5306 conscrypt::jniutil::throwNullPointerException(env, "x509Ref2 == null");
5307 JNI_TRACE("X509_check_issued(%p, %p) => x509_2 == null", x509_1, x509_2);
5308 return 0;
5309 }
5310 int ret = X509_check_issued(x509_1, x509_2);
5311 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5312 return ret;
5313 }
5314
get_X509_signature(X509 * x509)5315 static const ASN1_BIT_STRING* get_X509_signature(X509* x509) {
5316 const ASN1_BIT_STRING* signature;
5317 X509_get0_signature(&signature, nullptr, x509);
5318 return signature;
5319 }
5320
get_X509_CRL_signature(X509_CRL * crl)5321 static const ASN1_BIT_STRING* get_X509_CRL_signature(X509_CRL* crl) {
5322 const ASN1_BIT_STRING* signature;
5323 X509_CRL_get0_signature(crl, &signature, nullptr);
5324 return signature;
5325 }
5326
5327 template <typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,const ASN1_BIT_STRING * (* get_signature_func)(T *))5328 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type,
5329 const ASN1_BIT_STRING* (*get_signature_func)(T*)) {
5330 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5331
5332 if (x509Type == nullptr) {
5333 conscrypt::jniutil::throwNullPointerException(env, "x509Type == null");
5334 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5335 return nullptr;
5336 }
5337
5338 const ASN1_BIT_STRING* signature = get_signature_func(x509Type);
5339
5340 ScopedLocalRef<jbyteArray> signatureArray(env,
5341 env->NewByteArray(ASN1_STRING_length(signature)));
5342 if (env->ExceptionCheck()) {
5343 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5344 return nullptr;
5345 }
5346
5347 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5348 if (signatureBytes.get() == nullptr) {
5349 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5350 return nullptr;
5351 }
5352
5353 memcpy(signatureBytes.get(), ASN1_STRING_get0_data(signature), ASN1_STRING_length(signature));
5354
5355 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5356 ASN1_STRING_length(signature));
5357 return signatureArray.release();
5358 }
5359
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)5360 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref,
5361 CONSCRYPT_UNUSED jobject holder) {
5362 CHECK_ERROR_QUEUE_ON_RETURN;
5363 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5364 JNI_TRACE("get_X509_signature(%p)", x509);
5365
5366 if (x509 == nullptr) {
5367 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5368 JNI_TRACE("get_X509_signature(%p) => x509 == null", x509);
5369 return nullptr;
5370 }
5371 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5372 }
5373
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5374 static jbyteArray NativeCrypto_get_X509_CRL_signature(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_signature(%p)", crl);
5379
5380 if (crl == nullptr) {
5381 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5382 JNI_TRACE("X509_CRL_signature(%p) => crl == null", crl);
5383 return nullptr;
5384 }
5385 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5386 }
5387
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jlong x509Ref,CONSCRYPT_UNUSED jobject holder2)5388 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef,
5389 CONSCRYPT_UNUSED jobject holder, jlong x509Ref,
5390 CONSCRYPT_UNUSED jobject holder2) {
5391 CHECK_ERROR_QUEUE_ON_RETURN;
5392 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5393 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5394 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5395
5396 if (x509crl == nullptr) {
5397 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5398 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5399 return 0;
5400 } else if (x509 == nullptr) {
5401 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5402 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5403 return 0;
5404 }
5405
5406 X509_REVOKED* revoked = nullptr;
5407 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5408 if (ret == 0) {
5409 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5410 return 0;
5411 }
5412
5413 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5414 return reinterpret_cast<uintptr_t>(revoked);
5415 }
5416
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,CONSCRYPT_UNUSED jobject holder,jbyteArray serialArray)5417 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef,
5418 CONSCRYPT_UNUSED jobject holder,
5419 jbyteArray serialArray) {
5420 CHECK_ERROR_QUEUE_ON_RETURN;
5421 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5422 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5423
5424 if (x509crl == nullptr) {
5425 conscrypt::jniutil::throwNullPointerException(env, "x509crl == null");
5426 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5427 return 0;
5428 }
5429
5430 bssl::UniquePtr<BIGNUM> serialBn = arrayToBignum(env, serialArray);
5431 if (serialBn == nullptr) {
5432 if (!env->ExceptionCheck()) {
5433 conscrypt::jniutil::throwNullPointerException(env, "serial == null");
5434 }
5435 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5436 return 0;
5437 }
5438
5439 bssl::UniquePtr<ASN1_INTEGER> serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), nullptr));
5440 if (serialInteger.get() == nullptr) {
5441 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5442 return 0;
5443 }
5444
5445 X509_REVOKED* revoked = nullptr;
5446 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5447 if (ret == 0) {
5448 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5449 return 0;
5450 }
5451
5452 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5453 return reinterpret_cast<uintptr_t>(revoked);
5454 }
5455
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5456 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef,
5457 CONSCRYPT_UNUSED jobject holder) {
5458 CHECK_ERROR_QUEUE_ON_RETURN;
5459 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5460 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5461
5462 if (crl == nullptr) {
5463 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5464 JNI_TRACE("X509_CRL_get_REVOKED(%p) => crl == null", crl);
5465 return nullptr;
5466 }
5467
5468 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5469 if (stack == nullptr) {
5470 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5471 return nullptr;
5472 }
5473
5474 size_t size = sk_X509_REVOKED_num(stack);
5475
5476 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(static_cast<jsize>(size)));
5477 ScopedLongArrayRW revoked(env, revokedArray.get());
5478 for (size_t i = 0; i < size; i++) {
5479 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5480 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5481 }
5482
5483 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
5484 return revokedArray.release();
5485 }
5486
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5487 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef,
5488 CONSCRYPT_UNUSED jobject holder) {
5489 CHECK_ERROR_QUEUE_ON_RETURN;
5490 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5491 JNI_TRACE("i2d_X509_CRL(%p)", crl);
5492
5493 if (crl == nullptr) {
5494 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5495 JNI_TRACE("i2d_X509_CRL(%p) => crl == null", crl);
5496 return nullptr;
5497 }
5498 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
5499 }
5500
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5501 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef,
5502 CONSCRYPT_UNUSED jobject holder) {
5503 CHECK_ERROR_QUEUE_ON_RETURN;
5504 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5505 JNI_TRACE("X509_CRL_free(%p)", crl);
5506
5507 if (crl == nullptr) {
5508 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5509 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5510 return;
5511 }
5512
5513 X509_CRL_free(crl);
5514 }
5515
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5516 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef,
5517 CONSCRYPT_UNUSED jobject holder) {
5518 CHECK_ERROR_QUEUE_ON_RETURN;
5519 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5520 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5521 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5522
5523 if (bio == nullptr) {
5524 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5525 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5526 return;
5527 }
5528
5529 if (crl == nullptr) {
5530 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5531 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5532 return;
5533 }
5534
5535 if (!X509_CRL_print(bio, crl)) {
5536 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_print");
5537 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5538 return;
5539 }
5540 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5541 }
5542
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5543 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef,
5544 CONSCRYPT_UNUSED jobject holder) {
5545 CHECK_ERROR_QUEUE_ON_RETURN;
5546 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5547 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5548
5549 if (crl == nullptr) {
5550 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5551 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == null", crl);
5552 return nullptr;
5553 }
5554
5555 const X509_ALGOR* sig_alg;
5556 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5557 const ASN1_OBJECT* oid;
5558 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
5559 return ASN1_OBJECT_to_OID_string(env, oid);
5560 }
5561
get_X509_ALGOR_parameter(JNIEnv * env,const X509_ALGOR * algor)5562 static jbyteArray get_X509_ALGOR_parameter(JNIEnv* env, const X509_ALGOR* algor) {
5563 int param_type;
5564 const void* param_value;
5565 X509_ALGOR_get0(nullptr, ¶m_type, ¶m_value, algor);
5566
5567 if (param_type == V_ASN1_UNDEF) {
5568 JNI_TRACE("get_X509_ALGOR_parameter(%p) => no parameters", algor);
5569 return nullptr;
5570 }
5571
5572 // The OpenSSL 1.1.x API lacks a function to get the ASN1_TYPE out of X509_ALGOR directly, so
5573 // recreate it from the returned components.
5574 bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
5575 if (!param || !ASN1_TYPE_set1(param.get(), param_type, param_value)) {
5576 conscrypt::jniutil::throwOutOfMemory(env, "Unable to serialize parameter");
5577 return nullptr;
5578 }
5579
5580 return ASN1ToByteArray<ASN1_TYPE>(env, param.get(), i2d_ASN1_TYPE);
5581 }
5582
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5583 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef,
5584 CONSCRYPT_UNUSED jobject holder) {
5585 CHECK_ERROR_QUEUE_ON_RETURN;
5586 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5587 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5588
5589 if (crl == nullptr) {
5590 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5591 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5592 return nullptr;
5593 }
5594
5595 const X509_ALGOR* sig_alg;
5596 X509_CRL_get0_signature(crl, nullptr, &sig_alg);
5597 return get_X509_ALGOR_parameter(env, sig_alg);
5598 }
5599
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5600 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef,
5601 CONSCRYPT_UNUSED jobject holder) {
5602 CHECK_ERROR_QUEUE_ON_RETURN;
5603 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5604
5605 if (crl == nullptr) {
5606 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5607 JNI_TRACE("X509_CRL_get_issuer_name(%p) => crl == null", crl);
5608 return nullptr;
5609 }
5610 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5611 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
5612 }
5613
5614 // NOLINTNEXTLINE(runtime/int)
NativeCrypto_X509_CRL_get_version(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5615 static long NativeCrypto_X509_CRL_get_version(JNIEnv* env, jclass, jlong x509CrlRef,
5616 CONSCRYPT_UNUSED jobject holder) {
5617 CHECK_ERROR_QUEUE_ON_RETURN;
5618 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5619 JNI_TRACE("X509_CRL_get_version(%p)", crl);
5620
5621 if (crl == nullptr) {
5622 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5623 JNI_TRACE("X509_CRL_get_version(%p) => crl == null", crl);
5624 return 0;
5625 }
5626 // NOLINTNEXTLINE(runtime/int)
5627 long version = X509_CRL_get_version(crl);
5628 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5629 return version;
5630 }
5631
5632 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5633 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext(JNIEnv * env,const T * x509Type,jstring oidString)5634 static X509_EXTENSION* X509Type_get_ext(JNIEnv* env, const T* x509Type, jstring oidString) {
5635 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5636
5637 if (x509Type == nullptr) {
5638 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
5639 return nullptr;
5640 }
5641
5642 ScopedUtfChars oid(env, oidString);
5643 if (oid.c_str() == nullptr) {
5644 return nullptr;
5645 }
5646
5647 bssl::UniquePtr<ASN1_OBJECT> asn1(OBJ_txt2obj(oid.c_str(), 1));
5648 if (asn1.get() == nullptr) {
5649 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5650 ERR_clear_error();
5651 return nullptr;
5652 }
5653
5654 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5655 if (extIndex == -1) {
5656 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5657 return nullptr;
5658 }
5659
5660 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5661 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5662 return ext;
5663 }
5664
5665 template <typename T, int (*get_ext_by_OBJ_func)(const T*, const ASN1_OBJECT*, int),
5666 X509_EXTENSION* (*get_ext_func)(const T*, int)>
X509Type_get_ext_oid(JNIEnv * env,const T * x509Type,jstring oidString)5667 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, const T* x509Type, jstring oidString) {
5668 X509_EXTENSION* ext =
5669 X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, oidString);
5670 if (ext == nullptr) {
5671 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5672 return nullptr;
5673 }
5674
5675 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString,
5676 X509_EXTENSION_get_data(ext));
5677 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, X509_EXTENSION_get_data(ext),
5678 i2d_ASN1_OCTET_STRING);
5679 }
5680
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oid)5681 static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef,
5682 CONSCRYPT_UNUSED jobject holder, jstring oid) {
5683 CHECK_ERROR_QUEUE_ON_RETURN;
5684 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5685 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5686
5687 if (crl == nullptr) {
5688 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5689 JNI_TRACE("X509_CRL_get_ext(%p) => crl == null", crl);
5690 return 0;
5691 }
5692 X509_EXTENSION* ext =
5693 X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl, oid);
5694 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5695 return reinterpret_cast<uintptr_t>(ext);
5696 }
5697
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)5698 static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5699 jstring oid) {
5700 CHECK_ERROR_QUEUE_ON_RETURN;
5701 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5702 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5703 X509_EXTENSION* ext =
5704 X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
5705 env, revoked, oid);
5706 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5707 return reinterpret_cast<uintptr_t>(ext);
5708 }
5709
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)5710 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5711 CHECK_ERROR_QUEUE_ON_RETURN;
5712 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5713 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5714
5715 if (revoked == nullptr) {
5716 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5717 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5718 return 0;
5719 }
5720
5721 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5722 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5723 return reinterpret_cast<uintptr_t>(dup);
5724 }
5725
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5726 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
5727 jlong x509RevokedRef) {
5728 CHECK_ERROR_QUEUE_ON_RETURN;
5729 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5730 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5731
5732 if (revoked == nullptr) {
5733 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5734 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5735 return 0;
5736 }
5737
5738 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
5739 X509_REVOKED_get0_revocationDate(revoked));
5740 return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5741 }
5742
5743 #ifdef __GNUC__
5744 #pragma GCC diagnostic push
5745 #pragma GCC diagnostic ignored "-Wwrite-strings"
5746 #endif
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5747 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef,
5748 jlong x509RevokedRef) {
5749 CHECK_ERROR_QUEUE_ON_RETURN;
5750 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5751 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5752 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5753
5754 if (bio == nullptr) {
5755 conscrypt::jniutil::throwNullPointerException(env, "bio == null");
5756 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5757 return;
5758 }
5759
5760 if (revoked == nullptr) {
5761 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
5762 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5763 return;
5764 }
5765
5766 BIO_printf(bio, "Serial Number: ");
5767 i2a_ASN1_INTEGER(bio, X509_REVOKED_get0_serialNumber(revoked));
5768 BIO_printf(bio, "\nRevocation Date: ");
5769 ASN1_TIME_print(bio, X509_REVOKED_get0_revocationDate(revoked));
5770 BIO_printf(bio, "\n");
5771 // TODO(davidben): Should the flags parameter be |X509V3_EXT_DUMP_UNKNOWN| so we don't error on
5772 // unknown extensions. Alternatively, maybe we can use a simpler toString() implementation.
5773 X509V3_extensions_print(bio, "CRL entry extensions", X509_REVOKED_get0_extensions(revoked), 0,
5774 0);
5775 }
5776 #ifndef _WIN32
5777 #pragma GCC diagnostic pop
5778 #endif
5779
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5780 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef,
5781 CONSCRYPT_UNUSED jobject holder) {
5782 CHECK_ERROR_QUEUE_ON_RETURN;
5783 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5784 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5785
5786 if (crl == nullptr) {
5787 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5788 JNI_TRACE("get_X509_CRL_crl_enc(%p) => crl == null", crl);
5789 return nullptr;
5790 }
5791 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL_tbs);
5792 }
5793
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jobject pkeyRef)5794 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef,
5795 CONSCRYPT_UNUSED jobject holder, jobject pkeyRef) {
5796 CHECK_ERROR_QUEUE_ON_RETURN;
5797 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5798 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
5799 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5800
5801 if (pkey == nullptr) {
5802 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5803 return;
5804 }
5805
5806 if (crl == nullptr) {
5807 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5808 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5809 return;
5810 }
5811
5812 if (X509_CRL_verify(crl, pkey) != 1) {
5813 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_CRL_verify");
5814 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5815 return;
5816 }
5817 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5818 }
5819
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5820 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5821 CONSCRYPT_UNUSED jobject holder) {
5822 CHECK_ERROR_QUEUE_ON_RETURN;
5823 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5824 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5825
5826 if (crl == nullptr) {
5827 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5828 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5829 return 0;
5830 }
5831
5832 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5833 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5834 return reinterpret_cast<uintptr_t>(lastUpdate);
5835 }
5836
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder)5837 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
5838 CONSCRYPT_UNUSED jobject holder) {
5839 CHECK_ERROR_QUEUE_ON_RETURN;
5840 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5841 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5842
5843 if (crl == nullptr) {
5844 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
5845 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5846 return 0;
5847 }
5848
5849 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5850 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5851 return reinterpret_cast<uintptr_t>(nextUpdate);
5852 }
5853
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5854 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5855 CHECK_ERROR_QUEUE_ON_RETURN;
5856 X509_REVOKED* x509Revoked =
5857 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5858 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5859 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
5860 }
5861
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5862 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5863 CHECK_ERROR_QUEUE_ON_RETURN;
5864 X509_EXTENSION* ext =
5865 reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5866
5867 if (ext == nullptr) {
5868 conscrypt::jniutil::throwNullPointerException(env, "ext == null");
5869 return 0;
5870 }
5871
5872 return X509_supported_extension(ext);
5873 }
5874
decimal_to_integer(const char * data,size_t len,int * out)5875 static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5876 int ret = 0;
5877 for (size_t i = 0; i < len; i++) {
5878 ret *= 10;
5879 if (data[i] < '0' || data[i] > '9') {
5880 return false;
5881 }
5882 ret += data[i] - '0';
5883 }
5884 *out = ret;
5885 return true;
5886 }
5887
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5888 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5889 jobject calendar) {
5890 CHECK_ERROR_QUEUE_ON_RETURN;
5891 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5892 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5893
5894 if (asn1Time == nullptr) {
5895 conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5896 return;
5897 }
5898
5899 if (!ASN1_TIME_check(asn1Time)) {
5900 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5901 return;
5902 }
5903
5904 bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5905 if (gen.get() == nullptr) {
5906 conscrypt::jniutil::throwParsingException(env,
5907 "ASN1_TIME_to_generalizedtime returned null");
5908 return;
5909 }
5910
5911 if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5912 conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5913 return;
5914 }
5915
5916 int year, mon, mday, hour, min, sec;
5917 const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5918 if (!decimal_to_integer(data, 4, &year) ||
5919 !decimal_to_integer(data + 4, 2, &mon) ||
5920 !decimal_to_integer(data + 6, 2, &mday) ||
5921 !decimal_to_integer(data + 8, 2, &hour) ||
5922 !decimal_to_integer(data + 10, 2, &min) ||
5923 !decimal_to_integer(data + 12, 2, &sec)) {
5924 conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5925 return;
5926 }
5927
5928 env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5929 min, sec);
5930 }
5931
5932 // A CbsHandle is a structure used to manage resources allocated by asn1_read-*
5933 // functions so that they can be freed properly when finished. This struct owns
5934 // all objects pointed to by its members.
5935 struct CbsHandle {
5936 // A pointer to the CBS.
5937 std::unique_ptr<CBS> cbs;
5938 // A pointer to the data held by the CBS. If the data held by the CBS
5939 // is owned by a different CbsHandle, data will be null.
5940 std::unique_ptr<unsigned char[]> data;
5941 };
5942
NativeCrypto_asn1_read_init(JNIEnv * env,jclass,jbyteArray data)5943 static jlong NativeCrypto_asn1_read_init(JNIEnv* env, jclass, jbyteArray data) {
5944 CHECK_ERROR_QUEUE_ON_RETURN;
5945 JNI_TRACE("asn1_read_init(%p)", data);
5946
5947 ScopedByteArrayRO bytes(env, data);
5948 if (bytes.get() == nullptr) {
5949 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5950 return 0;
5951 }
5952
5953 std::unique_ptr<CbsHandle> cbs(new CbsHandle());
5954 cbs->data.reset(new unsigned char[bytes.size()]);
5955 memcpy(cbs->data.get(), bytes.get(), bytes.size());
5956
5957 cbs->cbs.reset(new CBS());
5958 CBS_init(cbs->cbs.get(), cbs->data.get(), bytes.size());
5959 JNI_TRACE("asn1_read_init(%p) => %p", data, cbs.get());
5960 return reinterpret_cast<uintptr_t>(cbs.release());
5961 }
5962
NativeCrypto_asn1_read_sequence(JNIEnv * env,jclass,jlong cbsRef)5963 static jlong NativeCrypto_asn1_read_sequence(JNIEnv* env, jclass, jlong cbsRef) {
5964 CHECK_ERROR_QUEUE_ON_RETURN;
5965 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5966 JNI_TRACE("asn1_read_sequence(%p)", cbs);
5967
5968 std::unique_ptr<CbsHandle> seq(new CbsHandle());
5969 seq->cbs.reset(new CBS());
5970 if (!CBS_get_asn1(cbs->cbs.get(), seq->cbs.get(), CBS_ASN1_SEQUENCE)) {
5971 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5972 return 0;
5973 }
5974 JNI_TRACE("asn1_read_sequence(%p) => %p", cbs, seq.get());
5975 return reinterpret_cast<uintptr_t>(seq.release());
5976 }
5977
NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef,jint tag)5978 static jboolean NativeCrypto_asn1_read_next_tag_is(CONSCRYPT_UNUSED JNIEnv* env, jclass,
5979 jlong cbsRef, jint tag) {
5980 CHECK_ERROR_QUEUE_ON_RETURN;
5981 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5982 JNI_TRACE("asn1_read_next_tag_is(%p)", cbs);
5983
5984 int result = CBS_peek_asn1_tag(cbs->cbs.get(),
5985 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | tag);
5986 JNI_TRACE("asn1_read_next_tag_is(%p) => %s", cbs, result ? "true" : "false");
5987 return result ? JNI_TRUE : JNI_FALSE;
5988 }
5989
NativeCrypto_asn1_read_tagged(JNIEnv * env,jclass,jlong cbsRef)5990 static jlong NativeCrypto_asn1_read_tagged(JNIEnv* env, jclass, jlong cbsRef) {
5991 CHECK_ERROR_QUEUE_ON_RETURN;
5992 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
5993 JNI_TRACE("asn1_read_tagged(%p)", cbs);
5994
5995 std::unique_ptr<CbsHandle> tag(new CbsHandle());
5996 tag->cbs.reset(new CBS());
5997 if (!CBS_get_any_asn1(cbs->cbs.get(), tag->cbs.get(), nullptr)) {
5998 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
5999 return 0;
6000 }
6001 JNI_TRACE("asn1_read_tagged(%p) => %p", cbs, tag.get());
6002 return reinterpret_cast<uintptr_t>(tag.release());
6003 }
6004
NativeCrypto_asn1_read_octetstring(JNIEnv * env,jclass,jlong cbsRef)6005 static jbyteArray NativeCrypto_asn1_read_octetstring(JNIEnv* env, jclass, jlong cbsRef) {
6006 CHECK_ERROR_QUEUE_ON_RETURN;
6007 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6008 JNI_TRACE("asn1_read_octetstring(%p)", cbs);
6009
6010 std::unique_ptr<CBS> str(new CBS());
6011 if (!CBS_get_asn1(cbs->cbs.get(), str.get(), CBS_ASN1_OCTETSTRING)) {
6012 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6013 return 0;
6014 }
6015 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(CBS_len(str.get()))));
6016 if (out.get() == nullptr) {
6017 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6018 return 0;
6019 }
6020 ScopedByteArrayRW outBytes(env, out.get());
6021 if (outBytes.get() == nullptr) {
6022 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6023 return 0;
6024 }
6025 memcpy(outBytes.get(), CBS_data(str.get()), CBS_len(str.get()));
6026 JNI_TRACE("asn1_read_octetstring(%p) => %p", cbs, out.get());
6027 return out.release();
6028 }
6029
NativeCrypto_asn1_read_uint64(JNIEnv * env,jclass,jlong cbsRef)6030 static jlong NativeCrypto_asn1_read_uint64(JNIEnv* env, jclass, jlong cbsRef) {
6031 CHECK_ERROR_QUEUE_ON_RETURN;
6032 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6033 JNI_TRACE("asn1_read_uint64(%p)", cbs);
6034
6035 // NOLINTNEXTLINE(runtime/int)
6036 uint64_t value;
6037 if (!CBS_get_asn1_uint64(cbs->cbs.get(), &value)) {
6038 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6039 return 0;
6040 }
6041 return value;
6042 }
6043
NativeCrypto_asn1_read_null(JNIEnv * env,jclass,jlong cbsRef)6044 static void NativeCrypto_asn1_read_null(JNIEnv* env, jclass, jlong cbsRef) {
6045 CHECK_ERROR_QUEUE_ON_RETURN;
6046 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6047 JNI_TRACE("asn1_read_null(%p)", cbs);
6048
6049 CBS null_holder;
6050 if (!CBS_get_asn1(cbs->cbs.get(), &null_holder, CBS_ASN1_NULL)) {
6051 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6052 }
6053 }
6054
NativeCrypto_asn1_read_oid(JNIEnv * env,jclass,jlong cbsRef)6055 static jstring NativeCrypto_asn1_read_oid(JNIEnv* env, jclass, jlong cbsRef) {
6056 CHECK_ERROR_QUEUE_ON_RETURN;
6057 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6058 JNI_TRACE("asn1_read_oid(%p)", cbs);
6059
6060 CBS oid_cbs;
6061 if (!CBS_get_asn1(cbs->cbs.get(), &oid_cbs, CBS_ASN1_OBJECT)) {
6062 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding");
6063 return nullptr;
6064 }
6065 int nid = OBJ_cbs2nid(&oid_cbs);
6066 if (nid == NID_undef) {
6067 conscrypt::jniutil::throwIOException(env, "Error reading ASN.1 encoding: OID not found");
6068 return nullptr;
6069 }
6070 const ASN1_OBJECT* obj(OBJ_nid2obj(nid));
6071 if (obj == nullptr) {
6072 conscrypt::jniutil::throwIOException(env,
6073 "Error reading ASN.1 encoding: "
6074 "Could not find ASN1_OBJECT for NID");
6075 return nullptr;
6076 }
6077 return ASN1_OBJECT_to_OID_string(env, obj);
6078 }
6079
NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)6080 static jboolean NativeCrypto_asn1_read_is_empty(CONSCRYPT_UNUSED JNIEnv* env, jclass,
6081 jlong cbsRef) {
6082 CHECK_ERROR_QUEUE_ON_RETURN;
6083 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6084 JNI_TRACE("asn1_read_is_empty(%p)", cbs);
6085
6086 bool empty = (CBS_len(cbs->cbs.get()) == 0);
6087 JNI_TRACE("asn1_read_is_empty(%p) => %s", cbs, empty ? "true" : "false");
6088 return empty;
6089 }
6090
NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbsRef)6091 static void NativeCrypto_asn1_read_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbsRef) {
6092 CHECK_ERROR_QUEUE_ON_RETURN;
6093 if (cbsRef == 0) {
6094 JNI_TRACE("asn1_read_free(0)");
6095 return;
6096 }
6097 CbsHandle* cbs = reinterpret_cast<CbsHandle*>(static_cast<uintptr_t>(cbsRef));
6098 JNI_TRACE("asn1_read_free(%p)", cbs);
6099 delete cbs;
6100 }
6101
NativeCrypto_asn1_write_init(JNIEnv * env,jclass)6102 static jlong NativeCrypto_asn1_write_init(JNIEnv* env, jclass) {
6103 CHECK_ERROR_QUEUE_ON_RETURN;
6104 JNI_TRACE("asn1_write_init");
6105 std::unique_ptr<CBB> cbb(new CBB());
6106 if (!CBB_init(cbb.get(), 128)) {
6107 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6108 return 0;
6109 }
6110 JNI_TRACE("asn1_write_init => %p", cbb.get());
6111 return reinterpret_cast<uintptr_t>(cbb.release());
6112 }
6113
NativeCrypto_asn1_write_sequence(JNIEnv * env,jclass,jlong cbbRef)6114 static jlong NativeCrypto_asn1_write_sequence(JNIEnv* env, jclass, jlong cbbRef) {
6115 CHECK_ERROR_QUEUE_ON_RETURN;
6116 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6117 JNI_TRACE("asn1_write_sequence(%p)", cbb);
6118
6119 std::unique_ptr<CBB> seq(new CBB());
6120 if (!CBB_add_asn1(cbb, seq.get(), CBS_ASN1_SEQUENCE)) {
6121 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6122 return 0;
6123 }
6124 JNI_TRACE("asn1_write_sequence(%p) => %p", cbb, seq.get());
6125 return reinterpret_cast<uintptr_t>(seq.release());
6126 }
6127
NativeCrypto_asn1_write_tag(JNIEnv * env,jclass,jlong cbbRef,jint tag)6128 static jlong NativeCrypto_asn1_write_tag(JNIEnv* env, jclass, jlong cbbRef, jint tag) {
6129 CHECK_ERROR_QUEUE_ON_RETURN;
6130 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6131 JNI_TRACE("asn1_write_tag(%p)", cbb);
6132
6133 std::unique_ptr<CBB> tag_holder(new CBB());
6134 if (!CBB_add_asn1(cbb, tag_holder.get(),
6135 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | tag)) {
6136 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6137 return 0;
6138 }
6139 JNI_TRACE("asn1_write_tag(%p) => %p", cbb, tag_holder.get());
6140 return reinterpret_cast<uintptr_t>(tag_holder.release());
6141 }
6142
NativeCrypto_asn1_write_octetstring(JNIEnv * env,jclass,jlong cbbRef,jbyteArray data)6143 static void NativeCrypto_asn1_write_octetstring(JNIEnv* env, jclass, jlong cbbRef,
6144 jbyteArray data) {
6145 CHECK_ERROR_QUEUE_ON_RETURN;
6146 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6147 JNI_TRACE("asn1_write_octetstring(%p, %p)", cbb, data);
6148
6149 ScopedByteArrayRO bytes(env, data);
6150 if (bytes.get() == nullptr) {
6151 JNI_TRACE("asn1_write_octetstring(%p, %p) => using byte array failed", cbb, data);
6152 return;
6153 }
6154
6155 std::unique_ptr<CBB> octetstring(new CBB());
6156 if (!CBB_add_asn1(cbb, octetstring.get(), CBS_ASN1_OCTETSTRING)) {
6157 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6158 return;
6159 }
6160 if (!CBB_add_bytes(octetstring.get(), reinterpret_cast<const uint8_t*>(bytes.get()),
6161 bytes.size())) {
6162 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6163 return;
6164 }
6165 if (!CBB_flush(cbb)) {
6166 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6167 return;
6168 }
6169 }
6170
NativeCrypto_asn1_write_uint64(JNIEnv * env,jclass,jlong cbbRef,jlong data)6171 static void NativeCrypto_asn1_write_uint64(JNIEnv* env, jclass, jlong cbbRef, jlong data) {
6172 CHECK_ERROR_QUEUE_ON_RETURN;
6173 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6174 JNI_TRACE("asn1_write_uint64(%p)", cbb);
6175
6176 if (!CBB_add_asn1_uint64(cbb, static_cast<uint64_t>(data))) {
6177 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6178 return;
6179 }
6180 }
6181
NativeCrypto_asn1_write_null(JNIEnv * env,jclass,jlong cbbRef)6182 static void NativeCrypto_asn1_write_null(JNIEnv* env, jclass, jlong cbbRef) {
6183 CHECK_ERROR_QUEUE_ON_RETURN;
6184 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6185 JNI_TRACE("asn1_write_null(%p)", cbb);
6186
6187 CBB null_holder;
6188 if (!CBB_add_asn1(cbb, &null_holder, CBS_ASN1_NULL)) {
6189 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6190 return;
6191 }
6192 if (!CBB_flush(cbb)) {
6193 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6194 return;
6195 }
6196 }
6197
NativeCrypto_asn1_write_oid(JNIEnv * env,jclass,jlong cbbRef,jstring oid)6198 static void NativeCrypto_asn1_write_oid(JNIEnv* env, jclass, jlong cbbRef, jstring oid) {
6199 CHECK_ERROR_QUEUE_ON_RETURN;
6200 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6201 JNI_TRACE("asn1_write_oid(%p)", cbb);
6202
6203 ScopedUtfChars oid_chars(env, oid);
6204 if (oid_chars.c_str() == nullptr) {
6205 return;
6206 }
6207
6208 int nid = OBJ_txt2nid(oid_chars.c_str());
6209 if (nid == NID_undef) {
6210 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6211 return;
6212 }
6213
6214 if (!OBJ_nid2cbb(cbb, nid)) {
6215 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6216 return;
6217 }
6218 }
6219
NativeCrypto_asn1_write_flush(JNIEnv * env,jclass,jlong cbbRef)6220 static void NativeCrypto_asn1_write_flush(JNIEnv* env, jclass, jlong cbbRef) {
6221 CHECK_ERROR_QUEUE_ON_RETURN;
6222 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6223 JNI_TRACE("asn1_write_flush(%p)", cbb);
6224
6225 if (!CBB_flush(cbb)) {
6226 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6227 return;
6228 }
6229 }
6230
NativeCrypto_asn1_write_finish(JNIEnv * env,jclass,jlong cbbRef)6231 static jbyteArray NativeCrypto_asn1_write_finish(JNIEnv* env, jclass, jlong cbbRef) {
6232 CHECK_ERROR_QUEUE_ON_RETURN;
6233 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6234 JNI_TRACE("asn1_write_finish(%p)", cbb);
6235
6236 uint8_t* data;
6237 size_t data_len;
6238 if (!CBB_finish(cbb, &data, &data_len)) {
6239 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6240 return 0;
6241 }
6242 bssl::UniquePtr<uint8_t> data_storage(data);
6243 ScopedLocalRef<jbyteArray> out(env, env->NewByteArray(static_cast<jsize>(data_len)));
6244 if (out.get() == nullptr) {
6245 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6246 return 0;
6247 }
6248 ScopedByteArrayRW outBytes(env, out.get());
6249 if (outBytes.get() == nullptr) {
6250 conscrypt::jniutil::throwIOException(env, "Error writing ASN.1 encoding");
6251 return 0;
6252 }
6253 memcpy(outBytes.get(), data, data_len);
6254 return out.release();
6255 }
6256
NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6257 static void NativeCrypto_asn1_write_cleanup(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6258 CHECK_ERROR_QUEUE_ON_RETURN;
6259 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6260 JNI_TRACE("asn1_write_cleanup(%p)", cbb);
6261
6262 CBB_cleanup(cbb);
6263 }
6264
NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv * env,jclass,jlong cbbRef)6265 static void NativeCrypto_asn1_write_free(CONSCRYPT_UNUSED JNIEnv* env, jclass, jlong cbbRef) {
6266 CHECK_ERROR_QUEUE_ON_RETURN;
6267 if (cbbRef == 0) {
6268 JNI_TRACE("asn1_write_free(0)");
6269 return;
6270 }
6271 CBB* cbb = reinterpret_cast<CBB*>(static_cast<uintptr_t>(cbbRef));
6272 JNI_TRACE("asn1_write_free(%p)", cbb);
6273 delete cbb;
6274 }
6275
6276 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)6277 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6278 BIO* bio = to_BIO(env, bioRef);
6279 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
6280
6281 if (bio == nullptr) {
6282 return 0;
6283 }
6284
6285 T* x = d2i_func(bio, nullptr);
6286 if (x == nullptr) {
6287 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_ASN1Object_to_jlong");
6288 return 0;
6289 }
6290
6291 return reinterpret_cast<uintptr_t>(x);
6292 }
6293
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)6294 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
6295 CHECK_ERROR_QUEUE_ON_RETURN;
6296 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
6297 }
6298
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)6299 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6300 CHECK_ERROR_QUEUE_ON_RETURN;
6301 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
6302 }
6303
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)6304 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
6305 CHECK_ERROR_QUEUE_ON_RETURN;
6306 ScopedByteArrayRO bytes(env, certBytes);
6307 if (bytes.get() == nullptr) {
6308 JNI_TRACE("NativeCrypto_d2i_X509(%p) => using byte array failed", certBytes);
6309 return 0;
6310 }
6311
6312 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
6313 // NOLINTNEXTLINE(runtime/int)
6314 X509* x = d2i_X509(nullptr, &tmp, static_cast<long>(bytes.size()));
6315 if (x == nullptr) {
6316 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6317 env, "Error reading X.509 data", conscrypt::jniutil::throwParsingException);
6318 return 0;
6319 }
6320 return reinterpret_cast<uintptr_t>(x);
6321 }
6322
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6323 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref,
6324 CONSCRYPT_UNUSED jobject holder) {
6325 CHECK_ERROR_QUEUE_ON_RETURN;
6326 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6327 JNI_TRACE("i2d_X509(%p)", x509);
6328
6329 if (x509 == nullptr) {
6330 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6331 JNI_TRACE("i2d_X509(%p) => x509 == null", x509);
6332 return nullptr;
6333 }
6334 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
6335 }
6336
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6337 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref,
6338 CONSCRYPT_UNUSED jobject holder) {
6339 CHECK_ERROR_QUEUE_ON_RETURN;
6340 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6341 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
6342
6343 if (x509 == nullptr) {
6344 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6345 JNI_TRACE("i2d_X509_PUBKEY(%p) => x509 == null", x509);
6346 return nullptr;
6347 }
6348 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
6349 }
6350
6351 template <typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_to_jlong(JNIEnv * env,jlong bioRef)6352 static jlong PEM_to_jlong(JNIEnv* env, jlong bioRef) {
6353 BIO* bio = to_BIO(env, bioRef);
6354 JNI_TRACE("PEM_to_jlong(%p)", bio);
6355
6356 if (bio == nullptr) {
6357 JNI_TRACE("PEM_to_jlong(%p) => bio == null", bio);
6358 return 0;
6359 }
6360
6361 T* x = PEM_read_func(bio, nullptr, nullptr, nullptr);
6362 if (x == nullptr) {
6363 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PEM_to_jlong");
6364 JNI_TRACE("PEM_to_jlong(%p) => threw exception", bio);
6365 return 0;
6366 }
6367
6368 JNI_TRACE("PEM_to_jlong(%p) => %p", bio, x);
6369 return reinterpret_cast<uintptr_t>(x);
6370 }
6371
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)6372 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
6373 CHECK_ERROR_QUEUE_ON_RETURN;
6374 // NOLINTNEXTLINE(runtime/int)
6375 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long)bioRef);
6376 return PEM_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
6377 }
6378
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)6379 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
6380 CHECK_ERROR_QUEUE_ON_RETURN;
6381 // NOLINTNEXTLINE(runtime/int)
6382 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long)bioRef);
6383 return PEM_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
6384 }
6385
NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv * env,jclass,jlong bioRef)6386 static jlong NativeCrypto_PEM_read_bio_PUBKEY(JNIEnv* env, jclass, jlong bioRef) {
6387 CHECK_ERROR_QUEUE_ON_RETURN;
6388 // NOLINTNEXTLINE(runtime/int)
6389 JNI_TRACE("PEM_read_bio_PUBKEY(0x%llx)", (long long)bioRef);
6390 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PUBKEY>(env, bioRef);
6391 }
6392
NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv * env,jclass,jlong bioRef)6393 static jlong NativeCrypto_PEM_read_bio_PrivateKey(JNIEnv* env, jclass, jlong bioRef) {
6394 CHECK_ERROR_QUEUE_ON_RETURN;
6395 // NOLINTNEXTLINE(runtime/int)
6396 JNI_TRACE("PEM_read_bio_PrivateKey(0x%llx)", (long long)bioRef);
6397 return PEM_to_jlong<EVP_PKEY, PEM_read_bio_PrivateKey>(env, bioRef);
6398 }
6399
X509s_to_ItemArray(JNIEnv * env,STACK_OF (X509)* certs)6400 static jlongArray X509s_to_ItemArray(JNIEnv* env, STACK_OF(X509)* certs) {
6401 if (certs == nullptr) {
6402 return nullptr;
6403 }
6404
6405 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6406 size_t size = sk_X509_num(certs);
6407 ref_array.reset(env->NewLongArray(size));
6408 ScopedLongArrayRW items(env, ref_array.get());
6409 for (size_t i = 0; i < size; i++) {
6410 X509* cert = sk_X509_value(certs, i);
6411 X509_up_ref(cert);
6412 items[i] = reinterpret_cast<uintptr_t>(cert);
6413 }
6414
6415 JNI_TRACE("X509s_to_ItemArray(%p) => %p [size=%zd]", certs, ref_array.get(), size);
6416 return ref_array.release();
6417 }
6418
X509_CRLs_to_ItemArray(JNIEnv * env,STACK_OF (X509_CRL)* crls)6419 static jlongArray X509_CRLs_to_ItemArray(JNIEnv* env, STACK_OF(X509_CRL)* crls) {
6420 if (crls == nullptr) {
6421 return nullptr;
6422 }
6423
6424 ScopedLocalRef<jlongArray> ref_array(env, nullptr);
6425 size_t size = sk_X509_CRL_num(crls);
6426 ref_array.reset(env->NewLongArray(size));
6427 ScopedLongArrayRW items(env, ref_array.get());
6428 for (size_t i = 0; i < size; i++) {
6429 X509_CRL* crl = sk_X509_CRL_value(crls, i);
6430 X509_CRL_up_ref(crl);
6431 items[i] = reinterpret_cast<uintptr_t>(crl);
6432 }
6433
6434 JNI_TRACE("X509_CRLs_to_ItemArray(%p) => %p [size=%zd]", crls, ref_array.get(), size);
6435 return ref_array.release();
6436 }
6437
6438 #define PKCS7_CERTS 1
6439 #define PKCS7_CRLS 2
6440
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)6441 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
6442 CHECK_ERROR_QUEUE_ON_RETURN;
6443 STACK_OF(X509)* stack = sk_X509_new_null();
6444
6445 ScopedLongArrayRO certs(env, certsArray);
6446 for (size_t i = 0; i < certs.size(); i++) {
6447 X509* item = reinterpret_cast<X509*>(certs[i]);
6448 if (sk_X509_push(stack, item) == 0) {
6449 sk_X509_free(stack);
6450 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "sk_X509_push");
6451 return nullptr;
6452 }
6453 }
6454
6455 bssl::ScopedCBB out;
6456 CBB_init(out.get(), 1024 * certs.size());
6457 if (!PKCS7_bundle_certificates(out.get(), stack)) {
6458 sk_X509_free(stack);
6459 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_bundle_certificates");
6460 return nullptr;
6461 }
6462
6463 sk_X509_free(stack);
6464
6465 return CBBToByteArray(env, out.get());
6466 }
6467
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)6468 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
6469 CHECK_ERROR_QUEUE_ON_RETURN;
6470 BIO* bio = to_BIO(env, bioRef);
6471 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
6472
6473 if (bio == nullptr) {
6474 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
6475 return nullptr;
6476 }
6477
6478 if (which == PKCS7_CERTS) {
6479 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6480 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
6481 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_certificates");
6482 return nullptr;
6483 }
6484 return X509s_to_ItemArray(env, outCerts.get());
6485 } else if (which == PKCS7_CRLS) {
6486 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6487 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
6488 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_PEM_CRLs");
6489 return nullptr;
6490 }
6491 return X509_CRLs_to_ItemArray(env, outCRLs.get());
6492 } else {
6493 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6494 return nullptr;
6495 }
6496 }
6497
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)6498 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
6499 CHECK_ERROR_QUEUE_ON_RETURN;
6500 BIO* bio = to_BIO(env, bioRef);
6501 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
6502
6503 if (bio == nullptr) {
6504 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
6505 return nullptr;
6506 }
6507
6508 uint8_t* data;
6509 size_t len;
6510 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6511 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading PKCS#7 data",
6512 conscrypt::jniutil::throwParsingException);
6513 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
6514 return nullptr;
6515 }
6516 bssl::UniquePtr<uint8_t> data_storage(data);
6517
6518 CBS cbs;
6519 CBS_init(&cbs, data, len);
6520
6521 if (which == PKCS7_CERTS) {
6522 bssl::UniquePtr<STACK_OF(X509)> outCerts(sk_X509_new_null());
6523 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
6524 conscrypt::jniutil::throwExceptionFromBoringSSLError(env,
6525 "PKCS7_get_certificates", conscrypt::jniutil::throwParsingException);
6526 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
6527 return nullptr;
6528 }
6529 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
6530 return X509s_to_ItemArray(env, outCerts.get());
6531 } else if (which == PKCS7_CRLS) {
6532 bssl::UniquePtr<STACK_OF(X509_CRL)> outCRLs(sk_X509_CRL_new_null());
6533 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
6534 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "PKCS7_get_CRLs",
6535 conscrypt::jniutil::throwParsingException);
6536 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
6537 return nullptr;
6538 }
6539 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
6540 return X509_CRLs_to_ItemArray(env, outCRLs.get());
6541 } else {
6542 conscrypt::jniutil::throwRuntimeException(env, "unknown PKCS7 field");
6543 return nullptr;
6544 }
6545 }
6546
NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv * env,jclass,jlong bioRef)6547 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6548 CHECK_ERROR_QUEUE_ON_RETURN;
6549 BIO* bio = to_BIO(env, bioRef);
6550 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
6551
6552 if (bio == nullptr) {
6553 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => bio == null", bio);
6554 return nullptr;
6555 }
6556
6557 uint8_t* data;
6558 size_t len;
6559 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
6560 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Error reading X.509 data",
6561 conscrypt::jniutil::throwParsingException);
6562 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => error reading BIO", bio);
6563 return nullptr;
6564 }
6565 bssl::UniquePtr<uint8_t> data_storage(data);
6566
6567 bssl::UniquePtr<STACK_OF(X509)> path(sk_X509_new_null());
6568 if (path.get() == nullptr) {
6569 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => failed to make cert stack", bio);
6570 return nullptr;
6571 }
6572
6573 CBS cbs, sequence;
6574 CBS_init(&cbs, data, len);
6575 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
6576 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6577 ERR_clear_error();
6578 return nullptr;
6579 }
6580
6581 while (CBS_len(&sequence) > 0) {
6582 CBS child;
6583 if (!CBS_get_asn1_element(&sequence, &child, CBS_ASN1_SEQUENCE)) {
6584 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6585 ERR_clear_error();
6586 return nullptr;
6587 }
6588
6589 const uint8_t* tmp = CBS_data(&child);
6590 // NOLINTNEXTLINE(runtime/int)
6591 bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &tmp, static_cast<long>(CBS_len(&child))));
6592 if (!cert || tmp != CBS_data(&child) + CBS_len(&child)) {
6593 conscrypt::jniutil::throwParsingException(env, "Error reading X.509 data");
6594 ERR_clear_error();
6595 return nullptr;
6596 }
6597
6598 if (!sk_X509_push(path.get(), cert.get())) {
6599 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push local certificate");
6600 return nullptr;
6601 }
6602 OWNERSHIP_TRANSFERRED(cert);
6603 }
6604
6605 size_t size = sk_X509_num(path.get());
6606
6607 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(static_cast<jsize>(size)));
6608 ScopedLongArrayRW certs(env, certArray.get());
6609 for (size_t i = 0; i < size; i++) {
6610 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
6611 certs[i] = reinterpret_cast<uintptr_t>(item);
6612 }
6613
6614 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
6615 return certArray.release();
6616 }
6617
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)6618 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
6619 CHECK_ERROR_QUEUE_ON_RETURN;
6620 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
6621 ScopedLongArrayRO certsArray(env, certs);
6622 if (certsArray.get() == nullptr) {
6623 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
6624 return nullptr;
6625 }
6626
6627 bssl::ScopedCBB result;
6628 CBB seq_contents;
6629 if (!CBB_init(result.get(), 2048 * certsArray.size())) {
6630 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
6631 return nullptr;
6632 }
6633 if (!CBB_add_asn1(result.get(), &seq_contents, CBS_ASN1_SEQUENCE)) {
6634 return nullptr;
6635 }
6636
6637 for (size_t i = 0; i < certsArray.size(); i++) {
6638 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
6639 uint8_t* buf;
6640 int len = i2d_X509(x509, nullptr);
6641
6642 if (len < 0 || !CBB_add_space(&seq_contents, &buf, static_cast<size_t>(len)) ||
6643 i2d_X509(x509, &buf) < 0) {
6644 return nullptr;
6645 }
6646 }
6647
6648 return CBBToByteArray(env, result.get());
6649 }
6650
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6651 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref,
6652 CONSCRYPT_UNUSED jobject holder) {
6653 CHECK_ERROR_QUEUE_ON_RETURN;
6654 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6655 JNI_TRACE("X509_free(%p)", x509);
6656
6657 if (x509 == nullptr) {
6658 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6659 JNI_TRACE("X509_free(%p) => x509 == null", x509);
6660 return;
6661 }
6662
6663 X509_free(x509);
6664 }
6665
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,CONSCRYPT_UNUSED jobject holder,jlong x509Ref2,CONSCRYPT_UNUSED jobject holder2)6666 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1,
6667 CONSCRYPT_UNUSED jobject holder, jlong x509Ref2,
6668 CONSCRYPT_UNUSED jobject holder2) {
6669 CHECK_ERROR_QUEUE_ON_RETURN;
6670 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
6671 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
6672 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
6673
6674 if (x509_1 == nullptr) {
6675 conscrypt::jniutil::throwNullPointerException(env, "x509_1 == null");
6676 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
6677 return -1;
6678 }
6679
6680 if (x509_2 == nullptr) {
6681 conscrypt::jniutil::throwNullPointerException(env, "x509_2 == null");
6682 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
6683 return -1;
6684 }
6685
6686 int ret = X509_cmp(x509_1, x509_2);
6687 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6688 return ret;
6689 }
6690
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong nmflagJava,jlong certflagJava)6691 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6692 CONSCRYPT_UNUSED jobject holder, jlong nmflagJava,
6693 jlong certflagJava) {
6694 CHECK_ERROR_QUEUE_ON_RETURN;
6695 BIO* bio = to_BIO(env, bioRef);
6696 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6697 // NOLINTNEXTLINE(runtime/int)
6698 unsigned long nmflag = static_cast<unsigned long>(nmflagJava);
6699 // NOLINTNEXTLINE(runtime/int)
6700 unsigned long certflag = static_cast<unsigned long>(certflagJava);
6701 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6702
6703 if (bio == nullptr) {
6704 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6705 return;
6706 }
6707
6708 if (x509 == nullptr) {
6709 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6710 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6711 return;
6712 }
6713
6714 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6715 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "X509_print_ex");
6716 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6717 return;
6718 }
6719 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6720 }
6721
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6722 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref,
6723 CONSCRYPT_UNUSED jobject holder) {
6724 CHECK_ERROR_QUEUE_ON_RETURN;
6725 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6726 JNI_TRACE("X509_get_pubkey(%p)", x509);
6727
6728 if (x509 == nullptr) {
6729 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6730 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6731 return 0;
6732 }
6733
6734 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
6735 if (pkey.get() == nullptr) {
6736 const uint32_t last_error = ERR_peek_last_error();
6737 const uint32_t first_error = ERR_peek_error();
6738 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6739 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6740 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6741 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6742 ERR_clear_error();
6743 conscrypt::jniutil::throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6744 return 0;
6745 }
6746
6747 conscrypt::jniutil::throwExceptionFromBoringSSLError(
6748 env, "X509_get_pubkey", conscrypt::jniutil::throwInvalidKeyException);
6749 return 0;
6750 }
6751
6752 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6753 return reinterpret_cast<uintptr_t>(pkey.release());
6754 }
6755
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6756 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref,
6757 CONSCRYPT_UNUSED jobject holder) {
6758 CHECK_ERROR_QUEUE_ON_RETURN;
6759 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6760 JNI_TRACE("X509_get_issuer_name(%p)", x509);
6761
6762 if (x509 == nullptr) {
6763 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6764 JNI_TRACE("X509_get_issuer_name(%p) => x509 == null", x509);
6765 return nullptr;
6766 }
6767 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
6768 }
6769
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6770 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref,
6771 CONSCRYPT_UNUSED jobject holder) {
6772 CHECK_ERROR_QUEUE_ON_RETURN;
6773 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6774 JNI_TRACE("X509_get_subject_name(%p)", x509);
6775
6776 if (x509 == nullptr) {
6777 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6778 JNI_TRACE("X509_get_subject_name(%p) => x509 == null", x509);
6779 return nullptr;
6780 }
6781 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
6782 }
6783
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6784 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref,
6785 CONSCRYPT_UNUSED jobject holder) {
6786 CHECK_ERROR_QUEUE_ON_RETURN;
6787 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6788 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6789
6790 if (x509 == nullptr) {
6791 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6792 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6793 return nullptr;
6794 }
6795
6796 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6797 ASN1_OBJECT* algorithm;
6798 X509_PUBKEY_get0_param(&algorithm, nullptr, nullptr, nullptr, pubkey);
6799 return ASN1_OBJECT_to_OID_string(env, algorithm);
6800 }
6801
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6802 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref,
6803 CONSCRYPT_UNUSED jobject holder) {
6804 CHECK_ERROR_QUEUE_ON_RETURN;
6805 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6806 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6807
6808 if (x509 == nullptr) {
6809 conscrypt::jniutil::throwNullPointerException(env, "x509 == null || x509->sig_alg == null");
6810 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == null", x509);
6811 return nullptr;
6812 }
6813
6814 const X509_ALGOR* sig_alg;
6815 X509_get0_signature(nullptr, &sig_alg, x509);
6816 const ASN1_OBJECT* oid;
6817 X509_ALGOR_get0(&oid, nullptr, nullptr, sig_alg);
6818 return ASN1_OBJECT_to_OID_string(env, oid);
6819 }
6820
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6821 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref,
6822 CONSCRYPT_UNUSED jobject holder) {
6823 CHECK_ERROR_QUEUE_ON_RETURN;
6824 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6825 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6826
6827 if (x509 == nullptr) {
6828 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6829 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6830 return nullptr;
6831 }
6832
6833 const X509_ALGOR* sig_alg;
6834 X509_get0_signature(nullptr, &sig_alg, x509);
6835 return get_X509_ALGOR_parameter(env, sig_alg);
6836 }
6837
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6838 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref,
6839 CONSCRYPT_UNUSED jobject holder) {
6840 CHECK_ERROR_QUEUE_ON_RETURN;
6841 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6842 JNI_TRACE("get_X509_issuerUID(%p)", x509);
6843
6844 if (x509 == nullptr) {
6845 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6846 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6847 return nullptr;
6848 }
6849
6850 const ASN1_BIT_STRING* issuer_uid;
6851 X509_get0_uids(x509, &issuer_uid, /*out_subject_uid=*/nullptr);
6852 if (issuer_uid == nullptr) {
6853 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6854 return nullptr;
6855 }
6856
6857 return ASN1BitStringToBooleanArray(env, issuer_uid);
6858 }
6859
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6860 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref,
6861 CONSCRYPT_UNUSED jobject holder) {
6862 CHECK_ERROR_QUEUE_ON_RETURN;
6863 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6864 JNI_TRACE("get_X509_subjectUID(%p)", x509);
6865
6866 if (x509 == nullptr) {
6867 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6868 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6869 return nullptr;
6870 }
6871
6872 const ASN1_BIT_STRING* subject_uid;
6873 X509_get0_uids(x509, /*out_issuer_uid=*/nullptr, &subject_uid);
6874 if (subject_uid == nullptr) {
6875 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6876 return nullptr;
6877 }
6878
6879 return ASN1BitStringToBooleanArray(env, subject_uid);
6880 }
6881
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6882 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref,
6883 CONSCRYPT_UNUSED jobject holder) {
6884 CHECK_ERROR_QUEUE_ON_RETURN;
6885 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6886 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6887
6888 if (x509 == nullptr) {
6889 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6890 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6891 return nullptr;
6892 }
6893
6894 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6895 // |ERR_clear_error|. Note X509Certificate.getKeyUsage() cannot throw
6896 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6897 bssl::UniquePtr<ASN1_BIT_STRING> bitStr(
6898 static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_key_usage, nullptr, nullptr)));
6899 if (bitStr.get() == nullptr) {
6900 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6901 ERR_clear_error();
6902 return nullptr;
6903 }
6904
6905 return ASN1BitStringToBooleanArray(env, bitStr.get());
6906 }
6907
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6908 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref,
6909 CONSCRYPT_UNUSED jobject holder) {
6910 CHECK_ERROR_QUEUE_ON_RETURN;
6911 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6912 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6913
6914 if (x509 == nullptr) {
6915 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6916 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6917 return nullptr;
6918 }
6919
6920 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors, remove
6921 // |ERR_clear_error|, and throw CertificateParsingException.
6922 bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6923 X509_get_ext_d2i(x509, NID_ext_key_usage, nullptr, nullptr)));
6924 if (objArray.get() == nullptr) {
6925 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6926 ERR_clear_error();
6927 return nullptr;
6928 }
6929
6930 size_t size = sk_ASN1_OBJECT_num(objArray.get());
6931 ScopedLocalRef<jobjectArray> exKeyUsage(
6932 env, env->NewObjectArray(static_cast<jsize>(size), conscrypt::jniutil::stringClass,
6933 nullptr));
6934 if (exKeyUsage.get() == nullptr) {
6935 return nullptr;
6936 }
6937
6938 for (size_t i = 0; i < size; i++) {
6939 ScopedLocalRef<jstring> oidStr(
6940 env, ASN1_OBJECT_to_OID_string(env, sk_ASN1_OBJECT_value(objArray.get(), i)));
6941 env->SetObjectArrayElement(exKeyUsage.get(), static_cast<jsize>(i), oidStr.get());
6942 }
6943
6944 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
6945 return exKeyUsage.release();
6946 }
6947
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder)6948 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref,
6949 CONSCRYPT_UNUSED jobject holder) {
6950 CHECK_ERROR_QUEUE_ON_RETURN;
6951 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6952 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6953
6954 if (x509 == nullptr) {
6955 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
6956 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6957 return 0;
6958 }
6959
6960 // Use |X509_get_ext_d2i| instead of |X509_get_pathlen| because the latter treats
6961 // |EXFLAG_INVALID| as the error case. |EXFLAG_INVALID| is set if any built-in extension is
6962 // invalid. For now, we preserve Conscrypt's historical behavior in accepting certificates in
6963 // the constructor even if |EXFLAG_INVALID| is set.
6964 //
6965 // TODO(https://github.com/google/conscrypt/issues/916): Handle errors and remove
6966 // |ERR_clear_error|. Note X509Certificate.getBasicConstraints() cannot throw
6967 // CertificateParsingException, so this needs to be checked earlier, e.g. in the constructor.
6968 bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(static_cast<BASIC_CONSTRAINTS*>(
6969 X509_get_ext_d2i(x509, NID_basic_constraints, nullptr, nullptr)));
6970 if (basic_constraints == nullptr) {
6971 JNI_TRACE("get_X509_ex_path(%p) => -1 (no extension or error)", x509);
6972 ERR_clear_error();
6973 return -1;
6974 }
6975
6976 if (basic_constraints->pathlen == nullptr) {
6977 JNI_TRACE("get_X509_ex_path(%p) => -1 (no pathLenConstraint)", x509);
6978 return -1;
6979 }
6980
6981 if (!basic_constraints->ca) {
6982 // Path length constraints are only valid for CA certificates.
6983 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6984 JNI_TRACE("get_X509_ex_path(%p) => -1 (not a CA)", x509);
6985 return -1;
6986 }
6987
6988 if (basic_constraints->pathlen->type == V_ASN1_NEG_INTEGER) {
6989 // Path length constraints may not be negative.
6990 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6991 JNI_TRACE("get_X509_ex_path(%p) => -1 (negative)", x509);
6992 return -1;
6993 }
6994
6995 long pathlen = ASN1_INTEGER_get(basic_constraints->pathlen);
6996 if (pathlen == -1 || pathlen > INT_MAX) {
6997 // TODO(https://github.com/google/conscrypt/issues/916): Treat this as an error condition.
6998 // If the integer overflows, the certificate is effectively unconstrained. Reporting no
6999 // constraint is plausible, but Chromium rejects all values above 255.
7000 JNI_TRACE("get_X509_ex_path(%p) => -1 (overflow)", x509);
7001 return -1;
7002 }
7003
7004 JNI_TRACE("get_X509_ex_path(%p) => %ld", x509, pathlen);
7005 return pathlen;
7006 }
7007
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jstring oidString)7008 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
7009 CONSCRYPT_UNUSED jobject holder,
7010 jstring oidString) {
7011 CHECK_ERROR_QUEUE_ON_RETURN;
7012 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7013 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
7014 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
7015 }
7016
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jstring oidString)7017 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
7018 CONSCRYPT_UNUSED jobject holder,
7019 jstring oidString) {
7020 CHECK_ERROR_QUEUE_ON_RETURN;
7021 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
7022 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
7023
7024 if (crl == nullptr) {
7025 conscrypt::jniutil::throwNullPointerException(env, "crl == null");
7026 JNI_TRACE("X509_CRL_get_ext_oid(%p) => crl == null", crl);
7027 return nullptr;
7028 }
7029 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
7030 oidString);
7031 }
7032
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)7033 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
7034 jstring oidString) {
7035 CHECK_ERROR_QUEUE_ON_RETURN;
7036 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
7037 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
7038
7039 if (revoked == nullptr) {
7040 conscrypt::jniutil::throwNullPointerException(env, "revoked == null");
7041 JNI_TRACE("X509_REVOKED_get_ext_oid(%p) => revoked == null", revoked);
7042 return nullptr;
7043 }
7044 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
7045 env, revoked, oidString);
7046 }
7047
7048 template <typename T, int (*get_ext_by_critical_func)(const T*, int, int),
7049 X509_EXTENSION* (*get_ext_func)(const T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)7050 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
7051 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
7052 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
7053
7054 if (x509 == nullptr) {
7055 conscrypt::jniutil::throwNullPointerException(env, "x509 == null");
7056 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
7057 return nullptr;
7058 }
7059
7060 int lastPos = -1;
7061 int count = 0;
7062 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7063 count++;
7064 }
7065
7066 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
7067
7068 ScopedLocalRef<jobjectArray> joa(
7069 env, env->NewObjectArray(count, conscrypt::jniutil::stringClass, nullptr));
7070 if (joa.get() == nullptr) {
7071 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
7072 return nullptr;
7073 }
7074
7075 lastPos = -1;
7076 count = 0;
7077 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7078 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
7079
7080 ScopedLocalRef<jstring> extOid(
7081 env, ASN1_OBJECT_to_OID_string(env, X509_EXTENSION_get_object(ext)));
7082 if (extOid.get() == nullptr) {
7083 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
7084 return nullptr;
7085 }
7086
7087 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
7088 }
7089
7090 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
7091 return joa.release();
7092 }
7093
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jint critical)7094 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
7095 CONSCRYPT_UNUSED jobject holder, jint critical) {
7096 CHECK_ERROR_QUEUE_ON_RETURN;
7097 // NOLINTNEXTLINE(runtime/int)
7098 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long)x509Ref, critical);
7099 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
7100 critical);
7101 }
7102
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,CONSCRYPT_UNUSED jobject holder,jint critical)7103 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
7104 CONSCRYPT_UNUSED jobject holder,
7105 jint critical) {
7106 CHECK_ERROR_QUEUE_ON_RETURN;
7107 // NOLINTNEXTLINE(runtime/int)
7108 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509CrlRef, critical);
7109 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(
7110 env, x509CrlRef, critical);
7111 }
7112
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)7113 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass,
7114 jlong x509RevokedRef, jint critical) {
7115 CHECK_ERROR_QUEUE_ON_RETURN;
7116 // NOLINTNEXTLINE(runtime/int)
7117 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long)x509RevokedRef, critical);
7118 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
7119 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
7120 }
7121
7122 /**
7123 * Based on example logging call back from SSL_CTX_set_info_callback man page
7124 */
info_callback_LOG(const SSL * s,int where,int ret)7125 static void info_callback_LOG(const SSL* s, int where, int ret) {
7126 int w = where & ~SSL_ST_MASK;
7127 const char* str;
7128 if (w & SSL_ST_CONNECT) {
7129 str = "SSL_connect";
7130 } else if (w & SSL_ST_ACCEPT) {
7131 str = "SSL_accept";
7132 } else {
7133 str = "undefined";
7134 }
7135
7136 if (where & SSL_CB_LOOP) {
7137 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
7138 } else if (where & SSL_CB_ALERT) {
7139 str = (where & SSL_CB_READ) ? "read" : "write";
7140 JNI_TRACE("ssl=%p SSL3 alert %s %s %s", s, str, SSL_alert_type_string_long(ret),
7141 SSL_alert_desc_string_long(ret));
7142 } else if (where & SSL_CB_EXIT) {
7143 if (ret == 0) {
7144 JNI_TRACE("ssl=%p %s:failed exit in %s %s", s, str, SSL_state_string(s),
7145 SSL_state_string_long(s));
7146 } else if (ret < 0) {
7147 JNI_TRACE("ssl=%p %s:error exit in %s %s", s, str, SSL_state_string(s),
7148 SSL_state_string_long(s));
7149 } else if (ret == 1) {
7150 JNI_TRACE("ssl=%p %s:ok exit in %s %s", s, str, SSL_state_string(s),
7151 SSL_state_string_long(s));
7152 } else {
7153 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s", s, str, ret, SSL_state_string(s),
7154 SSL_state_string_long(s));
7155 }
7156 } else if (where & SSL_CB_HANDSHAKE_START) {
7157 JNI_TRACE("ssl=%p handshake start in %s %s", s, SSL_state_string(s),
7158 SSL_state_string_long(s));
7159 } else if (where & SSL_CB_HANDSHAKE_DONE) {
7160 JNI_TRACE("ssl=%p handshake done in %s %s", s, SSL_state_string(s),
7161 SSL_state_string_long(s));
7162 } else {
7163 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s", s, str, where, SSL_state_string(s),
7164 SSL_state_string_long(s));
7165 }
7166 }
7167
7168 #ifdef _WIN32
7169
7170 /**
7171 * Dark magic helper function that checks, for a given SSL session, whether it
7172 * can SSL_read() or SSL_write() without blocking. Takes into account any
7173 * concurrent attempts to close the SSLSocket from the Java side. This is
7174 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7175 * while thread #2 is sitting in a blocking read or write. The type argument
7176 * specifies whether we are waiting for readability or writability. It expects
7177 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7178 * only need to wait in case one of these problems occurs.
7179 *
7180 * @param env
7181 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7182 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
7183 * @param appData The application data structure with mutex info etc.
7184 * @param timeout_millis The timeout value for select call, with the special value
7185 * 0 meaning no timeout at all (wait indefinitely). Note: This is
7186 * the Java semantics of the timeout value, not the usual
7187 * select() semantics.
7188 * @return THROWN_EXCEPTION on close socket, 0 on timeout, -1 on error, and 1 on success
7189 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7190 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7191 int timeout_millis) {
7192 int result = -1;
7193
7194 NetFd fd(env, fdObject);
7195 do {
7196 if (fd.isClosed()) {
7197 result = THROWN_EXCEPTION;
7198 break;
7199 }
7200
7201 WSAEVENT events[2];
7202 events[0] = appData->interruptEvent;
7203 events[1] = WSACreateEvent();
7204 if (events[1] == WSA_INVALID_EVENT) {
7205 JNI_TRACE("sslSelect failure in WSACreateEvent: %d", WSAGetLastError());
7206 break;
7207 }
7208
7209 if (WSAEventSelect(fd.get(), events[1], (type == SSL_ERROR_WANT_READ ? FD_READ : FD_WRITE) |
7210 FD_CLOSE) == SOCKET_ERROR) {
7211 JNI_TRACE("sslSelect failure in WSAEventSelect: %d", WSAGetLastError());
7212 break;
7213 }
7214
7215 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7216 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7217 timeout_millis);
7218
7219 int rc = WSAWaitForMultipleEvents(
7220 2, events, FALSE, timeout_millis == 0 ? WSA_INFINITE : timeout_millis, FALSE);
7221 if (rc == WSA_WAIT_FAILED) {
7222 JNI_TRACE("WSAWaitForMultipleEvents failed: %d", WSAGetLastError());
7223 result = -1;
7224 } else if (rc == WSA_WAIT_TIMEOUT) {
7225 result = 0;
7226 } else {
7227 result = 1;
7228 }
7229 WSACloseEvent(events[1]);
7230 } while (0);
7231
7232 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d => %d",
7233 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData, timeout_millis,
7234 result);
7235
7236 std::lock_guard<std::mutex> appDataLock(appData->mutex);
7237 appData->waitingThreads--;
7238
7239 return result;
7240 }
7241
7242 #else // !defined(_WIN32)
7243
7244 /**
7245 * Dark magic helper function that checks, for a given SSL session, whether it
7246 * can SSL_read() or SSL_write() without blocking. Takes into account any
7247 * concurrent attempts to close the SSLSocket from the Java side. This is
7248 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7249 * while thread #2 is sitting in a blocking read or write. The type argument
7250 * specifies whether we are waiting for readability or writability. It expects
7251 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7252 * only need to wait in case one of these problems occurs.
7253 *
7254 * @param env
7255 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7256 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be nullptr
7257 * @param appData The application data structure with mutex info etc.
7258 * @param timeout_millis The timeout value for poll call, with the special value
7259 * 0 meaning no timeout at all (wait indefinitely). Note: This is
7260 * the Java semantics of the timeout value, not the usual
7261 * poll() semantics.
7262 * @return The result of the inner poll() call,
7263 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
7264 * additional errors
7265 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)7266 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData,
7267 int timeout_millis) {
7268 // This loop is an expanded version of the NET_FAILURE_RETRY
7269 // macro. It cannot simply be used in this case because poll
7270 // cannot be restarted without recreating the pollfd structure.
7271 int result;
7272 struct pollfd fds[2];
7273 do {
7274 NetFd fd(env, fdObject);
7275 if (fd.isClosed()) {
7276 result = THROWN_EXCEPTION;
7277 break;
7278 }
7279 int intFd = fd.get();
7280 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7281 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
7282
7283 memset(&fds, 0, sizeof(fds));
7284 fds[0].fd = intFd;
7285 if (type == SSL_ERROR_WANT_READ) {
7286 fds[0].events = POLLIN | POLLPRI;
7287 } else {
7288 fds[0].events = POLLOUT | POLLPRI;
7289 }
7290
7291 fds[1].fd = appData->fdsEmergency[0];
7292 fds[1].events = POLLIN | POLLPRI;
7293
7294 // Converting from Java semantics to Posix semantics.
7295 if (timeout_millis <= 0) {
7296 timeout_millis = -1;
7297 }
7298
7299 CompatibilityCloseMonitor monitor(intFd);
7300
7301 result = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_millis);
7302 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
7303 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", fd.get(), appData,
7304 timeout_millis, result);
7305 if (result == -1) {
7306 if (fd.isClosed()) {
7307 result = THROWN_EXCEPTION;
7308 break;
7309 }
7310 if (errno != EINTR) {
7311 break;
7312 }
7313 }
7314 } while (result == -1);
7315
7316 std::lock_guard<std::mutex> appDataLock(appData->mutex);
7317
7318 if (result > 0) {
7319 // We have been woken up by a token in the emergency pipe. We
7320 // can't be sure the token is still in the pipe at this point
7321 // because it could have already been read by the thread that
7322 // originally wrote it if it entered sslSelect and acquired
7323 // the mutex before we did. Thus we cannot safely read from
7324 // the pipe in a blocking way (so we make the pipe
7325 // non-blocking at creation).
7326 if (fds[1].revents & POLLIN) {
7327 char token;
7328 do {
7329 (void)read(appData->fdsEmergency[0], &token, 1);
7330 } while (errno == EINTR);
7331 }
7332 }
7333
7334 // Tell the world that there is now one thread less waiting for the
7335 // underlying network.
7336 appData->waitingThreads--;
7337
7338 return result;
7339 }
7340 #endif // !defined(_WIN32)
7341
7342 /**
7343 * Helper function that wakes up a thread blocked in select(), in case there is
7344 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
7345 * before closing the connection.
7346 *
7347 * @param data The application data structure with mutex info etc.
7348 */
sslNotify(AppData * appData)7349 static void sslNotify(AppData* appData) {
7350 #ifdef _WIN32
7351 SetEvent(appData->interruptEvent);
7352 #else
7353 // Write a byte to the emergency pipe, so a concurrent select() can return.
7354 // Note we have to restore the errno of the original system call, since the
7355 // caller relies on it for generating error messages.
7356 int errnoBackup = errno;
7357 char token = '*';
7358 do {
7359 errno = 0;
7360 (void)write(appData->fdsEmergency[1], &token, 1);
7361 } while (errno == EINTR);
7362 errno = errnoBackup;
7363 #endif
7364 }
7365
toAppData(const SSL * ssl)7366 static AppData* toAppData(const SSL* ssl) {
7367 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
7368 }
7369
cert_verify_callback(SSL * ssl,CONSCRYPT_UNUSED uint8_t * out_alert)7370 static ssl_verify_result_t cert_verify_callback(SSL* ssl, CONSCRYPT_UNUSED uint8_t* out_alert) {
7371 JNI_TRACE("ssl=%p cert_verify_callback", ssl);
7372
7373 AppData* appData = toAppData(ssl);
7374 JNIEnv* env = appData->env;
7375 if (env == nullptr) {
7376 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_verify_callback");
7377 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
7378 return ssl_verify_invalid;
7379 }
7380
7381 // Create the byte[][] array that holds all the certs
7382 ScopedLocalRef<jobjectArray> array(
7383 env, CryptoBuffersToObjectArray(env, SSL_get0_peer_certificates(ssl)));
7384 if (array.get() == nullptr) {
7385 return ssl_verify_invalid;
7386 }
7387
7388 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7389 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_verifyCertificateChain;
7390
7391 const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
7392 const char* authMethod = SSL_CIPHER_get_kx_name(cipher);
7393
7394 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s", ssl,
7395 authMethod);
7396 ScopedLocalRef<jstring> authMethodString(env, env->NewStringUTF(authMethod));
7397 env->CallVoidMethod(sslHandshakeCallbacks, methodID, array.get(), authMethodString.get());
7398
7399 ssl_verify_result_t result = env->ExceptionCheck() ? ssl_verify_invalid : ssl_verify_ok;
7400 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
7401 return result;
7402 }
7403
7404 /**
7405 * Call back to watch for handshake to be completed. This is necessary for
7406 * False Start support, since SSL_do_handshake returns before the handshake is
7407 * completed in this case.
7408 */
info_callback(const SSL * ssl,int type,int value)7409 static void info_callback(const SSL* ssl, int type, int value) {
7410 JNI_TRACE("ssl=%p info_callback type=0x%x value=%d", ssl, type, value);
7411 if (conscrypt::trace::kWithJniTrace) {
7412 info_callback_LOG(ssl, type, value);
7413 }
7414 if (!(type & SSL_CB_HANDSHAKE_DONE) && !(type & SSL_CB_HANDSHAKE_START)) {
7415 JNI_TRACE("ssl=%p info_callback ignored", ssl);
7416 return;
7417 }
7418
7419 AppData* appData = toAppData(ssl);
7420 JNIEnv* env = appData->env;
7421 if (env == nullptr) {
7422 CONSCRYPT_LOG_ERROR("AppData->env missing in info_callback");
7423 JNI_TRACE("ssl=%p info_callback env error", ssl);
7424 return;
7425 }
7426 if (env->ExceptionCheck()) {
7427 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
7428 return;
7429 }
7430
7431 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7432
7433 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
7434 env->CallVoidMethod(sslHandshakeCallbacks,
7435 conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
7436
7437 if (env->ExceptionCheck()) {
7438 JNI_TRACE("ssl=%p info_callback exception", ssl);
7439 }
7440 JNI_TRACE("ssl=%p info_callback completed", ssl);
7441 }
7442
7443 /**
7444 * Call back to ask for a certificate. There are three possible exit codes:
7445 *
7446 * 1 is success.
7447 * 0 is error.
7448 * -1 is to pause the handshake to continue from the same place later.
7449 */
cert_cb(SSL * ssl,CONSCRYPT_UNUSED void * arg)7450 static int cert_cb(SSL* ssl, CONSCRYPT_UNUSED void* arg) {
7451 JNI_TRACE("ssl=%p cert_cb", ssl);
7452
7453 // cert_cb is called for both clients and servers, but we are only
7454 // interested in client certificates.
7455 if (SSL_is_server(ssl)) {
7456 JNI_TRACE("ssl=%p cert_cb not a client => 1", ssl);
7457 return 1;
7458 }
7459
7460 AppData* appData = toAppData(ssl);
7461 JNIEnv* env = appData->env;
7462 if (env == nullptr) {
7463 CONSCRYPT_LOG_ERROR("AppData->env missing in cert_cb");
7464 JNI_TRACE("ssl=%p cert_cb env error => 0", ssl);
7465 return 0;
7466 }
7467 if (env->ExceptionCheck()) {
7468 JNI_TRACE("ssl=%p cert_cb already pending exception => 0", ssl);
7469 return 0;
7470 }
7471 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7472
7473 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientCertificateRequested;
7474
7475 // Call Java callback which can reconfigure the client certificate.
7476 const uint8_t* ctype = nullptr;
7477 size_t ctype_num = SSL_get0_certificate_types(ssl, &ctype);
7478 const uint16_t* sigalgs = nullptr;
7479 size_t sigalgs_num = SSL_get0_peer_verify_algorithms(ssl, &sigalgs);
7480 ScopedLocalRef<jobjectArray> issuers(
7481 env, CryptoBuffersToObjectArray(env, SSL_get0_server_requested_CAs(ssl)));
7482 if (issuers.get() == nullptr) {
7483 return 0;
7484 }
7485
7486 if (conscrypt::trace::kWithJniTrace) {
7487 for (size_t i = 0; i < ctype_num; i++) {
7488 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%zu]=%d", ssl, i, ctype[i]);
7489 }
7490 for (size_t i = 0; i < sigalgs_num; i++) {
7491 JNI_TRACE("ssl=%p clientCertificateRequested sigAlgs[%zu]=%d", ssl, i, sigalgs[i]);
7492 }
7493 }
7494
7495 jbyteArray keyTypes = env->NewByteArray(static_cast<jsize>(ctype_num));
7496 if (keyTypes == nullptr) {
7497 JNI_TRACE("ssl=%p cert_cb keyTypes == null => 0", ssl);
7498 return 0;
7499 }
7500 env->SetByteArrayRegion(keyTypes, 0, static_cast<jsize>(ctype_num),
7501 reinterpret_cast<const jbyte*>(ctype));
7502
7503 jintArray signatureAlgs = env->NewIntArray(static_cast<jsize>(sigalgs_num));
7504 if (signatureAlgs == nullptr) {
7505 JNI_TRACE("ssl=%p cert_cb signatureAlgs == null => 0", ssl);
7506 return 0;
7507 }
7508 {
7509 ScopedIntArrayRW sigAlgsRW(env, signatureAlgs);
7510 for (size_t i = 0; i < sigalgs_num; i++) {
7511 sigAlgsRW[i] = sigalgs[i];
7512 }
7513 }
7514
7515 JNI_TRACE(
7516 "ssl=%p clientCertificateRequested calling clientCertificateRequested "
7517 "keyTypes=%p signatureAlgs=%p issuers=%p",
7518 ssl, keyTypes, signatureAlgs, issuers.get());
7519 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, signatureAlgs, issuers.get());
7520
7521 if (env->ExceptionCheck()) {
7522 JNI_TRACE("ssl=%p cert_cb exception => 0", ssl);
7523 return 0;
7524 }
7525
7526 JNI_TRACE("ssl=%p cert_cb => 1", ssl);
7527 return 1;
7528 }
7529
select_certificate_cb(const SSL_CLIENT_HELLO * client_hello)7530 static enum ssl_select_cert_result_t select_certificate_cb(const SSL_CLIENT_HELLO* client_hello) {
7531 SSL* ssl = client_hello->ssl;
7532 JNI_TRACE("ssl=%p select_certificate_cb_callback", ssl);
7533
7534 AppData* appData = toAppData(ssl);
7535 JNIEnv* env = appData->env;
7536 if (env == nullptr) {
7537 CONSCRYPT_LOG_ERROR("AppData->env missing in select_certificate_cb");
7538 JNI_TRACE("ssl=%p select_certificate_cb env error", ssl);
7539 return ssl_select_cert_error;
7540 }
7541 if (env->ExceptionCheck()) {
7542 JNI_TRACE("ssl=%p select_certificate_cb already pending exception", ssl);
7543 return ssl_select_cert_error;
7544 }
7545
7546 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7547 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverCertificateRequested;
7548
7549 JNI_TRACE("ssl=%p select_certificate_cb calling serverCertificateRequested", ssl);
7550 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
7551
7552 if (env->ExceptionCheck()) {
7553 JNI_TRACE("ssl=%p select_certificate_cb exception", ssl);
7554 return ssl_select_cert_error;
7555 }
7556 JNI_TRACE("ssl=%p select_certificate_cb completed", ssl);
7557 return ssl_select_cert_success;
7558 }
7559
7560 /**
7561 * Pre-Shared Key (PSK) client callback.
7562 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)7563 static unsigned int psk_client_callback(SSL* ssl, const char* hint, char* identity,
7564 unsigned int max_identity_len, unsigned char* psk,
7565 unsigned int max_psk_len) {
7566 JNI_TRACE("ssl=%p psk_client_callback", ssl);
7567
7568 AppData* appData = toAppData(ssl);
7569 JNIEnv* env = appData->env;
7570 if (env == nullptr) {
7571 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_client_callback");
7572 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
7573 return 0;
7574 }
7575 if (env->ExceptionCheck()) {
7576 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
7577 return 0;
7578 }
7579
7580 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7581 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_clientPSKKeyRequested;
7582 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
7583 ScopedLocalRef<jstring> identityHintJava(env,
7584 (hint != nullptr) ? env->NewStringUTF(hint) : nullptr);
7585 ScopedLocalRef<jbyteArray> identityJava(
7586 env, env->NewByteArray(static_cast<jsize>(max_identity_len)));
7587 if (identityJava.get() == nullptr) {
7588 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
7589 return 0;
7590 }
7591 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7592 if (keyJava.get() == nullptr) {
7593 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
7594 return 0;
7595 }
7596 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7597 identityJava.get(), keyJava.get());
7598 if (env->ExceptionCheck()) {
7599 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
7600 return 0;
7601 }
7602 if (keyLen <= 0) {
7603 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
7604 return 0;
7605 } else if ((unsigned int)keyLen > max_psk_len) {
7606 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
7607 return 0;
7608 }
7609 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7610 if (keyJavaRo.get() == nullptr) {
7611 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7612 return 0;
7613 }
7614 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7615
7616 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7617 if (identityJavaRo.get() == nullptr) {
7618 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7619 return 0;
7620 }
7621 memcpy(identity, identityJavaRo.get(), max_identity_len);
7622
7623 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7624 return static_cast<unsigned int>(keyLen);
7625 }
7626
7627 /**
7628 * Pre-Shared Key (PSK) server callback.
7629 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)7630 static unsigned int psk_server_callback(SSL* ssl, const char* identity, unsigned char* psk,
7631 unsigned int max_psk_len) {
7632 JNI_TRACE("ssl=%p psk_server_callback", ssl);
7633
7634 AppData* appData = toAppData(ssl);
7635 JNIEnv* env = appData->env;
7636 if (env == nullptr) {
7637 CONSCRYPT_LOG_ERROR("AppData->env missing in psk_server_callback");
7638 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7639 return 0;
7640 }
7641 if (env->ExceptionCheck()) {
7642 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7643 return 0;
7644 }
7645
7646 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7647 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverPSKKeyRequested;
7648 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7649 const char* identityHint = SSL_get_psk_identity_hint(ssl);
7650 ScopedLocalRef<jstring> identityHintJava(
7651 env, (identityHint != nullptr) ? env->NewStringUTF(identityHint) : nullptr);
7652 ScopedLocalRef<jstring> identityJava(
7653 env, (identity != nullptr) ? env->NewStringUTF(identity) : nullptr);
7654 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(static_cast<jsize>(max_psk_len)));
7655 if (keyJava.get() == nullptr) {
7656 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7657 return 0;
7658 }
7659 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID, identityHintJava.get(),
7660 identityJava.get(), keyJava.get());
7661 if (env->ExceptionCheck()) {
7662 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7663 return 0;
7664 }
7665 if (keyLen <= 0) {
7666 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7667 return 0;
7668 } else if ((unsigned int)keyLen > max_psk_len) {
7669 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7670 return 0;
7671 }
7672 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7673 if (keyJavaRo.get() == nullptr) {
7674 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7675 return 0;
7676 }
7677 memcpy(psk, keyJavaRo.get(), static_cast<size_t>(keyLen));
7678
7679 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7680 return static_cast<unsigned int>(keyLen);
7681 }
7682
new_session_callback(SSL * ssl,SSL_SESSION * session)7683 static int new_session_callback(SSL* ssl, SSL_SESSION* session) {
7684 JNI_TRACE("ssl=%p new_session_callback session=%p", ssl, session);
7685
7686 AppData* appData = toAppData(ssl);
7687 JNIEnv* env = appData->env;
7688 if (env == nullptr) {
7689 CONSCRYPT_LOG_ERROR("AppData->env missing in new_session_callback");
7690 JNI_TRACE("ssl=%p new_session_callback env error", ssl);
7691 return 0;
7692 }
7693 if (env->ExceptionCheck()) {
7694 JNI_TRACE("ssl=%p new_session_callback already pending exception", ssl);
7695 return 0;
7696 }
7697
7698 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7699 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_onNewSessionEstablished;
7700 JNI_TRACE("ssl=%p new_session_callback calling onNewSessionEstablished", ssl);
7701 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(session));
7702 if (env->ExceptionCheck()) {
7703 JNI_TRACE("ssl=%p new_session_callback exception cleared", ssl);
7704 env->ExceptionClear();
7705 }
7706 JNI_TRACE("ssl=%p new_session_callback completed", ssl);
7707
7708 // Always returning 0 (not taking ownership). The Java code is responsible for incrementing
7709 // the reference count.
7710 return 0;
7711 }
7712
server_session_requested_callback(SSL * ssl,const uint8_t * id,int id_len,int * out_copy)7713 static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* id, int id_len,
7714 int* out_copy) {
7715 JNI_TRACE("ssl=%p server_session_requested_callback", ssl);
7716
7717 // Always set to out_copy to zero. The Java callback will be responsible for incrementing
7718 // the reference count (and any required synchronization).
7719 *out_copy = 0;
7720
7721 AppData* appData = toAppData(ssl);
7722 JNIEnv* env = appData->env;
7723 if (env == nullptr) {
7724 CONSCRYPT_LOG_ERROR("AppData->env missing in server_session_requested_callback");
7725 JNI_TRACE("ssl=%p server_session_requested_callback env error", ssl);
7726 return 0;
7727 }
7728 if (env->ExceptionCheck()) {
7729 JNI_TRACE("ssl=%p server_session_requested_callback already pending exception", ssl);
7730 return 0;
7731 }
7732
7733 // Copy the ID to a byte[].
7734 jbyteArray id_array = env->NewByteArray(static_cast<jsize>(id_len));
7735 if (id_array == nullptr) {
7736 JNI_TRACE("ssl=%p id_array bytes == null => 0", ssl);
7737 return 0;
7738 }
7739 env->SetByteArrayRegion(id_array, 0, static_cast<jsize>(id_len),
7740 reinterpret_cast<const jbyte*>(id));
7741
7742 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7743 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_serverSessionRequested;
7744 JNI_TRACE("ssl=%p server_session_requested_callback calling serverSessionRequested", ssl);
7745 jlong ssl_session_address = env->CallLongMethod(sslHandshakeCallbacks, methodID, id_array);
7746 if (env->ExceptionCheck()) {
7747 JNI_TRACE("ssl=%p server_session_requested_callback exception cleared", ssl);
7748 env->ExceptionClear();
7749 }
7750 SSL_SESSION* ssl_session_ptr =
7751 reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
7752 JNI_TRACE("ssl=%p server_session_requested_callback completed => %p", ssl, ssl_session_ptr);
7753 return ssl_session_ptr;
7754 }
7755
NativeCrypto_EVP_has_aes_hardware(JNIEnv * env,jclass)7756 static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) {
7757 CHECK_ERROR_QUEUE_ON_RETURN;
7758 int ret = 0;
7759 ret = EVP_has_aes_hardware();
7760 JNI_TRACE("EVP_has_aes_hardware => %d", ret);
7761 return ret;
7762 }
7763
debug_print_session_key(const SSL * ssl,const char * line)7764 static void debug_print_session_key(const SSL* ssl, const char* line) {
7765 JNI_TRACE_KEYS("ssl=%p KEY_LINE: %s", ssl, line);
7766 }
7767
debug_print_packet_data(const SSL * ssl,char direction,const char * data,size_t len)7768 static void debug_print_packet_data(const SSL* ssl, char direction, const char* data, size_t len) {
7769 static constexpr size_t kDataWidth = 16;
7770
7771 struct timeval tv;
7772 if (gettimeofday(&tv, NULL)) {
7773 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7774 "debug_print_packet_data: could not get time of day");
7775 return;
7776 }
7777
7778 // Packet preamble for text2pcap
7779 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %c %ld.%06ld", ssl, direction,
7780 static_cast<long>(tv.tv_sec),
7781 static_cast<long>(tv.tv_usec)); // NOLINT(runtime/int)
7782
7783 char out[kDataWidth * 3 + 1];
7784 for (size_t i = 0; i < len; i += kDataWidth) {
7785 size_t n = len - i < kDataWidth ? len - i : kDataWidth;
7786
7787 for (size_t j = 0, offset = 0; j < n; j++, offset += 3) {
7788 int ret = snprintf(out + offset, sizeof(out) - offset, "%02x ", data[i + j] & 0xFF);
7789 if (ret < 0 || static_cast<size_t>(ret) >= sizeof(out) - offset) {
7790 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni",
7791 "debug_print_packet_data failed to output %d", ret);
7792 return;
7793 }
7794 }
7795
7796 // Print out packet data in format understood by text2pcap
7797 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx %s", ssl, i, out);
7798 }
7799
7800 // Conclude the packet data
7801 CONSCRYPT_LOG(LOG_INFO, LOG_TAG "-jni", "ssl=%p SSL_DATA: %06zx", ssl, len);
7802 }
7803
7804 /*
7805 * public static native int SSL_CTX_new();
7806 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7807 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7808 CHECK_ERROR_QUEUE_ON_RETURN;
7809 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
7810 if (sslCtx.get() == nullptr) {
7811 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_new");
7812 return 0;
7813 }
7814 SSL_CTX_set_options(
7815 sslCtx.get(),
7816 SSL_OP_ALL
7817 // We also disable session tickets for better compatibility b/2682876
7818 | SSL_OP_NO_TICKET
7819 // We also disable compression for better compatibility b/2710492 b/2710497
7820 | SSL_OP_NO_COMPRESSION
7821 // Generate a fresh ECDH keypair for each key exchange.
7822 | SSL_OP_SINGLE_ECDH_USE);
7823 SSL_CTX_set_min_proto_version(sslCtx.get(), TLS1_VERSION);
7824 SSL_CTX_set_max_proto_version(sslCtx.get(), TLS1_2_VERSION);
7825
7826 uint32_t mode = SSL_CTX_get_mode(sslCtx.get());
7827 /*
7828 * Turn on "partial write" mode. This means that SSL_write() will
7829 * behave like Posix write() and possibly return after only
7830 * writing a partial buffer. Note: The alternative, perhaps
7831 * surprisingly, is not that SSL_write() always does full writes
7832 * but that it will force you to retry write calls having
7833 * preserved the full state of the original call. (This is icky
7834 * and undesirable.)
7835 */
7836 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7837
7838 // Reuse empty buffers within the SSL_CTX to save memory
7839 mode |= SSL_MODE_RELEASE_BUFFERS;
7840
7841 // Enable False Start.
7842 mode |= SSL_MODE_ENABLE_FALSE_START;
7843
7844 // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change
7845 // between
7846 // calls to wrap(...).
7847 // See https://github.com/netty/netty-tcnative/issues/100
7848 mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
7849
7850 SSL_CTX_set_mode(sslCtx.get(), mode);
7851
7852 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7853 SSL_CTX_set_cert_cb(sslCtx.get(), cert_cb, nullptr);
7854 SSL_CTX_set_select_certificate_cb(sslCtx.get(), select_certificate_cb);
7855 if (conscrypt::trace::kWithJniTraceKeys) {
7856 SSL_CTX_set_keylog_callback(sslCtx.get(), debug_print_session_key);
7857 }
7858
7859 // By default BoringSSL will cache in server mode, but we want to get
7860 // notified of new sessions being created in client mode. We set
7861 // SSL_SESS_CACHE_BOTH in order to get the callback in client mode, but
7862 // ignore it in server mode in favor of the internal cache.
7863 SSL_CTX_set_session_cache_mode(sslCtx.get(), SSL_SESS_CACHE_BOTH);
7864 SSL_CTX_sess_set_new_cb(sslCtx.get(), new_session_callback);
7865 SSL_CTX_sess_set_get_cb(sslCtx.get(), server_session_requested_callback);
7866
7867 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7868 return (jlong)sslCtx.release();
7869 }
7870
7871 /**
7872 * public static native void SSL_CTX_free(long ssl_ctx)
7873 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7874 static void NativeCrypto_SSL_CTX_free(JNIEnv* env, jclass, jlong ssl_ctx_address,
7875 CONSCRYPT_UNUSED jobject holder) {
7876 CHECK_ERROR_QUEUE_ON_RETURN;
7877 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7878 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7879 if (ssl_ctx == nullptr) {
7880 return;
7881 }
7882 SSL_CTX_free(ssl_ctx);
7883 }
7884
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jbyteArray sid_ctx)7885 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass, jlong ssl_ctx_address,
7886 CONSCRYPT_UNUSED jobject holder,
7887 jbyteArray sid_ctx) {
7888 CHECK_ERROR_QUEUE_ON_RETURN;
7889 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7890 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx,
7891 sid_ctx);
7892 if (ssl_ctx == nullptr) {
7893 return;
7894 }
7895
7896 ScopedByteArrayRO buf(env, sid_ctx);
7897 if (buf.get() == nullptr) {
7898 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception",
7899 ssl_ctx);
7900 return;
7901 }
7902
7903 unsigned int length = static_cast<unsigned int>(buf.size());
7904 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7905 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
7906 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7907 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7908 return;
7909 }
7910 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7911 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7912 if (result == 0) {
7913 conscrypt::jniutil::throwExceptionFromBoringSSLError(
7914 env, "NativeCrypto_SSL_CTX_set_session_id_context");
7915 return;
7916 }
7917 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7918 }
7919
NativeCrypto_SSL_CTX_set_timeout(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder,jlong seconds)7920 static jlong NativeCrypto_SSL_CTX_set_timeout(JNIEnv* env, jclass, jlong ssl_ctx_address,
7921 CONSCRYPT_UNUSED jobject holder, jlong seconds) {
7922 CHECK_ERROR_QUEUE_ON_RETURN;
7923 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7924 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_timeout seconds=%d", ssl_ctx, (int)seconds);
7925 if (ssl_ctx == nullptr) {
7926 return 0L;
7927 }
7928
7929 return SSL_CTX_set_timeout(ssl_ctx, static_cast<uint32_t>(seconds));
7930 }
7931
7932 /**
7933 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7934 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)7935 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address,
7936 CONSCRYPT_UNUSED jobject holder) {
7937 CHECK_ERROR_QUEUE_ON_RETURN;
7938 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7939 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7940 if (ssl_ctx == nullptr) {
7941 return 0;
7942 }
7943 bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
7944 if (ssl.get() == nullptr) {
7945 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, nullptr, SSL_ERROR_NONE,
7946 "Unable to create SSL structure");
7947 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => null", ssl_ctx);
7948 return 0;
7949 }
7950
7951 /*
7952 * Create our special application data.
7953 */
7954 AppData* appData = AppData::create();
7955 if (appData == nullptr) {
7956 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to create application data");
7957 ERR_clear_error();
7958 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7959 return 0;
7960 }
7961 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7962
7963 SSL_set_custom_verify(ssl.get(), SSL_VERIFY_PEER, cert_verify_callback);
7964
7965 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7966 return (jlong)ssl.release();
7967 }
7968
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7969 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7970 CONSCRYPT_UNUSED jobject ssl_holder) {
7971 CHECK_ERROR_QUEUE_ON_RETURN;
7972 SSL* ssl = to_SSL(env, ssl_address, true);
7973 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id", ssl);
7974 if (ssl == nullptr) {
7975 return;
7976 }
7977
7978 // NOLINTNEXTLINE(runtime/int)
7979 long ret = SSL_enable_tls_channel_id(ssl);
7980 if (ret != 1L) {
7981 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
7982 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
7983 "Error enabling Channel ID");
7984 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7985 return;
7986 }
7987 }
7988
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)7989 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
7990 CONSCRYPT_UNUSED jobject ssl_holder) {
7991 CHECK_ERROR_QUEUE_ON_RETURN;
7992 SSL* ssl = to_SSL(env, ssl_address, true);
7993 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id", ssl);
7994 if (ssl == nullptr) {
7995 return nullptr;
7996 }
7997
7998 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7999 // as a constant anywhere.
8000 jbyteArray javaBytes = env->NewByteArray(64);
8001 ScopedByteArrayRW bytes(env, javaBytes);
8002 if (bytes.get() == nullptr) {
8003 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => null", ssl);
8004 return nullptr;
8005 }
8006
8007 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
8008 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
8009 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
8010 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
8011 size_t ret = SSL_get_tls_channel_id(ssl, tmp, 64);
8012 if (ret == 0) {
8013 // Channel ID either not set or did not verify
8014 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
8015 return nullptr;
8016 } else if (ret != 64) {
8017 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
8018 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8019 "Error getting Channel ID");
8020 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %zd", ssl, ret);
8021 return nullptr;
8022 }
8023
8024 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
8025 return javaBytes;
8026 }
8027
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject pkeyRef)8028 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address,
8029 CONSCRYPT_UNUSED jobject ssl_holder,
8030 jobject pkeyRef) {
8031 CHECK_ERROR_QUEUE_ON_RETURN;
8032 SSL* ssl = to_SSL(env, ssl_address, true);
8033 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkeyRef);
8034 if (ssl == nullptr) {
8035 return;
8036 }
8037
8038 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
8039 if (pkey == nullptr) {
8040 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
8041 return;
8042 }
8043
8044 // NOLINTNEXTLINE(runtime/int)
8045 long ret = SSL_set1_tls_channel_id(ssl, pkey);
8046
8047 if (ret != 1L) {
8048 CONSCRYPT_LOG_ERROR("%s", ERR_error_string(ERR_peek_error(), nullptr));
8049 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
8050 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
8051 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
8052 return;
8053 }
8054
8055 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
8056 }
8057
NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray encodedCertificatesJava,jobject pkeyRef)8058 static void NativeCrypto_setLocalCertsAndPrivateKey(JNIEnv* env, jclass, jlong ssl_address,
8059 CONSCRYPT_UNUSED jobject ssl_holder,
8060 jobjectArray encodedCertificatesJava,
8061 jobject pkeyRef) {
8062 CHECK_ERROR_QUEUE_ON_RETURN;
8063 SSL* ssl = to_SSL(env, ssl_address, true);
8064 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key certificates=%p, privateKey=%p", ssl,
8065 encodedCertificatesJava, pkeyRef);
8066 if (ssl == nullptr) {
8067 return;
8068 }
8069 if (encodedCertificatesJava == nullptr) {
8070 conscrypt::jniutil::throwNullPointerException(env, "certificates == null");
8071 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates == null", ssl);
8072 return;
8073 }
8074 size_t numCerts = static_cast<size_t>(env->GetArrayLength(encodedCertificatesJava));
8075 if (numCerts == 0) {
8076 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8077 "certificates.length == 0");
8078 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => certificates.length == 0", ssl);
8079 return;
8080 }
8081 if (pkeyRef == nullptr) {
8082 conscrypt::jniutil::throwNullPointerException(env, "privateKey == null");
8083 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => privateKey == null", ssl);
8084 return;
8085 }
8086
8087 // Get the private key.
8088 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
8089 if (pkey == nullptr) {
8090 conscrypt::jniutil::throwNullPointerException(env, "pkey == null");
8091 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => pkey == null", ssl);
8092 return;
8093 }
8094
8095 // Copy the certificates.
8096 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certBufferRefs(numCerts);
8097 std::vector<CRYPTO_BUFFER*> certBuffers(numCerts);
8098 for (size_t i = 0; i < numCerts; ++i) {
8099 ScopedLocalRef<jbyteArray> certArray(
8100 env, reinterpret_cast<jbyteArray>(
8101 env->GetObjectArrayElement(encodedCertificatesJava, i)));
8102 certBufferRefs[i] = ByteArrayToCryptoBuffer(env, certArray.get(), nullptr);
8103 if (!certBufferRefs[i]) {
8104 return;
8105 }
8106 certBuffers[i] = certBufferRefs[i].get();
8107 }
8108
8109 if (!SSL_set_chain_and_key(ssl, certBuffers.data(), numCerts, pkey, nullptr)) {
8110 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8111 "Error configuring certificate");
8112 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => error", ssl);
8113 return;
8114 }
8115 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_chain_and_key => ok", ssl);
8116 }
8117
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray principals)8118 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass, jlong ssl_address,
8119 CONSCRYPT_UNUSED jobject ssl_holder,
8120 jobjectArray principals) {
8121 CHECK_ERROR_QUEUE_ON_RETURN;
8122 SSL* ssl = to_SSL(env, ssl_address, true);
8123 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
8124 if (ssl == nullptr) {
8125 return;
8126 }
8127
8128 if (principals == nullptr) {
8129 conscrypt::jniutil::throwNullPointerException(env, "principals == null");
8130 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
8131 return;
8132 }
8133
8134 int length = env->GetArrayLength(principals);
8135 if (length == 0) {
8136 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8137 "principals.length == 0");
8138 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
8139 return;
8140 }
8141
8142 bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> principalsStack(sk_CRYPTO_BUFFER_new_null());
8143 if (principalsStack.get() == nullptr) {
8144 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate principal stack");
8145 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
8146 return;
8147 }
8148 for (int i = 0; i < length; i++) {
8149 ScopedLocalRef<jbyteArray> principal(
8150 env, reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
8151 bssl::UniquePtr<CRYPTO_BUFFER> buf = ByteArrayToCryptoBuffer(env, principal.get(), nullptr);
8152 if (!buf) {
8153 return;
8154 }
8155 if (!sk_CRYPTO_BUFFER_push(principalsStack.get(), buf.get())) {
8156 conscrypt::jniutil::throwOutOfMemory(env, "Unable to push principal");
8157 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
8158 return;
8159 }
8160 OWNERSHIP_TRANSFERRED(buf);
8161 }
8162
8163 SSL_set0_client_CAs(ssl, principalsStack.release());
8164 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
8165 }
8166
8167 /**
8168 * public static native long SSL_set_mode(long ssl, long mode);
8169 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)8170 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass, jlong ssl_address,
8171 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
8172 CHECK_ERROR_QUEUE_ON_RETURN;
8173 SSL* ssl = to_SSL(env, ssl_address, true);
8174 // NOLINTNEXTLINE(runtime/int)
8175 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long)mode);
8176 if (ssl == nullptr) {
8177 return 0;
8178 }
8179 jlong result = static_cast<jlong>(SSL_set_mode(ssl, static_cast<uint32_t>(mode)));
8180 // NOLINTNEXTLINE(runtime/int)
8181 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, (long)result);
8182 return result;
8183 }
8184
8185 /**
8186 * public static native long SSL_set_options(long ssl, long options);
8187 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8188 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass, jlong ssl_address,
8189 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8190 CHECK_ERROR_QUEUE_ON_RETURN;
8191 SSL* ssl = to_SSL(env, ssl_address, true);
8192 // NOLINTNEXTLINE(runtime/int)
8193 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long)options);
8194 if (ssl == nullptr) {
8195 return 0;
8196 }
8197 jlong result = static_cast<jlong>(SSL_set_options(ssl, static_cast<uint32_t>(options)));
8198 // NOLINTNEXTLINE(runtime/int)
8199 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, (long)result);
8200 return result;
8201 }
8202
8203 /**
8204 * public static native long SSL_clear_options(long ssl, long options);
8205 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong options)8206 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass, jlong ssl_address,
8207 CONSCRYPT_UNUSED jobject ssl_holder, jlong options) {
8208 CHECK_ERROR_QUEUE_ON_RETURN;
8209 SSL* ssl = to_SSL(env, ssl_address, true);
8210 // NOLINTNEXTLINE(runtime/int)
8211 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long)options);
8212 if (ssl == nullptr) {
8213 return 0;
8214 }
8215 jlong result = static_cast<jlong>(SSL_clear_options(ssl, static_cast<uint32_t>(options)));
8216 // NOLINTNEXTLINE(runtime/int)
8217 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, (long)result);
8218 return result;
8219 }
8220
NativeCrypto_SSL_set_protocol_versions(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint min_version,jint max_version)8221 static jint NativeCrypto_SSL_set_protocol_versions(JNIEnv* env, jclass, jlong ssl_address,
8222 CONSCRYPT_UNUSED jobject ssl_holder,
8223 jint min_version, jint max_version) {
8224 CHECK_ERROR_QUEUE_ON_RETURN;
8225 SSL* ssl = to_SSL(env, ssl_address, true);
8226 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions min=0x%x max=0x%x", ssl, min_version,
8227 max_version);
8228 if (ssl == nullptr) {
8229 return 0;
8230 }
8231 int min_result = SSL_set_min_proto_version(ssl, static_cast<uint16_t>(min_version));
8232 int max_result = SSL_set_max_proto_version(ssl, static_cast<uint16_t>(max_version));
8233 // Return failure if either call failed.
8234 int result = 1;
8235 if (!min_result || !max_result) {
8236 result = 0;
8237 // The only possible error is an invalid version, so we don't need the details.
8238 ERR_clear_error();
8239 }
8240 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_protocol_versions => (min: %d, max: %d) == %d", ssl,
8241 min_result, max_result, result);
8242 return result;
8243 }
8244
8245 /**
8246 * public static native void SSL_enable_signed_cert_timestamps(long ssl);
8247 */
NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8248 static void NativeCrypto_SSL_enable_signed_cert_timestamps(JNIEnv* env, jclass, jlong ssl_address,
8249 CONSCRYPT_UNUSED jobject ssl_holder) {
8250 CHECK_ERROR_QUEUE_ON_RETURN;
8251 SSL* ssl = to_SSL(env, ssl_address, true);
8252 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_signed_cert_timestamps", ssl);
8253 if (ssl == nullptr) {
8254 return;
8255 }
8256
8257 SSL_enable_signed_cert_timestamps(ssl);
8258 }
8259
8260 /**
8261 * public static native byte[] SSL_get_signed_cert_timestamp_list(long ssl);
8262 */
NativeCrypto_SSL_get_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8263 static jbyteArray NativeCrypto_SSL_get_signed_cert_timestamp_list(
8264 JNIEnv* env, jclass, jlong ssl_address, CONSCRYPT_UNUSED jobject ssl_holder) {
8265 CHECK_ERROR_QUEUE_ON_RETURN;
8266 SSL* ssl = to_SSL(env, ssl_address, true);
8267 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_signed_cert_timestamp_list", ssl);
8268 if (ssl == nullptr) {
8269 return nullptr;
8270 }
8271
8272 const uint8_t* data;
8273 size_t data_len;
8274 SSL_get0_signed_cert_timestamp_list(ssl, &data, &data_len);
8275
8276 if (data_len == 0) {
8277 JNI_TRACE("NativeCrypto_SSL_get_signed_cert_timestamp_list(%p) => null", ssl);
8278 return nullptr;
8279 }
8280
8281 jbyteArray result = env->NewByteArray(static_cast<jsize>(data_len));
8282 if (result != nullptr) {
8283 env->SetByteArrayRegion(result, 0, static_cast<jsize>(data_len), (const jbyte*)data);
8284 }
8285 return result;
8286 }
8287
8288 /*
8289 * public static native void SSL_set_signed_cert_timestamp_list(long ssl, byte[] response);
8290 */
NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray list)8291 static void NativeCrypto_SSL_set_signed_cert_timestamp_list(JNIEnv* env, jclass, jlong ssl_address,
8292 CONSCRYPT_UNUSED jobject ssl_holder,
8293 jbyteArray list) {
8294 CHECK_ERROR_QUEUE_ON_RETURN;
8295 SSL* ssl = to_SSL(env, ssl_address, true);
8296 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list", ssl);
8297 if (ssl == nullptr) {
8298 return;
8299 }
8300
8301 ScopedByteArrayRO listBytes(env, list);
8302 if (listBytes.get() == nullptr) {
8303 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => list == null", ssl);
8304 return;
8305 }
8306
8307 if (!SSL_set_signed_cert_timestamp_list(ssl, reinterpret_cast<const uint8_t*>(listBytes.get()),
8308 listBytes.size())) {
8309 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => fail", ssl);
8310 } else {
8311 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_signed_cert_timestamp_list => ok", ssl);
8312 }
8313 }
8314
8315 /*
8316 * public static native void SSL_enable_ocsp_stapling(long ssl);
8317 */
NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8318 static void NativeCrypto_SSL_enable_ocsp_stapling(JNIEnv* env, jclass, jlong ssl_address,
8319 CONSCRYPT_UNUSED jobject ssl_holder) {
8320 CHECK_ERROR_QUEUE_ON_RETURN;
8321 SSL* ssl = to_SSL(env, ssl_address, true);
8322 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_ocsp_stapling", ssl);
8323 if (ssl == nullptr) {
8324 return;
8325 }
8326
8327 SSL_enable_ocsp_stapling(ssl);
8328 }
8329
8330 /*
8331 * public static native byte[] SSL_get_ocsp_response(long ssl);
8332 */
NativeCrypto_SSL_get_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8333 static jbyteArray NativeCrypto_SSL_get_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8334 CONSCRYPT_UNUSED jobject ssl_holder) {
8335 CHECK_ERROR_QUEUE_ON_RETURN;
8336 SSL* ssl = to_SSL(env, ssl_address, true);
8337 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ocsp_response", ssl);
8338 if (ssl == nullptr) {
8339 return nullptr;
8340 }
8341
8342 const uint8_t* data;
8343 size_t data_len;
8344 SSL_get0_ocsp_response(ssl, &data, &data_len);
8345
8346 if (data_len == 0) {
8347 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => null", ssl);
8348 return nullptr;
8349 }
8350
8351 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8352 if (byteArray.get() == nullptr) {
8353 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => creating byte array failed", ssl);
8354 return nullptr;
8355 }
8356
8357 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8358 JNI_TRACE("NativeCrypto_SSL_get_ocsp_response(%p) => %p [size=%zd]", ssl, byteArray.get(),
8359 data_len);
8360
8361 return byteArray.release();
8362 }
8363
8364 /*
8365 * public static native void SSL_set_ocsp_response(long ssl, byte[] response);
8366 */
NativeCrypto_SSL_set_ocsp_response(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray response)8367 static void NativeCrypto_SSL_set_ocsp_response(JNIEnv* env, jclass, jlong ssl_address,
8368 CONSCRYPT_UNUSED jobject ssl_holder,
8369 jbyteArray response) {
8370 CHECK_ERROR_QUEUE_ON_RETURN;
8371 SSL* ssl = to_SSL(env, ssl_address, true);
8372 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response", ssl);
8373 if (ssl == nullptr) {
8374 return;
8375 }
8376
8377 ScopedByteArrayRO responseBytes(env, response);
8378 if (responseBytes.get() == nullptr) {
8379 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => response == null", ssl);
8380 return;
8381 }
8382
8383 if (!SSL_set_ocsp_response(ssl, reinterpret_cast<const uint8_t*>(responseBytes.get()),
8384 responseBytes.size())) {
8385 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => fail", ssl);
8386 } else {
8387 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_ocsp_response => ok", ssl);
8388 }
8389 }
8390
8391 // All verify_data values are currently 12 bytes long, but cipher suites are allowed
8392 // to customize the length of their verify_data (with a default of 12 bytes). We accept
8393 // up to 16 bytes so that we can check that the results are actually 12 bytes long in
8394 // tests and update this value if necessary.
8395 const size_t MAX_TLS_UNIQUE_LENGTH = 16;
8396
NativeCrypto_SSL_get_tls_unique(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8397 static jbyteArray NativeCrypto_SSL_get_tls_unique(JNIEnv* env, jclass, jlong ssl_address,
8398 CONSCRYPT_UNUSED jobject ssl_holder) {
8399 CHECK_ERROR_QUEUE_ON_RETURN;
8400 SSL* ssl = to_SSL(env, ssl_address, true);
8401 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_unique", ssl);
8402 if (ssl == nullptr) {
8403 return nullptr;
8404 }
8405
8406 uint8_t data[MAX_TLS_UNIQUE_LENGTH];
8407 size_t data_len;
8408 int ret = SSL_get_tls_unique(ssl, data, &data_len, MAX_TLS_UNIQUE_LENGTH);
8409
8410 if (!ret || data_len == 0) {
8411 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => null", ssl);
8412 return nullptr;
8413 }
8414
8415 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(static_cast<jsize>(data_len)));
8416 if (byteArray.get() == nullptr) {
8417 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => creating byte array failed", ssl);
8418 return nullptr;
8419 }
8420
8421 env->SetByteArrayRegion(byteArray.get(), 0, static_cast<jsize>(data_len), (const jbyte*)data);
8422 JNI_TRACE("NativeCrypto_SSL_get_tls_unique(%p) => %p [size=%zd]", ssl, byteArray.get(),
8423 data_len);
8424
8425 return byteArray.release();
8426 }
8427
NativeCrypto_SSL_export_keying_material(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jbyteArray label,jbyteArray context,jint num_bytes)8428 static jbyteArray NativeCrypto_SSL_export_keying_material(JNIEnv* env, jclass, jlong ssl_address,
8429 CONSCRYPT_UNUSED jobject ssl_holder,
8430 jbyteArray label, jbyteArray context,
8431 jint num_bytes) {
8432 CHECK_ERROR_QUEUE_ON_RETURN;
8433 SSL* ssl = to_SSL(env, ssl_address, true);
8434 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material", ssl);
8435 if (ssl == nullptr) {
8436 return nullptr;
8437 }
8438 ScopedByteArrayRO labelBytes(env, label);
8439 if (labelBytes.get() == nullptr) {
8440 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material label == null => exception", ssl);
8441 return nullptr;
8442 }
8443 std::unique_ptr<uint8_t[]> out(new uint8_t[num_bytes]);
8444 int ret;
8445 if (context == nullptr) {
8446 ret = SSL_export_keying_material(ssl, out.get(), num_bytes,
8447 reinterpret_cast<const char*>(labelBytes.get()), labelBytes.size(),
8448 nullptr, 0, 0);
8449 } else {
8450 ScopedByteArrayRO contextBytes(env, context);
8451 if (contextBytes.get() == nullptr) {
8452 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material context == null => exception",
8453 ssl);
8454 return nullptr;
8455 }
8456 ret = SSL_export_keying_material(
8457 ssl, out.get(), num_bytes, reinterpret_cast<const char*>(labelBytes.get()),
8458 labelBytes.size(), reinterpret_cast<const uint8_t*>(contextBytes.get()),
8459 contextBytes.size(), 1);
8460 }
8461 if (!ret) {
8462 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_export_keying_material",
8463 conscrypt::jniutil::throwSSLExceptionStr);
8464 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => exception", ssl);
8465 return nullptr;
8466 }
8467 jbyteArray result = env->NewByteArray(static_cast<jsize>(num_bytes));
8468 if (result == nullptr) {
8469 conscrypt::jniutil::throwSSLExceptionStr(env, "Could not create result array");
8470 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => could not create array", ssl);
8471 return nullptr;
8472 }
8473 const jbyte* src = reinterpret_cast<jbyte*>(out.get());
8474 env->SetByteArrayRegion(result, 0, static_cast<jsize>(num_bytes), src);
8475 JNI_TRACE("ssl=%p NativeCrypto_SSL_export_keying_material => success", ssl);
8476 return result;
8477 }
8478
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring identityHintJava)8479 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass, jlong ssl_address,
8480 CONSCRYPT_UNUSED jobject ssl_holder,
8481 jstring identityHintJava) {
8482 CHECK_ERROR_QUEUE_ON_RETURN;
8483 SSL* ssl = to_SSL(env, ssl_address, true);
8484 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p", ssl,
8485 identityHintJava);
8486 if (ssl == nullptr) {
8487 return;
8488 }
8489
8490 int ret;
8491 if (identityHintJava == nullptr) {
8492 ret = SSL_use_psk_identity_hint(ssl, nullptr);
8493 } else {
8494 ScopedUtfChars identityHint(env, identityHintJava);
8495 if (identityHint.c_str() == nullptr) {
8496 conscrypt::jniutil::throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
8497 return;
8498 }
8499 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
8500 }
8501
8502 if (ret != 1) {
8503 int sslErrorCode = SSL_get_error(ssl, ret);
8504 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8505 "Failed to set PSK identity hint");
8506 }
8507 }
8508
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8509 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8510 CONSCRYPT_UNUSED jobject ssl_holder,
8511 jboolean enabled) {
8512 CHECK_ERROR_QUEUE_ON_RETURN;
8513 SSL* ssl = to_SSL(env, ssl_address, true);
8514 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)", ssl, enabled);
8515 if (ssl == nullptr) {
8516 return;
8517 }
8518
8519 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : nullptr);
8520 }
8521
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean enabled)8522 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass, jlong ssl_address,
8523 CONSCRYPT_UNUSED jobject ssl_holder,
8524 jboolean enabled) {
8525 CHECK_ERROR_QUEUE_ON_RETURN;
8526 SSL* ssl = to_SSL(env, ssl_address, true);
8527 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)", ssl, enabled);
8528 if (ssl == nullptr) {
8529 return;
8530 }
8531
8532 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : nullptr);
8533 }
8534
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8535 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address,
8536 CONSCRYPT_UNUSED jobject ssl_holder) {
8537 CHECK_ERROR_QUEUE_ON_RETURN;
8538 SSL* ssl = to_SSL(env, ssl_address, true);
8539 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
8540 if (ssl == nullptr) {
8541 return nullptr;
8542 }
8543
8544 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
8545 size_t count = (cipherStack != nullptr) ? sk_SSL_CIPHER_num(cipherStack) : 0;
8546 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(static_cast<jsize>(count)));
8547 ScopedLongArrayRW ciphers(env, ciphersArray.get());
8548 for (size_t i = 0; i < count; i++) {
8549 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
8550 }
8551
8552 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%zu]", ssl, ciphersArray.get(), count);
8553 return ciphersArray.release();
8554 }
8555
8556 /**
8557 * Sets the ciphers suites that are enabled in the SSL
8558 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobjectArray cipherSuites)8559 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
8560 CONSCRYPT_UNUSED jobject ssl_holder,
8561 jobjectArray cipherSuites) {
8562 CHECK_ERROR_QUEUE_ON_RETURN;
8563 SSL* ssl = to_SSL(env, ssl_address, true);
8564 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
8565 if (ssl == nullptr) {
8566 return;
8567 }
8568 if (cipherSuites == nullptr) {
8569 conscrypt::jniutil::throwNullPointerException(env, "cipherSuites == null");
8570 return;
8571 }
8572
8573 int length = env->GetArrayLength(cipherSuites);
8574
8575 /*
8576 * Special case for empty cipher list. This is considered an error by the
8577 * SSL_set_cipher_list API, but Java allows this silly configuration.
8578 * However, the SSL cipher list is still set even when SSL_set_cipher_list
8579 * returns 0 in this case. Just to make sure, we check the resulting cipher
8580 * list to make sure it's zero length.
8581 */
8582 if (length == 0) {
8583 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
8584 SSL_set_cipher_list(ssl, "");
8585 ERR_clear_error();
8586 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
8587 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
8588 conscrypt::jniutil::throwRuntimeException(
8589 env, "SSL_set_cipher_list did not update ciphers!");
8590 ERR_clear_error();
8591 }
8592 return;
8593 }
8594
8595 static const char noSSLv2[] = "!SSLv2";
8596 size_t cipherStringLen = strlen(noSSLv2);
8597
8598 for (int i = 0; i < length; i++) {
8599 ScopedLocalRef<jstring> cipherSuite(
8600 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8601 ScopedUtfChars c(env, cipherSuite.get());
8602 if (c.c_str() == nullptr) {
8603 return;
8604 }
8605
8606 if (cipherStringLen + 1 < cipherStringLen) {
8607 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8608 "Overflow in cipher suite strings");
8609 return;
8610 }
8611 cipherStringLen += 1; /* For the separating colon */
8612
8613 if (cipherStringLen + c.size() < cipherStringLen) {
8614 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8615 "Overflow in cipher suite strings");
8616 return;
8617 }
8618 cipherStringLen += c.size();
8619 }
8620
8621 if (cipherStringLen + 1 < cipherStringLen) {
8622 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8623 "Overflow in cipher suite strings");
8624 return;
8625 }
8626 cipherStringLen += 1; /* For final NUL. */
8627
8628 std::unique_ptr<char[]> cipherString(new char[cipherStringLen]);
8629 if (cipherString.get() == nullptr) {
8630 conscrypt::jniutil::throwOutOfMemory(env, "Unable to alloc cipher string");
8631 return;
8632 }
8633 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
8634 size_t j = strlen(noSSLv2);
8635
8636 for (int i = 0; i < length; i++) {
8637 ScopedLocalRef<jstring> cipherSuite(
8638 env, reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8639 ScopedUtfChars c(env, cipherSuite.get());
8640
8641 cipherString[j++] = ':';
8642 memcpy(&cipherString[j], c.c_str(), c.size());
8643 j += c.size();
8644 }
8645
8646 cipherString[j++] = 0;
8647 if (j != cipherStringLen) {
8648 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8649 "Internal error");
8650 return;
8651 }
8652
8653 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
8654 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
8655 ERR_clear_error();
8656 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
8657 "Illegal cipher suite strings.");
8658 return;
8659 }
8660 }
8661
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8662 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong ssl_address,
8663 CONSCRYPT_UNUSED jobject ssl_holder) {
8664 CHECK_ERROR_QUEUE_ON_RETURN;
8665 SSL* ssl = to_SSL(env, ssl_address, true);
8666 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
8667 if (ssl == nullptr) {
8668 return;
8669 }
8670 SSL_set_accept_state(ssl);
8671 }
8672
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8673 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong ssl_address,
8674 CONSCRYPT_UNUSED jobject ssl_holder) {
8675 CHECK_ERROR_QUEUE_ON_RETURN;
8676 SSL* ssl = to_SSL(env, ssl_address, true);
8677 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
8678 if (ssl == nullptr) {
8679 return;
8680 }
8681 SSL_set_connect_state(ssl);
8682 }
8683
8684 /**
8685 * Sets certificate expectations, especially for server to request client auth
8686 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint mode)8687 static void NativeCrypto_SSL_set_verify(JNIEnv* env, jclass, jlong ssl_address,
8688 CONSCRYPT_UNUSED jobject ssl_holder, jint mode) {
8689 CHECK_ERROR_QUEUE_ON_RETURN;
8690 SSL* ssl = to_SSL(env, ssl_address, true);
8691 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
8692 if (ssl == nullptr) {
8693 return;
8694 }
8695 SSL_set_custom_verify(ssl, static_cast<int>(mode), cert_verify_callback);
8696 }
8697
8698 /**
8699 * Sets the ciphers suites that are enabled in the SSL
8700 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong ssl_session_address)8701 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass, jlong ssl_address,
8702 CONSCRYPT_UNUSED jobject ssl_holder,
8703 jlong ssl_session_address) {
8704 CHECK_ERROR_QUEUE_ON_RETURN;
8705 SSL* ssl = to_SSL(env, ssl_address, true);
8706 if (ssl == nullptr) {
8707 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session => exception", ssl);
8708 return;
8709 }
8710
8711 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
8712 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
8713 if (ssl_session == nullptr) {
8714 return;
8715 }
8716
8717 int ret = SSL_set_session(ssl, ssl_session);
8718 if (ret != 1) {
8719 /*
8720 * Translate the error, and throw if it turns out to be a real
8721 * problem.
8722 */
8723 int sslErrorCode = SSL_get_error(ssl, ret);
8724 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8725 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode,
8726 "SSL session set");
8727 }
8728 }
8729 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p => ret=%d", ssl, ssl_session,
8730 ret);
8731 }
8732
8733 /**
8734 * Sets the ciphers suites that are enabled in the SSL
8735 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean creation_enabled)8736 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass, jlong ssl_address,
8737 CONSCRYPT_UNUSED jobject ssl_holder,
8738 jboolean creation_enabled) {
8739 CHECK_ERROR_QUEUE_ON_RETURN;
8740 SSL* ssl = to_SSL(env, ssl_address, true);
8741 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl,
8742 creation_enabled);
8743 if (ssl == nullptr) {
8744 return;
8745 }
8746
8747 if (creation_enabled) {
8748 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8749 } else {
8750 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8751 }
8752 }
8753
NativeCrypto_SSL_session_reused(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8754 static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address,
8755 CONSCRYPT_UNUSED jobject ssl_holder) {
8756 CHECK_ERROR_QUEUE_ON_RETURN;
8757 SSL* ssl = to_SSL(env, ssl_address, true);
8758 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8759 if (ssl == nullptr) {
8760 return JNI_FALSE;
8761 }
8762
8763 int reused = SSL_session_reused(ssl);
8764 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8765 return static_cast<jboolean>(reused);
8766 }
8767
NativeCrypto_SSL_accept_renegotiations(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8768 static void NativeCrypto_SSL_accept_renegotiations(JNIEnv* env, jclass, jlong ssl_address,
8769 CONSCRYPT_UNUSED jobject ssl_holder) {
8770 CHECK_ERROR_QUEUE_ON_RETURN;
8771 SSL* ssl = to_SSL(env, ssl_address, true);
8772 JNI_TRACE("ssl=%p NativeCrypto_SSL_accept_renegotiations", ssl);
8773 if (ssl == nullptr) {
8774 return;
8775 }
8776
8777 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_freely);
8778 }
8779
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jstring hostname)8780 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass, jlong ssl_address,
8781 CONSCRYPT_UNUSED jobject ssl_holder,
8782 jstring hostname) {
8783 CHECK_ERROR_QUEUE_ON_RETURN;
8784 SSL* ssl = to_SSL(env, ssl_address, true);
8785 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p", ssl, hostname);
8786 if (ssl == nullptr) {
8787 return;
8788 }
8789
8790 ScopedUtfChars hostnameChars(env, hostname);
8791 if (hostnameChars.c_str() == nullptr) {
8792 return;
8793 }
8794 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", ssl,
8795 hostnameChars.c_str());
8796
8797 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8798 if (ret != 1) {
8799 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8800 "Error setting host name");
8801 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8802 return;
8803 }
8804 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8805 }
8806
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8807 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address,
8808 CONSCRYPT_UNUSED jobject ssl_holder) {
8809 CHECK_ERROR_QUEUE_ON_RETURN;
8810 SSL* ssl = to_SSL(env, ssl_address, true);
8811 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8812 if (ssl == nullptr) {
8813 return nullptr;
8814 }
8815 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8816 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8817 return env->NewStringUTF(servername);
8818 }
8819
8820 /**
8821 * Selects the ALPN protocol to use. The list of protocols in "primary" is considered the order
8822 * which should take precedence.
8823 */
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)8824 static int selectApplicationProtocol(SSL* ssl, unsigned char** out, unsigned char* outLength,
8825 const unsigned char* primary,
8826 const unsigned int primaryLength,
8827 const unsigned char* secondary,
8828 const unsigned int secondaryLength) {
8829 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8830
8831 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8832 secondaryLength);
8833 switch (status) {
8834 case OPENSSL_NPN_NEGOTIATED:
8835 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN negotiated", ssl);
8836 return SSL_TLSEXT_ERR_OK;
8837 break;
8838 case OPENSSL_NPN_UNSUPPORTED:
8839 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN unsupported", ssl);
8840 break;
8841 case OPENSSL_NPN_NO_OVERLAP:
8842 JNI_TRACE("ssl=%p selectApplicationProtocol ALPN no overlap", ssl);
8843 break;
8844 }
8845 return SSL_TLSEXT_ERR_NOACK;
8846 }
8847
8848 /**
8849 * Calls out to an application-provided selector to choose the ALPN protocol.
8850 */
selectApplicationProtocol(SSL * ssl,JNIEnv * env,jobject sslHandshakeCallbacks,unsigned char ** out,unsigned char * outLen,const unsigned char * in,const unsigned int inLen)8851 static int selectApplicationProtocol(SSL* ssl, JNIEnv* env, jobject sslHandshakeCallbacks,
8852 unsigned char** out,
8853 unsigned char* outLen, const unsigned char* in,
8854 const unsigned int inLen) {
8855 // Copy the input array.
8856 ScopedLocalRef<jbyteArray> protocols(env, env->NewByteArray(static_cast<jsize>(inLen)));
8857 if (protocols.get() == nullptr) {
8858 JNI_TRACE("ssl=%p selectApplicationProtocol failed allocating array", ssl);
8859 return SSL_TLSEXT_ERR_NOACK;
8860 }
8861 env->SetByteArrayRegion(protocols.get(), 0, (static_cast<jsize>(inLen)),
8862 reinterpret_cast<const jbyte*>(in));
8863
8864 // Invoke the selection method.
8865 jmethodID methodID = conscrypt::jniutil::sslHandshakeCallbacks_selectApplicationProtocol;
8866 jint offset = env->CallIntMethod(sslHandshakeCallbacks, methodID, protocols.get());
8867
8868 if (offset < 0) {
8869 JNI_TRACE("ssl=%p selectApplicationProtocol selection failed", ssl);
8870 return SSL_TLSEXT_ERR_NOACK;
8871 }
8872
8873 // Point the output to the selected protocol.
8874 *outLen = *(in + offset);
8875 *out = const_cast<unsigned char*>(in + offset + 1);
8876
8877 return SSL_TLSEXT_ERR_OK;
8878 }
8879
8880 /**
8881 * Callback for the server to select an ALPN protocol.
8882 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outLen,const unsigned char * in,unsigned int inLen,void *)8883 static int alpn_select_callback(SSL* ssl, const unsigned char** out, unsigned char* outLen,
8884 const unsigned char* in, unsigned int inLen, void*) {
8885 JNI_TRACE("ssl=%p alpn_select_callback in=%p inLen=%d", ssl, in, inLen);
8886
8887 AppData* appData = toAppData(ssl);
8888 if (appData == nullptr) {
8889 JNI_TRACE("ssl=%p alpn_select_callback appData => 0", ssl);
8890 return SSL_TLSEXT_ERR_NOACK;
8891 }
8892 JNIEnv* env = appData->env;
8893 if (env == nullptr) {
8894 CONSCRYPT_LOG_ERROR("AppData->env missing in alpn_select_callback");
8895 JNI_TRACE("ssl=%p alpn_select_callback => 0", ssl);
8896 return SSL_TLSEXT_ERR_NOACK;
8897 }
8898
8899 if (in == nullptr || (appData->applicationProtocolsData == nullptr &&
8900 !appData->hasApplicationProtocolSelector)) {
8901 if (out != nullptr && outLen != nullptr) {
8902 *out = nullptr;
8903 *outLen = 0;
8904 }
8905 JNI_TRACE("ssl=%p alpn_select_callback protocols => 0", ssl);
8906 return SSL_TLSEXT_ERR_NOACK;
8907 }
8908
8909 if (appData->hasApplicationProtocolSelector) {
8910 return selectApplicationProtocol(ssl, env, appData->sslHandshakeCallbacks,
8911 const_cast<unsigned char**>(out), outLen, in, inLen);
8912 }
8913
8914 return selectApplicationProtocol(ssl, const_cast<unsigned char**>(out), outLen,
8915 reinterpret_cast<unsigned char*>(appData->applicationProtocolsData),
8916 static_cast<unsigned int>(appData->applicationProtocolsLength),
8917 in, inLen);
8918 }
8919
NativeCrypto_getApplicationProtocol(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)8920 static jbyteArray NativeCrypto_getApplicationProtocol(JNIEnv* env, jclass, jlong ssl_address,
8921 CONSCRYPT_UNUSED jobject ssl_holder) {
8922 CHECK_ERROR_QUEUE_ON_RETURN;
8923 SSL* ssl = to_SSL(env, ssl_address, true);
8924 JNI_TRACE("ssl=%p NativeCrypto_getApplicationProtocol", ssl);
8925 if (ssl == nullptr) {
8926 return nullptr;
8927 }
8928 const jbyte* protocol;
8929 unsigned int protocolLength;
8930 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&protocol),
8931 &protocolLength);
8932 if (protocolLength == 0) {
8933 return nullptr;
8934 }
8935 jbyteArray result = env->NewByteArray(static_cast<jsize>(protocolLength));
8936 if (result != nullptr) {
8937 env->SetByteArrayRegion(result, 0, (static_cast<jsize>(protocolLength)), protocol);
8938 }
8939 return result;
8940 }
8941
NativeCrypto_setApplicationProtocols(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean client_mode,jbyteArray protocols)8942 static void NativeCrypto_setApplicationProtocols(JNIEnv* env, jclass, jlong ssl_address,
8943 CONSCRYPT_UNUSED jobject ssl_holder,
8944 jboolean client_mode, jbyteArray protocols) {
8945 CHECK_ERROR_QUEUE_ON_RETURN;
8946 SSL* ssl = to_SSL(env, ssl_address, true);
8947 if (ssl == nullptr) {
8948 return;
8949 }
8950 AppData* appData = toAppData(ssl);
8951 if (appData == nullptr) {
8952 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
8953 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols appData => 0", ssl);
8954 return;
8955 }
8956
8957 if (protocols != nullptr) {
8958 if (client_mode) {
8959 ScopedByteArrayRO protosBytes(env, protocols);
8960 if (protosBytes.get() == nullptr) {
8961 JNI_TRACE(
8962 "ssl=%p NativeCrypto_setApplicationProtocols protocols=%p => "
8963 "protosBytes == null",
8964 ssl, protocols);
8965 return;
8966 }
8967
8968 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8969 int ret = SSL_set_alpn_protos(ssl, tmp, static_cast<unsigned int>(protosBytes.size()));
8970 if (ret != 0) {
8971 conscrypt::jniutil::throwSSLExceptionStr(env,
8972 "Unable to set ALPN protocols for client");
8973 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8974 return;
8975 }
8976 } else {
8977 // Server mode - configure the ALPN protocol selection callback.
8978 if (!appData->setApplicationProtocols(env, protocols)) {
8979 conscrypt::jniutil::throwSSLExceptionStr(env,
8980 "Unable to set ALPN protocols for server");
8981 JNI_TRACE("ssl=%p NativeCrypto_setApplicationProtocols => exception", ssl);
8982 return;
8983 }
8984 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
8985 }
8986 }
8987 }
8988
NativeCrypto_setHasApplicationProtocolSelector(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jboolean hasSelector)8989 static void NativeCrypto_setHasApplicationProtocolSelector(JNIEnv* env, jclass, jlong ssl_address,
8990 CONSCRYPT_UNUSED jobject ssl_holder,
8991 jboolean hasSelector) {
8992 CHECK_ERROR_QUEUE_ON_RETURN;
8993 SSL* ssl = to_SSL(env, ssl_address, true);
8994 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector selector=%d", ssl,
8995 hasSelector);
8996 if (ssl == nullptr) {
8997 return;
8998 }
8999 AppData* appData = toAppData(ssl);
9000 if (appData == nullptr) {
9001 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9002 JNI_TRACE("ssl=%p NativeCrypto_setHasApplicationProtocolSelector appData => 0", ssl);
9003 return;
9004 }
9005
9006 appData->hasApplicationProtocolSelector = hasSelector;
9007 if (hasSelector) {
9008 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, nullptr);
9009 }
9010 }
9011
9012 /**
9013 * Perform SSL handshake
9014 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc,jint timeout_millis)9015 static void NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
9016 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9017 jobject shc, jint timeout_millis) {
9018 CHECK_ERROR_QUEUE_ON_RETURN;
9019 SSL* ssl = to_SSL(env, ssl_address, true);
9020 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d", ssl, fdObject,
9021 shc, timeout_millis);
9022 if (ssl == nullptr) {
9023 return;
9024 }
9025 if (fdObject == nullptr) {
9026 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9027 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => exception", ssl);
9028 return;
9029 }
9030 if (shc == nullptr) {
9031 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9032 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => exception",
9033 ssl);
9034 return;
9035 }
9036
9037 NetFd fd(env, fdObject);
9038 if (fd.isClosed()) {
9039 // SocketException thrown by NetFd.isClosed
9040 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => exception", ssl);
9041 return;
9042 }
9043
9044 int ret = SSL_set_fd(ssl, fd.get());
9045 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
9046
9047 if (ret != 1) {
9048 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9049 "Error setting the file descriptor");
9050 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => exception", ssl);
9051 return;
9052 }
9053
9054 /*
9055 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
9056 * forever and we can use select() to find out if the socket is ready.
9057 */
9058 if (!conscrypt::netutil::setBlocking(fd.get(), false)) {
9059 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to make socket non blocking");
9060 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => exception", ssl);
9061 return;
9062 }
9063
9064 AppData* appData = toAppData(ssl);
9065 if (appData == nullptr) {
9066 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
9067 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => exception", ssl);
9068 return;
9069 }
9070
9071 ret = 0;
9072 SslError sslError;
9073 while (appData->aliveAndKicking) {
9074 errno = 0;
9075
9076 if (!appData->setCallbackState(env, shc, fdObject)) {
9077 // SocketException thrown by NetFd.isClosed
9078 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => exception", ssl);
9079 return;
9080 }
9081 ret = SSL_do_handshake(ssl);
9082 appData->clearCallbackState();
9083 // cert_verify_callback threw exception
9084 if (env->ExceptionCheck()) {
9085 ERR_clear_error();
9086 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => exception", ssl);
9087 return;
9088 }
9089 // success case
9090 if (ret == 1) {
9091 break;
9092 }
9093 // retry case
9094 if (errno == EINTR) {
9095 continue;
9096 }
9097 // error case
9098 sslError.reset(ssl, ret);
9099 JNI_TRACE(
9100 "ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d "
9101 "timeout_millis=%d",
9102 ssl, ret, errno, sslError.get(), timeout_millis);
9103
9104 /*
9105 * If SSL_do_handshake doesn't succeed due to the socket being
9106 * either unreadable or unwritable, we use sslSelect to
9107 * wait for it to become ready. If that doesn't happen
9108 * before the specified timeout or an error occurs, we
9109 * cancel the handshake. Otherwise we try the SSL_connect
9110 * again.
9111 */
9112 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
9113 appData->waitingThreads++;
9114 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
9115
9116 if (selectResult == THROWN_EXCEPTION) {
9117 // SocketException thrown by NetFd.isClosed
9118 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => exception", ssl);
9119 return;
9120 }
9121 if (selectResult == -1) {
9122 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9123 env, ssl, SSL_ERROR_SYSCALL, "handshake error",
9124 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9125 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => exception",
9126 ssl);
9127 return;
9128 }
9129 if (selectResult == 0) {
9130 conscrypt::jniutil::throwSocketTimeoutException(env, "SSL handshake timed out");
9131 ERR_clear_error();
9132 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => exception",
9133 ssl);
9134 return;
9135 }
9136 } else {
9137 // CONSCRYPT_LOG_ERROR("Unknown error %d during handshake", error);
9138 break;
9139 }
9140 }
9141
9142 // clean error. See SSL_do_handshake(3SSL) man page.
9143 if (ret == 0) {
9144 /*
9145 * The other side closed the socket before the handshake could be
9146 * completed, but everything is within the bounds of the TLS protocol.
9147 * We still might want to find out the real reason of the failure.
9148 */
9149 if (sslError.get() == SSL_ERROR_NONE ||
9150 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
9151 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
9152 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
9153 } else {
9154 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9155 env, ssl, sslError.release(), "SSL handshake terminated",
9156 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9157 }
9158 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
9159 return;
9160 }
9161
9162 // unclean error. See SSL_do_handshake(3SSL) man page.
9163 if (ret < 0) {
9164 /*
9165 * Translate the error and throw exception. We are sure it is an error
9166 * at this point.
9167 */
9168 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
9169 env, ssl, sslError.release(), "SSL handshake aborted",
9170 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
9171 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
9172 return;
9173 }
9174 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => success", ssl);
9175 }
9176
NativeCrypto_SSL_get_current_cipher(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9177 static jstring NativeCrypto_SSL_get_current_cipher(JNIEnv* env, jclass, jlong ssl_address,
9178 CONSCRYPT_UNUSED jobject ssl_holder) {
9179 CHECK_ERROR_QUEUE_ON_RETURN;
9180 SSL* ssl = to_SSL(env, ssl_address, true);
9181 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher", ssl);
9182 if (ssl == nullptr) {
9183 return nullptr;
9184 }
9185 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
9186 if (cipher == nullptr) {
9187 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher cipher => null", ssl);
9188 return nullptr;
9189 }
9190 const char* name = SSL_CIPHER_standard_name(cipher);
9191 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_current_cipher => %s", ssl, name);
9192 return env->NewStringUTF(name);
9193 }
9194
NativeCrypto_SSL_get_version(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9195 static jstring NativeCrypto_SSL_get_version(JNIEnv* env, jclass, jlong ssl_address,
9196 CONSCRYPT_UNUSED jobject ssl_holder) {
9197 CHECK_ERROR_QUEUE_ON_RETURN;
9198 SSL* ssl = to_SSL(env, ssl_address, true);
9199 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version", ssl);
9200 if (ssl == nullptr) {
9201 return nullptr;
9202 }
9203 const char* protocol = SSL_get_version(ssl);
9204 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_version => %s", ssl, protocol);
9205 return env->NewStringUTF(protocol);
9206 }
9207
NativeCrypto_SSL_get0_peer_certificates(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9208 static jobjectArray NativeCrypto_SSL_get0_peer_certificates(JNIEnv* env, jclass, jlong ssl_address,
9209 CONSCRYPT_UNUSED jobject ssl_holder) {
9210 CHECK_ERROR_QUEUE_ON_RETURN;
9211 SSL* ssl = to_SSL(env, ssl_address, true);
9212 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates", ssl);
9213 if (ssl == nullptr) {
9214 return nullptr;
9215 }
9216
9217 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
9218 if (chain == nullptr) {
9219 return nullptr;
9220 }
9221
9222 ScopedLocalRef<jobjectArray> array(env, CryptoBuffersToObjectArray(env, chain));
9223 if (array.get() == nullptr) {
9224 return nullptr;
9225 }
9226
9227 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_peer_certificates => %p", ssl, array.get());
9228 return array.release();
9229 }
9230
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,SslError * sslError,int read_timeout_millis)9231 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
9232 SslError* sslError, int read_timeout_millis) {
9233 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
9234
9235 if (len == 0) {
9236 // Don't bother doing anything in this case.
9237 return 0;
9238 }
9239
9240 BIO* rbio = SSL_get_rbio(ssl);
9241 BIO* wbio = SSL_get_wbio(ssl);
9242
9243 AppData* appData = toAppData(ssl);
9244 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
9245 if (appData == nullptr) {
9246 return THROW_SSLEXCEPTION;
9247 }
9248
9249 while (appData->aliveAndKicking) {
9250 errno = 0;
9251
9252 std::unique_lock<std::mutex> appDataLock(appData->mutex);
9253
9254 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9255 !SSL_renegotiate_pending(ssl)) {
9256 JNI_TRACE("ssl=%p sslRead => init is not finished (state: %s)", ssl,
9257 SSL_state_string_long(ssl));
9258 return THROW_SSLEXCEPTION;
9259 }
9260
9261 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9262
9263 if (!appData->setCallbackState(env, shc, fdObject)) {
9264 return THROWN_EXCEPTION;
9265 }
9266 int result = SSL_read(ssl, buf, len);
9267 appData->clearCallbackState();
9268 // callbacks can happen if server requests renegotiation
9269 if (env->ExceptionCheck()) {
9270 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
9271 return THROWN_EXCEPTION;
9272 }
9273 sslError->reset(ssl, result);
9274
9275 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError->get());
9276 if (conscrypt::trace::kWithJniTraceData) {
9277 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9278 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9279 size_t n = result - i;
9280 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9281 n = conscrypt::trace::kWithJniTraceDataChunkSize;
9282 }
9283 JNI_TRACE("ssl=%p sslRead data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9284 }
9285 }
9286
9287 // If we have been successful in moving data around, check whether it
9288 // might make sense to wake up other blocked threads, so they can give
9289 // it a try, too.
9290 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9291 appData->waitingThreads > 0) {
9292 sslNotify(appData);
9293 }
9294
9295 // If we are blocked by the underlying socket, tell the world that
9296 // there will be one more waiting thread now.
9297 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9298 appData->waitingThreads++;
9299 }
9300
9301 appDataLock.unlock();
9302
9303 switch (sslError->get()) {
9304 // Successfully read at least one byte.
9305 case SSL_ERROR_NONE: {
9306 return result;
9307 }
9308
9309 // Read zero bytes. End of stream reached.
9310 case SSL_ERROR_ZERO_RETURN: {
9311 return -1;
9312 }
9313
9314 // Need to wait for availability of underlying layer, then retry.
9315 case SSL_ERROR_WANT_READ:
9316 case SSL_ERROR_WANT_WRITE: {
9317 int selectResult =
9318 sslSelect(env, sslError->get(), fdObject, appData, read_timeout_millis);
9319 if (selectResult == THROWN_EXCEPTION) {
9320 return THROWN_EXCEPTION;
9321 }
9322 if (selectResult == -1) {
9323 return THROW_SSLEXCEPTION;
9324 }
9325 if (selectResult == 0) {
9326 return THROW_SOCKETTIMEOUTEXCEPTION;
9327 }
9328
9329 break;
9330 }
9331
9332 // A problem occurred during a system call, but this is not
9333 // necessarily an error.
9334 case SSL_ERROR_SYSCALL: {
9335 // Connection closed without proper shutdown. Tell caller we
9336 // have reached end-of-stream.
9337 if (result == 0) {
9338 return -1;
9339 }
9340
9341 // System call has been interrupted. Simply retry.
9342 if (errno == EINTR) {
9343 break;
9344 }
9345
9346 // Note that for all other system call errors we fall through
9347 // to the default case, which results in an Exception.
9348 FALLTHROUGH_INTENDED;
9349 }
9350
9351 // Everything else is basically an error.
9352 default: { return THROW_SSLEXCEPTION; }
9353 }
9354 }
9355
9356 return -1;
9357 }
9358
9359 /**
9360 * OpenSSL read function (2): read into buffer at offset n chunks.
9361 * Returns the number of bytes read (success) or value <= 0 (failure).
9362 */
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)9363 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address,
9364 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9365 jobject shc, jbyteArray b, jint offset, jint len,
9366 jint read_timeout_millis) {
9367 CHECK_ERROR_QUEUE_ON_RETURN;
9368 SSL* ssl = to_SSL(env, ssl_address, true);
9369 JNI_TRACE(
9370 "ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d "
9371 "read_timeout_millis=%d",
9372 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
9373 if (ssl == nullptr) {
9374 return 0;
9375 }
9376 if (fdObject == nullptr) {
9377 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9378 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
9379 return 0;
9380 }
9381 if (shc == nullptr) {
9382 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9383 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
9384 return 0;
9385 }
9386 if (b == nullptr) {
9387 conscrypt::jniutil::throwNullPointerException(env, "b == null");
9388 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => b == null", ssl);
9389 return 0;
9390 }
9391
9392 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9393 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9394 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9395 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => ArrayIndexOutOfBoundsException", ssl);
9396 return 0;
9397 }
9398
9399 SslError sslError;
9400 int ret;
9401 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9402 if (len <= 1024) {
9403 // Allocate small buffers on the stack for performance.
9404 jbyte buf[1024];
9405 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&buf[0]), len, &sslError,
9406 read_timeout_millis);
9407 if (ret > 0) {
9408 // Don't bother applying changes if issues were encountered.
9409 env->SetByteArrayRegion(b, offset, ret, &buf[0]);
9410 }
9411 } else {
9412 // Allocate larger buffers on the heap.
9413 // ARRAY_CHUNK_INVALID above ensures that len >= 0.
9414 jint remaining = len;
9415 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9416 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9417 // TODO(flooey): Use new(std::nothrow).
9418 if (buf.get() == nullptr) {
9419 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9420 return 0;
9421 }
9422 // TODO(flooey): Fix cumulative read timeout? The effective timeout is the multiplied
9423 // by the number of internal calls to sslRead() below.
9424 ret = 0;
9425 while (remaining > 0) {
9426 jint temp_ret;
9427 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9428 temp_ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(buf.get()),
9429 chunk_size, &sslError, read_timeout_millis);
9430 if (temp_ret < 0) {
9431 if (ret > 0) {
9432 // We've already read some bytes; attempt to preserve them if this is an
9433 // "expected" error.
9434 if (temp_ret == -1) {
9435 // EOF
9436 break;
9437 } else if (temp_ret == THROWN_EXCEPTION) {
9438 // FD closed. Subsequent calls to sslRead should reproduce the
9439 // exception.
9440 env->ExceptionClear();
9441 break;
9442 }
9443 }
9444 // An error was encountered. Handle below.
9445 ret = temp_ret;
9446 break;
9447 }
9448 env->SetByteArrayRegion(b, offset, temp_ret, buf.get());
9449 if (env->ExceptionCheck()) {
9450 // Error committing changes to JVM.
9451 return -1;
9452 }
9453 // Accumulate bytes read.
9454 ret += temp_ret;
9455 offset += temp_ret;
9456 remaining -= temp_ret;
9457 if (temp_ret < chunk_size) {
9458 // sslRead isn't able to fulfill our request right now.
9459 break;
9460 }
9461 }
9462 }
9463 } else {
9464 ScopedByteArrayRW bytes(env, b);
9465 if (bytes.get() == nullptr) {
9466 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
9467 return 0;
9468 }
9469
9470 ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
9471 &sslError, read_timeout_millis);
9472 }
9473
9474 int result;
9475 switch (ret) {
9476 case THROW_SSLEXCEPTION:
9477 // See sslRead() regarding improper failure to handle normal cases.
9478 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9479 "Read error");
9480 result = -1;
9481 break;
9482 case THROW_SOCKETTIMEOUTEXCEPTION:
9483 conscrypt::jniutil::throwSocketTimeoutException(env, "Read timed out");
9484 result = -1;
9485 break;
9486 case THROWN_EXCEPTION:
9487 // SocketException thrown by NetFd.isClosed
9488 // or RuntimeException thrown by callback
9489 result = -1;
9490 break;
9491 default:
9492 result = ret;
9493 break;
9494 }
9495
9496 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
9497 return result;
9498 }
9499
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,SslError * sslError,int write_timeout_millis)9500 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
9501 SslError* sslError, int write_timeout_millis) {
9502 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d", ssl, buf, len,
9503 write_timeout_millis);
9504
9505 if (len == 0) {
9506 // Don't bother doing anything in this case.
9507 return 0;
9508 }
9509
9510 BIO* rbio = SSL_get_rbio(ssl);
9511 BIO* wbio = SSL_get_wbio(ssl);
9512
9513 AppData* appData = toAppData(ssl);
9514 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
9515 if (appData == nullptr) {
9516 return THROW_SSLEXCEPTION;
9517 }
9518
9519 int count = len;
9520
9521 while (appData->aliveAndKicking && len > 0) {
9522 errno = 0;
9523
9524 std::unique_lock<std::mutex> appDataLock(appData->mutex);
9525
9526 if (!SSL_is_init_finished(ssl) && !SSL_in_false_start(ssl) &&
9527 !SSL_renegotiate_pending(ssl)) {
9528 JNI_TRACE("ssl=%p sslWrite => init is not finished (state: %s)", ssl,
9529 SSL_state_string_long(ssl));
9530 return THROW_SSLEXCEPTION;
9531 }
9532
9533 size_t bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
9534
9535 if (!appData->setCallbackState(env, shc, fdObject)) {
9536 return THROWN_EXCEPTION;
9537 }
9538 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d", ssl, len);
9539 int result = SSL_write(ssl, buf, len);
9540 appData->clearCallbackState();
9541 // callbacks can happen if server requests renegotiation
9542 if (env->ExceptionCheck()) {
9543 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
9544 return THROWN_EXCEPTION;
9545 }
9546 sslError->reset(ssl, result);
9547
9548 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError->get());
9549 if (conscrypt::trace::kWithJniTraceData) {
9550 for (size_t i = 0; result > 0 && i < static_cast<size_t>(result);
9551 i += conscrypt::trace::kWithJniTraceDataChunkSize) {
9552 size_t n = result - i;
9553 if (n > conscrypt::trace::kWithJniTraceDataChunkSize) {
9554 n = conscrypt::trace::kWithJniTraceDataChunkSize;
9555 }
9556 JNI_TRACE("ssl=%p sslWrite data: %zu:\n%.*s", ssl, n, (int)n, buf + i);
9557 }
9558 }
9559
9560 // If we have been successful in moving data around, check whether it
9561 // might make sense to wake up other blocked threads, so they can give
9562 // it a try, too.
9563 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved &&
9564 appData->waitingThreads > 0) {
9565 sslNotify(appData);
9566 }
9567
9568 // If we are blocked by the underlying socket, tell the world that
9569 // there will be one more waiting thread now.
9570 if (sslError->get() == SSL_ERROR_WANT_READ || sslError->get() == SSL_ERROR_WANT_WRITE) {
9571 appData->waitingThreads++;
9572 }
9573
9574 appDataLock.unlock();
9575
9576 switch (sslError->get()) {
9577 // Successfully wrote at least one byte.
9578 case SSL_ERROR_NONE: {
9579 buf += result;
9580 len -= result;
9581 break;
9582 }
9583
9584 // Wrote zero bytes. End of stream reached.
9585 case SSL_ERROR_ZERO_RETURN: {
9586 return -1;
9587 }
9588
9589 // Need to wait for availability of underlying layer, then retry.
9590 // The concept of a write timeout doesn't really make sense, and
9591 // it's also not standard Java behavior, so we wait forever here.
9592 case SSL_ERROR_WANT_READ:
9593 case SSL_ERROR_WANT_WRITE: {
9594 int selectResult =
9595 sslSelect(env, sslError->get(), fdObject, appData, write_timeout_millis);
9596 if (selectResult == THROWN_EXCEPTION) {
9597 return THROWN_EXCEPTION;
9598 }
9599 if (selectResult == -1) {
9600 return THROW_SSLEXCEPTION;
9601 }
9602 if (selectResult == 0) {
9603 return THROW_SOCKETTIMEOUTEXCEPTION;
9604 }
9605
9606 break;
9607 }
9608
9609 // A problem occurred during a system call, but this is not
9610 // necessarily an error.
9611 case SSL_ERROR_SYSCALL: {
9612 // Connection closed without proper shutdown. Tell caller we
9613 // have reached end-of-stream.
9614 if (result == 0) {
9615 return -1;
9616 }
9617
9618 // System call has been interrupted. Simply retry.
9619 if (errno == EINTR) {
9620 break;
9621 }
9622
9623 // Note that for all other system call errors we fall through
9624 // to the default case, which results in an Exception.
9625 FALLTHROUGH_INTENDED;
9626 }
9627
9628 // Everything else is basically an error.
9629 default: { return THROW_SSLEXCEPTION; }
9630 }
9631 }
9632 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9633
9634 return count;
9635 }
9636
9637 /**
9638 * OpenSSL write function (2): write into buffer at offset n chunks.
9639 */
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)9640 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address,
9641 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9642 jobject shc, jbyteArray b, jint offset, jint len,
9643 jint write_timeout_millis) {
9644 CHECK_ERROR_QUEUE_ON_RETURN;
9645 SSL* ssl = to_SSL(env, ssl_address, true);
9646 JNI_TRACE(
9647 "ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d "
9648 "write_timeout_millis=%d",
9649 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9650 if (ssl == nullptr) {
9651 return;
9652 }
9653 if (fdObject == nullptr) {
9654 conscrypt::jniutil::throwNullPointerException(env, "fd == null");
9655 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9656 return;
9657 }
9658 if (shc == nullptr) {
9659 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9660 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9661 return;
9662 }
9663 if (b == nullptr) {
9664 conscrypt::jniutil::throwNullPointerException(env, "b == null");
9665 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => b == null", ssl);
9666 return;
9667 }
9668
9669 size_t array_size = static_cast<size_t>(env->GetArrayLength(b));
9670 if (ARRAY_CHUNK_INVALID(array_size, offset, len)) {
9671 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException", "b");
9672 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => ArrayIndexOutOfBoundsException", ssl);
9673 return;
9674 }
9675
9676 SslError sslError;
9677 int ret;
9678 if (conscrypt::jniutil::isGetByteArrayElementsLikelyToReturnACopy(array_size)) {
9679 if (len <= 1024) {
9680 jbyte buf[1024];
9681 env->GetByteArrayRegion(b, offset, len, buf);
9682 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(&buf[0]), len,
9683 &sslError, write_timeout_millis);
9684 } else {
9685 // TODO(flooey): Similar safety concerns and questions here as in SSL_read.
9686 jint remaining = len;
9687 jint buf_size = (remaining >= 65536) ? 65536 : remaining;
9688 std::unique_ptr<jbyte[]> buf(new jbyte[static_cast<unsigned int>(buf_size)]);
9689 if (buf.get() == nullptr) {
9690 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate chunk buffer");
9691 return;
9692 }
9693 while (remaining > 0) {
9694 jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
9695 env->GetByteArrayRegion(b, offset, chunk_size, buf.get());
9696 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(buf.get()),
9697 chunk_size, &sslError, write_timeout_millis);
9698 if (ret == THROW_SSLEXCEPTION || ret == THROW_SOCKETTIMEOUTEXCEPTION ||
9699 ret == THROWN_EXCEPTION) {
9700 // Encountered an error. Terminate early and handle below.
9701 break;
9702 }
9703 offset += ret;
9704 remaining -= ret;
9705 }
9706 }
9707 } else {
9708 ScopedByteArrayRO bytes(env, b);
9709 if (bytes.get() == nullptr) {
9710 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9711 return;
9712 }
9713 ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9714 len, &sslError, write_timeout_millis);
9715 }
9716
9717 switch (ret) {
9718 case THROW_SSLEXCEPTION:
9719 // See sslWrite() regarding improper failure to handle normal cases.
9720 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9721 "Write error");
9722 break;
9723 case THROW_SOCKETTIMEOUTEXCEPTION:
9724 conscrypt::jniutil::throwSocketTimeoutException(env, "Write timed out");
9725 break;
9726 case THROWN_EXCEPTION:
9727 // SocketException thrown by NetFd.isClosed
9728 break;
9729 default:
9730 break;
9731 }
9732 }
9733
9734 /**
9735 * Interrupt any pending I/O before closing the socket.
9736 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9737 static void NativeCrypto_SSL_interrupt(JNIEnv* env, jclass, jlong ssl_address,
9738 CONSCRYPT_UNUSED jobject ssl_holder) {
9739 CHECK_ERROR_QUEUE_ON_RETURN;
9740 SSL* ssl = to_SSL(env, ssl_address, false);
9741 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9742 if (ssl == nullptr) {
9743 return;
9744 }
9745
9746 /*
9747 * Mark the connection as quasi-dead, then send something to the emergency
9748 * file descriptor, so any blocking select() calls are woken up.
9749 */
9750 AppData* appData = toAppData(ssl);
9751 if (appData != nullptr) {
9752 appData->aliveAndKicking = false;
9753
9754 // At most two threads can be waiting.
9755 sslNotify(appData);
9756 sslNotify(appData);
9757 }
9758 }
9759
9760 /**
9761 * OpenSSL close SSL socket function.
9762 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject fdObject,jobject shc)9763 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9764 CONSCRYPT_UNUSED jobject ssl_holder, jobject fdObject,
9765 jobject shc) {
9766 CHECK_ERROR_QUEUE_ON_RETURN;
9767 SSL* ssl = to_SSL(env, ssl_address, false);
9768 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9769 if (ssl == nullptr) {
9770 return;
9771 }
9772 if (fdObject == nullptr) {
9773 return;
9774 }
9775 if (shc == nullptr) {
9776 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
9777 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9778 return;
9779 }
9780
9781 AppData* appData = toAppData(ssl);
9782 if (appData != nullptr) {
9783 if (!appData->setCallbackState(env, shc, fdObject)) {
9784 // SocketException thrown by NetFd.isClosed
9785 ERR_clear_error();
9786 return;
9787 }
9788
9789 /*
9790 * Try to make socket blocking again. OpenSSL literature recommends this.
9791 */
9792 int fd = SSL_get_fd(ssl);
9793 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9794 #ifndef _WIN32
9795 if (fd != -1) {
9796 conscrypt::netutil::setBlocking(fd, true);
9797 }
9798 #endif
9799
9800 int ret = SSL_shutdown(ssl);
9801 appData->clearCallbackState();
9802 // callbacks can happen if server requests renegotiation
9803 if (env->ExceptionCheck()) {
9804 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9805 return;
9806 }
9807 switch (ret) {
9808 case 0:
9809 /*
9810 * Shutdown was not successful (yet), but there also
9811 * is no error. Since we can't know whether the remote
9812 * server is actually still there, and we don't want to
9813 * get stuck forever in a second SSL_shutdown() call, we
9814 * simply return. This is not security a problem as long
9815 * as we close the underlying socket, which we actually
9816 * do, because that's where we are just coming from.
9817 */
9818 break;
9819 case 1:
9820 /*
9821 * Shutdown was successful. We can safely return. Hooray!
9822 */
9823 break;
9824 default:
9825 /*
9826 * Everything else is a real error condition. We should
9827 * let the Java layer know about this by throwing an
9828 * exception.
9829 */
9830 int sslError = SSL_get_error(ssl, ret);
9831 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
9832 "SSL shutdown failed");
9833 break;
9834 }
9835 }
9836
9837 ERR_clear_error();
9838 }
9839
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9840 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9841 CONSCRYPT_UNUSED jobject ssl_holder) {
9842 CHECK_ERROR_QUEUE_ON_RETURN;
9843 const SSL* ssl = to_SSL(env, ssl_address, true);
9844 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9845 if (ssl == nullptr) {
9846 return 0;
9847 }
9848
9849 int status = SSL_get_shutdown(ssl);
9850 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9851 return static_cast<jint>(status);
9852 }
9853
9854 /**
9855 * public static native void SSL_free(long ssl);
9856 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9857 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address,
9858 CONSCRYPT_UNUSED jobject ssl_holder) {
9859 CHECK_ERROR_QUEUE_ON_RETURN;
9860 SSL* ssl = to_SSL(env, ssl_address, true);
9861 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9862 if (ssl == nullptr) {
9863 return;
9864 }
9865
9866 AppData* appData = toAppData(ssl);
9867 SSL_set_app_data(ssl, nullptr);
9868 delete appData;
9869 SSL_free(ssl);
9870 }
9871
get_session_id(JNIEnv * env,SSL_SESSION * ssl_session)9872 static jbyteArray get_session_id(JNIEnv* env, SSL_SESSION* ssl_session) {
9873 unsigned int length;
9874 const uint8_t* id = SSL_SESSION_get_id(ssl_session, &length);
9875 JNI_TRACE("ssl_session=%p get_session_id id=%p length=%u", ssl_session, id, length);
9876 if (id && length > 0) {
9877 jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
9878 if (result != nullptr) {
9879 const jbyte* src = reinterpret_cast<const jbyte*>(id);
9880 env->SetByteArrayRegion(result, 0, static_cast<jsize>(length), src);
9881 }
9882 return result;
9883 }
9884 return nullptr;
9885 }
9886
9887 /**
9888 * Gets and returns in a byte array the ID of the actual SSL session.
9889 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9890 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9891 jlong ssl_session_address) {
9892 CHECK_ERROR_QUEUE_ON_RETURN;
9893 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9894 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9895 if (ssl_session == nullptr) {
9896 return nullptr;
9897 }
9898 jbyteArray result = get_session_id(env, ssl_session);
9899 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p", ssl_session, result);
9900 return result;
9901 }
9902
9903 /**
9904 * Gets and returns in a long integer the creation's time of the
9905 * actual SSL session.
9906 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9907 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9908 CHECK_ERROR_QUEUE_ON_RETURN;
9909 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9910 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9911 if (ssl_session == nullptr) {
9912 return 0;
9913 }
9914 // result must be jlong, not long or *1000 will overflow
9915 jlong result = SSL_SESSION_get_time(ssl_session);
9916 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9917 // NOLINTNEXTLINE(runtime/int)
9918 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session,
9919 (long long)result); // NOLINT(runtime/int)
9920 return result;
9921 }
9922
9923 /**
9924 * Gets and returns in a long integer the creation's time of the
9925 * actual SSL session.
9926 */
NativeCrypto_SSL_get_time(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9927 static jlong NativeCrypto_SSL_get_time(JNIEnv* env, jclass, jlong ssl_address,
9928 CONSCRYPT_UNUSED jobject ssl_holder) {
9929 CHECK_ERROR_QUEUE_ON_RETURN;
9930 SSL* ssl = to_SSL(env, ssl_address, true);
9931 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_time", ssl);
9932 if (ssl == nullptr) {
9933 return 0;
9934 }
9935
9936 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9937 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time", ssl_session);
9938 if (ssl_session == nullptr) {
9939 // BoringSSL does not protect against a NULL session.
9940 return 0;
9941 }
9942 // result must be jlong, not long or *1000 will overflow
9943 jlong result = SSL_SESSION_get_time(ssl_session);
9944 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9945 // NOLINTNEXTLINE(runtime/int)
9946 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_time => %lld", ssl_session, (long long)result);
9947 return result;
9948 }
9949
9950 /**
9951 * Sets the timeout on the SSL session.
9952 */
NativeCrypto_SSL_set_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong millis)9953 static jlong NativeCrypto_SSL_set_timeout(JNIEnv* env, jclass, jlong ssl_address,
9954 CONSCRYPT_UNUSED jobject ssl_holder, jlong millis) {
9955 CHECK_ERROR_QUEUE_ON_RETURN;
9956 SSL* ssl = to_SSL(env, ssl_address, true);
9957 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_timeout", ssl);
9958 if (ssl == nullptr) {
9959 return 0;
9960 }
9961
9962 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9963 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_set_timeout", ssl_session);
9964 if (ssl_session == nullptr) {
9965 // BoringSSL does not protect against a NULL session.
9966 return 0;
9967 }
9968
9969 // Convert to seconds
9970 static const jlong INT_MAX_AS_JLONG = static_cast<jlong>(INT_MAX);
9971 uint32_t timeout = static_cast<uint32_t>(
9972 std::max(0, static_cast<int>(std::min(INT_MAX_AS_JLONG, millis / 1000))));
9973 return SSL_set_timeout(ssl_session, timeout);
9974 }
9975
9976 /**
9977 * Gets the timeout for the SSL session.
9978 */
NativeCrypto_SSL_get_timeout(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)9979 static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address,
9980 CONSCRYPT_UNUSED jobject ssl_holder) {
9981 CHECK_ERROR_QUEUE_ON_RETURN;
9982 SSL* ssl = to_SSL(env, ssl_address, true);
9983 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_timeout", ssl);
9984 if (ssl == nullptr) {
9985 return 0;
9986 }
9987
9988 SSL_SESSION* ssl_session = SSL_get_session(ssl);
9989 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout", ssl_session);
9990 if (ssl_session == nullptr) {
9991 // BoringSSL does not protect against a NULL session.
9992 return 0;
9993 }
9994
9995 jlong result = SSL_get_timeout(ssl_session);
9996 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9997 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_get_timeout => %lld", ssl_session,
9998 (long long)result) // NOLINT(runtime/int);
9999 return result;
10000 }
10001
NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv * env,jclass,jint signatureAlg)10002 static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass,
10003 jint signatureAlg) {
10004 CHECK_ERROR_QUEUE_ON_RETURN;
10005 return SSL_get_signature_algorithm_key_type(signatureAlg);
10006 }
10007
10008 /**
10009 * Gets the timeout for the SSL session.
10010 */
NativeCrypto_SSL_SESSION_get_timeout(JNIEnv * env,jclass,jlong ssl_session_address)10011 static jlong NativeCrypto_SSL_SESSION_get_timeout(JNIEnv* env, jclass, jlong ssl_session_address) {
10012 CHECK_ERROR_QUEUE_ON_RETURN;
10013 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10014 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_timeout", ssl_session);
10015 if (ssl_session == nullptr) {
10016 return 0;
10017 }
10018
10019 return SSL_get_timeout(ssl_session);
10020 }
10021
10022 /**
10023 * Gets the ID for the SSL session, or null if no session is currently available.
10024 */
NativeCrypto_SSL_session_id(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10025 static jbyteArray NativeCrypto_SSL_session_id(JNIEnv* env, jclass, jlong ssl_address,
10026 CONSCRYPT_UNUSED jobject ssl_holder) {
10027 CHECK_ERROR_QUEUE_ON_RETURN;
10028 SSL* ssl = to_SSL(env, ssl_address, true);
10029 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_id", ssl);
10030 if (ssl == nullptr) {
10031 return nullptr;
10032 }
10033
10034 SSL_SESSION* ssl_session = SSL_get_session(ssl);
10035 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id", ssl_session);
10036 if (ssl_session == nullptr) {
10037 return nullptr;
10038 }
10039 jbyteArray result = get_session_id(env, ssl_session);
10040 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_session_id => %p", ssl_session, result);
10041 return result;
10042 }
10043
10044 /**
10045 * Gets and returns in a string the version of the SSL protocol. If it
10046 * returns the string "unknown" it means that no connection is established.
10047 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)10048 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass,
10049 jlong ssl_session_address) {
10050 CHECK_ERROR_QUEUE_ON_RETURN;
10051 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10052 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
10053 if (ssl_session == nullptr) {
10054 return nullptr;
10055 }
10056 const char* protocol = SSL_SESSION_get_version(ssl_session);
10057 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
10058 return env->NewStringUTF(protocol);
10059 }
10060
10061 /**
10062 * Gets and returns in a string the cipher negotiated for the SSL session.
10063 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)10064 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
10065 CHECK_ERROR_QUEUE_ON_RETURN;
10066 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10067 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
10068 if (ssl_session == nullptr) {
10069 return nullptr;
10070 }
10071 const SSL_CIPHER* cipher = SSL_SESSION_get0_cipher(ssl_session);
10072 const char* name = SSL_CIPHER_standard_name(cipher);
10073 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
10074 return env->NewStringUTF(name);
10075 }
10076
NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv * env,jclass,jlong ssl_session_address)10077 static jboolean NativeCrypto_SSL_SESSION_should_be_single_use(JNIEnv* env, jclass,
10078 jlong ssl_session_address) {
10079 CHECK_ERROR_QUEUE_ON_RETURN;
10080 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10081 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use", ssl_session);
10082 if (ssl_session == nullptr) {
10083 return JNI_FALSE;
10084 }
10085 int single_use = SSL_SESSION_should_be_single_use(ssl_session);
10086 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_should_be_single_use => %d", ssl_session,
10087 single_use);
10088 return single_use ? JNI_TRUE : JNI_FALSE;
10089 }
10090
10091 /**
10092 * Increments the reference count of the session.
10093 */
NativeCrypto_SSL_SESSION_up_ref(JNIEnv * env,jclass,jlong ssl_session_address)10094 static void NativeCrypto_SSL_SESSION_up_ref(JNIEnv* env, jclass, jlong ssl_session_address) {
10095 CHECK_ERROR_QUEUE_ON_RETURN;
10096 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10097 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_up_ref", ssl_session);
10098 if (ssl_session == nullptr) {
10099 return;
10100 }
10101 SSL_SESSION_up_ref(ssl_session);
10102 }
10103
10104 /**
10105 * Frees the SSL session.
10106 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)10107 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
10108 CHECK_ERROR_QUEUE_ON_RETURN;
10109 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10110 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
10111 if (ssl_session == nullptr) {
10112 return;
10113 }
10114 SSL_SESSION_free(ssl_session);
10115 }
10116
10117 /**
10118 * Serializes the native state of the session (ID, cipher, and keys but
10119 * not certificates). Returns a byte[] containing the DER-encoded state.
10120 * See apache mod_ssl.
10121 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)10122 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
10123 CHECK_ERROR_QUEUE_ON_RETURN;
10124 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10125 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
10126 if (ssl_session == nullptr) {
10127 return nullptr;
10128 }
10129 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
10130 }
10131
10132 /**
10133 * Deserialize the session.
10134 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)10135 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
10136 CHECK_ERROR_QUEUE_ON_RETURN;
10137 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
10138
10139 ScopedByteArrayRO bytes(env, javaBytes);
10140 if (bytes.get() == nullptr) {
10141 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
10142 return 0;
10143 }
10144 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
10145 // NOLINTNEXTLINE(runtime/int)
10146 SSL_SESSION* ssl_session = d2i_SSL_SESSION(nullptr, &ucp, static_cast<long>(bytes.size()));
10147
10148 if (ssl_session == nullptr ||
10149 ucp != (reinterpret_cast<const unsigned char*>(bytes.get()) + bytes.size())) {
10150 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "d2i_SSL_SESSION",
10151 conscrypt::jniutil::throwIOException);
10152 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => failure to convert");
10153 return 0L;
10154 }
10155
10156 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
10157 return reinterpret_cast<uintptr_t>(ssl_session);
10158 }
10159
NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv * env,jclass,jlong cipher_address)10160 static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
10161 CHECK_ERROR_QUEUE_ON_RETURN;
10162 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, /*throwIfNull=*/true);
10163 if (cipher == nullptr) {
10164 return nullptr;
10165 }
10166
10167 const char* kx_name = SSL_CIPHER_get_kx_name(cipher);
10168 return env->NewStringUTF(kx_name);
10169 }
10170
NativeCrypto_get_cipher_names(JNIEnv * env,jclass,jstring selectorJava)10171 static jobjectArray NativeCrypto_get_cipher_names(JNIEnv* env, jclass, jstring selectorJava) {
10172 CHECK_ERROR_QUEUE_ON_RETURN;
10173 ScopedUtfChars selector(env, selectorJava);
10174 if (selector.c_str() == nullptr) {
10175 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10176 "selector == null");
10177 return nullptr;
10178 }
10179
10180 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
10181
10182 bssl::UniquePtr<SSL_CTX> sslCtx(SSL_CTX_new(TLS_with_buffers_method()));
10183 bssl::UniquePtr<SSL> ssl(SSL_new(sslCtx.get()));
10184
10185 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
10186 conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
10187 "Unable to set SSL cipher list");
10188 return nullptr;
10189 }
10190 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl.get());
10191
10192 size_t size = sk_SSL_CIPHER_num(ciphers);
10193 ScopedLocalRef<jobjectArray> cipherNamesArray(
10194 env, env->NewObjectArray(static_cast<jsize>(2 * size), conscrypt::jniutil::stringClass,
10195 nullptr));
10196 if (cipherNamesArray.get() == nullptr) {
10197 return nullptr;
10198 }
10199
10200 // Return an array of standard and OpenSSL name pairs.
10201 for (size_t i = 0; i < size; i++) {
10202 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
10203 ScopedLocalRef<jstring> cipherName(env,
10204 env->NewStringUTF(SSL_CIPHER_standard_name(cipher)));
10205 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i),
10206 cipherName.get());
10207
10208 ScopedLocalRef<jstring> opensslName(env, env->NewStringUTF(SSL_CIPHER_get_name(cipher)));
10209 env->SetObjectArrayElement(cipherNamesArray.get(), static_cast<jsize>(2 * i + 1),
10210 opensslName.get());
10211 }
10212
10213 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(),
10214 2 * size);
10215 return cipherNamesArray.release();
10216 }
10217
10218 /**
10219 * Compare the given CertID with a certificate and it's issuer.
10220 * True is returned if the CertID matches.
10221 */
ocsp_cert_id_matches_certificate(CBS * cert_id,X509 * x509,X509 * issuerX509)10222 static bool ocsp_cert_id_matches_certificate(CBS* cert_id, X509* x509, X509* issuerX509) {
10223 // Get the hash algorithm used by this CertID
10224 CBS hash_algorithm, hash;
10225 if (!CBS_get_asn1(cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) ||
10226 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT)) {
10227 return false;
10228 }
10229
10230 // Get the issuer's name hash from the CertID
10231 CBS issuer_name_hash;
10232 if (!CBS_get_asn1(cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING)) {
10233 return false;
10234 }
10235
10236 // Get the issuer's key hash from the CertID
10237 CBS issuer_key_hash;
10238 if (!CBS_get_asn1(cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING)) {
10239 return false;
10240 }
10241
10242 // Get the serial number from the CertID
10243 CBS serial;
10244 if (!CBS_get_asn1(cert_id, &serial, CBS_ASN1_INTEGER)) {
10245 return false;
10246 }
10247
10248 // Compare the certificate's serial number with the one from the Cert ID
10249 const uint8_t* p = CBS_data(&serial);
10250 bssl::UniquePtr<ASN1_INTEGER> serial_number(
10251 c2i_ASN1_INTEGER(nullptr, &p,
10252 static_cast<long>(CBS_len(&serial)))); // NOLINT(runtime/int)
10253 const ASN1_INTEGER* expected_serial_number = X509_get_serialNumber(x509);
10254 if (serial_number.get() == nullptr ||
10255 ASN1_INTEGER_cmp(expected_serial_number, serial_number.get()) != 0) {
10256 return false;
10257 }
10258
10259 // Find the hash algorithm to be used
10260 const EVP_MD* digest = EVP_get_digestbynid(OBJ_cbs2nid(&hash));
10261 if (digest == nullptr) {
10262 return false;
10263 }
10264
10265 // Hash the issuer's name and compare the hash with the one from the Cert ID
10266 uint8_t md[EVP_MAX_MD_SIZE];
10267 const X509_NAME* issuer_name = X509_get_subject_name(issuerX509);
10268 if (!X509_NAME_digest(issuer_name, digest, md, nullptr) ||
10269 !CBS_mem_equal(&issuer_name_hash, md, EVP_MD_size(digest))) {
10270 return false;
10271 }
10272
10273 // Same thing with the issuer's key
10274 const ASN1_BIT_STRING* issuer_key = X509_get0_pubkey_bitstr(issuerX509);
10275 if (!EVP_Digest(ASN1_STRING_get0_data(issuer_key),
10276 static_cast<size_t>(ASN1_STRING_length(issuer_key)), md, nullptr, digest,
10277 nullptr) ||
10278 !CBS_mem_equal(&issuer_key_hash, md, EVP_MD_size(digest))) {
10279 return false;
10280 }
10281
10282 return true;
10283 }
10284
10285 /**
10286 * Get a SingleResponse whose CertID matches the given certificate and issuer from a
10287 * SEQUENCE OF SingleResponse.
10288 *
10289 * If found, |out_single_response| is set to the response, and true is returned. Otherwise if an
10290 * error occured or no response matches the certificate, false is returned and |out_single_response|
10291 * is unchanged.
10292 */
find_ocsp_single_response(CBS * responses,X509 * x509,X509 * issuerX509,CBS * out_single_response)10293 static bool find_ocsp_single_response(CBS* responses, X509* x509, X509* issuerX509,
10294 CBS* out_single_response) {
10295 // Iterate over all the SingleResponses, until one matches the certificate
10296 while (CBS_len(responses) > 0) {
10297 // Get the next available SingleResponse from the sequence
10298 CBS single_response;
10299 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE)) {
10300 return false;
10301 }
10302
10303 // Make a copy of the stream so we pass it back to the caller
10304 CBS single_response_original = single_response;
10305
10306 // Get the SingleResponse's CertID
10307 // If this fails ignore the current response and move to the next one
10308 CBS cert_id;
10309 if (!CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) {
10310 continue;
10311 }
10312
10313 // Compare the CertID with the given certificate and issuer
10314 if (ocsp_cert_id_matches_certificate(&cert_id, x509, issuerX509)) {
10315 *out_single_response = single_response_original;
10316 return true;
10317 }
10318 }
10319
10320 return false;
10321 }
10322
10323 /**
10324 * Get the BasicOCSPResponse from an OCSPResponse.
10325 * If parsing succeeds and the response is of type basic, |basic_response| is set to it, and true is
10326 * returned.
10327 */
get_ocsp_basic_response(CBS * ocsp_response,CBS * basic_response)10328 static bool get_ocsp_basic_response(CBS* ocsp_response, CBS* basic_response) {
10329 CBS tagged_response_bytes, response_bytes, response_type, response;
10330
10331 // Get the ResponseBytes out of the OCSPResponse
10332 if (!CBS_get_asn1(ocsp_response, nullptr /* responseStatus */, CBS_ASN1_ENUMERATED) ||
10333 !CBS_get_asn1(ocsp_response, &tagged_response_bytes,
10334 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10335 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, CBS_ASN1_SEQUENCE)) {
10336 return false;
10337 }
10338
10339 // Parse the response type and data out of the ResponseBytes
10340 if (!CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) ||
10341 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING)) {
10342 return false;
10343 }
10344
10345 // Only basic OCSP responses are supported
10346 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) {
10347 return false;
10348 }
10349
10350 // Parse the octet string as a BasicOCSPResponse
10351 return CBS_get_asn1(&response, basic_response, CBS_ASN1_SEQUENCE) == 1;
10352 }
10353
10354 /**
10355 * Get the SEQUENCE OF SingleResponse from a BasicOCSPResponse.
10356 * If parsing succeeds, |single_responses| is set to point to the sequence of SingleResponse, and
10357 * true is returned.
10358 */
get_ocsp_single_responses(CBS * basic_response,CBS * single_responses)10359 static bool get_ocsp_single_responses(CBS* basic_response, CBS* single_responses) {
10360 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest.
10361 CBS response_data;
10362 if (!CBS_get_asn1(basic_response, &response_data, CBS_ASN1_SEQUENCE)) {
10363 return false;
10364 }
10365
10366 // Skip the version, responderID and producedAt fields
10367 if (!CBS_get_optional_asn1(&response_data, nullptr /* version */, nullptr,
10368 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
10369 !CBS_get_any_asn1_element(&response_data, nullptr /* responderID */, nullptr, nullptr) ||
10370 !CBS_get_any_asn1_element(&response_data, nullptr /* producedAt */, nullptr, nullptr)) {
10371 return false;
10372 }
10373
10374 // Extract the list of SingleResponse.
10375 return CBS_get_asn1(&response_data, single_responses, CBS_ASN1_SEQUENCE) == 1;
10376 }
10377
10378 /**
10379 * Get the SEQUENCE OF Extension from a SingleResponse.
10380 * If parsing succeeds, |extensions| is set to point the the extension sequence and true is
10381 * returned.
10382 */
get_ocsp_single_response_extensions(CBS * single_response,CBS * extensions)10383 static bool get_ocsp_single_response_extensions(CBS* single_response, CBS* extensions) {
10384 // Skip the certID, certStatus, thisUpdate and optional nextUpdate fields.
10385 if (!CBS_get_any_asn1_element(single_response, nullptr /* certID */, nullptr, nullptr) ||
10386 !CBS_get_any_asn1_element(single_response, nullptr /* certStatus */, nullptr, nullptr) ||
10387 !CBS_get_any_asn1_element(single_response, nullptr /* thisUpdate */, nullptr, nullptr) ||
10388 !CBS_get_optional_asn1(single_response, nullptr /* nextUpdate */, nullptr,
10389 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
10390 return false;
10391 }
10392
10393 // Get the list of Extension
10394 return CBS_get_asn1(single_response, extensions,
10395 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) == 1;
10396 }
10397
10398 /*
10399 public static native byte[] get_ocsp_single_extension(byte[] ocspData, String oid,
10400 long x509Ref, long issuerX509Ref);
10401 */
NativeCrypto_get_ocsp_single_extension(JNIEnv * env,jclass,jbyteArray ocspDataBytes,jstring oid,jlong x509Ref,CONSCRYPT_UNUSED jobject holder,jlong issuerX509Ref,CONSCRYPT_UNUSED jobject holder2)10402 static jbyteArray NativeCrypto_get_ocsp_single_extension(
10403 JNIEnv* env, jclass, jbyteArray ocspDataBytes, jstring oid, jlong x509Ref,
10404 CONSCRYPT_UNUSED jobject holder, jlong issuerX509Ref, CONSCRYPT_UNUSED jobject holder2) {
10405 CHECK_ERROR_QUEUE_ON_RETURN;
10406 ScopedByteArrayRO ocspData(env, ocspDataBytes);
10407 if (ocspData.get() == nullptr) {
10408 return nullptr;
10409 }
10410
10411 CBS cbs;
10412 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocspData.get()), ocspData.size());
10413
10414 // Start parsing the OCSPResponse
10415 CBS ocsp_response;
10416 if (!CBS_get_asn1(&cbs, &ocsp_response, CBS_ASN1_SEQUENCE)) {
10417 return nullptr;
10418 }
10419
10420 // Get the BasicOCSPResponse from the OCSP Response
10421 CBS basic_response;
10422 if (!get_ocsp_basic_response(&ocsp_response, &basic_response)) {
10423 return nullptr;
10424 }
10425
10426 // Get the list of SingleResponses from the BasicOCSPResponse
10427 CBS responses;
10428 if (!get_ocsp_single_responses(&basic_response, &responses)) {
10429 return nullptr;
10430 }
10431
10432 // Find the response matching the certificate
10433 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
10434 X509* issuerX509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(issuerX509Ref));
10435 CBS single_response;
10436 if (!find_ocsp_single_response(&responses, x509, issuerX509, &single_response)) {
10437 return nullptr;
10438 }
10439
10440 // Get the extensions from the SingleResponse
10441 CBS extensions;
10442 if (!get_ocsp_single_response_extensions(&single_response, &extensions)) {
10443 return nullptr;
10444 }
10445
10446 const uint8_t* ptr = CBS_data(&extensions);
10447 bssl::UniquePtr<X509_EXTENSIONS> x509_exts(
10448 d2i_X509_EXTENSIONS(nullptr, &ptr,
10449 static_cast<long>(CBS_len(&extensions)))); // NOLINT(runtime/int)
10450 if (x509_exts.get() == nullptr) {
10451 return nullptr;
10452 }
10453
10454 return X509Type_get_ext_oid<X509_EXTENSIONS, X509v3_get_ext_by_OBJ, X509v3_get_ext>(
10455 env, x509_exts.get(), oid);
10456 }
10457
NativeCrypto_getDirectBufferAddress(JNIEnv * env,jclass,jobject buffer)10458 static jlong NativeCrypto_getDirectBufferAddress(JNIEnv* env, jclass, jobject buffer) {
10459 // The javadoc for NativeCrypto.getDirectBufferAddress(Buffer buf) defines the behaviour here,
10460 // no throwing if the buffer is null or not a direct ByteBuffer.
10461 if (!conscrypt::jniutil::isDirectByteBufferInstance(env, buffer)) {
10462 return 0;
10463 }
10464 return reinterpret_cast<jlong>(env->GetDirectBufferAddress(buffer));
10465 }
10466
NativeCrypto_SSL_get_error(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jint ret)10467 static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address,
10468 CONSCRYPT_UNUSED jobject ssl_holder, jint ret) {
10469 CHECK_ERROR_QUEUE_ON_RETURN;
10470 SSL* ssl = to_SSL(env, ssl_address, true);
10471 if (ssl == nullptr) {
10472 return 0;
10473 }
10474 return SSL_get_error(ssl, ret);
10475 }
10476
NativeCrypto_SSL_clear_error(JNIEnv *,jclass)10477 static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) {
10478 ERR_clear_error();
10479 }
10480
NativeCrypto_SSL_pending_readable_bytes(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10481 static jint NativeCrypto_SSL_pending_readable_bytes(JNIEnv* env, jclass, jlong ssl_address,
10482 CONSCRYPT_UNUSED jobject ssl_holder) {
10483 CHECK_ERROR_QUEUE_ON_RETURN;
10484 SSL* ssl = to_SSL(env, ssl_address, true);
10485 if (ssl == nullptr) {
10486 return 0;
10487 }
10488 return SSL_pending(ssl);
10489 }
10490
NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv * env,jclass,jlong bio_address)10491 static jint NativeCrypto_SSL_pending_written_bytes_in_BIO(JNIEnv* env, jclass, jlong bio_address) {
10492 CHECK_ERROR_QUEUE_ON_RETURN;
10493 BIO* bio = to_BIO(env, bio_address);
10494 if (bio == nullptr) {
10495 return 0;
10496 }
10497 return static_cast<jint>(BIO_ctrl_pending(bio));
10498 }
10499
NativeCrypto_SSL_max_seal_overhead(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10500 static jint NativeCrypto_SSL_max_seal_overhead(JNIEnv* env, jclass, jlong ssl_address,
10501 CONSCRYPT_UNUSED jobject ssl_holder) {
10502 CHECK_ERROR_QUEUE_ON_RETURN;
10503 SSL* ssl = to_SSL(env, ssl_address, true);
10504 if (ssl == nullptr) {
10505 return 0;
10506 }
10507 return (jint)SSL_max_seal_overhead(ssl);
10508 }
10509
10510 /**
10511 * public static native int SSL_new_BIO(long ssl) throws SSLException;
10512 */
NativeCrypto_SSL_BIO_new(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)10513 static jlong NativeCrypto_SSL_BIO_new(JNIEnv* env, jclass, jlong ssl_address,
10514 CONSCRYPT_UNUSED jobject ssl_holder) {
10515 CHECK_ERROR_QUEUE_ON_RETURN;
10516 SSL* ssl = to_SSL(env, ssl_address, true);
10517 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new", ssl);
10518 if (ssl == nullptr) {
10519 return 0;
10520 }
10521
10522 BIO* internal_bio;
10523 BIO* network_bio;
10524 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
10525 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
10526 "BIO_new_bio_pair failed");
10527 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => BIO_new_bio_pair exception", ssl);
10528 return 0;
10529 }
10530
10531 SSL_set_bio(ssl, internal_bio, internal_bio);
10532
10533 JNI_TRACE("ssl=%p NativeCrypto_SSL_BIO_new => network_bio=%p", ssl, network_bio);
10534 return reinterpret_cast<uintptr_t>(network_bio);
10535 }
10536
NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10537 static jint NativeCrypto_ENGINE_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
10538 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10539 CHECK_ERROR_QUEUE_ON_RETURN;
10540 SSL* ssl = to_SSL(env, ssl_address, true);
10541 if (ssl == nullptr) {
10542 return 0;
10543 }
10544 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p", ssl, shc);
10545
10546 if (shc == nullptr) {
10547 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10548 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => sslHandshakeCallbacks == null",
10549 ssl);
10550 return 0;
10551 }
10552
10553 AppData* appData = toAppData(ssl);
10554 if (appData == nullptr) {
10555 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10556 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake appData => 0", ssl);
10557 return 0;
10558 }
10559
10560 errno = 0;
10561
10562 if (!appData->setCallbackState(env, shc, nullptr)) {
10563 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10564 ERR_clear_error();
10565 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10566 return 0;
10567 }
10568
10569 int ret = SSL_do_handshake(ssl);
10570 appData->clearCallbackState();
10571 if (env->ExceptionCheck()) {
10572 // cert_verify_callback threw exception
10573 ERR_clear_error();
10574 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake => exception", ssl);
10575 return 0;
10576 }
10577
10578 SslError sslError(ssl, ret);
10579 int code = sslError.get();
10580
10581 if (ret > 0 || code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE) {
10582 // Non-exceptional case.
10583 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_do_handshake shc=%p => ret=%d", ssl, shc, code);
10584 return code;
10585 }
10586
10587 // Exceptional case...
10588 if (ret == 0) {
10589 // TODO(nmittler): Can this happen with memory BIOs?
10590 /*
10591 * Clean error. See SSL_do_handshake(3SSL) man page.
10592 * The other side closed the socket before the handshake could be
10593 * completed, but everything is within the bounds of the TLS protocol.
10594 * We still might want to find out the real reason of the failure.
10595 */
10596 if (code == SSL_ERROR_NONE || (code == SSL_ERROR_SYSCALL && errno == 0) ||
10597 (code == SSL_ERROR_ZERO_RETURN)) {
10598 conscrypt::jniutil::throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
10599 } else {
10600 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10601 env, ssl, sslError.release(), "SSL handshake terminated",
10602 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10603 }
10604 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => exception", ssl);
10605 return code;
10606 }
10607
10608 /*
10609 * Unclean error. See SSL_do_handshake(3SSL) man page.
10610 * Translate the error and throw exception. We are sure it is an error
10611 * at this point.
10612 */
10613 conscrypt::jniutil::throwSSLExceptionWithSslErrors(
10614 env, ssl, sslError.release(), "SSL handshake aborted",
10615 conscrypt::jniutil::throwSSLHandshakeExceptionStr);
10616 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => exception", ssl);
10617 return code;
10618 }
10619
NativeCrypto_ENGINE_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10620 static void NativeCrypto_ENGINE_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
10621 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10622 CHECK_ERROR_QUEUE_ON_RETURN;
10623 SSL* ssl = to_SSL(env, ssl_address, false);
10624 if (ssl == nullptr) {
10625 return;
10626 }
10627 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown", ssl);
10628
10629 if (shc == nullptr) {
10630 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10631 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10632 return;
10633 }
10634
10635 AppData* appData = toAppData(ssl);
10636 if (appData != nullptr) {
10637 if (!appData->setCallbackState(env, shc, nullptr)) {
10638 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10639 ERR_clear_error();
10640 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10641 return;
10642 }
10643 int ret = SSL_shutdown(ssl);
10644 appData->clearCallbackState();
10645 // callbacks can happen if server requests renegotiation
10646 if (env->ExceptionCheck()) {
10647 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => exception", ssl);
10648 return;
10649 }
10650 switch (ret) {
10651 case 0:
10652 /*
10653 * Shutdown was not successful (yet), but there also
10654 * is no error. Since we can't know whether the remote
10655 * server is actually still there, and we don't want to
10656 * get stuck forever in a second SSL_shutdown() call, we
10657 * simply return. This is not security a problem as long
10658 * as we close the underlying socket, which we actually
10659 * do, because that's where we are just coming from.
10660 */
10661 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 0", ssl);
10662 break;
10663 case 1:
10664 /*
10665 * Shutdown was successful. We can safely return. Hooray!
10666 */
10667 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => 1", ssl);
10668 break;
10669 default:
10670 /*
10671 * Everything else is a real error condition. We should
10672 * let the Java layer know about this by throwing an
10673 * exception.
10674 */
10675 int sslError = SSL_get_error(ssl, ret);
10676 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_shutdown => sslError=%d", ssl, sslError);
10677 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError,
10678 "SSL shutdown failed");
10679 break;
10680 }
10681 }
10682
10683 ERR_clear_error();
10684 }
10685
NativeCrypto_ENGINE_SSL_read_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint length,jobject shc)10686 static jint NativeCrypto_ENGINE_SSL_read_direct(JNIEnv* env, jclass, jlong ssl_address,
10687 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10688 jint length, jobject shc) {
10689 CHECK_ERROR_QUEUE_ON_RETURN;
10690 SSL* ssl = to_SSL(env, ssl_address, true);
10691 char* destPtr = reinterpret_cast<char*>(address);
10692 if (ssl == nullptr) {
10693 return -1;
10694 }
10695 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p", ssl,
10696 destPtr, length, shc);
10697
10698 if (shc == nullptr) {
10699 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10700 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => sslHandshakeCallbacks == null",
10701 ssl);
10702 return -1;
10703 }
10704 AppData* appData = toAppData(ssl);
10705 if (appData == nullptr) {
10706 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10707 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => appData == null", ssl);
10708 return -1;
10709 }
10710 if (!appData->setCallbackState(env, shc, nullptr)) {
10711 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10712 ERR_clear_error();
10713 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => exception", ssl);
10714 return -1;
10715 }
10716
10717 errno = 0;
10718
10719 int result = SSL_read(ssl, destPtr, length);
10720 appData->clearCallbackState();
10721 if (env->ExceptionCheck()) {
10722 // An exception was thrown by one of the callbacks. Just propagate that exception.
10723 ERR_clear_error();
10724 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct => THROWN_EXCEPTION", ssl);
10725 return -1;
10726 }
10727
10728 SslError sslError(ssl, result);
10729 switch (sslError.get()) {
10730 case SSL_ERROR_NONE: {
10731 // Successfully read at least one byte. Just return the result.
10732 break;
10733 }
10734 case SSL_ERROR_ZERO_RETURN: {
10735 // A close_notify was received, this stream is finished.
10736 return -SSL_ERROR_ZERO_RETURN;
10737 }
10738 case SSL_ERROR_WANT_READ:
10739 case SSL_ERROR_WANT_WRITE: {
10740 // Return the negative of these values.
10741 result = -sslError.get();
10742 break;
10743 }
10744 case SSL_ERROR_SYSCALL: {
10745 // A problem occurred during a system call, but this is not
10746 // necessarily an error.
10747 if (result == 0) {
10748 // TODO(nmittler): Can this happen with memory BIOs?
10749 // Connection closed without proper shutdown. Tell caller we
10750 // have reached end-of-stream.
10751 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10752 break;
10753 }
10754
10755 if (errno == EINTR) {
10756 // TODO(nmittler): Can this happen with memory BIOs?
10757 // System call has been interrupted. Simply retry.
10758 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10759 "Read error");
10760 break;
10761 }
10762
10763 // Note that for all other system call errors we fall through
10764 // to the default case, which results in an Exception.
10765 FALLTHROUGH_INTENDED;
10766 }
10767 default: {
10768 // Everything else is basically an error.
10769 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10770 "Read error");
10771 break;
10772 }
10773 }
10774
10775 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_direct address=%p length=%d shc=%p result=%d",
10776 ssl, destPtr, length, shc, result);
10777 return result;
10778 }
10779
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)10780 static int NativeCrypto_ENGINE_SSL_write_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10781 CONSCRYPT_UNUSED jobject ssl_holder,
10782 jlong bioRef, jlong address, jint len,
10783 jobject shc) {
10784 CHECK_ERROR_QUEUE_ON_RETURN;
10785 SSL* ssl = to_SSL(env, ssl_address, true);
10786 if (ssl == nullptr) {
10787 return -1;
10788 }
10789 if (shc == nullptr) {
10790 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10791 JNI_TRACE(
10792 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => "
10793 "sslHandshakeCallbacks == null",
10794 ssl);
10795 return -1;
10796 }
10797 BIO* bio = to_BIO(env, bioRef);
10798 if (bio == nullptr) {
10799 return -1;
10800 }
10801 if (len < 0 || BIO_ctrl_get_write_guarantee(bio) < static_cast<size_t>(len)) {
10802 // The network BIO couldn't handle the entire write. Don't write anything, so that we
10803 // only process one packet at a time.
10804 return 0;
10805 }
10806 const char* sourcePtr = reinterpret_cast<const char*>(address);
10807
10808 AppData* appData = toAppData(ssl);
10809 if (appData == nullptr) {
10810 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10811 ERR_clear_error();
10812 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct appData => null", ssl);
10813 return -1;
10814 }
10815 if (!appData->setCallbackState(env, shc, nullptr)) {
10816 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10817 ERR_clear_error();
10818 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct => exception", ssl);
10819 return -1;
10820 }
10821
10822 errno = 0;
10823
10824 int result = BIO_write(bio, reinterpret_cast<const char*>(sourcePtr), len);
10825 appData->clearCallbackState();
10826 JNI_TRACE(
10827 "ssl=%p NativeCrypto_ENGINE_SSL_write_BIO_direct bio=%p sourcePtr=%p len=%d shc=%p => "
10828 "ret=%d",
10829 ssl, bio, sourcePtr, len, shc, result);
10830 JNI_TRACE_PACKET_DATA(ssl, 'O', reinterpret_cast<const char*>(sourcePtr),
10831 static_cast<size_t>(result));
10832 return result;
10833 }
10834
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)10835 static int NativeCrypto_ENGINE_SSL_read_BIO_direct(JNIEnv* env, jclass, jlong ssl_address,
10836 CONSCRYPT_UNUSED jobject ssl_holder,
10837 jlong bioRef, jlong address, jint outputSize,
10838 jobject shc) {
10839 CHECK_ERROR_QUEUE_ON_RETURN;
10840 SSL* ssl = to_SSL(env, ssl_address, true);
10841 if (ssl == nullptr) {
10842 return -1;
10843 }
10844 if (shc == nullptr) {
10845 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10846 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => sslHandshakeCallbacks == null",
10847 ssl);
10848 return -1;
10849 }
10850 BIO* bio = to_BIO(env, bioRef);
10851 if (bio == nullptr) {
10852 return -1;
10853 }
10854 char* destPtr = reinterpret_cast<char*>(address);
10855 if (destPtr == nullptr) {
10856 conscrypt::jniutil::throwNullPointerException(env, "destPtr == null");
10857 return -1;
10858 }
10859
10860 AppData* appData = toAppData(ssl);
10861 if (appData == nullptr) {
10862 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10863 ERR_clear_error();
10864 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct appData => null", ssl);
10865 return -1;
10866 }
10867 if (!appData->setCallbackState(env, shc, nullptr)) {
10868 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10869 ERR_clear_error();
10870 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct => exception", ssl);
10871 return -1;
10872 }
10873
10874 errno = 0;
10875
10876 int result = BIO_read(bio, destPtr, outputSize);
10877 appData->clearCallbackState();
10878 JNI_TRACE(
10879 "ssl=%p NativeCrypto_ENGINE_SSL_read_BIO_direct bio=%p destPtr=%p outputSize=%d shc=%p "
10880 "=> ret=%d",
10881 ssl, bio, destPtr, outputSize, shc, result);
10882 JNI_TRACE_PACKET_DATA(ssl, 'I', destPtr, static_cast<size_t>(result));
10883 return result;
10884 }
10885
NativeCrypto_ENGINE_SSL_force_read(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jobject shc)10886 static void NativeCrypto_ENGINE_SSL_force_read(JNIEnv* env, jclass, jlong ssl_address,
10887 CONSCRYPT_UNUSED jobject ssl_holder, jobject shc) {
10888 CHECK_ERROR_QUEUE_ON_RETURN;
10889 SSL* ssl = to_SSL(env, ssl_address, true);
10890 if (ssl == nullptr) {
10891 return;
10892 }
10893 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10894 if (shc == nullptr) {
10895 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10896 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => sslHandshakeCallbacks == null",
10897 ssl);
10898 return;
10899 }
10900 AppData* appData = toAppData(ssl);
10901 if (appData == nullptr) {
10902 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10903 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => appData == null", ssl);
10904 return;
10905 }
10906 if (!appData->setCallbackState(env, shc, nullptr)) {
10907 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10908 ERR_clear_error();
10909 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => exception", ssl);
10910 return;
10911 }
10912 char c;
10913 int result = SSL_peek(ssl, &c, 1);
10914 appData->clearCallbackState();
10915 if (env->ExceptionCheck()) {
10916 // An exception was thrown by one of the callbacks. Just propagate that exception.
10917 ERR_clear_error();
10918 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read => THROWN_EXCEPTION", ssl);
10919 return;
10920 }
10921
10922 SslError sslError(ssl, result);
10923 switch (sslError.get()) {
10924 case SSL_ERROR_NONE:
10925 case SSL_ERROR_ZERO_RETURN:
10926 case SSL_ERROR_WANT_READ:
10927 case SSL_ERROR_WANT_WRITE: {
10928 // The call succeeded, lacked data, or the SSL is closed. All is well.
10929 break;
10930 }
10931 case SSL_ERROR_SYSCALL: {
10932 // A problem occurred during a system call, but this is not
10933 // necessarily an error.
10934 if (result == 0) {
10935 // TODO(nmittler): Can this happen with memory BIOs?
10936 // Connection closed without proper shutdown. Tell caller we
10937 // have reached end-of-stream.
10938 conscrypt::jniutil::throwException(env, "java/io/EOFException", "Read error");
10939 break;
10940 }
10941
10942 if (errno == EINTR) {
10943 // TODO(nmittler): Can this happen with memory BIOs?
10944 // System call has been interrupted. Simply retry.
10945 conscrypt::jniutil::throwException(env, "java/io/InterruptedIOException",
10946 "Read error");
10947 break;
10948 }
10949
10950 // Note that for all other system call errors we fall through
10951 // to the default case, which results in an Exception.
10952 FALLTHROUGH_INTENDED;
10953 }
10954 default: {
10955 // Everything else is basically an error.
10956 conscrypt::jniutil::throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
10957 "Read error");
10958 break;
10959 }
10960 }
10961
10962 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_force_read shc=%p", ssl, shc);
10963 }
10964
10965 /**
10966 * OpenSSL write function (2): write into buffer at offset n chunks.
10967 */
NativeCrypto_ENGINE_SSL_write_direct(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong address,jint len,jobject shc)10968 static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_address,
10969 CONSCRYPT_UNUSED jobject ssl_holder, jlong address,
10970 jint len, jobject shc) {
10971 CHECK_ERROR_QUEUE_ON_RETURN;
10972 SSL* ssl = to_SSL(env, ssl_address, true);
10973 const char* sourcePtr = reinterpret_cast<const char*>(address);
10974 if (ssl == nullptr) {
10975 return -1;
10976 }
10977 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p", ssl,
10978 sourcePtr, len, shc);
10979 if (shc == nullptr) {
10980 conscrypt::jniutil::throwNullPointerException(env, "sslHandshakeCallbacks == null");
10981 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => sslHandshakeCallbacks == null",
10982 ssl);
10983 return -1;
10984 }
10985
10986 AppData* appData = toAppData(ssl);
10987 if (appData == nullptr) {
10988 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to retrieve application data");
10989 ERR_clear_error();
10990 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct appData => null", ssl);
10991 return -1;
10992 }
10993 if (!appData->setCallbackState(env, shc, nullptr)) {
10994 conscrypt::jniutil::throwSSLExceptionStr(env, "Unable to set appdata callback");
10995 ERR_clear_error();
10996 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct => exception", ssl);
10997 return -1;
10998 }
10999
11000 errno = 0;
11001
11002 int result = SSL_write(ssl, sourcePtr, len);
11003 appData->clearCallbackState();
11004 JNI_TRACE("ssl=%p NativeCrypto_ENGINE_SSL_write_direct address=%p length=%d shc=%p => ret=%d",
11005 ssl, sourcePtr, len, shc, result);
11006 return result;
11007 }
11008
11009 /**
11010 * public static native bool usesBoringSsl_FIPS_mode();
11011 */
NativeCrypto_usesBoringSsl_FIPS_mode()11012 static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() {
11013 return FIPS_mode();
11014 }
11015
11016 /**
11017 * Scrypt support
11018 */
11019
NativeCrypto_Scrypt_generate_key(JNIEnv * env,jclass,jbyteArray password,jbyteArray salt,jint n,jint r,jint p,jint key_len)11020 static jbyteArray NativeCrypto_Scrypt_generate_key(JNIEnv* env, jclass, jbyteArray password, jbyteArray salt,
11021 jint n, jint r, jint p, jint key_len) {
11022 CHECK_ERROR_QUEUE_ON_RETURN;
11023 JNI_TRACE("Scrypt_generate_key(%p, %p, %d, %d, %d, %d)", password, salt, n, r, p, key_len);
11024
11025 if (password == nullptr) {
11026 conscrypt::jniutil::throwNullPointerException(env, "password == null");
11027 JNI_TRACE("Scrypt_generate_key() => password == null");
11028 return nullptr;
11029 }
11030 if (salt == nullptr) {
11031 conscrypt::jniutil::throwNullPointerException(env, "salt == null");
11032 JNI_TRACE("Scrypt_generate_key() => salt == null");
11033 return nullptr;
11034 }
11035
11036 jbyteArray key_bytes = env->NewByteArray(static_cast<jsize>(key_len));
11037 ScopedByteArrayRW out_key(env, key_bytes);
11038 if (out_key.get() == nullptr) {
11039 conscrypt::jniutil::throwNullPointerException(env, "out_key == null");
11040 JNI_TRACE("Scrypt_generate_key() => out_key == null");
11041 return nullptr;
11042 }
11043
11044 size_t memory_limit = 1u << 29;
11045 ScopedByteArrayRO password_bytes(env, password);
11046 ScopedByteArrayRO salt_bytes(env, salt);
11047
11048 int result = EVP_PBE_scrypt(reinterpret_cast<const char*>(password_bytes.get()), password_bytes.size(),
11049 reinterpret_cast<const uint8_t*>(salt_bytes.get()), salt_bytes.size(),
11050 n, r, p, memory_limit,
11051 reinterpret_cast<uint8_t*>(out_key.get()), key_len);
11052
11053 if (result <= 0) {
11054 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "Scrypt_generate_key");
11055 return nullptr;
11056 }
11057 return key_bytes;
11058 }
11059
11060 /**
11061 * SPAKE2+ support
11062 */
11063
11064 #define SPAKE2PLUS_PW_VERIFIER_SIZE 32
11065 #define SPAKE2PLUS_REGISTRATION_RECORD_SIZE 65
11066
NativeCrypto_SSL_CTX_set_spake_credential(JNIEnv * env,jclass,jbyteArray context,jbyteArray pw_array,jbyteArray id_prover_array,jbyteArray id_verifier_array,jboolean is_client,jint handshake_limit,jlong ssl_ctx_address,CONSCRYPT_UNUSED jobject holder)11067 static void NativeCrypto_SSL_CTX_set_spake_credential(JNIEnv* env, jclass,
11068 jbyteArray context, jbyteArray pw_array,
11069 jbyteArray id_prover_array,
11070 jbyteArray id_verifier_array,
11071 jboolean is_client,
11072 jint handshake_limit,
11073 jlong ssl_ctx_address,
11074 CONSCRYPT_UNUSED jobject holder) {
11075 CHECK_ERROR_QUEUE_ON_RETURN;
11076
11077 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
11078
11079 if (ssl_ctx == nullptr) {
11080 JNI_TRACE("SSL_CTX_set_spake_credential => ssl_ctx == null");
11081 return;
11082 }
11083
11084 JNI_TRACE("SSL_CTX_set_spake_credential(%p, %p, %p, %p, %d, %d, %p)", context, pw_array,
11085 id_prover_array, id_verifier_array, is_client, handshake_limit,
11086 ssl_ctx);
11087
11088 if (context == nullptr || pw_array == nullptr || id_prover_array == nullptr ||
11089 id_verifier_array == nullptr) {
11090 conscrypt::jniutil::throwNullPointerException(env, "Input parameters cannot be null");
11091 return;
11092 }
11093
11094 ScopedByteArrayRO context_bytes(env, context);
11095 if (context_bytes.get() == nullptr) {
11096 JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11097 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for context");
11098 return;
11099 }
11100
11101 ScopedByteArrayRO pw_bytes(env, pw_array);
11102 if (pw_bytes.get() == nullptr) {
11103 JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11104 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for pw_array");
11105 return;
11106 }
11107
11108 ScopedByteArrayRO id_prover_bytes(env, id_prover_array);
11109 if (id_prover_bytes.get() == nullptr) {
11110 JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11111 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for id_prover_array");
11112 return;
11113 }
11114
11115 ScopedByteArrayRO id_verifier_bytes(env, id_verifier_array);
11116 if (id_verifier_bytes.get() == nullptr) {
11117 JNI_TRACE("ctx=%p SSL_CTX_set_spake_credential => threw exception", ssl_ctx);
11118 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for id_verifier_array");
11119 return;
11120 }
11121
11122 uint8_t pw_verifier_w0[SPAKE2PLUS_PW_VERIFIER_SIZE];
11123 uint8_t pw_verifier_w1[SPAKE2PLUS_PW_VERIFIER_SIZE];
11124 uint8_t registration_record[SPAKE2PLUS_REGISTRATION_RECORD_SIZE];
11125 int ret = SSL_spake2plusv1_register(
11126 /* out_pw_verifier_w0= */ pw_verifier_w0,
11127 /* out_pw_verifier_w1= */ pw_verifier_w1,
11128 /* out_registration_record= */ registration_record,
11129 /* pw= */ reinterpret_cast<const uint8_t*>(pw_bytes.get()),
11130 /* pw_len= */ pw_bytes.size(),
11131 /* id_prover= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11132 /* id_prover_len= */ id_prover_bytes.size(),
11133 /* id_verifier= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11134 /* id_verifier_len= */ id_verifier_bytes.size());
11135 if (ret != 1) {
11136 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_spake2plusv1_register failed");
11137 return;
11138 }
11139
11140 bssl::UniquePtr<SSL_CREDENTIAL> creds;
11141 if (is_client) {
11142 bssl::UniquePtr<SSL_CREDENTIAL> creds_client(SSL_CREDENTIAL_new_spake2plusv1_client(
11143 /* context= */ reinterpret_cast<const uint8_t*>(context_bytes.get()),
11144 /* context_len= */ context_bytes.size(),
11145 /* client_identity= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11146 /* client_identity_len= */ id_prover_bytes.size(),
11147 /* server_identity= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11148 /* server_identity_len= */ id_verifier_bytes.size(),
11149 /* attempts= */ handshake_limit,
11150 /* w0= */ pw_verifier_w0,
11151 /* w0_len= */ sizeof(pw_verifier_w0),
11152 /* w1= */ pw_verifier_w1,
11153 /* w1_len= */ sizeof(pw_verifier_w1)));
11154 creds = std::move(creds_client);
11155 } else {
11156 bssl::UniquePtr<SSL_CREDENTIAL> creds_server(SSL_CREDENTIAL_new_spake2plusv1_server(
11157 /* context= */ reinterpret_cast<const uint8_t*>(context_bytes.get()),
11158 /* context_len= */ context_bytes.size(),
11159 /* client_identity= */ reinterpret_cast<const uint8_t*>(id_prover_bytes.get()),
11160 /* client_identity_len= */ id_prover_bytes.size(),
11161 /* server_identity= */ reinterpret_cast<const uint8_t*>(id_verifier_bytes.get()),
11162 /* server_identity_len= */ id_verifier_bytes.size(),
11163 /* attempts= */ handshake_limit,
11164 /* w0= */ pw_verifier_w0,
11165 /* w0_len= */ sizeof(pw_verifier_w0),
11166 /* registration_record= */ registration_record,
11167 /* registration_record_len= */ sizeof(registration_record)));
11168 creds = std::move(creds_server);
11169 }
11170 if (creds == nullptr) {
11171 conscrypt::jniutil::throwSSLExceptionStr(
11172 env, "SSL_CREDENTIAL_new_spake2plusv1 failed");
11173 return;
11174 }
11175 ret = SSL_CTX_add1_credential(ssl_ctx, creds.get());
11176 if (ret != 1) {
11177 conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_add1_credential failed");
11178 return;
11179 }
11180 JNI_TRACE("SSL_CTX_set_spake_credential (%p, %p, %p, %p, %d, %d, %p) => %p", context, pw_array,
11181 id_prover_array, id_verifier_array, is_client, handshake_limit, ssl_ctx, creds.get());
11182 return;
11183 }
11184
11185 // TESTING METHODS BEGIN
11186
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)11187 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
11188 CHECK_ERROR_QUEUE_ON_RETURN;
11189 BIO* bio = to_BIO(env, bioRef);
11190 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
11191
11192 if (bio == nullptr) {
11193 JNI_TRACE("BIO_read(%p, %p) => bio == null", bio, outputJavaBytes);
11194 return 0;
11195 }
11196
11197 if (outputJavaBytes == nullptr) {
11198 conscrypt::jniutil::throwNullPointerException(env, "output == null");
11199 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
11200 return 0;
11201 }
11202
11203 jsize outputSize = env->GetArrayLength(outputJavaBytes);
11204
11205 std::unique_ptr<unsigned char[]> buffer(
11206 new unsigned char[static_cast<unsigned int>(outputSize)]);
11207 if (buffer.get() == nullptr) {
11208 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for read");
11209 return 0;
11210 }
11211
11212 int read = BIO_read(bio, buffer.get(), static_cast<int>(outputSize));
11213 if (read <= 0) {
11214 conscrypt::jniutil::throwIOException(env, "BIO_read");
11215 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
11216 return 0;
11217 }
11218
11219 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
11220 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
11221 return read;
11222 }
11223
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)11224 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
11225 jint offset, jint length) {
11226 CHECK_ERROR_QUEUE_ON_RETURN;
11227 BIO* bio = to_BIO(env, bioRef);
11228 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
11229
11230 if (bio == nullptr) {
11231 return;
11232 }
11233
11234 if (inputJavaBytes == nullptr) {
11235 conscrypt::jniutil::throwNullPointerException(env, "input == null");
11236 return;
11237 }
11238
11239 int inputSize = env->GetArrayLength(inputJavaBytes);
11240 if (offset < 0 || offset > inputSize || length < 0 || length > inputSize - offset) {
11241 conscrypt::jniutil::throwException(env, "java/lang/ArrayIndexOutOfBoundsException",
11242 "inputJavaBytes");
11243 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
11244 return;
11245 }
11246
11247 std::unique_ptr<unsigned char[]> buffer(new unsigned char[static_cast<unsigned int>(length)]);
11248 if (buffer.get() == nullptr) {
11249 conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for write");
11250 return;
11251 }
11252
11253 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
11254 if (BIO_write(bio, buffer.get(), length) != length) {
11255 ERR_clear_error();
11256 conscrypt::jniutil::throwIOException(env, "BIO_write");
11257 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
11258 return;
11259 }
11260
11261 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
11262 }
11263
11264 /**
11265 * public static native long SSL_clear_mode(long ssl, long mode);
11266 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder,jlong mode)11267 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass, jlong ssl_address,
11268 CONSCRYPT_UNUSED jobject ssl_holder, jlong mode) {
11269 CHECK_ERROR_QUEUE_ON_RETURN;
11270 SSL* ssl = to_SSL(env, ssl_address, true);
11271 // NOLINTNEXTLINE(runtime/int)
11272 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long)mode);
11273 if (ssl == nullptr) {
11274 return 0;
11275 }
11276 jlong result = static_cast<jlong>(SSL_clear_mode(ssl, static_cast<uint32_t>(mode)));
11277 // NOLINTNEXTLINE(runtime/int)
11278 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, (long)result);
11279 return result;
11280 }
11281
11282 /**
11283 * public static native long SSL_get_mode(long ssl);
11284 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11285 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address,
11286 CONSCRYPT_UNUSED jobject ssl_holder) {
11287 CHECK_ERROR_QUEUE_ON_RETURN;
11288 SSL* ssl = to_SSL(env, ssl_address, true);
11289 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
11290 if (ssl == nullptr) {
11291 return 0;
11292 }
11293 jlong mode = static_cast<jlong>(SSL_get_mode(ssl));
11294 // NOLINTNEXTLINE(runtime/int)
11295 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, (long)mode);
11296 return mode;
11297 }
11298
11299 /**
11300 * public static native long SSL_get_options(long ssl);
11301 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11302 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass, jlong ssl_address,
11303 CONSCRYPT_UNUSED jobject ssl_holder) {
11304 CHECK_ERROR_QUEUE_ON_RETURN;
11305 SSL* ssl = to_SSL(env, ssl_address, true);
11306 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
11307 if (ssl == nullptr) {
11308 return 0;
11309 }
11310 jlong options = static_cast<jlong>(SSL_get_options(ssl));
11311 // NOLINTNEXTLINE(runtime/int)
11312 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, (long)options);
11313 return options;
11314 }
11315
NativeCrypto_SSL_get1_session(JNIEnv * env,jclass,jlong ssl_address,CONSCRYPT_UNUSED jobject ssl_holder)11316 static jlong NativeCrypto_SSL_get1_session(JNIEnv* env, jclass, jlong ssl_address,
11317 CONSCRYPT_UNUSED jobject ssl_holder) {
11318 CHECK_ERROR_QUEUE_ON_RETURN;
11319 SSL* ssl = to_SSL(env, ssl_address, true);
11320 if (ssl == nullptr) {
11321 return 0;
11322 }
11323 return reinterpret_cast<uintptr_t>(SSL_get1_session(ssl));
11324 }
11325
11326 // TESTING METHODS END
11327
11328 #define CONSCRYPT_NATIVE_METHOD(functionName, signature) \
11329 { \
11330 /* NOLINTNEXTLINE */ \
11331 (char*)#functionName, (char*)(signature), \
11332 reinterpret_cast<void*>(NativeCrypto_##functionName) \
11333 }
11334
11335 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
11336 #define SSL_CALLBACKS \
11337 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
11338 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
11339 #define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
11340 #define REF_EVP_CIPHER_CTX \
11341 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
11342 #define REF_EVP_HPKE_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_CTX;"
11343 #define REF_EVP_HPKE_KEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_HPKE_KEY;"
11344 #define REF_EVP_MD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;"
11345 #define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
11346 #define REF_EVP_PKEY_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY_CTX;"
11347 #define REF_HMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$HMAC_CTX;"
11348 #define REF_CMAC_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$CMAC_CTX;"
11349 #define REF_BIO_IN_STREAM "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;"
11350 #define REF_X509 "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509Certificate;"
11351 #define REF_X509_CRL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CRL;"
11352 #define REF_SSL "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeSsl;"
11353 #define REF_SSL_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/AbstractSessionContext;"
11354 static JNINativeMethod sNativeCryptoMethods[] = {
11355 CONSCRYPT_NATIVE_METHOD(clinit, "()V"),
11356 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_new, "()J"),
11357 CONSCRYPT_NATIVE_METHOD(CMAC_CTX_free, "(J)V"),
11358 CONSCRYPT_NATIVE_METHOD(CMAC_Init, "(" REF_CMAC_CTX "[B)V"),
11359 CONSCRYPT_NATIVE_METHOD(CMAC_Update, "(" REF_CMAC_CTX "[BII)V"),
11360 CONSCRYPT_NATIVE_METHOD(CMAC_UpdateDirect, "(" REF_CMAC_CTX "JI)V"),
11361 CONSCRYPT_NATIVE_METHOD(CMAC_Final, "(" REF_CMAC_CTX ")[B"),
11362 CONSCRYPT_NATIVE_METHOD(CMAC_Reset, "(" REF_CMAC_CTX ")V"),
11363 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
11364 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
11365 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
11366 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11367 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_print_params, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
11368 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_free, "(J)V"),
11369 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11370 CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
11371 CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
11372 CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"),
11373 CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
11374 CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),
11375 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"),
11376 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PrivateKey, "(J)J"),
11377 CONSCRYPT_NATIVE_METHOD(getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
11378 CONSCRYPT_NATIVE_METHOD(getECPrivateKeyWrapper,
11379 "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
11380 CONSCRYPT_NATIVE_METHOD(RSA_generate_key_ex, "(I[B)J"),
11381 CONSCRYPT_NATIVE_METHOD(RSA_size, "(" REF_EVP_PKEY ")I"),
11382 CONSCRYPT_NATIVE_METHOD(RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11383 CONSCRYPT_NATIVE_METHOD(RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11384 CONSCRYPT_NATIVE_METHOD(RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11385 CONSCRYPT_NATIVE_METHOD(RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
11386 CONSCRYPT_NATIVE_METHOD(get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
11387 CONSCRYPT_NATIVE_METHOD(get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
11388 CONSCRYPT_NATIVE_METHOD(chacha20_encrypt_decrypt, "([BI[BII[B[BI)V"),
11389 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
11390 CONSCRYPT_NATIVE_METHOD(EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
11391 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
11392 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
11393 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
11394 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
11395 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
11396 CONSCRYPT_NATIVE_METHOD(EC_GROUP_clear_free, "(J)V"),
11397 CONSCRYPT_NATIVE_METHOD(EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
11398 CONSCRYPT_NATIVE_METHOD(EC_POINT_new, "(" REF_EC_GROUP ")J"),
11399 CONSCRYPT_NATIVE_METHOD(EC_POINT_clear_free, "(J)V"),
11400 CONSCRYPT_NATIVE_METHOD(EC_POINT_set_affine_coordinates,
11401 "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
11402 CONSCRYPT_NATIVE_METHOD(EC_POINT_get_affine_coordinates,
11403 "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
11404 CONSCRYPT_NATIVE_METHOD(EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
11405 CONSCRYPT_NATIVE_METHOD(EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
11406 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
11407 CONSCRYPT_NATIVE_METHOD(EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
11408 CONSCRYPT_NATIVE_METHOD(EC_KEY_marshal_curve_name, "(" REF_EC_GROUP ")[B"),
11409 CONSCRYPT_NATIVE_METHOD(EC_KEY_parse_curve_name, "([B)J"),
11410 CONSCRYPT_NATIVE_METHOD(ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
11411 CONSCRYPT_NATIVE_METHOD(ECDSA_size, "(" REF_EVP_PKEY ")I"),
11412 CONSCRYPT_NATIVE_METHOD(ECDSA_sign, "([B[B" REF_EVP_PKEY ")I"),
11413 CONSCRYPT_NATIVE_METHOD(ECDSA_verify, "([B[B" REF_EVP_PKEY ")I"),
11414 CONSCRYPT_NATIVE_METHOD(X25519, "([B[B[B)Z"),
11415 CONSCRYPT_NATIVE_METHOD(X25519_keypair, "([B[B)V"),
11416 CONSCRYPT_NATIVE_METHOD(ED25519_keypair, "([B[B)V"),
11417 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_create, "()J"),
11418 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_cleanup, "(" REF_EVP_MD_CTX ")V"),
11419 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_destroy, "(J)V"),
11420 CONSCRYPT_NATIVE_METHOD(EVP_MD_CTX_copy_ex, "(" REF_EVP_MD_CTX REF_EVP_MD_CTX ")I"),
11421 CONSCRYPT_NATIVE_METHOD(EVP_DigestInit_ex, "(" REF_EVP_MD_CTX "J)I"),
11422 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11423 CONSCRYPT_NATIVE_METHOD(EVP_DigestUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11424 CONSCRYPT_NATIVE_METHOD(EVP_DigestFinal_ex, "(" REF_EVP_MD_CTX "[BI)I"),
11425 CONSCRYPT_NATIVE_METHOD(EVP_get_digestbyname, "(Ljava/lang/String;)J"),
11426 CONSCRYPT_NATIVE_METHOD(EVP_MD_size, "(J)I"),
11427 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11428 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11429 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11430 CONSCRYPT_NATIVE_METHOD(EVP_DigestSignFinal, "(" REF_EVP_MD_CTX ")[B"),
11431 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyInit, "(" REF_EVP_MD_CTX "J" REF_EVP_PKEY ")J"),
11432 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdate, "(" REF_EVP_MD_CTX "[BII)V"),
11433 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyUpdateDirect, "(" REF_EVP_MD_CTX "JI)V"),
11434 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerifyFinal, "(" REF_EVP_MD_CTX "[BII)Z"),
11435 CONSCRYPT_NATIVE_METHOD(EVP_DigestSign, "(" REF_EVP_MD_CTX "[BII)[B"),
11436 CONSCRYPT_NATIVE_METHOD(EVP_DigestVerify, "(" REF_EVP_MD_CTX "[BII[BII)Z"),
11437 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt_init, "(" REF_EVP_PKEY ")J"),
11438 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_encrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11439 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt_init, "(" REF_EVP_PKEY ")J"),
11440 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_decrypt, "(" REF_EVP_PKEY_CTX "[BI[BII)I"),
11441 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_free, "(J)V"),
11442 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_padding, "(JI)V"),
11443 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_pss_saltlen, "(JI)V"),
11444 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_mgf1_md, "(JJ)V"),
11445 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_md, "(JJ)V"),
11446 CONSCRYPT_NATIVE_METHOD(EVP_PKEY_CTX_set_rsa_oaep_label, "(J[B)V"),
11447 CONSCRYPT_NATIVE_METHOD(EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
11448 CONSCRYPT_NATIVE_METHOD(EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
11449 CONSCRYPT_NATIVE_METHOD(EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
11450 CONSCRYPT_NATIVE_METHOD(EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
11451 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_iv_length, "(J)I"),
11452 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_new, "()J"),
11453 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
11454 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
11455 CONSCRYPT_NATIVE_METHOD(get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
11456 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
11457 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
11458 CONSCRYPT_NATIVE_METHOD(EVP_CIPHER_CTX_free, "(J)V"),
11459 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm, "()J"),
11460 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm, "()J"),
11461 CONSCRYPT_NATIVE_METHOD(EVP_aead_chacha20_poly1305, "()J"),
11462 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_128_gcm_siv, "()J"),
11463 CONSCRYPT_NATIVE_METHOD(EVP_aead_aes_256_gcm_siv, "()J"),
11464 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_max_overhead, "(J)I"),
11465 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_nonce_length, "(J)I"),
11466 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal, "(J[BI[BI[B[BII[B)I"),
11467 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open, "(J[BI[BI[B[BII[B)I"),
11468 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_seal_buf,
11469 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11470 CONSCRYPT_NATIVE_METHOD(EVP_AEAD_CTX_open_buf,
11471 "(J[BILjava/nio/ByteBuffer;[BLjava/nio/ByteBuffer;[B)I"),
11472 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_export, "(" REF_EVP_HPKE_CTX "[BI)[B"),
11473 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_free, "(J)V"),
11474 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_open, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11475 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_seal, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11476 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_recipient,
11477 "(III[B[B[B)Ljava/lang/Object;"),
11478 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender,
11479 "(III[B[B)[Ljava/lang/Object;"),
11480 CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing,
11481 "(III[B[B[B)[Ljava/lang/Object;"),
11482 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
11483 CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
11484 CONSCRYPT_NATIVE_METHOD(HMAC_Init_ex, "(" REF_HMAC_CTX "[BJ)V"),
11485 CONSCRYPT_NATIVE_METHOD(HMAC_Update, "(" REF_HMAC_CTX "[BII)V"),
11486 CONSCRYPT_NATIVE_METHOD(HMAC_UpdateDirect, "(" REF_HMAC_CTX "JI)V"),
11487 CONSCRYPT_NATIVE_METHOD(HMAC_Final, "(" REF_HMAC_CTX ")[B"),
11488 CONSCRYPT_NATIVE_METHOD(HMAC_Reset, "(" REF_HMAC_CTX ")V"),
11489 CONSCRYPT_NATIVE_METHOD(RAND_bytes, "([B)V"),
11490 CONSCRYPT_NATIVE_METHOD(create_BIO_InputStream, ("(" REF_BIO_IN_STREAM "Z)J")),
11491 CONSCRYPT_NATIVE_METHOD(create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
11492 CONSCRYPT_NATIVE_METHOD(BIO_free_all, "(J)V"),
11493 CONSCRYPT_NATIVE_METHOD(d2i_X509_bio, "(J)J"),
11494 CONSCRYPT_NATIVE_METHOD(d2i_X509, "([B)J"),
11495 CONSCRYPT_NATIVE_METHOD(i2d_X509, "(J" REF_X509 ")[B"),
11496 CONSCRYPT_NATIVE_METHOD(i2d_X509_PUBKEY, "(J" REF_X509 ")[B"),
11497 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509, "(J)J"),
11498 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PKCS7, "(JI)[J"),
11499 CONSCRYPT_NATIVE_METHOD(d2i_PKCS7_bio, "(JI)[J"),
11500 CONSCRYPT_NATIVE_METHOD(i2d_PKCS7, "([J)[B"),
11501 CONSCRYPT_NATIVE_METHOD(ASN1_seq_unpack_X509_bio, "(J)[J"),
11502 CONSCRYPT_NATIVE_METHOD(ASN1_seq_pack_X509, "([J)[B"),
11503 CONSCRYPT_NATIVE_METHOD(X509_free, "(J" REF_X509 ")V"),
11504 CONSCRYPT_NATIVE_METHOD(X509_cmp, "(J" REF_X509 "J" REF_X509 ")I"),
11505 CONSCRYPT_NATIVE_METHOD(X509_print_ex, "(JJ" REF_X509 "JJ)V"),
11506 CONSCRYPT_NATIVE_METHOD(X509_get_pubkey, "(J" REF_X509 ")J"),
11507 CONSCRYPT_NATIVE_METHOD(X509_get_issuer_name, "(J" REF_X509 ")[B"),
11508 CONSCRYPT_NATIVE_METHOD(X509_get_subject_name, "(J" REF_X509 ")[B"),
11509 CONSCRYPT_NATIVE_METHOD(get_X509_pubkey_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11510 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_oid, "(J" REF_X509 ")Ljava/lang/String;"),
11511 CONSCRYPT_NATIVE_METHOD(get_X509_sig_alg_parameter, "(J" REF_X509 ")[B"),
11512 CONSCRYPT_NATIVE_METHOD(get_X509_issuerUID, "(J" REF_X509 ")[Z"),
11513 CONSCRYPT_NATIVE_METHOD(get_X509_subjectUID, "(J" REF_X509 ")[Z"),
11514 CONSCRYPT_NATIVE_METHOD(get_X509_ex_kusage, "(J" REF_X509 ")[Z"),
11515 CONSCRYPT_NATIVE_METHOD(get_X509_ex_xkusage, "(J" REF_X509 ")[Ljava/lang/String;"),
11516 CONSCRYPT_NATIVE_METHOD(get_X509_ex_pathlen, "(J" REF_X509 ")I"),
11517 CONSCRYPT_NATIVE_METHOD(X509_get_ext_oid, "(J" REF_X509 "Ljava/lang/String;)[B"),
11518 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext_oid, "(J" REF_X509_CRL "Ljava/lang/String;)[B"),
11519 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_crl_enc, "(J" REF_X509_CRL ")[B"),
11520 CONSCRYPT_NATIVE_METHOD(X509_CRL_verify, "(J" REF_X509_CRL REF_EVP_PKEY ")V"),
11521 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_lastUpdate, "(J" REF_X509_CRL ")J"),
11522 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_nextUpdate, "(J" REF_X509_CRL ")J"),
11523 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
11524 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_serialNumber, "(J)[B"),
11525 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_print, "(JJ)V"),
11526 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_revocationDate, "(J)J"),
11527 CONSCRYPT_NATIVE_METHOD(get_X509_ext_oids, "(J" REF_X509 "I)[Ljava/lang/String;"),
11528 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_ext_oids, "(J" REF_X509_CRL "I)[Ljava/lang/String;"),
11529 CONSCRYPT_NATIVE_METHOD(get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
11530 CONSCRYPT_NATIVE_METHOD(get_X509_GENERAL_NAME_stack,
11531 "(J" REF_X509 "I)[[Ljava/lang/Object;"),
11532 CONSCRYPT_NATIVE_METHOD(X509_get_notBefore, "(J" REF_X509 ")J"),
11533 CONSCRYPT_NATIVE_METHOD(X509_get_notAfter, "(J" REF_X509 ")J"),
11534 CONSCRYPT_NATIVE_METHOD(X509_get_version, "(J" REF_X509 ")J"),
11535 CONSCRYPT_NATIVE_METHOD(X509_get_serialNumber, "(J" REF_X509 ")[B"),
11536 CONSCRYPT_NATIVE_METHOD(X509_verify, "(J" REF_X509 REF_EVP_PKEY ")V"),
11537 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert, "(J" REF_X509 ")[B"),
11538 CONSCRYPT_NATIVE_METHOD(get_X509_tbs_cert_without_ext,
11539 "(J" REF_X509 "Ljava/lang/String;)[B"),
11540 CONSCRYPT_NATIVE_METHOD(get_X509_signature, "(J" REF_X509 ")[B"),
11541 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_signature, "(J" REF_X509_CRL ")[B"),
11542 CONSCRYPT_NATIVE_METHOD(get_X509_ex_flags, "(J" REF_X509 ")I"),
11543 CONSCRYPT_NATIVE_METHOD(X509_check_issued, "(J" REF_X509 "J" REF_X509 ")I"),
11544 CONSCRYPT_NATIVE_METHOD(d2i_X509_CRL_bio, "(J)J"),
11545 CONSCRYPT_NATIVE_METHOD(PEM_read_bio_X509_CRL, "(J)J"),
11546 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_cert, "(J" REF_X509_CRL "J" REF_X509 ")J"),
11547 CONSCRYPT_NATIVE_METHOD(X509_CRL_get0_by_serial, "(J" REF_X509_CRL "[B)J"),
11548 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_REVOKED, "(J" REF_X509_CRL ")[J"),
11549 CONSCRYPT_NATIVE_METHOD(i2d_X509_CRL, "(J" REF_X509_CRL ")[B"),
11550 CONSCRYPT_NATIVE_METHOD(X509_CRL_free, "(J" REF_X509_CRL ")V"),
11551 CONSCRYPT_NATIVE_METHOD(X509_CRL_print, "(JJ" REF_X509_CRL ")V"),
11552 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_oid, "(J" REF_X509_CRL ")Ljava/lang/String;"),
11553 CONSCRYPT_NATIVE_METHOD(get_X509_CRL_sig_alg_parameter, "(J" REF_X509_CRL ")[B"),
11554 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_issuer_name, "(J" REF_X509_CRL ")[B"),
11555 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_version, "(J" REF_X509_CRL ")J"),
11556 CONSCRYPT_NATIVE_METHOD(X509_CRL_get_ext, "(J" REF_X509_CRL "Ljava/lang/String;)J"),
11557 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
11558 CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
11559 CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
11560 CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
11561 CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
11562 CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
11563 CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
11564 CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
11565 CONSCRYPT_NATIVE_METHOD(asn1_read_tagged, "(J)J"),
11566 CONSCRYPT_NATIVE_METHOD(asn1_read_octetstring, "(J)[B"),
11567 CONSCRYPT_NATIVE_METHOD(asn1_read_uint64, "(J)J"),
11568 CONSCRYPT_NATIVE_METHOD(asn1_read_null, "(J)V"),
11569 CONSCRYPT_NATIVE_METHOD(asn1_read_oid, "(J)Ljava/lang/String;"),
11570 CONSCRYPT_NATIVE_METHOD(asn1_read_is_empty, "(J)Z"),
11571 CONSCRYPT_NATIVE_METHOD(asn1_read_free, "(J)V"),
11572 CONSCRYPT_NATIVE_METHOD(asn1_write_init, "()J"),
11573 CONSCRYPT_NATIVE_METHOD(asn1_write_sequence, "(J)J"),
11574 CONSCRYPT_NATIVE_METHOD(asn1_write_tag, "(JI)J"),
11575 CONSCRYPT_NATIVE_METHOD(asn1_write_octetstring, "(J[B)V"),
11576 CONSCRYPT_NATIVE_METHOD(asn1_write_uint64, "(JJ)V"),
11577 CONSCRYPT_NATIVE_METHOD(asn1_write_null, "(J)V"),
11578 CONSCRYPT_NATIVE_METHOD(asn1_write_oid, "(JLjava/lang/String;)V"),
11579 CONSCRYPT_NATIVE_METHOD(asn1_write_flush, "(J)V"),
11580 CONSCRYPT_NATIVE_METHOD(asn1_write_cleanup, "(J)V"),
11581 CONSCRYPT_NATIVE_METHOD(asn1_write_finish, "(J)[B"),
11582 CONSCRYPT_NATIVE_METHOD(asn1_write_free, "(J)V"),
11583 CONSCRYPT_NATIVE_METHOD(EVP_has_aes_hardware, "()I"),
11584 CONSCRYPT_NATIVE_METHOD(SSL_CTX_new, "()J"),
11585 CONSCRYPT_NATIVE_METHOD(SSL_CTX_free, "(J" REF_SSL_CTX ")V"),
11586 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_session_id_context, "(J" REF_SSL_CTX "[B)V"),
11587 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_timeout, "(J" REF_SSL_CTX "J)J"),
11588 CONSCRYPT_NATIVE_METHOD(SSL_new, "(J" REF_SSL_CTX ")J"),
11589 CONSCRYPT_NATIVE_METHOD(SSL_enable_tls_channel_id, "(J" REF_SSL ")V"),
11590 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_channel_id, "(J" REF_SSL ")[B"),
11591 CONSCRYPT_NATIVE_METHOD(SSL_set1_tls_channel_id, "(J" REF_SSL REF_EVP_PKEY ")V"),
11592 CONSCRYPT_NATIVE_METHOD(setLocalCertsAndPrivateKey, "(J" REF_SSL "[[B" REF_EVP_PKEY ")V"),
11593 CONSCRYPT_NATIVE_METHOD(SSL_set_client_CA_list, "(J" REF_SSL "[[B)V"),
11594 CONSCRYPT_NATIVE_METHOD(SSL_set_mode, "(J" REF_SSL "J)J"),
11595 CONSCRYPT_NATIVE_METHOD(SSL_set_options, "(J" REF_SSL "J)J"),
11596 CONSCRYPT_NATIVE_METHOD(SSL_clear_options, "(J" REF_SSL "J)J"),
11597 CONSCRYPT_NATIVE_METHOD(SSL_set_protocol_versions, "(J" REF_SSL "II)I"),
11598 CONSCRYPT_NATIVE_METHOD(SSL_enable_signed_cert_timestamps, "(J" REF_SSL ")V"),
11599 CONSCRYPT_NATIVE_METHOD(SSL_get_signed_cert_timestamp_list, "(J" REF_SSL ")[B"),
11600 CONSCRYPT_NATIVE_METHOD(SSL_set_signed_cert_timestamp_list, "(J" REF_SSL "[B)V"),
11601 CONSCRYPT_NATIVE_METHOD(SSL_enable_ocsp_stapling, "(J" REF_SSL ")V"),
11602 CONSCRYPT_NATIVE_METHOD(SSL_get_ocsp_response, "(J" REF_SSL ")[B"),
11603 CONSCRYPT_NATIVE_METHOD(SSL_set_ocsp_response, "(J" REF_SSL "[B)V"),
11604 CONSCRYPT_NATIVE_METHOD(SSL_get_tls_unique, "(J" REF_SSL ")[B"),
11605 CONSCRYPT_NATIVE_METHOD(SSL_export_keying_material, "(J" REF_SSL "[B[BI)[B"),
11606 CONSCRYPT_NATIVE_METHOD(SSL_use_psk_identity_hint, "(J" REF_SSL "Ljava/lang/String;)V"),
11607 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_client_callback_enabled, "(J" REF_SSL "Z)V"),
11608 CONSCRYPT_NATIVE_METHOD(set_SSL_psk_server_callback_enabled, "(J" REF_SSL "Z)V"),
11609 CONSCRYPT_NATIVE_METHOD(SSL_set_cipher_lists, "(J" REF_SSL "[Ljava/lang/String;)V"),
11610 CONSCRYPT_NATIVE_METHOD(SSL_get_ciphers, "(J" REF_SSL ")[J"),
11611 CONSCRYPT_NATIVE_METHOD(SSL_set_accept_state, "(J" REF_SSL ")V"),
11612 CONSCRYPT_NATIVE_METHOD(SSL_set_connect_state, "(J" REF_SSL ")V"),
11613 CONSCRYPT_NATIVE_METHOD(SSL_set_verify, "(J" REF_SSL "I)V"),
11614 CONSCRYPT_NATIVE_METHOD(SSL_set_session, "(J" REF_SSL "J)V"),
11615 CONSCRYPT_NATIVE_METHOD(SSL_set_session_creation_enabled, "(J" REF_SSL "Z)V"),
11616 CONSCRYPT_NATIVE_METHOD(SSL_session_reused, "(J" REF_SSL ")Z"),
11617 CONSCRYPT_NATIVE_METHOD(SSL_accept_renegotiations, "(J" REF_SSL ")V"),
11618 CONSCRYPT_NATIVE_METHOD(SSL_set_tlsext_host_name, "(J" REF_SSL "Ljava/lang/String;)V"),
11619 CONSCRYPT_NATIVE_METHOD(SSL_get_servername, "(J" REF_SSL ")Ljava/lang/String;"),
11620 CONSCRYPT_NATIVE_METHOD(SSL_do_handshake, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
11621 CONSCRYPT_NATIVE_METHOD(SSL_get_current_cipher, "(J" REF_SSL ")Ljava/lang/String;"),
11622 CONSCRYPT_NATIVE_METHOD(SSL_get_version, "(J" REF_SSL ")Ljava/lang/String;"),
11623 CONSCRYPT_NATIVE_METHOD(SSL_get0_peer_certificates, "(J" REF_SSL ")[[B"),
11624 CONSCRYPT_NATIVE_METHOD(SSL_read, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
11625 CONSCRYPT_NATIVE_METHOD(SSL_write, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
11626 CONSCRYPT_NATIVE_METHOD(SSL_interrupt, "(J" REF_SSL ")V"),
11627 CONSCRYPT_NATIVE_METHOD(SSL_shutdown, "(J" REF_SSL FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
11628 CONSCRYPT_NATIVE_METHOD(SSL_get_shutdown, "(J" REF_SSL ")I"),
11629 CONSCRYPT_NATIVE_METHOD(SSL_free, "(J" REF_SSL ")V"),
11630 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_session_id, "(J)[B"),
11631 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_time, "(J)J"),
11632 CONSCRYPT_NATIVE_METHOD(SSL_get_time, "(J" REF_SSL ")J"),
11633 CONSCRYPT_NATIVE_METHOD(SSL_set_timeout, "(J" REF_SSL "J)J"),
11634 CONSCRYPT_NATIVE_METHOD(SSL_get_timeout, "(J" REF_SSL ")J"),
11635 CONSCRYPT_NATIVE_METHOD(SSL_get_signature_algorithm_key_type, "(I)I"),
11636 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_timeout, "(J)J"),
11637 CONSCRYPT_NATIVE_METHOD(SSL_session_id, "(J" REF_SSL ")[B"),
11638 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
11639 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
11640 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_should_be_single_use, "(J)Z"),
11641 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_up_ref, "(J)V"),
11642 CONSCRYPT_NATIVE_METHOD(SSL_SESSION_free, "(J)V"),
11643 CONSCRYPT_NATIVE_METHOD(i2d_SSL_SESSION, "(J)[B"),
11644 CONSCRYPT_NATIVE_METHOD(d2i_SSL_SESSION, "([B)J"),
11645 CONSCRYPT_NATIVE_METHOD(getApplicationProtocol, "(J" REF_SSL ")[B"),
11646 CONSCRYPT_NATIVE_METHOD(setApplicationProtocols, "(J" REF_SSL "Z[B)V"),
11647 CONSCRYPT_NATIVE_METHOD(setHasApplicationProtocolSelector, "(J" REF_SSL "Z)V"),
11648 CONSCRYPT_NATIVE_METHOD(SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
11649 CONSCRYPT_NATIVE_METHOD(get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
11650 CONSCRYPT_NATIVE_METHOD(get_ocsp_single_extension,
11651 "([BLjava/lang/String;J" REF_X509 "J" REF_X509 ")[B"),
11652 CONSCRYPT_NATIVE_METHOD(getDirectBufferAddress, "(Ljava/nio/Buffer;)J"),
11653 CONSCRYPT_NATIVE_METHOD(SSL_BIO_new, "(J" REF_SSL ")J"),
11654 CONSCRYPT_NATIVE_METHOD(SSL_max_seal_overhead, "(J" REF_SSL ")I"),
11655 CONSCRYPT_NATIVE_METHOD(SSL_clear_error, "()V"),
11656 CONSCRYPT_NATIVE_METHOD(SSL_pending_readable_bytes, "(J" REF_SSL ")I"),
11657 CONSCRYPT_NATIVE_METHOD(SSL_pending_written_bytes_in_BIO, "(J)I"),
11658 CONSCRYPT_NATIVE_METHOD(SSL_get_error, "(J" REF_SSL "I)I"),
11659 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_do_handshake, "(J" REF_SSL SSL_CALLBACKS ")I"),
11660 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11661 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_direct, "(J" REF_SSL "JI" SSL_CALLBACKS ")I"),
11662 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_write_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11663 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_read_BIO_direct, "(J" REF_SSL "JJI" SSL_CALLBACKS ")I"),
11664 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_force_read, "(J" REF_SSL SSL_CALLBACKS ")V"),
11665 CONSCRYPT_NATIVE_METHOD(ENGINE_SSL_shutdown, "(J" REF_SSL SSL_CALLBACKS ")V"),
11666 CONSCRYPT_NATIVE_METHOD(usesBoringSsl_FIPS_mode, "()Z"),
11667 CONSCRYPT_NATIVE_METHOD(Scrypt_generate_key, "([B[BIIII)[B"),
11668 CONSCRYPT_NATIVE_METHOD(SSL_CTX_set_spake_credential, "([B[B[B[BZIJ" REF_SSL_CTX ")V"),
11669
11670 // Used for testing only.
11671 CONSCRYPT_NATIVE_METHOD(BIO_read, "(J[B)I"),
11672 CONSCRYPT_NATIVE_METHOD(BIO_write, "(J[BII)V"),
11673 CONSCRYPT_NATIVE_METHOD(SSL_clear_mode, "(J" REF_SSL "J)J"),
11674 CONSCRYPT_NATIVE_METHOD(SSL_get_mode, "(J" REF_SSL ")J"),
11675 CONSCRYPT_NATIVE_METHOD(SSL_get_options, "(J" REF_SSL ")J"),
11676 CONSCRYPT_NATIVE_METHOD(SSL_get1_session, "(J" REF_SSL ")J"),
11677 };
11678
registerNativeMethods(JNIEnv * env)11679 void NativeCrypto::registerNativeMethods(JNIEnv* env) {
11680 conscrypt::jniutil::jniRegisterNativeMethods(
11681 env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto", sNativeCryptoMethods,
11682 NELEM(sNativeCryptoMethods));
11683 }
11684
11685 /* Local Variables: */
11686 /* mode: c++ */
11687 /* tab-width: 4 */
11688 /* indent-tabs-mode: nil */
11689 /* c-basic-offset: 4 */
11690 /* End: */
11691 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
11692