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