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