• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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