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 /**
18 * Native glue for Java class org.conscrypt.NativeCrypto
19 */
20
21 #define TO_STRING1(x) #x
22 #define TO_STRING(x) TO_STRING1(x)
23 #ifndef JNI_JARJAR_PREFIX
24 #ifndef CONSCRYPT_NOT_UNBUNDLED
25 #define CONSCRYPT_UNBUNDLED
26 #endif
27 #define JNI_JARJAR_PREFIX
28 #endif
29
30 #define LOG_TAG "NativeCrypto"
31
32 #include <arpa/inet.h>
33 #include <fcntl.h>
34 #include <pthread.h>
35 #include <sys/socket.h>
36 #include <unistd.h>
37
38 #ifdef CONSCRYPT_UNBUNDLED
39 #include <dlfcn.h>
40 #endif
41
42 #include <jni.h>
43
44 #include <openssl/asn1t.h>
45 #include <openssl/dsa.h>
46 #include <openssl/engine.h>
47 #include <openssl/err.h>
48 #include <openssl/evp.h>
49 #include <openssl/rand.h>
50 #include <openssl/rsa.h>
51 #include <openssl/ssl.h>
52 #include <openssl/x509v3.h>
53 #include "crypto/ecdsa/ecs_locl.h"
54
55 #ifndef CONSCRYPT_UNBUNDLED
56 /* If we're compiled unbundled from Android system image, we use the
57 * CompatibilityCloseMonitor
58 */
59 #include "AsynchronousCloseMonitor.h"
60 #endif
61
62 #ifndef CONSCRYPT_UNBUNDLED
63 #include "cutils/log.h"
64 #else
65 #include <android/log.h>
66 #define ALOG(priority, tag, ...) \
67 __android_log_print(ANDROID_##priority, tag, __VA_ARGS__)
68 #define ALOGD(...) \
69 __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
70 #define ALOGE(...) \
71 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
72 #define ALOGV(...) \
73 __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
74 #endif
75
76 #ifndef CONSCRYPT_UNBUNDLED
77 #include "JNIHelp.h"
78 #include "JniConstants.h"
79 #include "JniException.h"
80 #else
81 #define NATIVE_METHOD(className, functionName, signature) \
82 { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
83 #define REGISTER_NATIVE_METHODS(jni_class_name) \
84 RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
85 #endif
86
87 #include "ScopedLocalRef.h"
88 #include "ScopedPrimitiveArray.h"
89 #include "ScopedUtfChars.h"
90 #include "UniquePtr.h"
91 #include "NetFd.h"
92
93 #undef WITH_JNI_TRACE
94 #undef WITH_JNI_TRACE_MD
95 #undef WITH_JNI_TRACE_DATA
96
97 /*
98 * How to use this for debugging with Wireshark:
99 *
100 * 1. Pull lines from logcat to a file that looks like (without quotes):
101 * "RSA Session-ID:... Master-Key:..." <CR>
102 * "RSA Session-ID:... Master-Key:..." <CR>
103 * <etc>
104 * 2. Start Wireshark
105 * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in
106 * the file you put the lines in above.
107 * 4. Follow the stream that corresponds to the desired "Session-ID" in
108 * the Server Hello.
109 */
110 #undef WITH_JNI_TRACE_KEYS
111
112 #ifdef WITH_JNI_TRACE
113 #define JNI_TRACE(...) \
114 ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__))
115 #else
116 #define JNI_TRACE(...) ((void)0)
117 #endif
118 #ifdef WITH_JNI_TRACE_MD
119 #define JNI_TRACE_MD(...) \
120 ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__));
121 #else
122 #define JNI_TRACE_MD(...) ((void)0)
123 #endif
124 // don't overwhelm logcat
125 #define WITH_JNI_TRACE_DATA_CHUNK_SIZE 512
126
127 static JavaVM* gJavaVM;
128 static jclass cryptoUpcallsClass;
129 static jclass openSslInputStreamClass;
130 static jclass openSslNativeReferenceClass;
131
132 static jclass byteArrayClass;
133 static jclass calendarClass;
134 static jclass objectClass;
135 static jclass objectArrayClass;
136 static jclass integerClass;
137 static jclass inputStreamClass;
138 static jclass outputStreamClass;
139 static jclass stringClass;
140
141 static jfieldID openSslNativeReference_context;
142
143 static jmethodID calendar_setMethod;
144 static jmethodID inputStream_readMethod;
145 static jmethodID integer_valueOfMethod;
146 static jmethodID openSslInputStream_readLineMethod;
147 static jmethodID outputStream_writeMethod;
148 static jmethodID outputStream_flushMethod;
149
150 struct OPENSSL_Delete {
operator ()OPENSSL_Delete151 void operator()(void* p) const {
152 OPENSSL_free(p);
153 }
154 };
155 typedef UniquePtr<unsigned char, OPENSSL_Delete> Unique_OPENSSL_str;
156
157 struct BIO_Delete {
operator ()BIO_Delete158 void operator()(BIO* p) const {
159 BIO_free_all(p);
160 }
161 };
162 typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
163
164 struct BIGNUM_Delete {
operator ()BIGNUM_Delete165 void operator()(BIGNUM* p) const {
166 BN_free(p);
167 }
168 };
169 typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
170
171 struct ASN1_INTEGER_Delete {
operator ()ASN1_INTEGER_Delete172 void operator()(ASN1_INTEGER* p) const {
173 ASN1_INTEGER_free(p);
174 }
175 };
176 typedef UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> Unique_ASN1_INTEGER;
177
178 struct DH_Delete {
operator ()DH_Delete179 void operator()(DH* p) const {
180 DH_free(p);
181 }
182 };
183 typedef UniquePtr<DH, DH_Delete> Unique_DH;
184
185 struct DSA_Delete {
operator ()DSA_Delete186 void operator()(DSA* p) const {
187 DSA_free(p);
188 }
189 };
190 typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
191
192 struct EC_GROUP_Delete {
operator ()EC_GROUP_Delete193 void operator()(EC_GROUP* p) const {
194 EC_GROUP_clear_free(p);
195 }
196 };
197 typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
198
199 struct EC_POINT_Delete {
operator ()EC_POINT_Delete200 void operator()(EC_POINT* p) const {
201 EC_POINT_clear_free(p);
202 }
203 };
204 typedef UniquePtr<EC_POINT, EC_POINT_Delete> Unique_EC_POINT;
205
206 struct EC_KEY_Delete {
operator ()EC_KEY_Delete207 void operator()(EC_KEY* p) const {
208 EC_KEY_free(p);
209 }
210 };
211 typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
212
213 struct EVP_MD_CTX_Delete {
operator ()EVP_MD_CTX_Delete214 void operator()(EVP_MD_CTX* p) const {
215 EVP_MD_CTX_destroy(p);
216 }
217 };
218 typedef UniquePtr<EVP_MD_CTX, EVP_MD_CTX_Delete> Unique_EVP_MD_CTX;
219
220 struct EVP_CIPHER_CTX_Delete {
operator ()EVP_CIPHER_CTX_Delete221 void operator()(EVP_CIPHER_CTX* p) const {
222 EVP_CIPHER_CTX_free(p);
223 }
224 };
225 typedef UniquePtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Delete> Unique_EVP_CIPHER_CTX;
226
227 struct EVP_PKEY_Delete {
operator ()EVP_PKEY_Delete228 void operator()(EVP_PKEY* p) const {
229 EVP_PKEY_free(p);
230 }
231 };
232 typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
233
234 struct PKCS8_PRIV_KEY_INFO_Delete {
operator ()PKCS8_PRIV_KEY_INFO_Delete235 void operator()(PKCS8_PRIV_KEY_INFO* p) const {
236 PKCS8_PRIV_KEY_INFO_free(p);
237 }
238 };
239 typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
240
241 struct RSA_Delete {
operator ()RSA_Delete242 void operator()(RSA* p) const {
243 RSA_free(p);
244 }
245 };
246 typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
247
248 struct ASN1_BIT_STRING_Delete {
operator ()ASN1_BIT_STRING_Delete249 void operator()(ASN1_BIT_STRING* p) const {
250 ASN1_BIT_STRING_free(p);
251 }
252 };
253 typedef UniquePtr<ASN1_BIT_STRING, ASN1_BIT_STRING_Delete> Unique_ASN1_BIT_STRING;
254
255 struct ASN1_OBJECT_Delete {
operator ()ASN1_OBJECT_Delete256 void operator()(ASN1_OBJECT* p) const {
257 ASN1_OBJECT_free(p);
258 }
259 };
260 typedef UniquePtr<ASN1_OBJECT, ASN1_OBJECT_Delete> Unique_ASN1_OBJECT;
261
262 struct ASN1_GENERALIZEDTIME_Delete {
operator ()ASN1_GENERALIZEDTIME_Delete263 void operator()(ASN1_GENERALIZEDTIME* p) const {
264 ASN1_GENERALIZEDTIME_free(p);
265 }
266 };
267 typedef UniquePtr<ASN1_GENERALIZEDTIME, ASN1_GENERALIZEDTIME_Delete> Unique_ASN1_GENERALIZEDTIME;
268
269 struct SSL_Delete {
operator ()SSL_Delete270 void operator()(SSL* p) const {
271 SSL_free(p);
272 }
273 };
274 typedef UniquePtr<SSL, SSL_Delete> Unique_SSL;
275
276 struct SSL_CTX_Delete {
operator ()SSL_CTX_Delete277 void operator()(SSL_CTX* p) const {
278 SSL_CTX_free(p);
279 }
280 };
281 typedef UniquePtr<SSL_CTX, SSL_CTX_Delete> Unique_SSL_CTX;
282
283 struct X509_Delete {
operator ()X509_Delete284 void operator()(X509* p) const {
285 X509_free(p);
286 }
287 };
288 typedef UniquePtr<X509, X509_Delete> Unique_X509;
289
290 struct X509_NAME_Delete {
operator ()X509_NAME_Delete291 void operator()(X509_NAME* p) const {
292 X509_NAME_free(p);
293 }
294 };
295 typedef UniquePtr<X509_NAME, X509_NAME_Delete> Unique_X509_NAME;
296
297 struct PKCS7_Delete {
operator ()PKCS7_Delete298 void operator()(PKCS7* p) const {
299 PKCS7_free(p);
300 }
301 };
302 typedef UniquePtr<PKCS7, PKCS7_Delete> Unique_PKCS7;
303
304 struct sk_SSL_CIPHER_Delete {
operator ()sk_SSL_CIPHER_Delete305 void operator()(STACK_OF(SSL_CIPHER)* p) const {
306 // We don't own SSL_CIPHER references, so no need for pop_free
307 sk_SSL_CIPHER_free(p);
308 }
309 };
310 typedef UniquePtr<STACK_OF(SSL_CIPHER), sk_SSL_CIPHER_Delete> Unique_sk_SSL_CIPHER;
311
312 struct sk_X509_Delete {
operator ()sk_X509_Delete313 void operator()(STACK_OF(X509)* p) const {
314 sk_X509_pop_free(p, X509_free);
315 }
316 };
317 typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509;
318
319 struct sk_X509_NAME_Delete {
operator ()sk_X509_NAME_Delete320 void operator()(STACK_OF(X509_NAME)* p) const {
321 sk_X509_NAME_pop_free(p, X509_NAME_free);
322 }
323 };
324 typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME;
325
326 struct sk_ASN1_OBJECT_Delete {
operator ()sk_ASN1_OBJECT_Delete327 void operator()(STACK_OF(ASN1_OBJECT)* p) const {
328 sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free);
329 }
330 };
331 typedef UniquePtr<STACK_OF(ASN1_OBJECT), sk_ASN1_OBJECT_Delete> Unique_sk_ASN1_OBJECT;
332
333 struct sk_GENERAL_NAME_Delete {
operator ()sk_GENERAL_NAME_Delete334 void operator()(STACK_OF(GENERAL_NAME)* p) const {
335 sk_GENERAL_NAME_pop_free(p, GENERAL_NAME_free);
336 }
337 };
338 typedef UniquePtr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_Delete> Unique_sk_GENERAL_NAME;
339
340 /**
341 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
342 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
343 * without triggering a warning by not using the result of release().
344 */
345 #define OWNERSHIP_TRANSFERRED(obj) \
346 do { typeof (obj.release()) _dummy __attribute__((unused)) = obj.release(); } while(0)
347
348 /**
349 * Frees the SSL error state.
350 *
351 * OpenSSL keeps an "error stack" per thread, and given that this code
352 * can be called from arbitrary threads that we don't keep track of,
353 * we err on the side of freeing the error state promptly (instead of,
354 * say, at thread death).
355 */
freeOpenSslErrorState(void)356 static void freeOpenSslErrorState(void) {
357 ERR_clear_error();
358 ERR_remove_state(0);
359 }
360
361 /**
362 * Manages the freeing of the OpenSSL error stack. This allows you to
363 * instantiate this object during an SSL call that may fail and not worry
364 * about manually calling freeOpenSslErrorState() later.
365 *
366 * As an optimization, you can also call .release() for passing as an
367 * argument to things that free the error stack state as a side-effect.
368 */
369 class OpenSslError {
370 public:
OpenSslError()371 OpenSslError() : sslError_(SSL_ERROR_NONE), released_(false) {
372 }
373
OpenSslError(SSL * ssl,int returnCode)374 OpenSslError(SSL* ssl, int returnCode) : sslError_(SSL_ERROR_NONE), released_(false) {
375 reset(ssl, returnCode);
376 }
377
~OpenSslError()378 ~OpenSslError() {
379 if (!released_ && sslError_ != SSL_ERROR_NONE) {
380 freeOpenSslErrorState();
381 }
382 }
383
get() const384 int get() const {
385 return sslError_;
386 }
387
reset(SSL * ssl,int returnCode)388 void reset(SSL* ssl, int returnCode) {
389 if (returnCode <= 0) {
390 sslError_ = SSL_get_error(ssl, returnCode);
391 } else {
392 sslError_ = SSL_ERROR_NONE;
393 }
394 }
395
release()396 int release() {
397 released_ = true;
398 return sslError_;
399 }
400
401 private:
402 int sslError_;
403 bool released_;
404 };
405
406 /**
407 * Throws a OutOfMemoryError with the given string as a message.
408 */
jniThrowOutOfMemory(JNIEnv * env,const char * message)409 static void jniThrowOutOfMemory(JNIEnv* env, const char* message) {
410 jniThrowException(env, "java/lang/OutOfMemoryError", message);
411 }
412
413 /**
414 * Throws a BadPaddingException with the given string as a message.
415 */
throwBadPaddingException(JNIEnv * env,const char * message)416 static void throwBadPaddingException(JNIEnv* env, const char* message) {
417 JNI_TRACE("throwBadPaddingException %s", message);
418 jniThrowException(env, "javax/crypto/BadPaddingException", message);
419 }
420
421 /**
422 * Throws a SignatureException with the given string as a message.
423 */
throwSignatureException(JNIEnv * env,const char * message)424 static void throwSignatureException(JNIEnv* env, const char* message) {
425 JNI_TRACE("throwSignatureException %s", message);
426 jniThrowException(env, "java/security/SignatureException", message);
427 }
428
429 /**
430 * Throws a InvalidKeyException with the given string as a message.
431 */
throwInvalidKeyException(JNIEnv * env,const char * message)432 static void throwInvalidKeyException(JNIEnv* env, const char* message) {
433 JNI_TRACE("throwInvalidKeyException %s", message);
434 jniThrowException(env, "java/security/InvalidKeyException", message);
435 }
436
437 /**
438 * Throws a SignatureException with the given string as a message.
439 */
throwIllegalBlockSizeException(JNIEnv * env,const char * message)440 static void throwIllegalBlockSizeException(JNIEnv* env, const char* message) {
441 JNI_TRACE("throwIllegalBlockSizeException %s", message);
442 jniThrowException(env, "javax/crypto/IllegalBlockSizeException", message);
443 }
444
445 /**
446 * Throws a NoSuchAlgorithmException with the given string as a message.
447 */
throwNoSuchAlgorithmException(JNIEnv * env,const char * message)448 static void throwNoSuchAlgorithmException(JNIEnv* env, const char* message) {
449 JNI_TRACE("throwUnknownAlgorithmException %s", message);
450 jniThrowException(env, "java/security/NoSuchAlgorithmException", message);
451 }
452
throwForAsn1Error(JNIEnv * env,int reason,const char * message)453 static void throwForAsn1Error(JNIEnv* env, int reason, const char *message) {
454 switch (reason) {
455 case ASN1_R_UNABLE_TO_DECODE_RSA_KEY:
456 case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY:
457 case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:
458 case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:
459 case ASN1_R_WRONG_PUBLIC_KEY_TYPE:
460 throwInvalidKeyException(env, message);
461 break;
462 case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
463 throwNoSuchAlgorithmException(env, message);
464 break;
465 default:
466 jniThrowRuntimeException(env, message);
467 break;
468 }
469 }
470
throwForEvpError(JNIEnv * env,int reason,const char * message)471 static void throwForEvpError(JNIEnv* env, int reason, const char *message) {
472 switch (reason) {
473 case EVP_R_BAD_DECRYPT:
474 throwBadPaddingException(env, message);
475 break;
476 case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
477 case EVP_R_WRONG_FINAL_BLOCK_LENGTH:
478 throwIllegalBlockSizeException(env, message);
479 break;
480 case EVP_R_BAD_KEY_LENGTH:
481 case EVP_R_BN_DECODE_ERROR:
482 case EVP_R_BN_PUBKEY_ERROR:
483 case EVP_R_INVALID_KEY_LENGTH:
484 case EVP_R_MISSING_PARAMETERS:
485 case EVP_R_UNSUPPORTED_KEY_SIZE:
486 case EVP_R_UNSUPPORTED_KEYLENGTH:
487 throwInvalidKeyException(env, message);
488 break;
489 case EVP_R_WRONG_PUBLIC_KEY_TYPE:
490 throwSignatureException(env, message);
491 break;
492 case EVP_R_UNSUPPORTED_ALGORITHM:
493 throwNoSuchAlgorithmException(env, message);
494 break;
495 default:
496 jniThrowRuntimeException(env, message);
497 break;
498 }
499 }
500
throwForRsaError(JNIEnv * env,int reason,const char * message)501 static void throwForRsaError(JNIEnv* env, int reason, const char *message) {
502 switch (reason) {
503 case RSA_R_BLOCK_TYPE_IS_NOT_01:
504 case RSA_R_BLOCK_TYPE_IS_NOT_02:
505 case RSA_R_PKCS_DECODING_ERROR:
506 throwBadPaddingException(env, message);
507 break;
508 case RSA_R_ALGORITHM_MISMATCH:
509 case RSA_R_BAD_SIGNATURE:
510 case RSA_R_DATA_GREATER_THAN_MOD_LEN:
511 case RSA_R_DATA_TOO_LARGE_FOR_MODULUS:
512 case RSA_R_INVALID_MESSAGE_LENGTH:
513 case RSA_R_WRONG_SIGNATURE_LENGTH:
514 throwSignatureException(env, message);
515 break;
516 case RSA_R_UNKNOWN_ALGORITHM_TYPE:
517 throwNoSuchAlgorithmException(env, message);
518 break;
519 case RSA_R_MODULUS_TOO_LARGE:
520 case RSA_R_NO_PUBLIC_EXPONENT:
521 throwInvalidKeyException(env, message);
522 break;
523 default:
524 jniThrowRuntimeException(env, message);
525 break;
526 }
527 }
528
throwForX509Error(JNIEnv * env,int reason,const char * message)529 static void throwForX509Error(JNIEnv* env, int reason, const char *message) {
530 switch (reason) {
531 case X509_R_UNSUPPORTED_ALGORITHM:
532 throwNoSuchAlgorithmException(env, message);
533 break;
534 default:
535 jniThrowRuntimeException(env, message);
536 break;
537 }
538 }
539
540 /*
541 * Checks this thread's OpenSSL error queue and throws a RuntimeException if
542 * necessary.
543 *
544 * @return true if an exception was thrown, false if not.
545 */
throwExceptionIfNecessary(JNIEnv * env,const char * location)546 static bool throwExceptionIfNecessary(JNIEnv* env, const char* location __attribute__ ((unused))) {
547 const char* file;
548 int line;
549 const char* data;
550 int flags;
551 unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags);
552 int result = false;
553
554 if (error != 0) {
555 char message[256];
556 ERR_error_string_n(error, message, sizeof(message));
557 int library = ERR_GET_LIB(error);
558 int reason = ERR_GET_REASON(error);
559 JNI_TRACE("OpenSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s",
560 location, error, library, reason, file, line, message,
561 (flags & ERR_TXT_STRING) ? data : "(no data)");
562 switch (library) {
563 case ERR_LIB_RSA:
564 throwForRsaError(env, reason, message);
565 break;
566 case ERR_LIB_ASN1:
567 throwForAsn1Error(env, reason, message);
568 break;
569 case ERR_LIB_EVP:
570 throwForEvpError(env, reason, message);
571 break;
572 case ERR_LIB_X509:
573 throwForX509Error(env, reason, message);
574 break;
575 case ERR_LIB_DSA:
576 throwInvalidKeyException(env, message);
577 break;
578 default:
579 jniThrowRuntimeException(env, message);
580 break;
581 }
582 result = true;
583 }
584
585 freeOpenSslErrorState();
586 return result;
587 }
588
589 /**
590 * Throws an SocketTimeoutException with the given string as a message.
591 */
throwSocketTimeoutException(JNIEnv * env,const char * message)592 static void throwSocketTimeoutException(JNIEnv* env, const char* message) {
593 JNI_TRACE("throwSocketTimeoutException %s", message);
594 jniThrowException(env, "java/net/SocketTimeoutException", message);
595 }
596
597 /**
598 * Throws a javax.net.ssl.SSLException with the given string as a message.
599 */
throwSSLHandshakeExceptionStr(JNIEnv * env,const char * message)600 static void throwSSLHandshakeExceptionStr(JNIEnv* env, const char* message) {
601 JNI_TRACE("throwSSLExceptionStr %s", message);
602 jniThrowException(env, "javax/net/ssl/SSLHandshakeException", message);
603 }
604
605 /**
606 * Throws a javax.net.ssl.SSLException with the given string as a message.
607 */
throwSSLExceptionStr(JNIEnv * env,const char * message)608 static void throwSSLExceptionStr(JNIEnv* env, const char* message) {
609 JNI_TRACE("throwSSLExceptionStr %s", message);
610 jniThrowException(env, "javax/net/ssl/SSLException", message);
611 }
612
613 /**
614 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message.
615 */
throwSSLProtocolExceptionStr(JNIEnv * env,const char * message)616 static void throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) {
617 JNI_TRACE("throwSSLProtocolExceptionStr %s", message);
618 jniThrowException(env, "javax/net/ssl/SSLProtocolException", message);
619 }
620
621 /**
622 * Throws an SSLException with a message constructed from the current
623 * SSL errors. This will also log the errors.
624 *
625 * @param env the JNI environment
626 * @param ssl the possibly NULL SSL
627 * @param sslErrorCode error code returned from SSL_get_error() or
628 * SSL_ERROR_NONE to probe with ERR_get_error
629 * @param message null-ok; general error message
630 */
throwSSLExceptionWithSslErrors(JNIEnv * env,SSL * ssl,int sslErrorCode,const char * message,void (* actualThrow)(JNIEnv *,const char *)=throwSSLExceptionStr)631 static void throwSSLExceptionWithSslErrors(JNIEnv* env, SSL* ssl, int sslErrorCode,
632 const char* message, void (*actualThrow)(JNIEnv*, const char*) = throwSSLExceptionStr) {
633
634 if (message == NULL) {
635 message = "SSL error";
636 }
637
638 // First consult the SSL error code for the general message.
639 const char* sslErrorStr = NULL;
640 switch (sslErrorCode) {
641 case SSL_ERROR_NONE:
642 if (ERR_peek_error() == 0) {
643 sslErrorStr = "OK";
644 } else {
645 sslErrorStr = "";
646 }
647 break;
648 case SSL_ERROR_SSL:
649 sslErrorStr = "Failure in SSL library, usually a protocol error";
650 break;
651 case SSL_ERROR_WANT_READ:
652 sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this.";
653 break;
654 case SSL_ERROR_WANT_WRITE:
655 sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this.";
656 break;
657 case SSL_ERROR_WANT_X509_LOOKUP:
658 sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this.";
659 break;
660 case SSL_ERROR_SYSCALL:
661 sslErrorStr = "I/O error during system call";
662 break;
663 case SSL_ERROR_ZERO_RETURN:
664 sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this.";
665 break;
666 case SSL_ERROR_WANT_CONNECT:
667 sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this.";
668 break;
669 case SSL_ERROR_WANT_ACCEPT:
670 sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this.";
671 break;
672 default:
673 sslErrorStr = "Unknown SSL error";
674 }
675
676 // Prepend either our explicit message or a default one.
677 char* str;
678 if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) {
679 // problem with asprintf, just throw argument message, log everything
680 actualThrow(env, message);
681 ALOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr);
682 freeOpenSslErrorState();
683 return;
684 }
685
686 char* allocStr = str;
687
688 // For protocol errors, SSL might have more information.
689 if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) {
690 // Append each error as an additional line to the message.
691 for (;;) {
692 char errStr[256];
693 const char* file;
694 int line;
695 const char* data;
696 int flags;
697 unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags);
698 if (err == 0) {
699 break;
700 }
701
702 ERR_error_string_n(err, errStr, sizeof(errStr));
703
704 int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
705 (allocStr == NULL) ? "" : allocStr,
706 errStr,
707 file,
708 line,
709 (flags & ERR_TXT_STRING) ? data : "(no data)",
710 flags);
711
712 if (ret < 0) {
713 break;
714 }
715
716 free(allocStr);
717 allocStr = str;
718 }
719 // For errors during system calls, errno might be our friend.
720 } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
721 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
722 free(allocStr);
723 allocStr = str;
724 }
725 // If the error code is invalid, print it.
726 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
727 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
728 free(allocStr);
729 allocStr = str;
730 }
731 }
732
733 if (sslErrorCode == SSL_ERROR_SSL) {
734 throwSSLProtocolExceptionStr(env, allocStr);
735 } else {
736 actualThrow(env, allocStr);
737 }
738
739 ALOGV("%s", allocStr);
740 free(allocStr);
741 freeOpenSslErrorState();
742 }
743
744 /**
745 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
746 * If this function returns NULL and <code>throwIfNull</code> is
747 * passed as <code>true</code>, then this function will call
748 * <code>throwSSLExceptionStr</code> before returning, so in this case of
749 * NULL, a caller of this function should simply return and allow JNI
750 * to do its thing.
751 *
752 * @param env the JNI environment
753 * @param ssl_address; the ssl_address pointer as an integer
754 * @param throwIfNull whether to throw if the SSL pointer is NULL
755 * @returns the pointer, which may be NULL
756 */
to_SSL_CTX(JNIEnv * env,jlong ssl_ctx_address,bool throwIfNull)757 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
758 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
759 if ((ssl_ctx == NULL) && throwIfNull) {
760 JNI_TRACE("ssl_ctx == null");
761 jniThrowNullPointerException(env, "ssl_ctx == null");
762 }
763 return ssl_ctx;
764 }
765
to_SSL(JNIEnv * env,jlong ssl_address,bool throwIfNull)766 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
767 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
768 if ((ssl == NULL) && throwIfNull) {
769 JNI_TRACE("ssl == null");
770 jniThrowNullPointerException(env, "ssl == null");
771 }
772 return ssl;
773 }
774
to_SSL_SESSION(JNIEnv * env,jlong ssl_session_address,bool throwIfNull)775 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
776 SSL_SESSION* ssl_session
777 = reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
778 if ((ssl_session == NULL) && throwIfNull) {
779 JNI_TRACE("ssl_session == null");
780 jniThrowNullPointerException(env, "ssl_session == null");
781 }
782 return ssl_session;
783 }
784
to_SSL_CIPHER(JNIEnv * env,jlong ssl_cipher_address,bool throwIfNull)785 static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
786 SSL_CIPHER* ssl_cipher
787 = reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
788 if ((ssl_cipher == NULL) && throwIfNull) {
789 JNI_TRACE("ssl_cipher == null");
790 jniThrowNullPointerException(env, "ssl_cipher == null");
791 }
792 return ssl_cipher;
793 }
794
795 template<typename T>
fromContextObject(JNIEnv * env,jobject contextObject)796 static T* fromContextObject(JNIEnv* env, jobject contextObject) {
797 T* ref = reinterpret_cast<T*>(env->GetLongField(contextObject, openSslNativeReference_context));
798 if (ref == NULL) {
799 JNI_TRACE("ctx == null");
800 jniThrowNullPointerException(env, "ctx == null");
801 }
802 return ref;
803 }
804
805 /**
806 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
807 * allocate the BIGNUM if *dest == NULL. Returns true on success. If the
808 * return value is false, there is a pending exception.
809 */
arrayToBignum(JNIEnv * env,jbyteArray source,BIGNUM ** dest)810 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
811 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
812 if (dest == NULL) {
813 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
814 jniThrowNullPointerException(env, "dest == null");
815 return false;
816 }
817 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
818
819 ScopedByteArrayRO sourceBytes(env, source);
820 if (sourceBytes.get() == NULL) {
821 JNI_TRACE("arrayToBignum(%p, %p) => NULL", source, dest);
822 return false;
823 }
824 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
825 size_t tmpSize = sourceBytes.size();
826
827 /* if the array is empty, it is zero. */
828 if (tmpSize == 0) {
829 if (*dest == NULL) {
830 *dest = BN_new();
831 }
832 BN_zero(*dest);
833 return true;
834 }
835
836 UniquePtr<unsigned char[]> twosComplement;
837 bool negative = (tmp[0] & 0x80) != 0;
838 if (negative) {
839 // Need to convert to two's complement.
840 twosComplement.reset(new unsigned char[tmpSize]);
841 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
842 memcpy(twosBytes, tmp, tmpSize);
843 tmp = twosBytes;
844
845 bool carry = true;
846 for (ssize_t i = tmpSize - 1; i >= 0; i--) {
847 twosBytes[i] ^= 0xFF;
848 if (carry) {
849 carry = (++twosBytes[i]) == 0;
850 }
851 }
852 }
853 BIGNUM *ret = BN_bin2bn(tmp, tmpSize, *dest);
854 if (ret == NULL) {
855 jniThrowRuntimeException(env, "Conversion to BIGNUM failed");
856 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
857 return false;
858 }
859 BN_set_negative(ret, negative ? 1 : 0);
860
861 *dest = ret;
862 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
863 return true;
864 }
865
866 /**
867 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
868 */
bignumToArray(JNIEnv * env,const BIGNUM * source,const char * sourceName)869 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
870 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
871
872 if (source == NULL) {
873 jniThrowNullPointerException(env, sourceName);
874 return NULL;
875 }
876
877 size_t numBytes = BN_num_bytes(source) + 1;
878 jbyteArray javaBytes = env->NewByteArray(numBytes);
879 ScopedByteArrayRW bytes(env, javaBytes);
880 if (bytes.get() == NULL) {
881 JNI_TRACE("bignumToArray(%p, %s) => NULL", source, sourceName);
882 return NULL;
883 }
884
885 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
886 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
887 throwExceptionIfNecessary(env, "bignumToArray");
888 return NULL;
889 }
890
891 // Set the sign and convert to two's complement if necessary for the Java code.
892 if (BN_is_negative(source)) {
893 bool carry = true;
894 for (ssize_t i = numBytes - 1; i >= 0; i--) {
895 tmp[i] ^= 0xFF;
896 if (carry) {
897 carry = (++tmp[i]) == 0;
898 }
899 }
900 *tmp |= 0x80;
901 } else {
902 *tmp = 0x00;
903 }
904
905 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
906 return javaBytes;
907 }
908
909 /**
910 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
911 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
912 * from the OpenSSL ASN.1 API.
913 */
914 template<typename T, int (*i2d_func)(T*, unsigned char**)>
ASN1ToByteArray(JNIEnv * env,T * obj)915 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj) {
916 if (obj == NULL) {
917 jniThrowNullPointerException(env, "ASN1 input == null");
918 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
919 return NULL;
920 }
921
922 int derLen = i2d_func(obj, NULL);
923 if (derLen < 0) {
924 throwExceptionIfNecessary(env, "ASN1ToByteArray");
925 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
926 return NULL;
927 }
928
929 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
930 if (byteArray.get() == NULL) {
931 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
932 return NULL;
933 }
934
935 ScopedByteArrayRW bytes(env, byteArray.get());
936 if (bytes.get() == NULL) {
937 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
938 return NULL;
939 }
940
941 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
942 int ret = i2d_func(obj, &p);
943 if (ret < 0) {
944 throwExceptionIfNecessary(env, "ASN1ToByteArray");
945 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
946 return NULL;
947 }
948
949 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
950 return byteArray.release();
951 }
952
953 template<typename T, T* (*d2i_func)(T**, const unsigned char**, long)>
ByteArrayToASN1(JNIEnv * env,jbyteArray byteArray)954 T* ByteArrayToASN1(JNIEnv* env, jbyteArray byteArray) {
955 ScopedByteArrayRO bytes(env, byteArray);
956 if (bytes.get() == NULL) {
957 JNI_TRACE("ByteArrayToASN1(%p) => using byte array failed", byteArray);
958 return 0;
959 }
960
961 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
962 return d2i_func(NULL, &tmp, bytes.size());
963 }
964
965 /**
966 * Converts ASN.1 BIT STRING to a jbooleanArray.
967 */
ASN1BitStringToBooleanArray(JNIEnv * env,ASN1_BIT_STRING * bitStr)968 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, ASN1_BIT_STRING* bitStr) {
969 int size = bitStr->length * 8;
970 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
971 size -= bitStr->flags & 0x07;
972 }
973
974 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
975 if (bitsRef.get() == NULL) {
976 return NULL;
977 }
978
979 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
980 for (int i = 0; i < static_cast<int>(bitsArray.size()); i++) {
981 bitsArray[i] = ASN1_BIT_STRING_get_bit(bitStr, i);
982 }
983
984 return bitsRef.release();
985 }
986
987 /**
988 * Safely clear SSL sessions and throw an error if there was something already
989 * in the error stack.
990 */
safeSslClear(SSL * ssl)991 static void safeSslClear(SSL* ssl) {
992 if (SSL_clear(ssl) != 1) {
993 freeOpenSslErrorState();
994 }
995 }
996
997 /**
998 * To avoid the round-trip to ASN.1 and back in X509_dup, we just up the reference count.
999 */
X509_dup_nocopy(X509 * x509)1000 static X509* X509_dup_nocopy(X509* x509) {
1001 if (x509 == NULL) {
1002 return NULL;
1003 }
1004 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
1005 return x509;
1006 }
1007
1008 /*
1009 * Sets the read and write BIO for an SSL connection and removes it when it goes out of scope.
1010 * We hang on to BIO with a JNI GlobalRef and we want to remove them as soon as possible.
1011 */
1012 class ScopedSslBio {
1013 public:
ScopedSslBio(SSL * ssl,BIO * rbio,BIO * wbio)1014 ScopedSslBio(SSL *ssl, BIO* rbio, BIO* wbio) : ssl_(ssl) {
1015 SSL_set_bio(ssl_, rbio, wbio);
1016 CRYPTO_add(&rbio->references,1,CRYPTO_LOCK_BIO);
1017 CRYPTO_add(&wbio->references,1,CRYPTO_LOCK_BIO);
1018 }
1019
~ScopedSslBio()1020 ~ScopedSslBio() {
1021 SSL_set_bio(ssl_, NULL, NULL);
1022 }
1023
1024 private:
1025 SSL* const ssl_;
1026 };
1027
1028 /**
1029 * Obtains the current thread's JNIEnv
1030 */
getJNIEnv()1031 static JNIEnv* getJNIEnv() {
1032 JNIEnv* env;
1033 if (gJavaVM->AttachCurrentThread(&env, NULL) < 0) {
1034 ALOGE("Could not attach JavaVM to find current JNIEnv");
1035 return NULL;
1036 }
1037 return env;
1038 }
1039
1040 /**
1041 * BIO for InputStream
1042 */
1043 class BIO_Stream {
1044 public:
BIO_Stream(jobject stream)1045 BIO_Stream(jobject stream) :
1046 mEof(false) {
1047 JNIEnv* env = getJNIEnv();
1048 mStream = env->NewGlobalRef(stream);
1049 }
1050
~BIO_Stream()1051 ~BIO_Stream() {
1052 JNIEnv* env = getJNIEnv();
1053
1054 env->DeleteGlobalRef(mStream);
1055 }
1056
isEof() const1057 bool isEof() const {
1058 JNI_TRACE("isEof? %s", mEof ? "yes" : "no");
1059 return mEof;
1060 }
1061
flush()1062 int flush() {
1063 JNIEnv* env = getJNIEnv();
1064 if (env == NULL) {
1065 return -1;
1066 }
1067
1068 if (env->ExceptionCheck()) {
1069 JNI_TRACE("BIO_Stream::flush called with pending exception");
1070 return -1;
1071 }
1072
1073 env->CallVoidMethod(mStream, outputStream_flushMethod);
1074 if (env->ExceptionCheck()) {
1075 return -1;
1076 }
1077
1078 return 1;
1079 }
1080
1081 protected:
getStream()1082 jobject getStream() {
1083 return mStream;
1084 }
1085
setEof(bool eof)1086 void setEof(bool eof) {
1087 mEof = eof;
1088 }
1089
1090 private:
1091 jobject mStream;
1092 bool mEof;
1093 };
1094
1095 class BIO_InputStream : public BIO_Stream {
1096 public:
BIO_InputStream(jobject stream)1097 BIO_InputStream(jobject stream) :
1098 BIO_Stream(stream) {
1099 }
1100
read(char * buf,int len)1101 int read(char *buf, int len) {
1102 return read_internal(buf, len, inputStream_readMethod);
1103 }
1104
gets(char * buf,int len)1105 int gets(char *buf, int len) {
1106 if (len > PEM_LINE_LENGTH) {
1107 len = PEM_LINE_LENGTH;
1108 }
1109
1110 int read = read_internal(buf, len - 1, openSslInputStream_readLineMethod);
1111 buf[read] = '\0';
1112 JNI_TRACE("BIO::gets \"%s\"", buf);
1113 return read;
1114 }
1115
1116 private:
read_internal(char * buf,int len,jmethodID method)1117 int read_internal(char *buf, int len, jmethodID method) {
1118 JNIEnv* env = getJNIEnv();
1119 if (env == NULL) {
1120 JNI_TRACE("BIO_InputStream::read could not get JNIEnv");
1121 return -1;
1122 }
1123
1124 if (env->ExceptionCheck()) {
1125 JNI_TRACE("BIO_InputStream::read called with pending exception");
1126 return -1;
1127 }
1128
1129 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1130 if (javaBytes.get() == NULL) {
1131 JNI_TRACE("BIO_InputStream::read failed call to NewByteArray");
1132 return -1;
1133 }
1134
1135 jint read = env->CallIntMethod(getStream(), method, javaBytes.get());
1136 if (env->ExceptionCheck()) {
1137 JNI_TRACE("BIO_InputStream::read failed call to InputStream#read");
1138 return -1;
1139 }
1140
1141 /* Java uses -1 to indicate EOF condition. */
1142 if (read == -1) {
1143 setEof(true);
1144 read = 0;
1145 } else if (read > 0) {
1146 env->GetByteArrayRegion(javaBytes.get(), 0, read, reinterpret_cast<jbyte*>(buf));
1147 }
1148
1149 return read;
1150 }
1151
1152 public:
1153 /** Length of PEM-encoded line (64) plus CR plus NULL */
1154 static const int PEM_LINE_LENGTH = 66;
1155 };
1156
1157 class BIO_OutputStream : public BIO_Stream {
1158 public:
BIO_OutputStream(jobject stream)1159 BIO_OutputStream(jobject stream) :
1160 BIO_Stream(stream) {
1161 }
1162
write(const char * buf,int len)1163 int write(const char *buf, int len) {
1164 JNIEnv* env = getJNIEnv();
1165 if (env == NULL) {
1166 JNI_TRACE("BIO_OutputStream::write => could not get JNIEnv");
1167 return -1;
1168 }
1169
1170 if (env->ExceptionCheck()) {
1171 JNI_TRACE("BIO_OutputStream::write => called with pending exception");
1172 return -1;
1173 }
1174
1175 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1176 if (javaBytes.get() == NULL) {
1177 JNI_TRACE("BIO_OutputStream::write => failed call to NewByteArray");
1178 return -1;
1179 }
1180
1181 env->SetByteArrayRegion(javaBytes.get(), 0, len, reinterpret_cast<const jbyte*>(buf));
1182
1183 env->CallVoidMethod(getStream(), outputStream_writeMethod, javaBytes.get());
1184 if (env->ExceptionCheck()) {
1185 JNI_TRACE("BIO_OutputStream::write => failed call to OutputStream#write");
1186 return -1;
1187 }
1188
1189 return len;
1190 }
1191 };
1192
bio_stream_create(BIO * b)1193 static int bio_stream_create(BIO *b) {
1194 b->init = 1;
1195 b->num = 0;
1196 b->ptr = NULL;
1197 b->flags = 0;
1198 return 1;
1199 }
1200
bio_stream_destroy(BIO * b)1201 static int bio_stream_destroy(BIO *b) {
1202 if (b == NULL) {
1203 return 0;
1204 }
1205
1206 if (b->ptr != NULL) {
1207 delete static_cast<BIO_Stream*>(b->ptr);
1208 b->ptr = NULL;
1209 }
1210
1211 b->init = 0;
1212 b->flags = 0;
1213 return 1;
1214 }
1215
bio_stream_read(BIO * b,char * buf,int len)1216 static int bio_stream_read(BIO *b, char *buf, int len) {
1217 BIO_clear_retry_flags(b);
1218 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
1219 int ret = stream->read(buf, len);
1220 if (ret == 0) {
1221 // EOF is indicated by -1 with a BIO flag.
1222 BIO_set_retry_read(b);
1223 return -1;
1224 }
1225 return ret;
1226 }
1227
bio_stream_write(BIO * b,const char * buf,int len)1228 static int bio_stream_write(BIO *b, const char *buf, int len) {
1229 BIO_clear_retry_flags(b);
1230 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1231 return stream->write(buf, len);
1232 }
1233
bio_stream_puts(BIO * b,const char * buf)1234 static int bio_stream_puts(BIO *b, const char *buf) {
1235 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1236 return stream->write(buf, strlen(buf));
1237 }
1238
bio_stream_gets(BIO * b,char * buf,int len)1239 static int bio_stream_gets(BIO *b, char *buf, int len) {
1240 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
1241 return stream->gets(buf, len);
1242 }
1243
bio_stream_assign(BIO * b,BIO_Stream * stream)1244 static void bio_stream_assign(BIO *b, BIO_Stream* stream) {
1245 b->ptr = static_cast<void*>(stream);
1246 }
1247
bio_stream_ctrl(BIO * b,int cmd,long,void *)1248 static long bio_stream_ctrl(BIO *b, int cmd, long, void *) {
1249 BIO_Stream* stream = static_cast<BIO_Stream*>(b->ptr);
1250
1251 switch (cmd) {
1252 case BIO_CTRL_EOF:
1253 return stream->isEof() ? 1 : 0;
1254 case BIO_CTRL_FLUSH:
1255 return stream->flush();
1256 default:
1257 return 0;
1258 }
1259 }
1260
1261 static BIO_METHOD stream_bio_method = {
1262 ( 100 | 0x0400 ), /* source/sink BIO */
1263 "InputStream/OutputStream BIO",
1264 bio_stream_write, /* bio_write */
1265 bio_stream_read, /* bio_read */
1266 bio_stream_puts, /* bio_puts */
1267 bio_stream_gets, /* bio_gets */
1268 bio_stream_ctrl, /* bio_ctrl */
1269 bio_stream_create, /* bio_create */
1270 bio_stream_destroy, /* bio_free */
1271 NULL, /* no bio_callback_ctrl */
1272 };
1273
rawSignDigestWithPrivateKey(JNIEnv * env,jobject privateKey,const char * message,size_t message_len)1274 static jbyteArray rawSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey,
1275 const char* message, size_t message_len) {
1276 ScopedLocalRef<jbyteArray> messageArray(env, env->NewByteArray(message_len));
1277 if (env->ExceptionCheck()) {
1278 JNI_TRACE("rawSignDigestWithPrivateKey(%p) => threw exception", privateKey);
1279 return NULL;
1280 }
1281
1282 {
1283 ScopedByteArrayRW messageBytes(env, messageArray.get());
1284 if (messageBytes.get() == NULL) {
1285 JNI_TRACE("rawSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
1286 return NULL;
1287 }
1288
1289 memcpy(messageBytes.get(), message, message_len);
1290 }
1291
1292 jmethodID rawSignMethod = env->GetStaticMethodID(cryptoUpcallsClass,
1293 "rawSignDigestWithPrivateKey", "(Ljava/security/PrivateKey;[B)[B");
1294 if (rawSignMethod == NULL) {
1295 ALOGE("Could not find rawSignDigestWithPrivateKey");
1296 return NULL;
1297 }
1298
1299 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
1300 cryptoUpcallsClass, rawSignMethod, privateKey, messageArray.get()));
1301 }
1302
rawCipherWithPrivateKey(JNIEnv * env,jobject privateKey,jboolean encrypt,const char * ciphertext,size_t ciphertext_len)1303 static jbyteArray rawCipherWithPrivateKey(JNIEnv* env, jobject privateKey, jboolean encrypt,
1304 const char* ciphertext, size_t ciphertext_len) {
1305 ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(ciphertext_len));
1306 if (env->ExceptionCheck()) {
1307 JNI_TRACE("rawCipherWithPrivateKey(%p) => threw exception", privateKey);
1308 return NULL;
1309 }
1310
1311 {
1312 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
1313 if (ciphertextBytes.get() == NULL) {
1314 JNI_TRACE("rawCipherWithPrivateKey(%p) => using byte array failed", privateKey);
1315 return NULL;
1316 }
1317
1318 memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
1319 }
1320
1321 jmethodID rawCipherMethod = env->GetStaticMethodID(cryptoUpcallsClass,
1322 "rawCipherWithPrivateKey", "(Ljava/security/PrivateKey;Z[B)[B");
1323 if (rawCipherMethod == NULL) {
1324 ALOGE("Could not find rawCipherWithPrivateKey");
1325 return NULL;
1326 }
1327
1328 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
1329 cryptoUpcallsClass, rawCipherMethod, privateKey, encrypt, ciphertextArray.get()));
1330 }
1331
1332 // *********************************************
1333 // From keystore_openssl.cpp in Chromium source.
1334 // *********************************************
1335
1336 // Custom RSA_METHOD that uses the platform APIs.
1337 // Note that for now, only signing through RSA_sign() is really supported.
1338 // all other method pointers are either stubs returning errors, or no-ops.
1339 // See <openssl/rsa.h> for exact declaration of RSA_METHOD.
1340
RsaMethodPubEnc(int,const unsigned char *,unsigned char *,RSA *,int)1341 int RsaMethodPubEnc(int /* flen */,
1342 const unsigned char* /* from */,
1343 unsigned char* /* to */,
1344 RSA* /* rsa */,
1345 int /* padding */) {
1346 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
1347 return -1;
1348 }
1349
RsaMethodPubDec(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)1350 int RsaMethodPubDec(int flen,
1351 const unsigned char* from,
1352 unsigned char* to,
1353 RSA* rsa,
1354 int padding) {
1355 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
1356 return -1;
1357 }
1358
1359 // See RSA_eay_private_encrypt in
1360 // third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default
1361 // implementation of this function.
RsaMethodPrivEnc(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)1362 int RsaMethodPrivEnc(int flen,
1363 const unsigned char *from,
1364 unsigned char *to,
1365 RSA *rsa,
1366 int padding) {
1367 if (padding != RSA_PKCS1_PADDING) {
1368 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
1369 // by using javax.crypto.Cipher and picking either the
1370 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
1371 // appropriate. I believe support for both of these was added in
1372 // the same Android version as the "NONEwithRSA"
1373 // java.security.Signature algorithm, so the same version checks
1374 // for GetRsaLegacyKey should work.
1375 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
1376 return -1;
1377 }
1378
1379 // Retrieve private key JNI reference.
1380 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1381 if (!private_key) {
1382 ALOGE("Null JNI reference passed to RsaMethodPrivEnc!");
1383 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1384 return -1;
1385 }
1386
1387 JNIEnv* env = getJNIEnv();
1388 if (env == NULL) {
1389 return -1;
1390 }
1391
1392 // For RSA keys, this function behaves as RSA_private_encrypt with
1393 // PKCS#1 padding.
1394 ScopedLocalRef<jbyteArray> signature(
1395 env, rawSignDigestWithPrivateKey(env, private_key,
1396 reinterpret_cast<const char*>(from), flen));
1397 if (signature.get() == NULL) {
1398 ALOGE("Could not sign message in RsaMethodPrivEnc!");
1399 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1400 return -1;
1401 }
1402
1403 ScopedByteArrayRO signatureBytes(env, signature.get());
1404 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
1405 if (signatureBytes.size() > expected_size) {
1406 ALOGE("RSA Signature size mismatch, actual: %zd, expected <= %zd", signatureBytes.size(),
1407 expected_size);
1408 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1409 return -1;
1410 }
1411
1412 // Copy result to OpenSSL-provided buffer. rawSignDigestWithPrivateKey
1413 // should pad with leading 0s, but if it doesn't, pad the result.
1414 size_t zero_pad = expected_size - signatureBytes.size();
1415 memset(to, 0, zero_pad);
1416 memcpy(to + zero_pad, signatureBytes.get(), signatureBytes.size());
1417
1418 return expected_size;
1419 }
1420
RsaMethodPrivDec(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)1421 int RsaMethodPrivDec(int flen,
1422 const unsigned char* from,
1423 unsigned char* to,
1424 RSA* rsa,
1425 int padding) {
1426 if (padding != RSA_PKCS1_PADDING) {
1427 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
1428 return -1;
1429 }
1430
1431 // Retrieve private key JNI reference.
1432 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1433 if (!private_key) {
1434 ALOGE("Null JNI reference passed to RsaMethodPrivDec!");
1435 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1436 return -1;
1437 }
1438
1439 JNIEnv* env = getJNIEnv();
1440 if (env == NULL) {
1441 return -1;
1442 }
1443
1444 // For RSA keys, this function behaves as RSA_private_decrypt with
1445 // PKCS#1 padding.
1446 ScopedLocalRef<jbyteArray> cleartext(env, rawCipherWithPrivateKey(env, private_key, false,
1447 reinterpret_cast<const char*>(from), flen));
1448 if (cleartext.get() == NULL) {
1449 ALOGE("Could not decrypt message in RsaMethodPrivDec!");
1450 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1451 return -1;
1452 }
1453
1454 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
1455 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
1456 if (cleartextBytes.size() > expected_size) {
1457 ALOGE("RSA ciphertext size mismatch, actual: %zd, expected <= %zd", cleartextBytes.size(),
1458 expected_size);
1459 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1460 return -1;
1461 }
1462
1463 // Copy result to OpenSSL-provided buffer.
1464 memcpy(to, cleartextBytes.get(), cleartextBytes.size());
1465
1466 return cleartextBytes.size();
1467 }
1468
RsaMethodInit(RSA *)1469 int RsaMethodInit(RSA*) {
1470 return 0;
1471 }
1472
RsaMethodFinish(RSA * rsa)1473 int RsaMethodFinish(RSA* rsa) {
1474 // Ensure the global JNI reference created with this wrapper is
1475 // properly destroyed with it.
1476 jobject key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1477 if (key != NULL) {
1478 RSA_set_app_data(rsa, NULL);
1479 JNIEnv* env = getJNIEnv();
1480 env->DeleteGlobalRef(key);
1481 }
1482 // Actual return value is ignored by OpenSSL. There are no docs
1483 // explaining what this is supposed to be.
1484 return 0;
1485 }
1486
1487 const RSA_METHOD android_rsa_method = {
1488 /* .name = */ "Android signing-only RSA method",
1489 /* .rsa_pub_enc = */ RsaMethodPubEnc,
1490 /* .rsa_pub_dec = */ RsaMethodPubDec,
1491 /* .rsa_priv_enc = */ RsaMethodPrivEnc,
1492 /* .rsa_priv_dec = */ RsaMethodPrivDec,
1493 /* .rsa_mod_exp = */ NULL,
1494 /* .bn_mod_exp = */ NULL,
1495 /* .init = */ RsaMethodInit,
1496 /* .finish = */ RsaMethodFinish,
1497 // This flag is necessary to tell OpenSSL to avoid checking the content
1498 // (i.e. internal fields) of the private key. Otherwise, it will complain
1499 // it's not valid for the certificate.
1500 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK,
1501 /* .app_data = */ NULL,
1502 /* .rsa_sign = */ NULL,
1503 /* .rsa_verify = */ NULL,
1504 /* .rsa_keygen = */ NULL,
1505 };
1506
1507 // Custom DSA_METHOD that uses the platform APIs.
1508 // Note that for now, only signing through DSA_sign() is really supported.
1509 // all other method pointers are either stubs returning errors, or no-ops.
1510 // See <openssl/dsa.h> for exact declaration of DSA_METHOD.
1511 //
1512 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions,
1513 // but RSA_set_app_data() is defined as a simple macro that calls
1514 // RSA_set_ex_data() with a hard-coded index of 0, so this code
1515 // does the same thing here.
1516
DsaMethodDoSign(const unsigned char * dgst,int dlen,DSA * dsa)1517 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst,
1518 int dlen,
1519 DSA* dsa) {
1520 // Extract the JNI reference to the PrivateKey object.
1521 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0));
1522 if (private_key == NULL) return NULL;
1523
1524 JNIEnv* env = getJNIEnv();
1525 if (env == NULL) {
1526 return NULL;
1527 }
1528
1529 // Sign the message with it, calling platform APIs.
1530 ScopedLocalRef<jbyteArray> signature(
1531 env, rawSignDigestWithPrivateKey(env, private_key, reinterpret_cast<const char*>(dgst),
1532 dlen));
1533 if (signature.get() == NULL) {
1534 ALOGE("Could not sign message in DsaMethodDoSign!");
1535 return NULL;
1536 }
1537
1538 ScopedByteArrayRO signatureBytes(env, signature.get());
1539 // Note: With DSA, the actual signature might be smaller than DSA_size().
1540 size_t max_expected_size = static_cast<size_t>(DSA_size(dsa));
1541 if (signatureBytes.size() > max_expected_size) {
1542 ALOGE("DSA Signature size mismatch, actual: %zd, expected <= %zd", signatureBytes.size(),
1543 max_expected_size);
1544 return NULL;
1545 }
1546
1547 // Convert the signature into a DSA_SIG object.
1548 const unsigned char* sigbuf = reinterpret_cast<const unsigned char*>(signatureBytes.get());
1549 int siglen = static_cast<size_t>(signatureBytes.size());
1550 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen);
1551 return dsa_sig;
1552 }
1553
DsaMethodSignSetup(DSA *,BN_CTX *,BIGNUM **,BIGNUM **,const unsigned char *,int)1554 int DsaMethodSignSetup(DSA* /* dsa */,
1555 BN_CTX* /* ctx_in */,
1556 BIGNUM** /* kinvp */,
1557 BIGNUM** /* rp */,
1558 const unsigned char* /* dgst */,
1559 int /* dlen */) {
1560 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE);
1561 return -1;
1562 }
1563
DsaMethodDoVerify(const unsigned char *,int,DSA_SIG *,DSA *)1564 int DsaMethodDoVerify(const unsigned char* /* dgst */,
1565 int /* dgst_len */,
1566 DSA_SIG* /* sig */,
1567 DSA* /* dsa */) {
1568 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE);
1569 return -1;
1570 }
1571
DsaMethodFinish(DSA * dsa)1572 int DsaMethodFinish(DSA* dsa) {
1573 // Free the global JNI reference that was created with this
1574 // wrapper key.
1575 jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0));
1576 if (key != NULL) {
1577 DSA_set_ex_data(dsa, 0, NULL);
1578 JNIEnv* env = getJNIEnv();
1579 env->DeleteGlobalRef(key);
1580 }
1581 // Actual return value is ignored by OpenSSL. There are no docs
1582 // explaining what this is supposed to be.
1583 return 0;
1584 }
1585
1586 const DSA_METHOD android_dsa_method = {
1587 /* .name = */ "Android signing-only DSA method",
1588 /* .dsa_do_sign = */ DsaMethodDoSign,
1589 /* .dsa_sign_setup = */ DsaMethodSignSetup,
1590 /* .dsa_do_verify = */ DsaMethodDoVerify,
1591 /* .dsa_mod_exp = */ NULL,
1592 /* .bn_mod_exp = */ NULL,
1593 /* .init = */ NULL, // nothing to do here.
1594 /* .finish = */ DsaMethodFinish,
1595 /* .flags = */ 0,
1596 /* .app_data = */ NULL,
1597 /* .dsa_paramgem = */ NULL,
1598 /* .dsa_keygen = */ NULL};
1599
1600 // Used to ensure that the global JNI reference associated with a custom
1601 // EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed
1602 // (this function is called when EVP_PKEY_free() is called on the wrapper).
ExDataFree(void *,void * ptr,CRYPTO_EX_DATA * ad,int idx,long,void *)1603 void ExDataFree(void* /* parent */,
1604 void* ptr,
1605 CRYPTO_EX_DATA* ad,
1606 int idx,
1607 long /* argl */,
1608 void* /* argp */) {
1609 jobject private_key = reinterpret_cast<jobject>(ptr);
1610 if (private_key == NULL) return;
1611
1612 CRYPTO_set_ex_data(ad, idx, NULL);
1613 JNIEnv* env = getJNIEnv();
1614 env->DeleteGlobalRef(private_key);
1615 }
1616
ExDataDup(CRYPTO_EX_DATA *,CRYPTO_EX_DATA *,void *,int,long,void *)1617 int ExDataDup(CRYPTO_EX_DATA* /* to */,
1618 CRYPTO_EX_DATA* /* from */,
1619 void* /* from_d */,
1620 int /* idx */,
1621 long /* argl */,
1622 void* /* argp */) {
1623 // This callback shall never be called with the current OpenSSL
1624 // implementation (the library only ever duplicates EX_DATA items
1625 // for SSL and BIO objects). But provide this to catch regressions
1626 // in the future.
1627 // Return value is currently ignored by OpenSSL.
1628 return 0;
1629 }
1630
1631 class EcdsaExDataIndex {
1632 public:
ex_data_index()1633 int ex_data_index() { return ex_data_index_; }
1634
Instance()1635 static EcdsaExDataIndex& Instance() {
1636 static EcdsaExDataIndex singleton;
1637 return singleton;
1638 }
1639
1640 private:
EcdsaExDataIndex()1641 EcdsaExDataIndex() {
1642 ex_data_index_ = ECDSA_get_ex_new_index(0, NULL, NULL, ExDataDup, ExDataFree);
1643 }
1644 EcdsaExDataIndex(EcdsaExDataIndex const&);
~EcdsaExDataIndex()1645 ~EcdsaExDataIndex() {}
1646 EcdsaExDataIndex& operator=(EcdsaExDataIndex const&);
1647
1648 int ex_data_index_;
1649 };
1650
1651 // Returns the index of the custom EX_DATA used to store the JNI reference.
EcdsaGetExDataIndex(void)1652 int EcdsaGetExDataIndex(void) {
1653 EcdsaExDataIndex& exData = EcdsaExDataIndex::Instance();
1654 return exData.ex_data_index();
1655 }
1656
EcdsaMethodDoSign(const unsigned char * dgst,int dgst_len,const BIGNUM *,const BIGNUM *,EC_KEY * eckey)1657 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, int dgst_len, const BIGNUM* /* inv */,
1658 const BIGNUM* /* rp */, EC_KEY* eckey) {
1659 // Retrieve private key JNI reference.
1660 jobject private_key =
1661 reinterpret_cast<jobject>(ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
1662 if (!private_key) {
1663 ALOGE("Null JNI reference passed to EcdsaMethodDoSign!");
1664 return NULL;
1665 }
1666 JNIEnv* env = getJNIEnv();
1667 if (env == NULL) {
1668 return NULL;
1669 }
1670
1671 // Sign message with it through JNI.
1672 ScopedLocalRef<jbyteArray> signature(
1673 env, rawSignDigestWithPrivateKey(env, private_key, reinterpret_cast<const char*>(dgst),
1674 dgst_len));
1675 if (signature.get() == NULL) {
1676 ALOGE("Could not sign message in EcdsaMethodDoSign!");
1677 return NULL;
1678 }
1679
1680 ScopedByteArrayRO signatureBytes(env, signature.get());
1681 // Note: With ECDSA, the actual signature may be smaller than
1682 // ECDSA_size().
1683 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey));
1684 if (signatureBytes.size() > max_expected_size) {
1685 ALOGE("ECDSA Signature size mismatch, actual: %zd, expected <= %zd", signatureBytes.size(),
1686 max_expected_size);
1687 return NULL;
1688 }
1689
1690 // Convert signature to ECDSA_SIG object
1691 const unsigned char* sigbuf = reinterpret_cast<const unsigned char*>(signatureBytes.get());
1692 long siglen = static_cast<long>(signatureBytes.size());
1693 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
1694 }
1695
EcdsaMethodSignSetup(EC_KEY *,BN_CTX *,BIGNUM **,BIGNUM **,const unsigned char *,int)1696 int EcdsaMethodSignSetup(EC_KEY* /* eckey */,
1697 BN_CTX* /* ctx */,
1698 BIGNUM** /* kinv */,
1699 BIGNUM** /* r */,
1700 const unsigned char*,
1701 int) {
1702 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB);
1703 return -1;
1704 }
1705
EcdsaMethodDoVerify(const unsigned char *,int,const ECDSA_SIG *,EC_KEY *)1706 int EcdsaMethodDoVerify(const unsigned char* /* dgst */,
1707 int /* dgst_len */,
1708 const ECDSA_SIG* /* sig */,
1709 EC_KEY* /* eckey */) {
1710 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB);
1711 return -1;
1712 }
1713
1714 const ECDSA_METHOD android_ecdsa_method = {
1715 /* .name = */ "Android signing-only ECDSA method",
1716 /* .ecdsa_do_sign = */ EcdsaMethodDoSign,
1717 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup,
1718 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify,
1719 /* .flags = */ 0,
1720 /* .app_data = */ NULL,
1721 };
1722
1723 #ifdef CONSCRYPT_UNBUNDLED
1724 /*
1725 * This is a big hack; don't learn from this. Basically what happened is we do
1726 * not have an API way to insert ourselves into the AsynchronousCloseMonitor
1727 * that's compiled into the native libraries for libcore when we're unbundled.
1728 * So we try to look up the symbol from the main library to find it.
1729 */
1730 typedef void (*acm_ctor_func)(void*, int);
1731 typedef void (*acm_dtor_func)(void*);
1732 static acm_ctor_func async_close_monitor_ctor = NULL;
1733 static acm_dtor_func async_close_monitor_dtor = NULL;
1734
1735 class CompatibilityCloseMonitor {
1736 public:
CompatibilityCloseMonitor(int fd)1737 CompatibilityCloseMonitor(int fd) {
1738 if (async_close_monitor_ctor != NULL) {
1739 async_close_monitor_ctor(objBuffer, fd);
1740 }
1741 }
1742
~CompatibilityCloseMonitor()1743 ~CompatibilityCloseMonitor() {
1744 if (async_close_monitor_dtor != NULL) {
1745 async_close_monitor_dtor(objBuffer);
1746 }
1747 }
1748 private:
1749 char objBuffer[256];
1750 #if 0
1751 static_assert(sizeof(objBuffer) > 2*sizeof(AsynchronousCloseMonitor),
1752 "CompatibilityCloseMonitor must be larger than the actual object");
1753 #endif
1754 };
1755
findAsynchronousCloseMonitorFuncs()1756 static void findAsynchronousCloseMonitorFuncs() {
1757 void *lib = dlopen("libjavacore.so", RTLD_NOW);
1758 if (lib != NULL) {
1759 async_close_monitor_ctor = (acm_ctor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorC1Ei");
1760 async_close_monitor_dtor = (acm_dtor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorD1Ev");
1761 }
1762 }
1763 #endif
1764
1765 /**
1766 * Copied from libnativehelper NetworkUtilites.cpp
1767 */
setBlocking(int fd,bool blocking)1768 static bool setBlocking(int fd, bool blocking) {
1769 int flags = fcntl(fd, F_GETFL);
1770 if (flags == -1) {
1771 return false;
1772 }
1773
1774 if (!blocking) {
1775 flags |= O_NONBLOCK;
1776 } else {
1777 flags &= ~O_NONBLOCK;
1778 }
1779
1780 int rc = fcntl(fd, F_SETFL, flags);
1781 return (rc != -1);
1782 }
1783
1784 /**
1785 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
1786 * suppose there are not many other ways to do this on a Linux system (modulo
1787 * isomorphism).
1788 */
1789 #define MUTEX_TYPE pthread_mutex_t
1790 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
1791 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
1792 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
1793 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
1794 #define THREAD_ID pthread_self()
1795 #define THROW_SSLEXCEPTION (-2)
1796 #define THROW_SOCKETTIMEOUTEXCEPTION (-3)
1797 #define THROWN_EXCEPTION (-4)
1798
1799 static MUTEX_TYPE* mutex_buf = NULL;
1800
locking_function(int mode,int n,const char *,int)1801 static void locking_function(int mode, int n, const char*, int) {
1802 if (mode & CRYPTO_LOCK) {
1803 MUTEX_LOCK(mutex_buf[n]);
1804 } else {
1805 MUTEX_UNLOCK(mutex_buf[n]);
1806 }
1807 }
1808
id_function(void)1809 static unsigned long id_function(void) {
1810 return ((unsigned long)THREAD_ID);
1811 }
1812
THREAD_setup(void)1813 int THREAD_setup(void) {
1814 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
1815 if (!mutex_buf) {
1816 return 0;
1817 }
1818
1819 for (int i = 0; i < CRYPTO_num_locks(); ++i) {
1820 MUTEX_SETUP(mutex_buf[i]);
1821 }
1822
1823 CRYPTO_set_id_callback(id_function);
1824 CRYPTO_set_locking_callback(locking_function);
1825
1826 return 1;
1827 }
1828
THREAD_cleanup(void)1829 int THREAD_cleanup(void) {
1830 if (!mutex_buf) {
1831 return 0;
1832 }
1833
1834 CRYPTO_set_id_callback(NULL);
1835 CRYPTO_set_locking_callback(NULL);
1836
1837 for (int i = 0; i < CRYPTO_num_locks( ); i++) {
1838 MUTEX_CLEANUP(mutex_buf[i]);
1839 }
1840
1841 free(mutex_buf);
1842 mutex_buf = NULL;
1843
1844 return 1;
1845 }
1846
1847 /**
1848 * Initialization phase for every OpenSSL job: Loads the Error strings, the
1849 * crypto algorithms and reset the OpenSSL library
1850 */
NativeCrypto_clinit(JNIEnv *,jclass)1851 static void NativeCrypto_clinit(JNIEnv*, jclass)
1852 {
1853 SSL_load_error_strings();
1854 ERR_load_crypto_strings();
1855 SSL_library_init();
1856 OpenSSL_add_all_algorithms();
1857 THREAD_setup();
1858 }
1859
NativeCrypto_ENGINE_load_dynamic(JNIEnv *,jclass)1860 static void NativeCrypto_ENGINE_load_dynamic(JNIEnv*, jclass) {
1861 JNI_TRACE("ENGINE_load_dynamic()");
1862
1863 ENGINE_load_dynamic();
1864 }
1865
NativeCrypto_ENGINE_by_id(JNIEnv * env,jclass,jstring idJava)1866 static jlong NativeCrypto_ENGINE_by_id(JNIEnv* env, jclass, jstring idJava) {
1867 JNI_TRACE("ENGINE_by_id(%p)", idJava);
1868
1869 ScopedUtfChars id(env, idJava);
1870 if (id.c_str() == NULL) {
1871 JNI_TRACE("ENGINE_by_id(%p) => id == null", idJava);
1872 return 0;
1873 }
1874 JNI_TRACE("ENGINE_by_id(\"%s\")", id.c_str());
1875
1876 ENGINE* e = ENGINE_by_id(id.c_str());
1877 if (e == NULL) {
1878 freeOpenSslErrorState();
1879 }
1880
1881 JNI_TRACE("ENGINE_by_id(\"%s\") => %p", id.c_str(), e);
1882 return reinterpret_cast<uintptr_t>(e);
1883 }
1884
NativeCrypto_ENGINE_add(JNIEnv * env,jclass,jlong engineRef)1885 static jint NativeCrypto_ENGINE_add(JNIEnv* env, jclass, jlong engineRef) {
1886 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1887 JNI_TRACE("ENGINE_add(%p)", e);
1888
1889 if (e == NULL) {
1890 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1891 return 0;
1892 }
1893
1894 int ret = ENGINE_add(e);
1895
1896 /*
1897 * We tolerate errors, because the most likely error is that
1898 * the ENGINE is already in the list.
1899 */
1900 freeOpenSslErrorState();
1901
1902 JNI_TRACE("ENGINE_add(%p) => %d", e, ret);
1903 return ret;
1904 }
1905
NativeCrypto_ENGINE_init(JNIEnv * env,jclass,jlong engineRef)1906 static jint NativeCrypto_ENGINE_init(JNIEnv* env, jclass, jlong engineRef) {
1907 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1908 JNI_TRACE("ENGINE_init(%p)", e);
1909
1910 if (e == NULL) {
1911 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1912 return 0;
1913 }
1914
1915 int ret = ENGINE_init(e);
1916 JNI_TRACE("ENGINE_init(%p) => %d", e, ret);
1917 return ret;
1918 }
1919
NativeCrypto_ENGINE_finish(JNIEnv * env,jclass,jlong engineRef)1920 static jint NativeCrypto_ENGINE_finish(JNIEnv* env, jclass, jlong engineRef) {
1921 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1922 JNI_TRACE("ENGINE_finish(%p)", e);
1923
1924 if (e == NULL) {
1925 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1926 return 0;
1927 }
1928
1929 int ret = ENGINE_finish(e);
1930 JNI_TRACE("ENGINE_finish(%p) => %d", e, ret);
1931 return ret;
1932 }
1933
NativeCrypto_ENGINE_free(JNIEnv * env,jclass,jlong engineRef)1934 static jint NativeCrypto_ENGINE_free(JNIEnv* env, jclass, jlong engineRef) {
1935 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1936 JNI_TRACE("ENGINE_free(%p)", e);
1937
1938 if (e == NULL) {
1939 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
1940 return 0;
1941 }
1942
1943 int ret = ENGINE_free(e);
1944 JNI_TRACE("ENGINE_free(%p) => %d", e, ret);
1945 return ret;
1946 }
1947
NativeCrypto_ENGINE_load_private_key(JNIEnv * env,jclass,jlong engineRef,jstring idJava)1948 static jlong NativeCrypto_ENGINE_load_private_key(JNIEnv* env, jclass, jlong engineRef,
1949 jstring idJava) {
1950 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1951 JNI_TRACE("ENGINE_load_private_key(%p, %p)", e, idJava);
1952
1953 ScopedUtfChars id(env, idJava);
1954 if (id.c_str() == NULL) {
1955 jniThrowException(env, "java/lang/IllegalArgumentException", "id == NULL");
1956 return 0;
1957 }
1958
1959 Unique_EVP_PKEY pkey(ENGINE_load_private_key(e, id.c_str(), NULL, NULL));
1960 if (pkey.get() == NULL) {
1961 throwExceptionIfNecessary(env, "ENGINE_load_private_key");
1962 return 0;
1963 }
1964
1965 JNI_TRACE("ENGINE_load_private_key(%p, %p) => %p", e, idJava, pkey.get());
1966 return reinterpret_cast<uintptr_t>(pkey.release());
1967 }
1968
NativeCrypto_ENGINE_get_id(JNIEnv * env,jclass,jlong engineRef)1969 static jstring NativeCrypto_ENGINE_get_id(JNIEnv* env, jclass, jlong engineRef)
1970 {
1971 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1972 JNI_TRACE("ENGINE_get_id(%p)", e);
1973
1974 if (e == NULL) {
1975 jniThrowNullPointerException(env, "engine == null");
1976 JNI_TRACE("ENGINE_get_id(%p) => engine == null", e);
1977 return NULL;
1978 }
1979
1980 const char *id = ENGINE_get_id(e);
1981 ScopedLocalRef<jstring> idJava(env, env->NewStringUTF(id));
1982
1983 JNI_TRACE("ENGINE_get_id(%p) => \"%s\"", e, id);
1984 return idJava.release();
1985 }
1986
NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv * env,jclass,jlong engineRef,jstring cmdJava,jstring argJava,jint cmd_optional)1987 static jint NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv* env, jclass, jlong engineRef,
1988 jstring cmdJava, jstring argJava, jint cmd_optional)
1989 {
1990 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
1991 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d)", e, cmdJava, argJava, cmd_optional);
1992
1993 if (e == NULL) {
1994 jniThrowNullPointerException(env, "engine == null");
1995 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d) => engine == null", e, cmdJava, argJava,
1996 cmd_optional);
1997 return 0;
1998 }
1999
2000 ScopedUtfChars cmdChars(env, cmdJava);
2001 if (cmdChars.c_str() == NULL) {
2002 return 0;
2003 }
2004
2005 UniquePtr<ScopedUtfChars> arg;
2006 const char* arg_c_str = NULL;
2007 if (argJava != NULL) {
2008 arg.reset(new ScopedUtfChars(env, argJava));
2009 arg_c_str = arg->c_str();
2010 if (arg_c_str == NULL) {
2011 return 0;
2012 }
2013 }
2014 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d)", e, cmdChars.c_str(), arg_c_str,
2015 cmd_optional);
2016
2017 int ret = ENGINE_ctrl_cmd_string(e, cmdChars.c_str(), arg_c_str, cmd_optional);
2018 if (ret != 1) {
2019 throwExceptionIfNecessary(env, "ENGINE_ctrl_cmd_string");
2020 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => threw error", e,
2021 cmdChars.c_str(), arg_c_str, cmd_optional);
2022 return 0;
2023 }
2024
2025 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => %d", e, cmdChars.c_str(),
2026 arg_c_str, cmd_optional, ret);
2027 return ret;
2028 }
2029
NativeCrypto_EVP_PKEY_new_DH(JNIEnv * env,jclass,jbyteArray p,jbyteArray g,jbyteArray pub_key,jbyteArray priv_key)2030 static jlong NativeCrypto_EVP_PKEY_new_DH(JNIEnv* env, jclass,
2031 jbyteArray p, jbyteArray g,
2032 jbyteArray pub_key, jbyteArray priv_key) {
2033 JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p)",
2034 p, g, pub_key, priv_key);
2035
2036 Unique_DH dh(DH_new());
2037 if (dh.get() == NULL) {
2038 jniThrowRuntimeException(env, "DH_new failed");
2039 return 0;
2040 }
2041
2042 if (!arrayToBignum(env, p, &dh->p)) {
2043 return 0;
2044 }
2045
2046 if (!arrayToBignum(env, g, &dh->g)) {
2047 return 0;
2048 }
2049
2050 if (pub_key != NULL && !arrayToBignum(env, pub_key, &dh->pub_key)) {
2051 return 0;
2052 }
2053
2054 if (priv_key != NULL && !arrayToBignum(env, priv_key, &dh->priv_key)) {
2055 return 0;
2056 }
2057
2058 if (dh->p == NULL || dh->g == NULL
2059 || (pub_key != NULL && dh->pub_key == NULL)
2060 || (priv_key != NULL && dh->priv_key == NULL)) {
2061 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
2062 return 0;
2063 }
2064
2065 /* The public key can be recovered if the private key is available. */
2066 if (dh->pub_key == NULL && dh->priv_key != NULL) {
2067 if (!DH_generate_key(dh.get())) {
2068 jniThrowRuntimeException(env, "EVP_PKEY_new_DH failed during pub_key generation");
2069 return 0;
2070 }
2071 }
2072
2073 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2074 if (pkey.get() == NULL) {
2075 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2076 return 0;
2077 }
2078 if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
2079 jniThrowRuntimeException(env, "EVP_PKEY_assign_DH failed");
2080 return 0;
2081 }
2082 OWNERSHIP_TRANSFERRED(dh);
2083 JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
2084 p, g, pub_key, priv_key, pkey.get());
2085 return reinterpret_cast<jlong>(pkey.release());
2086 }
2087
2088 /**
2089 * public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g,
2090 * byte[] pub_key, byte[] priv_key);
2091 */
NativeCrypto_EVP_PKEY_new_DSA(JNIEnv * env,jclass,jbyteArray p,jbyteArray q,jbyteArray g,jbyteArray pub_key,jbyteArray priv_key)2092 static jlong NativeCrypto_EVP_PKEY_new_DSA(JNIEnv* env, jclass,
2093 jbyteArray p, jbyteArray q, jbyteArray g,
2094 jbyteArray pub_key, jbyteArray priv_key) {
2095 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p)",
2096 p, q, g, pub_key, priv_key);
2097
2098 Unique_DSA dsa(DSA_new());
2099 if (dsa.get() == NULL) {
2100 jniThrowRuntimeException(env, "DSA_new failed");
2101 return 0;
2102 }
2103
2104 if (!arrayToBignum(env, p, &dsa->p)) {
2105 return 0;
2106 }
2107
2108 if (!arrayToBignum(env, q, &dsa->q)) {
2109 return 0;
2110 }
2111
2112 if (!arrayToBignum(env, g, &dsa->g)) {
2113 return 0;
2114 }
2115
2116 if (pub_key != NULL && !arrayToBignum(env, pub_key, &dsa->pub_key)) {
2117 return 0;
2118 }
2119
2120 if (priv_key != NULL && !arrayToBignum(env, priv_key, &dsa->priv_key)) {
2121 return 0;
2122 }
2123
2124 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL
2125 || (dsa->pub_key == NULL && dsa->priv_key == NULL)) {
2126 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
2127 return 0;
2128 }
2129
2130 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2131 if (pkey.get() == NULL) {
2132 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2133 return 0;
2134 }
2135 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
2136 jniThrowRuntimeException(env, "EVP_PKEY_assign_DSA failed");
2137 return 0;
2138 }
2139 OWNERSHIP_TRANSFERRED(dsa);
2140 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
2141 p, q, g, pub_key, priv_key, pkey.get());
2142 return reinterpret_cast<jlong>(pkey.release());
2143 }
2144
2145 /**
2146 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
2147 */
NativeCrypto_EVP_PKEY_new_RSA(JNIEnv * env,jclass,jbyteArray n,jbyteArray e,jbyteArray d,jbyteArray p,jbyteArray q,jbyteArray dmp1,jbyteArray dmq1,jbyteArray iqmp)2148 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass,
2149 jbyteArray n, jbyteArray e, jbyteArray d,
2150 jbyteArray p, jbyteArray q,
2151 jbyteArray dmp1, jbyteArray dmq1,
2152 jbyteArray iqmp) {
2153 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p, dmp1=%p, dmq1=%p, iqmp=%p)",
2154 n, e, d, p, q, dmp1, dmq1, iqmp);
2155
2156 Unique_RSA rsa(RSA_new());
2157 if (rsa.get() == NULL) {
2158 jniThrowRuntimeException(env, "RSA_new failed");
2159 return 0;
2160 }
2161
2162 if (e == NULL && d == NULL) {
2163 jniThrowException(env, "java/lang/IllegalArgumentException", "e == NULL && d == NULL");
2164 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == NULL && d == NULL");
2165 return 0;
2166 }
2167
2168 if (!arrayToBignum(env, n, &rsa->n)) {
2169 return 0;
2170 }
2171
2172 if (e != NULL && !arrayToBignum(env, e, &rsa->e)) {
2173 return 0;
2174 }
2175
2176 if (d != NULL && !arrayToBignum(env, d, &rsa->d)) {
2177 return 0;
2178 }
2179
2180 if (p != NULL && !arrayToBignum(env, p, &rsa->p)) {
2181 return 0;
2182 }
2183
2184 if (q != NULL && !arrayToBignum(env, q, &rsa->q)) {
2185 return 0;
2186 }
2187
2188 if (dmp1 != NULL && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
2189 return 0;
2190 }
2191
2192 if (dmq1 != NULL && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
2193 return 0;
2194 }
2195
2196 if (iqmp != NULL && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
2197 return 0;
2198 }
2199
2200 #ifdef WITH_JNI_TRACE
2201 if (p != NULL && q != NULL) {
2202 int check = RSA_check_key(rsa.get());
2203 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
2204 }
2205 #endif
2206
2207 if (rsa->n == NULL || (rsa->e == NULL && rsa->d == NULL)) {
2208 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
2209 return 0;
2210 }
2211
2212 /*
2213 * If the private exponent is available, there is the potential to do signing
2214 * operations. If the public exponent is also available, OpenSSL will do RSA
2215 * blinding. Enable it if possible.
2216 */
2217 if (rsa->d != NULL) {
2218 if (rsa->e != NULL) {
2219 JNI_TRACE("EVP_PKEY_new_RSA(...) enabling RSA blinding => %p", rsa.get());
2220 RSA_blinding_on(rsa.get(), NULL);
2221 } else {
2222 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
2223 RSA_blinding_off(rsa.get());
2224 }
2225 }
2226
2227 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2228 if (pkey.get() == NULL) {
2229 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2230 return 0;
2231 }
2232 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
2233 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2234 return 0;
2235 }
2236 OWNERSHIP_TRANSFERRED(rsa);
2237 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p",
2238 n, e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
2239 return reinterpret_cast<uintptr_t>(pkey.release());
2240 }
2241
NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv * env,jclass,jlong groupRef,jlong pubkeyRef,jbyteArray keyJavaBytes)2242 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jlong groupRef,
2243 jlong pubkeyRef, jbyteArray keyJavaBytes) {
2244 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2245 const EC_POINT* pubkey = reinterpret_cast<const EC_POINT*>(pubkeyRef);
2246 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", group, pubkey, keyJavaBytes);
2247
2248 Unique_BIGNUM key(NULL);
2249 if (keyJavaBytes != NULL) {
2250 BIGNUM* keyRef = NULL;
2251 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
2252 return 0;
2253 }
2254 key.reset(keyRef);
2255 }
2256
2257 Unique_EC_KEY eckey(EC_KEY_new());
2258 if (eckey.get() == NULL) {
2259 jniThrowRuntimeException(env, "EC_KEY_new failed");
2260 return 0;
2261 }
2262
2263 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2264 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
2265 keyJavaBytes);
2266 throwExceptionIfNecessary(env, "EC_KEY_set_group");
2267 return 0;
2268 }
2269
2270 if (pubkey != NULL) {
2271 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
2272 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
2273 pubkey, keyJavaBytes);
2274 throwExceptionIfNecessary(env, "EC_KEY_set_public_key");
2275 return 0;
2276 }
2277 }
2278
2279 if (key.get() != NULL) {
2280 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
2281 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
2282 pubkey, keyJavaBytes);
2283 throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
2284 return 0;
2285 }
2286 if (pubkey == NULL) {
2287 Unique_EC_POINT calcPubkey(EC_POINT_new(group));
2288 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), NULL, NULL, NULL)) {
2289 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calulate public key", group,
2290 pubkey, keyJavaBytes);
2291 throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
2292 return 0;
2293 }
2294 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
2295 }
2296 }
2297
2298 if (!EC_KEY_check_key(eckey.get())) {
2299 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey, keyJavaBytes);
2300 throwExceptionIfNecessary(env, "EC_KEY_check_key");
2301 return 0;
2302 }
2303
2304 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2305 if (pkey.get() == NULL) {
2306 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
2307 throwExceptionIfNecessary(env, "EVP_PKEY_new failed");
2308 return 0;
2309 }
2310 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2311 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
2312 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2313 return 0;
2314 }
2315 OWNERSHIP_TRANSFERRED(eckey);
2316
2317 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
2318 return reinterpret_cast<uintptr_t>(pkey.release());
2319 }
2320
NativeCrypto_EVP_PKEY_new_mac_key(JNIEnv * env,jclass,jint pkeyType,jbyteArray keyJavaBytes)2321 static jlong NativeCrypto_EVP_PKEY_new_mac_key(JNIEnv* env, jclass, jint pkeyType,
2322 jbyteArray keyJavaBytes)
2323 {
2324 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p)", pkeyType, keyJavaBytes);
2325
2326 ScopedByteArrayRO key(env, keyJavaBytes);
2327 if (key.get() == NULL) {
2328 return 0;
2329 }
2330
2331 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(key.get());
2332 Unique_EVP_PKEY pkey(EVP_PKEY_new_mac_key(pkeyType, (ENGINE *) NULL, tmp, key.size()));
2333 if (pkey.get() == NULL) {
2334 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => threw error", pkeyType, keyJavaBytes);
2335 throwExceptionIfNecessary(env, "ENGINE_load_private_key");
2336 return 0;
2337 }
2338
2339 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => %p", pkeyType, keyJavaBytes, pkey.get());
2340 return reinterpret_cast<uintptr_t>(pkey.release());
2341 }
2342
NativeCrypto_EVP_PKEY_type(JNIEnv * env,jclass,jlong pkeyRef)2343 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jlong pkeyRef) {
2344 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2345 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
2346
2347 if (pkey == NULL) {
2348 jniThrowNullPointerException(env, NULL);
2349 return -1;
2350 }
2351
2352 int result = EVP_PKEY_type(pkey->type);
2353 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
2354 return result;
2355 }
2356
2357 /**
2358 * private static native int EVP_PKEY_size(int pkey);
2359 */
NativeCrypto_EVP_PKEY_size(JNIEnv * env,jclass,jlong pkeyRef)2360 static int NativeCrypto_EVP_PKEY_size(JNIEnv* env, jclass, jlong pkeyRef) {
2361 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2362 JNI_TRACE("EVP_PKEY_size(%p)", pkey);
2363
2364 if (pkey == NULL) {
2365 jniThrowNullPointerException(env, NULL);
2366 return -1;
2367 }
2368
2369 int result = EVP_PKEY_size(pkey);
2370 JNI_TRACE("EVP_PKEY_size(%p) => %d", pkey, result);
2371 return result;
2372 }
2373
NativeCrypto_EVP_PKEY_print_public(JNIEnv * env,jclass,jlong pkeyRef)2374 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jlong pkeyRef) {
2375 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2376 JNI_TRACE("EVP_PKEY_print_public(%p)", pkey);
2377
2378 if (pkey == NULL) {
2379 jniThrowNullPointerException(env, "pkey == null");
2380 return NULL;
2381 }
2382
2383 Unique_BIO buffer(BIO_new(BIO_s_mem()));
2384 if (buffer.get() == NULL) {
2385 jniThrowOutOfMemory(env, "Unable to allocate BIO");
2386 return NULL;
2387 }
2388
2389 if (EVP_PKEY_print_public(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
2390 throwExceptionIfNecessary(env, "EVP_PKEY_print_public");
2391 return NULL;
2392 }
2393 // Null terminate this
2394 BIO_write(buffer.get(), "\0", 1);
2395
2396 char *tmp;
2397 BIO_get_mem_data(buffer.get(), &tmp);
2398 jstring description = env->NewStringUTF(tmp);
2399
2400 JNI_TRACE("EVP_PKEY_print_public(%p) => \"%s\"", pkey, tmp);
2401 return description;
2402 }
2403
NativeCrypto_EVP_PKEY_print_private(JNIEnv * env,jclass,jlong pkeyRef)2404 static jstring NativeCrypto_EVP_PKEY_print_private(JNIEnv* env, jclass, jlong pkeyRef) {
2405 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2406 JNI_TRACE("EVP_PKEY_print_private(%p)", pkey);
2407
2408 if (pkey == NULL) {
2409 jniThrowNullPointerException(env, "pkey == null");
2410 return NULL;
2411 }
2412
2413 Unique_BIO buffer(BIO_new(BIO_s_mem()));
2414 if (buffer.get() == NULL) {
2415 jniThrowOutOfMemory(env, "Unable to allocate BIO");
2416 return NULL;
2417 }
2418
2419 if (EVP_PKEY_print_private(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
2420 throwExceptionIfNecessary(env, "EVP_PKEY_print_private");
2421 return NULL;
2422 }
2423 // Null terminate this
2424 BIO_write(buffer.get(), "\0", 1);
2425
2426 char *tmp;
2427 BIO_get_mem_data(buffer.get(), &tmp);
2428 jstring description = env->NewStringUTF(tmp);
2429
2430 JNI_TRACE("EVP_PKEY_print_private(%p) => \"%s\"", pkey, tmp);
2431 return description;
2432 }
2433
NativeCrypto_EVP_PKEY_free(JNIEnv *,jclass,jlong pkeyRef)2434 static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, jlong pkeyRef) {
2435 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2436 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
2437
2438 if (pkey != NULL) {
2439 EVP_PKEY_free(pkey);
2440 }
2441 }
2442
NativeCrypto_EVP_PKEY_cmp(JNIEnv * env,jclass,jlong pkey1Ref,jlong pkey2Ref)2443 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jlong pkey1Ref, jlong pkey2Ref) {
2444 EVP_PKEY* pkey1 = reinterpret_cast<EVP_PKEY*>(pkey1Ref);
2445 EVP_PKEY* pkey2 = reinterpret_cast<EVP_PKEY*>(pkey2Ref);
2446 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1, pkey2);
2447
2448 if (pkey1 == NULL) {
2449 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey1 == NULL", pkey1, pkey2);
2450 jniThrowNullPointerException(env, "pkey1 == NULL");
2451 return -1;
2452 } else if (pkey2 == NULL) {
2453 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey2 == NULL", pkey1, pkey2);
2454 jniThrowNullPointerException(env, "pkey2 == NULL");
2455 return -1;
2456 }
2457
2458 int result = EVP_PKEY_cmp(pkey1, pkey2);
2459 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
2460 return result;
2461 }
2462
2463 /*
2464 * static native byte[] i2d_PKCS8_PRIV_KEY_INFO(int, byte[])
2465 */
NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO(JNIEnv * env,jclass,jlong pkeyRef)2466 static jbyteArray NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jlong pkeyRef) {
2467 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2468 JNI_TRACE("i2d_PKCS8_PRIV_KEY_INFO(%p)", pkey);
2469
2470 if (pkey == NULL) {
2471 jniThrowNullPointerException(env, NULL);
2472 return NULL;
2473 }
2474
2475 Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey));
2476 if (pkcs8.get() == NULL) {
2477 throwExceptionIfNecessary(env, "NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO");
2478 JNI_TRACE("key=%p i2d_PKCS8_PRIV_KEY_INFO => error from key to PKCS8", pkey);
2479 return NULL;
2480 }
2481
2482 return ASN1ToByteArray<PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO>(env, pkcs8.get());
2483 }
2484
2485 /*
2486 * static native int d2i_PKCS8_PRIV_KEY_INFO(byte[])
2487 */
NativeCrypto_d2i_PKCS8_PRIV_KEY_INFO(JNIEnv * env,jclass,jbyteArray keyJavaBytes)2488 static jlong NativeCrypto_d2i_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
2489 JNI_TRACE("d2i_PKCS8_PRIV_KEY_INFO(%p)", keyJavaBytes);
2490
2491 ScopedByteArrayRO bytes(env, keyJavaBytes);
2492 if (bytes.get() == NULL) {
2493 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => threw exception", keyJavaBytes);
2494 return 0;
2495 }
2496
2497 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
2498 Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, bytes.size()));
2499 if (pkcs8.get() == NULL) {
2500 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
2501 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from DER to PKCS8", keyJavaBytes);
2502 return 0;
2503 }
2504
2505 Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
2506 if (pkey.get() == NULL) {
2507 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
2508 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from PKCS8 to key", keyJavaBytes);
2509 return 0;
2510 }
2511
2512 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => %p", keyJavaBytes, pkey.get());
2513 return reinterpret_cast<uintptr_t>(pkey.release());
2514 }
2515
2516 /*
2517 * static native byte[] i2d_PUBKEY(int)
2518 */
NativeCrypto_i2d_PUBKEY(JNIEnv * env,jclass,jlong pkeyRef)2519 static jbyteArray NativeCrypto_i2d_PUBKEY(JNIEnv* env, jclass, jlong pkeyRef) {
2520 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2521 JNI_TRACE("i2d_PUBKEY(%p)", pkey);
2522 return ASN1ToByteArray<EVP_PKEY, i2d_PUBKEY>(env, pkey);
2523 }
2524
2525 /*
2526 * static native int d2i_PUBKEY(byte[])
2527 */
NativeCrypto_d2i_PUBKEY(JNIEnv * env,jclass,jbyteArray javaBytes)2528 static jlong NativeCrypto_d2i_PUBKEY(JNIEnv* env, jclass, jbyteArray javaBytes) {
2529 JNI_TRACE("d2i_PUBKEY(%p)", javaBytes);
2530
2531 ScopedByteArrayRO bytes(env, javaBytes);
2532 if (bytes.get() == NULL) {
2533 JNI_TRACE("d2i_PUBKEY(%p) => threw error", javaBytes);
2534 return 0;
2535 }
2536
2537 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
2538 Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, bytes.size()));
2539 if (pkey.get() == NULL) {
2540 JNI_TRACE("bytes=%p d2i_PUBKEY => threw exception", javaBytes);
2541 throwExceptionIfNecessary(env, "d2i_PUBKEY");
2542 return 0;
2543 }
2544
2545 return reinterpret_cast<uintptr_t>(pkey.release());
2546 }
2547
NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray modulusBytes)2548 static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
2549 jbyteArray modulusBytes) {
2550 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
2551
2552 Unique_RSA rsa(RSA_new());
2553 if (rsa.get() == NULL) {
2554 jniThrowOutOfMemory(env, "Unable to allocate RSA key");
2555 return 0;
2556 }
2557
2558 RSA_set_method(rsa.get(), &android_rsa_method);
2559
2560 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
2561 return 0;
2562 }
2563
2564 RSA_set_app_data(rsa.get(), env->NewGlobalRef(javaKey));
2565
2566 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2567 if (pkey.get() == NULL) {
2568 JNI_TRACE("getRSAPrivateKeyWrapper failed");
2569 jniThrowRuntimeException(env, "NativeCrypto_getRSAPrivateKeyWrapper failed");
2570 freeOpenSslErrorState();
2571 return 0;
2572 }
2573
2574 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
2575 jniThrowRuntimeException(env, "getRSAPrivateKeyWrapper failed");
2576 return 0;
2577 }
2578 OWNERSHIP_TRANSFERRED(rsa);
2579 return reinterpret_cast<uintptr_t>(pkey.release());
2580 }
2581
NativeCrypto_getDSAPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jbyteArray qBytes)2582 static jlong NativeCrypto_getDSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
2583 jbyteArray qBytes) {
2584 JNI_TRACE("getDSAPrivateKeyWrapper(%p, %p)", javaKey, qBytes);
2585
2586 Unique_DSA dsa(DSA_new());
2587 if (dsa.get() == NULL) {
2588 jniThrowOutOfMemory(env, "Unable to allocate DSA key");
2589 return 0;
2590 }
2591
2592 if (!arrayToBignum(env, qBytes, &dsa->q)) {
2593 return 0;
2594 }
2595
2596 DSA_set_method(dsa.get(), &android_dsa_method);
2597 DSA_set_ex_data(dsa.get(), 0, env->NewGlobalRef(javaKey));
2598
2599 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2600 if (pkey.get() == NULL) {
2601 JNI_TRACE("getDSAPrivateKeyWrapper failed");
2602 jniThrowRuntimeException(env, "NativeCrypto_getDSAPrivateKeyWrapper failed");
2603 freeOpenSslErrorState();
2604 return 0;
2605 }
2606
2607 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
2608 jniThrowRuntimeException(env, "getDSAPrivateKeyWrapper failed");
2609 return 0;
2610 }
2611 OWNERSHIP_TRANSFERRED(dsa);
2612 return reinterpret_cast<uintptr_t>(pkey.release());
2613 }
2614
NativeCrypto_getECPrivateKeyWrapper(JNIEnv * env,jclass,jobject javaKey,jlong groupRef)2615 static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey, jlong groupRef) {
2616 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
2617 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
2618
2619 Unique_EC_KEY ecKey(EC_KEY_new());
2620 if (ecKey.get() == NULL) {
2621 jniThrowOutOfMemory(env, "Unable to allocate EC key");
2622 return 0;
2623 }
2624
2625 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
2626
2627 if (group == NULL) {
2628 JNI_TRACE("EC_GROUP_get_curve_name => group == NULL");
2629 jniThrowNullPointerException(env, "group == NULL");
2630 return 0;
2631 }
2632
2633 EC_KEY_set_group(ecKey.get(), group);
2634
2635 ECDSA_set_method(ecKey.get(), &android_ecdsa_method);
2636 ECDSA_set_ex_data(ecKey.get(), EcdsaGetExDataIndex(), env->NewGlobalRef(javaKey));
2637
2638 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2639 if (pkey.get() == NULL) {
2640 JNI_TRACE("getDSAPrivateKeyWrapper failed");
2641 jniThrowRuntimeException(env, "NativeCrypto_getDSAPrivateKeyWrapper failed");
2642 freeOpenSslErrorState();
2643 return 0;
2644 }
2645
2646 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
2647 jniThrowRuntimeException(env, "getECPrivateKeyWrapper failed");
2648 return 0;
2649 }
2650 OWNERSHIP_TRANSFERRED(ecKey);
2651 return reinterpret_cast<uintptr_t>(pkey.release());
2652 }
2653
2654 /*
2655 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
2656 */
NativeCrypto_RSA_generate_key_ex(JNIEnv * env,jclass,jint modulusBits,jbyteArray publicExponent)2657 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
2658 jbyteArray publicExponent) {
2659 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
2660
2661 BIGNUM* eRef = NULL;
2662 if (!arrayToBignum(env, publicExponent, &eRef)) {
2663 return 0;
2664 }
2665 Unique_BIGNUM e(eRef);
2666
2667 Unique_RSA rsa(RSA_new());
2668 if (rsa.get() == NULL) {
2669 jniThrowOutOfMemory(env, "Unable to allocate RSA key");
2670 return 0;
2671 }
2672
2673 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), NULL) < 0) {
2674 throwExceptionIfNecessary(env, "RSA_generate_key_ex");
2675 return 0;
2676 }
2677
2678 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2679 if (pkey.get() == NULL) {
2680 jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
2681 return 0;
2682 }
2683
2684 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
2685 jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
2686 return 0;
2687 }
2688
2689 OWNERSHIP_TRANSFERRED(rsa);
2690 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
2691 return reinterpret_cast<uintptr_t>(pkey.release());
2692 }
2693
NativeCrypto_RSA_size(JNIEnv * env,jclass,jlong pkeyRef)2694 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jlong pkeyRef) {
2695 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2696 JNI_TRACE("RSA_size(%p)", pkey);
2697
2698 if (pkey == NULL) {
2699 jniThrowNullPointerException(env, "pkey == null");
2700 return 0;
2701 }
2702
2703 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2704 if (rsa.get() == NULL) {
2705 jniThrowRuntimeException(env, "RSA_size failed");
2706 return 0;
2707 }
2708
2709 return static_cast<jint>(RSA_size(rsa.get()));
2710 }
2711
2712 typedef int RSACryptOperation(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
2713 int padding);
2714
RSA_crypt_operation(RSACryptOperation operation,const char * caller,JNIEnv * env,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jlong pkeyRef,jint padding)2715 static jint RSA_crypt_operation(RSACryptOperation operation,
2716 const char* caller __attribute__ ((unused)), JNIEnv* env, jint flen,
2717 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2718 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2719 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
2720
2721 if (pkey == NULL) {
2722 jniThrowNullPointerException(env, "pkey == null");
2723 return -1;
2724 }
2725
2726 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2727 if (rsa.get() == NULL) {
2728 return -1;
2729 }
2730
2731 ScopedByteArrayRO from(env, fromJavaBytes);
2732 if (from.get() == NULL) {
2733 return -1;
2734 }
2735
2736 ScopedByteArrayRW to(env, toJavaBytes);
2737 if (to.get() == NULL) {
2738 return -1;
2739 }
2740
2741 int resultSize = operation(static_cast<int>(flen),
2742 reinterpret_cast<const unsigned char*>(from.get()),
2743 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
2744 if (resultSize == -1) {
2745 JNI_TRACE("%s => failed", caller);
2746 throwExceptionIfNecessary(env, "RSA_crypt_operation");
2747 return -1;
2748 }
2749
2750 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
2751 resultSize);
2752 return static_cast<jint>(resultSize);
2753 }
2754
NativeCrypto_RSA_private_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jlong pkeyRef,jint padding)2755 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
2756 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2757 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__,
2758 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2759 }
NativeCrypto_RSA_public_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jlong pkeyRef,jint padding)2760 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
2761 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2762 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__,
2763 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2764 }
NativeCrypto_RSA_public_encrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jlong pkeyRef,jint padding)2765 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
2766 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2767 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__,
2768 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2769 }
NativeCrypto_RSA_private_decrypt(JNIEnv * env,jclass,jint flen,jbyteArray fromJavaBytes,jbyteArray toJavaBytes,jlong pkeyRef,jint padding)2770 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
2771 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) {
2772 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__,
2773 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
2774 }
2775
2776 /*
2777 * public static native byte[][] get_RSA_public_params(long);
2778 */
NativeCrypto_get_RSA_public_params(JNIEnv * env,jclass,jlong pkeyRef)2779 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jlong pkeyRef) {
2780 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2781 JNI_TRACE("get_RSA_public_params(%p)", pkey);
2782
2783 if (pkey == NULL) {
2784 jniThrowNullPointerException(env, "pkey == null");
2785 return 0;
2786 }
2787
2788 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2789 if (rsa.get() == NULL) {
2790 throwExceptionIfNecessary(env, "get_RSA_public_params failed");
2791 return 0;
2792 }
2793
2794 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
2795 if (joa == NULL) {
2796 return NULL;
2797 }
2798
2799 jbyteArray n = bignumToArray(env, rsa->n, "n");
2800 if (env->ExceptionCheck()) {
2801 return NULL;
2802 }
2803 env->SetObjectArrayElement(joa, 0, n);
2804
2805 jbyteArray e = bignumToArray(env, rsa->e, "e");
2806 if (env->ExceptionCheck()) {
2807 return NULL;
2808 }
2809 env->SetObjectArrayElement(joa, 1, e);
2810
2811 return joa;
2812 }
2813
2814 /*
2815 * public static native byte[][] get_RSA_private_params(long);
2816 */
NativeCrypto_get_RSA_private_params(JNIEnv * env,jclass,jlong pkeyRef)2817 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jlong pkeyRef) {
2818 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2819 JNI_TRACE("get_RSA_public_params(%p)", pkey);
2820
2821 if (pkey == NULL) {
2822 jniThrowNullPointerException(env, "pkey == null");
2823 return 0;
2824 }
2825
2826 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
2827 if (rsa.get() == NULL) {
2828 throwExceptionIfNecessary(env, "get_RSA_public_params failed");
2829 return 0;
2830 }
2831
2832 jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL);
2833 if (joa == NULL) {
2834 return NULL;
2835 }
2836
2837 jbyteArray n = bignumToArray(env, rsa->n, "n");
2838 if (env->ExceptionCheck()) {
2839 return NULL;
2840 }
2841 env->SetObjectArrayElement(joa, 0, n);
2842
2843 if (rsa->e != NULL) {
2844 jbyteArray e = bignumToArray(env, rsa->e, "e");
2845 if (env->ExceptionCheck()) {
2846 return NULL;
2847 }
2848 env->SetObjectArrayElement(joa, 1, e);
2849 }
2850
2851 if (rsa->d != NULL) {
2852 jbyteArray d = bignumToArray(env, rsa->d, "d");
2853 if (env->ExceptionCheck()) {
2854 return NULL;
2855 }
2856 env->SetObjectArrayElement(joa, 2, d);
2857 }
2858
2859 if (rsa->p != NULL) {
2860 jbyteArray p = bignumToArray(env, rsa->p, "p");
2861 if (env->ExceptionCheck()) {
2862 return NULL;
2863 }
2864 env->SetObjectArrayElement(joa, 3, p);
2865 }
2866
2867 if (rsa->q != NULL) {
2868 jbyteArray q = bignumToArray(env, rsa->q, "q");
2869 if (env->ExceptionCheck()) {
2870 return NULL;
2871 }
2872 env->SetObjectArrayElement(joa, 4, q);
2873 }
2874
2875 if (rsa->dmp1 != NULL) {
2876 jbyteArray dmp1 = bignumToArray(env, rsa->dmp1, "dmp1");
2877 if (env->ExceptionCheck()) {
2878 return NULL;
2879 }
2880 env->SetObjectArrayElement(joa, 5, dmp1);
2881 }
2882
2883 if (rsa->dmq1 != NULL) {
2884 jbyteArray dmq1 = bignumToArray(env, rsa->dmq1, "dmq1");
2885 if (env->ExceptionCheck()) {
2886 return NULL;
2887 }
2888 env->SetObjectArrayElement(joa, 6, dmq1);
2889 }
2890
2891 if (rsa->iqmp != NULL) {
2892 jbyteArray iqmp = bignumToArray(env, rsa->iqmp, "iqmp");
2893 if (env->ExceptionCheck()) {
2894 return NULL;
2895 }
2896 env->SetObjectArrayElement(joa, 7, iqmp);
2897 }
2898
2899 return joa;
2900 }
2901
2902 /*
2903 * public static native int DSA_generate_key(int, byte[], byte[], byte[], byte[]);
2904 */
NativeCrypto_DSA_generate_key(JNIEnv * env,jclass,jint primeBits,jbyteArray seedJavaBytes,jbyteArray gBytes,jbyteArray pBytes,jbyteArray qBytes)2905 static jlong NativeCrypto_DSA_generate_key(JNIEnv* env, jclass, jint primeBits,
2906 jbyteArray seedJavaBytes, jbyteArray gBytes, jbyteArray pBytes, jbyteArray qBytes) {
2907 JNI_TRACE("DSA_generate_key(%d, %p, %p, %p, %p)", primeBits, seedJavaBytes,
2908 gBytes, pBytes, qBytes);
2909
2910 UniquePtr<unsigned char[]> seedPtr;
2911 unsigned long seedSize = 0;
2912 if (seedJavaBytes != NULL) {
2913 ScopedByteArrayRO seed(env, seedJavaBytes);
2914 if (seed.get() == NULL) {
2915 return 0;
2916 }
2917
2918 seedSize = seed.size();
2919 seedPtr.reset(new unsigned char[seedSize]);
2920
2921 memcpy(seedPtr.get(), seed.get(), seedSize);
2922 }
2923
2924 Unique_DSA dsa(DSA_new());
2925 if (dsa.get() == NULL) {
2926 JNI_TRACE("DSA_generate_key failed");
2927 jniThrowOutOfMemory(env, "Unable to allocate DSA key");
2928 freeOpenSslErrorState();
2929 return 0;
2930 }
2931
2932 if (gBytes != NULL && pBytes != NULL && qBytes != NULL) {
2933 JNI_TRACE("DSA_generate_key parameters specified");
2934
2935 if (!arrayToBignum(env, gBytes, &dsa->g)) {
2936 return 0;
2937 }
2938
2939 if (!arrayToBignum(env, pBytes, &dsa->p)) {
2940 return 0;
2941 }
2942
2943 if (!arrayToBignum(env, qBytes, &dsa->q)) {
2944 return 0;
2945 }
2946 } else {
2947 JNI_TRACE("DSA_generate_key generating parameters");
2948
2949 if (!DSA_generate_parameters_ex(dsa.get(), primeBits, seedPtr.get(), seedSize, NULL, NULL, NULL)) {
2950 JNI_TRACE("DSA_generate_key => param generation failed");
2951 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_parameters_ex failed");
2952 return 0;
2953 }
2954 }
2955
2956 if (!DSA_generate_key(dsa.get())) {
2957 JNI_TRACE("DSA_generate_key failed");
2958 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed");
2959 return 0;
2960 }
2961
2962 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2963 if (pkey.get() == NULL) {
2964 JNI_TRACE("DSA_generate_key failed");
2965 jniThrowRuntimeException(env, "NativeCrypto_DSA_generate_key failed");
2966 freeOpenSslErrorState();
2967 return 0;
2968 }
2969
2970 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
2971 JNI_TRACE("DSA_generate_key failed");
2972 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed");
2973 return 0;
2974 }
2975
2976 OWNERSHIP_TRANSFERRED(dsa);
2977 JNI_TRACE("DSA_generate_key(n=%d, e=%p) => %p", primeBits, seedPtr.get(), pkey.get());
2978 return reinterpret_cast<uintptr_t>(pkey.release());
2979 }
2980
2981 /*
2982 * public static native byte[][] get_DSA_params(long);
2983 */
NativeCrypto_get_DSA_params(JNIEnv * env,jclass,jlong pkeyRef)2984 static jobjectArray NativeCrypto_get_DSA_params(JNIEnv* env, jclass, jlong pkeyRef) {
2985 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2986 JNI_TRACE("get_DSA_params(%p)", pkey);
2987
2988 if (pkey == NULL) {
2989 jniThrowNullPointerException(env, "pkey == null");
2990 return NULL;
2991 }
2992
2993 Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
2994 if (dsa.get() == NULL) {
2995 throwExceptionIfNecessary(env, "get_DSA_params failed");
2996 return 0;
2997 }
2998
2999 jobjectArray joa = env->NewObjectArray(5, byteArrayClass, NULL);
3000 if (joa == NULL) {
3001 return NULL;
3002 }
3003
3004 if (dsa->g != NULL) {
3005 jbyteArray g = bignumToArray(env, dsa->g, "g");
3006 if (env->ExceptionCheck()) {
3007 return NULL;
3008 }
3009 env->SetObjectArrayElement(joa, 0, g);
3010 }
3011
3012 if (dsa->p != NULL) {
3013 jbyteArray p = bignumToArray(env, dsa->p, "p");
3014 if (env->ExceptionCheck()) {
3015 return NULL;
3016 }
3017 env->SetObjectArrayElement(joa, 1, p);
3018 }
3019
3020 if (dsa->q != NULL) {
3021 jbyteArray q = bignumToArray(env, dsa->q, "q");
3022 if (env->ExceptionCheck()) {
3023 return NULL;
3024 }
3025 env->SetObjectArrayElement(joa, 2, q);
3026 }
3027
3028 if (dsa->pub_key != NULL) {
3029 jbyteArray pub_key = bignumToArray(env, dsa->pub_key, "pub_key");
3030 if (env->ExceptionCheck()) {
3031 return NULL;
3032 }
3033 env->SetObjectArrayElement(joa, 3, pub_key);
3034 }
3035
3036 if (dsa->priv_key != NULL) {
3037 jbyteArray priv_key = bignumToArray(env, dsa->priv_key, "priv_key");
3038 if (env->ExceptionCheck()) {
3039 return NULL;
3040 }
3041 env->SetObjectArrayElement(joa, 4, priv_key);
3042 }
3043
3044 return joa;
3045 }
3046
NativeCrypto_set_DSA_flag_nonce_from_hash(JNIEnv * env,jclass,jlong pkeyRef)3047 static void NativeCrypto_set_DSA_flag_nonce_from_hash(JNIEnv* env, jclass, jlong pkeyRef)
3048 {
3049 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3050 JNI_TRACE("set_DSA_flag_nonce_from_hash(%p)", pkey);
3051
3052 if (pkey == NULL) {
3053 jniThrowNullPointerException(env, "pkey == null");
3054 return;
3055 }
3056
3057 Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
3058 if (dsa.get() == NULL) {
3059 throwExceptionIfNecessary(env, "set_DSA_flag_nonce_from_hash failed");
3060 return;
3061 }
3062
3063 dsa->flags |= DSA_FLAG_NONCE_FROM_HASH;
3064 }
3065
NativeCrypto_DH_generate_parameters_ex(JNIEnv * env,jclass,jint primeBits,jlong generator)3066 static jlong NativeCrypto_DH_generate_parameters_ex(JNIEnv* env, jclass, jint primeBits, jlong generator) {
3067 JNI_TRACE("DH_generate_parameters_ex(%d, %lld)", primeBits, (long long) generator);
3068
3069 Unique_DH dh(DH_new());
3070 if (dh.get() == NULL) {
3071 JNI_TRACE("DH_generate_parameters_ex failed");
3072 jniThrowOutOfMemory(env, "Unable to allocate DH key");
3073 freeOpenSslErrorState();
3074 return 0;
3075 }
3076
3077 JNI_TRACE("DH_generate_parameters_ex generating parameters");
3078
3079 if (!DH_generate_parameters_ex(dh.get(), primeBits, generator, NULL)) {
3080 JNI_TRACE("DH_generate_parameters_ex => param generation failed");
3081 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_parameters_ex failed");
3082 return 0;
3083 }
3084
3085 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3086 if (pkey.get() == NULL) {
3087 JNI_TRACE("DH_generate_parameters_ex failed");
3088 jniThrowRuntimeException(env, "NativeCrypto_DH_generate_parameters_ex failed");
3089 freeOpenSslErrorState();
3090 return 0;
3091 }
3092
3093 if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
3094 JNI_TRACE("DH_generate_parameters_ex failed");
3095 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_parameters_ex failed");
3096 return 0;
3097 }
3098
3099 OWNERSHIP_TRANSFERRED(dh);
3100 JNI_TRACE("DH_generate_parameters_ex(n=%d, g=%lld) => %p", primeBits, (long long) generator,
3101 pkey.get());
3102 return reinterpret_cast<uintptr_t>(pkey.release());
3103 }
3104
NativeCrypto_DH_generate_key(JNIEnv * env,jclass,jlong pkeyRef)3105 static void NativeCrypto_DH_generate_key(JNIEnv* env, jclass, jlong pkeyRef) {
3106 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3107 JNI_TRACE("DH_generate_key(%p)", pkey);
3108
3109 if (pkey == NULL) {
3110 jniThrowNullPointerException(env, "pkey == null");
3111 }
3112
3113 Unique_DH dh(EVP_PKEY_get1_DH(pkey));
3114 if (dh.get() == NULL) {
3115 JNI_TRACE("DH_generate_key failed");
3116 throwExceptionIfNecessary(env, "Unable to get DH key");
3117 freeOpenSslErrorState();
3118 }
3119
3120 if (!DH_generate_key(dh.get())) {
3121 JNI_TRACE("DH_generate_key failed");
3122 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_key failed");
3123 }
3124 }
3125
NativeCrypto_get_DH_params(JNIEnv * env,jclass,jlong pkeyRef)3126 static jobjectArray NativeCrypto_get_DH_params(JNIEnv* env, jclass, jlong pkeyRef) {
3127 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3128 JNI_TRACE("get_DH_params(%p)", pkey);
3129
3130 if (pkey == NULL) {
3131 jniThrowNullPointerException(env, "pkey == null");
3132 return NULL;
3133 }
3134
3135 Unique_DH dh(EVP_PKEY_get1_DH(pkey));
3136 if (dh.get() == NULL) {
3137 throwExceptionIfNecessary(env, "get_DH_params failed");
3138 return 0;
3139 }
3140
3141 jobjectArray joa = env->NewObjectArray(4, byteArrayClass, NULL);
3142 if (joa == NULL) {
3143 return NULL;
3144 }
3145
3146 if (dh->p != NULL) {
3147 jbyteArray p = bignumToArray(env, dh->p, "p");
3148 if (env->ExceptionCheck()) {
3149 return NULL;
3150 }
3151 env->SetObjectArrayElement(joa, 0, p);
3152 }
3153
3154 if (dh->g != NULL) {
3155 jbyteArray g = bignumToArray(env, dh->g, "g");
3156 if (env->ExceptionCheck()) {
3157 return NULL;
3158 }
3159 env->SetObjectArrayElement(joa, 1, g);
3160 }
3161
3162 if (dh->pub_key != NULL) {
3163 jbyteArray pub_key = bignumToArray(env, dh->pub_key, "pub_key");
3164 if (env->ExceptionCheck()) {
3165 return NULL;
3166 }
3167 env->SetObjectArrayElement(joa, 2, pub_key);
3168 }
3169
3170 if (dh->priv_key != NULL) {
3171 jbyteArray priv_key = bignumToArray(env, dh->priv_key, "priv_key");
3172 if (env->ExceptionCheck()) {
3173 return NULL;
3174 }
3175 env->SetObjectArrayElement(joa, 3, priv_key);
3176 }
3177
3178 return joa;
3179 }
3180
3181 #define EC_CURVE_GFP 1
3182 #define EC_CURVE_GF2M 2
3183
3184 /**
3185 * Return group type or 0 if unknown group.
3186 * EC_GROUP_GFP or EC_GROUP_GF2M
3187 */
get_EC_GROUP_type(const EC_GROUP * group)3188 static int get_EC_GROUP_type(const EC_GROUP* group)
3189 {
3190 const EC_METHOD* method = EC_GROUP_method_of(group);
3191 if (method == EC_GFp_nist_method()
3192 || method == EC_GFp_mont_method()
3193 || method == EC_GFp_simple_method()) {
3194 return EC_CURVE_GFP;
3195 } else if (method == EC_GF2m_simple_method()) {
3196 return EC_CURVE_GF2M;
3197 }
3198
3199 return 0;
3200 }
3201
NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv * env,jclass,jstring curveNameJava)3202 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava)
3203 {
3204 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
3205
3206 ScopedUtfChars curveName(env, curveNameJava);
3207 if (curveName.c_str() == NULL) {
3208 return 0;
3209 }
3210 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
3211
3212 int nid = OBJ_sn2nid(curveName.c_str());
3213 if (nid == NID_undef) {
3214 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
3215 return 0;
3216 }
3217
3218 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
3219 if (group == NULL) {
3220 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
3221 freeOpenSslErrorState();
3222 return 0;
3223 }
3224
3225 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
3226 return reinterpret_cast<uintptr_t>(group);
3227 }
3228
NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv * env,jclass,jlong groupRef,jint flag)3229 static void NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv* env, jclass, jlong groupRef,
3230 jint flag)
3231 {
3232 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
3233 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d)", group, flag);
3234
3235 if (group == NULL) {
3236 JNI_TRACE("EC_GROUP_set_asn1_flag => group == NULL");
3237 jniThrowNullPointerException(env, "group == NULL");
3238 return;
3239 }
3240
3241 EC_GROUP_set_asn1_flag(group, flag);
3242 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d) => success", group, flag);
3243 }
3244
NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv * env,jclass,jlong groupRef,jint form)3245 static void NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv* env, jclass,
3246 jlong groupRef, jint form)
3247 {
3248 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
3249 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d)", group, form);
3250
3251 if (group == NULL) {
3252 JNI_TRACE("EC_GROUP_set_point_conversion_form => group == NULL");
3253 jniThrowNullPointerException(env, "group == NULL");
3254 return;
3255 }
3256
3257 EC_GROUP_set_point_conversion_form(group, static_cast<point_conversion_form_t>(form));
3258 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d) => success", group, form);
3259 }
3260
NativeCrypto_EC_GROUP_new_curve(JNIEnv * env,jclass,jint type,jbyteArray pJava,jbyteArray aJava,jbyteArray bJava)3261 static jlong NativeCrypto_EC_GROUP_new_curve(JNIEnv* env, jclass, jint type, jbyteArray pJava,
3262 jbyteArray aJava, jbyteArray bJava)
3263 {
3264 JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p)", type, pJava, aJava, bJava);
3265
3266 BIGNUM* pRef = NULL;
3267 if (!arrayToBignum(env, pJava, &pRef)) {
3268 return 0;
3269 }
3270 Unique_BIGNUM p(pRef);
3271
3272 BIGNUM* aRef = NULL;
3273 if (!arrayToBignum(env, aJava, &aRef)) {
3274 return 0;
3275 }
3276 Unique_BIGNUM a(aRef);
3277
3278 BIGNUM* bRef = NULL;
3279 if (!arrayToBignum(env, bJava, &bRef)) {
3280 return 0;
3281 }
3282 Unique_BIGNUM b(bRef);
3283
3284 EC_GROUP* group;
3285 switch (type) {
3286 case EC_CURVE_GFP:
3287 group = EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), (BN_CTX*) NULL);
3288 break;
3289 case EC_CURVE_GF2M:
3290 group = EC_GROUP_new_curve_GF2m(p.get(), a.get(), b.get(), (BN_CTX*) NULL);
3291 break;
3292 default:
3293 jniThrowRuntimeException(env, "invalid group");
3294 return 0;
3295 }
3296
3297 if (group == NULL) {
3298 throwExceptionIfNecessary(env, "EC_GROUP_new_curve");
3299 }
3300
3301 JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p) => %p", type, pJava, aJava, bJava, group);
3302 return reinterpret_cast<uintptr_t>(group);
3303 }
3304
NativeCrypto_EC_GROUP_dup(JNIEnv * env,jclass,jlong groupRef)3305 static jlong NativeCrypto_EC_GROUP_dup(JNIEnv* env, jclass, jlong groupRef) {
3306 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3307 JNI_TRACE("EC_GROUP_dup(%p)", group);
3308
3309 if (group == NULL) {
3310 JNI_TRACE("EC_GROUP_dup => group == NULL");
3311 jniThrowNullPointerException(env, "group == NULL");
3312 return 0;
3313 }
3314
3315 EC_GROUP* groupDup = EC_GROUP_dup(group);
3316 JNI_TRACE("EC_GROUP_dup(%p) => %p", group, groupDup);
3317 return reinterpret_cast<uintptr_t>(groupDup);
3318 }
3319
NativeCrypto_EC_GROUP_get_curve_name(JNIEnv * env,jclass,jlong groupRef)3320 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jlong groupRef) {
3321 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3322 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
3323
3324 if (group == NULL) {
3325 JNI_TRACE("EC_GROUP_get_curve_name => group == NULL");
3326 jniThrowNullPointerException(env, "group == NULL");
3327 return 0;
3328 }
3329
3330 int nid = EC_GROUP_get_curve_name(group);
3331 if (nid == NID_undef) {
3332 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
3333 return NULL;
3334 }
3335
3336 const char* shortName = OBJ_nid2sn(nid);
3337 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
3338 return env->NewStringUTF(shortName);
3339 }
3340
NativeCrypto_EC_GROUP_get_curve(JNIEnv * env,jclass,jlong groupRef)3341 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jlong groupRef)
3342 {
3343 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3344 JNI_TRACE("EC_GROUP_get_curve(%p)", group);
3345
3346 Unique_BIGNUM p(BN_new());
3347 Unique_BIGNUM a(BN_new());
3348 Unique_BIGNUM b(BN_new());
3349
3350 int ret;
3351 switch (get_EC_GROUP_type(group)) {
3352 case EC_CURVE_GFP:
3353 ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), (BN_CTX*) NULL);
3354 break;
3355 case EC_CURVE_GF2M:
3356 ret = EC_GROUP_get_curve_GF2m(group, p.get(), a.get(), b.get(), (BN_CTX*)NULL);
3357 break;
3358 default:
3359 jniThrowRuntimeException(env, "invalid group");
3360 return NULL;
3361 }
3362 if (ret != 1) {
3363 throwExceptionIfNecessary(env, "EC_GROUP_get_curve");
3364 return NULL;
3365 }
3366
3367 jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL);
3368 if (joa == NULL) {
3369 return NULL;
3370 }
3371
3372 jbyteArray pArray = bignumToArray(env, p.get(), "p");
3373 if (env->ExceptionCheck()) {
3374 return NULL;
3375 }
3376 env->SetObjectArrayElement(joa, 0, pArray);
3377
3378 jbyteArray aArray = bignumToArray(env, a.get(), "a");
3379 if (env->ExceptionCheck()) {
3380 return NULL;
3381 }
3382 env->SetObjectArrayElement(joa, 1, aArray);
3383
3384 jbyteArray bArray = bignumToArray(env, b.get(), "b");
3385 if (env->ExceptionCheck()) {
3386 return NULL;
3387 }
3388 env->SetObjectArrayElement(joa, 2, bArray);
3389
3390 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
3391 return joa;
3392 }
3393
NativeCrypto_EC_GROUP_get_order(JNIEnv * env,jclass,jlong groupRef)3394 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jlong groupRef)
3395 {
3396 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3397 JNI_TRACE("EC_GROUP_get_order(%p)", group);
3398
3399 Unique_BIGNUM order(BN_new());
3400 if (order.get() == NULL) {
3401 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
3402 jniThrowOutOfMemory(env, "BN_new");
3403 return NULL;
3404 }
3405
3406 if (EC_GROUP_get_order(group, order.get(), NULL) != 1) {
3407 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
3408 throwExceptionIfNecessary(env, "EC_GROUP_get_order");
3409 return NULL;
3410 }
3411
3412 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
3413 if (env->ExceptionCheck()) {
3414 return NULL;
3415 }
3416
3417 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
3418 return orderArray;
3419 }
3420
NativeCrypto_EC_GROUP_get_degree(JNIEnv * env,jclass,jlong groupRef)3421 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jlong groupRef)
3422 {
3423 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3424 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
3425
3426 jint degree = EC_GROUP_get_degree(group);
3427 if (degree == 0) {
3428 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
3429 jniThrowRuntimeException(env, "not supported");
3430 return 0;
3431 }
3432
3433 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
3434 return degree;
3435 }
3436
NativeCrypto_EC_GROUP_get_cofactor(JNIEnv * env,jclass,jlong groupRef)3437 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jlong groupRef)
3438 {
3439 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3440 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
3441
3442 Unique_BIGNUM cofactor(BN_new());
3443 if (cofactor.get() == NULL) {
3444 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
3445 jniThrowOutOfMemory(env, "BN_new");
3446 return NULL;
3447 }
3448
3449 if (EC_GROUP_get_cofactor(group, cofactor.get(), NULL) != 1) {
3450 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
3451 throwExceptionIfNecessary(env, "EC_GROUP_get_cofactor");
3452 return NULL;
3453 }
3454
3455 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
3456 if (env->ExceptionCheck()) {
3457 return NULL;
3458 }
3459
3460 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
3461 return cofactorArray;
3462 }
3463
NativeCrypto_get_EC_GROUP_type(JNIEnv * env,jclass,jlong groupRef)3464 static jint NativeCrypto_get_EC_GROUP_type(JNIEnv* env, jclass, jlong groupRef)
3465 {
3466 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3467 JNI_TRACE("get_EC_GROUP_type(%p)", group);
3468
3469 int type = get_EC_GROUP_type(group);
3470 if (type == 0) {
3471 JNI_TRACE("get_EC_GROUP_type(%p) => curve type", group);
3472 jniThrowRuntimeException(env, "unknown curve type");
3473 } else {
3474 JNI_TRACE("get_EC_GROUP_type(%p) => %d", group, type);
3475 }
3476 return type;
3477 }
3478
NativeCrypto_EC_GROUP_clear_free(JNIEnv * env,jclass,jlong groupRef)3479 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef)
3480 {
3481 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
3482 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
3483
3484 if (group == NULL) {
3485 JNI_TRACE("EC_GROUP_clear_free => group == NULL");
3486 jniThrowNullPointerException(env, "group == NULL");
3487 return;
3488 }
3489
3490 EC_GROUP_clear_free(group);
3491 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
3492 }
3493
NativeCrypto_EC_GROUP_cmp(JNIEnv * env,jclass,jlong group1Ref,jlong group2Ref)3494 static jboolean NativeCrypto_EC_GROUP_cmp(JNIEnv* env, jclass, jlong group1Ref, jlong group2Ref)
3495 {
3496 const EC_GROUP* group1 = reinterpret_cast<const EC_GROUP*>(group1Ref);
3497 const EC_GROUP* group2 = reinterpret_cast<const EC_GROUP*>(group2Ref);
3498 JNI_TRACE("EC_GROUP_cmp(%p, %p)", group1, group2);
3499
3500 if (group1 == NULL || group2 == NULL) {
3501 JNI_TRACE("EC_GROUP_cmp(%p, %p) => group1 == null || group2 == null", group1, group2);
3502 jniThrowNullPointerException(env, "group1 == null || group2 == null");
3503 return false;
3504 }
3505
3506 int ret = EC_GROUP_cmp(group1, group2, (BN_CTX*)NULL);
3507
3508 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", group1, group2, ret);
3509 return ret == 0;
3510 }
3511
NativeCrypto_EC_GROUP_set_generator(JNIEnv * env,jclass,jlong groupRef,jlong pointRef,jbyteArray njavaBytes,jbyteArray hjavaBytes)3512 static void NativeCrypto_EC_GROUP_set_generator(JNIEnv* env, jclass, jlong groupRef, jlong pointRef, jbyteArray njavaBytes, jbyteArray hjavaBytes)
3513 {
3514 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
3515 const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef);
3516 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p)", group, point, njavaBytes, hjavaBytes);
3517
3518 if (group == NULL || point == NULL) {
3519 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => group == null || point == null",
3520 group, point, njavaBytes, hjavaBytes);
3521 jniThrowNullPointerException(env, "group == null || point == null");
3522 return;
3523 }
3524
3525 BIGNUM* nRef = NULL;
3526 if (!arrayToBignum(env, njavaBytes, &nRef)) {
3527 return;
3528 }
3529 Unique_BIGNUM n(nRef);
3530
3531 BIGNUM* hRef = NULL;
3532 if (!arrayToBignum(env, hjavaBytes, &hRef)) {
3533 return;
3534 }
3535 Unique_BIGNUM h(hRef);
3536
3537 int ret = EC_GROUP_set_generator(group, point, n.get(), h.get());
3538 if (ret == 0) {
3539 throwExceptionIfNecessary(env, "EC_GROUP_set_generator");
3540 }
3541
3542 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => %d", group, point, njavaBytes, hjavaBytes, ret);
3543 }
3544
NativeCrypto_EC_GROUP_get_generator(JNIEnv * env,jclass,jlong groupRef)3545 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jlong groupRef)
3546 {
3547 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3548 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
3549
3550 if (group == NULL) {
3551 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
3552 jniThrowNullPointerException(env, "group == null");
3553 return 0;
3554 }
3555
3556 const EC_POINT* generator = EC_GROUP_get0_generator(group);
3557
3558 Unique_EC_POINT dup(EC_POINT_dup(generator, group));
3559 if (dup.get() == NULL) {
3560 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
3561 jniThrowOutOfMemory(env, "unable to dupe generator");
3562 return 0;
3563 }
3564
3565 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
3566 return reinterpret_cast<uintptr_t>(dup.release());
3567 }
3568
NativeCrypto_EC_POINT_new(JNIEnv * env,jclass,jlong groupRef)3569 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jlong groupRef)
3570 {
3571 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3572 JNI_TRACE("EC_POINT_new(%p)", group);
3573
3574 if (group == NULL) {
3575 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
3576 jniThrowNullPointerException(env, "group == null");
3577 return 0;
3578 }
3579
3580 EC_POINT* point = EC_POINT_new(group);
3581 if (point == NULL) {
3582 jniThrowOutOfMemory(env, "Unable create an EC_POINT");
3583 return 0;
3584 }
3585
3586 return reinterpret_cast<uintptr_t>(point);
3587 }
3588
NativeCrypto_EC_POINT_clear_free(JNIEnv * env,jclass,jlong groupRef)3589 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
3590 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
3591 JNI_TRACE("EC_POINT_clear_free(%p)", group);
3592
3593 if (group == NULL) {
3594 JNI_TRACE("EC_POINT_clear_free => group == NULL");
3595 jniThrowNullPointerException(env, "group == NULL");
3596 return;
3597 }
3598
3599 EC_POINT_clear_free(group);
3600 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
3601 }
3602
NativeCrypto_EC_POINT_cmp(JNIEnv * env,jclass,jlong groupRef,jlong point1Ref,jlong point2Ref)3603 static jboolean NativeCrypto_EC_POINT_cmp(JNIEnv* env, jclass, jlong groupRef, jlong point1Ref, jlong point2Ref)
3604 {
3605 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3606 const EC_POINT* point1 = reinterpret_cast<const EC_POINT*>(point1Ref);
3607 const EC_POINT* point2 = reinterpret_cast<const EC_POINT*>(point2Ref);
3608 JNI_TRACE("EC_POINT_cmp(%p, %p, %p)", group, point1, point2);
3609
3610 if (group == NULL || point1 == NULL || point2 == NULL) {
3611 JNI_TRACE("EC_POINT_cmp(%p, %p, %p) => group == null || point1 == null || point2 == null",
3612 group, point1, point2);
3613 jniThrowNullPointerException(env, "group == null || point1 == null || point2 == null");
3614 return false;
3615 }
3616
3617 int ret = EC_POINT_cmp(group, point1, point2, (BN_CTX*)NULL);
3618
3619 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", point1, point2, ret);
3620 return ret == 0;
3621 }
3622
NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv * env,jclass,jlong groupRef,jlong pointRef,jbyteArray xjavaBytes,jbyteArray yjavaBytes)3623 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass,
3624 jlong groupRef, jlong pointRef, jbyteArray xjavaBytes, jbyteArray yjavaBytes)
3625 {
3626 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3627 EC_POINT* point = reinterpret_cast<EC_POINT*>(pointRef);
3628 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", group, point, xjavaBytes,
3629 yjavaBytes);
3630
3631 if (group == NULL || point == NULL) {
3632 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => group == null || point == null",
3633 group, point, xjavaBytes, yjavaBytes);
3634 jniThrowNullPointerException(env, "group == null || point == null");
3635 return;
3636 }
3637
3638 BIGNUM* xRef = NULL;
3639 if (!arrayToBignum(env, xjavaBytes, &xRef)) {
3640 return;
3641 }
3642 Unique_BIGNUM x(xRef);
3643
3644 BIGNUM* yRef = NULL;
3645 if (!arrayToBignum(env, yjavaBytes, &yRef)) {
3646 return;
3647 }
3648 Unique_BIGNUM y(yRef);
3649
3650 int ret;
3651 switch (get_EC_GROUP_type(group)) {
3652 case EC_CURVE_GFP:
3653 ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
3654 break;
3655 case EC_CURVE_GF2M:
3656 ret = EC_POINT_set_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL);
3657 break;
3658 default:
3659 jniThrowRuntimeException(env, "invalid curve type");
3660 return;
3661 }
3662
3663 if (ret != 1) {
3664 throwExceptionIfNecessary(env, "EC_POINT_set_affine_coordinates");
3665 }
3666
3667 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point,
3668 xjavaBytes, yjavaBytes, ret);
3669 }
3670
NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv * env,jclass,jlong groupRef,jlong pointRef)3671 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass, jlong groupRef,
3672 jlong pointRef)
3673 {
3674 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3675 const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef);
3676 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
3677
3678 Unique_BIGNUM x(BN_new());
3679 Unique_BIGNUM y(BN_new());
3680
3681 int ret;
3682 switch (get_EC_GROUP_type(group)) {
3683 case EC_CURVE_GFP:
3684 ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
3685 break;
3686 case EC_CURVE_GF2M:
3687 ret = EC_POINT_get_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL);
3688 break;
3689 default:
3690 jniThrowRuntimeException(env, "invalid curve type");
3691 return NULL;
3692 }
3693 if (ret != 1) {
3694 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
3695 throwExceptionIfNecessary(env, "EC_POINT_get_affine_coordinates");
3696 return NULL;
3697 }
3698
3699 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
3700 if (joa == NULL) {
3701 return NULL;
3702 }
3703
3704 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
3705 if (env->ExceptionCheck()) {
3706 return NULL;
3707 }
3708 env->SetObjectArrayElement(joa, 0, xBytes);
3709
3710 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
3711 if (env->ExceptionCheck()) {
3712 return NULL;
3713 }
3714 env->SetObjectArrayElement(joa, 1, yBytes);
3715
3716 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
3717 return joa;
3718 }
3719
NativeCrypto_EC_KEY_generate_key(JNIEnv * env,jclass,jlong groupRef)3720 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jlong groupRef)
3721 {
3722 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
3723 JNI_TRACE("EC_KEY_generate_key(%p)", group);
3724
3725 Unique_EC_KEY eckey(EC_KEY_new());
3726 if (eckey.get() == NULL) {
3727 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
3728 jniThrowOutOfMemory(env, "Unable to create an EC_KEY");
3729 return 0;
3730 }
3731
3732 if (EC_KEY_set_group(eckey.get(), group) != 1) {
3733 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
3734 throwExceptionIfNecessary(env, "EC_KEY_set_group");
3735 return 0;
3736 }
3737
3738 if (EC_KEY_generate_key(eckey.get()) != 1) {
3739 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
3740 throwExceptionIfNecessary(env, "EC_KEY_set_group");
3741 return 0;
3742 }
3743
3744 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3745 if (pkey.get() == NULL) {
3746 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
3747 throwExceptionIfNecessary(env, "EC_KEY_generate_key");
3748 return 0;
3749 }
3750 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
3751 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
3752 return 0;
3753 }
3754 OWNERSHIP_TRANSFERRED(eckey);
3755
3756 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
3757 return reinterpret_cast<uintptr_t>(pkey.release());
3758 }
3759
NativeCrypto_EC_KEY_get0_group(JNIEnv * env,jclass,jlong pkeyRef)3760 static jlong NativeCrypto_EC_KEY_get0_group(JNIEnv* env, jclass, jlong pkeyRef)
3761 {
3762 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3763 JNI_TRACE("EC_KEY_get0_group(%p)", pkey);
3764
3765 if (pkey == NULL) {
3766 jniThrowNullPointerException(env, "pkey == null");
3767 JNI_TRACE("EC_KEY_get0_group(%p) => pkey == null", pkey);
3768 return 0;
3769 }
3770
3771 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
3772 jniThrowRuntimeException(env, "not EC key");
3773 JNI_TRACE("EC_KEY_get0_group(%p) => not EC key (type == %d)", pkey,
3774 EVP_PKEY_type(pkey->type));
3775 return 0;
3776 }
3777
3778 const EC_GROUP* group = EC_KEY_get0_group(pkey->pkey.ec);
3779 JNI_TRACE("EC_KEY_get0_group(%p) => %p", pkey, group);
3780 return reinterpret_cast<uintptr_t>(group);
3781 }
3782
NativeCrypto_EC_KEY_get_private_key(JNIEnv * env,jclass,jlong pkeyRef)3783 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jlong pkeyRef)
3784 {
3785 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3786 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
3787
3788 if (pkey == NULL) {
3789 jniThrowNullPointerException(env, "pkey == null");
3790 return NULL;
3791 }
3792
3793 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3794 if (eckey.get() == NULL) {
3795 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3796 return NULL;
3797 }
3798
3799 const BIGNUM *privkey = EC_KEY_get0_private_key(eckey.get());
3800
3801 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
3802 if (env->ExceptionCheck()) {
3803 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
3804 return NULL;
3805 }
3806
3807 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
3808 return privBytes;
3809 }
3810
NativeCrypto_EC_KEY_get_public_key(JNIEnv * env,jclass,jlong pkeyRef)3811 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jlong pkeyRef)
3812 {
3813 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3814 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
3815
3816 if (pkey == NULL) {
3817 jniThrowNullPointerException(env, "pkey == null");
3818 return 0;
3819 }
3820
3821 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3822 if (eckey.get() == NULL) {
3823 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3824 return 0;
3825 }
3826
3827 Unique_EC_POINT dup(EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()),
3828 EC_KEY_get0_group(eckey.get())));
3829 if (dup.get() == NULL) {
3830 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
3831 jniThrowRuntimeException(env, "EC_POINT_dup");
3832 return 0;
3833 }
3834
3835 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
3836 return reinterpret_cast<uintptr_t>(dup.release());
3837 }
3838
NativeCrypto_EC_KEY_set_nonce_from_hash(JNIEnv * env,jclass,jlong pkeyRef,jboolean enabled)3839 static void NativeCrypto_EC_KEY_set_nonce_from_hash(JNIEnv* env, jclass, jlong pkeyRef,
3840 jboolean enabled)
3841 {
3842 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
3843 JNI_TRACE("EC_KEY_set_nonce_from_hash(%p, %d)", pkey, enabled ? 1 : 0);
3844
3845 if (pkey == NULL) {
3846 jniThrowNullPointerException(env, "pkey == null");
3847 return;
3848 }
3849
3850 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
3851 if (eckey.get() == NULL) {
3852 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
3853 return;
3854 }
3855
3856 EC_KEY_set_nonce_from_hash(eckey.get(), enabled ? 1 : 0);
3857 }
3858
NativeCrypto_ECDH_compute_key(JNIEnv * env,jclass,jbyteArray outArray,jint outOffset,jlong pubkeyRef,jlong privkeyRef)3859 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass,
3860 jbyteArray outArray, jint outOffset, jlong pubkeyRef, jlong privkeyRef)
3861 {
3862 EVP_PKEY* pubPkey = reinterpret_cast<EVP_PKEY*>(pubkeyRef);
3863 EVP_PKEY* privPkey = reinterpret_cast<EVP_PKEY*>(privkeyRef);
3864 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubPkey, privPkey);
3865
3866 ScopedByteArrayRW out(env, outArray);
3867 if (out.get() == NULL) {
3868 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer",
3869 outArray, outOffset, pubPkey, privPkey);
3870 return -1;
3871 }
3872
3873 if ((outOffset < 0) || ((size_t) outOffset >= out.size())) {
3874 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
3875 return -1;
3876 }
3877
3878 if (pubPkey == NULL) {
3879 jniThrowNullPointerException(env, "pubPkey == null");
3880 return -1;
3881 }
3882
3883 Unique_EC_KEY pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
3884 if (pubkey.get() == NULL) {
3885 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
3886 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
3887 return -1;
3888 }
3889
3890 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
3891 if (pubkeyPoint == NULL) {
3892 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
3893 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
3894 return -1;
3895 }
3896
3897 if (privPkey == NULL) {
3898 jniThrowNullPointerException(env, "privPkey == null");
3899 return -1;
3900 }
3901
3902 Unique_EC_KEY privkey(EVP_PKEY_get1_EC_KEY(privPkey));
3903 if (privkey.get() == NULL) {
3904 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY private");
3905 return -1;
3906 }
3907
3908 int outputLength = ECDH_compute_key(
3909 &out[outOffset],
3910 out.size() - outOffset,
3911 pubkeyPoint,
3912 privkey.get(),
3913 NULL // No KDF
3914 );
3915 if (outputLength == -1) {
3916 throwExceptionIfNecessary(env, "ECDH_compute_key");
3917 return -1;
3918 }
3919
3920 return outputLength;
3921 }
3922
NativeCrypto_EVP_MD_CTX_create(JNIEnv * env,jclass)3923 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
3924 JNI_TRACE_MD("EVP_MD_CTX_create()");
3925
3926 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
3927 if (ctx.get() == NULL) {
3928 jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX");
3929 return 0;
3930 }
3931
3932 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
3933 return reinterpret_cast<uintptr_t>(ctx.release());
3934 }
3935
NativeCrypto_EVP_MD_CTX_init(JNIEnv * env,jclass,jobject ctxRef)3936 static void NativeCrypto_EVP_MD_CTX_init(JNIEnv* env, jclass, jobject ctxRef) {
3937 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3938 JNI_TRACE_MD("EVP_MD_CTX_init(%p)", ctx);
3939
3940 if (ctx != NULL) {
3941 EVP_MD_CTX_init(ctx);
3942 }
3943 }
3944
NativeCrypto_EVP_MD_CTX_destroy(JNIEnv *,jclass,jlong ctxRef)3945 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv*, jclass, jlong ctxRef) {
3946 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
3947 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
3948
3949 if (ctx != NULL) {
3950 EVP_MD_CTX_destroy(ctx);
3951 }
3952 }
3953
NativeCrypto_EVP_MD_CTX_copy(JNIEnv * env,jclass,jobject dstCtxRef,jobject srcCtxRef)3954 static jint NativeCrypto_EVP_MD_CTX_copy(JNIEnv* env, jclass, jobject dstCtxRef, jobject srcCtxRef) {
3955 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
3956 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
3957 JNI_TRACE_MD("EVP_MD_CTX_copy(%p. %p)", dst_ctx, src_ctx);
3958
3959 if (src_ctx == NULL) {
3960 return 0;
3961 } else if (dst_ctx == NULL) {
3962 return 0;
3963 }
3964
3965 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
3966 if (result == 0) {
3967 jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX");
3968 freeOpenSslErrorState();
3969 }
3970
3971 JNI_TRACE_MD("EVP_MD_CTX_copy(%p, %p) => %d", dst_ctx, src_ctx, result);
3972 return result;
3973 }
3974
3975 /*
3976 * public static native int EVP_DigestFinal(long, byte[], int)
3977 */
NativeCrypto_EVP_DigestFinal(JNIEnv * env,jclass,jobject ctxRef,jbyteArray hash,jint offset)3978 static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
3979 jint offset) {
3980 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
3981 JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset);
3982
3983 if (ctx == NULL) {
3984 return -1;
3985 } else if (hash == NULL) {
3986 jniThrowNullPointerException(env, "ctx == null || hash == null");
3987 return -1;
3988 }
3989
3990 ScopedByteArrayRW hashBytes(env, hash);
3991 if (hashBytes.get() == NULL) {
3992 return -1;
3993 }
3994 unsigned int bytesWritten = -1;
3995 int ok = EVP_DigestFinal_ex(ctx,
3996 reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
3997 &bytesWritten);
3998 if (ok == 0) {
3999 throwExceptionIfNecessary(env, "EVP_DigestFinal");
4000 }
4001
4002 JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d) => %d", ctx, hash, offset, bytesWritten);
4003 return bytesWritten;
4004 }
4005
evpInit(JNIEnv * env,jobject evpMdCtxRef,jlong evpMdRef,const char * jniName,int (* init_func)(EVP_MD_CTX *,const EVP_MD *,ENGINE *))4006 static jint evpInit(JNIEnv* env, jobject evpMdCtxRef, jlong evpMdRef, const char* jniName,
4007 int (*init_func)(EVP_MD_CTX*, const EVP_MD*, ENGINE*)) {
4008 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
4009 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4010 JNI_TRACE_MD("%s(%p, %p)", jniName, ctx, evp_md);
4011
4012 if (ctx == NULL) {
4013 return 0;
4014 } else if (evp_md == NULL) {
4015 jniThrowNullPointerException(env, "evp_md == null");
4016 return 0;
4017 }
4018
4019 int ok = init_func(ctx, evp_md, NULL);
4020 if (ok == 0) {
4021 bool exception = throwExceptionIfNecessary(env, jniName);
4022 if (exception) {
4023 JNI_TRACE("%s(%p) => threw exception", jniName, evp_md);
4024 return 0;
4025 }
4026 }
4027 JNI_TRACE_MD("%s(%p, %p) => %d", jniName, ctx, evp_md, ok);
4028 return ok;
4029 }
4030
NativeCrypto_EVP_DigestInit(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)4031 static jint NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4032 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_DigestInit", EVP_DigestInit_ex);
4033 }
4034
NativeCrypto_EVP_SignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)4035 static jint NativeCrypto_EVP_SignInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4036 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_SignInit", EVP_DigestInit_ex);
4037 }
4038
NativeCrypto_EVP_VerifyInit(JNIEnv * env,jclass,jobject evpMdCtxRef,jlong evpMdRef)4039 static jint NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4040 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_VerifyInit", EVP_DigestInit_ex);
4041 }
4042
4043 /*
4044 * public static native int EVP_get_digestbyname(java.lang.String)
4045 */
NativeCrypto_EVP_get_digestbyname(JNIEnv * env,jclass,jstring algorithm)4046 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
4047 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
4048
4049 if (algorithm == NULL) {
4050 jniThrowNullPointerException(env, NULL);
4051 return -1;
4052 }
4053
4054 ScopedUtfChars algorithmChars(env, algorithm);
4055 if (algorithmChars.c_str() == NULL) {
4056 return 0;
4057 }
4058 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
4059
4060 const EVP_MD* evp_md = EVP_get_digestbyname(algorithmChars.c_str());
4061 if (evp_md == NULL) {
4062 jniThrowRuntimeException(env, "Hash algorithm not found");
4063 return 0;
4064 }
4065
4066 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => %p", algorithmChars.c_str(), evp_md);
4067 return reinterpret_cast<uintptr_t>(evp_md);
4068 }
4069
4070 /*
4071 * public static native int EVP_MD_size(long)
4072 */
NativeCrypto_EVP_MD_size(JNIEnv * env,jclass,jlong evpMdRef)4073 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
4074 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
4075 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
4076
4077 if (evp_md == NULL) {
4078 jniThrowNullPointerException(env, NULL);
4079 return -1;
4080 }
4081
4082 int result = EVP_MD_size(evp_md);
4083 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
4084 return result;
4085 }
4086
4087 /*
4088 * public static int void EVP_MD_block_size(long)
4089 */
NativeCrypto_EVP_MD_block_size(JNIEnv * env,jclass,jlong evpMdRef)4090 static jint NativeCrypto_EVP_MD_block_size(JNIEnv* env, jclass, jlong evpMdRef) {
4091 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
4092 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p)", evp_md);
4093
4094 if (evp_md == NULL) {
4095 jniThrowNullPointerException(env, NULL);
4096 return -1;
4097 }
4098
4099 int result = EVP_MD_block_size(evp_md);
4100 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p) => %d", evp_md, result);
4101 return result;
4102 }
4103
NativeCrypto_EVP_DigestSignInit(JNIEnv * env,jclass,jobject evpMdCtxRef,const jlong evpMdRef,jlong pkeyRef)4104 static void NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
4105 const jlong evpMdRef, jlong pkeyRef) {
4106 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
4107 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
4108 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
4109 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p)", mdCtx, md, pkey);
4110
4111 if (mdCtx == NULL) {
4112 return;
4113 }
4114
4115 if (md == NULL) {
4116 jniThrowNullPointerException(env, "md == null");
4117 return;
4118 }
4119
4120 if (pkey == NULL) {
4121 jniThrowNullPointerException(env, "pkey == null");
4122 return;
4123 }
4124
4125 if (EVP_DigestSignInit(mdCtx, (EVP_PKEY_CTX **) NULL, md, (ENGINE *) NULL, pkey) <= 0) {
4126 JNI_TRACE("ctx=%p EVP_DigestSignInit => threw exception", mdCtx);
4127 throwExceptionIfNecessary(env, "EVP_DigestSignInit");
4128 return;
4129 }
4130
4131 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p) => success", mdCtx, md, pkey);
4132 }
4133
evpUpdate(JNIEnv * env,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength,const char * jniName,int (* update_func)(EVP_MD_CTX *,const void *,size_t))4134 static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
4135 jint inLength, const char *jniName, int (*update_func)(EVP_MD_CTX*, const void *,
4136 size_t))
4137 {
4138 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
4139 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
4140
4141 if (mdCtx == NULL) {
4142 return;
4143 }
4144
4145 ScopedByteArrayRO inBytes(env, inJavaBytes);
4146 if (inBytes.get() == NULL) {
4147 return;
4148 }
4149
4150 if (inOffset < 0 || size_t(inOffset) > inBytes.size()) {
4151 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inOffset");
4152 return;
4153 }
4154
4155 const ssize_t inEnd = inOffset + inLength;
4156 if (inLength < 0 || inEnd < 0 || size_t(inEnd) > inBytes.size()) {
4157 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inLength");
4158 return;
4159 }
4160
4161 const unsigned char *tmp = reinterpret_cast<const unsigned char *>(inBytes.get());
4162 if (!update_func(mdCtx, tmp + inOffset, inLength)) {
4163 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
4164 throwExceptionIfNecessary(env, jniName);
4165 }
4166
4167 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
4168 }
4169
NativeCrypto_EVP_DigestUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)4170 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4171 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4172 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
4173 EVP_DigestUpdate);
4174 }
4175
NativeCrypto_EVP_DigestSignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)4176 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4177 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4178 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
4179 EVP_DigestUpdate);
4180 }
4181
NativeCrypto_EVP_SignUpdate(JNIEnv * env,jclass,jobject evpMdCtxRef,jbyteArray inJavaBytes,jint inOffset,jint inLength)4182 static void NativeCrypto_EVP_SignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4183 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4184 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_SignUpdate",
4185 EVP_DigestUpdate);
4186 }
4187
NativeCrypto_EVP_DigestSignFinal(JNIEnv * env,jclass,jobject evpMdCtxRef)4188 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef)
4189 {
4190 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
4191 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
4192
4193 if (mdCtx == NULL) {
4194 return NULL;
4195 }
4196
4197 size_t len;
4198 if (EVP_DigestSignFinal(mdCtx, NULL, &len) != 1) {
4199 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
4200 throwExceptionIfNecessary(env, "EVP_DigestSignFinal");
4201 return 0;
4202 }
4203 ScopedLocalRef<jbyteArray> outJavaBytes(env, env->NewByteArray(len));
4204 if (outJavaBytes.get() == NULL) {
4205 return NULL;
4206 }
4207 ScopedByteArrayRW outBytes(env, outJavaBytes.get());
4208 if (outBytes.get() == NULL) {
4209 return NULL;
4210 }
4211 unsigned char *tmp = reinterpret_cast<unsigned char*>(outBytes.get());
4212 if (EVP_DigestSignFinal(mdCtx, tmp, &len) != 1) {
4213 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
4214 throwExceptionIfNecessary(env, "EVP_DigestSignFinal");
4215 return 0;
4216 }
4217
4218 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, outJavaBytes.get());
4219 return outJavaBytes.release();
4220 }
4221
4222 /*
4223 * public static native int EVP_SignFinal(long, byte[], int, long)
4224 */
NativeCrypto_EVP_SignFinal(JNIEnv * env,jclass,jobject ctxRef,jbyteArray signature,jint offset,jlong pkeyRef)4225 static jint NativeCrypto_EVP_SignFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray signature,
4226 jint offset, jlong pkeyRef) {
4227 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
4228 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
4229 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p)", ctx, signature, offset, pkey);
4230
4231 if (ctx == NULL) {
4232 return -1;
4233 } else if (pkey == NULL) {
4234 jniThrowNullPointerException(env, NULL);
4235 return -1;
4236 }
4237
4238 ScopedByteArrayRW signatureBytes(env, signature);
4239 if (signatureBytes.get() == NULL) {
4240 return -1;
4241 }
4242 unsigned int bytesWritten = -1;
4243 int ok = EVP_SignFinal(ctx,
4244 reinterpret_cast<unsigned char*>(signatureBytes.get() + offset),
4245 &bytesWritten,
4246 pkey);
4247 if (ok == 0) {
4248 throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignFinal");
4249 }
4250 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p) => %u",
4251 ctx, signature, offset, pkey, bytesWritten);
4252
4253 return bytesWritten;
4254 }
4255
4256 /*
4257 * public static native void EVP_VerifyUpdate(long, byte[], int, int)
4258 */
NativeCrypto_EVP_VerifyUpdate(JNIEnv * env,jclass,jobject ctxRef,jbyteArray buffer,jint offset,jint length)4259 static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, jobject ctxRef,
4260 jbyteArray buffer, jint offset, jint length) {
4261 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
4262 JNI_TRACE("NativeCrypto_EVP_VerifyUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length);
4263
4264 if (ctx == NULL) {
4265 return;
4266 } else if (buffer == NULL) {
4267 jniThrowNullPointerException(env, NULL);
4268 return;
4269 }
4270
4271 if (offset < 0 || length < 0) {
4272 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
4273 return;
4274 }
4275
4276 ScopedByteArrayRO bufferBytes(env, buffer);
4277 if (bufferBytes.get() == NULL) {
4278 return;
4279 }
4280 if (bufferBytes.size() < static_cast<size_t>(offset + length)) {
4281 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
4282 return;
4283 }
4284
4285 int ok = EVP_VerifyUpdate(ctx,
4286 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
4287 length);
4288 if (ok == 0) {
4289 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate");
4290 }
4291 }
4292
4293 /*
4294 * public static native int EVP_VerifyFinal(long, byte[], int, int, long)
4295 */
NativeCrypto_EVP_VerifyFinal(JNIEnv * env,jclass,jobject ctxRef,jbyteArray buffer,jint offset,jint length,jlong pkeyRef)4296 static jint NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray buffer,
4297 jint offset, jint length, jlong pkeyRef) {
4298 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
4299 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
4300 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p)",
4301 ctx, buffer, offset, length, pkey);
4302
4303 if (ctx == NULL) {
4304 return -1;
4305 } else if (buffer == NULL || pkey == NULL) {
4306 jniThrowNullPointerException(env, NULL);
4307 return -1;
4308 }
4309
4310 ScopedByteArrayRO bufferBytes(env, buffer);
4311 if (bufferBytes.get() == NULL) {
4312 return -1;
4313 }
4314 int ok = EVP_VerifyFinal(ctx,
4315 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
4316 length,
4317 pkey);
4318 if (ok < 0) {
4319 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyFinal");
4320 }
4321
4322 /*
4323 * For DSA keys, OpenSSL appears to have a bug where it returns
4324 * errors for any result != 1. See dsa_ossl.c in dsa_do_verify
4325 */
4326 freeOpenSslErrorState();
4327
4328 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) => %d",
4329 ctx, buffer, offset, length, pkey, ok);
4330
4331 return ok;
4332 }
4333
NativeCrypto_EVP_get_cipherbyname(JNIEnv * env,jclass,jstring algorithm)4334 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
4335 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
4336 if (algorithm == NULL) {
4337 JNI_TRACE("EVP_get_cipherbyname(%p) => threw exception algorithm == null", algorithm);
4338 jniThrowNullPointerException(env, NULL);
4339 return -1;
4340 }
4341
4342 ScopedUtfChars algorithmChars(env, algorithm);
4343 if (algorithmChars.c_str() == NULL) {
4344 return 0;
4345 }
4346 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm = %s", algorithm, algorithmChars.c_str());
4347
4348 const EVP_CIPHER* evp_cipher = EVP_get_cipherbyname(algorithmChars.c_str());
4349 if (evp_cipher == NULL) {
4350 freeOpenSslErrorState();
4351 }
4352
4353 JNI_TRACE("EVP_get_cipherbyname(%s) => %p", algorithmChars.c_str(), evp_cipher);
4354 return reinterpret_cast<uintptr_t>(evp_cipher);
4355 }
4356
NativeCrypto_EVP_CipherInit_ex(JNIEnv * env,jclass,jlong ctxRef,jlong evpCipherRef,jbyteArray keyArray,jbyteArray ivArray,jboolean encrypting)4357 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jlong ctxRef, jlong evpCipherRef,
4358 jbyteArray keyArray, jbyteArray ivArray, jboolean encrypting) {
4359 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4360 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
4361 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
4362 encrypting ? 1 : 0);
4363
4364 if (ctx == NULL) {
4365 jniThrowNullPointerException(env, "ctx == null");
4366 JNI_TRACE("EVP_CipherUpdate => ctx == null");
4367 return;
4368 }
4369
4370 // The key can be null if we need to set extra parameters.
4371 UniquePtr<unsigned char[]> keyPtr;
4372 if (keyArray != NULL) {
4373 ScopedByteArrayRO keyBytes(env, keyArray);
4374 if (keyBytes.get() == NULL) {
4375 return;
4376 }
4377
4378 keyPtr.reset(new unsigned char[keyBytes.size()]);
4379 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
4380 }
4381
4382 // The IV can be null if we're using ECB.
4383 UniquePtr<unsigned char[]> ivPtr;
4384 if (ivArray != NULL) {
4385 ScopedByteArrayRO ivBytes(env, ivArray);
4386 if (ivBytes.get() == NULL) {
4387 return;
4388 }
4389
4390 ivPtr.reset(new unsigned char[ivBytes.size()]);
4391 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
4392 }
4393
4394 if (!EVP_CipherInit_ex(ctx, evpCipher, NULL, keyPtr.get(), ivPtr.get(), encrypting ? 1 : 0)) {
4395 throwExceptionIfNecessary(env, "EVP_CipherInit_ex");
4396 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
4397 return;
4398 }
4399
4400 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
4401 encrypting ? 1 : 0);
4402 }
4403
4404 /*
4405 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
4406 * int inOffset, int inLength);
4407 */
NativeCrypto_EVP_CipherUpdate(JNIEnv * env,jclass,jlong ctxRef,jbyteArray outArray,jint outOffset,jbyteArray inArray,jint inOffset,jint inLength)4408 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray,
4409 jint outOffset, jbyteArray inArray, jint inOffset, jint inLength) {
4410 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4411 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
4412
4413 if (ctx == NULL) {
4414 jniThrowNullPointerException(env, "ctx == null");
4415 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
4416 return 0;
4417 }
4418
4419 ScopedByteArrayRO inBytes(env, inArray);
4420 if (inBytes.get() == NULL) {
4421 return 0;
4422 }
4423 const size_t inSize = inBytes.size();
4424 if (size_t(inOffset + inLength) > inSize) {
4425 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
4426 "in.length < (inSize + inOffset)");
4427 return 0;
4428 }
4429
4430 ScopedByteArrayRW outBytes(env, outArray);
4431 if (outBytes.get() == NULL) {
4432 return 0;
4433 }
4434 const size_t outSize = outBytes.size();
4435 if (size_t(outOffset + inLength) > outSize) {
4436 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
4437 "out.length < inSize + outOffset + blockSize - 1");
4438 return 0;
4439 }
4440
4441 JNI_TRACE("ctx=%p EVP_CipherUpdate in=%p in.length=%d inOffset=%d inLength=%d out=%p out.length=%d outOffset=%d",
4442 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(), outOffset);
4443
4444 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
4445 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
4446
4447 int outl;
4448 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
4449 throwExceptionIfNecessary(env, "EVP_CipherUpdate");
4450 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
4451 return 0;
4452 }
4453
4454 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
4455 inOffset, outl);
4456 return outl;
4457 }
4458
NativeCrypto_EVP_CipherFinal_ex(JNIEnv * env,jclass,jlong ctxRef,jbyteArray outArray,jint outOffset)4459 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray,
4460 jint outOffset) {
4461 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4462 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
4463
4464 if (ctx == NULL) {
4465 jniThrowNullPointerException(env, "ctx == null");
4466 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
4467 return 0;
4468 }
4469
4470 ScopedByteArrayRW outBytes(env, outArray);
4471 if (outBytes.get() == NULL) {
4472 return 0;
4473 }
4474
4475 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
4476
4477 int outl;
4478 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
4479 if (throwExceptionIfNecessary(env, "EVP_CipherFinal_ex")) {
4480 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
4481 } else {
4482 throwBadPaddingException(env, "EVP_CipherFinal_ex");
4483 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw padding exception", ctx);
4484 }
4485 return 0;
4486 }
4487
4488 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
4489 return outl;
4490 }
4491
NativeCrypto_EVP_CIPHER_iv_length(JNIEnv * env,jclass,jlong evpCipherRef)4492 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
4493 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
4494 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
4495
4496 if (evpCipher == NULL) {
4497 jniThrowNullPointerException(env, "evpCipher == null");
4498 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
4499 return 0;
4500 }
4501
4502 const int ivLength = EVP_CIPHER_iv_length(evpCipher);
4503 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
4504 return ivLength;
4505 }
4506
NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv * env,jclass)4507 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
4508 JNI_TRACE("EVP_CIPHER_CTX_new()");
4509
4510 Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
4511 if (ctx.get() == NULL) {
4512 jniThrowOutOfMemory(env, "Unable to allocate cipher context");
4513 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
4514 return 0;
4515 }
4516
4517 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
4518 return reinterpret_cast<uintptr_t>(ctx.release());
4519 }
4520
NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv * env,jclass,jlong ctxRef)4521 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jlong ctxRef) {
4522 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4523 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
4524
4525 if (ctx == NULL) {
4526 jniThrowNullPointerException(env, "ctx == null");
4527 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
4528 return 0;
4529 }
4530
4531 int blockSize = EVP_CIPHER_CTX_block_size(ctx);
4532 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
4533 return blockSize;
4534 }
4535
NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv * env,jclass,jlong ctxRef)4536 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jlong ctxRef) {
4537 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4538 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
4539
4540 if (ctx == NULL) {
4541 jniThrowNullPointerException(env, "ctx == null");
4542 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
4543 return 0;
4544 }
4545
4546 int buf_len = ctx->buf_len;
4547 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
4548 return buf_len;
4549 }
4550
NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv * env,jclass,jlong ctxRef,jboolean enablePaddingBool)4551 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jlong ctxRef, jboolean enablePaddingBool) {
4552 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4553 jint enablePadding = enablePaddingBool ? 1 : 0;
4554 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
4555
4556 if (ctx == NULL) {
4557 jniThrowNullPointerException(env, "ctx == null");
4558 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
4559 return;
4560 }
4561
4562 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
4563 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
4564 }
4565
NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv * env,jclass,jlong ctxRef,jint keySizeBits)4566 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jlong ctxRef,
4567 jint keySizeBits) {
4568 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4569 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
4570
4571 if (ctx == NULL) {
4572 jniThrowNullPointerException(env, "ctx == null");
4573 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
4574 return;
4575 }
4576
4577 if (!EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits)) {
4578 throwExceptionIfNecessary(env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
4579 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
4580 return;
4581 }
4582 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
4583 }
4584
NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv *,jclass,jlong ctxRef)4585 static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv*, jclass, jlong ctxRef) {
4586 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
4587 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
4588
4589 EVP_CIPHER_CTX_free(ctx);
4590 }
4591
4592 /**
4593 * public static native void RAND_seed(byte[]);
4594 */
NativeCrypto_RAND_seed(JNIEnv * env,jclass,jbyteArray seed)4595 static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) {
4596 JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed);
4597 ScopedByteArrayRO randseed(env, seed);
4598 if (randseed.get() == NULL) {
4599 return;
4600 }
4601 RAND_seed(randseed.get(), randseed.size());
4602 }
4603
NativeCrypto_RAND_load_file(JNIEnv * env,jclass,jstring filename,jlong max_bytes)4604 static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) {
4605 JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, max_bytes);
4606 ScopedUtfChars file(env, filename);
4607 if (file.c_str() == NULL) {
4608 return -1;
4609 }
4610 int result = RAND_load_file(file.c_str(), max_bytes);
4611 JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result);
4612 return result;
4613 }
4614
NativeCrypto_RAND_bytes(JNIEnv * env,jclass,jbyteArray output)4615 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
4616 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
4617
4618 ScopedByteArrayRW outputBytes(env, output);
4619 if (outputBytes.get() == NULL) {
4620 return;
4621 }
4622
4623 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
4624 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
4625 throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes");
4626 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
4627 return;
4628 }
4629
4630 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
4631 }
4632
NativeCrypto_OBJ_txt2nid(JNIEnv * env,jclass,jstring oidStr)4633 static jint NativeCrypto_OBJ_txt2nid(JNIEnv* env, jclass, jstring oidStr) {
4634 JNI_TRACE("OBJ_txt2nid(%p)", oidStr);
4635
4636 ScopedUtfChars oid(env, oidStr);
4637 if (oid.c_str() == NULL) {
4638 return 0;
4639 }
4640
4641 int nid = OBJ_txt2nid(oid.c_str());
4642 JNI_TRACE("OBJ_txt2nid(%s) => %d", oid.c_str(), nid);
4643 return nid;
4644 }
4645
NativeCrypto_OBJ_txt2nid_longName(JNIEnv * env,jclass,jstring oidStr)4646 static jstring NativeCrypto_OBJ_txt2nid_longName(JNIEnv* env, jclass, jstring oidStr) {
4647 JNI_TRACE("OBJ_txt2nid_longName(%p)", oidStr);
4648
4649 ScopedUtfChars oid(env, oidStr);
4650 if (oid.c_str() == NULL) {
4651 return NULL;
4652 }
4653
4654 JNI_TRACE("OBJ_txt2nid_longName(%s)", oid.c_str());
4655
4656 int nid = OBJ_txt2nid(oid.c_str());
4657 if (nid == NID_undef) {
4658 JNI_TRACE("OBJ_txt2nid_longName(%s) => NID_undef", oid.c_str());
4659 freeOpenSslErrorState();
4660 return NULL;
4661 }
4662
4663 const char* longName = OBJ_nid2ln(nid);
4664 JNI_TRACE("OBJ_txt2nid_longName(%s) => %s", oid.c_str(), longName);
4665 return env->NewStringUTF(longName);
4666 }
4667
ASN1_OBJECT_to_OID_string(JNIEnv * env,ASN1_OBJECT * obj)4668 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, ASN1_OBJECT* obj) {
4669 /*
4670 * The OBJ_obj2txt API doesn't "measure" if you pass in NULL as the buffer.
4671 * Just make a buffer that's large enough here. The documentation recommends
4672 * 80 characters.
4673 */
4674 char output[128];
4675 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
4676 if (ret < 0) {
4677 throwExceptionIfNecessary(env, "ASN1_OBJECT_to_OID_string");
4678 return NULL;
4679 } else if (size_t(ret) >= sizeof(output)) {
4680 jniThrowRuntimeException(env, "ASN1_OBJECT_to_OID_string buffer too small");
4681 return NULL;
4682 }
4683
4684 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
4685 return env->NewStringUTF(output);
4686 }
4687
NativeCrypto_create_BIO_InputStream(JNIEnv * env,jclass,jobject streamObj)4688 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj) {
4689 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
4690
4691 if (streamObj == NULL) {
4692 jniThrowNullPointerException(env, "stream == null");
4693 return 0;
4694 }
4695
4696 Unique_BIO bio(BIO_new(&stream_bio_method));
4697 if (bio.get() == NULL) {
4698 return 0;
4699 }
4700
4701 bio_stream_assign(bio.get(), new BIO_InputStream(streamObj));
4702
4703 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
4704 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4705 }
4706
NativeCrypto_create_BIO_OutputStream(JNIEnv * env,jclass,jobject streamObj)4707 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
4708 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
4709
4710 if (streamObj == NULL) {
4711 jniThrowNullPointerException(env, "stream == null");
4712 return 0;
4713 }
4714
4715 Unique_BIO bio(BIO_new(&stream_bio_method));
4716 if (bio.get() == NULL) {
4717 return 0;
4718 }
4719
4720 bio_stream_assign(bio.get(), new BIO_OutputStream(streamObj));
4721
4722 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
4723 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
4724 }
4725
NativeCrypto_BIO_read(JNIEnv * env,jclass,jlong bioRef,jbyteArray outputJavaBytes)4726 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
4727 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4728 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
4729
4730 if (outputJavaBytes == NULL) {
4731 jniThrowNullPointerException(env, "output == null");
4732 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
4733 return 0;
4734 }
4735
4736 int outputSize = env->GetArrayLength(outputJavaBytes);
4737
4738 UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
4739 if (buffer.get() == NULL) {
4740 jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
4741 return 0;
4742 }
4743
4744 int read = BIO_read(bio, buffer.get(), outputSize);
4745 if (read <= 0) {
4746 jniThrowException(env, "java/io/IOException", "BIO_read");
4747 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
4748 return 0;
4749 }
4750
4751 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
4752 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
4753 return read;
4754 }
4755
NativeCrypto_BIO_write(JNIEnv * env,jclass,jlong bioRef,jbyteArray inputJavaBytes,jint offset,jint length)4756 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
4757 jint offset, jint length) {
4758 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4759 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
4760
4761 if (inputJavaBytes == NULL) {
4762 jniThrowNullPointerException(env, "input == null");
4763 return;
4764 }
4765
4766 if (offset < 0 || length < 0) {
4767 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "offset < 0 || length < 0");
4768 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4769 return;
4770 }
4771
4772 int inputSize = env->GetArrayLength(inputJavaBytes);
4773 if (inputSize < offset + length) {
4774 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
4775 "input.length < offset + length");
4776 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
4777 return;
4778 }
4779
4780 UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
4781 if (buffer.get() == NULL) {
4782 jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
4783 return;
4784 }
4785
4786 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
4787 if (BIO_write(bio, buffer.get(), length) != length) {
4788 freeOpenSslErrorState();
4789 jniThrowException(env, "java/io/IOException", "BIO_write");
4790 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
4791 return;
4792 }
4793
4794 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
4795 }
4796
NativeCrypto_BIO_free_all(JNIEnv * env,jclass,jlong bioRef)4797 static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
4798 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
4799 JNI_TRACE("BIO_free_all(%p)", bio);
4800
4801 if (bio == NULL) {
4802 jniThrowNullPointerException(env, "bio == null");
4803 return;
4804 }
4805
4806 BIO_free_all(bio);
4807 }
4808
X509_NAME_to_jstring(JNIEnv * env,X509_NAME * name,unsigned long flags)4809 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
4810 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
4811
4812 Unique_BIO buffer(BIO_new(BIO_s_mem()));
4813 if (buffer.get() == NULL) {
4814 jniThrowOutOfMemory(env, "Unable to allocate BIO");
4815 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
4816 return NULL;
4817 }
4818
4819 /* Don't interpret the string. */
4820 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
4821
4822 /* Write in given format and null terminate. */
4823 X509_NAME_print_ex(buffer.get(), name, 0, flags);
4824 BIO_write(buffer.get(), "\0", 1);
4825
4826 char *tmp;
4827 BIO_get_mem_data(buffer.get(), &tmp);
4828 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
4829 return env->NewStringUTF(tmp);
4830 }
4831
4832
4833 /**
4834 * Converts GENERAL_NAME items to the output format expected in
4835 * X509Certificate#getSubjectAlternativeNames and
4836 * X509Certificate#getIssuerAlternativeNames return.
4837 */
GENERAL_NAME_to_jobject(JNIEnv * env,GENERAL_NAME * gen)4838 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
4839 switch (gen->type) {
4840 case GEN_EMAIL:
4841 case GEN_DNS:
4842 case GEN_URI: {
4843 // This must not be a T61String and must not contain NULLs.
4844 const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
4845 ssize_t len = ASN1_STRING_length(gen->d.ia5);
4846 if ((len == static_cast<ssize_t>(strlen(data)))
4847 && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
4848 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
4849 return env->NewStringUTF(data);
4850 } else {
4851 jniThrowException(env, "java/security/cert/CertificateParsingException",
4852 "Invalid dNSName encoding");
4853 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
4854 return NULL;
4855 }
4856 }
4857 case GEN_DIRNAME:
4858 /* Write in RFC 2253 format */
4859 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
4860 case GEN_IPADD: {
4861 const void *ip = reinterpret_cast<const void *>(gen->d.ip->data);
4862 if (gen->d.ip->length == 4) {
4863 // IPv4
4864 UniquePtr<char[]> buffer(new char[INET_ADDRSTRLEN]);
4865 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != NULL) {
4866 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
4867 return env->NewStringUTF(buffer.get());
4868 } else {
4869 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen, strerror(errno));
4870 }
4871 } else if (gen->d.ip->length == 16) {
4872 // IPv6
4873 UniquePtr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
4874 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != NULL) {
4875 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
4876 return env->NewStringUTF(buffer.get());
4877 } else {
4878 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno));
4879 }
4880 }
4881
4882 /* Invalid IP encodings are pruned out without throwing an exception. */
4883 return NULL;
4884 }
4885 case GEN_RID:
4886 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
4887 case GEN_OTHERNAME:
4888 case GEN_X400:
4889 default:
4890 return ASN1ToByteArray<GENERAL_NAME, i2d_GENERAL_NAME>(env, gen);
4891 }
4892
4893 return NULL;
4894 }
4895
4896 #define GN_STACK_SUBJECT_ALT_NAME 1
4897 #define GN_STACK_ISSUER_ALT_NAME 2
4898
NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv * env,jclass,jlong x509Ref,jint type)4899 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
4900 jint type) {
4901 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4902 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
4903
4904 if (x509 == NULL) {
4905 jniThrowNullPointerException(env, "x509 == null");
4906 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
4907 return NULL;
4908 }
4909
4910 X509_check_ca(x509);
4911
4912 STACK_OF(GENERAL_NAME)* gn_stack;
4913 Unique_sk_GENERAL_NAME stackHolder;
4914 if (type == GN_STACK_SUBJECT_ALT_NAME) {
4915 gn_stack = x509->altname;
4916 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
4917 stackHolder.reset(
4918 static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, NID_issuer_alt_name,
4919 NULL, NULL)));
4920 gn_stack = stackHolder.get();
4921 } else {
4922 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
4923 return NULL;
4924 }
4925
4926 int count = sk_GENERAL_NAME_num(gn_stack);
4927 if (count <= 0) {
4928 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
4929 return NULL;
4930 }
4931
4932 /*
4933 * Keep track of how many originally so we can ignore any invalid
4934 * values later.
4935 */
4936 const int origCount = count;
4937
4938 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
4939 for (int i = 0, j = 0; i < origCount; i++, j++) {
4940 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
4941 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
4942 if (env->ExceptionCheck()) {
4943 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
4944 x509, type);
4945 return NULL;
4946 }
4947
4948 /*
4949 * If it's NULL, we'll have to skip this, reduce the number of total
4950 * entries, and fix up the array later.
4951 */
4952 if (val.get() == NULL) {
4953 j--;
4954 count--;
4955 continue;
4956 }
4957
4958 ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
4959
4960 ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
4961 integer_valueOfMethod, gen->type));
4962 env->SetObjectArrayElement(item.get(), 0, type.get());
4963 env->SetObjectArrayElement(item.get(), 1, val.get());
4964
4965 env->SetObjectArrayElement(joa.get(), j, item.get());
4966 }
4967
4968 if (count == 0) {
4969 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning NULL",
4970 x509, type, origCount);
4971 joa.reset(NULL);
4972 } else if (origCount != count) {
4973 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
4974 origCount, count);
4975
4976 ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
4977 NULL));
4978
4979 for (int i = 0; i < count; i++) {
4980 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
4981 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
4982 }
4983
4984 joa.reset(joa_copy.release());
4985 }
4986
4987 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
4988 return joa.release();
4989 }
4990
NativeCrypto_X509_get_notBefore(JNIEnv * env,jclass,jlong x509Ref)4991 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref) {
4992 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
4993 JNI_TRACE("X509_get_notBefore(%p)", x509);
4994
4995 if (x509 == NULL) {
4996 jniThrowNullPointerException(env, "x509 == null");
4997 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
4998 return 0;
4999 }
5000
5001 ASN1_TIME* notBefore = X509_get_notBefore(x509);
5002 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
5003 return reinterpret_cast<uintptr_t>(notBefore);
5004 }
5005
NativeCrypto_X509_get_notAfter(JNIEnv * env,jclass,jlong x509Ref)5006 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref) {
5007 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5008 JNI_TRACE("X509_get_notAfter(%p)", x509);
5009
5010 if (x509 == NULL) {
5011 jniThrowNullPointerException(env, "x509 == null");
5012 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
5013 return 0;
5014 }
5015
5016 ASN1_TIME* notAfter = X509_get_notAfter(x509);
5017 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
5018 return reinterpret_cast<uintptr_t>(notAfter);
5019 }
5020
NativeCrypto_X509_get_version(JNIEnv *,jclass,jlong x509Ref)5021 static long NativeCrypto_X509_get_version(JNIEnv*, jclass, jlong x509Ref) {
5022 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5023 JNI_TRACE("X509_get_version(%p)", x509);
5024
5025 long version = X509_get_version(x509);
5026 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
5027 return version;
5028 }
5029
5030 template<typename T>
get_X509Type_serialNumber(JNIEnv * env,T * x509Type,ASN1_INTEGER * (* get_serial_func)(T *))5031 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type, ASN1_INTEGER* (*get_serial_func)(T*)) {
5032 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
5033
5034 if (x509Type == NULL) {
5035 jniThrowNullPointerException(env, "x509Type == null");
5036 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
5037 return NULL;
5038 }
5039
5040 ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
5041 Unique_BIGNUM serialBn(ASN1_INTEGER_to_BN(serialNumber, NULL));
5042 if (serialBn.get() == NULL) {
5043 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5044 return NULL;
5045 }
5046
5047 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
5048 if (env->ExceptionCheck()) {
5049 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5050 return NULL;
5051 }
5052
5053 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
5054 return serialArray.release();
5055 }
5056
5057 /* OpenSSL includes set_serialNumber but not get. */
5058 #if !defined(X509_REVOKED_get_serialNumber)
X509_REVOKED_get_serialNumber(X509_REVOKED * x)5059 static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) {
5060 return x->serialNumber;
5061 }
5062 #endif
5063
NativeCrypto_X509_get_serialNumber(JNIEnv * env,jclass,jlong x509Ref)5064 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref) {
5065 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5066 JNI_TRACE("X509_get_serialNumber(%p)", x509);
5067 return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber);
5068 }
5069
NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv * env,jclass,jlong x509RevokedRef)5070 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass, jlong x509RevokedRef) {
5071 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5072 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5073 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber);
5074 }
5075
NativeCrypto_X509_verify(JNIEnv * env,jclass,jlong x509Ref,jlong pkeyRef)5076 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref, jlong pkeyRef) {
5077 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5078 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
5079 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5080
5081 if (x509 == NULL) {
5082 jniThrowNullPointerException(env, "x509 == null");
5083 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5084 return;
5085 }
5086
5087 if (pkey == NULL) {
5088 jniThrowNullPointerException(env, "pkey == null");
5089 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5090 return;
5091 }
5092
5093 if (X509_verify(x509, pkey) != 1) {
5094 throwExceptionIfNecessary(env, "X509_verify");
5095 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5096 } else {
5097 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5098 }
5099 }
5100
NativeCrypto_get_X509_cert_info_enc(JNIEnv * env,jclass,jlong x509Ref)5101 static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref) {
5102 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5103 JNI_TRACE("get_X509_cert_info_enc(%p)", x509);
5104 return ASN1ToByteArray<X509_CINF, i2d_X509_CINF>(env, x509->cert_info);
5105 }
5106
NativeCrypto_get_X509_ex_flags(JNIEnv * env,jclass,jlong x509Ref)5107 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) {
5108 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5109 JNI_TRACE("get_X509_ex_flags(%p)", x509);
5110
5111 if (x509 == NULL) {
5112 jniThrowNullPointerException(env, "x509 == null");
5113 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5114 return 0;
5115 }
5116
5117 X509_check_ca(x509);
5118
5119 return x509->ex_flags;
5120 }
5121
NativeCrypto_X509_check_issued(JNIEnv *,jclass,jlong x509Ref1,jlong x509Ref2)5122 static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
5123 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5124 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5125 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5126
5127 int ret = X509_check_issued(x509_1, x509_2);
5128 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5129 return ret;
5130 }
5131
get_X509_signature(X509 * x509,ASN1_BIT_STRING ** signature)5132 static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
5133 *signature = x509->signature;
5134 }
5135
get_X509_CRL_signature(X509_CRL * crl,ASN1_BIT_STRING ** signature)5136 static void get_X509_CRL_signature(X509_CRL *crl, ASN1_BIT_STRING** signature) {
5137 *signature = crl->signature;
5138 }
5139
5140 template<typename T>
get_X509Type_signature(JNIEnv * env,T * x509Type,void (* get_signature_func)(T *,ASN1_BIT_STRING **))5141 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type, void (*get_signature_func)(T*, ASN1_BIT_STRING**)) {
5142 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5143
5144 if (x509Type == NULL) {
5145 jniThrowNullPointerException(env, "x509Type == null");
5146 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5147 return NULL;
5148 }
5149
5150 ASN1_BIT_STRING* signature;
5151 get_signature_func(x509Type, &signature);
5152
5153 ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length));
5154 if (env->ExceptionCheck()) {
5155 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5156 return NULL;
5157 }
5158
5159 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5160 if (signatureBytes.get() == NULL) {
5161 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5162 return NULL;
5163 }
5164
5165 memcpy(signatureBytes.get(), signature->data, signature->length);
5166
5167 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5168 signature->length);
5169 return signatureArray.release();
5170 }
5171
NativeCrypto_get_X509_signature(JNIEnv * env,jclass,jlong x509Ref)5172 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref) {
5173 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5174 JNI_TRACE("get_X509_signature(%p)", x509);
5175 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5176 }
5177
NativeCrypto_get_X509_CRL_signature(JNIEnv * env,jclass,jlong x509CrlRef)5178 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef) {
5179 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5180 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
5181 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5182 }
5183
NativeCrypto_X509_CRL_get0_by_cert(JNIEnv * env,jclass,jlong x509crlRef,jlong x509Ref)5184 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef, jlong x509Ref) {
5185 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5186 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5187 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5188
5189 if (x509crl == NULL) {
5190 jniThrowNullPointerException(env, "x509crl == null");
5191 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5192 return 0;
5193 } else if (x509 == NULL) {
5194 jniThrowNullPointerException(env, "x509 == null");
5195 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5196 return 0;
5197 }
5198
5199 X509_REVOKED* revoked = NULL;
5200 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5201 if (ret == 0) {
5202 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5203 return 0;
5204 }
5205
5206 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5207 return reinterpret_cast<uintptr_t>(revoked);
5208 }
5209
NativeCrypto_X509_CRL_get0_by_serial(JNIEnv * env,jclass,jlong x509crlRef,jbyteArray serialArray)5210 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef, jbyteArray serialArray) {
5211 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5212 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5213
5214 if (x509crl == NULL) {
5215 jniThrowNullPointerException(env, "x509crl == null");
5216 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5217 return 0;
5218 }
5219
5220 Unique_BIGNUM serialBn(BN_new());
5221 if (serialBn.get() == NULL) {
5222 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
5223 return 0;
5224 }
5225
5226 BIGNUM* serialBare = serialBn.get();
5227 if (!arrayToBignum(env, serialArray, &serialBare)) {
5228 if (!env->ExceptionCheck()) {
5229 jniThrowNullPointerException(env, "serial == null");
5230 }
5231 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5232 return 0;
5233 }
5234
5235 Unique_ASN1_INTEGER serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), NULL));
5236 if (serialInteger.get() == NULL) {
5237 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5238 return 0;
5239 }
5240
5241 X509_REVOKED* revoked = NULL;
5242 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5243 if (ret == 0) {
5244 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5245 return 0;
5246 }
5247
5248 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5249 return reinterpret_cast<uintptr_t>(revoked);
5250 }
5251
5252
5253 /* This appears to be missing from OpenSSL. */
5254 #if !defined(X509_REVOKED_dup)
X509_REVOKED_dup(X509_REVOKED * x)5255 X509_REVOKED* X509_REVOKED_dup(X509_REVOKED* x) {
5256 return reinterpret_cast<X509_REVOKED*>(ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), x));
5257 }
5258 #endif
5259
NativeCrypto_X509_CRL_get_REVOKED(JNIEnv * env,jclass,jlong x509CrlRef)5260 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef) {
5261 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5262 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5263
5264 if (crl == NULL) {
5265 jniThrowNullPointerException(env, "crl == null");
5266 return NULL;
5267 }
5268
5269 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5270 if (stack == NULL) {
5271 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5272 return NULL;
5273 }
5274
5275 size_t size = sk_X509_REVOKED_num(stack);
5276
5277 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(size));
5278 ScopedLongArrayRW revoked(env, revokedArray.get());
5279 for (size_t i = 0; i < size; i++) {
5280 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5281 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5282 }
5283
5284 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%d]", stack, revokedArray.get(), size);
5285 return revokedArray.release();
5286 }
5287
NativeCrypto_i2d_X509_CRL(JNIEnv * env,jclass,jlong x509CrlRef)5288 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef) {
5289 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5290 JNI_TRACE("i2d_X509_CRL(%p)", crl);
5291 return ASN1ToByteArray<X509_CRL, i2d_X509_CRL>(env, crl);
5292 }
5293
NativeCrypto_X509_CRL_free(JNIEnv * env,jclass,jlong x509CrlRef)5294 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef) {
5295 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5296 JNI_TRACE("X509_CRL_free(%p)", crl);
5297
5298 if (crl == NULL) {
5299 jniThrowNullPointerException(env, "crl == null");
5300 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
5301 return;
5302 }
5303
5304 X509_CRL_free(crl);
5305 }
5306
NativeCrypto_X509_CRL_print(JNIEnv * env,jclass,jlong bioRef,jlong x509CrlRef)5307 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef) {
5308 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5309 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5310 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
5311
5312 if (bio == NULL) {
5313 jniThrowNullPointerException(env, "bio == null");
5314 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
5315 return;
5316 }
5317
5318 if (crl == NULL) {
5319 jniThrowNullPointerException(env, "crl == null");
5320 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
5321 return;
5322 }
5323
5324 if (!X509_CRL_print(bio, crl)) {
5325 throwExceptionIfNecessary(env, "X509_CRL_print");
5326 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
5327 } else {
5328 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
5329 }
5330 }
5331
NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv * env,jclass,jlong x509CrlRef)5332 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) {
5333 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5334 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
5335
5336 if (crl == NULL || crl->sig_alg == NULL) {
5337 jniThrowNullPointerException(env, "crl == NULL || crl->sig_alg == NULL");
5338 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == NULL", crl);
5339 return NULL;
5340 }
5341
5342 return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm);
5343 }
5344
NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv * env,jclass,jlong x509CrlRef)5345 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef) {
5346 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5347 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
5348
5349 if (crl == NULL) {
5350 jniThrowNullPointerException(env, "crl == null");
5351 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
5352 return NULL;
5353 }
5354
5355 if (crl->sig_alg->parameter == NULL) {
5356 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl);
5357 return NULL;
5358 }
5359
5360 return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, crl->sig_alg->parameter);
5361 }
5362
NativeCrypto_X509_CRL_get_issuer_name(JNIEnv * env,jclass,jlong x509CrlRef)5363 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef) {
5364 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5365 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
5366 return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_CRL_get_issuer(crl));
5367 }
5368
NativeCrypto_X509_CRL_get_version(JNIEnv *,jclass,jlong x509CrlRef)5369 static long NativeCrypto_X509_CRL_get_version(JNIEnv*, jclass, jlong x509CrlRef) {
5370 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5371 JNI_TRACE("X509_CRL_get_version(%p)", crl);
5372
5373 long version = X509_CRL_get_version(crl);
5374 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
5375 return version;
5376 }
5377
5378 template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
5379 X509_EXTENSION* (*get_ext_func)(T*, int)>
X509Type_get_ext(JNIEnv * env,T * x509Type,jstring oidString)5380 static X509_EXTENSION *X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) {
5381 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
5382
5383 if (x509Type == NULL) {
5384 jniThrowNullPointerException(env, "x509 == null");
5385 return NULL;
5386 }
5387
5388 ScopedUtfChars oid(env, oidString);
5389 if (oid.c_str() == NULL) {
5390 return NULL;
5391 }
5392
5393 Unique_ASN1_OBJECT asn1(OBJ_txt2obj(oid.c_str(), 1));
5394 if (asn1.get() == NULL) {
5395 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
5396 freeOpenSslErrorState();
5397 return NULL;
5398 }
5399
5400 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1);
5401 if (extIndex == -1) {
5402 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
5403 return NULL;
5404 }
5405
5406 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
5407 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
5408 return ext;
5409 }
5410
5411 template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
5412 X509_EXTENSION* (*get_ext_func)(T*, int)>
X509Type_get_ext_oid(JNIEnv * env,T * x509Type,jstring oidString)5413 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) {
5414 X509_EXTENSION* ext = X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type,
5415 oidString);
5416 if (ext == NULL) {
5417 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
5418 return NULL;
5419 }
5420
5421 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value);
5422 return ASN1ToByteArray<ASN1_OCTET_STRING, i2d_ASN1_OCTET_STRING>(env, ext->value);
5423 }
5424
NativeCrypto_X509_CRL_get_ext(JNIEnv * env,jclass,jlong x509CrlRef,jstring oid)5425 static jint NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef, jstring oid) {
5426 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5427 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
5428 X509_EXTENSION* ext = X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(
5429 env, crl, oid);
5430 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
5431 return reinterpret_cast<uintptr_t>(ext);
5432 }
5433
NativeCrypto_X509_REVOKED_get_ext(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oid)5434 static jint NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
5435 jstring oid) {
5436 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5437 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
5438 X509_EXTENSION* ext = X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ,
5439 X509_REVOKED_get_ext>(env, revoked, oid);
5440 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
5441 return reinterpret_cast<uintptr_t>(ext);
5442 }
5443
NativeCrypto_X509_REVOKED_dup(JNIEnv * env,jclass,jlong x509RevokedRef)5444 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
5445 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5446 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
5447
5448 if (revoked == NULL) {
5449 jniThrowNullPointerException(env, "revoked == null");
5450 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
5451 return 0;
5452 }
5453
5454 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
5455 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
5456 return reinterpret_cast<uintptr_t>(dup);
5457 }
5458
NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv * env,jclass,jlong x509RevokedRef)5459 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass, jlong x509RevokedRef) {
5460 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5461 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
5462
5463 if (revoked == NULL) {
5464 jniThrowNullPointerException(env, "revoked == null");
5465 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
5466 return 0;
5467 }
5468
5469 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate);
5470 return reinterpret_cast<uintptr_t>(revoked->revocationDate);
5471 }
5472
5473 #pragma GCC diagnostic push
5474 #pragma GCC diagnostic ignored "-Wwrite-strings"
NativeCrypto_X509_REVOKED_print(JNIEnv * env,jclass,jlong bioRef,jlong x509RevokedRef)5475 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) {
5476 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5477 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5478 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
5479
5480 if (bio == NULL) {
5481 jniThrowNullPointerException(env, "bio == null");
5482 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
5483 return;
5484 }
5485
5486 if (revoked == NULL) {
5487 jniThrowNullPointerException(env, "revoked == null");
5488 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
5489 return;
5490 }
5491
5492 BIO_printf(bio, "Serial Number: ");
5493 i2a_ASN1_INTEGER(bio, revoked->serialNumber);
5494 BIO_printf(bio, "\nRevocation Date: ");
5495 ASN1_TIME_print(bio, revoked->revocationDate);
5496 BIO_printf(bio, "\n");
5497 X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
5498 }
5499 #pragma GCC diagnostic pop
5500
NativeCrypto_get_X509_CRL_crl_enc(JNIEnv * env,jclass,jlong x509CrlRef)5501 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) {
5502 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5503 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
5504 return ASN1ToByteArray<X509_CRL_INFO, i2d_X509_CRL_INFO>(env, crl->crl);
5505 }
5506
NativeCrypto_X509_CRL_verify(JNIEnv * env,jclass,jlong x509CrlRef,jlong pkeyRef)5507 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef, jlong pkeyRef) {
5508 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5509 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
5510 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
5511
5512 if (crl == NULL) {
5513 jniThrowNullPointerException(env, "crl == null");
5514 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
5515 return;
5516 }
5517
5518 if (pkey == NULL) {
5519 jniThrowNullPointerException(env, "pkey == null");
5520 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
5521 return;
5522 }
5523
5524 if (X509_CRL_verify(crl, pkey) != 1) {
5525 throwExceptionIfNecessary(env, "X509_CRL_verify");
5526 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
5527 } else {
5528 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
5529 }
5530 }
5531
NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv * env,jclass,jlong x509CrlRef)5532 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
5533 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5534 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
5535
5536 if (crl == NULL) {
5537 jniThrowNullPointerException(env, "crl == null");
5538 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
5539 return 0;
5540 }
5541
5542 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
5543 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5544 return reinterpret_cast<uintptr_t>(lastUpdate);
5545 }
5546
NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv * env,jclass,jlong x509CrlRef)5547 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
5548 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5549 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
5550
5551 if (crl == NULL) {
5552 jniThrowNullPointerException(env, "crl == null");
5553 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
5554 return 0;
5555 }
5556
5557 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
5558 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5559 return reinterpret_cast<uintptr_t>(nextUpdate);
5560 }
5561
NativeCrypto_i2d_X509_REVOKED(JNIEnv * env,jclass,jlong x509RevokedRef)5562 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
5563 X509_REVOKED* x509Revoked =
5564 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5565 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
5566 return ASN1ToByteArray<X509_REVOKED, i2d_X509_REVOKED>(env, x509Revoked);
5567 }
5568
NativeCrypto_X509_supported_extension(JNIEnv * env,jclass,jlong x509ExtensionRef)5569 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
5570 X509_EXTENSION* ext = reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
5571
5572 if (ext == NULL) {
5573 jniThrowNullPointerException(env, "ext == NULL");
5574 return 0;
5575 }
5576
5577 return X509_supported_extension(ext);
5578 }
5579
get_ASN1_TIME_data(char ** data,int * output,size_t len)5580 static inline void get_ASN1_TIME_data(char **data, int* output, size_t len) {
5581 char c = **data;
5582 **data = '\0';
5583 *data -= len;
5584 *output = atoi(*data);
5585 *(*data + len) = c;
5586 }
5587
NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv * env,jclass,jlong asn1TimeRef,jobject calendar)5588 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef, jobject calendar) {
5589 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5590 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5591
5592 if (asn1Time == NULL) {
5593 jniThrowNullPointerException(env, "asn1Time == null");
5594 return;
5595 }
5596
5597 Unique_ASN1_GENERALIZEDTIME gen(ASN1_TIME_to_generalizedtime(asn1Time, NULL));
5598 if (gen.get() == NULL) {
5599 jniThrowNullPointerException(env, "asn1Time == null");
5600 return;
5601 }
5602
5603 if (gen->length < 14 || gen->data == NULL) {
5604 jniThrowNullPointerException(env, "gen->length < 14 || gen->data == NULL");
5605 return;
5606 }
5607
5608 int sec, min, hour, mday, mon, year;
5609
5610 char *p = (char*) &gen->data[14];
5611
5612 get_ASN1_TIME_data(&p, &sec, 2);
5613 get_ASN1_TIME_data(&p, &min, 2);
5614 get_ASN1_TIME_data(&p, &hour, 2);
5615 get_ASN1_TIME_data(&p, &mday, 2);
5616 get_ASN1_TIME_data(&p, &mon, 2);
5617 get_ASN1_TIME_data(&p, &year, 4);
5618
5619 env->CallVoidMethod(calendar, calendar_setMethod, year, mon - 1, mday, hour, min, sec);
5620 }
5621
NativeCrypto_OBJ_txt2nid_oid(JNIEnv * env,jclass,jstring oidStr)5622 static jstring NativeCrypto_OBJ_txt2nid_oid(JNIEnv* env, jclass, jstring oidStr) {
5623 JNI_TRACE("OBJ_txt2nid_oid(%p)", oidStr);
5624
5625 ScopedUtfChars oid(env, oidStr);
5626 if (oid.c_str() == NULL) {
5627 return NULL;
5628 }
5629
5630 JNI_TRACE("OBJ_txt2nid_oid(%s)", oid.c_str());
5631
5632 int nid = OBJ_txt2nid(oid.c_str());
5633 if (nid == NID_undef) {
5634 JNI_TRACE("OBJ_txt2nid_oid(%s) => NID_undef", oid.c_str());
5635 freeOpenSslErrorState();
5636 return NULL;
5637 }
5638
5639 Unique_ASN1_OBJECT obj(OBJ_nid2obj(nid));
5640 if (obj.get() == NULL) {
5641 throwExceptionIfNecessary(env, "OBJ_nid2obj");
5642 return NULL;
5643 }
5644
5645 ScopedLocalRef<jstring> ouputStr(env, ASN1_OBJECT_to_OID_string(env, obj.get()));
5646 JNI_TRACE("OBJ_txt2nid_oid(%s) => %p", oid.c_str(), ouputStr.get());
5647 return ouputStr.release();
5648 }
5649
NativeCrypto_X509_NAME_print_ex(JNIEnv * env,jclass,jlong x509NameRef,jlong jflags)5650 static jstring NativeCrypto_X509_NAME_print_ex(JNIEnv* env, jclass, jlong x509NameRef, jlong jflags) {
5651 X509_NAME* x509name = reinterpret_cast<X509_NAME*>(static_cast<uintptr_t>(x509NameRef));
5652 unsigned long flags = static_cast<unsigned long>(jflags);
5653 JNI_TRACE("X509_NAME_print_ex(%p, %ld)", x509name, flags);
5654
5655 if (x509name == NULL) {
5656 jniThrowNullPointerException(env, "x509name == null");
5657 JNI_TRACE("X509_NAME_print_ex(%p, %ld) => x509name == null", x509name, flags);
5658 return NULL;
5659 }
5660
5661 return X509_NAME_to_jstring(env, x509name, flags);
5662 }
5663
5664 template <typename T, T* (*d2i_func)(BIO*, T**)>
d2i_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5665 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5666 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5667 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
5668
5669 if (bio == NULL) {
5670 jniThrowNullPointerException(env, "bio == null");
5671 return 0;
5672 }
5673
5674 T* x = d2i_func(bio, NULL);
5675 if (x == NULL) {
5676 throwExceptionIfNecessary(env, "d2i_ASN1Object_to_jlong");
5677 return 0;
5678 }
5679
5680 return reinterpret_cast<uintptr_t>(x);
5681 }
5682
NativeCrypto_d2i_X509_CRL_bio(JNIEnv * env,jclass,jlong bioRef)5683 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
5684 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
5685 }
5686
NativeCrypto_d2i_X509_bio(JNIEnv * env,jclass,jlong bioRef)5687 static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5688 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
5689 }
5690
NativeCrypto_d2i_X509(JNIEnv * env,jclass,jbyteArray certBytes)5691 static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
5692 X509* x = ByteArrayToASN1<X509, d2i_X509>(env, certBytes);
5693 return reinterpret_cast<uintptr_t>(x);
5694 }
5695
NativeCrypto_i2d_X509(JNIEnv * env,jclass,jlong x509Ref)5696 static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref) {
5697 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5698 JNI_TRACE("i2d_X509(%p)", x509);
5699 return ASN1ToByteArray<X509, i2d_X509>(env, x509);
5700 }
5701
NativeCrypto_i2d_X509_PUBKEY(JNIEnv * env,jclass,jlong x509Ref)5702 static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref) {
5703 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5704 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
5705 return ASN1ToByteArray<X509_PUBKEY, i2d_X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509));
5706 }
5707
5708
5709 template<typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
PEM_ASN1Object_to_jlong(JNIEnv * env,jlong bioRef)5710 static jlong PEM_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
5711 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5712 JNI_TRACE("PEM_ASN1Object_to_jlong(%p)", bio);
5713
5714 if (bio == NULL) {
5715 jniThrowNullPointerException(env, "bio == null");
5716 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => bio == null", bio);
5717 return 0;
5718 }
5719
5720 T* x = PEM_read_func(bio, NULL, NULL, NULL);
5721 if (x == NULL) {
5722 throwExceptionIfNecessary(env, "PEM_ASN1Object_to_jlong");
5723 // Sometimes the PEM functions fail without pushing an error
5724 if (!env->ExceptionCheck()) {
5725 jniThrowRuntimeException(env, "Failure parsing PEM");
5726 }
5727 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => threw exception", bio);
5728 return 0;
5729 }
5730
5731 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => %p", bio, x);
5732 return reinterpret_cast<uintptr_t>(x);
5733 }
5734
NativeCrypto_PEM_read_bio_X509(JNIEnv * env,jclass,jlong bioRef)5735 static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
5736 JNI_TRACE("PEM_read_bio_X509(0x%llx)", bioRef);
5737 return PEM_ASN1Object_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
5738 }
5739
NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv * env,jclass,jlong bioRef)5740 static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
5741 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", bioRef);
5742 return PEM_ASN1Object_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
5743 }
5744
STACK_OF(X509)5745 static STACK_OF(X509)* PKCS7_get_certs(PKCS7* pkcs7) {
5746 if (PKCS7_type_is_signed(pkcs7)) {
5747 return pkcs7->d.sign->cert;
5748 } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5749 return pkcs7->d.signed_and_enveloped->cert;
5750 } else {
5751 JNI_TRACE("PKCS7_get_certs(%p) => unknown PKCS7 type", pkcs7);
5752 return NULL;
5753 }
5754 }
5755
STACK_OF(X509_CRL)5756 static STACK_OF(X509_CRL)* PKCS7_get_CRLs(PKCS7* pkcs7) {
5757 if (PKCS7_type_is_signed(pkcs7)) {
5758 return pkcs7->d.sign->crl;
5759 } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
5760 return pkcs7->d.signed_and_enveloped->crl;
5761 } else {
5762 JNI_TRACE("PKCS7_get_CRLs(%p) => unknown PKCS7 type", pkcs7);
5763 return NULL;
5764 }
5765 }
5766
5767 template <typename T, typename T_stack>
PKCS7_to_ItemArray(JNIEnv * env,T_stack * stack,T * (* dup_func)(T *))5768 static jlongArray PKCS7_to_ItemArray(JNIEnv* env, T_stack* stack, T* (*dup_func)(T*))
5769 {
5770 if (stack == NULL) {
5771 return NULL;
5772 }
5773
5774 ScopedLocalRef<jlongArray> ref_array(env, NULL);
5775 size_t size = sk_num(reinterpret_cast<_STACK*>(stack));
5776 ref_array.reset(env->NewLongArray(size));
5777 ScopedLongArrayRW items(env, ref_array.get());
5778 for (size_t i = 0; i < size; i++) {
5779 T* item = reinterpret_cast<T*>(sk_value(reinterpret_cast<_STACK*>(stack), i));
5780 items[i] = reinterpret_cast<uintptr_t>(dup_func(item));
5781 }
5782
5783 JNI_TRACE("PKCS7_to_ItemArray(%p) => %p [size=%d]", stack, ref_array.get(), size);
5784 return ref_array.release();
5785 }
5786
5787 #define PKCS7_CERTS 1
5788 #define PKCS7_CRLS 2
5789
NativeCrypto_PEM_read_bio_PKCS7(JNIEnv * env,jclass,jlong bioRef,jint which)5790 static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
5791 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5792 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
5793
5794 if (bio == NULL) {
5795 jniThrowNullPointerException(env, "bio == null");
5796 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
5797 return 0;
5798 }
5799
5800 Unique_PKCS7 pkcs7(PEM_read_bio_PKCS7(bio, NULL, NULL, NULL));
5801 if (pkcs7.get() == NULL) {
5802 throwExceptionIfNecessary(env, "PEM_read_bio_PKCS7_CRLs");
5803 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => threw exception", bio);
5804 return 0;
5805 }
5806
5807 switch (which) {
5808 case PKCS7_CERTS:
5809 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5810 case PKCS7_CRLS:
5811 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5812 X509_CRL_dup);
5813 default:
5814 jniThrowRuntimeException(env, "unknown PKCS7 field");
5815 return NULL;
5816 }
5817 }
5818
NativeCrypto_d2i_PKCS7_bio(JNIEnv * env,jclass,jlong bioRef,jint which)5819 static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
5820 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5821 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
5822
5823 if (bio == NULL) {
5824 jniThrowNullPointerException(env, "bio == null");
5825 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
5826 return 0;
5827 }
5828
5829 Unique_PKCS7 pkcs7(d2i_PKCS7_bio(bio, NULL));
5830 if (pkcs7.get() == NULL) {
5831 throwExceptionIfNecessary(env, "d2i_PKCS7_bio");
5832 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => threw exception", bio, which);
5833 return 0;
5834 }
5835
5836 switch (which) {
5837 case PKCS7_CERTS:
5838 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
5839 case PKCS7_CRLS:
5840 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
5841 X509_CRL_dup);
5842 default:
5843 jniThrowRuntimeException(env, "unknown PKCS7 field");
5844 return NULL;
5845 }
5846 }
5847
NativeCrypto_i2d_PKCS7(JNIEnv * env,jclass,jlongArray certsArray)5848 static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
5849 JNI_TRACE("i2d_PKCS7(%p)", certsArray);
5850
5851 Unique_PKCS7 pkcs7(PKCS7_new());
5852 if (pkcs7.get() == NULL) {
5853 jniThrowNullPointerException(env, "pkcs7 == null");
5854 JNI_TRACE("i2d_PKCS7(%p) => pkcs7 == null", certsArray);
5855 return NULL;
5856 }
5857
5858 if (PKCS7_set_type(pkcs7.get(), NID_pkcs7_signed) != 1) {
5859 throwExceptionIfNecessary(env, "PKCS7_set_type");
5860 return NULL;
5861 }
5862
5863 // The EncapsulatedContentInfo must be present in the output, but OpenSSL
5864 // will fill in a zero-length OID if you don't call PKCS7_set_content on the
5865 // outer PKCS7 container. So we construct an empty PKCS7 data container and
5866 // set it as the content.
5867 Unique_PKCS7 pkcs7Data(PKCS7_new());
5868 if (PKCS7_set_type(pkcs7Data.get(), NID_pkcs7_data) != 1) {
5869 throwExceptionIfNecessary(env, "PKCS7_set_type data");
5870 return NULL;
5871 }
5872
5873 if (PKCS7_set_content(pkcs7.get(), pkcs7Data.get()) != 1) {
5874 throwExceptionIfNecessary(env, "PKCS7_set_content");
5875 return NULL;
5876 }
5877 OWNERSHIP_TRANSFERRED(pkcs7Data);
5878
5879 ScopedLongArrayRO certs(env, certsArray);
5880 for (size_t i = 0; i < certs.size(); i++) {
5881 X509* item = reinterpret_cast<X509*>(certs[i]);
5882 if (PKCS7_add_certificate(pkcs7.get(), item) != 1) {
5883 throwExceptionIfNecessary(env, "i2d_PKCS7");
5884 return NULL;
5885 }
5886 }
5887
5888 JNI_TRACE("i2d_PKCS7(%p) => %d certs", certsArray, certs.size());
5889 return ASN1ToByteArray<PKCS7, i2d_PKCS7>(env, pkcs7.get());
5890 }
5891
5892 typedef STACK_OF(X509) PKIPATH;
5893
ASN1_ITEM_TEMPLATE(PKIPATH)5894 ASN1_ITEM_TEMPLATE(PKIPATH) =
5895 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PkiPath, X509)
5896 ASN1_ITEM_TEMPLATE_END(PKIPATH)
5897
5898 static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
5899 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5900 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
5901
5902 Unique_sk_X509 path((PKIPATH*) ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKIPATH), bio, NULL));
5903 if (path.get() == NULL) {
5904 throwExceptionIfNecessary(env, "ASN1_seq_unpack_X509_bio");
5905 return NULL;
5906 }
5907
5908 size_t size = sk_X509_num(path.get());
5909
5910 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(size));
5911 ScopedLongArrayRW certs(env, certArray.get());
5912 for (size_t i = 0; i < size; i++) {
5913 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
5914 certs[i] = reinterpret_cast<uintptr_t>(item);
5915 }
5916
5917 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %d items", bio, size);
5918 return certArray.release();
5919 }
5920
NativeCrypto_ASN1_seq_pack_X509(JNIEnv * env,jclass,jlongArray certs)5921 static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
5922 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
5923 ScopedLongArrayRO certsArray(env, certs);
5924 if (certsArray.get() == NULL) {
5925 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
5926 return NULL;
5927 }
5928
5929 Unique_sk_X509 certStack(sk_X509_new_null());
5930 if (certStack.get() == NULL) {
5931 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to make cert stack", certs);
5932 return NULL;
5933 }
5934
5935 for (size_t i = 0; i < certsArray.size(); i++) {
5936 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
5937 sk_X509_push(certStack.get(), X509_dup_nocopy(x509));
5938 }
5939
5940 int len;
5941 Unique_OPENSSL_str encoded(ASN1_seq_pack(
5942 reinterpret_cast<STACK_OF(OPENSSL_BLOCK)*>(
5943 reinterpret_cast<uintptr_t>(certStack.get())),
5944 reinterpret_cast<int (*)(void*, unsigned char**)>(i2d_X509), NULL, &len));
5945 if (encoded.get() == NULL) {
5946 JNI_TRACE("ASN1_seq_pack_X509(%p) => trouble encoding", certs);
5947 return NULL;
5948 }
5949
5950 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
5951 if (byteArray.get() == NULL) {
5952 JNI_TRACE("ASN1_seq_pack_X509(%p) => creating byte array failed", certs);
5953 return NULL;
5954 }
5955
5956 ScopedByteArrayRW bytes(env, byteArray.get());
5957 if (bytes.get() == NULL) {
5958 JNI_TRACE("ASN1_seq_pack_X509(%p) => using byte array failed", certs);
5959 return NULL;
5960 }
5961
5962 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
5963 memcpy(p, encoded.get(), len);
5964
5965 return byteArray.release();
5966 }
5967
NativeCrypto_X509_free(JNIEnv * env,jclass,jlong x509Ref)5968 static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref) {
5969 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5970 JNI_TRACE("X509_free(%p)", x509);
5971
5972 if (x509 == NULL) {
5973 jniThrowNullPointerException(env, "x509 == null");
5974 JNI_TRACE("X509_free(%p) => x509 == null", x509);
5975 return;
5976 }
5977
5978 X509_free(x509);
5979 }
5980
NativeCrypto_X509_cmp(JNIEnv * env,jclass,jlong x509Ref1,jlong x509Ref2)5981 static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1, jlong x509Ref2) {
5982 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5983 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5984 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
5985
5986 if (x509_1 == NULL) {
5987 jniThrowNullPointerException(env, "x509_1 == null");
5988 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
5989 return -1;
5990 }
5991
5992 if (x509_2 == NULL) {
5993 jniThrowNullPointerException(env, "x509_2 == null");
5994 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
5995 return -1;
5996 }
5997
5998 int ret = X509_cmp(x509_1, x509_2);
5999 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6000 return ret;
6001 }
6002
NativeCrypto_get_X509_hashCode(JNIEnv * env,jclass,jlong x509Ref)6003 static jint NativeCrypto_get_X509_hashCode(JNIEnv* env, jclass, jlong x509Ref) {
6004 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6005
6006 if (x509 == NULL) {
6007 jniThrowNullPointerException(env, "x509 == null");
6008 JNI_TRACE("get_X509_hashCode(%p) => x509 == null", x509);
6009 return 0;
6010 }
6011
6012 // Force caching extensions.
6013 X509_check_ca(x509);
6014
6015 jint hashCode = 0L;
6016 for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
6017 hashCode = 31 * hashCode + x509->sha1_hash[i];
6018 }
6019 return hashCode;
6020 }
6021
NativeCrypto_X509_print_ex(JNIEnv * env,jclass,jlong bioRef,jlong x509Ref,jlong nmflagJava,jlong certflagJava)6022 static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6023 jlong nmflagJava, jlong certflagJava) {
6024 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6025 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6026 long nmflag = static_cast<long>(nmflagJava);
6027 long certflag = static_cast<long>(certflagJava);
6028 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6029
6030 if (bio == NULL) {
6031 jniThrowNullPointerException(env, "bio == null");
6032 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6033 return;
6034 }
6035
6036 if (x509 == NULL) {
6037 jniThrowNullPointerException(env, "x509 == null");
6038 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6039 return;
6040 }
6041
6042 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6043 throwExceptionIfNecessary(env, "X509_print_ex");
6044 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6045 } else {
6046 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6047 }
6048 }
6049
NativeCrypto_X509_get_pubkey(JNIEnv * env,jclass,jlong x509Ref)6050 static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref) {
6051 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6052 JNI_TRACE("X509_get_pubkey(%p)", x509);
6053
6054 if (x509 == NULL) {
6055 jniThrowNullPointerException(env, "x509 == null");
6056 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6057 return 0;
6058 }
6059
6060 Unique_EVP_PKEY pkey(X509_get_pubkey(x509));
6061 if (pkey.get() == NULL) {
6062 throwExceptionIfNecessary(env, "X509_get_pubkey");
6063 return 0;
6064 }
6065
6066 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
6067 return reinterpret_cast<uintptr_t>(pkey.release());
6068 }
6069
NativeCrypto_X509_get_issuer_name(JNIEnv * env,jclass,jlong x509Ref)6070 static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref) {
6071 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6072 JNI_TRACE("X509_get_issuer_name(%p)", x509);
6073 return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_issuer_name(x509));
6074 }
6075
NativeCrypto_X509_get_subject_name(JNIEnv * env,jclass,jlong x509Ref)6076 static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref) {
6077 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6078 JNI_TRACE("X509_get_subject_name(%p)", x509);
6079 return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_get_subject_name(x509));
6080 }
6081
NativeCrypto_get_X509_pubkey_oid(JNIEnv * env,jclass,jlong x509Ref)6082 static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref) {
6083 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6084 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6085
6086 if (x509 == NULL) {
6087 jniThrowNullPointerException(env, "x509 == null");
6088 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6089 return NULL;
6090 }
6091
6092 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6093 return ASN1_OBJECT_to_OID_string(env, pubkey->algor->algorithm);
6094 }
6095
NativeCrypto_get_X509_sig_alg_oid(JNIEnv * env,jclass,jlong x509Ref)6096 static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref) {
6097 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6098 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6099
6100 if (x509 == NULL || x509->sig_alg == NULL) {
6101 jniThrowNullPointerException(env, "x509 == NULL || x509->sig_alg == NULL");
6102 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == NULL", x509);
6103 return NULL;
6104 }
6105
6106 return ASN1_OBJECT_to_OID_string(env, x509->sig_alg->algorithm);
6107 }
6108
NativeCrypto_get_X509_sig_alg_parameter(JNIEnv * env,jclass,jlong x509Ref)6109 static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref) {
6110 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6111 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6112
6113 if (x509 == NULL) {
6114 jniThrowNullPointerException(env, "x509 == null");
6115 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6116 return NULL;
6117 }
6118
6119 if (x509->sig_alg->parameter == NULL) {
6120 JNI_TRACE("get_X509_sig_alg_parameter(%p) => null", x509);
6121 return NULL;
6122 }
6123
6124 return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, x509->sig_alg->parameter);
6125 }
6126
NativeCrypto_get_X509_issuerUID(JNIEnv * env,jclass,jlong x509Ref)6127 static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref) {
6128 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6129 JNI_TRACE("get_X509_issuerUID(%p)", x509);
6130
6131 if (x509 == NULL) {
6132 jniThrowNullPointerException(env, "x509 == null");
6133 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
6134 return NULL;
6135 }
6136
6137 if (x509->cert_info->issuerUID == NULL) {
6138 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
6139 return NULL;
6140 }
6141
6142 return ASN1BitStringToBooleanArray(env, x509->cert_info->issuerUID);
6143 }
NativeCrypto_get_X509_subjectUID(JNIEnv * env,jclass,jlong x509Ref)6144 static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref) {
6145 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6146 JNI_TRACE("get_X509_subjectUID(%p)", x509);
6147
6148 if (x509 == NULL) {
6149 jniThrowNullPointerException(env, "x509 == null");
6150 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
6151 return NULL;
6152 }
6153
6154 if (x509->cert_info->subjectUID == NULL) {
6155 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
6156 return NULL;
6157 }
6158
6159 return ASN1BitStringToBooleanArray(env, x509->cert_info->subjectUID);
6160 }
6161
NativeCrypto_get_X509_ex_kusage(JNIEnv * env,jclass,jlong x509Ref)6162 static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref) {
6163 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6164 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
6165
6166 if (x509 == NULL) {
6167 jniThrowNullPointerException(env, "x509 == null");
6168 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
6169 return NULL;
6170 }
6171
6172 Unique_ASN1_BIT_STRING bitStr(static_cast<ASN1_BIT_STRING*>(
6173 X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL)));
6174 if (bitStr.get() == NULL) {
6175 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
6176 return NULL;
6177 }
6178
6179 return ASN1BitStringToBooleanArray(env, bitStr.get());
6180 }
6181
NativeCrypto_get_X509_ex_xkusage(JNIEnv * env,jclass,jlong x509Ref)6182 static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref) {
6183 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6184 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
6185
6186 if (x509 == NULL) {
6187 jniThrowNullPointerException(env, "x509 == null");
6188 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
6189 return NULL;
6190 }
6191
6192 Unique_sk_ASN1_OBJECT objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
6193 X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)));
6194 if (objArray.get() == NULL) {
6195 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
6196 return NULL;
6197 }
6198
6199 size_t size = sk_ASN1_OBJECT_num(objArray.get());
6200 ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
6201 if (exKeyUsage.get() == NULL) {
6202 return NULL;
6203 }
6204
6205 for (size_t i = 0; i < size; i++) {
6206 ScopedLocalRef<jstring> oidStr(env, ASN1_OBJECT_to_OID_string(env,
6207 sk_ASN1_OBJECT_value(objArray.get(), i)));
6208 env->SetObjectArrayElement(exKeyUsage.get(), i, oidStr.get());
6209 }
6210
6211 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%d entries)", x509, size);
6212 return exKeyUsage.release();
6213 }
6214
NativeCrypto_get_X509_ex_pathlen(JNIEnv * env,jclass,jlong x509Ref)6215 static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref) {
6216 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6217 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
6218
6219 if (x509 == NULL) {
6220 jniThrowNullPointerException(env, "x509 == null");
6221 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
6222 return 0;
6223 }
6224
6225 /* Just need to do this to cache the ex_* values. */
6226 X509_check_ca(x509);
6227
6228 JNI_TRACE("get_X509_ex_pathlen(%p) => %ld", x509, x509->ex_pathlen);
6229 return x509->ex_pathlen;
6230 }
6231
NativeCrypto_X509_get_ext_oid(JNIEnv * env,jclass,jlong x509Ref,jstring oidString)6232 static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
6233 jstring oidString) {
6234 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6235 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
6236 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
6237 }
6238
NativeCrypto_X509_CRL_get_ext_oid(JNIEnv * env,jclass,jlong x509CrlRef,jstring oidString)6239 static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
6240 jstring oidString) {
6241 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6242 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
6243 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
6244 oidString);
6245 }
6246
NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv * env,jclass,jlong x509RevokedRef,jstring oidString)6247 static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
6248 jstring oidString) {
6249 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6250 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
6251 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
6252 env, revoked, oidString);
6253 }
6254
6255 template<typename T, int (*get_ext_by_critical_func)(T*, int, int), X509_EXTENSION* (*get_ext_func)(T*, int)>
get_X509Type_ext_oids(JNIEnv * env,jlong x509Ref,jint critical)6256 static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
6257 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
6258 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
6259
6260 if (x509 == NULL) {
6261 jniThrowNullPointerException(env, "x509 == null");
6262 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
6263 return NULL;
6264 }
6265
6266 int lastPos = -1;
6267 int count = 0;
6268 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6269 count++;
6270 }
6271
6272 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
6273
6274 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
6275 if (joa.get() == NULL) {
6276 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
6277 return NULL;
6278 }
6279
6280 lastPos = -1;
6281 count = 0;
6282 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
6283 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
6284
6285 ScopedLocalRef<jstring> extOid(env, ASN1_OBJECT_to_OID_string(env, ext->object));
6286 if (extOid.get() == NULL) {
6287 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
6288 return NULL;
6289 }
6290
6291 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
6292 }
6293
6294 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
6295 return joa.release();
6296 }
6297
NativeCrypto_get_X509_ext_oids(JNIEnv * env,jclass,jlong x509Ref,jint critical)6298 static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
6299 jint critical) {
6300 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", x509Ref, critical);
6301 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
6302 critical);
6303 }
6304
NativeCrypto_get_X509_CRL_ext_oids(JNIEnv * env,jclass,jlong x509CrlRef,jint critical)6305 static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
6306 jint critical) {
6307 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509CrlRef, critical);
6308 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(env,
6309 x509CrlRef, critical);
6310 }
6311
NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv * env,jclass,jlong x509RevokedRef,jint critical)6312 static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass, jlong x509RevokedRef,
6313 jint critical) {
6314 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", x509RevokedRef, critical);
6315 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
6316 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
6317 }
6318
6319 #ifdef WITH_JNI_TRACE
6320 /**
6321 * Based on example logging call back from SSL_CTX_set_info_callback man page
6322 */
info_callback_LOG(const SSL * s,int where,int ret)6323 static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
6324 {
6325 int w = where & ~SSL_ST_MASK;
6326 const char* str;
6327 if (w & SSL_ST_CONNECT) {
6328 str = "SSL_connect";
6329 } else if (w & SSL_ST_ACCEPT) {
6330 str = "SSL_accept";
6331 } else {
6332 str = "undefined";
6333 }
6334
6335 if (where & SSL_CB_LOOP) {
6336 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
6337 } else if (where & SSL_CB_ALERT) {
6338 str = (where & SSL_CB_READ) ? "read" : "write";
6339 JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
6340 s,
6341 str,
6342 SSL_alert_type_string(ret),
6343 SSL_alert_desc_string(ret),
6344 SSL_alert_type_string_long(ret),
6345 SSL_alert_desc_string_long(ret));
6346 } else if (where & SSL_CB_EXIT) {
6347 if (ret == 0) {
6348 JNI_TRACE("ssl=%p %s:failed exit in %s %s",
6349 s, str, SSL_state_string(s), SSL_state_string_long(s));
6350 } else if (ret < 0) {
6351 JNI_TRACE("ssl=%p %s:error exit in %s %s",
6352 s, str, SSL_state_string(s), SSL_state_string_long(s));
6353 } else if (ret == 1) {
6354 JNI_TRACE("ssl=%p %s:ok exit in %s %s",
6355 s, str, SSL_state_string(s), SSL_state_string_long(s));
6356 } else {
6357 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
6358 s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
6359 }
6360 } else if (where & SSL_CB_HANDSHAKE_START) {
6361 JNI_TRACE("ssl=%p handshake start in %s %s",
6362 s, SSL_state_string(s), SSL_state_string_long(s));
6363 } else if (where & SSL_CB_HANDSHAKE_DONE) {
6364 JNI_TRACE("ssl=%p handshake done in %s %s",
6365 s, SSL_state_string(s), SSL_state_string_long(s));
6366 } else {
6367 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
6368 s, str, where, SSL_state_string(s), SSL_state_string_long(s));
6369 }
6370 }
6371 #endif
6372
6373 /**
6374 * Returns an array containing all the X509 certificate references
6375 */
getCertificateRefs(JNIEnv * env,const STACK_OF (X509)* chain)6376 static jlongArray getCertificateRefs(JNIEnv* env, const STACK_OF(X509)* chain)
6377 {
6378 if (chain == NULL) {
6379 // Chain can be NULL if the associated cipher doesn't do certs.
6380 return NULL;
6381 }
6382 ssize_t count = sk_X509_num(chain);
6383 if (count <= 0) {
6384 return NULL;
6385 }
6386 ScopedLocalRef<jlongArray> refArray(env, env->NewLongArray(count));
6387 ScopedLongArrayRW refs(env, refArray.get());
6388 if (refs.get() == NULL) {
6389 return NULL;
6390 }
6391 for (ssize_t i = 0; i < count; i++) {
6392 refs[i] = reinterpret_cast<uintptr_t>(X509_dup_nocopy(sk_X509_value(chain, i)));
6393 }
6394 return refArray.release();
6395 }
6396
6397 /**
6398 * Returns an array containing all the X500 principal's bytes.
6399 */
getPrincipalBytes(JNIEnv * env,const STACK_OF (X509_NAME)* names)6400 static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
6401 {
6402 if (names == NULL) {
6403 return NULL;
6404 }
6405
6406 int count = sk_X509_NAME_num(names);
6407 if (count <= 0) {
6408 return NULL;
6409 }
6410
6411 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
6412 if (joa.get() == NULL) {
6413 return NULL;
6414 }
6415
6416 for (int i = 0; i < count; i++) {
6417 X509_NAME* principal = sk_X509_NAME_value(names, i);
6418
6419 ScopedLocalRef<jbyteArray> byteArray(env, ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env,
6420 principal));
6421 if (byteArray.get() == NULL) {
6422 return NULL;
6423 }
6424 env->SetObjectArrayElement(joa.get(), i, byteArray.get());
6425 }
6426
6427 return joa.release();
6428 }
6429
6430 /**
6431 * Our additional application data needed for getting synchronization right.
6432 * This maybe warrants a bit of lengthy prose:
6433 *
6434 * (1) We use a flag to reflect whether we consider the SSL connection alive.
6435 * Any read or write attempt loops will be cancelled once this flag becomes 0.
6436 *
6437 * (2) We use an int to count the number of threads that are blocked by the
6438 * underlying socket. This may be at most two (one reader and one writer), since
6439 * the Java layer ensures that no more threads will enter the native code at the
6440 * same time.
6441 *
6442 * (3) The pipe is used primarily as a means of cancelling a blocking select()
6443 * when we want to close the connection (aka "emergency button"). It is also
6444 * necessary for dealing with a possible race condition situation: There might
6445 * be cases where both threads see an SSL_ERROR_WANT_READ or
6446 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
6447 * If one leaves the select() successfully before the other enters it, the
6448 * "success" event is already consumed and the second thread will be blocked,
6449 * possibly forever (depending on network conditions).
6450 *
6451 * The idea for solving the problem looks like this: Whenever a thread is
6452 * successful in moving around data on the network, and it knows there is
6453 * another thread stuck in a select(), it will write a byte to the pipe, waking
6454 * up the other thread. A thread that returned from select(), on the other hand,
6455 * knows whether it's been woken up by the pipe. If so, it will consume the
6456 * byte, and the original state of affairs has been restored.
6457 *
6458 * The pipe may seem like a bit of overhead, but it fits in nicely with the
6459 * other file descriptors of the select(), so there's only one condition to wait
6460 * for.
6461 *
6462 * (4) Finally, a mutex is needed to make sure that at most one thread is in
6463 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
6464 * requirement. We use the same mutex to guard the field for counting the
6465 * waiting threads.
6466 *
6467 * Note: The current implementation assumes that we don't have to deal with
6468 * problems induced by multiple cores or processors and their respective
6469 * memory caches. One possible problem is that of inconsistent views on the
6470 * "aliveAndKicking" field. This could be worked around by also enclosing all
6471 * accesses to that field inside a lock/unlock sequence of our mutex, but
6472 * currently this seems a bit like overkill. Marking volatile at the very least.
6473 *
6474 * During handshaking, additional fields are used to up-call into
6475 * Java to perform certificate verification and handshake
6476 * completion. These are also used in any renegotiation.
6477 *
6478 * (5) the JNIEnv so we can invoke the Java callback
6479 *
6480 * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
6481 *
6482 * (7) a java.io.FileDescriptor wrapper to check for socket close
6483 *
6484 * We store the NPN protocols list so we can either send it (from the server) or
6485 * select a protocol (on the client). We eagerly acquire a pointer to the array
6486 * data so the callback doesn't need to acquire resources that it cannot
6487 * release.
6488 *
6489 * Because renegotiation can be requested by the peer at any time,
6490 * care should be taken to maintain an appropriate JNIEnv on any
6491 * downcall to openssl since it could result in an upcall to Java. The
6492 * current code does try to cover these cases by conditionally setting
6493 * the JNIEnv on calls that can read and write to the SSL such as
6494 * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
6495 *
6496 * Finally, we have two emphemeral keys setup by OpenSSL callbacks:
6497 *
6498 * (8) a set of ephemeral RSA keys that is lazily generated if a peer
6499 * wants to use an exportable RSA cipher suite.
6500 *
6501 * (9) a set of ephemeral EC keys that is lazily generated if a peer
6502 * wants to use an TLS_ECDHE_* cipher suite.
6503 *
6504 */
6505 class AppData {
6506 public:
6507 volatile int aliveAndKicking;
6508 int waitingThreads;
6509 int fdsEmergency[2];
6510 MUTEX_TYPE mutex;
6511 JNIEnv* env;
6512 jobject sslHandshakeCallbacks;
6513 jbyteArray npnProtocolsArray;
6514 jbyte* npnProtocolsData;
6515 size_t npnProtocolsLength;
6516 jbyteArray alpnProtocolsArray;
6517 jbyte* alpnProtocolsData;
6518 size_t alpnProtocolsLength;
6519 Unique_RSA ephemeralRsa;
6520 Unique_EC_KEY ephemeralEc;
6521
6522 /**
6523 * Creates the application data context for the SSL*.
6524 */
6525 public:
create()6526 static AppData* create() {
6527 UniquePtr<AppData> appData(new AppData());
6528 if (pipe(appData.get()->fdsEmergency) == -1) {
6529 ALOGE("AppData::create pipe(2) failed: %s", strerror(errno));
6530 return NULL;
6531 }
6532 if (!setBlocking(appData.get()->fdsEmergency[0], false)) {
6533 ALOGE("AppData::create fcntl(2) failed: %s", strerror(errno));
6534 return NULL;
6535 }
6536 if (MUTEX_SETUP(appData.get()->mutex) == -1) {
6537 ALOGE("pthread_mutex_init(3) failed: %s", strerror(errno));
6538 return NULL;
6539 }
6540 return appData.release();
6541 }
6542
~AppData()6543 ~AppData() {
6544 aliveAndKicking = 0;
6545 if (fdsEmergency[0] != -1) {
6546 close(fdsEmergency[0]);
6547 }
6548 if (fdsEmergency[1] != -1) {
6549 close(fdsEmergency[1]);
6550 }
6551 clearCallbackState();
6552 MUTEX_CLEANUP(mutex);
6553 }
6554
6555 private:
AppData()6556 AppData() :
6557 aliveAndKicking(1),
6558 waitingThreads(0),
6559 env(NULL),
6560 sslHandshakeCallbacks(NULL),
6561 npnProtocolsArray(NULL),
6562 npnProtocolsData(NULL),
6563 npnProtocolsLength(-1),
6564 alpnProtocolsArray(NULL),
6565 alpnProtocolsData(NULL),
6566 alpnProtocolsLength(-1),
6567 ephemeralRsa(NULL),
6568 ephemeralEc(NULL) {
6569 fdsEmergency[0] = -1;
6570 fdsEmergency[1] = -1;
6571 }
6572
6573 public:
6574 /**
6575 * Used to set the SSL-to-Java callback state before each SSL_*
6576 * call that may result in a callback. It should be cleared after
6577 * the operation returns with clearCallbackState.
6578 *
6579 * @param env The JNIEnv
6580 * @param shc The SSLHandshakeCallbacks
6581 * @param fd The FileDescriptor
6582 * @param npnProtocols NPN protocols so that they may be advertised (by the
6583 * server) or selected (by the client). Has no effect
6584 * unless NPN is enabled.
6585 * @param alpnProtocols ALPN protocols so that they may be advertised (by the
6586 * server) or selected (by the client). Passing non-NULL
6587 * enables ALPN.
6588 */
setCallbackState(JNIEnv * e,jobject shc,jobject fd,jbyteArray npnProtocols,jbyteArray alpnProtocols)6589 bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
6590 jbyteArray alpnProtocols) {
6591 UniquePtr<NetFd> netFd;
6592 if (fd != NULL) {
6593 netFd.reset(new NetFd(e, fd));
6594 if (netFd->isClosed()) {
6595 JNI_TRACE("appData=%p setCallbackState => netFd->isClosed() == true", this);
6596 return false;
6597 }
6598 }
6599 env = e;
6600 sslHandshakeCallbacks = shc;
6601 if (npnProtocols != NULL) {
6602 npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
6603 if (npnProtocolsData == NULL) {
6604 clearCallbackState();
6605 JNI_TRACE("appData=%p setCallbackState => npnProtocolsData == NULL", this);
6606 return false;
6607 }
6608 npnProtocolsArray = npnProtocols;
6609 npnProtocolsLength = e->GetArrayLength(npnProtocols);
6610 }
6611 if (alpnProtocols != NULL) {
6612 alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
6613 if (alpnProtocolsData == NULL) {
6614 clearCallbackState();
6615 JNI_TRACE("appData=%p setCallbackState => alpnProtocolsData == NULL", this);
6616 return false;
6617 }
6618 alpnProtocolsArray = alpnProtocols;
6619 alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
6620 }
6621 return true;
6622 }
6623
clearCallbackState()6624 void clearCallbackState() {
6625 sslHandshakeCallbacks = NULL;
6626 if (npnProtocolsArray != NULL) {
6627 env->ReleaseByteArrayElements(npnProtocolsArray, npnProtocolsData, JNI_ABORT);
6628 npnProtocolsArray = NULL;
6629 npnProtocolsData = NULL;
6630 npnProtocolsLength = -1;
6631 }
6632 if (alpnProtocolsArray != NULL) {
6633 env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
6634 alpnProtocolsArray = NULL;
6635 alpnProtocolsData = NULL;
6636 alpnProtocolsLength = -1;
6637 }
6638 env = NULL;
6639 }
6640
6641 };
6642
6643 /**
6644 * Dark magic helper function that checks, for a given SSL session, whether it
6645 * can SSL_read() or SSL_write() without blocking. Takes into account any
6646 * concurrent attempts to close the SSLSocket from the Java side. This is
6647 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
6648 * while thread #2 is sitting in a blocking read or write. The type argument
6649 * specifies whether we are waiting for readability or writability. It expects
6650 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
6651 * only need to wait in case one of these problems occurs.
6652 *
6653 * @param env
6654 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
6655 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
6656 * @param appData The application data structure with mutex info etc.
6657 * @param timeout_millis The timeout value for select call, with the special value
6658 * 0 meaning no timeout at all (wait indefinitely). Note: This is
6659 * the Java semantics of the timeout value, not the usual
6660 * select() semantics.
6661 * @return The result of the inner select() call,
6662 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
6663 * additional errors
6664 */
sslSelect(JNIEnv * env,int type,jobject fdObject,AppData * appData,int timeout_millis)6665 static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout_millis) {
6666 // This loop is an expanded version of the NET_FAILURE_RETRY
6667 // macro. It cannot simply be used in this case because select
6668 // cannot be restarted without recreating the fd_sets and timeout
6669 // structure.
6670 int result;
6671 fd_set rfds;
6672 fd_set wfds;
6673 do {
6674 NetFd fd(env, fdObject);
6675 if (fd.isClosed()) {
6676 result = THROWN_EXCEPTION;
6677 break;
6678 }
6679 int intFd = fd.get();
6680 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
6681 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
6682
6683 FD_ZERO(&rfds);
6684 FD_ZERO(&wfds);
6685
6686 if (type == SSL_ERROR_WANT_READ) {
6687 FD_SET(intFd, &rfds);
6688 } else {
6689 FD_SET(intFd, &wfds);
6690 }
6691
6692 FD_SET(appData->fdsEmergency[0], &rfds);
6693
6694 int maxFd = (intFd > appData->fdsEmergency[0]) ? intFd : appData->fdsEmergency[0];
6695
6696 // Build a struct for the timeout data if we actually want a timeout.
6697 timeval tv;
6698 timeval* ptv;
6699 if (timeout_millis > 0) {
6700 tv.tv_sec = timeout_millis / 1000;
6701 tv.tv_usec = (timeout_millis % 1000) * 1000;
6702 ptv = &tv;
6703 } else {
6704 ptv = NULL;
6705 }
6706
6707 #ifndef CONSCRYPT_UNBUNDLED
6708 AsynchronousCloseMonitor monitor(intFd);
6709 #else
6710 CompatibilityCloseMonitor monitor(intFd);
6711 #endif
6712 result = select(maxFd + 1, &rfds, &wfds, NULL, ptv);
6713 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
6714 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
6715 fd.get(), appData, timeout_millis, result);
6716 if (result == -1) {
6717 if (fd.isClosed()) {
6718 result = THROWN_EXCEPTION;
6719 break;
6720 }
6721 if (errno != EINTR) {
6722 break;
6723 }
6724 }
6725 } while (result == -1);
6726
6727 if (MUTEX_LOCK(appData->mutex) == -1) {
6728 return -1;
6729 }
6730
6731 if (result > 0) {
6732 // We have been woken up by a token in the emergency pipe. We
6733 // can't be sure the token is still in the pipe at this point
6734 // because it could have already been read by the thread that
6735 // originally wrote it if it entered sslSelect and acquired
6736 // the mutex before we did. Thus we cannot safely read from
6737 // the pipe in a blocking way (so we make the pipe
6738 // non-blocking at creation).
6739 if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
6740 char token;
6741 do {
6742 read(appData->fdsEmergency[0], &token, 1);
6743 } while (errno == EINTR);
6744 }
6745 }
6746
6747 // Tell the world that there is now one thread less waiting for the
6748 // underlying network.
6749 appData->waitingThreads--;
6750
6751 MUTEX_UNLOCK(appData->mutex);
6752
6753 return result;
6754 }
6755
6756 /**
6757 * Helper function that wakes up a thread blocked in select(), in case there is
6758 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
6759 * before closing the connection.
6760 *
6761 * @param data The application data structure with mutex info etc.
6762 */
sslNotify(AppData * appData)6763 static void sslNotify(AppData* appData) {
6764 // Write a byte to the emergency pipe, so a concurrent select() can return.
6765 // Note we have to restore the errno of the original system call, since the
6766 // caller relies on it for generating error messages.
6767 int errnoBackup = errno;
6768 char token = '*';
6769 do {
6770 errno = 0;
6771 write(appData->fdsEmergency[1], &token, 1);
6772 } while (errno == EINTR);
6773 errno = errnoBackup;
6774 }
6775
toAppData(const SSL * ssl)6776 static AppData* toAppData(const SSL* ssl) {
6777 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
6778 }
6779
6780 /**
6781 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
6782 */
cert_verify_callback(X509_STORE_CTX * x509_store_ctx,void * arg)6783 static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
6784 {
6785 /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
6786 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
6787 SSL_get_ex_data_X509_STORE_CTX_idx()));
6788 JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
6789
6790 AppData* appData = toAppData(ssl);
6791 JNIEnv* env = appData->env;
6792 if (env == NULL) {
6793 ALOGE("AppData->env missing in cert_verify_callback");
6794 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
6795 return 0;
6796 }
6797 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6798
6799 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6800 jmethodID methodID
6801 = env->GetMethodID(cls, "verifyCertificateChain", "(J[JLjava/lang/String;)V");
6802
6803 jlongArray refArray = getCertificateRefs(env, x509_store_ctx->untrusted);
6804
6805 const char* authMethod = SSL_authentication_method(ssl);
6806 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
6807 ssl, authMethod);
6808 jstring authMethodString = env->NewStringUTF(authMethod);
6809 env->CallVoidMethod(sslHandshakeCallbacks, methodID,
6810 static_cast<jlong>(reinterpret_cast<uintptr_t>(SSL_get1_session(ssl))), refArray,
6811 authMethodString);
6812
6813 int result = (env->ExceptionCheck()) ? 0 : 1;
6814 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
6815 return result;
6816 }
6817
6818 /**
6819 * Call back to watch for handshake to be completed. This is necessary
6820 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
6821 * returns before the handshake is completed in this case.
6822 */
info_callback(const SSL * ssl,int where,int ret)6823 static void info_callback(const SSL* ssl, int where, int ret) {
6824 JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
6825 #ifdef WITH_JNI_TRACE
6826 info_callback_LOG(ssl, where, ret);
6827 #endif
6828 if (!(where & SSL_CB_HANDSHAKE_DONE) && !(where & SSL_CB_HANDSHAKE_START)) {
6829 JNI_TRACE("ssl=%p info_callback ignored", ssl);
6830 return;
6831 }
6832
6833 AppData* appData = toAppData(ssl);
6834 JNIEnv* env = appData->env;
6835 if (env == NULL) {
6836 ALOGE("AppData->env missing in info_callback");
6837 JNI_TRACE("ssl=%p info_callback env error", ssl);
6838 return;
6839 }
6840 if (env->ExceptionCheck()) {
6841 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
6842 return;
6843 }
6844
6845 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6846
6847 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6848 jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(JII)V");
6849
6850 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
6851 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(ssl), where, ret);
6852
6853 if (env->ExceptionCheck()) {
6854 JNI_TRACE("ssl=%p info_callback exception", ssl);
6855 }
6856 JNI_TRACE("ssl=%p info_callback completed", ssl);
6857 }
6858
6859 /**
6860 * Call back to ask for a client certificate. There are three possible exit codes:
6861 *
6862 * 1 is success. x509Out and pkeyOut should point to the correct private key and certificate.
6863 * 0 is unable to find key. x509Out and pkeyOut should be NULL.
6864 * -1 is error and it doesn't matter what x509Out and pkeyOut are.
6865 */
client_cert_cb(SSL * ssl,X509 ** x509Out,EVP_PKEY ** pkeyOut)6866 static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
6867 JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
6868
6869 /* Clear output of key and certificate in case of early exit due to error. */
6870 *x509Out = NULL;
6871 *pkeyOut = NULL;
6872
6873 AppData* appData = toAppData(ssl);
6874 JNIEnv* env = appData->env;
6875 if (env == NULL) {
6876 ALOGE("AppData->env missing in client_cert_cb");
6877 JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
6878 return 0;
6879 }
6880 if (env->ExceptionCheck()) {
6881 JNI_TRACE("ssl=%p client_cert_cb already pending exception => 0", ssl);
6882 return -1;
6883 }
6884 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6885
6886 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6887 jmethodID methodID
6888 = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
6889
6890 // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
6891 char ssl2_ctype = SSL3_CT_RSA_SIGN;
6892 const char* ctype = NULL;
6893 int ctype_num = 0;
6894 jobjectArray issuers = NULL;
6895 switch (ssl->version) {
6896 case SSL2_VERSION:
6897 ctype = &ssl2_ctype;
6898 ctype_num = 1;
6899 break;
6900 case SSL3_VERSION:
6901 case TLS1_VERSION:
6902 case TLS1_1_VERSION:
6903 case TLS1_2_VERSION:
6904 case DTLS1_VERSION:
6905 ctype = ssl->s3->tmp.ctype;
6906 ctype_num = ssl->s3->tmp.ctype_num;
6907 issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
6908 break;
6909 }
6910 #ifdef WITH_JNI_TRACE
6911 for (int i = 0; i < ctype_num; i++) {
6912 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
6913 }
6914 #endif
6915
6916 jbyteArray keyTypes = env->NewByteArray(ctype_num);
6917 if (keyTypes == NULL) {
6918 JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
6919 return 0;
6920 }
6921 env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
6922
6923 JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
6924 "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
6925 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
6926
6927 if (env->ExceptionCheck()) {
6928 JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
6929 return -1;
6930 }
6931
6932 // Check for values set from Java
6933 X509* certificate = SSL_get_certificate(ssl);
6934 EVP_PKEY* privatekey = SSL_get_privatekey(ssl);
6935 int result = 0;
6936 if (certificate != NULL && privatekey != NULL) {
6937 *x509Out = certificate;
6938 *pkeyOut = privatekey;
6939 result = 1;
6940 } else {
6941 // Some error conditions return NULL, so make sure it doesn't linger.
6942 freeOpenSslErrorState();
6943 }
6944 JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
6945 return result;
6946 }
6947
6948 /**
6949 * Pre-Shared Key (PSK) client callback.
6950 */
psk_client_callback(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)6951 static unsigned int psk_client_callback(SSL* ssl, const char *hint,
6952 char *identity, unsigned int max_identity_len,
6953 unsigned char *psk, unsigned int max_psk_len) {
6954 JNI_TRACE("ssl=%p psk_client_callback", ssl);
6955
6956 AppData* appData = toAppData(ssl);
6957 JNIEnv* env = appData->env;
6958 if (env == NULL) {
6959 ALOGE("AppData->env missing in psk_client_callback");
6960 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
6961 return 0;
6962 }
6963 if (env->ExceptionCheck()) {
6964 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
6965 return 0;
6966 }
6967
6968 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
6969 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
6970 jmethodID methodID =
6971 env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
6972 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
6973 ScopedLocalRef<jstring> identityHintJava(
6974 env,
6975 (hint != NULL) ? env->NewStringUTF(hint) : NULL);
6976 ScopedLocalRef<jbyteArray> identityJava(env, env->NewByteArray(max_identity_len));
6977 if (identityJava.get() == NULL) {
6978 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
6979 return 0;
6980 }
6981 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
6982 if (keyJava.get() == NULL) {
6983 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
6984 return 0;
6985 }
6986 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
6987 identityHintJava.get(), identityJava.get(), keyJava.get());
6988 if (env->ExceptionCheck()) {
6989 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
6990 return 0;
6991 }
6992 if (keyLen <= 0) {
6993 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
6994 return 0;
6995 } else if ((unsigned int) keyLen > max_psk_len) {
6996 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
6997 return 0;
6998 }
6999 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7000 if (keyJavaRo.get() == NULL) {
7001 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7002 return 0;
7003 }
7004 memcpy(psk, keyJavaRo.get(), keyLen);
7005
7006 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7007 if (identityJavaRo.get() == NULL) {
7008 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7009 return 0;
7010 }
7011 memcpy(identity, identityJavaRo.get(), max_identity_len);
7012
7013 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7014 return keyLen;
7015 }
7016
7017 /**
7018 * Pre-Shared Key (PSK) server callback.
7019 */
psk_server_callback(SSL * ssl,const char * identity,unsigned char * psk,unsigned int max_psk_len)7020 static unsigned int psk_server_callback(SSL* ssl, const char *identity,
7021 unsigned char *psk, unsigned int max_psk_len) {
7022 JNI_TRACE("ssl=%p psk_server_callback", ssl);
7023
7024 AppData* appData = toAppData(ssl);
7025 JNIEnv* env = appData->env;
7026 if (env == NULL) {
7027 ALOGE("AppData->env missing in psk_server_callback");
7028 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7029 return 0;
7030 }
7031 if (env->ExceptionCheck()) {
7032 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7033 return 0;
7034 }
7035
7036 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7037 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7038 jmethodID methodID = env->GetMethodID(
7039 cls, "serverPSKKeyRequested", "(Ljava/lang/String;Ljava/lang/String;[B)I");
7040 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7041 const char* identityHint = SSL_get_psk_identity_hint(ssl);
7042 // identityHint = NULL;
7043 // identity = NULL;
7044 ScopedLocalRef<jstring> identityHintJava(
7045 env,
7046 (identityHint != NULL) ? env->NewStringUTF(identityHint) : NULL);
7047 ScopedLocalRef<jstring> identityJava(
7048 env,
7049 (identity != NULL) ? env->NewStringUTF(identity) : NULL);
7050 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
7051 if (keyJava.get() == NULL) {
7052 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7053 return 0;
7054 }
7055 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
7056 identityHintJava.get(), identityJava.get(), keyJava.get());
7057 if (env->ExceptionCheck()) {
7058 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7059 return 0;
7060 }
7061 if (keyLen <= 0) {
7062 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7063 return 0;
7064 } else if ((unsigned int) keyLen > max_psk_len) {
7065 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7066 return 0;
7067 }
7068 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7069 if (keyJavaRo.get() == NULL) {
7070 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7071 return 0;
7072 }
7073 memcpy(psk, keyJavaRo.get(), keyLen);
7074
7075 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7076 return keyLen;
7077 }
7078
rsaGenerateKey(int keylength)7079 static RSA* rsaGenerateKey(int keylength) {
7080 Unique_BIGNUM bn(BN_new());
7081 if (bn.get() == NULL) {
7082 return NULL;
7083 }
7084 int setWordResult = BN_set_word(bn.get(), RSA_F4);
7085 if (setWordResult != 1) {
7086 return NULL;
7087 }
7088 Unique_RSA rsa(RSA_new());
7089 if (rsa.get() == NULL) {
7090 return NULL;
7091 }
7092 int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
7093 if (generateResult != 1) {
7094 return NULL;
7095 }
7096 return rsa.release();
7097 }
7098
7099 /**
7100 * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
7101 */
tmp_rsa_callback(SSL * ssl,int is_export,int keylength)7102 static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
7103 int is_export __attribute__ ((unused)),
7104 int keylength) {
7105 JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7106
7107 AppData* appData = toAppData(ssl);
7108 if (appData->ephemeralRsa.get() == NULL) {
7109 JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
7110 appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
7111 }
7112 JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
7113 return appData->ephemeralRsa.get();
7114 }
7115
dhGenerateParameters(int keylength)7116 static DH* dhGenerateParameters(int keylength) {
7117
7118 /*
7119 * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
7120 * different options for generating DH keys. One is generating the
7121 * keys using a single set of DH parameters. However, generating
7122 * DH parameters is slow enough (minutes) that they suggest doing
7123 * it once at install time. The other is to generate DH keys from
7124 * DSA parameters. Generating DSA parameters is faster than DH
7125 * parameters, but to prevent small subgroup attacks, they needed
7126 * to be regenerated for each set of DH keys. Setting the
7127 * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
7128 * for new DH parameters every type it needs to generate DH keys.
7129 */
7130 #if 0
7131 // Slow path that takes minutes but could be cached
7132 Unique_DH dh(DH_new());
7133 if (!DH_generate_parameters_ex(dh.get(), keylength, 2, NULL)) {
7134 return NULL;
7135 }
7136 return dh.release();
7137 #else
7138 // Faster path but must have SSL_OP_SINGLE_DH_USE set
7139 Unique_DSA dsa(DSA_new());
7140 if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
7141 return NULL;
7142 }
7143 DH* dh = DSA_dup_DH(dsa.get());
7144 return dh;
7145 #endif
7146 }
7147
7148 /**
7149 * Call back to ask for Diffie-Hellman parameters
7150 */
tmp_dh_callback(SSL * ssl,int is_export,int keylength)7151 static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
7152 int is_export __attribute__ ((unused)),
7153 int keylength) {
7154 JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7155 DH* tmp_dh = dhGenerateParameters(keylength);
7156 JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
7157 return tmp_dh;
7158 }
7159
ecGenerateKey(int keylength)7160 static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
7161 // TODO selected curve based on keylength
7162 Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
7163 if (ec.get() == NULL) {
7164 return NULL;
7165 }
7166 return ec.release();
7167 }
7168
7169 /**
7170 * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
7171 */
tmp_ecdh_callback(SSL * ssl,int is_export,int keylength)7172 static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
7173 int is_export __attribute__ ((unused)),
7174 int keylength) {
7175 JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7176 AppData* appData = toAppData(ssl);
7177 if (appData->ephemeralEc.get() == NULL) {
7178 JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
7179 appData->ephemeralEc.reset(ecGenerateKey(keylength));
7180 }
7181 JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
7182 return appData->ephemeralEc.get();
7183 }
7184
7185 /*
7186 * public static native int SSL_CTX_new();
7187 */
NativeCrypto_SSL_CTX_new(JNIEnv * env,jclass)7188 static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
7189 Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
7190 if (sslCtx.get() == NULL) {
7191 throwExceptionIfNecessary(env, "SSL_CTX_new");
7192 return 0;
7193 }
7194 SSL_CTX_set_options(sslCtx.get(),
7195 SSL_OP_ALL
7196 // Note: We explicitly do not allow SSLv2 to be used.
7197 | SSL_OP_NO_SSLv2
7198 // We also disable session tickets for better compatibility b/2682876
7199 | SSL_OP_NO_TICKET
7200 // We also disable compression for better compatibility b/2710492 b/2710497
7201 | SSL_OP_NO_COMPRESSION
7202 // Because dhGenerateParameters uses DSA_generate_parameters_ex
7203 | SSL_OP_SINGLE_DH_USE
7204 // Because ecGenerateParameters uses a fixed named curve
7205 | SSL_OP_SINGLE_ECDH_USE);
7206
7207 int mode = SSL_CTX_get_mode(sslCtx.get());
7208 /*
7209 * Turn on "partial write" mode. This means that SSL_write() will
7210 * behave like Posix write() and possibly return after only
7211 * writing a partial buffer. Note: The alternative, perhaps
7212 * surprisingly, is not that SSL_write() always does full writes
7213 * but that it will force you to retry write calls having
7214 * preserved the full state of the original call. (This is icky
7215 * and undesirable.)
7216 */
7217 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
7218
7219 // Reuse empty buffers within the SSL_CTX to save memory
7220 mode |= SSL_MODE_RELEASE_BUFFERS;
7221
7222 SSL_CTX_set_mode(sslCtx.get(), mode);
7223
7224 SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
7225 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
7226 SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
7227 SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
7228 SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
7229 SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
7230
7231 // When TLS Channel ID extension is used, use the new version of it.
7232 sslCtx.get()->tlsext_channel_id_enabled_new = 1;
7233
7234 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
7235 return (jlong) sslCtx.release();
7236 }
7237
7238 /**
7239 * public static native void SSL_CTX_free(long ssl_ctx)
7240 */
NativeCrypto_SSL_CTX_free(JNIEnv * env,jclass,jlong ssl_ctx_address)7241 static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
7242 jclass, jlong ssl_ctx_address)
7243 {
7244 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7245 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
7246 if (ssl_ctx == NULL) {
7247 return;
7248 }
7249 SSL_CTX_free(ssl_ctx);
7250 }
7251
NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv * env,jclass,jlong ssl_ctx_address,jbyteArray sid_ctx)7252 static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass,
7253 jlong ssl_ctx_address, jbyteArray sid_ctx)
7254 {
7255 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7256 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx, sid_ctx);
7257 if (ssl_ctx == NULL) {
7258 return;
7259 }
7260
7261 ScopedByteArrayRO buf(env, sid_ctx);
7262 if (buf.get() == NULL) {
7263 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception", ssl_ctx);
7264 return;
7265 }
7266
7267 unsigned int length = buf.size();
7268 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
7269 jniThrowException(env, "java/lang/IllegalArgumentException",
7270 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
7271 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
7272 return;
7273 }
7274 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
7275 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
7276 if (result == 0) {
7277 throwExceptionIfNecessary(env, "NativeCrypto_SSL_CTX_set_session_id_context");
7278 return;
7279 }
7280 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
7281 }
7282
7283 /**
7284 * public static native int SSL_new(long ssl_ctx) throws SSLException;
7285 */
NativeCrypto_SSL_new(JNIEnv * env,jclass,jlong ssl_ctx_address)7286 static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address)
7287 {
7288 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
7289 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
7290 if (ssl_ctx == NULL) {
7291 return 0;
7292 }
7293 Unique_SSL ssl(SSL_new(ssl_ctx));
7294 if (ssl.get() == NULL) {
7295 throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
7296 "Unable to create SSL structure");
7297 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
7298 return 0;
7299 }
7300
7301 /*
7302 * Create our special application data.
7303 */
7304 AppData* appData = AppData::create();
7305 if (appData == NULL) {
7306 throwSSLExceptionStr(env, "Unable to create application data");
7307 freeOpenSslErrorState();
7308 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
7309 return 0;
7310 }
7311 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
7312
7313 /*
7314 * Java code in class OpenSSLSocketImpl does the verification. Since
7315 * the callbacks do all the verification of the chain, this flag
7316 * simply controls whether to send protocol-level alerts or not.
7317 * SSL_VERIFY_NONE means don't send alerts and anything else means send
7318 * alerts.
7319 */
7320 SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
7321
7322 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
7323 return (jlong) ssl.release();
7324 }
7325
7326
NativeCrypto_SSL_enable_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address)7327 static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
7328 {
7329 SSL* ssl = to_SSL(env, ssl_address, true);
7330 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_enable_tls_channel_id", ssl);
7331 if (ssl == NULL) {
7332 return;
7333 }
7334
7335 long ret = SSL_enable_tls_channel_id(ssl);
7336 if (ret != 1L) {
7337 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7338 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error enabling Channel ID");
7339 safeSslClear(ssl);
7340 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
7341 return;
7342 }
7343 }
7344
NativeCrypto_SSL_get_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address)7345 static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
7346 {
7347 SSL* ssl = to_SSL(env, ssl_address, true);
7348 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id", ssl);
7349 if (ssl == NULL) {
7350 return NULL;
7351 }
7352
7353 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
7354 // as a constant anywhere.
7355 jbyteArray javaBytes = env->NewByteArray(64);
7356 ScopedByteArrayRW bytes(env, javaBytes);
7357 if (bytes.get() == NULL) {
7358 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => NULL", ssl);
7359 return NULL;
7360 }
7361
7362 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
7363 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
7364 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
7365 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
7366 long ret = SSL_get_tls_channel_id(ssl, tmp, 64);
7367 if (ret == 0) {
7368 // Channel ID either not set or did not verify
7369 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
7370 return NULL;
7371 } else if (ret != 64) {
7372 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7373 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error getting Channel ID");
7374 safeSslClear(ssl);
7375 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %ld", ssl, ret);
7376 return NULL;
7377 }
7378
7379 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
7380 return javaBytes;
7381 }
7382
NativeCrypto_SSL_set1_tls_channel_id(JNIEnv * env,jclass,jlong ssl_address,jlong pkeyRef)7383 static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
7384 jlong ssl_address, jlong pkeyRef)
7385 {
7386 SSL* ssl = to_SSL(env, ssl_address, true);
7387 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
7388 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
7389 if (ssl == NULL) {
7390 return;
7391 }
7392
7393 if (pkey == NULL) {
7394 jniThrowNullPointerException(env, "pkey == null");
7395 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
7396 return;
7397 }
7398
7399 // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
7400 // Unfortunately, the default value is 1 and it's only changed to 0 just
7401 // before the handshake starts (see NativeCrypto_SSL_do_handshake).
7402 ssl->server = 0;
7403 long ret = SSL_set1_tls_channel_id(ssl, pkey);
7404
7405 if (ret != 1L) {
7406 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7407 throwSSLExceptionWithSslErrors(
7408 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
7409 safeSslClear(ssl);
7410 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
7411 return;
7412 }
7413 // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
7414 // we have an external reference from the caller such as an OpenSSLKey,
7415 // so we manually increment the reference count here.
7416 CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
7417
7418 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
7419 }
7420
NativeCrypto_SSL_use_PrivateKey(JNIEnv * env,jclass,jlong ssl_address,jlong pkeyRef)7421 static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
7422 SSL* ssl = to_SSL(env, ssl_address, true);
7423 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
7424 JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
7425 if (ssl == NULL) {
7426 return;
7427 }
7428
7429 if (pkey == NULL) {
7430 jniThrowNullPointerException(env, "pkey == null");
7431 JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
7432 return;
7433 }
7434
7435 int ret = SSL_use_PrivateKey(ssl, pkey);
7436 if (ret != 1) {
7437 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7438 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
7439 safeSslClear(ssl);
7440 JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
7441 return;
7442 }
7443 // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
7444 // but we have an external reference from the caller such as an
7445 // OpenSSLKey, so we manually increment the reference count here.
7446 CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
7447
7448 JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
7449 }
7450
NativeCrypto_SSL_use_certificate(JNIEnv * env,jclass,jlong ssl_address,jlongArray certificatesJava)7451 static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
7452 jlong ssl_address, jlongArray certificatesJava)
7453 {
7454 SSL* ssl = to_SSL(env, ssl_address, true);
7455 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificatesJava);
7456 if (ssl == NULL) {
7457 return;
7458 }
7459
7460 if (certificatesJava == NULL) {
7461 jniThrowNullPointerException(env, "certificates == null");
7462 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
7463 return;
7464 }
7465
7466 size_t length = env->GetArrayLength(certificatesJava);
7467 if (length == 0) {
7468 jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
7469 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
7470 return;
7471 }
7472
7473 ScopedLongArrayRO certificates(env, certificatesJava);
7474 if (certificates.get() == NULL) {
7475 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
7476 return;
7477 }
7478
7479 Unique_X509 serverCert(
7480 X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[0]))));
7481 if (serverCert.get() == NULL) {
7482 // Note this shouldn't happen since we checked the number of certificates above.
7483 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
7484 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
7485 return;
7486 }
7487
7488 Unique_sk_X509 chain(sk_X509_new_null());
7489 if (chain.get() == NULL) {
7490 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
7491 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
7492 return;
7493 }
7494
7495 for (size_t i = 1; i < length; i++) {
7496 Unique_X509 cert(
7497 X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[i]))));
7498 if (cert.get() == NULL || !sk_X509_push(chain.get(), cert.get())) {
7499 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7500 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
7501 safeSslClear(ssl);
7502 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
7503 return;
7504 }
7505 OWNERSHIP_TRANSFERRED(cert);
7506 }
7507
7508 int ret = SSL_use_certificate(ssl, serverCert.get());
7509 if (ret != 1) {
7510 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7511 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
7512 safeSslClear(ssl);
7513 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
7514 return;
7515 }
7516 OWNERSHIP_TRANSFERRED(serverCert);
7517
7518 int chainResult = SSL_use_certificate_chain(ssl, chain.get());
7519 if (chainResult == 0) {
7520 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
7521 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
7522 ssl);
7523 return;
7524 }
7525 OWNERSHIP_TRANSFERRED(chain);
7526
7527 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
7528 }
7529
NativeCrypto_SSL_check_private_key(JNIEnv * env,jclass,jlong ssl_address)7530 static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jlong ssl_address)
7531 {
7532 SSL* ssl = to_SSL(env, ssl_address, true);
7533 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
7534 if (ssl == NULL) {
7535 return;
7536 }
7537 int ret = SSL_check_private_key(ssl);
7538 if (ret != 1) {
7539 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
7540 safeSslClear(ssl);
7541 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
7542 return;
7543 }
7544 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
7545 }
7546
NativeCrypto_SSL_set_client_CA_list(JNIEnv * env,jclass,jlong ssl_address,jobjectArray principals)7547 static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
7548 jlong ssl_address, jobjectArray principals)
7549 {
7550 SSL* ssl = to_SSL(env, ssl_address, true);
7551 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
7552 if (ssl == NULL) {
7553 return;
7554 }
7555
7556 if (principals == NULL) {
7557 jniThrowNullPointerException(env, "principals == null");
7558 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
7559 return;
7560 }
7561
7562 int length = env->GetArrayLength(principals);
7563 if (length == 0) {
7564 jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
7565 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
7566 return;
7567 }
7568
7569 Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
7570 if (principalsStack.get() == NULL) {
7571 jniThrowOutOfMemory(env, "Unable to allocate principal stack");
7572 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
7573 return;
7574 }
7575 for (int i = 0; i < length; i++) {
7576 ScopedLocalRef<jbyteArray> principal(env,
7577 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
7578 if (principal.get() == NULL) {
7579 jniThrowNullPointerException(env, "principals element == null");
7580 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
7581 return;
7582 }
7583
7584 ScopedByteArrayRO buf(env, principal.get());
7585 if (buf.get() == NULL) {
7586 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
7587 return;
7588 }
7589 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
7590 Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
7591
7592 if (principalX509Name.get() == NULL) {
7593 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
7594 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
7595 safeSslClear(ssl);
7596 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
7597 ssl);
7598 return;
7599 }
7600
7601 if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
7602 jniThrowOutOfMemory(env, "Unable to push principal");
7603 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
7604 return;
7605 }
7606 }
7607
7608 SSL_set_client_CA_list(ssl, principalsStack.release());
7609 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
7610 }
7611
7612 /**
7613 * public static native long SSL_get_mode(long ssl);
7614 */
NativeCrypto_SSL_get_mode(JNIEnv * env,jclass,jlong ssl_address)7615 static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address) {
7616 SSL* ssl = to_SSL(env, ssl_address, true);
7617 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
7618 if (ssl == NULL) {
7619 return 0;
7620 }
7621 long mode = SSL_get_mode(ssl);
7622 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
7623 return mode;
7624 }
7625
7626 /**
7627 * public static native long SSL_set_mode(long ssl, long mode);
7628 */
NativeCrypto_SSL_set_mode(JNIEnv * env,jclass,jlong ssl_address,jlong mode)7629 static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
7630 jlong ssl_address, jlong mode) {
7631 SSL* ssl = to_SSL(env, ssl_address, true);
7632 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
7633 if (ssl == NULL) {
7634 return 0;
7635 }
7636 long result = SSL_set_mode(ssl, mode);
7637 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
7638 return result;
7639 }
7640
7641 /**
7642 * public static native long SSL_clear_mode(long ssl, long mode);
7643 */
NativeCrypto_SSL_clear_mode(JNIEnv * env,jclass,jlong ssl_address,jlong mode)7644 static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
7645 jlong ssl_address, jlong mode) {
7646 SSL* ssl = to_SSL(env, ssl_address, true);
7647 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
7648 if (ssl == NULL) {
7649 return 0;
7650 }
7651 long result = SSL_clear_mode(ssl, mode);
7652 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
7653 return result;
7654 }
7655
7656 /**
7657 * public static native long SSL_get_options(long ssl);
7658 */
NativeCrypto_SSL_get_options(JNIEnv * env,jclass,jlong ssl_address)7659 static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
7660 jlong ssl_address) {
7661 SSL* ssl = to_SSL(env, ssl_address, true);
7662 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
7663 if (ssl == NULL) {
7664 return 0;
7665 }
7666 long options = SSL_get_options(ssl);
7667 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
7668 return options;
7669 }
7670
7671 /**
7672 * public static native long SSL_set_options(long ssl, long options);
7673 */
NativeCrypto_SSL_set_options(JNIEnv * env,jclass,jlong ssl_address,jlong options)7674 static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
7675 jlong ssl_address, jlong options) {
7676 SSL* ssl = to_SSL(env, ssl_address, true);
7677 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
7678 if (ssl == NULL) {
7679 return 0;
7680 }
7681 long result = SSL_set_options(ssl, options);
7682 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
7683 return result;
7684 }
7685
7686 /**
7687 * public static native long SSL_clear_options(long ssl, long options);
7688 */
NativeCrypto_SSL_clear_options(JNIEnv * env,jclass,jlong ssl_address,jlong options)7689 static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
7690 jlong ssl_address, jlong options) {
7691 SSL* ssl = to_SSL(env, ssl_address, true);
7692 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
7693 if (ssl == NULL) {
7694 return 0;
7695 }
7696 long result = SSL_clear_options(ssl, options);
7697 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
7698 return result;
7699 }
7700
7701
NativeCrypto_SSL_use_psk_identity_hint(JNIEnv * env,jclass,jlong ssl_address,jstring identityHintJava)7702 static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass,
7703 jlong ssl_address, jstring identityHintJava)
7704 {
7705 SSL* ssl = to_SSL(env, ssl_address, true);
7706 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p",
7707 ssl, identityHintJava);
7708 if (ssl == NULL) {
7709 return;
7710 }
7711
7712 int ret;
7713 if (identityHintJava == NULL) {
7714 ret = SSL_use_psk_identity_hint(ssl, NULL);
7715 } else {
7716 ScopedUtfChars identityHint(env, identityHintJava);
7717 if (identityHint.c_str() == NULL) {
7718 throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
7719 return;
7720 }
7721 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
7722 }
7723
7724 if (ret != 1) {
7725 int sslErrorCode = SSL_get_error(ssl, ret);
7726 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Failed to set PSK identity hint");
7727 safeSslClear(ssl);
7728 }
7729 }
7730
NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,jboolean enabled)7731 static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass,
7732 jlong ssl_address, jboolean enabled)
7733 {
7734 SSL* ssl = to_SSL(env, ssl_address, true);
7735 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)",
7736 ssl, enabled);
7737 if (ssl == NULL) {
7738 return;
7739 }
7740
7741 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : NULL);
7742 }
7743
NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv * env,jclass,jlong ssl_address,jboolean enabled)7744 static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass,
7745 jlong ssl_address, jboolean enabled)
7746 {
7747 SSL* ssl = to_SSL(env, ssl_address, true);
7748 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)",
7749 ssl, enabled);
7750 if (ssl == NULL) {
7751 return;
7752 }
7753
7754 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : NULL);
7755 }
7756
NativeCrypto_SSL_get_ciphers(JNIEnv * env,jclass,jlong ssl_address)7757 static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address)
7758 {
7759 SSL* ssl = to_SSL(env, ssl_address, true);
7760 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
7761
7762 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
7763 int count = (cipherStack != NULL) ? sk_SSL_CIPHER_num(cipherStack) : 0;
7764 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(count));
7765 ScopedLongArrayRW ciphers(env, ciphersArray.get());
7766 for (int i = 0; i < count; i++) {
7767 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
7768 }
7769
7770 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%d]", ssl, ciphersArray.get(), count);
7771 return ciphersArray.release();
7772 }
7773
NativeCrypto_get_SSL_CIPHER_algorithm_mkey(JNIEnv * env,jclass,jlong ssl_cipher_address)7774 static jint NativeCrypto_get_SSL_CIPHER_algorithm_mkey(JNIEnv* env, jclass,
7775 jlong ssl_cipher_address)
7776 {
7777 SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
7778 JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_mkey => %ld", cipher, cipher->algorithm_mkey);
7779 return cipher->algorithm_mkey;
7780 }
7781
NativeCrypto_get_SSL_CIPHER_algorithm_auth(JNIEnv * env,jclass,jlong ssl_cipher_address)7782 static jint NativeCrypto_get_SSL_CIPHER_algorithm_auth(JNIEnv* env, jclass,
7783 jlong ssl_cipher_address)
7784 {
7785 SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
7786 JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_auth => %ld", cipher, cipher->algorithm_auth);
7787 return cipher->algorithm_auth;
7788 }
7789
7790 /**
7791 * Sets the ciphers suites that are enabled in the SSL
7792 */
NativeCrypto_SSL_set_cipher_lists(JNIEnv * env,jclass,jlong ssl_address,jobjectArray cipherSuites)7793 static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
7794 jlong ssl_address, jobjectArray cipherSuites)
7795 {
7796 SSL* ssl = to_SSL(env, ssl_address, true);
7797 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
7798 if (ssl == NULL) {
7799 return;
7800 }
7801 if (cipherSuites == NULL) {
7802 jniThrowNullPointerException(env, "cipherSuites == null");
7803 return;
7804 }
7805
7806 Unique_sk_SSL_CIPHER cipherstack(sk_SSL_CIPHER_new_null());
7807 if (cipherstack.get() == NULL) {
7808 jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
7809 return;
7810 }
7811
7812 const SSL_METHOD* ssl_method = ssl->method;
7813 int num_ciphers = ssl_method->num_ciphers();
7814
7815 int length = env->GetArrayLength(cipherSuites);
7816 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
7817 for (int i = 0; i < length; i++) {
7818 ScopedLocalRef<jstring> cipherSuite(env,
7819 reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
7820 ScopedUtfChars c(env, cipherSuite.get());
7821 if (c.c_str() == NULL) {
7822 return;
7823 }
7824 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
7825 bool found = false;
7826 for (int j = 0; j < num_ciphers; j++) {
7827 const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
7828 if ((strcmp(c.c_str(), cipher->name) == 0)
7829 && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
7830 if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
7831 jniThrowOutOfMemory(env, "Unable to push cipher");
7832 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
7833 return;
7834 }
7835 found = true;
7836 }
7837 }
7838 if (!found) {
7839 jniThrowException(env, "java/lang/IllegalArgumentException",
7840 "Could not find cipher suite.");
7841 return;
7842 }
7843 }
7844
7845 int rc = SSL_set_cipher_lists(ssl, cipherstack.get());
7846 if (rc == 0) {
7847 freeOpenSslErrorState();
7848 jniThrowException(env, "java/lang/IllegalArgumentException",
7849 "Illegal cipher suite strings.");
7850 } else {
7851 OWNERSHIP_TRANSFERRED(cipherstack);
7852 }
7853 }
7854
NativeCrypto_SSL_set_accept_state(JNIEnv * env,jclass,jlong sslRef)7855 static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong sslRef) {
7856 SSL* ssl = to_SSL(env, sslRef, true);
7857 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
7858 if (ssl == NULL) {
7859 return;
7860 }
7861 SSL_set_accept_state(ssl);
7862 }
7863
NativeCrypto_SSL_set_connect_state(JNIEnv * env,jclass,jlong sslRef)7864 static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong sslRef) {
7865 SSL* ssl = to_SSL(env, sslRef, true);
7866 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
7867 if (ssl == NULL) {
7868 return;
7869 }
7870 SSL_set_connect_state(ssl);
7871 }
7872
7873 /**
7874 * Sets certificate expectations, especially for server to request client auth
7875 */
NativeCrypto_SSL_set_verify(JNIEnv * env,jclass,jlong ssl_address,jint mode)7876 static void NativeCrypto_SSL_set_verify(JNIEnv* env,
7877 jclass, jlong ssl_address, jint mode)
7878 {
7879 SSL* ssl = to_SSL(env, ssl_address, true);
7880 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
7881 if (ssl == NULL) {
7882 return;
7883 }
7884 SSL_set_verify(ssl, (int)mode, NULL);
7885 }
7886
7887 /**
7888 * Sets the ciphers suites that are enabled in the SSL
7889 */
NativeCrypto_SSL_set_session(JNIEnv * env,jclass,jlong ssl_address,jlong ssl_session_address)7890 static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
7891 jlong ssl_address, jlong ssl_session_address)
7892 {
7893 SSL* ssl = to_SSL(env, ssl_address, true);
7894 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
7895 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
7896 if (ssl == NULL) {
7897 return;
7898 }
7899
7900 int ret = SSL_set_session(ssl, ssl_session);
7901 if (ret != 1) {
7902 /*
7903 * Translate the error, and throw if it turns out to be a real
7904 * problem.
7905 */
7906 int sslErrorCode = SSL_get_error(ssl, ret);
7907 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
7908 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
7909 safeSslClear(ssl);
7910 }
7911 }
7912 }
7913
7914 /**
7915 * Sets the ciphers suites that are enabled in the SSL
7916 */
NativeCrypto_SSL_set_session_creation_enabled(JNIEnv * env,jclass,jlong ssl_address,jboolean creation_enabled)7917 static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
7918 jlong ssl_address, jboolean creation_enabled)
7919 {
7920 SSL* ssl = to_SSL(env, ssl_address, true);
7921 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
7922 ssl, creation_enabled);
7923 if (ssl == NULL) {
7924 return;
7925 }
7926 SSL_set_session_creation_enabled(ssl, creation_enabled);
7927 }
7928
NativeCrypto_SSL_set_tlsext_host_name(JNIEnv * env,jclass,jlong ssl_address,jstring hostname)7929 static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
7930 jlong ssl_address, jstring hostname)
7931 {
7932 SSL* ssl = to_SSL(env, ssl_address, true);
7933 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
7934 ssl, hostname);
7935 if (ssl == NULL) {
7936 return;
7937 }
7938
7939 ScopedUtfChars hostnameChars(env, hostname);
7940 if (hostnameChars.c_str() == NULL) {
7941 return;
7942 }
7943 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s",
7944 ssl, hostnameChars.c_str());
7945
7946 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
7947 if (ret != 1) {
7948 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
7949 safeSslClear(ssl);
7950 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
7951 return;
7952 }
7953 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
7954 }
7955
NativeCrypto_SSL_get_servername(JNIEnv * env,jclass,jlong ssl_address)7956 static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address) {
7957 SSL* ssl = to_SSL(env, ssl_address, true);
7958 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
7959 if (ssl == NULL) {
7960 return NULL;
7961 }
7962 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7963 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
7964 return env->NewStringUTF(servername);
7965 }
7966
7967 /**
7968 * A common selection path for both NPN and ALPN since they're essentially the
7969 * same protocol. The list of protocols in "primary" is considered the order
7970 * which should take precedence.
7971 */
proto_select(SSL * ssl,unsigned char ** out,unsigned char * outLength,const unsigned char * primary,const unsigned int primaryLength,const unsigned char * secondary,const unsigned int secondaryLength)7972 static int proto_select(SSL* ssl __attribute__ ((unused)),
7973 unsigned char **out, unsigned char *outLength,
7974 const unsigned char *primary, const unsigned int primaryLength,
7975 const unsigned char *secondary, const unsigned int secondaryLength) {
7976 if (primary != NULL && secondary != NULL) {
7977 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
7978
7979 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
7980 secondaryLength);
7981 switch (status) {
7982 case OPENSSL_NPN_NEGOTIATED:
7983 JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
7984 return SSL_TLSEXT_ERR_OK;
7985 break;
7986 case OPENSSL_NPN_UNSUPPORTED:
7987 JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
7988 break;
7989 case OPENSSL_NPN_NO_OVERLAP:
7990 JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
7991 break;
7992 }
7993 } else {
7994 if (out != NULL && outLength != NULL) {
7995 *out = NULL;
7996 *outLength = 0;
7997 }
7998 JNI_TRACE("protocols=NULL");
7999 }
8000 return SSL_TLSEXT_ERR_NOACK;
8001 }
8002
8003 /**
8004 * Callback for the server to select an ALPN protocol.
8005 */
alpn_select_callback(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void *)8006 static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
8007 const unsigned char *in, unsigned int inlen, void *) {
8008 JNI_TRACE("ssl=%p alpn_select_callback", ssl);
8009
8010 AppData* appData = toAppData(ssl);
8011 JNI_TRACE("AppData=%p", appData);
8012
8013 return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
8014 reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
8015 appData->alpnProtocolsLength, in, inlen);
8016 }
8017
8018 /**
8019 * Callback for the client to select an NPN protocol.
8020 */
next_proto_select_callback(SSL * ssl,unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void *)8021 static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
8022 const unsigned char* in, unsigned int inlen, void*)
8023 {
8024 JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
8025
8026 AppData* appData = toAppData(ssl);
8027 JNI_TRACE("AppData=%p", appData);
8028
8029 // Enable False Start on the client if the server understands NPN
8030 // http://www.imperialviolet.org/2012/04/11/falsestart.html
8031 SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
8032
8033 return proto_select(ssl, out, outlen, in, inlen,
8034 reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
8035 appData->npnProtocolsLength);
8036 }
8037
8038 /**
8039 * Callback for the server to advertise available protocols.
8040 */
next_protos_advertised_callback(SSL * ssl,const unsigned char ** out,unsigned int * outlen,void *)8041 static int next_protos_advertised_callback(SSL* ssl,
8042 const unsigned char **out, unsigned int *outlen, void *)
8043 {
8044 JNI_TRACE("ssl=%p next_protos_advertised_callback", ssl);
8045 AppData* appData = toAppData(ssl);
8046 unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
8047 if (npnProtocols != NULL) {
8048 *out = npnProtocols;
8049 *outlen = appData->npnProtocolsLength;
8050 return SSL_TLSEXT_ERR_OK;
8051 } else {
8052 *out = NULL;
8053 *outlen = 0;
8054 return SSL_TLSEXT_ERR_NOACK;
8055 }
8056 }
8057
NativeCrypto_SSL_CTX_enable_npn(JNIEnv * env,jclass,jlong ssl_ctx_address)8058 static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
8059 {
8060 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8061 if (ssl_ctx == NULL) {
8062 return;
8063 }
8064 SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); // client
8065 SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_protos_advertised_callback, NULL); // server
8066 }
8067
NativeCrypto_SSL_CTX_disable_npn(JNIEnv * env,jclass,jlong ssl_ctx_address)8068 static void NativeCrypto_SSL_CTX_disable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
8069 {
8070 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8071 if (ssl_ctx == NULL) {
8072 return;
8073 }
8074 SSL_CTX_set_next_proto_select_cb(ssl_ctx, NULL, NULL); // client
8075 SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, NULL, NULL); // server
8076 }
8077
NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv * env,jclass,jlong ssl_address)8078 static jbyteArray NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv* env, jclass,
8079 jlong ssl_address)
8080 {
8081 SSL* ssl = to_SSL(env, ssl_address, true);
8082 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_npn_negotiated_protocol", ssl);
8083 if (ssl == NULL) {
8084 return NULL;
8085 }
8086 const jbyte* npn;
8087 unsigned npnLength;
8088 SSL_get0_next_proto_negotiated(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
8089 if (npnLength == 0) {
8090 return NULL;
8091 }
8092 jbyteArray result = env->NewByteArray(npnLength);
8093 if (result != NULL) {
8094 env->SetByteArrayRegion(result, 0, npnLength, npn);
8095 }
8096 return result;
8097 }
8098
NativeCrypto_SSL_set_alpn_protos(JNIEnv * env,jclass,jlong ssl_address,jbyteArray protos)8099 static int NativeCrypto_SSL_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_address,
8100 jbyteArray protos) {
8101 SSL* ssl = to_SSL(env, ssl_address, true);
8102 if (ssl == NULL) {
8103 return 0;
8104 }
8105
8106 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p", ssl, protos);
8107
8108 if (protos == NULL) {
8109 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=NULL", ssl);
8110 return 1;
8111 }
8112
8113 ScopedByteArrayRO protosBytes(env, protos);
8114 if (protosBytes.get() == NULL) {
8115 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => protosBytes == NULL", ssl,
8116 protos);
8117 return 0;
8118 }
8119
8120 const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
8121 int ret = SSL_set_alpn_protos(ssl, tmp, protosBytes.size());
8122 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => ret=%d", ssl, protos, ret);
8123 return ret;
8124 }
8125
NativeCrypto_SSL_get0_alpn_selected(JNIEnv * env,jclass,jlong ssl_address)8126 static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
8127 jlong ssl_address)
8128 {
8129 SSL* ssl = to_SSL(env, ssl_address, true);
8130 JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
8131 if (ssl == NULL) {
8132 return NULL;
8133 }
8134 const jbyte* npn;
8135 unsigned npnLength;
8136 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
8137 if (npnLength == 0) {
8138 return NULL;
8139 }
8140 jbyteArray result = env->NewByteArray(npnLength);
8141 if (result != NULL) {
8142 env->SetByteArrayRegion(result, 0, npnLength, npn);
8143 }
8144 return result;
8145 }
8146
8147 #ifdef WITH_JNI_TRACE_KEYS
hex_char(unsigned char in)8148 static inline char hex_char(unsigned char in)
8149 {
8150 if (in < 10) {
8151 return '0' + in;
8152 } else if (in <= 0xF0) {
8153 return 'A' + in - 10;
8154 } else {
8155 return '?';
8156 }
8157 }
8158
hex_string(char ** dest,unsigned char * input,int len)8159 static void hex_string(char **dest, unsigned char* input, int len)
8160 {
8161 *dest = (char*) malloc(len * 2 + 1);
8162 char *output = *dest;
8163 for (int i = 0; i < len; i++) {
8164 *output++ = hex_char(input[i] >> 4);
8165 *output++ = hex_char(input[i] & 0xF);
8166 }
8167 *output = '\0';
8168 }
8169
debug_print_session_key(SSL_SESSION * session)8170 static void debug_print_session_key(SSL_SESSION* session)
8171 {
8172 char *session_id_str;
8173 char *master_key_str;
8174 const char *key_type;
8175 char *keyline;
8176
8177 hex_string(&session_id_str, session->session_id, session->session_id_length);
8178 hex_string(&master_key_str, session->master_key, session->master_key_length);
8179
8180 X509* peer = SSL_SESSION_get0_peer(session);
8181 EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
8182 switch (EVP_PKEY_type(pkey->type)) {
8183 case EVP_PKEY_RSA:
8184 key_type = "RSA";
8185 break;
8186 case EVP_PKEY_DSA:
8187 key_type = "DSA";
8188 break;
8189 case EVP_PKEY_EC:
8190 key_type = "EC";
8191 break;
8192 default:
8193 key_type = "Unknown";
8194 break;
8195 }
8196
8197 asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
8198 master_key_str);
8199 JNI_TRACE("ssl_session=%p %s", session, keyline);
8200
8201 free(session_id_str);
8202 free(master_key_str);
8203 free(keyline);
8204 }
8205 #endif /* WITH_JNI_TRACE_KEYS */
8206
8207 /**
8208 * Perform SSL handshake
8209 */
NativeCrypto_SSL_do_handshake_bio(JNIEnv * env,jclass,jlong ssl_address,jlong rbioRef,jlong wbioRef,jobject shc,jboolean client_mode,jbyteArray npnProtocols,jbyteArray alpnProtocols)8210 static jlong NativeCrypto_SSL_do_handshake_bio(JNIEnv* env, jclass, jlong ssl_address,
8211 jlong rbioRef, jlong wbioRef, jobject shc, jboolean client_mode, jbyteArray npnProtocols,
8212 jbyteArray alpnProtocols) {
8213 SSL* ssl = to_SSL(env, ssl_address, true);
8214 BIO* rbio = reinterpret_cast<BIO*>(rbioRef);
8215 BIO* wbio = reinterpret_cast<BIO*>(wbioRef);
8216 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio rbio=%p wbio=%p shc=%p client_mode=%d npn=%p",
8217 ssl, rbio, wbio, shc, client_mode, npnProtocols);
8218 if (ssl == NULL) {
8219 return 0;
8220 }
8221 if (shc == NULL) {
8222 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8223 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio sslHandshakeCallbacks == null => 0", ssl);
8224 return 0;
8225 }
8226
8227 if (rbio == NULL || wbio == NULL) {
8228 jniThrowNullPointerException(env, "rbio == null || wbio == null");
8229 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => rbio == null || wbio == NULL", ssl);
8230 return 0;
8231 }
8232
8233 ScopedSslBio sslBio(ssl, rbio, wbio);
8234
8235 AppData* appData = toAppData(ssl);
8236 if (appData == NULL) {
8237 throwSSLExceptionStr(env, "Unable to retrieve application data");
8238 safeSslClear(ssl);
8239 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
8240 return 0;
8241 }
8242
8243 if (!client_mode && alpnProtocols != NULL) {
8244 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
8245 }
8246
8247 int ret = 0;
8248 errno = 0;
8249
8250 if (!appData->setCallbackState(env, shc, NULL, npnProtocols, alpnProtocols)) {
8251 freeOpenSslErrorState();
8252 safeSslClear(ssl);
8253 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio setCallbackState => 0", ssl);
8254 return 0;
8255 }
8256 ret = SSL_do_handshake(ssl);
8257 appData->clearCallbackState();
8258 // cert_verify_callback threw exception
8259 if (env->ExceptionCheck()) {
8260 freeOpenSslErrorState();
8261 safeSslClear(ssl);
8262 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio exception => 0", ssl);
8263 return 0;
8264 }
8265
8266 if (ret <= 0) { // error. See SSL_do_handshake(3SSL) man page.
8267 // error case
8268 OpenSslError sslError(ssl, ret);
8269 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio ret=%d errno=%d sslError=%d",
8270 ssl, ret, errno, sslError.get());
8271
8272 /*
8273 * If SSL_do_handshake doesn't succeed due to the socket being
8274 * either unreadable or unwritable, we need to exit to allow
8275 * the SSLEngine code to wrap or unwrap.
8276 */
8277 if (sslError.get() == SSL_ERROR_NONE ||
8278 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8279 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8280 throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8281 safeSslClear(ssl);
8282 } else if (sslError.get() != SSL_ERROR_WANT_READ &&
8283 sslError.get() != SSL_ERROR_WANT_WRITE) {
8284 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8285 "SSL handshake terminated", throwSSLHandshakeExceptionStr);
8286 safeSslClear(ssl);
8287 }
8288 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio error => 0", ssl);
8289 return 0;
8290 }
8291
8292 // success. handshake completed
8293 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
8294 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => ssl_session=%p", ssl, ssl_session);
8295 #ifdef WITH_JNI_TRACE_KEYS
8296 debug_print_session_key(ssl_session);
8297 #endif
8298 return reinterpret_cast<uintptr_t>(ssl_session);
8299 }
8300
8301 /**
8302 * Perform SSL handshake
8303 */
NativeCrypto_SSL_do_handshake(JNIEnv * env,jclass,jlong ssl_address,jobject fdObject,jobject shc,jint timeout_millis,jboolean client_mode,jbyteArray npnProtocols,jbyteArray alpnProtocols)8304 static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8305 jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
8306 jbyteArray alpnProtocols) {
8307 SSL* ssl = to_SSL(env, ssl_address, true);
8308 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
8309 ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
8310 if (ssl == NULL) {
8311 return 0;
8312 }
8313 if (fdObject == NULL) {
8314 jniThrowNullPointerException(env, "fd == null");
8315 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => 0", ssl);
8316 return 0;
8317 }
8318 if (shc == NULL) {
8319 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8320 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => 0", ssl);
8321 return 0;
8322 }
8323
8324 NetFd fd(env, fdObject);
8325 if (fd.isClosed()) {
8326 // SocketException thrown by NetFd.isClosed
8327 safeSslClear(ssl);
8328 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => 0", ssl);
8329 return 0;
8330 }
8331
8332 int ret = SSL_set_fd(ssl, fd.get());
8333 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
8334
8335 if (ret != 1) {
8336 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
8337 "Error setting the file descriptor");
8338 safeSslClear(ssl);
8339 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => 0", ssl);
8340 return 0;
8341 }
8342
8343 /*
8344 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
8345 * forever and we can use select() to find out if the socket is ready.
8346 */
8347 if (!setBlocking(fd.get(), false)) {
8348 throwSSLExceptionStr(env, "Unable to make socket non blocking");
8349 safeSslClear(ssl);
8350 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => 0", ssl);
8351 return 0;
8352 }
8353
8354 AppData* appData = toAppData(ssl);
8355 if (appData == NULL) {
8356 throwSSLExceptionStr(env, "Unable to retrieve application data");
8357 safeSslClear(ssl);
8358 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
8359 return 0;
8360 }
8361
8362 if (client_mode) {
8363 SSL_set_connect_state(ssl);
8364 } else {
8365 SSL_set_accept_state(ssl);
8366 if (alpnProtocols != NULL) {
8367 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
8368 }
8369 }
8370
8371 ret = 0;
8372 OpenSslError sslError;
8373 while (appData->aliveAndKicking) {
8374 errno = 0;
8375
8376 if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
8377 // SocketException thrown by NetFd.isClosed
8378 safeSslClear(ssl);
8379 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
8380 return 0;
8381 }
8382 ret = SSL_do_handshake(ssl);
8383 appData->clearCallbackState();
8384 // cert_verify_callback threw exception
8385 if (env->ExceptionCheck()) {
8386 freeOpenSslErrorState();
8387 safeSslClear(ssl);
8388 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => 0", ssl);
8389 return 0;
8390 }
8391 // success case
8392 if (ret == 1) {
8393 break;
8394 }
8395 // retry case
8396 if (errno == EINTR) {
8397 continue;
8398 }
8399 // error case
8400 sslError.reset(ssl, ret);
8401 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout_millis=%d",
8402 ssl, ret, errno, sslError.get(), timeout_millis);
8403
8404 /*
8405 * If SSL_do_handshake doesn't succeed due to the socket being
8406 * either unreadable or unwritable, we use sslSelect to
8407 * wait for it to become ready. If that doesn't happen
8408 * before the specified timeout or an error occurs, we
8409 * cancel the handshake. Otherwise we try the SSL_connect
8410 * again.
8411 */
8412 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8413 appData->waitingThreads++;
8414 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
8415
8416 if (selectResult == THROWN_EXCEPTION) {
8417 // SocketException thrown by NetFd.isClosed
8418 safeSslClear(ssl);
8419 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => 0", ssl);
8420 return 0;
8421 }
8422 if (selectResult == -1) {
8423 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error",
8424 throwSSLHandshakeExceptionStr);
8425 safeSslClear(ssl);
8426 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => 0", ssl);
8427 return 0;
8428 }
8429 if (selectResult == 0) {
8430 throwSocketTimeoutException(env, "SSL handshake timed out");
8431 freeOpenSslErrorState();
8432 safeSslClear(ssl);
8433 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => 0", ssl);
8434 return 0;
8435 }
8436 } else {
8437 // ALOGE("Unknown error %d during handshake", error);
8438 break;
8439 }
8440 }
8441
8442 // clean error. See SSL_do_handshake(3SSL) man page.
8443 if (ret == 0) {
8444 /*
8445 * The other side closed the socket before the handshake could be
8446 * completed, but everything is within the bounds of the TLS protocol.
8447 * We still might want to find out the real reason of the failure.
8448 */
8449 if (sslError.get() == SSL_ERROR_NONE ||
8450 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
8451 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
8452 throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
8453 } else {
8454 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8455 "SSL handshake terminated", throwSSLHandshakeExceptionStr);
8456 }
8457 safeSslClear(ssl);
8458 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => 0", ssl);
8459 return 0;
8460 }
8461
8462 // unclean error. See SSL_do_handshake(3SSL) man page.
8463 if (ret < 0) {
8464 /*
8465 * Translate the error and throw exception. We are sure it is an error
8466 * at this point.
8467 */
8468 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "SSL handshake aborted",
8469 throwSSLHandshakeExceptionStr);
8470 safeSslClear(ssl);
8471 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => 0", ssl);
8472 return 0;
8473 }
8474 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
8475 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
8476 #ifdef WITH_JNI_TRACE_KEYS
8477 debug_print_session_key(ssl_session);
8478 #endif
8479 return (jlong) ssl_session;
8480 }
8481
8482 /**
8483 * Perform SSL renegotiation
8484 */
NativeCrypto_SSL_renegotiate(JNIEnv * env,jclass,jlong ssl_address)8485 static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jlong ssl_address)
8486 {
8487 SSL* ssl = to_SSL(env, ssl_address, true);
8488 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
8489 if (ssl == NULL) {
8490 return;
8491 }
8492 int result = SSL_renegotiate(ssl);
8493 if (result != 1) {
8494 throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
8495 return;
8496 }
8497 // first call asks client to perform renegotiation
8498 int ret = SSL_do_handshake(ssl);
8499 if (ret != 1) {
8500 OpenSslError sslError(ssl, ret);
8501 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
8502 "Problem with SSL_do_handshake after SSL_renegotiate");
8503 return;
8504 }
8505 // if client agrees, set ssl state and perform renegotiation
8506 ssl->state = SSL_ST_ACCEPT;
8507 SSL_do_handshake(ssl);
8508 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
8509 }
8510
8511 /**
8512 * public static native byte[][] SSL_get_certificate(long ssl);
8513 */
NativeCrypto_SSL_get_certificate(JNIEnv * env,jclass,jlong ssl_address)8514 static jlongArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jlong ssl_address)
8515 {
8516 SSL* ssl = to_SSL(env, ssl_address, true);
8517 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
8518 if (ssl == NULL) {
8519 return NULL;
8520 }
8521 X509* certificate = SSL_get_certificate(ssl);
8522 if (certificate == NULL) {
8523 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8524 // SSL_get_certificate can return NULL during an error as well.
8525 freeOpenSslErrorState();
8526 return NULL;
8527 }
8528
8529 Unique_sk_X509 chain(sk_X509_new_null());
8530 if (chain.get() == NULL) {
8531 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
8532 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
8533 return NULL;
8534 }
8535 if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
8536 jniThrowOutOfMemory(env, "Unable to push local certificate");
8537 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8538 return NULL;
8539 }
8540 STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
8541 for (int i=0; i<sk_X509_num(cert_chain); i++) {
8542 if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
8543 jniThrowOutOfMemory(env, "Unable to push local certificate chain");
8544 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
8545 return NULL;
8546 }
8547 }
8548
8549 jlongArray refArray = getCertificateRefs(env, chain.get());
8550 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, refArray);
8551 return refArray;
8552 }
8553
8554 // Fills a long[] with the peer certificates in the chain.
NativeCrypto_SSL_get_peer_cert_chain(JNIEnv * env,jclass,jlong ssl_address)8555 static jlongArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jlong ssl_address)
8556 {
8557 SSL* ssl = to_SSL(env, ssl_address, true);
8558 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
8559 if (ssl == NULL) {
8560 return NULL;
8561 }
8562 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
8563 Unique_sk_X509 chain_copy(NULL);
8564 if (ssl->server) {
8565 X509* x509 = SSL_get_peer_certificate(ssl);
8566 if (x509 == NULL) {
8567 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
8568 return NULL;
8569 }
8570 chain_copy.reset(sk_X509_new_null());
8571 if (chain_copy.get() == NULL) {
8572 jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
8573 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
8574 return NULL;
8575 }
8576 size_t chain_size = sk_X509_num(chain);
8577 for (size_t i = 0; i < chain_size; i++) {
8578 if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
8579 jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
8580 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
8581 return NULL;
8582 }
8583 }
8584 if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
8585 jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
8586 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
8587 return NULL;
8588 }
8589 chain = chain_copy.get();
8590 }
8591 jlongArray refArray = getCertificateRefs(env, chain);
8592 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, refArray);
8593 return refArray;
8594 }
8595
sslRead(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,char * buf,jint len,OpenSslError & sslError,int read_timeout_millis)8596 static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
8597 OpenSslError& sslError, int read_timeout_millis) {
8598 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
8599
8600 if (len == 0) {
8601 // Don't bother doing anything in this case.
8602 return 0;
8603 }
8604
8605 BIO* rbio = SSL_get_rbio(ssl);
8606 BIO* wbio = SSL_get_wbio(ssl);
8607
8608 AppData* appData = toAppData(ssl);
8609 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
8610 if (appData == NULL) {
8611 return THROW_SSLEXCEPTION;
8612 }
8613
8614 while (appData->aliveAndKicking) {
8615 errno = 0;
8616
8617 if (MUTEX_LOCK(appData->mutex) == -1) {
8618 return -1;
8619 }
8620
8621 if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
8622 !SSL_renegotiate_pending(ssl)) {
8623 JNI_TRACE("ssl=%p sslRead => init is not finished (state=0x%x)", ssl,
8624 SSL_get_state(ssl));
8625 MUTEX_UNLOCK(appData->mutex);
8626 return THROW_SSLEXCEPTION;
8627 }
8628
8629 unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8630
8631 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8632 MUTEX_UNLOCK(appData->mutex);
8633 return THROWN_EXCEPTION;
8634 }
8635 int result = SSL_read(ssl, buf, len);
8636 appData->clearCallbackState();
8637 // callbacks can happen if server requests renegotiation
8638 if (env->ExceptionCheck()) {
8639 safeSslClear(ssl);
8640 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
8641 return THROWN_EXCEPTION;
8642 }
8643 sslError.reset(ssl, result);
8644 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError.get());
8645 #ifdef WITH_JNI_TRACE_DATA
8646 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8647 int n = result - i;
8648 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8649 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8650 }
8651 JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
8652 }
8653 #endif
8654
8655 // If we have been successful in moving data around, check whether it
8656 // might make sense to wake up other blocked threads, so they can give
8657 // it a try, too.
8658 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
8659 && appData->waitingThreads > 0) {
8660 sslNotify(appData);
8661 }
8662
8663 // If we are blocked by the underlying socket, tell the world that
8664 // there will be one more waiting thread now.
8665 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8666 appData->waitingThreads++;
8667 }
8668
8669 MUTEX_UNLOCK(appData->mutex);
8670
8671 switch (sslError.get()) {
8672 // Successfully read at least one byte.
8673 case SSL_ERROR_NONE: {
8674 return result;
8675 }
8676
8677 // Read zero bytes. End of stream reached.
8678 case SSL_ERROR_ZERO_RETURN: {
8679 return -1;
8680 }
8681
8682 // Need to wait for availability of underlying layer, then retry.
8683 case SSL_ERROR_WANT_READ:
8684 case SSL_ERROR_WANT_WRITE: {
8685 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, read_timeout_millis);
8686 if (selectResult == THROWN_EXCEPTION) {
8687 return THROWN_EXCEPTION;
8688 }
8689 if (selectResult == -1) {
8690 return THROW_SSLEXCEPTION;
8691 }
8692 if (selectResult == 0) {
8693 return THROW_SOCKETTIMEOUTEXCEPTION;
8694 }
8695
8696 break;
8697 }
8698
8699 // A problem occurred during a system call, but this is not
8700 // necessarily an error.
8701 case SSL_ERROR_SYSCALL: {
8702 // Connection closed without proper shutdown. Tell caller we
8703 // have reached end-of-stream.
8704 if (result == 0) {
8705 return -1;
8706 }
8707
8708 // System call has been interrupted. Simply retry.
8709 if (errno == EINTR) {
8710 break;
8711 }
8712
8713 // Note that for all other system call errors we fall through
8714 // to the default case, which results in an Exception.
8715 }
8716
8717 // Everything else is basically an error.
8718 default: {
8719 return THROW_SSLEXCEPTION;
8720 }
8721 }
8722 }
8723
8724 return -1;
8725 }
8726
NativeCrypto_SSL_read_BIO(JNIEnv * env,jclass,jlong sslRef,jbyteArray destJava,jint destOffset,jint destLength,jlong sourceBioRef,jlong sinkBioRef,jobject shc)8727 static jint NativeCrypto_SSL_read_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray destJava,
8728 jint destOffset, jint destLength, jlong sourceBioRef, jlong sinkBioRef, jobject shc) {
8729 SSL* ssl = to_SSL(env, sslRef, true);
8730 BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sourceBioRef));
8731 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
8732 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO dest=%p sourceBio=%p sinkBio=%p shc=%p",
8733 ssl, destJava, rbio, wbio, shc);
8734 if (ssl == NULL) {
8735 return 0;
8736 }
8737 if (rbio == NULL || wbio == NULL) {
8738 jniThrowNullPointerException(env, "rbio == null || wbio == null");
8739 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => rbio == null || wbio == null", ssl);
8740 return -1;
8741 }
8742 if (shc == NULL) {
8743 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8744 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => sslHandshakeCallbacks == null", ssl);
8745 return -1;
8746 }
8747
8748 ScopedByteArrayRW dest(env, destJava);
8749 if (dest.get() == NULL) {
8750 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
8751 return -1;
8752 }
8753 if (destOffset < 0 || destOffset > ssize_t(dest.size()) || destLength < 0
8754 || destLength > (ssize_t) dest.size() - destOffset) {
8755 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => destOffset=%d, destLength=%d, size=%zd",
8756 destOffset, destLength, dest.size());
8757 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
8758 return -1;
8759 }
8760
8761 AppData* appData = toAppData(ssl);
8762 if (appData == NULL) {
8763 throwSSLExceptionStr(env, "Unable to retrieve application data");
8764 safeSslClear(ssl);
8765 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => appData == NULL", ssl);
8766 return -1;
8767 }
8768
8769 errno = 0;
8770
8771 if (MUTEX_LOCK(appData->mutex) == -1) {
8772 return -1;
8773 }
8774
8775 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
8776 MUTEX_UNLOCK(appData->mutex);
8777 throwSSLExceptionStr(env, "Unable to set callback state");
8778 safeSslClear(ssl);
8779 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => set callback state failed", ssl);
8780 return -1;
8781 }
8782
8783 ScopedSslBio sslBio(ssl, rbio, wbio);
8784
8785 int result = SSL_read(ssl, dest.get() + destOffset, destLength);
8786 appData->clearCallbackState();
8787 // callbacks can happen if server requests renegotiation
8788 if (env->ExceptionCheck()) {
8789 safeSslClear(ssl);
8790 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
8791 return THROWN_EXCEPTION;
8792 }
8793 OpenSslError sslError(ssl, result);
8794 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO SSL_read result=%d sslError=%d", ssl, result,
8795 sslError.get());
8796 #ifdef WITH_JNI_TRACE_DATA
8797 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8798 int n = result - i;
8799 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8800 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8801 }
8802 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
8803 }
8804 #endif
8805
8806 MUTEX_UNLOCK(appData->mutex);
8807
8808 switch (sslError.get()) {
8809 // Successfully read at least one byte.
8810 case SSL_ERROR_NONE:
8811 break;
8812
8813 // Read zero bytes. End of stream reached.
8814 case SSL_ERROR_ZERO_RETURN:
8815 result = -1;
8816 break;
8817
8818 // Need to wait for availability of underlying layer, then retry.
8819 case SSL_ERROR_WANT_READ:
8820 case SSL_ERROR_WANT_WRITE:
8821 result = 0;
8822 break;
8823
8824 // A problem occurred during a system call, but this is not
8825 // necessarily an error.
8826 case SSL_ERROR_SYSCALL: {
8827 // Connection closed without proper shutdown. Tell caller we
8828 // have reached end-of-stream.
8829 if (result == 0) {
8830 result = -1;
8831 break;
8832 } else if (errno == EINTR) {
8833 // System call has been interrupted. Simply retry.
8834 result = 0;
8835 break;
8836 }
8837
8838 // Note that for all other system call errors we fall through
8839 // to the default case, which results in an Exception.
8840 }
8841
8842 // Everything else is basically an error.
8843 default: {
8844 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
8845 return -1;
8846 }
8847 }
8848 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => %d", ssl, result);
8849 return result;
8850 }
8851
8852 /**
8853 * OpenSSL read function (2): read into buffer at offset n chunks.
8854 * Returns 1 (success) or value <= 0 (failure).
8855 */
NativeCrypto_SSL_read(JNIEnv * env,jclass,jlong ssl_address,jobject fdObject,jobject shc,jbyteArray b,jint offset,jint len,jint read_timeout_millis)8856 static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
8857 jobject shc, jbyteArray b, jint offset, jint len,
8858 jint read_timeout_millis)
8859 {
8860 SSL* ssl = to_SSL(env, ssl_address, true);
8861 JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d read_timeout_millis=%d",
8862 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
8863 if (ssl == NULL) {
8864 return 0;
8865 }
8866 if (fdObject == NULL) {
8867 jniThrowNullPointerException(env, "fd == null");
8868 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
8869 return 0;
8870 }
8871 if (shc == NULL) {
8872 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
8873 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
8874 return 0;
8875 }
8876
8877 ScopedByteArrayRW bytes(env, b);
8878 if (bytes.get() == NULL) {
8879 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
8880 return 0;
8881 }
8882
8883 OpenSslError sslError;
8884 int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
8885 sslError, read_timeout_millis);
8886
8887 int result;
8888 switch (ret) {
8889 case THROW_SSLEXCEPTION:
8890 // See sslRead() regarding improper failure to handle normal cases.
8891 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
8892 result = -1;
8893 break;
8894 case THROW_SOCKETTIMEOUTEXCEPTION:
8895 throwSocketTimeoutException(env, "Read timed out");
8896 result = -1;
8897 break;
8898 case THROWN_EXCEPTION:
8899 // SocketException thrown by NetFd.isClosed
8900 // or RuntimeException thrown by callback
8901 result = -1;
8902 break;
8903 default:
8904 result = ret;
8905 break;
8906 }
8907
8908 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
8909 return result;
8910 }
8911
sslWrite(JNIEnv * env,SSL * ssl,jobject fdObject,jobject shc,const char * buf,jint len,OpenSslError & sslError,int write_timeout_millis)8912 static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
8913 OpenSslError& sslError, int write_timeout_millis) {
8914 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d",
8915 ssl, buf, len, write_timeout_millis);
8916
8917 if (len == 0) {
8918 // Don't bother doing anything in this case.
8919 return 0;
8920 }
8921
8922 BIO* rbio = SSL_get_rbio(ssl);
8923 BIO* wbio = SSL_get_wbio(ssl);
8924
8925 AppData* appData = toAppData(ssl);
8926 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
8927 if (appData == NULL) {
8928 return THROW_SSLEXCEPTION;
8929 }
8930
8931 int count = len;
8932
8933 while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
8934 errno = 0;
8935
8936 if (MUTEX_LOCK(appData->mutex) == -1) {
8937 return -1;
8938 }
8939
8940 if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
8941 !SSL_renegotiate_pending(ssl)) {
8942 JNI_TRACE("ssl=%p sslWrite => init is not finished (state=0x%x)", ssl,
8943 SSL_get_state(ssl));
8944 MUTEX_UNLOCK(appData->mutex);
8945 return THROW_SSLEXCEPTION;
8946 }
8947
8948 unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
8949
8950 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
8951 MUTEX_UNLOCK(appData->mutex);
8952 return THROWN_EXCEPTION;
8953 }
8954 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
8955 int result = SSL_write(ssl, buf, len);
8956 appData->clearCallbackState();
8957 // callbacks can happen if server requests renegotiation
8958 if (env->ExceptionCheck()) {
8959 safeSslClear(ssl);
8960 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
8961 return THROWN_EXCEPTION;
8962 }
8963 sslError.reset(ssl, result);
8964 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
8965 ssl, result, sslError.get(), ssl->s3->wbuf.left);
8966 #ifdef WITH_JNI_TRACE_DATA
8967 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8968 int n = result - i;
8969 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
8970 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
8971 }
8972 JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
8973 }
8974 #endif
8975
8976 // If we have been successful in moving data around, check whether it
8977 // might make sense to wake up other blocked threads, so they can give
8978 // it a try, too.
8979 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
8980 && appData->waitingThreads > 0) {
8981 sslNotify(appData);
8982 }
8983
8984 // If we are blocked by the underlying socket, tell the world that
8985 // there will be one more waiting thread now.
8986 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
8987 appData->waitingThreads++;
8988 }
8989
8990 MUTEX_UNLOCK(appData->mutex);
8991
8992 switch (sslError.get()) {
8993 // Successfully wrote at least one byte.
8994 case SSL_ERROR_NONE: {
8995 buf += result;
8996 len -= result;
8997 break;
8998 }
8999
9000 // Wrote zero bytes. End of stream reached.
9001 case SSL_ERROR_ZERO_RETURN: {
9002 return -1;
9003 }
9004
9005 // Need to wait for availability of underlying layer, then retry.
9006 // The concept of a write timeout doesn't really make sense, and
9007 // it's also not standard Java behavior, so we wait forever here.
9008 case SSL_ERROR_WANT_READ:
9009 case SSL_ERROR_WANT_WRITE: {
9010 int selectResult = sslSelect(env, sslError.get(), fdObject, appData,
9011 write_timeout_millis);
9012 if (selectResult == THROWN_EXCEPTION) {
9013 return THROWN_EXCEPTION;
9014 }
9015 if (selectResult == -1) {
9016 return THROW_SSLEXCEPTION;
9017 }
9018 if (selectResult == 0) {
9019 return THROW_SOCKETTIMEOUTEXCEPTION;
9020 }
9021
9022 break;
9023 }
9024
9025 // A problem occurred during a system call, but this is not
9026 // necessarily an error.
9027 case SSL_ERROR_SYSCALL: {
9028 // Connection closed without proper shutdown. Tell caller we
9029 // have reached end-of-stream.
9030 if (result == 0) {
9031 return -1;
9032 }
9033
9034 // System call has been interrupted. Simply retry.
9035 if (errno == EINTR) {
9036 break;
9037 }
9038
9039 // Note that for all other system call errors we fall through
9040 // to the default case, which results in an Exception.
9041 }
9042
9043 // Everything else is basically an error.
9044 default: {
9045 return THROW_SSLEXCEPTION;
9046 }
9047 }
9048 }
9049 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
9050
9051 return count;
9052 }
9053
9054 /**
9055 * OpenSSL write function (2): write into buffer at offset n chunks.
9056 */
NativeCrypto_SSL_write_BIO(JNIEnv * env,jclass,jlong sslRef,jbyteArray sourceJava,jint len,jlong sinkBioRef,jobject shc)9057 static int NativeCrypto_SSL_write_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray sourceJava, jint len,
9058 jlong sinkBioRef, jobject shc) {
9059 SSL* ssl = to_SSL(env, sslRef, true);
9060 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
9061 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO source=%p len=%d wbio=%p shc=%p",
9062 ssl, sourceJava, len, wbio, shc);
9063 if (ssl == NULL) {
9064 return -1;
9065 }
9066 if (wbio == NULL) {
9067 jniThrowNullPointerException(env, "wbio == null");
9068 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => wbio == null", ssl);
9069 return -1;
9070 }
9071 if (shc == NULL) {
9072 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9073 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => sslHandshakeCallbacks == null", ssl);
9074 return -1;
9075 }
9076
9077 AppData* appData = toAppData(ssl);
9078 if (appData == NULL) {
9079 throwSSLExceptionStr(env, "Unable to retrieve application data");
9080 safeSslClear(ssl);
9081 freeOpenSslErrorState();
9082 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO appData => NULL", ssl);
9083 return -1;
9084 }
9085
9086 errno = 0;
9087
9088 if (MUTEX_LOCK(appData->mutex) == -1) {
9089 return 0;
9090 }
9091
9092 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
9093 MUTEX_UNLOCK(appData->mutex);
9094 throwSSLExceptionStr(env, "Unable to set appdata callback");
9095 freeOpenSslErrorState();
9096 safeSslClear(ssl);
9097 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => appData can't set callback", ssl);
9098 return -1;
9099 }
9100
9101 ScopedByteArrayRO source(env, sourceJava);
9102 if (source.get() == NULL) {
9103 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => threw exception", ssl);
9104 return -1;
9105 }
9106
9107 Unique_BIO nullBio(BIO_new(BIO_s_null()));
9108 ScopedSslBio sslBio(ssl, nullBio.get(), wbio);
9109
9110 int result = SSL_write(ssl, reinterpret_cast<const char*>(source.get()), len);
9111 appData->clearCallbackState();
9112 // callbacks can happen if server requests renegotiation
9113 if (env->ExceptionCheck()) {
9114 freeOpenSslErrorState();
9115 safeSslClear(ssl);
9116 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO exception => exception pending (reneg)", ssl);
9117 return -1;
9118 }
9119 OpenSslError sslError(ssl, result);
9120 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO SSL_write result=%d sslError=%d left=%d",
9121 ssl, result, sslError.get(), ssl->s3->wbuf.left);
9122 #ifdef WITH_JNI_TRACE_DATA
9123 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9124 int n = result - i;
9125 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9126 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
9127 }
9128 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
9129 }
9130 #endif
9131
9132 MUTEX_UNLOCK(appData->mutex);
9133
9134 switch (sslError.get()) {
9135 case SSL_ERROR_NONE:
9136 return result;
9137
9138 // Wrote zero bytes. End of stream reached.
9139 case SSL_ERROR_ZERO_RETURN:
9140 return -1;
9141
9142 case SSL_ERROR_WANT_READ:
9143 case SSL_ERROR_WANT_WRITE:
9144 return 0;
9145
9146 case SSL_ERROR_SYSCALL: {
9147 // Connection closed without proper shutdown. Tell caller we
9148 // have reached end-of-stream.
9149 if (result == 0) {
9150 return -1;
9151 }
9152
9153 // System call has been interrupted. Simply retry.
9154 if (errno == EINTR) {
9155 return 0;
9156 }
9157
9158 // Note that for all other system call errors we fall through
9159 // to the default case, which results in an Exception.
9160 }
9161
9162 // Everything else is basically an error.
9163 default: {
9164 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
9165 break;
9166 }
9167 }
9168 return -1;
9169 }
9170
9171 /**
9172 * OpenSSL write function (2): write into buffer at offset n chunks.
9173 */
NativeCrypto_SSL_write(JNIEnv * env,jclass,jlong ssl_address,jobject fdObject,jobject shc,jbyteArray b,jint offset,jint len,jint write_timeout_millis)9174 static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
9175 jobject shc, jbyteArray b, jint offset, jint len, jint write_timeout_millis)
9176 {
9177 SSL* ssl = to_SSL(env, ssl_address, true);
9178 JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d write_timeout_millis=%d",
9179 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
9180 if (ssl == NULL) {
9181 return;
9182 }
9183 if (fdObject == NULL) {
9184 jniThrowNullPointerException(env, "fd == null");
9185 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
9186 return;
9187 }
9188 if (shc == NULL) {
9189 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9190 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
9191 return;
9192 }
9193
9194 ScopedByteArrayRO bytes(env, b);
9195 if (bytes.get() == NULL) {
9196 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
9197 return;
9198 }
9199 OpenSslError sslError;
9200 int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
9201 len, sslError, write_timeout_millis);
9202
9203 switch (ret) {
9204 case THROW_SSLEXCEPTION:
9205 // See sslWrite() regarding improper failure to handle normal cases.
9206 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
9207 break;
9208 case THROW_SOCKETTIMEOUTEXCEPTION:
9209 throwSocketTimeoutException(env, "Write timed out");
9210 break;
9211 case THROWN_EXCEPTION:
9212 // SocketException thrown by NetFd.isClosed
9213 break;
9214 default:
9215 break;
9216 }
9217 }
9218
9219 /**
9220 * Interrupt any pending I/O before closing the socket.
9221 */
NativeCrypto_SSL_interrupt(JNIEnv * env,jclass,jlong ssl_address)9222 static void NativeCrypto_SSL_interrupt(
9223 JNIEnv* env, jclass, jlong ssl_address) {
9224 SSL* ssl = to_SSL(env, ssl_address, false);
9225 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
9226 if (ssl == NULL) {
9227 return;
9228 }
9229
9230 /*
9231 * Mark the connection as quasi-dead, then send something to the emergency
9232 * file descriptor, so any blocking select() calls are woken up.
9233 */
9234 AppData* appData = toAppData(ssl);
9235 if (appData != NULL) {
9236 appData->aliveAndKicking = 0;
9237
9238 // At most two threads can be waiting.
9239 sslNotify(appData);
9240 sslNotify(appData);
9241 }
9242 }
9243
9244 /**
9245 * OpenSSL close SSL socket function.
9246 */
NativeCrypto_SSL_shutdown(JNIEnv * env,jclass,jlong ssl_address,jobject fdObject,jobject shc)9247 static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
9248 jobject fdObject, jobject shc) {
9249 SSL* ssl = to_SSL(env, ssl_address, false);
9250 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
9251 if (ssl == NULL) {
9252 return;
9253 }
9254 if (fdObject == NULL) {
9255 jniThrowNullPointerException(env, "fd == null");
9256 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
9257 return;
9258 }
9259 if (shc == NULL) {
9260 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9261 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9262 return;
9263 }
9264
9265 AppData* appData = toAppData(ssl);
9266 if (appData != NULL) {
9267 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
9268 // SocketException thrown by NetFd.isClosed
9269 freeOpenSslErrorState();
9270 safeSslClear(ssl);
9271 return;
9272 }
9273
9274 /*
9275 * Try to make socket blocking again. OpenSSL literature recommends this.
9276 */
9277 int fd = SSL_get_fd(ssl);
9278 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
9279 if (fd != -1) {
9280 setBlocking(fd, true);
9281 }
9282
9283 int ret = SSL_shutdown(ssl);
9284 appData->clearCallbackState();
9285 // callbacks can happen if server requests renegotiation
9286 if (env->ExceptionCheck()) {
9287 safeSslClear(ssl);
9288 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9289 return;
9290 }
9291 switch (ret) {
9292 case 0:
9293 /*
9294 * Shutdown was not successful (yet), but there also
9295 * is no error. Since we can't know whether the remote
9296 * server is actually still there, and we don't want to
9297 * get stuck forever in a second SSL_shutdown() call, we
9298 * simply return. This is not security a problem as long
9299 * as we close the underlying socket, which we actually
9300 * do, because that's where we are just coming from.
9301 */
9302 break;
9303 case 1:
9304 /*
9305 * Shutdown was successful. We can safely return. Hooray!
9306 */
9307 break;
9308 default:
9309 /*
9310 * Everything else is a real error condition. We should
9311 * let the Java layer know about this by throwing an
9312 * exception.
9313 */
9314 int sslError = SSL_get_error(ssl, ret);
9315 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
9316 break;
9317 }
9318 }
9319
9320 freeOpenSslErrorState();
9321 safeSslClear(ssl);
9322 }
9323
9324 /**
9325 * OpenSSL close SSL socket function.
9326 */
NativeCrypto_SSL_shutdown_BIO(JNIEnv * env,jclass,jlong ssl_address,jlong rbioRef,jlong wbioRef,jobject shc)9327 static void NativeCrypto_SSL_shutdown_BIO(JNIEnv* env, jclass, jlong ssl_address, jlong rbioRef,
9328 jlong wbioRef, jobject shc) {
9329 SSL* ssl = to_SSL(env, ssl_address, false);
9330 BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(rbioRef));
9331 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(wbioRef));
9332 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown rbio=%p wbio=%p shc=%p", ssl, rbio, wbio, shc);
9333 if (ssl == NULL) {
9334 return;
9335 }
9336 if (rbio == NULL || wbio == NULL) {
9337 jniThrowNullPointerException(env, "rbio == null || wbio == null");
9338 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => rbio == null || wbio == null", ssl);
9339 return;
9340 }
9341 if (shc == NULL) {
9342 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9343 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
9344 return;
9345 }
9346
9347 AppData* appData = toAppData(ssl);
9348 if (appData != NULL) {
9349 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
9350 // SocketException thrown by NetFd.isClosed
9351 freeOpenSslErrorState();
9352 safeSslClear(ssl);
9353 return;
9354 }
9355
9356 ScopedSslBio scopedBio(ssl, rbio, wbio);
9357
9358 int ret = SSL_shutdown(ssl);
9359 appData->clearCallbackState();
9360 // callbacks can happen if server requests renegotiation
9361 if (env->ExceptionCheck()) {
9362 safeSslClear(ssl);
9363 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
9364 return;
9365 }
9366 switch (ret) {
9367 case 0:
9368 /*
9369 * Shutdown was not successful (yet), but there also
9370 * is no error. Since we can't know whether the remote
9371 * server is actually still there, and we don't want to
9372 * get stuck forever in a second SSL_shutdown() call, we
9373 * simply return. This is not security a problem as long
9374 * as we close the underlying socket, which we actually
9375 * do, because that's where we are just coming from.
9376 */
9377 break;
9378 case 1:
9379 /*
9380 * Shutdown was successful. We can safely return. Hooray!
9381 */
9382 break;
9383 default:
9384 /*
9385 * Everything else is a real error condition. We should
9386 * let the Java layer know about this by throwing an
9387 * exception.
9388 */
9389 int sslError = SSL_get_error(ssl, ret);
9390 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
9391 break;
9392 }
9393 }
9394
9395 freeOpenSslErrorState();
9396 safeSslClear(ssl);
9397 }
9398
NativeCrypto_SSL_get_shutdown(JNIEnv * env,jclass,jlong ssl_address)9399 static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address) {
9400 const SSL* ssl = to_SSL(env, ssl_address, true);
9401 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
9402 if (ssl == NULL) {
9403 jniThrowNullPointerException(env, "ssl == null");
9404 return 0;
9405 }
9406
9407 int status = SSL_get_shutdown(ssl);
9408 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
9409 return static_cast<jint>(status);
9410 }
9411
9412 /**
9413 * public static native void SSL_free(long ssl);
9414 */
NativeCrypto_SSL_free(JNIEnv * env,jclass,jlong ssl_address)9415 static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address)
9416 {
9417 SSL* ssl = to_SSL(env, ssl_address, true);
9418 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
9419 if (ssl == NULL) {
9420 return;
9421 }
9422
9423 AppData* appData = toAppData(ssl);
9424 SSL_set_app_data(ssl, NULL);
9425 delete appData;
9426 SSL_free(ssl);
9427 }
9428
9429 /**
9430 * Gets and returns in a byte array the ID of the actual SSL session.
9431 */
NativeCrypto_SSL_SESSION_session_id(JNIEnv * env,jclass,jlong ssl_session_address)9432 static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
9433 jlong ssl_session_address) {
9434 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9435 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
9436 if (ssl_session == NULL) {
9437 return NULL;
9438 }
9439 jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
9440 if (result != NULL) {
9441 jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
9442 env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
9443 }
9444 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
9445 ssl_session, result, ssl_session->session_id_length);
9446 return result;
9447 }
9448
9449 /**
9450 * Gets and returns in a long integer the creation's time of the
9451 * actual SSL session.
9452 */
NativeCrypto_SSL_SESSION_get_time(JNIEnv * env,jclass,jlong ssl_session_address)9453 static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
9454 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9455 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
9456 if (ssl_session == NULL) {
9457 return 0;
9458 }
9459 // result must be jlong, not long or *1000 will overflow
9460 jlong result = SSL_SESSION_get_time(ssl_session);
9461 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
9462 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
9463 return result;
9464 }
9465
9466 /**
9467 * Gets and returns in a string the version of the SSL protocol. If it
9468 * returns the string "unknown" it means that no connection is established.
9469 */
NativeCrypto_SSL_SESSION_get_version(JNIEnv * env,jclass,jlong ssl_session_address)9470 static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jlong ssl_session_address) {
9471 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9472 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
9473 if (ssl_session == NULL) {
9474 return NULL;
9475 }
9476 const char* protocol = SSL_SESSION_get_version(ssl_session);
9477 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
9478 return env->NewStringUTF(protocol);
9479 }
9480
9481 /**
9482 * Gets and returns in a string the cipher negotiated for the SSL session.
9483 */
NativeCrypto_SSL_SESSION_cipher(JNIEnv * env,jclass,jlong ssl_session_address)9484 static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
9485 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9486 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
9487 if (ssl_session == NULL) {
9488 return NULL;
9489 }
9490 const SSL_CIPHER* cipher = ssl_session->cipher;
9491 const char* name = SSL_CIPHER_get_name(cipher);
9492 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
9493 return env->NewStringUTF(name);
9494 }
9495
9496 /**
9497 * Frees the SSL session.
9498 */
NativeCrypto_SSL_SESSION_free(JNIEnv * env,jclass,jlong ssl_session_address)9499 static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
9500 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9501 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
9502 if (ssl_session == NULL) {
9503 return;
9504 }
9505 SSL_SESSION_free(ssl_session);
9506 }
9507
9508
9509 /**
9510 * Serializes the native state of the session (ID, cipher, and keys but
9511 * not certificates). Returns a byte[] containing the DER-encoded state.
9512 * See apache mod_ssl.
9513 */
NativeCrypto_i2d_SSL_SESSION(JNIEnv * env,jclass,jlong ssl_session_address)9514 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
9515 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
9516 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
9517 if (ssl_session == NULL) {
9518 return NULL;
9519 }
9520 return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
9521 }
9522
9523 /**
9524 * Deserialize the session.
9525 */
NativeCrypto_d2i_SSL_SESSION(JNIEnv * env,jclass,jbyteArray javaBytes)9526 static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
9527 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
9528
9529 ScopedByteArrayRO bytes(env, javaBytes);
9530 if (bytes.get() == NULL) {
9531 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
9532 return 0;
9533 }
9534 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
9535 SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
9536
9537 // Initialize SSL_SESSION cipher field based on cipher_id http://b/7091840
9538 if (ssl_session != NULL) {
9539 // based on ssl_get_prev_session
9540 uint32_t cipher_id_network_order = htonl(ssl_session->cipher_id);
9541 uint8_t* cipher_id_byte_pointer = reinterpret_cast<uint8_t*>(&cipher_id_network_order);
9542 if (ssl_session->ssl_version >= SSL3_VERSION_MAJOR) {
9543 cipher_id_byte_pointer += 2; // skip first two bytes for SSL3+
9544 } else {
9545 cipher_id_byte_pointer += 1; // skip first byte for SSL2
9546 }
9547 ssl_session->cipher = SSLv23_method()->get_cipher_by_char(cipher_id_byte_pointer);
9548 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION cipher_id=%lx hton=%x 0=%x 1=%x cipher=%s",
9549 ssl_session->cipher_id, cipher_id_network_order,
9550 cipher_id_byte_pointer[0], cipher_id_byte_pointer[1],
9551 SSL_CIPHER_get_name(ssl_session->cipher));
9552 } else {
9553 freeOpenSslErrorState();
9554 }
9555
9556 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
9557 return reinterpret_cast<uintptr_t>(ssl_session);
9558 }
9559
NativeCrypto_ERR_peek_last_error(JNIEnv *,jclass)9560 static jlong NativeCrypto_ERR_peek_last_error(JNIEnv*, jclass) {
9561 return ERR_peek_last_error();
9562 }
9563
9564 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
9565 #define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
9566 static JNINativeMethod sNativeCryptoMethods[] = {
9567 NATIVE_METHOD(NativeCrypto, clinit, "()V"),
9568 NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
9569 NATIVE_METHOD(NativeCrypto, ENGINE_by_id, "(Ljava/lang/String;)J"),
9570 NATIVE_METHOD(NativeCrypto, ENGINE_add, "(J)I"),
9571 NATIVE_METHOD(NativeCrypto, ENGINE_init, "(J)I"),
9572 NATIVE_METHOD(NativeCrypto, ENGINE_finish, "(J)I"),
9573 NATIVE_METHOD(NativeCrypto, ENGINE_free, "(J)I"),
9574 NATIVE_METHOD(NativeCrypto, ENGINE_load_private_key, "(JLjava/lang/String;)J"),
9575 NATIVE_METHOD(NativeCrypto, ENGINE_get_id, "(J)Ljava/lang/String;"),
9576 NATIVE_METHOD(NativeCrypto, ENGINE_ctrl_cmd_string, "(JLjava/lang/String;Ljava/lang/String;I)I"),
9577 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DH, "([B[B[B[B)J"),
9578 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)J"),
9579 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
9580 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_EC_KEY, "(JJ[B)J"),
9581 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_mac_key, "(I[B)J"),
9582 NATIVE_METHOD(NativeCrypto, EVP_PKEY_type, "(J)I"),
9583 NATIVE_METHOD(NativeCrypto, EVP_PKEY_size, "(J)I"),
9584 NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_public, "(J)Ljava/lang/String;"),
9585 NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_private, "(J)Ljava/lang/String;"),
9586 NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(J)V"),
9587 NATIVE_METHOD(NativeCrypto, EVP_PKEY_cmp, "(JJ)I"),
9588 NATIVE_METHOD(NativeCrypto, i2d_PKCS8_PRIV_KEY_INFO, "(J)[B"),
9589 NATIVE_METHOD(NativeCrypto, d2i_PKCS8_PRIV_KEY_INFO, "([B)J"),
9590 NATIVE_METHOD(NativeCrypto, i2d_PUBKEY, "(J)[B"),
9591 NATIVE_METHOD(NativeCrypto, d2i_PUBKEY, "([B)J"),
9592 NATIVE_METHOD(NativeCrypto, getRSAPrivateKeyWrapper, "(Ljava/security/interfaces/RSAPrivateKey;[B)J"),
9593 NATIVE_METHOD(NativeCrypto, getDSAPrivateKeyWrapper, "(Ljava/security/interfaces/DSAPrivateKey;)J"),
9594 NATIVE_METHOD(NativeCrypto, getECPrivateKeyWrapper, "(Ljava/security/interfaces/ECPrivateKey;J)J"),
9595 NATIVE_METHOD(NativeCrypto, RSA_generate_key_ex, "(I[B)J"),
9596 NATIVE_METHOD(NativeCrypto, RSA_size, "(J)I"),
9597 NATIVE_METHOD(NativeCrypto, RSA_private_encrypt, "(I[B[BJI)I"),
9598 NATIVE_METHOD(NativeCrypto, RSA_public_decrypt, "(I[B[BJI)I"),
9599 NATIVE_METHOD(NativeCrypto, RSA_public_encrypt, "(I[B[BJI)I"),
9600 NATIVE_METHOD(NativeCrypto, RSA_private_decrypt, "(I[B[BJI)I"),
9601 NATIVE_METHOD(NativeCrypto, get_RSA_private_params, "(J)[[B"),
9602 NATIVE_METHOD(NativeCrypto, get_RSA_public_params, "(J)[[B"),
9603 NATIVE_METHOD(NativeCrypto, DSA_generate_key, "(I[B[B[B[B)J"),
9604 NATIVE_METHOD(NativeCrypto, get_DSA_params, "(J)[[B"),
9605 NATIVE_METHOD(NativeCrypto, set_DSA_flag_nonce_from_hash, "(J)V"),
9606 NATIVE_METHOD(NativeCrypto, DH_generate_parameters_ex, "(IJ)J"),
9607 NATIVE_METHOD(NativeCrypto, DH_generate_key, "(J)V"),
9608 NATIVE_METHOD(NativeCrypto, get_DH_params, "(J)[[B"),
9609 NATIVE_METHOD(NativeCrypto, EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
9610 NATIVE_METHOD(NativeCrypto, EC_GROUP_new_curve, "(I[B[B[B)J"),
9611 NATIVE_METHOD(NativeCrypto, EC_GROUP_dup, "(J)J"),
9612 NATIVE_METHOD(NativeCrypto, EC_GROUP_set_asn1_flag, "(JI)V"),
9613 NATIVE_METHOD(NativeCrypto, EC_GROUP_set_point_conversion_form, "(JI)V"),
9614 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(J)Ljava/lang/String;"),
9615 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(J)[[B"),
9616 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(J)[B"),
9617 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(J)I"),
9618 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(J)[B"),
9619 NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
9620 NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(JJ)Z"),
9621 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_generator, "(J)J"),
9622 NATIVE_METHOD(NativeCrypto, EC_GROUP_set_generator, "(JJ[B[B)V"),
9623 NATIVE_METHOD(NativeCrypto, get_EC_GROUP_type, "(J)I"),
9624 NATIVE_METHOD(NativeCrypto, EC_POINT_new, "(J)J"),
9625 NATIVE_METHOD(NativeCrypto, EC_POINT_clear_free, "(J)V"),
9626 NATIVE_METHOD(NativeCrypto, EC_POINT_cmp, "(JJJ)Z"),
9627 NATIVE_METHOD(NativeCrypto, EC_POINT_set_affine_coordinates, "(JJ[B[B)V"),
9628 NATIVE_METHOD(NativeCrypto, EC_POINT_get_affine_coordinates, "(JJ)[[B"),
9629 NATIVE_METHOD(NativeCrypto, EC_KEY_generate_key, "(J)J"),
9630 NATIVE_METHOD(NativeCrypto, EC_KEY_get0_group, "(J)J"),
9631 NATIVE_METHOD(NativeCrypto, EC_KEY_get_private_key, "(J)[B"),
9632 NATIVE_METHOD(NativeCrypto, EC_KEY_get_public_key, "(J)J"),
9633 NATIVE_METHOD(NativeCrypto, EC_KEY_set_nonce_from_hash, "(JZ)V"),
9634 NATIVE_METHOD(NativeCrypto, ECDH_compute_key, "([BIJJ)I"),
9635 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()J"),
9636 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_init, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)V"),
9637 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(J)V"),
9638 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_copy, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)I"),
9639 NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9640 NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9641 NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BI)I"),
9642 NATIVE_METHOD(NativeCrypto, EVP_get_digestbyname, "(Ljava/lang/String;)J"),
9643 NATIVE_METHOD(NativeCrypto, EVP_MD_block_size, "(J)I"),
9644 NATIVE_METHOD(NativeCrypto, EVP_MD_size, "(J)I"),
9645 NATIVE_METHOD(NativeCrypto, EVP_SignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9646 NATIVE_METHOD(NativeCrypto, EVP_SignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9647 NATIVE_METHOD(NativeCrypto, EVP_SignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIJ)I"),
9648 NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;J)I"),
9649 NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BII)V"),
9650 NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[BIIJ)I"),
9651 NATIVE_METHOD(NativeCrypto, EVP_DigestSignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;JJ)V"),
9652 NATIVE_METHOD(NativeCrypto, EVP_DigestSignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;[B)V"),
9653 NATIVE_METHOD(NativeCrypto, EVP_DigestSignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLDigestContext;)[B"),
9654 NATIVE_METHOD(NativeCrypto, EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
9655 NATIVE_METHOD(NativeCrypto, EVP_CipherInit_ex, "(JJ[B[BZ)V"),
9656 NATIVE_METHOD(NativeCrypto, EVP_CipherUpdate, "(J[BI[BII)I"),
9657 NATIVE_METHOD(NativeCrypto, EVP_CipherFinal_ex, "(J[BI)I"),
9658 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_iv_length, "(J)I"),
9659 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_new, "()J"),
9660 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_block_size, "(J)I"),
9661 NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_buf_len, "(J)I"),
9662 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_padding, "(JZ)V"),
9663 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_key_length, "(JI)V"),
9664 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_free, "(J)V"),
9665 NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
9666 NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
9667 NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"),
9668 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
9669 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
9670 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
9671 NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
9672 NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
9673 NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
9674 NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
9675 NATIVE_METHOD(NativeCrypto, BIO_free_all, "(J)V"),
9676 NATIVE_METHOD(NativeCrypto, X509_NAME_print_ex, "(JJ)Ljava/lang/String;"),
9677 NATIVE_METHOD(NativeCrypto, d2i_X509_bio, "(J)J"),
9678 NATIVE_METHOD(NativeCrypto, d2i_X509, "([B)J"),
9679 NATIVE_METHOD(NativeCrypto, i2d_X509, "(J)[B"),
9680 NATIVE_METHOD(NativeCrypto, i2d_X509_PUBKEY, "(J)[B"),
9681 NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509, "(J)J"),
9682 NATIVE_METHOD(NativeCrypto, PEM_read_bio_PKCS7, "(JI)[J"),
9683 NATIVE_METHOD(NativeCrypto, d2i_PKCS7_bio, "(JI)[J"),
9684 NATIVE_METHOD(NativeCrypto, i2d_PKCS7, "([J)[B"),
9685 NATIVE_METHOD(NativeCrypto, ASN1_seq_unpack_X509_bio, "(J)[J"),
9686 NATIVE_METHOD(NativeCrypto, ASN1_seq_pack_X509, "([J)[B"),
9687 NATIVE_METHOD(NativeCrypto, X509_free, "(J)V"),
9688 NATIVE_METHOD(NativeCrypto, X509_cmp, "(JJ)I"),
9689 NATIVE_METHOD(NativeCrypto, get_X509_hashCode, "(J)I"),
9690 NATIVE_METHOD(NativeCrypto, X509_print_ex, "(JJJJ)V"),
9691 NATIVE_METHOD(NativeCrypto, X509_get_pubkey, "(J)J"),
9692 NATIVE_METHOD(NativeCrypto, X509_get_issuer_name, "(J)[B"),
9693 NATIVE_METHOD(NativeCrypto, X509_get_subject_name, "(J)[B"),
9694 NATIVE_METHOD(NativeCrypto, get_X509_pubkey_oid, "(J)Ljava/lang/String;"),
9695 NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_oid, "(J)Ljava/lang/String;"),
9696 NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_parameter, "(J)[B"),
9697 NATIVE_METHOD(NativeCrypto, get_X509_issuerUID, "(J)[Z"),
9698 NATIVE_METHOD(NativeCrypto, get_X509_subjectUID, "(J)[Z"),
9699 NATIVE_METHOD(NativeCrypto, get_X509_ex_kusage, "(J)[Z"),
9700 NATIVE_METHOD(NativeCrypto, get_X509_ex_xkusage, "(J)[Ljava/lang/String;"),
9701 NATIVE_METHOD(NativeCrypto, get_X509_ex_pathlen, "(J)I"),
9702 NATIVE_METHOD(NativeCrypto, X509_get_ext_oid, "(JLjava/lang/String;)[B"),
9703 NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext_oid, "(JLjava/lang/String;)[B"),
9704 NATIVE_METHOD(NativeCrypto, get_X509_CRL_crl_enc, "(J)[B"),
9705 NATIVE_METHOD(NativeCrypto, X509_CRL_verify, "(JJ)V"),
9706 NATIVE_METHOD(NativeCrypto, X509_CRL_get_lastUpdate, "(J)J"),
9707 NATIVE_METHOD(NativeCrypto, X509_CRL_get_nextUpdate, "(J)J"),
9708 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
9709 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_serialNumber, "(J)[B"),
9710 NATIVE_METHOD(NativeCrypto, X509_REVOKED_print, "(JJ)V"),
9711 NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_revocationDate, "(J)J"),
9712 NATIVE_METHOD(NativeCrypto, get_X509_ext_oids, "(JI)[Ljava/lang/String;"),
9713 NATIVE_METHOD(NativeCrypto, get_X509_CRL_ext_oids, "(JI)[Ljava/lang/String;"),
9714 NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
9715 NATIVE_METHOD(NativeCrypto, get_X509_GENERAL_NAME_stack, "(JI)[[Ljava/lang/Object;"),
9716 NATIVE_METHOD(NativeCrypto, X509_get_notBefore, "(J)J"),
9717 NATIVE_METHOD(NativeCrypto, X509_get_notAfter, "(J)J"),
9718 NATIVE_METHOD(NativeCrypto, X509_get_version, "(J)J"),
9719 NATIVE_METHOD(NativeCrypto, X509_get_serialNumber, "(J)[B"),
9720 NATIVE_METHOD(NativeCrypto, X509_verify, "(JJ)V"),
9721 NATIVE_METHOD(NativeCrypto, get_X509_cert_info_enc, "(J)[B"),
9722 NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
9723 NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
9724 NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
9725 NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
9726 NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
9727 NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
9728 NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
9729 NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_serial, "(J[B)J"),
9730 NATIVE_METHOD(NativeCrypto, X509_CRL_get_REVOKED, "(J)[J"),
9731 NATIVE_METHOD(NativeCrypto, i2d_X509_CRL, "(J)[B"),
9732 NATIVE_METHOD(NativeCrypto, X509_CRL_free, "(J)V"),
9733 NATIVE_METHOD(NativeCrypto, X509_CRL_print, "(JJ)V"),
9734 NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_oid, "(J)Ljava/lang/String;"),
9735 NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_parameter, "(J)[B"),
9736 NATIVE_METHOD(NativeCrypto, X509_CRL_get_issuer_name, "(J)[B"),
9737 NATIVE_METHOD(NativeCrypto, X509_CRL_get_version, "(J)J"),
9738 NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext, "(JLjava/lang/String;)J"),
9739 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
9740 NATIVE_METHOD(NativeCrypto, X509_REVOKED_dup, "(J)J"),
9741 NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
9742 NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
9743 NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
9744 NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
9745 NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
9746 NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),
9747 NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
9748 NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
9749 NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
9750 NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
9751 NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
9752 NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[J)V"),
9753 NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
9754 NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
9755 NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(J)J"),
9756 NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(JJ)J"),
9757 NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(JJ)J"),
9758 NATIVE_METHOD(NativeCrypto, SSL_get_options, "(J)J"),
9759 NATIVE_METHOD(NativeCrypto, SSL_set_options, "(JJ)J"),
9760 NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(JJ)J"),
9761 NATIVE_METHOD(NativeCrypto, SSL_use_psk_identity_hint, "(JLjava/lang/String;)V"),
9762 NATIVE_METHOD(NativeCrypto, set_SSL_psk_client_callback_enabled, "(JZ)V"),
9763 NATIVE_METHOD(NativeCrypto, set_SSL_psk_server_callback_enabled, "(JZ)V"),
9764 NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(J[Ljava/lang/String;)V"),
9765 NATIVE_METHOD(NativeCrypto, SSL_get_ciphers, "(J)[J"),
9766 NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_auth, "(J)I"),
9767 NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_mkey, "(J)I"),
9768 NATIVE_METHOD(NativeCrypto, SSL_set_accept_state, "(J)V"),
9769 NATIVE_METHOD(NativeCrypto, SSL_set_connect_state, "(J)V"),
9770 NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(JI)V"),
9771 NATIVE_METHOD(NativeCrypto, SSL_set_session, "(JJ)V"),
9772 NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
9773 NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
9774 NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
9775 NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)J"),
9776 NATIVE_METHOD(NativeCrypto, SSL_do_handshake_bio, "(JJJ" SSL_CALLBACKS "Z[B[B)J"),
9777 NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
9778 NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[J"),
9779 NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[J"),
9780 NATIVE_METHOD(NativeCrypto, SSL_read, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
9781 NATIVE_METHOD(NativeCrypto, SSL_read_BIO, "(J[BIIJJ" SSL_CALLBACKS ")I"),
9782 NATIVE_METHOD(NativeCrypto, SSL_write, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
9783 NATIVE_METHOD(NativeCrypto, SSL_write_BIO, "(J[BIJ" SSL_CALLBACKS ")I"),
9784 NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(J)V"),
9785 NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(J" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
9786 NATIVE_METHOD(NativeCrypto, SSL_shutdown_BIO, "(JJJ" SSL_CALLBACKS ")V"),
9787 NATIVE_METHOD(NativeCrypto, SSL_get_shutdown, "(J)I"),
9788 NATIVE_METHOD(NativeCrypto, SSL_free, "(J)V"),
9789 NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(J)[B"),
9790 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(J)J"),
9791 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
9792 NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
9793 NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(J)V"),
9794 NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(J)[B"),
9795 NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)J"),
9796 NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
9797 NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
9798 NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
9799 NATIVE_METHOD(NativeCrypto, SSL_set_alpn_protos, "(J[B)I"),
9800 NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
9801 NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
9802 };
9803
getGlobalRefToClass(JNIEnv * env,const char * className)9804 static jclass getGlobalRefToClass(JNIEnv* env, const char* className) {
9805 ScopedLocalRef<jclass> localClass(env, env->FindClass(className));
9806 jclass globalRef = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
9807 if (globalRef == NULL) {
9808 ALOGE("failed to find class %s", className);
9809 abort();
9810 }
9811 return globalRef;
9812 }
9813
getStaticMethodRef(JNIEnv * env,jclass clazz,const char * name,const char * sig)9814 static jmethodID getStaticMethodRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9815 jmethodID localMethod = env->GetStaticMethodID(clazz, name, sig);
9816 if (localMethod == NULL) {
9817 ALOGE("could not find static method %s", name);
9818 abort();
9819 }
9820 return localMethod;
9821 }
9822
getMethodRef(JNIEnv * env,jclass clazz,const char * name,const char * sig)9823 static jmethodID getMethodRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9824 jmethodID localMethod = env->GetMethodID(clazz, name, sig);
9825 if (localMethod == NULL) {
9826 ALOGE("could not find method %s", name);
9827 abort();
9828 }
9829 return localMethod;
9830 }
9831
getFieldRef(JNIEnv * env,jclass clazz,const char * name,const char * sig)9832 static jfieldID getFieldRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
9833 jfieldID localField = env->GetFieldID(clazz, name, sig);
9834 if (localField == NULL) {
9835 ALOGE("could not find field %s", name);
9836 abort();
9837 }
9838 return localField;
9839 }
9840
initialize_conscrypt(JNIEnv * env)9841 static void initialize_conscrypt(JNIEnv* env) {
9842 jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
9843 sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
9844
9845 cryptoUpcallsClass = getGlobalRefToClass(env,
9846 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/CryptoUpcalls");
9847 openSslNativeReferenceClass = getGlobalRefToClass(env,
9848 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLNativeReference");
9849 openSslInputStreamClass = getGlobalRefToClass(env,
9850 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream");
9851
9852 openSslNativeReference_context = getFieldRef(env, openSslNativeReferenceClass, "context", "J");
9853
9854 calendar_setMethod = getMethodRef(env, calendarClass, "set", "(IIIIII)V");
9855 inputStream_readMethod = getMethodRef(env, inputStreamClass, "read", "([B)I");
9856 integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
9857 "(I)Ljava/lang/Integer;");
9858 openSslInputStream_readLineMethod = getMethodRef(env, openSslInputStreamClass, "gets",
9859 "([B)I");
9860 outputStream_writeMethod = getMethodRef(env, outputStreamClass, "write", "([B)V");
9861 outputStream_flushMethod = getMethodRef(env, outputStreamClass, "flush", "()V");
9862
9863 #ifdef CONSCRYPT_UNBUNDLED
9864 findAsynchronousCloseMonitorFuncs();
9865 #endif
9866 }
9867
findClass(JNIEnv * env,const char * name)9868 static jclass findClass(JNIEnv* env, const char* name) {
9869 ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
9870 jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
9871 if (result == NULL) {
9872 ALOGE("failed to find class '%s'", name);
9873 abort();
9874 }
9875 return result;
9876 }
9877
9878 #ifdef STATIC_LIB
9879 // Give client libs everything they need to initialize our JNI
libconscrypt_JNI_OnLoad(JavaVM * vm,void *)9880 int libconscrypt_JNI_OnLoad(JavaVM *vm, void*) {
9881 #else
9882 // Use JNI_OnLoad for when we're standalone
9883 int JNI_OnLoad(JavaVM *vm, void*) {
9884 JNI_TRACE("JNI_OnLoad NativeCrypto");
9885 #endif
9886 gJavaVM = vm;
9887
9888 JNIEnv *env;
9889 if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
9890 ALOGE("Could not get JNIEnv");
9891 return JNI_ERR;
9892 }
9893
9894 byteArrayClass = findClass(env, "[B");
9895 calendarClass = findClass(env, "java/util/Calendar");
9896 inputStreamClass = findClass(env, "java/io/InputStream");
9897 integerClass = findClass(env, "java/lang/Integer");
9898 objectClass = findClass(env, "java/lang/Object");
9899 objectArrayClass = findClass(env, "[Ljava/lang/Object;");
9900 outputStreamClass = findClass(env, "java/io/OutputStream");
9901 stringClass = findClass(env, "java/lang/String");
9902
9903 initialize_conscrypt(env);
9904 return JNI_VERSION_1_6;
9905 }
9906