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