blob: 0989fb08c26a6450050deef025f9a7d694f9e2d9 [file] [log] [blame]
Kenny Root860d2702013-04-23 15:50:31 -07001/*
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
Kenny Root3e46e4e2014-05-23 13:35:10 -070024 #ifndef CONSCRYPT_NOT_UNBUNDLED
25 #define CONSCRYPT_UNBUNDLED
26 #endif
27 #define JNI_JARJAR_PREFIX
Kenny Root860d2702013-04-23 15:50:31 -070028#endif
29
30#define LOG_TAG "NativeCrypto"
31
Kenny Root860d2702013-04-23 15:50:31 -070032#include <arpa/inet.h>
33#include <fcntl.h>
Kenny Root3e46e4e2014-05-23 13:35:10 -070034#include <pthread.h>
Kenny Root860d2702013-04-23 15:50:31 -070035#include <sys/socket.h>
Adam Langleyde5225d2014-10-06 15:55:30 -070036#include <sys/syscall.h>
Kenny Root860d2702013-04-23 15:50:31 -070037#include <unistd.h>
Kenny Root860d2702013-04-23 15:50:31 -070038
Kenny Root3e46e4e2014-05-23 13:35:10 -070039#ifdef CONSCRYPT_UNBUNDLED
40#include <dlfcn.h>
41#endif
42
Kenny Root860d2702013-04-23 15:50:31 -070043#include <jni.h>
44
45#include <openssl/asn1t.h>
Kenny Root860d2702013-04-23 15:50:31 -070046#include <openssl/engine.h>
47#include <openssl/err.h>
48#include <openssl/evp.h>
49#include <openssl/rand.h>
50#include <openssl/rsa.h>
51#include <openssl/ssl.h>
52#include <openssl/x509v3.h>
Kenny Rootf6f66202015-05-08 14:01:56 -070053#if defined(OPENSSL_IS_BORINGSSL)
54#include <openssl/aead.h>
55#endif
Adam Langleyde5225d2014-10-06 15:55:30 -070056
57#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Rootf24ba062014-06-09 10:37:46 -070058#include "crypto/ecdsa/ecs_locl.h"
Adam Langleyde5225d2014-10-06 15:55:30 -070059#endif
Kenny Root860d2702013-04-23 15:50:31 -070060
Kenny Root3e46e4e2014-05-23 13:35:10 -070061#ifndef CONSCRYPT_UNBUNDLED
62/* If we're compiled unbundled from Android system image, we use the
63 * CompatibilityCloseMonitor
64 */
Neil Fuller798f9442014-04-11 17:26:59 +010065#include "AsynchronousCloseMonitor.h"
Kenny Root3e46e4e2014-05-23 13:35:10 -070066#endif
67
68#ifndef CONSCRYPT_UNBUNDLED
Ruben Brunk33bad172013-09-09 17:01:23 -070069#include "cutils/log.h"
Kenny Root3e46e4e2014-05-23 13:35:10 -070070#else
Kenny Root6af242c2014-11-10 15:00:46 -080071#include "log_compat.h"
Kenny Root3e46e4e2014-05-23 13:35:10 -070072#endif
73
74#ifndef CONSCRYPT_UNBUNDLED
Kenny Root860d2702013-04-23 15:50:31 -070075#include "JNIHelp.h"
76#include "JniConstants.h"
77#include "JniException.h"
Kenny Root3e46e4e2014-05-23 13:35:10 -070078#else
79#define NATIVE_METHOD(className, functionName, signature) \
Kenny Rootc625fa92015-04-28 16:23:39 -070080 { (char*) #functionName, (char*) signature, reinterpret_cast<void*>(className ## _ ## functionName) }
Kenny Root3e46e4e2014-05-23 13:35:10 -070081#define REGISTER_NATIVE_METHODS(jni_class_name) \
82 RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
83#endif
84
Kenny Root860d2702013-04-23 15:50:31 -070085#include "ScopedLocalRef.h"
86#include "ScopedPrimitiveArray.h"
87#include "ScopedUtfChars.h"
88#include "UniquePtr.h"
Kenny Root3e46e4e2014-05-23 13:35:10 -070089#include "NetFd.h"
Kenny Root860d2702013-04-23 15:50:31 -070090
Kenny Root8a9fc462015-04-02 17:06:30 -070091#include "macros.h"
92
Kenny Root860d2702013-04-23 15:50:31 -070093#undef WITH_JNI_TRACE
Kenny Rootacc950a2014-03-26 13:55:26 -070094#undef WITH_JNI_TRACE_MD
Kenny Root860d2702013-04-23 15:50:31 -070095#undef WITH_JNI_TRACE_DATA
96
Kenny Rootbcdb80d2013-05-28 14:51:51 -070097/*
98 * How to use this for debugging with Wireshark:
99 *
100 * 1. Pull lines from logcat to a file that looks like (without quotes):
101 * "RSA Session-ID:... Master-Key:..." <CR>
102 * "RSA Session-ID:... Master-Key:..." <CR>
103 * <etc>
104 * 2. Start Wireshark
105 * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in
106 * the file you put the lines in above.
107 * 4. Follow the stream that corresponds to the desired "Session-ID" in
108 * the Server Hello.
109 */
110#undef WITH_JNI_TRACE_KEYS
111
Kenny Root860d2702013-04-23 15:50:31 -0700112#ifdef WITH_JNI_TRACE
113#define JNI_TRACE(...) \
Kenny Root30550a82014-08-12 15:13:33 -0700114 ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__))
Kenny Root860d2702013-04-23 15:50:31 -0700115#else
116#define JNI_TRACE(...) ((void)0)
117#endif
Kenny Rootacc950a2014-03-26 13:55:26 -0700118#ifdef WITH_JNI_TRACE_MD
119#define JNI_TRACE_MD(...) \
120 ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__));
121#else
122#define JNI_TRACE_MD(...) ((void)0)
123#endif
Kenny Root860d2702013-04-23 15:50:31 -0700124// don't overwhelm logcat
125#define WITH_JNI_TRACE_DATA_CHUNK_SIZE 512
126
127static JavaVM* gJavaVM;
Kenny Rootf24ba062014-06-09 10:37:46 -0700128static jclass cryptoUpcallsClass;
Kenny Rootfee2d0f2014-06-04 11:24:40 -0700129static jclass openSslInputStreamClass;
Kenny Root4bff0a12014-11-25 12:02:21 -0800130static jclass nativeRefClass;
Kenny Root860d2702013-04-23 15:50:31 -0700131
Kenny Root923e3c52013-05-01 12:17:23 -0700132static jclass byteArrayClass;
133static jclass calendarClass;
134static jclass objectClass;
135static jclass objectArrayClass;
136static jclass integerClass;
137static jclass inputStreamClass;
138static jclass outputStreamClass;
139static jclass stringClass;
140
Kenny Root4bff0a12014-11-25 12:02:21 -0800141static jfieldID nativeRef_context;
Kenny Root652ff532014-02-24 12:35:11 -0800142
Kenny Root860d2702013-04-23 15:50:31 -0700143static jmethodID calendar_setMethod;
144static jmethodID inputStream_readMethod;
145static jmethodID integer_valueOfMethod;
146static jmethodID openSslInputStream_readLineMethod;
147static jmethodID outputStream_writeMethod;
148static jmethodID outputStream_flushMethod;
149
150struct OPENSSL_Delete {
151 void operator()(void* p) const {
152 OPENSSL_free(p);
153 }
154};
155typedef UniquePtr<unsigned char, OPENSSL_Delete> Unique_OPENSSL_str;
156
157struct BIO_Delete {
158 void operator()(BIO* p) const {
Kenny Root19fdf1a2014-04-10 11:45:19 -0700159 BIO_free_all(p);
Kenny Root860d2702013-04-23 15:50:31 -0700160 }
161};
162typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
163
164struct BIGNUM_Delete {
165 void operator()(BIGNUM* p) const {
166 BN_free(p);
167 }
168};
169typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
170
Adam Langley05b8e502015-05-12 19:24:49 -0700171struct BN_CTX_Delete {
172 void operator()(BN_CTX* ctx) const {
173 BN_CTX_free(ctx);
174 }
175};
176typedef UniquePtr<BN_CTX, BN_CTX_Delete> Unique_BN_CTX;
177
Kenny Root860d2702013-04-23 15:50:31 -0700178struct ASN1_INTEGER_Delete {
179 void operator()(ASN1_INTEGER* p) const {
180 ASN1_INTEGER_free(p);
181 }
182};
183typedef UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> Unique_ASN1_INTEGER;
184
185struct DH_Delete {
186 void operator()(DH* p) const {
187 DH_free(p);
188 }
189};
190typedef UniquePtr<DH, DH_Delete> Unique_DH;
191
192struct DSA_Delete {
193 void operator()(DSA* p) const {
194 DSA_free(p);
195 }
196};
197typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
198
199struct EC_GROUP_Delete {
200 void operator()(EC_GROUP* p) const {
Adam Langleyde5225d2014-10-06 15:55:30 -0700201 EC_GROUP_free(p);
Kenny Root860d2702013-04-23 15:50:31 -0700202 }
203};
204typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
205
206struct EC_POINT_Delete {
207 void operator()(EC_POINT* p) const {
208 EC_POINT_clear_free(p);
209 }
210};
211typedef UniquePtr<EC_POINT, EC_POINT_Delete> Unique_EC_POINT;
212
213struct EC_KEY_Delete {
214 void operator()(EC_KEY* p) const {
215 EC_KEY_free(p);
216 }
217};
218typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
219
220struct EVP_MD_CTX_Delete {
221 void operator()(EVP_MD_CTX* p) const {
222 EVP_MD_CTX_destroy(p);
223 }
224};
225typedef UniquePtr<EVP_MD_CTX, EVP_MD_CTX_Delete> Unique_EVP_MD_CTX;
226
Kenny Rootf6f66202015-05-08 14:01:56 -0700227#if defined(OPENSSL_IS_BORINGSSL)
228struct EVP_AEAD_CTX_Delete {
229 void operator()(EVP_AEAD_CTX* p) const {
230 EVP_AEAD_CTX_cleanup(p);
231 delete p;
232 }
233};
234typedef UniquePtr<EVP_AEAD_CTX, EVP_AEAD_CTX_Delete> Unique_EVP_AEAD_CTX;
235#endif
236
Kenny Root860d2702013-04-23 15:50:31 -0700237struct EVP_CIPHER_CTX_Delete {
238 void operator()(EVP_CIPHER_CTX* p) const {
Kenny Root11ac10b2013-10-18 09:51:43 -0700239 EVP_CIPHER_CTX_free(p);
Kenny Root860d2702013-04-23 15:50:31 -0700240 }
241};
242typedef UniquePtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Delete> Unique_EVP_CIPHER_CTX;
243
244struct EVP_PKEY_Delete {
245 void operator()(EVP_PKEY* p) const {
246 EVP_PKEY_free(p);
247 }
248};
249typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
250
251struct PKCS8_PRIV_KEY_INFO_Delete {
252 void operator()(PKCS8_PRIV_KEY_INFO* p) const {
253 PKCS8_PRIV_KEY_INFO_free(p);
254 }
255};
256typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
257
258struct RSA_Delete {
259 void operator()(RSA* p) const {
260 RSA_free(p);
261 }
262};
263typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
264
265struct ASN1_BIT_STRING_Delete {
266 void operator()(ASN1_BIT_STRING* p) const {
267 ASN1_BIT_STRING_free(p);
268 }
269};
270typedef UniquePtr<ASN1_BIT_STRING, ASN1_BIT_STRING_Delete> Unique_ASN1_BIT_STRING;
271
272struct ASN1_OBJECT_Delete {
273 void operator()(ASN1_OBJECT* p) const {
274 ASN1_OBJECT_free(p);
275 }
276};
277typedef UniquePtr<ASN1_OBJECT, ASN1_OBJECT_Delete> Unique_ASN1_OBJECT;
278
279struct ASN1_GENERALIZEDTIME_Delete {
280 void operator()(ASN1_GENERALIZEDTIME* p) const {
281 ASN1_GENERALIZEDTIME_free(p);
282 }
283};
284typedef UniquePtr<ASN1_GENERALIZEDTIME, ASN1_GENERALIZEDTIME_Delete> Unique_ASN1_GENERALIZEDTIME;
285
286struct SSL_Delete {
287 void operator()(SSL* p) const {
288 SSL_free(p);
289 }
290};
291typedef UniquePtr<SSL, SSL_Delete> Unique_SSL;
292
293struct SSL_CTX_Delete {
294 void operator()(SSL_CTX* p) const {
295 SSL_CTX_free(p);
296 }
297};
298typedef UniquePtr<SSL_CTX, SSL_CTX_Delete> Unique_SSL_CTX;
299
300struct X509_Delete {
301 void operator()(X509* p) const {
302 X509_free(p);
303 }
304};
305typedef UniquePtr<X509, X509_Delete> Unique_X509;
306
Kenny Root860d2702013-04-23 15:50:31 -0700307struct X509_NAME_Delete {
308 void operator()(X509_NAME* p) const {
309 X509_NAME_free(p);
310 }
311};
312typedef UniquePtr<X509_NAME, X509_NAME_Delete> Unique_X509_NAME;
313
Adam Langleyde5225d2014-10-06 15:55:30 -0700314#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -0700315struct PKCS7_Delete {
316 void operator()(PKCS7* p) const {
317 PKCS7_free(p);
318 }
319};
320typedef UniquePtr<PKCS7, PKCS7_Delete> Unique_PKCS7;
Adam Langleyde5225d2014-10-06 15:55:30 -0700321#endif
Kenny Root860d2702013-04-23 15:50:31 -0700322
323struct sk_SSL_CIPHER_Delete {
324 void operator()(STACK_OF(SSL_CIPHER)* p) const {
Kenny Root8c51e392013-09-09 19:15:39 -0700325 // We don't own SSL_CIPHER references, so no need for pop_free
Kenny Root860d2702013-04-23 15:50:31 -0700326 sk_SSL_CIPHER_free(p);
327 }
328};
329typedef UniquePtr<STACK_OF(SSL_CIPHER), sk_SSL_CIPHER_Delete> Unique_sk_SSL_CIPHER;
330
331struct sk_X509_Delete {
332 void operator()(STACK_OF(X509)* p) const {
Kenny Root8c51e392013-09-09 19:15:39 -0700333 sk_X509_pop_free(p, X509_free);
Kenny Root860d2702013-04-23 15:50:31 -0700334 }
335};
336typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509;
337
Adam Langley811e7ae2015-02-27 13:20:02 -0800338#if defined(OPENSSL_IS_BORINGSSL)
339struct sk_X509_CRL_Delete {
340 void operator()(STACK_OF(X509_CRL)* p) const {
341 sk_X509_CRL_pop_free(p, X509_CRL_free);
342 }
343};
344typedef UniquePtr<STACK_OF(X509_CRL), sk_X509_CRL_Delete> Unique_sk_X509_CRL;
345#endif
346
Kenny Root860d2702013-04-23 15:50:31 -0700347struct sk_X509_NAME_Delete {
348 void operator()(STACK_OF(X509_NAME)* p) const {
Kenny Root8c51e392013-09-09 19:15:39 -0700349 sk_X509_NAME_pop_free(p, X509_NAME_free);
Kenny Root860d2702013-04-23 15:50:31 -0700350 }
351};
352typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME;
353
354struct sk_ASN1_OBJECT_Delete {
355 void operator()(STACK_OF(ASN1_OBJECT)* p) const {
Kenny Root8c51e392013-09-09 19:15:39 -0700356 sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free);
Kenny Root860d2702013-04-23 15:50:31 -0700357 }
358};
359typedef UniquePtr<STACK_OF(ASN1_OBJECT), sk_ASN1_OBJECT_Delete> Unique_sk_ASN1_OBJECT;
360
361struct sk_GENERAL_NAME_Delete {
362 void operator()(STACK_OF(GENERAL_NAME)* p) const {
Kenny Root8c51e392013-09-09 19:15:39 -0700363 sk_GENERAL_NAME_pop_free(p, GENERAL_NAME_free);
Kenny Root860d2702013-04-23 15:50:31 -0700364 }
365};
366typedef UniquePtr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_Delete> Unique_sk_GENERAL_NAME;
367
368/**
369 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
370 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
371 * without triggering a warning by not using the result of release().
372 */
373#define OWNERSHIP_TRANSFERRED(obj) \
Kenny Root74f1a2a2013-09-11 15:24:38 -0700374 do { typeof (obj.release()) _dummy __attribute__((unused)) = obj.release(); } while(0)
Kenny Root860d2702013-04-23 15:50:31 -0700375
376/**
Adam Langleyca341142014-12-11 17:26:18 -0800377 * UNUSED_ARGUMENT can be used to mark an, otherwise unused, argument as "used"
378 * for the purposes of -Werror=unused-parameter. This can be needed when an
379 * argument's use is based on an #ifdef.
380 */
381#define UNUSED_ARGUMENT(x) ((void)(x));
382
383/**
Kenny Rootf6f66202015-05-08 14:01:56 -0700384 * Check array bounds for arguments when an array and offset are given.
385 */
386#define ARRAY_OFFSET_INVALID(array, offset) (offset < 0 || \
387 offset > static_cast<ssize_t>(array.size()))
388
389/**
390 * Check array bounds for arguments when an array, offset, and length are given.
391 */
392#define ARRAY_OFFSET_LENGTH_INVALID(array, offset, len) (offset < 0 || \
393 offset > static_cast<ssize_t>(array.size()) || len < 0 || \
394 len > static_cast<ssize_t>(array.size()) - offset)
395
396/**
Kenny Root860d2702013-04-23 15:50:31 -0700397 * Frees the SSL error state.
398 *
399 * OpenSSL keeps an "error stack" per thread, and given that this code
400 * can be called from arbitrary threads that we don't keep track of,
401 * we err on the side of freeing the error state promptly (instead of,
402 * say, at thread death).
403 */
404static void freeOpenSslErrorState(void) {
405 ERR_clear_error();
Adam Langleyde5225d2014-10-06 15:55:30 -0700406 ERR_remove_thread_state(NULL);
Kenny Root860d2702013-04-23 15:50:31 -0700407}
408
409/**
Kenny Roota260ee62014-08-12 15:38:10 -0700410 * Manages the freeing of the OpenSSL error stack. This allows you to
411 * instantiate this object during an SSL call that may fail and not worry
412 * about manually calling freeOpenSslErrorState() later.
413 *
414 * As an optimization, you can also call .release() for passing as an
415 * argument to things that free the error stack state as a side-effect.
416 */
417class OpenSslError {
418public:
419 OpenSslError() : sslError_(SSL_ERROR_NONE), released_(false) {
420 }
421
422 OpenSslError(SSL* ssl, int returnCode) : sslError_(SSL_ERROR_NONE), released_(false) {
423 reset(ssl, returnCode);
424 }
425
426 ~OpenSslError() {
427 if (!released_ && sslError_ != SSL_ERROR_NONE) {
428 freeOpenSslErrorState();
429 }
430 }
431
432 int get() const {
433 return sslError_;
434 }
435
436 void reset(SSL* ssl, int returnCode) {
437 if (returnCode <= 0) {
438 sslError_ = SSL_get_error(ssl, returnCode);
439 } else {
440 sslError_ = SSL_ERROR_NONE;
441 }
442 }
443
444 int release() {
445 released_ = true;
446 return sslError_;
447 }
448
449private:
450 int sslError_;
451 bool released_;
452};
453
454/**
Kenny Root923e3c52013-05-01 12:17:23 -0700455 * Throws a OutOfMemoryError with the given string as a message.
456 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700457static int jniThrowOutOfMemory(JNIEnv* env, const char* message) {
458 return jniThrowException(env, "java/lang/OutOfMemoryError", message);
Kenny Root923e3c52013-05-01 12:17:23 -0700459}
460
461/**
Kenny Root860d2702013-04-23 15:50:31 -0700462 * Throws a BadPaddingException with the given string as a message.
463 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700464static int throwBadPaddingException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700465 JNI_TRACE("throwBadPaddingException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700466 return jniThrowException(env, "javax/crypto/BadPaddingException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700467}
468
469/**
470 * Throws a SignatureException with the given string as a message.
471 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700472static int throwSignatureException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700473 JNI_TRACE("throwSignatureException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700474 return jniThrowException(env, "java/security/SignatureException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700475}
476
477/**
478 * Throws a InvalidKeyException with the given string as a message.
479 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700480static int throwInvalidKeyException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700481 JNI_TRACE("throwInvalidKeyException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700482 return jniThrowException(env, "java/security/InvalidKeyException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700483}
484
485/**
486 * Throws a SignatureException with the given string as a message.
487 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700488static int throwIllegalBlockSizeException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700489 JNI_TRACE("throwIllegalBlockSizeException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700490 return jniThrowException(env, "javax/crypto/IllegalBlockSizeException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700491}
492
493/**
494 * Throws a NoSuchAlgorithmException with the given string as a message.
495 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700496static int throwNoSuchAlgorithmException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700497 JNI_TRACE("throwUnknownAlgorithmException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700498 return jniThrowException(env, "java/security/NoSuchAlgorithmException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700499}
500
Kenny Root199a1342015-06-11 13:54:18 -0700501#if defined(OPENSSL_IS_BORINGSSL)
Kenny Rootccb82252015-06-11 12:58:31 -0700502/**
503 * Throws a ParsingException with the given string as a message.
504 */
505static int throwParsingException(JNIEnv* env, const char* message) {
506 return jniThrowException(
507 env,
508 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CertificateFactory$ParsingException",
509 message);
510}
Kenny Root199a1342015-06-11 13:54:18 -0700511#endif
Kenny Rootccb82252015-06-11 12:58:31 -0700512
Kenny Root48d7b0a2015-04-29 09:40:34 -0700513static int throwForAsn1Error(JNIEnv* env, int reason, const char *message,
514 int (*defaultThrow)(JNIEnv*, const char*)) {
Kenny Root860d2702013-04-23 15:50:31 -0700515 switch (reason) {
Kenny Root860d2702013-04-23 15:50:31 -0700516 case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:
Adam Langley09b021a2015-05-05 18:23:29 -0700517#if defined(ASN1_R_UNABLE_TO_DECODE_RSA_KEY)
518 case ASN1_R_UNABLE_TO_DECODE_RSA_KEY:
519#endif
Adam Langleyde5225d2014-10-06 15:55:30 -0700520#if defined(ASN1_R_WRONG_PUBLIC_KEY_TYPE)
Kenny Root860d2702013-04-23 15:50:31 -0700521 case ASN1_R_WRONG_PUBLIC_KEY_TYPE:
Adam Langleyde5225d2014-10-06 15:55:30 -0700522#endif
Adam Langley09b021a2015-05-05 18:23:29 -0700523#if defined(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY)
524 case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY:
525#endif
526#if defined(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE)
527 case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:
528#endif
Kenny Root48d7b0a2015-04-29 09:40:34 -0700529 return throwInvalidKeyException(env, message);
530 break;
Adam Langleyde5225d2014-10-06 15:55:30 -0700531#if defined(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
Kenny Root860d2702013-04-23 15:50:31 -0700532 case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700533 return throwNoSuchAlgorithmException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700534 break;
Adam Langleyde5225d2014-10-06 15:55:30 -0700535#endif
Adam Langleyde5225d2014-10-06 15:55:30 -0700536 }
Kenny Root48d7b0a2015-04-29 09:40:34 -0700537 return defaultThrow(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700538}
539
540#if defined(OPENSSL_IS_BORINGSSL)
Kenny Root48d7b0a2015-04-29 09:40:34 -0700541static int throwForCipherError(JNIEnv* env, int reason, const char *message,
542 int (*defaultThrow)(JNIEnv*, const char*)) {
Adam Langleyde5225d2014-10-06 15:55:30 -0700543 switch (reason) {
544 case CIPHER_R_BAD_DECRYPT:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700545 return throwBadPaddingException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700546 break;
547 case CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
548 case CIPHER_R_WRONG_FINAL_BLOCK_LENGTH:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700549 return throwIllegalBlockSizeException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700550 break;
551 case CIPHER_R_AES_KEY_SETUP_FAILED:
552 case CIPHER_R_BAD_KEY_LENGTH:
553 case CIPHER_R_UNSUPPORTED_KEY_SIZE:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700554 return throwInvalidKeyException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700555 break;
556 }
Kenny Root48d7b0a2015-04-29 09:40:34 -0700557 return defaultThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700558}
559
Kenny Root48d7b0a2015-04-29 09:40:34 -0700560static int throwForEvpError(JNIEnv* env, int reason, const char *message,
561 int (*defaultThrow)(JNIEnv*, const char*)) {
Kenny Root860d2702013-04-23 15:50:31 -0700562 switch (reason) {
Adam Langleyde5225d2014-10-06 15:55:30 -0700563 case EVP_R_MISSING_PARAMETERS:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700564 return throwInvalidKeyException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700565 break;
566 case EVP_R_UNSUPPORTED_ALGORITHM:
Adam Langley09b021a2015-05-05 18:23:29 -0700567#if defined(EVP_R_X931_UNSUPPORTED)
Adam Langleyde5225d2014-10-06 15:55:30 -0700568 case EVP_R_X931_UNSUPPORTED:
Adam Langley09b021a2015-05-05 18:23:29 -0700569#endif
Kenny Root48d7b0a2015-04-29 09:40:34 -0700570 return throwNoSuchAlgorithmException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700571 break;
Adam Langleyde5225d2014-10-06 15:55:30 -0700572#if defined(EVP_R_WRONG_PUBLIC_KEY_TYPE)
573 case EVP_R_WRONG_PUBLIC_KEY_TYPE:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700574 return throwInvalidKeyException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700575 break;
576#endif
577#if defined(EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
578 case EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700579 return throwNoSuchAlgorithmException(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700580 break;
581#endif
582 default:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700583 return defaultThrow(env, message);
Adam Langleyde5225d2014-10-06 15:55:30 -0700584 break;
585 }
586}
587#else
Kenny Root48d7b0a2015-04-29 09:40:34 -0700588static int throwForEvpError(JNIEnv* env, int reason, const char *message,
589 int (*defaultThrow)(JNIEnv*, const char*)) {
Adam Langleyde5225d2014-10-06 15:55:30 -0700590 switch (reason) {
Kenny Root860d2702013-04-23 15:50:31 -0700591 case EVP_R_BAD_DECRYPT:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700592 return throwBadPaddingException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700593 break;
594 case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
Kenny Root1d5c92f2013-09-12 10:48:37 -0700595 case EVP_R_WRONG_FINAL_BLOCK_LENGTH:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700596 return throwIllegalBlockSizeException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700597 break;
598 case EVP_R_BAD_KEY_LENGTH:
599 case EVP_R_BN_DECODE_ERROR:
600 case EVP_R_BN_PUBKEY_ERROR:
601 case EVP_R_INVALID_KEY_LENGTH:
602 case EVP_R_MISSING_PARAMETERS:
603 case EVP_R_UNSUPPORTED_KEY_SIZE:
604 case EVP_R_UNSUPPORTED_KEYLENGTH:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700605 return throwInvalidKeyException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700606 break;
607 case EVP_R_WRONG_PUBLIC_KEY_TYPE:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700608 return throwSignatureException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700609 break;
610 case EVP_R_UNSUPPORTED_ALGORITHM:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700611 return throwNoSuchAlgorithmException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700612 break;
613 default:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700614 return defaultThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700615 break;
616 }
617}
Adam Langleyde5225d2014-10-06 15:55:30 -0700618#endif
Kenny Root860d2702013-04-23 15:50:31 -0700619
Kenny Root48d7b0a2015-04-29 09:40:34 -0700620static int throwForRsaError(JNIEnv* env, int reason, const char *message,
621 int (*defaultThrow)(JNIEnv*, const char*)) {
Kenny Root860d2702013-04-23 15:50:31 -0700622 switch (reason) {
623 case RSA_R_BLOCK_TYPE_IS_NOT_01:
Kenny Root53497d02014-12-08 11:51:56 -0800624 case RSA_R_PKCS_DECODING_ERROR:
Adam Langley09b021a2015-05-05 18:23:29 -0700625#if defined(RSA_R_BLOCK_TYPE_IS_NOT_02)
626 case RSA_R_BLOCK_TYPE_IS_NOT_02:
627#endif
Kenny Root48d7b0a2015-04-29 09:40:34 -0700628 return throwBadPaddingException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700629 break;
Kenny Root860d2702013-04-23 15:50:31 -0700630 case RSA_R_BAD_SIGNATURE:
Kenny Root860d2702013-04-23 15:50:31 -0700631 case RSA_R_DATA_TOO_LARGE_FOR_MODULUS:
632 case RSA_R_INVALID_MESSAGE_LENGTH:
633 case RSA_R_WRONG_SIGNATURE_LENGTH:
Adam Langleyde5225d2014-10-06 15:55:30 -0700634#if !defined(OPENSSL_IS_BORINGSSL)
635 case RSA_R_ALGORITHM_MISMATCH:
636 case RSA_R_DATA_GREATER_THAN_MOD_LEN:
637#endif
Kenny Root48d7b0a2015-04-29 09:40:34 -0700638 return throwSignatureException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700639 break;
640 case RSA_R_UNKNOWN_ALGORITHM_TYPE:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700641 return throwNoSuchAlgorithmException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700642 break;
643 case RSA_R_MODULUS_TOO_LARGE:
644 case RSA_R_NO_PUBLIC_EXPONENT:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700645 return throwInvalidKeyException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700646 break;
647 }
Kenny Root48d7b0a2015-04-29 09:40:34 -0700648 return defaultThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700649}
650
Kenny Root48d7b0a2015-04-29 09:40:34 -0700651static int throwForX509Error(JNIEnv* env, int reason, const char *message,
652 int (*defaultThrow)(JNIEnv*, const char*)) {
Kenny Root860d2702013-04-23 15:50:31 -0700653 switch (reason) {
654 case X509_R_UNSUPPORTED_ALGORITHM:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700655 return throwNoSuchAlgorithmException(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700656 break;
657 default:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700658 return defaultThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700659 break;
660 }
661}
662
663/*
664 * Checks this thread's OpenSSL error queue and throws a RuntimeException if
665 * necessary.
666 *
667 * @return true if an exception was thrown, false if not.
668 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700669static bool throwExceptionIfNecessary(JNIEnv* env, const char* location __attribute__ ((unused)),
670 int (*defaultThrow)(JNIEnv*, const char*) = jniThrowRuntimeException) {
Kenny Root860d2702013-04-23 15:50:31 -0700671 const char* file;
672 int line;
673 const char* data;
674 int flags;
675 unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags);
676 int result = false;
677
678 if (error != 0) {
679 char message[256];
680 ERR_error_string_n(error, message, sizeof(message));
681 int library = ERR_GET_LIB(error);
682 int reason = ERR_GET_REASON(error);
683 JNI_TRACE("OpenSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s",
684 location, error, library, reason, file, line, message,
685 (flags & ERR_TXT_STRING) ? data : "(no data)");
686 switch (library) {
687 case ERR_LIB_RSA:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700688 throwForRsaError(env, reason, message, defaultThrow);
Kenny Root860d2702013-04-23 15:50:31 -0700689 break;
690 case ERR_LIB_ASN1:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700691 throwForAsn1Error(env, reason, message, defaultThrow);
Kenny Root860d2702013-04-23 15:50:31 -0700692 break;
Adam Langleyde5225d2014-10-06 15:55:30 -0700693#if defined(OPENSSL_IS_BORINGSSL)
694 case ERR_LIB_CIPHER:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700695 throwForCipherError(env, reason, message, defaultThrow);
Adam Langleyde5225d2014-10-06 15:55:30 -0700696 break;
697#endif
Kenny Root860d2702013-04-23 15:50:31 -0700698 case ERR_LIB_EVP:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700699 throwForEvpError(env, reason, message, defaultThrow);
Kenny Root860d2702013-04-23 15:50:31 -0700700 break;
701 case ERR_LIB_X509:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700702 throwForX509Error(env, reason, message, defaultThrow);
Kenny Root860d2702013-04-23 15:50:31 -0700703 break;
704 case ERR_LIB_DSA:
705 throwInvalidKeyException(env, message);
706 break;
707 default:
Kenny Root48d7b0a2015-04-29 09:40:34 -0700708 defaultThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700709 break;
710 }
711 result = true;
712 }
713
714 freeOpenSslErrorState();
715 return result;
716}
717
718/**
719 * Throws an SocketTimeoutException with the given string as a message.
720 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700721static int throwSocketTimeoutException(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700722 JNI_TRACE("throwSocketTimeoutException %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700723 return jniThrowException(env, "java/net/SocketTimeoutException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700724}
725
726/**
727 * Throws a javax.net.ssl.SSLException with the given string as a message.
728 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700729static int throwSSLHandshakeExceptionStr(JNIEnv* env, const char* message) {
Kenny Roota0c196d2014-03-26 13:56:24 -0700730 JNI_TRACE("throwSSLExceptionStr %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700731 return jniThrowException(env, "javax/net/ssl/SSLHandshakeException", message);
Kenny Roota0c196d2014-03-26 13:56:24 -0700732}
733
734/**
735 * Throws a javax.net.ssl.SSLException with the given string as a message.
736 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700737static int throwSSLExceptionStr(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700738 JNI_TRACE("throwSSLExceptionStr %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700739 return jniThrowException(env, "javax/net/ssl/SSLException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700740}
741
742/**
743 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message.
744 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700745static int throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) {
Kenny Root860d2702013-04-23 15:50:31 -0700746 JNI_TRACE("throwSSLProtocolExceptionStr %s", message);
Kenny Root48d7b0a2015-04-29 09:40:34 -0700747 return jniThrowException(env, "javax/net/ssl/SSLProtocolException", message);
Kenny Root860d2702013-04-23 15:50:31 -0700748}
749
750/**
751 * Throws an SSLException with a message constructed from the current
752 * SSL errors. This will also log the errors.
753 *
754 * @param env the JNI environment
755 * @param ssl the possibly NULL SSL
756 * @param sslErrorCode error code returned from SSL_get_error() or
757 * SSL_ERROR_NONE to probe with ERR_get_error
758 * @param message null-ok; general error message
759 */
Kenny Root48d7b0a2015-04-29 09:40:34 -0700760static int throwSSLExceptionWithSslErrors(JNIEnv* env, SSL* ssl, int sslErrorCode,
761 const char* message, int (*actualThrow)(JNIEnv*, const char*) = throwSSLExceptionStr) {
Kenny Root860d2702013-04-23 15:50:31 -0700762
763 if (message == NULL) {
764 message = "SSL error";
765 }
766
767 // First consult the SSL error code for the general message.
768 const char* sslErrorStr = NULL;
769 switch (sslErrorCode) {
770 case SSL_ERROR_NONE:
771 if (ERR_peek_error() == 0) {
772 sslErrorStr = "OK";
773 } else {
774 sslErrorStr = "";
775 }
776 break;
777 case SSL_ERROR_SSL:
778 sslErrorStr = "Failure in SSL library, usually a protocol error";
779 break;
780 case SSL_ERROR_WANT_READ:
781 sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this.";
782 break;
783 case SSL_ERROR_WANT_WRITE:
784 sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this.";
785 break;
786 case SSL_ERROR_WANT_X509_LOOKUP:
787 sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this.";
788 break;
789 case SSL_ERROR_SYSCALL:
790 sslErrorStr = "I/O error during system call";
791 break;
792 case SSL_ERROR_ZERO_RETURN:
793 sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this.";
794 break;
795 case SSL_ERROR_WANT_CONNECT:
796 sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this.";
797 break;
798 case SSL_ERROR_WANT_ACCEPT:
799 sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this.";
800 break;
801 default:
802 sslErrorStr = "Unknown SSL error";
803 }
804
805 // Prepend either our explicit message or a default one.
806 char* str;
807 if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) {
808 // problem with asprintf, just throw argument message, log everything
Kenny Root48d7b0a2015-04-29 09:40:34 -0700809 int ret = actualThrow(env, message);
Kenny Root860d2702013-04-23 15:50:31 -0700810 ALOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr);
811 freeOpenSslErrorState();
Kenny Root48d7b0a2015-04-29 09:40:34 -0700812 return ret;
Kenny Root860d2702013-04-23 15:50:31 -0700813 }
814
815 char* allocStr = str;
816
817 // For protocol errors, SSL might have more information.
818 if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) {
819 // Append each error as an additional line to the message.
820 for (;;) {
821 char errStr[256];
822 const char* file;
823 int line;
824 const char* data;
825 int flags;
826 unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags);
827 if (err == 0) {
828 break;
829 }
830
831 ERR_error_string_n(err, errStr, sizeof(errStr));
832
833 int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
834 (allocStr == NULL) ? "" : allocStr,
835 errStr,
836 file,
837 line,
838 (flags & ERR_TXT_STRING) ? data : "(no data)",
839 flags);
840
841 if (ret < 0) {
842 break;
843 }
844
845 free(allocStr);
846 allocStr = str;
847 }
848 // For errors during system calls, errno might be our friend.
849 } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
850 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
851 free(allocStr);
852 allocStr = str;
853 }
854 // If the error code is invalid, print it.
855 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
856 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
857 free(allocStr);
858 allocStr = str;
859 }
860 }
861
Kenny Root48d7b0a2015-04-29 09:40:34 -0700862 int ret;
Kenny Root860d2702013-04-23 15:50:31 -0700863 if (sslErrorCode == SSL_ERROR_SSL) {
Kenny Root48d7b0a2015-04-29 09:40:34 -0700864 ret = throwSSLProtocolExceptionStr(env, allocStr);
Kenny Root860d2702013-04-23 15:50:31 -0700865 } else {
Kenny Root48d7b0a2015-04-29 09:40:34 -0700866 ret = actualThrow(env, allocStr);
Kenny Root860d2702013-04-23 15:50:31 -0700867 }
868
869 ALOGV("%s", allocStr);
870 free(allocStr);
871 freeOpenSslErrorState();
Kenny Root48d7b0a2015-04-29 09:40:34 -0700872 return ret;
Kenny Root860d2702013-04-23 15:50:31 -0700873}
874
875/**
876 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
877 * If this function returns NULL and <code>throwIfNull</code> is
878 * passed as <code>true</code>, then this function will call
879 * <code>throwSSLExceptionStr</code> before returning, so in this case of
880 * NULL, a caller of this function should simply return and allow JNI
881 * to do its thing.
882 *
883 * @param env the JNI environment
884 * @param ssl_address; the ssl_address pointer as an integer
885 * @param throwIfNull whether to throw if the SSL pointer is NULL
886 * @returns the pointer, which may be NULL
887 */
888static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) {
889 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
890 if ((ssl_ctx == NULL) && throwIfNull) {
891 JNI_TRACE("ssl_ctx == null");
892 jniThrowNullPointerException(env, "ssl_ctx == null");
893 }
894 return ssl_ctx;
895}
896
897static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) {
898 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
899 if ((ssl == NULL) && throwIfNull) {
900 JNI_TRACE("ssl == null");
901 jniThrowNullPointerException(env, "ssl == null");
902 }
903 return ssl;
904}
905
906static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) {
907 SSL_SESSION* ssl_session
908 = reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
909 if ((ssl_session == NULL) && throwIfNull) {
910 JNI_TRACE("ssl_session == null");
911 jniThrowNullPointerException(env, "ssl_session == null");
912 }
913 return ssl_session;
914}
915
Alex Klyubin2d089e12013-11-21 10:28:08 -0800916static SSL_CIPHER* to_SSL_CIPHER(JNIEnv* env, jlong ssl_cipher_address, bool throwIfNull) {
917 SSL_CIPHER* ssl_cipher
918 = reinterpret_cast<SSL_CIPHER*>(static_cast<uintptr_t>(ssl_cipher_address));
919 if ((ssl_cipher == NULL) && throwIfNull) {
920 JNI_TRACE("ssl_cipher == null");
921 jniThrowNullPointerException(env, "ssl_cipher == null");
922 }
923 return ssl_cipher;
924}
925
Kenny Root652ff532014-02-24 12:35:11 -0800926template<typename T>
927static T* fromContextObject(JNIEnv* env, jobject contextObject) {
Sergio Giro796ed062015-03-18 17:01:28 +0000928 if (contextObject == NULL) {
929 JNI_TRACE("contextObject == null");
930 jniThrowNullPointerException(env, "contextObject == null");
931 return NULL;
932 }
Kenny Root4bff0a12014-11-25 12:02:21 -0800933 T* ref = reinterpret_cast<T*>(env->GetLongField(contextObject, nativeRef_context));
Kenny Root652ff532014-02-24 12:35:11 -0800934 if (ref == NULL) {
Sergio Giro796ed062015-03-18 17:01:28 +0000935 JNI_TRACE("ref == null");
936 jniThrowNullPointerException(env, "ref == null");
937 return NULL;
Kenny Root652ff532014-02-24 12:35:11 -0800938 }
939 return ref;
940}
941
Kenny Root860d2702013-04-23 15:50:31 -0700942/**
Kenny Root1744cf22014-01-30 13:41:26 -0800943 * Converts a Java byte[] two's complement to an OpenSSL BIGNUM. This will
944 * allocate the BIGNUM if *dest == NULL. Returns true on success. If the
945 * return value is false, there is a pending exception.
Kenny Root860d2702013-04-23 15:50:31 -0700946 */
947static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) {
Kenny Root1744cf22014-01-30 13:41:26 -0800948 JNI_TRACE("arrayToBignum(%p, %p)", source, dest);
949 if (dest == NULL) {
950 JNI_TRACE("arrayToBignum(%p, %p) => dest is null!", source, dest);
951 jniThrowNullPointerException(env, "dest == null");
952 return false;
953 }
954 JNI_TRACE("arrayToBignum(%p, %p) *dest == %p", source, dest, *dest);
Kenny Root860d2702013-04-23 15:50:31 -0700955
956 ScopedByteArrayRO sourceBytes(env, source);
957 if (sourceBytes.get() == NULL) {
Kenny Root1744cf22014-01-30 13:41:26 -0800958 JNI_TRACE("arrayToBignum(%p, %p) => NULL", source, dest);
Kenny Root860d2702013-04-23 15:50:31 -0700959 return false;
960 }
Kenny Root1744cf22014-01-30 13:41:26 -0800961 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(sourceBytes.get());
962 size_t tmpSize = sourceBytes.size();
Kenny Root5b1934c2014-01-31 15:35:13 -0800963
964 /* if the array is empty, it is zero. */
965 if (tmpSize == 0) {
966 if (*dest == NULL) {
967 *dest = BN_new();
968 }
969 BN_zero(*dest);
970 return true;
971 }
972
Kenny Root1744cf22014-01-30 13:41:26 -0800973 UniquePtr<unsigned char[]> twosComplement;
974 bool negative = (tmp[0] & 0x80) != 0;
975 if (negative) {
976 // Need to convert to two's complement.
977 twosComplement.reset(new unsigned char[tmpSize]);
978 unsigned char* twosBytes = reinterpret_cast<unsigned char*>(twosComplement.get());
979 memcpy(twosBytes, tmp, tmpSize);
980 tmp = twosBytes;
Kenny Root860d2702013-04-23 15:50:31 -0700981
Kenny Root1744cf22014-01-30 13:41:26 -0800982 bool carry = true;
983 for (ssize_t i = tmpSize - 1; i >= 0; i--) {
984 twosBytes[i] ^= 0xFF;
985 if (carry) {
986 carry = (++twosBytes[i]) == 0;
987 }
988 }
989 }
990 BIGNUM *ret = BN_bin2bn(tmp, tmpSize, *dest);
991 if (ret == NULL) {
992 jniThrowRuntimeException(env, "Conversion to BIGNUM failed");
993 JNI_TRACE("arrayToBignum(%p, %p) => threw exception", source, dest);
994 return false;
995 }
996 BN_set_negative(ret, negative ? 1 : 0);
997
998 *dest = ret;
999 JNI_TRACE("arrayToBignum(%p, %p) => *dest = %p", source, dest, ret);
Kenny Root860d2702013-04-23 15:50:31 -07001000 return true;
1001}
1002
Chih-Hung Hsiehdbb61002014-11-21 17:21:30 -08001003#if defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07001004/**
Adam Langleyde5225d2014-10-06 15:55:30 -07001005 * arrayToBignumSize sets |*out_size| to the size of the big-endian number
1006 * contained in |source|. It returns true on success and sets an exception and
1007 * returns false otherwise.
1008 */
1009static bool arrayToBignumSize(JNIEnv* env, jbyteArray source, size_t* out_size) {
1010 JNI_TRACE("arrayToBignumSize(%p, %p)", source, out_size);
1011
1012 ScopedByteArrayRO sourceBytes(env, source);
1013 if (sourceBytes.get() == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07001014 JNI_TRACE("arrayToBignum(%p, %p) => NULL", source, out_size);
Adam Langleyde5225d2014-10-06 15:55:30 -07001015 return false;
1016 }
1017 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(sourceBytes.get());
1018 size_t tmpSize = sourceBytes.size();
1019
1020 if (tmpSize == 0) {
1021 *out_size = 0;
1022 return true;
1023 }
1024
1025 if ((tmp[0] & 0x80) != 0) {
1026 // Negative numbers are invalid.
1027 jniThrowRuntimeException(env, "Negative number");
1028 return false;
1029 }
1030
1031 while (tmpSize > 0 && tmp[0] == 0) {
1032 tmp++;
1033 tmpSize--;
1034 }
1035
1036 *out_size = tmpSize;
1037 return true;
1038}
Chih-Hung Hsiehdbb61002014-11-21 17:21:30 -08001039#endif
Adam Langleyde5225d2014-10-06 15:55:30 -07001040
1041/**
Kenny Root1744cf22014-01-30 13:41:26 -08001042 * Converts an OpenSSL BIGNUM to a Java byte[] array in two's complement.
Kenny Root860d2702013-04-23 15:50:31 -07001043 */
1044static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) {
1045 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName);
1046
1047 if (source == NULL) {
1048 jniThrowNullPointerException(env, sourceName);
1049 return NULL;
1050 }
1051
Kenny Root1744cf22014-01-30 13:41:26 -08001052 size_t numBytes = BN_num_bytes(source) + 1;
1053 jbyteArray javaBytes = env->NewByteArray(numBytes);
Kenny Root860d2702013-04-23 15:50:31 -07001054 ScopedByteArrayRW bytes(env, javaBytes);
1055 if (bytes.get() == NULL) {
1056 JNI_TRACE("bignumToArray(%p, %s) => NULL", source, sourceName);
1057 return NULL;
1058 }
1059
1060 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
Kenny Root38f3d462013-06-05 15:31:11 -07001061 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) {
Kenny Root860d2702013-04-23 15:50:31 -07001062 throwExceptionIfNecessary(env, "bignumToArray");
1063 return NULL;
1064 }
1065
Kenny Root1744cf22014-01-30 13:41:26 -08001066 // Set the sign and convert to two's complement if necessary for the Java code.
1067 if (BN_is_negative(source)) {
1068 bool carry = true;
1069 for (ssize_t i = numBytes - 1; i >= 0; i--) {
1070 tmp[i] ^= 0xFF;
1071 if (carry) {
1072 carry = (++tmp[i]) == 0;
1073 }
1074 }
1075 *tmp |= 0x80;
1076 } else {
1077 *tmp = 0x00;
1078 }
1079
Kenny Root860d2702013-04-23 15:50:31 -07001080 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes);
1081 return javaBytes;
1082}
1083
1084/**
1085 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data
1086 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>"
1087 * from the OpenSSL ASN.1 API.
1088 */
Adam Langleyde5225d2014-10-06 15:55:30 -07001089template<typename T>
1090jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj, int (*i2d_func)(T*, unsigned char**)) {
Kenny Root860d2702013-04-23 15:50:31 -07001091 if (obj == NULL) {
1092 jniThrowNullPointerException(env, "ASN1 input == null");
1093 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj);
1094 return NULL;
1095 }
1096
1097 int derLen = i2d_func(obj, NULL);
1098 if (derLen < 0) {
1099 throwExceptionIfNecessary(env, "ASN1ToByteArray");
1100 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj);
1101 return NULL;
1102 }
1103
1104 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
1105 if (byteArray.get() == NULL) {
1106 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj);
1107 return NULL;
1108 }
1109
1110 ScopedByteArrayRW bytes(env, byteArray.get());
1111 if (bytes.get() == NULL) {
1112 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj);
1113 return NULL;
1114 }
1115
1116 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
1117 int ret = i2d_func(obj, &p);
1118 if (ret < 0) {
1119 throwExceptionIfNecessary(env, "ASN1ToByteArray");
1120 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj);
1121 return NULL;
1122 }
1123
1124 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret);
1125 return byteArray.release();
1126}
1127
1128template<typename T, T* (*d2i_func)(T**, const unsigned char**, long)>
1129T* ByteArrayToASN1(JNIEnv* env, jbyteArray byteArray) {
1130 ScopedByteArrayRO bytes(env, byteArray);
1131 if (bytes.get() == NULL) {
1132 JNI_TRACE("ByteArrayToASN1(%p) => using byte array failed", byteArray);
1133 return 0;
1134 }
1135
1136 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
1137 return d2i_func(NULL, &tmp, bytes.size());
1138}
1139
1140/**
1141 * Converts ASN.1 BIT STRING to a jbooleanArray.
1142 */
1143jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, ASN1_BIT_STRING* bitStr) {
1144 int size = bitStr->length * 8;
1145 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
1146 size -= bitStr->flags & 0x07;
1147 }
1148
1149 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
1150 if (bitsRef.get() == NULL) {
1151 return NULL;
1152 }
1153
1154 ScopedBooleanArrayRW bitsArray(env, bitsRef.get());
1155 for (int i = 0; i < static_cast<int>(bitsArray.size()); i++) {
1156 bitsArray[i] = ASN1_BIT_STRING_get_bit(bitStr, i);
1157 }
1158
1159 return bitsRef.release();
1160}
1161
1162/**
Kenny Root86dd8322014-12-01 12:01:44 -08001163 * Safely clear SSL sessions and throw an error if there was something already
1164 * in the error stack.
1165 */
1166static void safeSslClear(SSL* ssl) {
1167 if (SSL_clear(ssl) != 1) {
1168 freeOpenSslErrorState();
1169 }
1170}
1171
1172/**
Kenny Rootc58a1862013-09-11 10:05:32 -07001173 * To avoid the round-trip to ASN.1 and back in X509_dup, we just up the reference count.
1174 */
1175static X509* X509_dup_nocopy(X509* x509) {
Kenny Root0e9746b2013-09-12 15:14:48 -07001176 if (x509 == NULL) {
1177 return NULL;
1178 }
Adam Langleyca6d8d32015-06-04 18:03:28 -07001179#if defined(OPENSSL_IS_BORINGSSL)
1180 return X509_up_ref(x509);
1181#else
Kenny Rootc58a1862013-09-11 10:05:32 -07001182 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
1183 return x509;
Adam Langleyca6d8d32015-06-04 18:03:28 -07001184#endif
Kenny Rootc58a1862013-09-11 10:05:32 -07001185}
1186
Kenny Rootf878e432013-11-08 11:37:48 -08001187/*
1188 * Sets the read and write BIO for an SSL connection and removes it when it goes out of scope.
1189 * We hang on to BIO with a JNI GlobalRef and we want to remove them as soon as possible.
1190 */
1191class ScopedSslBio {
1192public:
1193 ScopedSslBio(SSL *ssl, BIO* rbio, BIO* wbio) : ssl_(ssl) {
1194 SSL_set_bio(ssl_, rbio, wbio);
Adam Langleyca6d8d32015-06-04 18:03:28 -07001195#if defined(OPENSSL_IS_BORINGSSL)
1196 BIO_up_ref(rbio);
1197 BIO_up_ref(wbio);
1198#else
Kenny Rootf878e432013-11-08 11:37:48 -08001199 CRYPTO_add(&rbio->references,1,CRYPTO_LOCK_BIO);
1200 CRYPTO_add(&wbio->references,1,CRYPTO_LOCK_BIO);
Adam Langleyca6d8d32015-06-04 18:03:28 -07001201#endif
Kenny Rootf878e432013-11-08 11:37:48 -08001202 }
1203
1204 ~ScopedSslBio() {
1205 SSL_set_bio(ssl_, NULL, NULL);
1206 }
1207
1208private:
1209 SSL* const ssl_;
1210};
1211
Kenny Rootc58a1862013-09-11 10:05:32 -07001212/**
Kenny Rootf24ba062014-06-09 10:37:46 -07001213 * Obtains the current thread's JNIEnv
1214 */
1215static JNIEnv* getJNIEnv() {
1216 JNIEnv* env;
Kenny Roote0e2a5b2015-04-28 16:43:59 -07001217#ifdef ANDROID
Kenny Rootf24ba062014-06-09 10:37:46 -07001218 if (gJavaVM->AttachCurrentThread(&env, NULL) < 0) {
Kenny Roote0e2a5b2015-04-28 16:43:59 -07001219#else
1220 if (gJavaVM->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL) < 0) {
1221#endif
Kenny Rootf24ba062014-06-09 10:37:46 -07001222 ALOGE("Could not attach JavaVM to find current JNIEnv");
1223 return NULL;
1224 }
1225 return env;
1226}
1227
1228/**
Kenny Root860d2702013-04-23 15:50:31 -07001229 * BIO for InputStream
1230 */
1231class BIO_Stream {
1232public:
1233 BIO_Stream(jobject stream) :
1234 mEof(false) {
Kenny Rootf24ba062014-06-09 10:37:46 -07001235 JNIEnv* env = getJNIEnv();
Kenny Root860d2702013-04-23 15:50:31 -07001236 mStream = env->NewGlobalRef(stream);
1237 }
1238
1239 ~BIO_Stream() {
Kenny Rootf24ba062014-06-09 10:37:46 -07001240 JNIEnv* env = getJNIEnv();
Kenny Root860d2702013-04-23 15:50:31 -07001241
1242 env->DeleteGlobalRef(mStream);
1243 }
1244
1245 bool isEof() const {
1246 JNI_TRACE("isEof? %s", mEof ? "yes" : "no");
1247 return mEof;
1248 }
1249
1250 int flush() {
Kenny Rootf24ba062014-06-09 10:37:46 -07001251 JNIEnv* env = getJNIEnv();
Kenny Root860d2702013-04-23 15:50:31 -07001252 if (env == NULL) {
1253 return -1;
1254 }
1255
Kenny Root64f361d2014-05-02 10:39:35 -07001256 if (env->ExceptionCheck()) {
1257 JNI_TRACE("BIO_Stream::flush called with pending exception");
1258 return -1;
1259 }
1260
Kenny Root860d2702013-04-23 15:50:31 -07001261 env->CallVoidMethod(mStream, outputStream_flushMethod);
1262 if (env->ExceptionCheck()) {
1263 return -1;
1264 }
1265
1266 return 1;
1267 }
1268
1269protected:
1270 jobject getStream() {
1271 return mStream;
1272 }
1273
1274 void setEof(bool eof) {
1275 mEof = eof;
1276 }
1277
Kenny Root860d2702013-04-23 15:50:31 -07001278private:
1279 jobject mStream;
1280 bool mEof;
1281};
1282
1283class BIO_InputStream : public BIO_Stream {
1284public:
Adam Langleyd82dc062015-05-18 17:29:43 -07001285 BIO_InputStream(jobject stream, bool isFinite) :
1286 BIO_Stream(stream),
1287 isFinite_(isFinite) {
Kenny Root860d2702013-04-23 15:50:31 -07001288 }
1289
1290 int read(char *buf, int len) {
1291 return read_internal(buf, len, inputStream_readMethod);
1292 }
1293
1294 int gets(char *buf, int len) {
1295 if (len > PEM_LINE_LENGTH) {
1296 len = PEM_LINE_LENGTH;
1297 }
1298
1299 int read = read_internal(buf, len - 1, openSslInputStream_readLineMethod);
1300 buf[read] = '\0';
1301 JNI_TRACE("BIO::gets \"%s\"", buf);
1302 return read;
1303 }
1304
Adam Langleyd82dc062015-05-18 17:29:43 -07001305 bool isFinite() const {
1306 return isFinite_;
1307 }
1308
Kenny Root860d2702013-04-23 15:50:31 -07001309private:
Adam Langleyd82dc062015-05-18 17:29:43 -07001310 const bool isFinite_;
1311
Kenny Root860d2702013-04-23 15:50:31 -07001312 int read_internal(char *buf, int len, jmethodID method) {
Kenny Rootf24ba062014-06-09 10:37:46 -07001313 JNIEnv* env = getJNIEnv();
Kenny Root860d2702013-04-23 15:50:31 -07001314 if (env == NULL) {
1315 JNI_TRACE("BIO_InputStream::read could not get JNIEnv");
1316 return -1;
1317 }
1318
Kenny Root64f361d2014-05-02 10:39:35 -07001319 if (env->ExceptionCheck()) {
1320 JNI_TRACE("BIO_InputStream::read called with pending exception");
1321 return -1;
1322 }
1323
Kenny Root860d2702013-04-23 15:50:31 -07001324 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1325 if (javaBytes.get() == NULL) {
1326 JNI_TRACE("BIO_InputStream::read failed call to NewByteArray");
1327 return -1;
1328 }
1329
1330 jint read = env->CallIntMethod(getStream(), method, javaBytes.get());
1331 if (env->ExceptionCheck()) {
1332 JNI_TRACE("BIO_InputStream::read failed call to InputStream#read");
1333 return -1;
1334 }
1335
1336 /* Java uses -1 to indicate EOF condition. */
1337 if (read == -1) {
1338 setEof(true);
1339 read = 0;
1340 } else if (read > 0) {
1341 env->GetByteArrayRegion(javaBytes.get(), 0, read, reinterpret_cast<jbyte*>(buf));
1342 }
1343
1344 return read;
1345 }
1346
1347public:
1348 /** Length of PEM-encoded line (64) plus CR plus NULL */
1349 static const int PEM_LINE_LENGTH = 66;
1350};
1351
1352class BIO_OutputStream : public BIO_Stream {
1353public:
1354 BIO_OutputStream(jobject stream) :
1355 BIO_Stream(stream) {
1356 }
1357
1358 int write(const char *buf, int len) {
Kenny Rootf24ba062014-06-09 10:37:46 -07001359 JNIEnv* env = getJNIEnv();
Kenny Root860d2702013-04-23 15:50:31 -07001360 if (env == NULL) {
1361 JNI_TRACE("BIO_OutputStream::write => could not get JNIEnv");
1362 return -1;
1363 }
1364
Kenny Root64f361d2014-05-02 10:39:35 -07001365 if (env->ExceptionCheck()) {
1366 JNI_TRACE("BIO_OutputStream::write => called with pending exception");
1367 return -1;
1368 }
1369
Kenny Root860d2702013-04-23 15:50:31 -07001370 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
1371 if (javaBytes.get() == NULL) {
1372 JNI_TRACE("BIO_OutputStream::write => failed call to NewByteArray");
1373 return -1;
1374 }
1375
1376 env->SetByteArrayRegion(javaBytes.get(), 0, len, reinterpret_cast<const jbyte*>(buf));
1377
1378 env->CallVoidMethod(getStream(), outputStream_writeMethod, javaBytes.get());
1379 if (env->ExceptionCheck()) {
1380 JNI_TRACE("BIO_OutputStream::write => failed call to OutputStream#write");
1381 return -1;
1382 }
1383
Elliott Hughesfb822ae2013-08-19 15:45:20 -07001384 return len;
Kenny Root860d2702013-04-23 15:50:31 -07001385 }
1386};
1387
1388static int bio_stream_create(BIO *b) {
1389 b->init = 1;
1390 b->num = 0;
1391 b->ptr = NULL;
1392 b->flags = 0;
1393 return 1;
1394}
1395
1396static int bio_stream_destroy(BIO *b) {
1397 if (b == NULL) {
1398 return 0;
1399 }
1400
1401 if (b->ptr != NULL) {
1402 delete static_cast<BIO_Stream*>(b->ptr);
1403 b->ptr = NULL;
1404 }
1405
1406 b->init = 0;
1407 b->flags = 0;
1408 return 1;
1409}
1410
1411static int bio_stream_read(BIO *b, char *buf, int len) {
Kenny Rootf878e432013-11-08 11:37:48 -08001412 BIO_clear_retry_flags(b);
Kenny Root860d2702013-04-23 15:50:31 -07001413 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
Kenny Rootf878e432013-11-08 11:37:48 -08001414 int ret = stream->read(buf, len);
1415 if (ret == 0) {
Adam Langleyd82dc062015-05-18 17:29:43 -07001416 if (stream->isFinite()) {
1417 return 0;
1418 }
1419 // If the BIO_InputStream is not finite then EOF doesn't mean that
1420 // there's nothing more coming.
Kenny Rootf878e432013-11-08 11:37:48 -08001421 BIO_set_retry_read(b);
1422 return -1;
1423 }
1424 return ret;
Kenny Root860d2702013-04-23 15:50:31 -07001425}
1426
1427static int bio_stream_write(BIO *b, const char *buf, int len) {
Kenny Rootf878e432013-11-08 11:37:48 -08001428 BIO_clear_retry_flags(b);
Kenny Root860d2702013-04-23 15:50:31 -07001429 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1430 return stream->write(buf, len);
1431}
1432
1433static int bio_stream_puts(BIO *b, const char *buf) {
1434 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr);
1435 return stream->write(buf, strlen(buf));
1436}
1437
1438static int bio_stream_gets(BIO *b, char *buf, int len) {
1439 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
1440 return stream->gets(buf, len);
1441}
1442
1443static void bio_stream_assign(BIO *b, BIO_Stream* stream) {
1444 b->ptr = static_cast<void*>(stream);
1445}
1446
1447static long bio_stream_ctrl(BIO *b, int cmd, long, void *) {
1448 BIO_Stream* stream = static_cast<BIO_Stream*>(b->ptr);
1449
1450 switch (cmd) {
1451 case BIO_CTRL_EOF:
1452 return stream->isEof() ? 1 : 0;
1453 case BIO_CTRL_FLUSH:
1454 return stream->flush();
1455 default:
1456 return 0;
1457 }
1458}
1459
1460static BIO_METHOD stream_bio_method = {
1461 ( 100 | 0x0400 ), /* source/sink BIO */
1462 "InputStream/OutputStream BIO",
1463 bio_stream_write, /* bio_write */
1464 bio_stream_read, /* bio_read */
1465 bio_stream_puts, /* bio_puts */
1466 bio_stream_gets, /* bio_gets */
1467 bio_stream_ctrl, /* bio_ctrl */
1468 bio_stream_create, /* bio_create */
1469 bio_stream_destroy, /* bio_free */
1470 NULL, /* no bio_callback_ctrl */
1471};
1472
Kenny Rootf24ba062014-06-09 10:37:46 -07001473static jbyteArray rawSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey,
1474 const char* message, size_t message_len) {
1475 ScopedLocalRef<jbyteArray> messageArray(env, env->NewByteArray(message_len));
1476 if (env->ExceptionCheck()) {
1477 JNI_TRACE("rawSignDigestWithPrivateKey(%p) => threw exception", privateKey);
1478 return NULL;
1479 }
1480
1481 {
1482 ScopedByteArrayRW messageBytes(env, messageArray.get());
1483 if (messageBytes.get() == NULL) {
1484 JNI_TRACE("rawSignDigestWithPrivateKey(%p) => using byte array failed", privateKey);
1485 return NULL;
1486 }
1487
1488 memcpy(messageBytes.get(), message, message_len);
1489 }
1490
1491 jmethodID rawSignMethod = env->GetStaticMethodID(cryptoUpcallsClass,
1492 "rawSignDigestWithPrivateKey", "(Ljava/security/PrivateKey;[B)[B");
1493 if (rawSignMethod == NULL) {
1494 ALOGE("Could not find rawSignDigestWithPrivateKey");
1495 return NULL;
1496 }
1497
1498 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
1499 cryptoUpcallsClass, rawSignMethod, privateKey, messageArray.get()));
1500}
1501
Alex Klyubind1b44882015-06-10 13:02:22 -07001502// rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
1503// from |ciphertext|. The ciphertext is expected to be padded using the scheme
1504// given in |padding|, which must be one of |RSA_*_PADDING| constants from
1505// OpenSSL.
1506static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
Kenny Rootf24ba062014-06-09 10:37:46 -07001507 const char* ciphertext, size_t ciphertext_len) {
1508 ScopedLocalRef<jbyteArray> ciphertextArray(env, env->NewByteArray(ciphertext_len));
1509 if (env->ExceptionCheck()) {
Alex Klyubind1b44882015-06-10 13:02:22 -07001510 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => threw exception", privateKey);
Kenny Rootf24ba062014-06-09 10:37:46 -07001511 return NULL;
1512 }
1513
1514 {
1515 ScopedByteArrayRW ciphertextBytes(env, ciphertextArray.get());
1516 if (ciphertextBytes.get() == NULL) {
Alex Klyubind1b44882015-06-10 13:02:22 -07001517 JNI_TRACE("rsaDecryptWithPrivateKey(%p) => using byte array failed", privateKey);
Kenny Rootf24ba062014-06-09 10:37:46 -07001518 return NULL;
1519 }
1520
1521 memcpy(ciphertextBytes.get(), ciphertext, ciphertext_len);
1522 }
1523
Alex Klyubind1b44882015-06-10 13:02:22 -07001524 jmethodID rsaDecryptMethod = env->GetStaticMethodID(cryptoUpcallsClass,
1525 "rsaDecryptWithPrivateKey", "(Ljava/security/PrivateKey;I[B)[B");
1526 if (rsaDecryptMethod == NULL) {
1527 ALOGE("Could not find rsaDecryptWithPrivateKey");
Kenny Rootf24ba062014-06-09 10:37:46 -07001528 return NULL;
1529 }
1530
1531 return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
Alex Klyubind1b44882015-06-10 13:02:22 -07001532 cryptoUpcallsClass,
1533 rsaDecryptMethod,
1534 privateKey,
1535 padding,
1536 ciphertextArray.get()));
Kenny Rootf24ba062014-06-09 10:37:46 -07001537}
1538
1539// *********************************************
1540// From keystore_openssl.cpp in Chromium source.
1541// *********************************************
1542
Adam Langleyde5225d2014-10-06 15:55:30 -07001543#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Rootf24ba062014-06-09 10:37:46 -07001544// Custom RSA_METHOD that uses the platform APIs.
1545// Note that for now, only signing through RSA_sign() is really supported.
1546// all other method pointers are either stubs returning errors, or no-ops.
1547// See <openssl/rsa.h> for exact declaration of RSA_METHOD.
1548
1549int RsaMethodPubEnc(int /* flen */,
1550 const unsigned char* /* from */,
1551 unsigned char* /* to */,
1552 RSA* /* rsa */,
1553 int /* padding */) {
1554 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
1555 return -1;
1556}
1557
Chih-Hung Hsieh04b35002014-08-26 11:16:49 -07001558int RsaMethodPubDec(int /* flen */,
1559 const unsigned char* /* from */,
1560 unsigned char* /* to */,
1561 RSA* /* rsa */,
1562 int /* padding */) {
Kenny Rootf24ba062014-06-09 10:37:46 -07001563 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
1564 return -1;
1565}
1566
1567// See RSA_eay_private_encrypt in
1568// third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default
1569// implementation of this function.
1570int RsaMethodPrivEnc(int flen,
1571 const unsigned char *from,
1572 unsigned char *to,
1573 RSA *rsa,
1574 int padding) {
1575 if (padding != RSA_PKCS1_PADDING) {
1576 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
1577 // by using javax.crypto.Cipher and picking either the
1578 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
1579 // appropriate. I believe support for both of these was added in
1580 // the same Android version as the "NONEwithRSA"
1581 // java.security.Signature algorithm, so the same version checks
1582 // for GetRsaLegacyKey should work.
1583 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
1584 return -1;
1585 }
1586
1587 // Retrieve private key JNI reference.
1588 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1589 if (!private_key) {
1590 ALOGE("Null JNI reference passed to RsaMethodPrivEnc!");
1591 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1592 return -1;
1593 }
1594
1595 JNIEnv* env = getJNIEnv();
1596 if (env == NULL) {
1597 return -1;
1598 }
1599
1600 // For RSA keys, this function behaves as RSA_private_encrypt with
1601 // PKCS#1 padding.
1602 ScopedLocalRef<jbyteArray> signature(
1603 env, rawSignDigestWithPrivateKey(env, private_key,
1604 reinterpret_cast<const char*>(from), flen));
1605 if (signature.get() == NULL) {
1606 ALOGE("Could not sign message in RsaMethodPrivEnc!");
1607 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1608 return -1;
1609 }
1610
1611 ScopedByteArrayRO signatureBytes(env, signature.get());
1612 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
1613 if (signatureBytes.size() > expected_size) {
Ian Rogers1b60d4f2014-06-11 12:41:41 -07001614 ALOGE("RSA Signature size mismatch, actual: %zd, expected <= %zd", signatureBytes.size(),
Kenny Rootf24ba062014-06-09 10:37:46 -07001615 expected_size);
1616 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
1617 return -1;
1618 }
1619
1620 // Copy result to OpenSSL-provided buffer. rawSignDigestWithPrivateKey
1621 // should pad with leading 0s, but if it doesn't, pad the result.
1622 size_t zero_pad = expected_size - signatureBytes.size();
1623 memset(to, 0, zero_pad);
1624 memcpy(to + zero_pad, signatureBytes.get(), signatureBytes.size());
1625
1626 return expected_size;
1627}
1628
1629int RsaMethodPrivDec(int flen,
1630 const unsigned char* from,
1631 unsigned char* to,
1632 RSA* rsa,
1633 int padding) {
Kenny Rootf24ba062014-06-09 10:37:46 -07001634 // Retrieve private key JNI reference.
1635 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1636 if (!private_key) {
1637 ALOGE("Null JNI reference passed to RsaMethodPrivDec!");
1638 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1639 return -1;
1640 }
1641
1642 JNIEnv* env = getJNIEnv();
1643 if (env == NULL) {
1644 return -1;
1645 }
1646
Alex Klyubind1b44882015-06-10 13:02:22 -07001647 // This function behaves as RSA_private_decrypt.
1648 ScopedLocalRef<jbyteArray> cleartext(env, rsaDecryptWithPrivateKey(env, private_key,
1649 padding, reinterpret_cast<const char*>(from), flen));
Kenny Rootf24ba062014-06-09 10:37:46 -07001650 if (cleartext.get() == NULL) {
1651 ALOGE("Could not decrypt message in RsaMethodPrivDec!");
1652 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1653 return -1;
1654 }
1655
1656 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
1657 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
1658 if (cleartextBytes.size() > expected_size) {
Ian Rogers1b60d4f2014-06-11 12:41:41 -07001659 ALOGE("RSA ciphertext size mismatch, actual: %zd, expected <= %zd", cleartextBytes.size(),
Kenny Rootf24ba062014-06-09 10:37:46 -07001660 expected_size);
1661 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
1662 return -1;
1663 }
1664
1665 // Copy result to OpenSSL-provided buffer.
1666 memcpy(to, cleartextBytes.get(), cleartextBytes.size());
1667
1668 return cleartextBytes.size();
1669}
1670
1671int RsaMethodInit(RSA*) {
1672 return 0;
1673}
1674
1675int RsaMethodFinish(RSA* rsa) {
1676 // Ensure the global JNI reference created with this wrapper is
1677 // properly destroyed with it.
1678 jobject key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
1679 if (key != NULL) {
1680 RSA_set_app_data(rsa, NULL);
1681 JNIEnv* env = getJNIEnv();
1682 env->DeleteGlobalRef(key);
1683 }
1684 // Actual return value is ignored by OpenSSL. There are no docs
1685 // explaining what this is supposed to be.
1686 return 0;
1687}
1688
1689const RSA_METHOD android_rsa_method = {
1690 /* .name = */ "Android signing-only RSA method",
1691 /* .rsa_pub_enc = */ RsaMethodPubEnc,
1692 /* .rsa_pub_dec = */ RsaMethodPubDec,
1693 /* .rsa_priv_enc = */ RsaMethodPrivEnc,
1694 /* .rsa_priv_dec = */ RsaMethodPrivDec,
1695 /* .rsa_mod_exp = */ NULL,
1696 /* .bn_mod_exp = */ NULL,
1697 /* .init = */ RsaMethodInit,
1698 /* .finish = */ RsaMethodFinish,
1699 // This flag is necessary to tell OpenSSL to avoid checking the content
1700 // (i.e. internal fields) of the private key. Otherwise, it will complain
1701 // it's not valid for the certificate.
1702 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK,
1703 /* .app_data = */ NULL,
1704 /* .rsa_sign = */ NULL,
1705 /* .rsa_verify = */ NULL,
1706 /* .rsa_keygen = */ NULL,
1707};
1708
Kenny Rootf24ba062014-06-09 10:37:46 -07001709// Used to ensure that the global JNI reference associated with a custom
1710// EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed
1711// (this function is called when EVP_PKEY_free() is called on the wrapper).
1712void ExDataFree(void* /* parent */,
1713 void* ptr,
1714 CRYPTO_EX_DATA* ad,
1715 int idx,
1716 long /* argl */,
Kenny Rootcf9111e2015-04-29 10:08:33 -07001717#if defined(OPENSSL_IS_BORINGSSL)
Kenny Roota6a38cd2015-04-28 16:44:36 -07001718 const void* /* argp */) {
Kenny Rootcf9111e2015-04-29 10:08:33 -07001719#else /* defined(OPENSSL_IS_BORINGSSL) */
1720 void* /* argp */) {
1721#endif /* defined(OPENSSL_IS_BORINGSSL) */
Kenny Rootf24ba062014-06-09 10:37:46 -07001722 jobject private_key = reinterpret_cast<jobject>(ptr);
1723 if (private_key == NULL) return;
1724
1725 CRYPTO_set_ex_data(ad, idx, NULL);
1726 JNIEnv* env = getJNIEnv();
1727 env->DeleteGlobalRef(private_key);
1728}
1729
1730int ExDataDup(CRYPTO_EX_DATA* /* to */,
1731 CRYPTO_EX_DATA* /* from */,
1732 void* /* from_d */,
1733 int /* idx */,
1734 long /* argl */,
Kenny Rootcf9111e2015-04-29 10:08:33 -07001735#if defined(OPENSSL_IS_BORINGSSL)
Kenny Roota6a38cd2015-04-28 16:44:36 -07001736 const void* /* argp */) {
Kenny Rootcf9111e2015-04-29 10:08:33 -07001737#else /* defined(OPENSSL_IS_BORINGSSL) */
1738 void* /* argp */) {
1739#endif /* defined(OPENSSL_IS_BORINGSSL) */
Kenny Rootf24ba062014-06-09 10:37:46 -07001740 // This callback shall never be called with the current OpenSSL
1741 // implementation (the library only ever duplicates EX_DATA items
1742 // for SSL and BIO objects). But provide this to catch regressions
1743 // in the future.
1744 // Return value is currently ignored by OpenSSL.
1745 return 0;
1746}
1747
1748class EcdsaExDataIndex {
1749 public:
1750 int ex_data_index() { return ex_data_index_; }
1751
1752 static EcdsaExDataIndex& Instance() {
1753 static EcdsaExDataIndex singleton;
1754 return singleton;
1755 }
1756
1757 private:
1758 EcdsaExDataIndex() {
1759 ex_data_index_ = ECDSA_get_ex_new_index(0, NULL, NULL, ExDataDup, ExDataFree);
1760 }
1761 EcdsaExDataIndex(EcdsaExDataIndex const&);
1762 ~EcdsaExDataIndex() {}
1763 EcdsaExDataIndex& operator=(EcdsaExDataIndex const&);
1764
1765 int ex_data_index_;
1766};
1767
1768// Returns the index of the custom EX_DATA used to store the JNI reference.
1769int EcdsaGetExDataIndex(void) {
1770 EcdsaExDataIndex& exData = EcdsaExDataIndex::Instance();
1771 return exData.ex_data_index();
1772}
1773
1774ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, int dgst_len, const BIGNUM* /* inv */,
1775 const BIGNUM* /* rp */, EC_KEY* eckey) {
1776 // Retrieve private key JNI reference.
1777 jobject private_key =
1778 reinterpret_cast<jobject>(ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
1779 if (!private_key) {
1780 ALOGE("Null JNI reference passed to EcdsaMethodDoSign!");
1781 return NULL;
1782 }
1783 JNIEnv* env = getJNIEnv();
1784 if (env == NULL) {
1785 return NULL;
1786 }
1787
1788 // Sign message with it through JNI.
1789 ScopedLocalRef<jbyteArray> signature(
1790 env, rawSignDigestWithPrivateKey(env, private_key, reinterpret_cast<const char*>(dgst),
1791 dgst_len));
1792 if (signature.get() == NULL) {
1793 ALOGE("Could not sign message in EcdsaMethodDoSign!");
1794 return NULL;
1795 }
1796
1797 ScopedByteArrayRO signatureBytes(env, signature.get());
1798 // Note: With ECDSA, the actual signature may be smaller than
1799 // ECDSA_size().
1800 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey));
1801 if (signatureBytes.size() > max_expected_size) {
Ian Rogers1b60d4f2014-06-11 12:41:41 -07001802 ALOGE("ECDSA Signature size mismatch, actual: %zd, expected <= %zd", signatureBytes.size(),
Kenny Rootf24ba062014-06-09 10:37:46 -07001803 max_expected_size);
1804 return NULL;
1805 }
1806
1807 // Convert signature to ECDSA_SIG object
1808 const unsigned char* sigbuf = reinterpret_cast<const unsigned char*>(signatureBytes.get());
1809 long siglen = static_cast<long>(signatureBytes.size());
1810 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
1811}
1812
1813int EcdsaMethodSignSetup(EC_KEY* /* eckey */,
1814 BN_CTX* /* ctx */,
1815 BIGNUM** /* kinv */,
1816 BIGNUM** /* r */,
1817 const unsigned char*,
1818 int) {
1819 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB);
1820 return -1;
1821}
1822
1823int EcdsaMethodDoVerify(const unsigned char* /* dgst */,
1824 int /* dgst_len */,
1825 const ECDSA_SIG* /* sig */,
1826 EC_KEY* /* eckey */) {
1827 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB);
1828 return -1;
1829}
1830
1831const ECDSA_METHOD android_ecdsa_method = {
1832 /* .name = */ "Android signing-only ECDSA method",
1833 /* .ecdsa_do_sign = */ EcdsaMethodDoSign,
1834 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup,
1835 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify,
1836 /* .flags = */ 0,
1837 /* .app_data = */ NULL,
1838};
1839
Adam Langleyde5225d2014-10-06 15:55:30 -07001840#else /* OPENSSL_IS_BORINGSSL */
1841
1842namespace {
1843
1844ENGINE *g_engine;
1845int g_rsa_exdata_index;
1846int g_ecdsa_exdata_index;
1847pthread_once_t g_engine_once = PTHREAD_ONCE_INIT;
1848
1849void init_engine_globals();
1850
1851void ensure_engine_globals() {
1852 pthread_once(&g_engine_once, init_engine_globals);
1853}
1854
Kenny Roote84805b2014-11-24 15:12:53 -08001855// KeyExData contains the data that is contained in the EX_DATA of the RSA
Adam Langleyde5225d2014-10-06 15:55:30 -07001856// and ECDSA objects that are created to wrap Android system keys.
1857struct KeyExData {
1858 // private_key contains a reference to a Java, private-key object.
1859 jobject private_key;
1860 // cached_size contains the "size" of the key. This is the size of the
Kenny Roote84805b2014-11-24 15:12:53 -08001861 // modulus (in bytes) for RSA, or the group order size for ECDSA. This
Adam Langleyde5225d2014-10-06 15:55:30 -07001862 // avoids calling into Java to calculate the size.
1863 size_t cached_size;
1864};
1865
1866// ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
1867// don't support this and it should never happen.
Adam Langleyca341142014-12-11 17:26:18 -08001868int ExDataDup(CRYPTO_EX_DATA* /* to */,
1869 const CRYPTO_EX_DATA* /* from */,
1870 void** /* from_d */,
1871 int /* index */,
1872 long /* argl */,
1873 void* /* argp */) {
Adam Langleyde5225d2014-10-06 15:55:30 -07001874 return 0;
1875}
1876
1877// ExDataFree is called when one of the RSA or EC_KEY objects is freed.
Adam Langleyca341142014-12-11 17:26:18 -08001878void ExDataFree(void* /* parent */,
Adam Langleyde5225d2014-10-06 15:55:30 -07001879 void* ptr,
Adam Langleyca341142014-12-11 17:26:18 -08001880 CRYPTO_EX_DATA* /* ad */,
1881 int /* index */,
1882 long /* argl */,
1883 void* /* argp */) {
Adam Langleyde5225d2014-10-06 15:55:30 -07001884 // Ensure the global JNI reference created with this wrapper is
1885 // properly destroyed with it.
1886 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
1887 if (ex_data != NULL) {
1888 JNIEnv* env = getJNIEnv();
1889 env->DeleteGlobalRef(ex_data->private_key);
1890 delete ex_data;
1891 }
1892}
1893
1894KeyExData* RsaGetExData(const RSA* rsa) {
1895 return reinterpret_cast<KeyExData*>(RSA_get_ex_data(rsa, g_rsa_exdata_index));
1896}
1897
1898size_t RsaMethodSize(const RSA *rsa) {
1899 const KeyExData *ex_data = RsaGetExData(rsa);
1900 return ex_data->cached_size;
1901}
1902
Adam Langleyca341142014-12-11 17:26:18 -08001903int RsaMethodEncrypt(RSA* /* rsa */,
1904 size_t* /* out_len */,
1905 uint8_t* /* out */,
1906 size_t /* max_out */,
1907 const uint8_t* /* in */,
1908 size_t /* in_len */,
1909 int /* padding */) {
Adam Langleyde5225d2014-10-06 15:55:30 -07001910 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
1911 return 0;
1912}
1913
1914int RsaMethodSignRaw(RSA* rsa,
1915 size_t* out_len,
1916 uint8_t* out,
1917 size_t max_out,
1918 const uint8_t* in,
1919 size_t in_len,
1920 int padding) {
1921 if (padding != RSA_PKCS1_PADDING) {
1922 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
1923 // by using javax.crypto.Cipher and picking either the
1924 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
1925 // appropriate. I believe support for both of these was added in
1926 // the same Android version as the "NONEwithRSA"
1927 // java.security.Signature algorithm, so the same version checks
1928 // for GetRsaLegacyKey should work.
1929 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
1930 return 0;
1931 }
1932
1933 // Retrieve private key JNI reference.
1934 const KeyExData *ex_data = RsaGetExData(rsa);
1935 if (!ex_data || !ex_data->private_key) {
1936 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
1937 return 0;
1938 }
1939
1940 JNIEnv* env = getJNIEnv();
1941 if (env == NULL) {
1942 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
1943 return 0;
1944 }
1945
Alex Klyubind1b44882015-06-10 13:02:22 -07001946 // For RSA keys, this function behaves as RSA_private_encrypt with
1947 // PKCS#1 padding.
1948 ScopedLocalRef<jbyteArray> signature(
1949 env, rawSignDigestWithPrivateKey(
1950 env, ex_data->private_key,
1951 reinterpret_cast<const char*>(in), in_len));
Adam Langleyde5225d2014-10-06 15:55:30 -07001952
Alex Klyubind1b44882015-06-10 13:02:22 -07001953 if (signature.get() == NULL) {
Adam Langleyde5225d2014-10-06 15:55:30 -07001954 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
1955 return 0;
1956 }
1957
Alex Klyubind1b44882015-06-10 13:02:22 -07001958 ScopedByteArrayRO result(env, signature.get());
Adam Langleyde5225d2014-10-06 15:55:30 -07001959
1960 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
1961 if (result.size() > expected_size) {
1962 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
1963 return 0;
1964 }
1965
1966 if (max_out < expected_size) {
1967 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
1968 return 0;
1969 }
1970
1971 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
1972 // should pad with leading 0s, but if it doesn't, pad the result.
1973 size_t zero_pad = expected_size - result.size();
1974 memset(out, 0, zero_pad);
1975 memcpy(out + zero_pad, &result[0], result.size());
1976 *out_len = expected_size;
1977
1978 return 1;
1979}
1980
Alex Klyubind1b44882015-06-10 13:02:22 -07001981int RsaMethodDecrypt(RSA* rsa,
1982 size_t* out_len,
1983 uint8_t* out,
1984 size_t max_out,
1985 const uint8_t* in,
1986 size_t in_len,
1987 int padding) {
1988 // Retrieve private key JNI reference.
1989 const KeyExData *ex_data = RsaGetExData(rsa);
1990 if (!ex_data || !ex_data->private_key) {
1991 OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_INTERNAL_ERROR);
1992 return 0;
1993 }
1994
1995 JNIEnv* env = getJNIEnv();
1996 if (env == NULL) {
1997 OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_INTERNAL_ERROR);
1998 return 0;
1999 }
2000
2001 // This function behaves as RSA_private_decrypt.
2002 ScopedLocalRef<jbyteArray> cleartext(
2003 env, rsaDecryptWithPrivateKey(
2004 env, ex_data->private_key, padding,
2005 reinterpret_cast<const char*>(in), in_len));
2006 if (cleartext.get() == NULL) {
2007 OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_INTERNAL_ERROR);
2008 return 0;
2009 }
2010
2011 ScopedByteArrayRO cleartextBytes(env, cleartext.get());
2012
2013 if (max_out < cleartextBytes.size()) {
2014 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_DATA_TOO_LARGE);
2015 return 0;
2016 }
2017
2018 // Copy result to OpenSSL-provided buffer.
2019 memcpy(out, cleartextBytes.get(), cleartextBytes.size());
2020 *out_len = cleartextBytes.size();
2021
2022 return 1;
Adam Langleyde5225d2014-10-06 15:55:30 -07002023}
2024
Adam Langleyca341142014-12-11 17:26:18 -08002025int RsaMethodVerifyRaw(RSA* /* rsa */,
2026 size_t* /* out_len */,
2027 uint8_t* /* out */,
2028 size_t /* max_out */,
2029 const uint8_t* /* in */,
2030 size_t /* in_len */,
2031 int /* padding */) {
Adam Langleyde5225d2014-10-06 15:55:30 -07002032 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
2033 return 0;
2034}
2035
2036const RSA_METHOD android_rsa_method = {
2037 {
2038 0 /* references */,
2039 1 /* is_static */
2040 } /* common */,
2041 NULL /* app_data */,
2042
2043 NULL /* init */,
2044 NULL /* finish */,
2045 RsaMethodSize,
2046 NULL /* sign */,
2047 NULL /* verify */,
2048 RsaMethodEncrypt,
2049 RsaMethodSignRaw,
2050 RsaMethodDecrypt,
2051 RsaMethodVerifyRaw,
2052 NULL /* mod_exp */,
2053 NULL /* bn_mod_exp */,
2054 NULL /* private_transform */,
2055 RSA_FLAG_OPAQUE,
2056 NULL /* keygen */,
Adam Langleyca341142014-12-11 17:26:18 -08002057 NULL /* supports_digest */,
Adam Langleyde5225d2014-10-06 15:55:30 -07002058};
2059
2060// Custom ECDSA_METHOD that uses the platform APIs.
2061// Note that for now, only signing through ECDSA_sign() is really supported.
2062// all other method pointers are either stubs returning errors, or no-ops.
2063
2064jobject EcKeyGetKey(const EC_KEY* ec_key) {
2065 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
2066 ec_key, g_ecdsa_exdata_index));
2067 return ex_data->private_key;
2068}
2069
2070size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
2071 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
2072 ec_key, g_ecdsa_exdata_index));
2073 return ex_data->cached_size;
2074}
2075
2076int EcdsaMethodSign(const uint8_t* digest,
2077 size_t digest_len,
2078 uint8_t* sig,
2079 unsigned int* sig_len,
2080 EC_KEY* ec_key) {
2081 // Retrieve private key JNI reference.
2082 jobject private_key = EcKeyGetKey(ec_key);
2083 if (!private_key) {
2084 ALOGE("Null JNI reference passed to EcdsaMethodSign!");
2085 return 0;
2086 }
2087
2088 JNIEnv* env = getJNIEnv();
2089 if (env == NULL) {
2090 return 0;
2091 }
2092
2093 // Sign message with it through JNI.
2094 ScopedLocalRef<jbyteArray> signature(
2095 env, rawSignDigestWithPrivateKey(env, private_key,
2096 reinterpret_cast<const char*>(digest),
2097 digest_len));
2098 if (signature.get() == NULL) {
2099 ALOGE("Could not sign message in EcdsaMethodDoSign!");
2100 return 0;
2101 }
2102
2103 ScopedByteArrayRO signatureBytes(env, signature.get());
2104 // Note: With ECDSA, the actual signature may be smaller than
2105 // ECDSA_size().
2106 size_t max_expected_size = ECDSA_size(ec_key);
2107 if (signatureBytes.size() > max_expected_size) {
2108 ALOGE("ECDSA Signature size mismatch, actual: %zd, expected <= %zd",
2109 signatureBytes.size(), max_expected_size);
2110 return 0;
2111 }
2112
2113 memcpy(sig, signatureBytes.get(), signatureBytes.size());
2114 *sig_len = signatureBytes.size();
2115 return 1;
2116}
2117
Adam Langleyca341142014-12-11 17:26:18 -08002118int EcdsaMethodVerify(const uint8_t* /* digest */,
2119 size_t /* digest_len */,
2120 const uint8_t* /* sig */,
2121 size_t /* sig_len */,
2122 EC_KEY* /* ec_key */) {
Adam Langleyde5225d2014-10-06 15:55:30 -07002123 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
2124 return 0;
2125}
2126
2127const ECDSA_METHOD android_ecdsa_method = {
2128 {
2129 0 /* references */,
2130 1 /* is_static */
2131 } /* common */,
2132 NULL /* app_data */,
2133
2134 NULL /* init */,
2135 NULL /* finish */,
2136 EcdsaMethodGroupOrderSize,
2137 EcdsaMethodSign,
2138 EcdsaMethodVerify,
2139 ECDSA_FLAG_OPAQUE,
2140};
2141
2142
2143void init_engine_globals() {
2144 g_rsa_exdata_index =
2145 RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
2146 ExDataDup, ExDataFree);
2147 g_ecdsa_exdata_index =
2148 EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */,
2149 NULL /* new_func */, ExDataDup, ExDataFree);
2150
2151 g_engine = ENGINE_new();
2152 ENGINE_set_RSA_method(g_engine, &android_rsa_method,
2153 sizeof(android_rsa_method));
2154 ENGINE_set_ECDSA_method(g_engine, &android_ecdsa_method,
2155 sizeof(android_ecdsa_method));
2156}
2157
2158} // anonymous namespace
2159#endif
2160
Kenny Root3e46e4e2014-05-23 13:35:10 -07002161#ifdef CONSCRYPT_UNBUNDLED
2162/*
2163 * This is a big hack; don't learn from this. Basically what happened is we do
2164 * not have an API way to insert ourselves into the AsynchronousCloseMonitor
2165 * that's compiled into the native libraries for libcore when we're unbundled.
2166 * So we try to look up the symbol from the main library to find it.
2167 */
2168typedef void (*acm_ctor_func)(void*, int);
2169typedef void (*acm_dtor_func)(void*);
2170static acm_ctor_func async_close_monitor_ctor = NULL;
2171static acm_dtor_func async_close_monitor_dtor = NULL;
2172
2173class CompatibilityCloseMonitor {
2174public:
2175 CompatibilityCloseMonitor(int fd) {
2176 if (async_close_monitor_ctor != NULL) {
2177 async_close_monitor_ctor(objBuffer, fd);
2178 }
2179 }
2180
2181 ~CompatibilityCloseMonitor() {
2182 if (async_close_monitor_dtor != NULL) {
2183 async_close_monitor_dtor(objBuffer);
2184 }
2185 }
2186private:
2187 char objBuffer[256];
2188#if 0
2189 static_assert(sizeof(objBuffer) > 2*sizeof(AsynchronousCloseMonitor),
2190 "CompatibilityCloseMonitor must be larger than the actual object");
2191#endif
2192};
2193
2194static void findAsynchronousCloseMonitorFuncs() {
2195 void *lib = dlopen("libjavacore.so", RTLD_NOW);
2196 if (lib != NULL) {
2197 async_close_monitor_ctor = (acm_ctor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorC1Ei");
2198 async_close_monitor_dtor = (acm_dtor_func) dlsym(lib, "_ZN24AsynchronousCloseMonitorD1Ev");
2199 }
2200}
2201#endif
2202
Kenny Root860d2702013-04-23 15:50:31 -07002203/**
Kenny Root923e3c52013-05-01 12:17:23 -07002204 * Copied from libnativehelper NetworkUtilites.cpp
2205 */
2206static bool setBlocking(int fd, bool blocking) {
2207 int flags = fcntl(fd, F_GETFL);
2208 if (flags == -1) {
2209 return false;
2210 }
2211
2212 if (!blocking) {
2213 flags |= O_NONBLOCK;
2214 } else {
2215 flags &= ~O_NONBLOCK;
2216 }
2217
2218 int rc = fcntl(fd, F_SETFL, flags);
2219 return (rc != -1);
2220}
2221
2222/**
Kenny Root860d2702013-04-23 15:50:31 -07002223 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
2224 * suppose there are not many other ways to do this on a Linux system (modulo
2225 * isomorphism).
2226 */
2227#define MUTEX_TYPE pthread_mutex_t
2228#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
2229#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
2230#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
2231#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
2232#define THREAD_ID pthread_self()
2233#define THROW_SSLEXCEPTION (-2)
2234#define THROW_SOCKETTIMEOUTEXCEPTION (-3)
2235#define THROWN_EXCEPTION (-4)
2236
2237static MUTEX_TYPE* mutex_buf = NULL;
2238
2239static void locking_function(int mode, int n, const char*, int) {
2240 if (mode & CRYPTO_LOCK) {
2241 MUTEX_LOCK(mutex_buf[n]);
2242 } else {
2243 MUTEX_UNLOCK(mutex_buf[n]);
2244 }
2245}
2246
Adam Langleyde5225d2014-10-06 15:55:30 -07002247static void threadid_callback(CRYPTO_THREADID *threadid) {
Ian Rogersa3a2eba2014-11-19 20:48:02 -08002248#if defined(__APPLE__)
Kenny Root0beef7d2014-11-20 09:01:08 -08002249 uint64_t owner;
2250 int rc = pthread_threadid_np(NULL, &owner); // Requires Mac OS 10.6
2251 if (rc == 0) {
2252 CRYPTO_THREADID_set_numeric(threadid, owner);
2253 } else {
2254 ALOGE("Error calling pthread_threadid_np");
2255 }
Adam Langleyde5225d2014-10-06 15:55:30 -07002256#else
Kenny Root0beef7d2014-11-20 09:01:08 -08002257 // bionic exposes gettid(), but glibc doesn't
2258 CRYPTO_THREADID_set_numeric(threadid, syscall(__NR_gettid));
Adam Langleyde5225d2014-10-06 15:55:30 -07002259#endif
Kenny Root860d2702013-04-23 15:50:31 -07002260}
2261
2262int THREAD_setup(void) {
2263 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
2264 if (!mutex_buf) {
2265 return 0;
2266 }
2267
2268 for (int i = 0; i < CRYPTO_num_locks(); ++i) {
2269 MUTEX_SETUP(mutex_buf[i]);
2270 }
2271
Adam Langleyde5225d2014-10-06 15:55:30 -07002272 CRYPTO_THREADID_set_callback(threadid_callback);
Kenny Root860d2702013-04-23 15:50:31 -07002273 CRYPTO_set_locking_callback(locking_function);
2274
2275 return 1;
2276}
2277
2278int THREAD_cleanup(void) {
2279 if (!mutex_buf) {
2280 return 0;
2281 }
2282
Adam Langleyde5225d2014-10-06 15:55:30 -07002283 CRYPTO_THREADID_set_callback(NULL);
Kenny Root860d2702013-04-23 15:50:31 -07002284 CRYPTO_set_locking_callback(NULL);
2285
2286 for (int i = 0; i < CRYPTO_num_locks( ); i++) {
2287 MUTEX_CLEANUP(mutex_buf[i]);
2288 }
2289
2290 free(mutex_buf);
2291 mutex_buf = NULL;
2292
2293 return 1;
2294}
2295
2296/**
2297 * Initialization phase for every OpenSSL job: Loads the Error strings, the
2298 * crypto algorithms and reset the OpenSSL library
2299 */
Kenny Root4d7e1f92015-04-22 09:00:29 -07002300static jboolean NativeCrypto_clinit(JNIEnv*, jclass)
Kenny Root860d2702013-04-23 15:50:31 -07002301{
2302 SSL_load_error_strings();
2303 ERR_load_crypto_strings();
2304 SSL_library_init();
2305 OpenSSL_add_all_algorithms();
2306 THREAD_setup();
Kenny Root4d7e1f92015-04-22 09:00:29 -07002307#if !defined(OPENSSL_IS_BORINGSSL)
2308 return JNI_FALSE;
2309#else
2310 return JNI_TRUE;
2311#endif
Kenny Root860d2702013-04-23 15:50:31 -07002312}
2313
2314static void NativeCrypto_ENGINE_load_dynamic(JNIEnv*, jclass) {
Adam Langleyde5225d2014-10-06 15:55:30 -07002315#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07002316 JNI_TRACE("ENGINE_load_dynamic()");
2317
2318 ENGINE_load_dynamic();
Adam Langleyde5225d2014-10-06 15:55:30 -07002319#endif
Kenny Root860d2702013-04-23 15:50:31 -07002320}
2321
Adam Langleyde5225d2014-10-06 15:55:30 -07002322#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08002323static jlong NativeCrypto_ENGINE_by_id(JNIEnv* env, jclass, jstring idJava) {
Kenny Root860d2702013-04-23 15:50:31 -07002324 JNI_TRACE("ENGINE_by_id(%p)", idJava);
2325
2326 ScopedUtfChars id(env, idJava);
2327 if (id.c_str() == NULL) {
2328 JNI_TRACE("ENGINE_by_id(%p) => id == null", idJava);
2329 return 0;
2330 }
2331 JNI_TRACE("ENGINE_by_id(\"%s\")", id.c_str());
2332
2333 ENGINE* e = ENGINE_by_id(id.c_str());
2334 if (e == NULL) {
2335 freeOpenSslErrorState();
2336 }
2337
2338 JNI_TRACE("ENGINE_by_id(\"%s\") => %p", id.c_str(), e);
2339 return reinterpret_cast<uintptr_t>(e);
2340}
Adam Langleyca341142014-12-11 17:26:18 -08002341#else
2342static jlong NativeCrypto_ENGINE_by_id(JNIEnv*, jclass, jstring) {
2343 return 0;
2344}
2345#endif
Kenny Root860d2702013-04-23 15:50:31 -07002346
Adam Langleyde5225d2014-10-06 15:55:30 -07002347#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08002348static jint NativeCrypto_ENGINE_add(JNIEnv* env, jclass, jlong engineRef) {
Kenny Root860d2702013-04-23 15:50:31 -07002349 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2350 JNI_TRACE("ENGINE_add(%p)", e);
2351
2352 if (e == NULL) {
2353 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
2354 return 0;
2355 }
2356
2357 int ret = ENGINE_add(e);
2358
2359 /*
2360 * We tolerate errors, because the most likely error is that
2361 * the ENGINE is already in the list.
2362 */
2363 freeOpenSslErrorState();
2364
2365 JNI_TRACE("ENGINE_add(%p) => %d", e, ret);
2366 return ret;
2367}
Adam Langleyca341142014-12-11 17:26:18 -08002368#else
2369static jint NativeCrypto_ENGINE_add(JNIEnv*, jclass, jlong) {
2370 return 0;
2371}
2372#endif
Kenny Root860d2702013-04-23 15:50:31 -07002373
Adam Langleyde5225d2014-10-06 15:55:30 -07002374#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08002375static jint NativeCrypto_ENGINE_init(JNIEnv* env, jclass, jlong engineRef) {
Kenny Root860d2702013-04-23 15:50:31 -07002376 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2377 JNI_TRACE("ENGINE_init(%p)", e);
2378
2379 if (e == NULL) {
2380 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
2381 return 0;
2382 }
2383
2384 int ret = ENGINE_init(e);
2385 JNI_TRACE("ENGINE_init(%p) => %d", e, ret);
2386 return ret;
2387}
Adam Langleyca341142014-12-11 17:26:18 -08002388#else
2389static jint NativeCrypto_ENGINE_init(JNIEnv*, jclass, jlong) {
2390 return 0;
2391}
2392#endif
Kenny Root860d2702013-04-23 15:50:31 -07002393
Adam Langleyde5225d2014-10-06 15:55:30 -07002394#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08002395static jint NativeCrypto_ENGINE_finish(JNIEnv* env, jclass, jlong engineRef) {
Kenny Root860d2702013-04-23 15:50:31 -07002396 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2397 JNI_TRACE("ENGINE_finish(%p)", e);
2398
2399 if (e == NULL) {
2400 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
2401 return 0;
2402 }
2403
2404 int ret = ENGINE_finish(e);
2405 JNI_TRACE("ENGINE_finish(%p) => %d", e, ret);
2406 return ret;
2407}
Adam Langleyca341142014-12-11 17:26:18 -08002408#else
2409static jint NativeCrypto_ENGINE_finish(JNIEnv*, jclass, jlong) {
2410 return 0;
2411}
2412#endif
Kenny Root860d2702013-04-23 15:50:31 -07002413
Adam Langleyde5225d2014-10-06 15:55:30 -07002414#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08002415static jint NativeCrypto_ENGINE_free(JNIEnv* env, jclass, jlong engineRef) {
Kenny Root860d2702013-04-23 15:50:31 -07002416 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2417 JNI_TRACE("ENGINE_free(%p)", e);
2418
2419 if (e == NULL) {
2420 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0");
2421 return 0;
2422 }
2423
2424 int ret = ENGINE_free(e);
2425 JNI_TRACE("ENGINE_free(%p) => %d", e, ret);
2426 return ret;
2427}
Adam Langleyca341142014-12-11 17:26:18 -08002428#else
2429static jint NativeCrypto_ENGINE_free(JNIEnv*, jclass, jlong) {
2430 return 0;
2431}
2432#endif
Kenny Root860d2702013-04-23 15:50:31 -07002433
Adam Langleyde5225d2014-10-06 15:55:30 -07002434#if defined(OPENSSL_IS_BORINGSSL)
2435extern "C" {
2436/* EVP_PKEY_from_keystore is from system/security/keystore-engine. */
2437extern EVP_PKEY* EVP_PKEY_from_keystore(const char *key_id);
2438}
2439#endif
2440
Kenny Root860d2702013-04-23 15:50:31 -07002441static jlong NativeCrypto_ENGINE_load_private_key(JNIEnv* env, jclass, jlong engineRef,
2442 jstring idJava) {
Kenny Root860d2702013-04-23 15:50:31 -07002443 ScopedUtfChars id(env, idJava);
2444 if (id.c_str() == NULL) {
2445 jniThrowException(env, "java/lang/IllegalArgumentException", "id == NULL");
2446 return 0;
2447 }
2448
Adam Langleyde5225d2014-10-06 15:55:30 -07002449#if !defined(OPENSSL_IS_BORINGSSL)
2450 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2451 JNI_TRACE("ENGINE_load_private_key(%p, %p)", e, idJava);
2452
Kenny Root860d2702013-04-23 15:50:31 -07002453 Unique_EVP_PKEY pkey(ENGINE_load_private_key(e, id.c_str(), NULL, NULL));
2454 if (pkey.get() == NULL) {
Kenny Rootd12c5672015-04-29 10:32:45 -07002455 throwExceptionIfNecessary(env, "ENGINE_load_private_key", throwInvalidKeyException);
Kenny Root860d2702013-04-23 15:50:31 -07002456 return 0;
2457 }
2458
2459 JNI_TRACE("ENGINE_load_private_key(%p, %p) => %p", e, idJava, pkey.get());
2460 return reinterpret_cast<uintptr_t>(pkey.release());
Adam Langleyde5225d2014-10-06 15:55:30 -07002461#else
Adam Langleyca341142014-12-11 17:26:18 -08002462 UNUSED_ARGUMENT(engineRef);
Adam Langleyde5225d2014-10-06 15:55:30 -07002463#if defined(NO_KEYSTORE_ENGINE)
2464 jniThrowRuntimeException(env, "No keystore ENGINE support compiled in");
2465 return 0;
2466#else
2467 Unique_EVP_PKEY pkey(EVP_PKEY_from_keystore(id.c_str()));
2468 if (pkey.get() == NULL) {
Kenny Rootd12c5672015-04-29 10:32:45 -07002469 throwExceptionIfNecessary(env, "ENGINE_load_private_key", throwInvalidKeyException);
Adam Langleyde5225d2014-10-06 15:55:30 -07002470 return 0;
2471 }
2472 return reinterpret_cast<uintptr_t>(pkey.release());
2473#endif
2474#endif
Kenny Root860d2702013-04-23 15:50:31 -07002475}
2476
Adam Langleyca341142014-12-11 17:26:18 -08002477#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07002478static jstring NativeCrypto_ENGINE_get_id(JNIEnv* env, jclass, jlong engineRef)
2479{
2480 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2481 JNI_TRACE("ENGINE_get_id(%p)", e);
2482
2483 if (e == NULL) {
2484 jniThrowNullPointerException(env, "engine == null");
2485 JNI_TRACE("ENGINE_get_id(%p) => engine == null", e);
2486 return NULL;
2487 }
2488
2489 const char *id = ENGINE_get_id(e);
2490 ScopedLocalRef<jstring> idJava(env, env->NewStringUTF(id));
2491
2492 JNI_TRACE("ENGINE_get_id(%p) => \"%s\"", e, id);
2493 return idJava.release();
Adam Langleyca341142014-12-11 17:26:18 -08002494}
Adam Langleyde5225d2014-10-06 15:55:30 -07002495#else
Adam Langleyca341142014-12-11 17:26:18 -08002496static jstring NativeCrypto_ENGINE_get_id(JNIEnv* env, jclass, jlong)
2497{
Adam Langleyde5225d2014-10-06 15:55:30 -07002498 ScopedLocalRef<jstring> idJava(env, env->NewStringUTF("keystore"));
2499 return idJava.release();
Kenny Root860d2702013-04-23 15:50:31 -07002500}
Adam Langleyca341142014-12-11 17:26:18 -08002501#endif
Kenny Root860d2702013-04-23 15:50:31 -07002502
Adam Langleyca341142014-12-11 17:26:18 -08002503#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07002504static jint NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv* env, jclass, jlong engineRef,
2505 jstring cmdJava, jstring argJava, jint cmd_optional)
2506{
2507 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef));
2508 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d)", e, cmdJava, argJava, cmd_optional);
2509
2510 if (e == NULL) {
2511 jniThrowNullPointerException(env, "engine == null");
2512 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d) => engine == null", e, cmdJava, argJava,
2513 cmd_optional);
2514 return 0;
2515 }
2516
2517 ScopedUtfChars cmdChars(env, cmdJava);
2518 if (cmdChars.c_str() == NULL) {
2519 return 0;
2520 }
2521
2522 UniquePtr<ScopedUtfChars> arg;
2523 const char* arg_c_str = NULL;
2524 if (argJava != NULL) {
2525 arg.reset(new ScopedUtfChars(env, argJava));
2526 arg_c_str = arg->c_str();
2527 if (arg_c_str == NULL) {
2528 return 0;
2529 }
2530 }
2531 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d)", e, cmdChars.c_str(), arg_c_str,
2532 cmd_optional);
2533
2534 int ret = ENGINE_ctrl_cmd_string(e, cmdChars.c_str(), arg_c_str, cmd_optional);
2535 if (ret != 1) {
2536 throwExceptionIfNecessary(env, "ENGINE_ctrl_cmd_string");
2537 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => threw error", e,
2538 cmdChars.c_str(), arg_c_str, cmd_optional);
2539 return 0;
2540 }
2541
2542 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => %d", e, cmdChars.c_str(),
2543 arg_c_str, cmd_optional, ret);
2544 return ret;
2545}
Adam Langleyca341142014-12-11 17:26:18 -08002546#else
2547static jint NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv*, jclass, jlong, jstring, jstring, jint)
2548{
2549 return 0;
2550}
2551#endif
Kenny Root860d2702013-04-23 15:50:31 -07002552
Kenny Root7b27ca72014-05-08 14:27:23 -07002553static jlong NativeCrypto_EVP_PKEY_new_DH(JNIEnv* env, jclass,
2554 jbyteArray p, jbyteArray g,
2555 jbyteArray pub_key, jbyteArray priv_key) {
2556 JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p)",
2557 p, g, pub_key, priv_key);
2558
2559 Unique_DH dh(DH_new());
2560 if (dh.get() == NULL) {
2561 jniThrowRuntimeException(env, "DH_new failed");
2562 return 0;
2563 }
2564
2565 if (!arrayToBignum(env, p, &dh->p)) {
2566 return 0;
2567 }
2568
2569 if (!arrayToBignum(env, g, &dh->g)) {
2570 return 0;
2571 }
2572
2573 if (pub_key != NULL && !arrayToBignum(env, pub_key, &dh->pub_key)) {
2574 return 0;
2575 }
2576
2577 if (priv_key != NULL && !arrayToBignum(env, priv_key, &dh->priv_key)) {
2578 return 0;
2579 }
2580
2581 if (dh->p == NULL || dh->g == NULL
Kenny Root9b226f92014-07-10 14:50:48 -07002582 || (pub_key != NULL && dh->pub_key == NULL)
2583 || (priv_key != NULL && dh->priv_key == NULL)) {
Kenny Root7b27ca72014-05-08 14:27:23 -07002584 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
2585 return 0;
2586 }
2587
Kenny Roote526e752014-05-14 09:37:56 -07002588 /* The public key can be recovered if the private key is available. */
2589 if (dh->pub_key == NULL && dh->priv_key != NULL) {
2590 if (!DH_generate_key(dh.get())) {
2591 jniThrowRuntimeException(env, "EVP_PKEY_new_DH failed during pub_key generation");
2592 return 0;
2593 }
2594 }
2595
Kenny Root7b27ca72014-05-08 14:27:23 -07002596 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2597 if (pkey.get() == NULL) {
2598 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2599 return 0;
2600 }
2601 if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
2602 jniThrowRuntimeException(env, "EVP_PKEY_assign_DH failed");
2603 return 0;
2604 }
2605 OWNERSHIP_TRANSFERRED(dh);
2606 JNI_TRACE("EVP_PKEY_new_DH(p=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
2607 p, g, pub_key, priv_key, pkey.get());
2608 return reinterpret_cast<jlong>(pkey.release());
2609}
2610
Kenny Root860d2702013-04-23 15:50:31 -07002611/**
Kenny Root860d2702013-04-23 15:50:31 -07002612 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
2613 */
2614static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass,
2615 jbyteArray n, jbyteArray e, jbyteArray d,
2616 jbyteArray p, jbyteArray q,
2617 jbyteArray dmp1, jbyteArray dmq1,
2618 jbyteArray iqmp) {
2619 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p, dmp1=%p, dmq1=%p, iqmp=%p)",
2620 n, e, d, p, q, dmp1, dmq1, iqmp);
2621
2622 Unique_RSA rsa(RSA_new());
2623 if (rsa.get() == NULL) {
2624 jniThrowRuntimeException(env, "RSA_new failed");
2625 return 0;
2626 }
2627
2628 if (e == NULL && d == NULL) {
2629 jniThrowException(env, "java/lang/IllegalArgumentException", "e == NULL && d == NULL");
2630 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == NULL && d == NULL");
2631 return 0;
2632 }
2633
2634 if (!arrayToBignum(env, n, &rsa->n)) {
2635 return 0;
2636 }
2637
2638 if (e != NULL && !arrayToBignum(env, e, &rsa->e)) {
2639 return 0;
2640 }
2641
2642 if (d != NULL && !arrayToBignum(env, d, &rsa->d)) {
2643 return 0;
2644 }
2645
2646 if (p != NULL && !arrayToBignum(env, p, &rsa->p)) {
2647 return 0;
2648 }
2649
2650 if (q != NULL && !arrayToBignum(env, q, &rsa->q)) {
2651 return 0;
2652 }
2653
2654 if (dmp1 != NULL && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
2655 return 0;
2656 }
2657
2658 if (dmq1 != NULL && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
2659 return 0;
2660 }
2661
2662 if (iqmp != NULL && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
2663 return 0;
2664 }
2665
2666#ifdef WITH_JNI_TRACE
2667 if (p != NULL && q != NULL) {
2668 int check = RSA_check_key(rsa.get());
2669 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
2670 }
2671#endif
2672
2673 if (rsa->n == NULL || (rsa->e == NULL && rsa->d == NULL)) {
2674 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
2675 return 0;
2676 }
2677
2678 /*
2679 * If the private exponent is available, there is the potential to do signing
Kenny Rootfbb754f2015-05-06 12:51:13 -07002680 * operations. However, we can only do blinding if the public exponent is also
2681 * available. Disable blinding if the public exponent isn't available.
2682 *
2683 * TODO[kroot]: We should try to recover the public exponent by trying
2684 * some common ones such 3, 17, or 65537.
Kenny Root860d2702013-04-23 15:50:31 -07002685 */
Kenny Rootfbb754f2015-05-06 12:51:13 -07002686 if (rsa->d != NULL && rsa->e == NULL) {
2687 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
2688 rsa->flags |= RSA_FLAG_NO_BLINDING;
Kenny Root860d2702013-04-23 15:50:31 -07002689 }
2690
2691 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2692 if (pkey.get() == NULL) {
2693 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2694 return 0;
2695 }
2696 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
2697 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
2698 return 0;
2699 }
2700 OWNERSHIP_TRANSFERRED(rsa);
2701 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p",
2702 n, e, d, p, q, dmp1, dmq1, iqmp, pkey.get());
2703 return reinterpret_cast<uintptr_t>(pkey.release());
2704}
2705
Kenny Root7dc06b92014-11-26 10:07:51 -08002706static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jobject groupRef,
2707 jobject pubkeyRef, jbyteArray keyJavaBytes) {
Kenny Root8a77c202015-04-24 10:37:11 -07002708 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", groupRef, pubkeyRef, keyJavaBytes);
Kenny Root7dc06b92014-11-26 10:07:51 -08002709 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root8a77c202015-04-24 10:37:11 -07002710 if (group == NULL) {
2711 return 0;
2712 }
Kenny Root03b08982014-12-30 14:25:55 -08002713 const EC_POINT* pubkey = pubkeyRef == NULL ? NULL :
2714 fromContextObject<EC_POINT>(env, pubkeyRef);
Kenny Root8a77c202015-04-24 10:37:11 -07002715 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) <- ptr", group, pubkey, keyJavaBytes);
Kenny Root860d2702013-04-23 15:50:31 -07002716
2717 Unique_BIGNUM key(NULL);
2718 if (keyJavaBytes != NULL) {
Kenny Root1744cf22014-01-30 13:41:26 -08002719 BIGNUM* keyRef = NULL;
Kenny Root860d2702013-04-23 15:50:31 -07002720 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) {
2721 return 0;
2722 }
2723 key.reset(keyRef);
2724 }
2725
2726 Unique_EC_KEY eckey(EC_KEY_new());
2727 if (eckey.get() == NULL) {
2728 jniThrowRuntimeException(env, "EC_KEY_new failed");
2729 return 0;
2730 }
2731
2732 if (EC_KEY_set_group(eckey.get(), group) != 1) {
2733 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey,
2734 keyJavaBytes);
2735 throwExceptionIfNecessary(env, "EC_KEY_set_group");
2736 return 0;
2737 }
2738
2739 if (pubkey != NULL) {
2740 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) {
2741 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
2742 pubkey, keyJavaBytes);
2743 throwExceptionIfNecessary(env, "EC_KEY_set_public_key");
2744 return 0;
2745 }
2746 }
2747
2748 if (key.get() != NULL) {
2749 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) {
2750 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group,
2751 pubkey, keyJavaBytes);
2752 throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
2753 return 0;
2754 }
2755 if (pubkey == NULL) {
2756 Unique_EC_POINT calcPubkey(EC_POINT_new(group));
2757 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), NULL, NULL, NULL)) {
2758 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calulate public key", group,
2759 pubkey, keyJavaBytes);
2760 throwExceptionIfNecessary(env, "EC_KEY_set_private_key");
2761 return 0;
2762 }
2763 EC_KEY_set_public_key(eckey.get(), calcPubkey.get());
2764 }
2765 }
2766
2767 if (!EC_KEY_check_key(eckey.get())) {
2768 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey, keyJavaBytes);
2769 throwExceptionIfNecessary(env, "EC_KEY_check_key");
2770 return 0;
2771 }
2772
2773 Unique_EVP_PKEY pkey(EVP_PKEY_new());
2774 if (pkey.get() == NULL) {
2775 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
2776 throwExceptionIfNecessary(env, "EVP_PKEY_new failed");
2777 return 0;
2778 }
2779 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
2780 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes);
2781 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
2782 return 0;
2783 }
2784 OWNERSHIP_TRANSFERRED(eckey);
2785
2786 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get());
2787 return reinterpret_cast<uintptr_t>(pkey.release());
2788}
2789
2790static jlong NativeCrypto_EVP_PKEY_new_mac_key(JNIEnv* env, jclass, jint pkeyType,
2791 jbyteArray keyJavaBytes)
2792{
2793 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p)", pkeyType, keyJavaBytes);
2794
2795 ScopedByteArrayRO key(env, keyJavaBytes);
2796 if (key.get() == NULL) {
2797 return 0;
2798 }
2799
2800 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(key.get());
2801 Unique_EVP_PKEY pkey(EVP_PKEY_new_mac_key(pkeyType, (ENGINE *) NULL, tmp, key.size()));
2802 if (pkey.get() == NULL) {
2803 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => threw error", pkeyType, keyJavaBytes);
2804 throwExceptionIfNecessary(env, "ENGINE_load_private_key");
2805 return 0;
2806 }
2807
2808 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => %p", pkeyType, keyJavaBytes, pkey.get());
2809 return reinterpret_cast<uintptr_t>(pkey.release());
2810}
2811
Kenny Root37e58bb2014-11-25 14:29:25 -08002812static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jobject pkeyRef) {
2813 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002814 JNI_TRACE("EVP_PKEY_type(%p)", pkey);
2815
2816 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07002817 return -1;
2818 }
2819
2820 int result = EVP_PKEY_type(pkey->type);
2821 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result);
2822 return result;
2823}
2824
2825/**
2826 * private static native int EVP_PKEY_size(int pkey);
2827 */
Kenny Root37e58bb2014-11-25 14:29:25 -08002828static int NativeCrypto_EVP_PKEY_size(JNIEnv* env, jclass, jobject pkeyRef) {
2829 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002830 JNI_TRACE("EVP_PKEY_size(%p)", pkey);
2831
2832 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07002833 return -1;
2834 }
2835
2836 int result = EVP_PKEY_size(pkey);
2837 JNI_TRACE("EVP_PKEY_size(%p) => %d", pkey, result);
2838 return result;
2839}
2840
Kenny Root37e58bb2014-11-25 14:29:25 -08002841static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jobject pkeyRef) {
2842 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002843 JNI_TRACE("EVP_PKEY_print_public(%p)", pkey);
2844
2845 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07002846 return NULL;
2847 }
2848
2849 Unique_BIO buffer(BIO_new(BIO_s_mem()));
2850 if (buffer.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07002851 jniThrowOutOfMemory(env, "Unable to allocate BIO");
Kenny Root860d2702013-04-23 15:50:31 -07002852 return NULL;
2853 }
2854
2855 if (EVP_PKEY_print_public(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
2856 throwExceptionIfNecessary(env, "EVP_PKEY_print_public");
2857 return NULL;
2858 }
2859 // Null terminate this
2860 BIO_write(buffer.get(), "\0", 1);
2861
2862 char *tmp;
2863 BIO_get_mem_data(buffer.get(), &tmp);
2864 jstring description = env->NewStringUTF(tmp);
2865
2866 JNI_TRACE("EVP_PKEY_print_public(%p) => \"%s\"", pkey, tmp);
2867 return description;
2868}
2869
Kenny Root37e58bb2014-11-25 14:29:25 -08002870static jstring NativeCrypto_EVP_PKEY_print_private(JNIEnv* env, jclass, jobject pkeyRef) {
2871 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002872 JNI_TRACE("EVP_PKEY_print_private(%p)", pkey);
2873
2874 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07002875 return NULL;
2876 }
2877
2878 Unique_BIO buffer(BIO_new(BIO_s_mem()));
2879 if (buffer.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07002880 jniThrowOutOfMemory(env, "Unable to allocate BIO");
Kenny Root860d2702013-04-23 15:50:31 -07002881 return NULL;
2882 }
2883
2884 if (EVP_PKEY_print_private(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) {
2885 throwExceptionIfNecessary(env, "EVP_PKEY_print_private");
2886 return NULL;
2887 }
2888 // Null terminate this
2889 BIO_write(buffer.get(), "\0", 1);
2890
2891 char *tmp;
2892 BIO_get_mem_data(buffer.get(), &tmp);
2893 jstring description = env->NewStringUTF(tmp);
2894
2895 JNI_TRACE("EVP_PKEY_print_private(%p) => \"%s\"", pkey, tmp);
2896 return description;
2897}
2898
2899static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, jlong pkeyRef) {
2900 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
2901 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
2902
2903 if (pkey != NULL) {
2904 EVP_PKEY_free(pkey);
2905 }
2906}
2907
Kenny Root37e58bb2014-11-25 14:29:25 -08002908static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jobject pkey1Ref, jobject pkey2Ref) {
Kenny Root8a77c202015-04-24 10:37:11 -07002909 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1Ref, pkey2Ref);
Kenny Root37e58bb2014-11-25 14:29:25 -08002910 EVP_PKEY* pkey1 = fromContextObject<EVP_PKEY>(env, pkey1Ref);
Kenny Root860d2702013-04-23 15:50:31 -07002911 if (pkey1 == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07002912 JNI_TRACE("EVP_PKEY_cmp => pkey1 == NULL");
2913 return 0;
Kenny Root860d2702013-04-23 15:50:31 -07002914 }
Kenny Root8a77c202015-04-24 10:37:11 -07002915 EVP_PKEY* pkey2 = fromContextObject<EVP_PKEY>(env, pkey2Ref);
2916 if (pkey2 == NULL) {
2917 JNI_TRACE("EVP_PKEY_cmp => pkey2 == NULL");
2918 return 0;
2919 }
2920 JNI_TRACE("EVP_PKEY_cmp(%p, %p) <- ptr", pkey1, pkey2);
Kenny Root860d2702013-04-23 15:50:31 -07002921
2922 int result = EVP_PKEY_cmp(pkey1, pkey2);
2923 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result);
2924 return result;
2925}
2926
2927/*
2928 * static native byte[] i2d_PKCS8_PRIV_KEY_INFO(int, byte[])
2929 */
Kenny Root37e58bb2014-11-25 14:29:25 -08002930static jbyteArray NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jobject pkeyRef) {
2931 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002932 JNI_TRACE("i2d_PKCS8_PRIV_KEY_INFO(%p)", pkey);
2933
2934 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07002935 return NULL;
2936 }
2937
2938 Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey));
2939 if (pkcs8.get() == NULL) {
2940 throwExceptionIfNecessary(env, "NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO");
2941 JNI_TRACE("key=%p i2d_PKCS8_PRIV_KEY_INFO => error from key to PKCS8", pkey);
2942 return NULL;
2943 }
2944
Adam Langleyde5225d2014-10-06 15:55:30 -07002945 return ASN1ToByteArray<PKCS8_PRIV_KEY_INFO>(env, pkcs8.get(), i2d_PKCS8_PRIV_KEY_INFO);
Kenny Root860d2702013-04-23 15:50:31 -07002946}
2947
2948/*
2949 * static native int d2i_PKCS8_PRIV_KEY_INFO(byte[])
2950 */
2951static jlong NativeCrypto_d2i_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jbyteArray keyJavaBytes) {
2952 JNI_TRACE("d2i_PKCS8_PRIV_KEY_INFO(%p)", keyJavaBytes);
2953
2954 ScopedByteArrayRO bytes(env, keyJavaBytes);
2955 if (bytes.get() == NULL) {
2956 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => threw exception", keyJavaBytes);
2957 return 0;
2958 }
2959
2960 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
2961 Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, bytes.size()));
2962 if (pkcs8.get() == NULL) {
2963 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
2964 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from DER to PKCS8", keyJavaBytes);
2965 return 0;
2966 }
2967
2968 Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
2969 if (pkey.get() == NULL) {
2970 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO");
2971 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from PKCS8 to key", keyJavaBytes);
2972 return 0;
2973 }
2974
2975 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => %p", keyJavaBytes, pkey.get());
2976 return reinterpret_cast<uintptr_t>(pkey.release());
2977}
2978
2979/*
2980 * static native byte[] i2d_PUBKEY(int)
2981 */
Kenny Root37e58bb2014-11-25 14:29:25 -08002982static jbyteArray NativeCrypto_i2d_PUBKEY(JNIEnv* env, jclass, jobject pkeyRef) {
2983 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07002984 JNI_TRACE("i2d_PUBKEY(%p)", pkey);
Kenny Root8a77c202015-04-24 10:37:11 -07002985 if (pkey == NULL) {
2986 return NULL;
2987 }
Adam Langleyde5225d2014-10-06 15:55:30 -07002988 return ASN1ToByteArray<EVP_PKEY>(env, pkey, reinterpret_cast<int (*) (EVP_PKEY*, uint8_t **)>(i2d_PUBKEY));
Kenny Root860d2702013-04-23 15:50:31 -07002989}
2990
2991/*
2992 * static native int d2i_PUBKEY(byte[])
2993 */
2994static jlong NativeCrypto_d2i_PUBKEY(JNIEnv* env, jclass, jbyteArray javaBytes) {
2995 JNI_TRACE("d2i_PUBKEY(%p)", javaBytes);
2996
2997 ScopedByteArrayRO bytes(env, javaBytes);
2998 if (bytes.get() == NULL) {
2999 JNI_TRACE("d2i_PUBKEY(%p) => threw error", javaBytes);
3000 return 0;
3001 }
3002
3003 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get());
3004 Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, bytes.size()));
3005 if (pkey.get() == NULL) {
3006 JNI_TRACE("bytes=%p d2i_PUBKEY => threw exception", javaBytes);
3007 throwExceptionIfNecessary(env, "d2i_PUBKEY");
3008 return 0;
3009 }
3010
3011 return reinterpret_cast<uintptr_t>(pkey.release());
3012}
3013
Kenny Rootf24ba062014-06-09 10:37:46 -07003014static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
3015 jbyteArray modulusBytes) {
Kenny Root977f0872014-08-04 12:15:04 -07003016 JNI_TRACE("getRSAPrivateKeyWrapper(%p, %p)", javaKey, modulusBytes);
Kenny Rootf24ba062014-06-09 10:37:46 -07003017
Adam Langleyde5225d2014-10-06 15:55:30 -07003018#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Rootf24ba062014-06-09 10:37:46 -07003019 Unique_RSA rsa(RSA_new());
3020 if (rsa.get() == NULL) {
3021 jniThrowOutOfMemory(env, "Unable to allocate RSA key");
3022 return 0;
3023 }
3024
3025 RSA_set_method(rsa.get(), &android_rsa_method);
3026
3027 if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
3028 return 0;
3029 }
3030
3031 RSA_set_app_data(rsa.get(), env->NewGlobalRef(javaKey));
Adam Langleyde5225d2014-10-06 15:55:30 -07003032#else
3033 size_t cached_size;
3034 if (!arrayToBignumSize(env, modulusBytes, &cached_size)) {
3035 JNI_TRACE("getRSAPrivateKeyWrapper failed");
3036 return 0;
3037 }
3038
3039 ensure_engine_globals();
3040
3041 Unique_RSA rsa(RSA_new_method(g_engine));
3042 if (rsa.get() == NULL) {
3043 jniThrowOutOfMemory(env, "Unable to allocate RSA key");
3044 return 0;
3045 }
3046
3047 KeyExData* ex_data = new KeyExData;
3048 ex_data->private_key = env->NewGlobalRef(javaKey);
3049 ex_data->cached_size = cached_size;
3050 RSA_set_ex_data(rsa.get(), g_rsa_exdata_index, ex_data);
3051#endif
Kenny Rootf24ba062014-06-09 10:37:46 -07003052
3053 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3054 if (pkey.get() == NULL) {
3055 JNI_TRACE("getRSAPrivateKeyWrapper failed");
3056 jniThrowRuntimeException(env, "NativeCrypto_getRSAPrivateKeyWrapper failed");
3057 freeOpenSslErrorState();
3058 return 0;
3059 }
3060
3061 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
3062 jniThrowRuntimeException(env, "getRSAPrivateKeyWrapper failed");
3063 return 0;
3064 }
3065 OWNERSHIP_TRANSFERRED(rsa);
3066 return reinterpret_cast<uintptr_t>(pkey.release());
3067}
3068
Kenny Root7dc06b92014-11-26 10:07:51 -08003069static jlong NativeCrypto_getECPrivateKeyWrapper(JNIEnv* env, jclass, jobject javaKey,
3070 jobject groupRef) {
3071 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root30550a82014-08-12 15:13:33 -07003072 JNI_TRACE("getECPrivateKeyWrapper(%p, %p)", javaKey, group);
Kenny Root8a77c202015-04-24 10:37:11 -07003073 if (group == NULL) {
3074 return 0;
3075 }
Kenny Rootf24ba062014-06-09 10:37:46 -07003076
Adam Langleyde5225d2014-10-06 15:55:30 -07003077#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Rootf24ba062014-06-09 10:37:46 -07003078 Unique_EC_KEY ecKey(EC_KEY_new());
3079 if (ecKey.get() == NULL) {
3080 jniThrowOutOfMemory(env, "Unable to allocate EC key");
3081 return 0;
3082 }
3083
Kenny Rootf24ba062014-06-09 10:37:46 -07003084 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
3085
3086 if (group == NULL) {
3087 JNI_TRACE("EC_GROUP_get_curve_name => group == NULL");
3088 jniThrowNullPointerException(env, "group == NULL");
3089 return 0;
3090 }
3091
3092 EC_KEY_set_group(ecKey.get(), group);
3093
3094 ECDSA_set_method(ecKey.get(), &android_ecdsa_method);
3095 ECDSA_set_ex_data(ecKey.get(), EcdsaGetExDataIndex(), env->NewGlobalRef(javaKey));
Adam Langleyde5225d2014-10-06 15:55:30 -07003096#else
3097 ensure_engine_globals();
3098
3099 Unique_EC_KEY ecKey(EC_KEY_new_method(g_engine));
3100 if (ecKey.get() == NULL) {
3101 jniThrowOutOfMemory(env, "Unable to allocate EC key");
3102 return 0;
3103 }
3104
3105 KeyExData* ex_data = new KeyExData;
3106 ex_data->private_key = env->NewGlobalRef(javaKey);
3107
Adam Langley9bca53c2015-06-10 13:25:47 -07003108 if (!EC_KEY_set_ex_data(ecKey.get(), g_ecdsa_exdata_index, ex_data)) {
3109 env->DeleteGlobalRef(ex_data->private_key);
3110 delete ex_data;
3111 jniThrowRuntimeException(env, "EC_KEY_set_ex_data");
3112 return 0;
3113 }
3114
Adam Langleyde5225d2014-10-06 15:55:30 -07003115 BIGNUM order;
3116 BN_init(&order);
3117 if (!EC_GROUP_get_order(group, &order, NULL)) {
3118 BN_free(&order);
3119 jniThrowRuntimeException(env, "EC_GROUP_get_order failed");
3120 return 0;
3121 }
3122 ex_data->cached_size = BN_num_bytes(&order);
3123 BN_free(&order);
3124#endif
Kenny Rootf24ba062014-06-09 10:37:46 -07003125
3126 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3127 if (pkey.get() == NULL) {
Adam Langleyde5225d2014-10-06 15:55:30 -07003128 JNI_TRACE("getECPrivateKeyWrapper failed");
3129 jniThrowRuntimeException(env, "NativeCrypto_getECPrivateKeyWrapper failed");
Kenny Rootf24ba062014-06-09 10:37:46 -07003130 freeOpenSslErrorState();
3131 return 0;
3132 }
3133
3134 if (EVP_PKEY_assign_EC_KEY(pkey.get(), ecKey.get()) != 1) {
3135 jniThrowRuntimeException(env, "getECPrivateKeyWrapper failed");
3136 return 0;
3137 }
3138 OWNERSHIP_TRANSFERRED(ecKey);
3139 return reinterpret_cast<uintptr_t>(pkey.release());
3140}
3141
Kenny Root860d2702013-04-23 15:50:31 -07003142/*
3143 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent);
3144 */
3145static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits,
3146 jbyteArray publicExponent) {
3147 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent);
3148
Kenny Root1744cf22014-01-30 13:41:26 -08003149 BIGNUM* eRef = NULL;
Kenny Root860d2702013-04-23 15:50:31 -07003150 if (!arrayToBignum(env, publicExponent, &eRef)) {
3151 return 0;
3152 }
3153 Unique_BIGNUM e(eRef);
3154
3155 Unique_RSA rsa(RSA_new());
3156 if (rsa.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07003157 jniThrowOutOfMemory(env, "Unable to allocate RSA key");
Kenny Root860d2702013-04-23 15:50:31 -07003158 return 0;
3159 }
3160
3161 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), NULL) < 0) {
3162 throwExceptionIfNecessary(env, "RSA_generate_key_ex");
3163 return 0;
3164 }
3165
3166 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3167 if (pkey.get() == NULL) {
3168 jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
3169 return 0;
3170 }
3171
3172 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
3173 jniThrowRuntimeException(env, "RSA_generate_key_ex failed");
3174 return 0;
3175 }
3176
3177 OWNERSHIP_TRANSFERRED(rsa);
3178 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get());
3179 return reinterpret_cast<uintptr_t>(pkey.release());
3180}
3181
Kenny Root37e58bb2014-11-25 14:29:25 -08003182static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jobject pkeyRef) {
3183 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07003184 JNI_TRACE("RSA_size(%p)", pkey);
3185
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08003186 if (pkey == NULL) {
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08003187 return 0;
3188 }
3189
Kenny Root860d2702013-04-23 15:50:31 -07003190 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
3191 if (rsa.get() == NULL) {
3192 jniThrowRuntimeException(env, "RSA_size failed");
3193 return 0;
3194 }
3195
3196 return static_cast<jint>(RSA_size(rsa.get()));
3197}
3198
3199typedef int RSACryptOperation(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
3200 int padding);
3201
Kenny Rootd5d70632015-05-28 17:07:44 -07003202static jint RSA_crypt_operation(RSACryptOperation operation, const char* caller, JNIEnv* env,
3203 jint flen, jbyteArray fromJavaBytes, jbyteArray toJavaBytes,
3204 jobject pkeyRef, jint padding) {
Kenny Root37e58bb2014-11-25 14:29:25 -08003205 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07003206 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey);
3207
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08003208 if (pkey == NULL) {
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08003209 return -1;
3210 }
3211
Kenny Root860d2702013-04-23 15:50:31 -07003212 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
3213 if (rsa.get() == NULL) {
3214 return -1;
3215 }
3216
3217 ScopedByteArrayRO from(env, fromJavaBytes);
3218 if (from.get() == NULL) {
3219 return -1;
3220 }
3221
3222 ScopedByteArrayRW to(env, toJavaBytes);
3223 if (to.get() == NULL) {
3224 return -1;
3225 }
3226
3227 int resultSize = operation(static_cast<int>(flen),
3228 reinterpret_cast<const unsigned char*>(from.get()),
3229 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding);
3230 if (resultSize == -1) {
Kenny Rootd5d70632015-05-28 17:07:44 -07003231 if (throwExceptionIfNecessary(env, caller)) {
3232 JNI_TRACE("%s => threw error", caller);
3233 } else {
3234 throwBadPaddingException(env, caller);
3235 JNI_TRACE("%s => threw padding exception", caller);
3236 }
Kenny Root860d2702013-04-23 15:50:31 -07003237 return -1;
3238 }
3239
3240 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey,
3241 resultSize);
3242 return static_cast<jint>(resultSize);
3243}
3244
3245static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen,
Kenny Root37e58bb2014-11-25 14:29:25 -08003246 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jobject pkeyRef, jint padding) {
Kenny Root860d2702013-04-23 15:50:31 -07003247 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__,
3248 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
3249}
3250static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen,
Kenny Root37e58bb2014-11-25 14:29:25 -08003251 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jobject pkeyRef, jint padding) {
Kenny Root860d2702013-04-23 15:50:31 -07003252 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__,
3253 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
3254}
3255static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen,
Kenny Root37e58bb2014-11-25 14:29:25 -08003256 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jobject pkeyRef, jint padding) {
Kenny Root860d2702013-04-23 15:50:31 -07003257 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__,
3258 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
3259}
3260static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen,
Kenny Root37e58bb2014-11-25 14:29:25 -08003261 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jobject pkeyRef, jint padding) {
Kenny Root860d2702013-04-23 15:50:31 -07003262 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__,
3263 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding);
3264}
3265
3266/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00003267 * public static native byte[][] get_RSA_public_params(long);
Kenny Root860d2702013-04-23 15:50:31 -07003268 */
Kenny Root37e58bb2014-11-25 14:29:25 -08003269static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jobject pkeyRef) {
3270 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07003271 JNI_TRACE("get_RSA_public_params(%p)", pkey);
3272
3273 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07003274 return 0;
3275 }
3276
3277 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
3278 if (rsa.get() == NULL) {
3279 throwExceptionIfNecessary(env, "get_RSA_public_params failed");
3280 return 0;
3281 }
3282
Kenny Root923e3c52013-05-01 12:17:23 -07003283 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07003284 if (joa == NULL) {
3285 return NULL;
3286 }
3287
3288 jbyteArray n = bignumToArray(env, rsa->n, "n");
3289 if (env->ExceptionCheck()) {
3290 return NULL;
3291 }
3292 env->SetObjectArrayElement(joa, 0, n);
3293
3294 jbyteArray e = bignumToArray(env, rsa->e, "e");
3295 if (env->ExceptionCheck()) {
3296 return NULL;
3297 }
3298 env->SetObjectArrayElement(joa, 1, e);
3299
3300 return joa;
3301}
3302
3303/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00003304 * public static native byte[][] get_RSA_private_params(long);
Kenny Root860d2702013-04-23 15:50:31 -07003305 */
Kenny Root37e58bb2014-11-25 14:29:25 -08003306static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jobject pkeyRef) {
3307 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07003308 JNI_TRACE("get_RSA_public_params(%p)", pkey);
3309
3310 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07003311 return 0;
3312 }
3313
3314 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
3315 if (rsa.get() == NULL) {
3316 throwExceptionIfNecessary(env, "get_RSA_public_params failed");
3317 return 0;
3318 }
3319
Kenny Root923e3c52013-05-01 12:17:23 -07003320 jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07003321 if (joa == NULL) {
3322 return NULL;
3323 }
3324
3325 jbyteArray n = bignumToArray(env, rsa->n, "n");
3326 if (env->ExceptionCheck()) {
3327 return NULL;
3328 }
3329 env->SetObjectArrayElement(joa, 0, n);
3330
3331 if (rsa->e != NULL) {
3332 jbyteArray e = bignumToArray(env, rsa->e, "e");
3333 if (env->ExceptionCheck()) {
3334 return NULL;
3335 }
3336 env->SetObjectArrayElement(joa, 1, e);
3337 }
3338
3339 if (rsa->d != NULL) {
3340 jbyteArray d = bignumToArray(env, rsa->d, "d");
3341 if (env->ExceptionCheck()) {
3342 return NULL;
3343 }
3344 env->SetObjectArrayElement(joa, 2, d);
3345 }
3346
3347 if (rsa->p != NULL) {
3348 jbyteArray p = bignumToArray(env, rsa->p, "p");
3349 if (env->ExceptionCheck()) {
3350 return NULL;
3351 }
3352 env->SetObjectArrayElement(joa, 3, p);
3353 }
3354
3355 if (rsa->q != NULL) {
3356 jbyteArray q = bignumToArray(env, rsa->q, "q");
3357 if (env->ExceptionCheck()) {
3358 return NULL;
3359 }
3360 env->SetObjectArrayElement(joa, 4, q);
3361 }
3362
3363 if (rsa->dmp1 != NULL) {
3364 jbyteArray dmp1 = bignumToArray(env, rsa->dmp1, "dmp1");
3365 if (env->ExceptionCheck()) {
3366 return NULL;
3367 }
3368 env->SetObjectArrayElement(joa, 5, dmp1);
3369 }
3370
3371 if (rsa->dmq1 != NULL) {
3372 jbyteArray dmq1 = bignumToArray(env, rsa->dmq1, "dmq1");
3373 if (env->ExceptionCheck()) {
3374 return NULL;
3375 }
3376 env->SetObjectArrayElement(joa, 6, dmq1);
3377 }
3378
3379 if (rsa->iqmp != NULL) {
3380 jbyteArray iqmp = bignumToArray(env, rsa->iqmp, "iqmp");
3381 if (env->ExceptionCheck()) {
3382 return NULL;
3383 }
3384 env->SetObjectArrayElement(joa, 7, iqmp);
3385 }
3386
3387 return joa;
3388}
3389
Kenny Root9b226f92014-07-10 14:50:48 -07003390static jlong NativeCrypto_DH_generate_parameters_ex(JNIEnv* env, jclass, jint primeBits, jlong generator) {
Kenny Root30550a82014-08-12 15:13:33 -07003391 JNI_TRACE("DH_generate_parameters_ex(%d, %lld)", primeBits, (long long) generator);
Kenny Root7b27ca72014-05-08 14:27:23 -07003392
3393 Unique_DH dh(DH_new());
3394 if (dh.get() == NULL) {
Kenny Root9b226f92014-07-10 14:50:48 -07003395 JNI_TRACE("DH_generate_parameters_ex failed");
Kenny Root7b27ca72014-05-08 14:27:23 -07003396 jniThrowOutOfMemory(env, "Unable to allocate DH key");
3397 freeOpenSslErrorState();
3398 return 0;
3399 }
3400
Kenny Root9b226f92014-07-10 14:50:48 -07003401 JNI_TRACE("DH_generate_parameters_ex generating parameters");
Kenny Root7b27ca72014-05-08 14:27:23 -07003402
3403 if (!DH_generate_parameters_ex(dh.get(), primeBits, generator, NULL)) {
Kenny Root9b226f92014-07-10 14:50:48 -07003404 JNI_TRACE("DH_generate_parameters_ex => param generation failed");
Kenny Root7b27ca72014-05-08 14:27:23 -07003405 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_parameters_ex failed");
3406 return 0;
3407 }
3408
Kenny Root7b27ca72014-05-08 14:27:23 -07003409 Unique_EVP_PKEY pkey(EVP_PKEY_new());
3410 if (pkey.get() == NULL) {
Kenny Root9b226f92014-07-10 14:50:48 -07003411 JNI_TRACE("DH_generate_parameters_ex failed");
3412 jniThrowRuntimeException(env, "NativeCrypto_DH_generate_parameters_ex failed");
Kenny Root7b27ca72014-05-08 14:27:23 -07003413 freeOpenSslErrorState();
3414 return 0;
3415 }
3416
3417 if (EVP_PKEY_assign_DH(pkey.get(), dh.get()) != 1) {
Kenny Root9b226f92014-07-10 14:50:48 -07003418 JNI_TRACE("DH_generate_parameters_ex failed");
3419 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_parameters_ex failed");
Kenny Root7b27ca72014-05-08 14:27:23 -07003420 return 0;
3421 }
3422
3423 OWNERSHIP_TRANSFERRED(dh);
Kenny Root30550a82014-08-12 15:13:33 -07003424 JNI_TRACE("DH_generate_parameters_ex(n=%d, g=%lld) => %p", primeBits, (long long) generator,
3425 pkey.get());
Kenny Root7b27ca72014-05-08 14:27:23 -07003426 return reinterpret_cast<uintptr_t>(pkey.release());
3427}
3428
Kenny Root37e58bb2014-11-25 14:29:25 -08003429static void NativeCrypto_DH_generate_key(JNIEnv* env, jclass, jobject pkeyRef) {
3430 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root30550a82014-08-12 15:13:33 -07003431 JNI_TRACE("DH_generate_key(%p)", pkey);
Kenny Root9b226f92014-07-10 14:50:48 -07003432
3433 if (pkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07003434 return;
Kenny Root9b226f92014-07-10 14:50:48 -07003435 }
3436
3437 Unique_DH dh(EVP_PKEY_get1_DH(pkey));
3438 if (dh.get() == NULL) {
3439 JNI_TRACE("DH_generate_key failed");
3440 throwExceptionIfNecessary(env, "Unable to get DH key");
3441 freeOpenSslErrorState();
3442 }
3443
3444 if (!DH_generate_key(dh.get())) {
3445 JNI_TRACE("DH_generate_key failed");
3446 throwExceptionIfNecessary(env, "NativeCrypto_DH_generate_key failed");
3447 }
3448}
3449
Kenny Root37e58bb2014-11-25 14:29:25 -08003450static jobjectArray NativeCrypto_get_DH_params(JNIEnv* env, jclass, jobject pkeyRef) {
3451 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root7b27ca72014-05-08 14:27:23 -07003452 JNI_TRACE("get_DH_params(%p)", pkey);
3453
3454 if (pkey == NULL) {
Kenny Root7b27ca72014-05-08 14:27:23 -07003455 return NULL;
3456 }
3457
3458 Unique_DH dh(EVP_PKEY_get1_DH(pkey));
3459 if (dh.get() == NULL) {
3460 throwExceptionIfNecessary(env, "get_DH_params failed");
3461 return 0;
3462 }
3463
3464 jobjectArray joa = env->NewObjectArray(4, byteArrayClass, NULL);
3465 if (joa == NULL) {
3466 return NULL;
3467 }
3468
3469 if (dh->p != NULL) {
3470 jbyteArray p = bignumToArray(env, dh->p, "p");
3471 if (env->ExceptionCheck()) {
3472 return NULL;
3473 }
3474 env->SetObjectArrayElement(joa, 0, p);
3475 }
3476
3477 if (dh->g != NULL) {
3478 jbyteArray g = bignumToArray(env, dh->g, "g");
3479 if (env->ExceptionCheck()) {
3480 return NULL;
3481 }
3482 env->SetObjectArrayElement(joa, 1, g);
3483 }
3484
3485 if (dh->pub_key != NULL) {
3486 jbyteArray pub_key = bignumToArray(env, dh->pub_key, "pub_key");
3487 if (env->ExceptionCheck()) {
3488 return NULL;
3489 }
3490 env->SetObjectArrayElement(joa, 2, pub_key);
3491 }
3492
3493 if (dh->priv_key != NULL) {
3494 jbyteArray priv_key = bignumToArray(env, dh->priv_key, "priv_key");
3495 if (env->ExceptionCheck()) {
3496 return NULL;
3497 }
3498 env->SetObjectArrayElement(joa, 3, priv_key);
3499 }
3500
3501 return joa;
3502}
3503
Kenny Root860d2702013-04-23 15:50:31 -07003504#define EC_CURVE_GFP 1
3505#define EC_CURVE_GF2M 2
3506
3507/**
3508 * Return group type or 0 if unknown group.
3509 * EC_GROUP_GFP or EC_GROUP_GF2M
3510 */
Adam Langleyca341142014-12-11 17:26:18 -08003511#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07003512static int get_EC_GROUP_type(const EC_GROUP* group)
3513{
Kenny Rootdc77a712015-05-03 17:15:59 -07003514 const int curve_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
3515 if (curve_nid == NID_X9_62_prime_field) {
Kenny Root860d2702013-04-23 15:50:31 -07003516 return EC_CURVE_GFP;
Kenny Rootdc77a712015-05-03 17:15:59 -07003517 } else if (curve_nid == NID_X9_62_characteristic_two_field) {
Kenny Root860d2702013-04-23 15:50:31 -07003518 return EC_CURVE_GF2M;
3519 }
3520
3521 return 0;
3522}
Adam Langleyca341142014-12-11 17:26:18 -08003523#else
3524static int get_EC_GROUP_type(const EC_GROUP*)
3525{
3526 return EC_CURVE_GFP;
3527}
3528#endif
Kenny Root860d2702013-04-23 15:50:31 -07003529
3530static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava)
3531{
3532 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava);
3533
3534 ScopedUtfChars curveName(env, curveNameJava);
3535 if (curveName.c_str() == NULL) {
3536 return 0;
3537 }
3538 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str());
3539
3540 int nid = OBJ_sn2nid(curveName.c_str());
3541 if (nid == NID_undef) {
3542 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str());
3543 return 0;
3544 }
3545
3546 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid);
3547 if (group == NULL) {
3548 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid);
3549 freeOpenSslErrorState();
3550 return 0;
3551 }
3552
3553 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group);
3554 return reinterpret_cast<uintptr_t>(group);
3555}
3556
Adam Langley05b8e502015-05-12 19:24:49 -07003557static jlong NativeCrypto_EC_GROUP_new_arbitrary(
3558 JNIEnv* env, jclass, jbyteArray pBytes, jbyteArray aBytes,
3559 jbyteArray bBytes, jbyteArray xBytes, jbyteArray yBytes,
3560 jbyteArray orderBytes, jint cofactorInt)
3561{
3562 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
3563 BIGNUM *order = NULL, *cofactor = NULL;
3564
3565 JNI_TRACE("EC_GROUP_new_arbitrary");
3566
3567 if (cofactorInt < 1) {
3568 jniThrowException(env, "java/lang/IllegalArgumentException", "cofactor < 1");
3569 return 0;
3570 }
3571
3572 cofactor = BN_new();
3573 if (cofactor == NULL) {
3574 return 0;
3575 }
3576
3577 int ok = 1;
3578
3579 if (!arrayToBignum(env, pBytes, &p) ||
3580 !arrayToBignum(env, aBytes, &a) ||
3581 !arrayToBignum(env, bBytes, &b) ||
3582 !arrayToBignum(env, xBytes, &x) ||
3583 !arrayToBignum(env, yBytes, &y) ||
3584 !arrayToBignum(env, orderBytes, &order) ||
3585 !BN_set_word(cofactor, cofactorInt)) {
3586 ok = 0;
3587 }
3588
3589 Unique_BIGNUM pStorage(p);
3590 Unique_BIGNUM aStorage(a);
3591 Unique_BIGNUM bStorage(b);
3592 Unique_BIGNUM xStorage(x);
3593 Unique_BIGNUM yStorage(y);
3594 Unique_BIGNUM orderStorage(order);
3595 Unique_BIGNUM cofactorStorage(cofactor);
3596
3597 if (!ok) {
3598 return 0;
3599 }
3600
3601 Unique_BN_CTX ctx(BN_CTX_new());
3602 Unique_EC_GROUP group(EC_GROUP_new_curve_GFp(p, a, b, ctx.get()));
3603 if (group.get() == NULL) {
3604 JNI_TRACE("EC_GROUP_new_curve_GFp => NULL");
3605 throwExceptionIfNecessary(env, "EC_GROUP_new_curve_GFp");
3606 return 0;
3607 }
3608
3609 Unique_EC_POINT generator(EC_POINT_new(group.get()));
3610 if (generator.get() == NULL) {
3611 JNI_TRACE("EC_POINT_new => NULL");
3612 freeOpenSslErrorState();
3613 return 0;
3614 }
3615
3616 if (!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), x, y, ctx.get())) {
3617 JNI_TRACE("EC_POINT_set_affine_coordinates_GFp => error");
3618 throwExceptionIfNecessary(env, "EC_POINT_set_affine_coordinates_GFp");
3619 return 0;
3620 }
3621
3622 if (!EC_GROUP_set_generator(group.get(), generator.get(), order, cofactor)) {
3623 JNI_TRACE("EC_GROUP_set_generator => error");
3624 throwExceptionIfNecessary(env, "EC_GROUP_set_generator");
3625 return 0;
3626 }
3627
3628 JNI_TRACE("EC_GROUP_new_arbitrary => %p", group.get());
3629 return reinterpret_cast<uintptr_t>(group.release());
3630}
3631
Adam Langleyca341142014-12-11 17:26:18 -08003632#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root7dc06b92014-11-26 10:07:51 -08003633static void NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv* env, jclass, jobject groupRef,
Kenny Root860d2702013-04-23 15:50:31 -07003634 jint flag)
3635{
Kenny Root7dc06b92014-11-26 10:07:51 -08003636 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003637 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d)", group, flag);
3638
3639 if (group == NULL) {
3640 JNI_TRACE("EC_GROUP_set_asn1_flag => group == NULL");
Kenny Root860d2702013-04-23 15:50:31 -07003641 return;
3642 }
3643
3644 EC_GROUP_set_asn1_flag(group, flag);
3645 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d) => success", group, flag);
3646}
Adam Langleyca341142014-12-11 17:26:18 -08003647#else
3648static void NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv*, jclass, jobject, jint)
3649{
3650}
3651#endif
Kenny Root860d2702013-04-23 15:50:31 -07003652
Adam Langleyca341142014-12-11 17:26:18 -08003653#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07003654static void NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv* env, jclass,
Kenny Root7dc06b92014-11-26 10:07:51 -08003655 jobject groupRef, jint form)
Kenny Root860d2702013-04-23 15:50:31 -07003656{
Kenny Root7dc06b92014-11-26 10:07:51 -08003657 EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003658 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d)", group, form);
3659
3660 if (group == NULL) {
3661 JNI_TRACE("EC_GROUP_set_point_conversion_form => group == NULL");
Kenny Root860d2702013-04-23 15:50:31 -07003662 return;
3663 }
3664
3665 EC_GROUP_set_point_conversion_form(group, static_cast<point_conversion_form_t>(form));
3666 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d) => success", group, form);
3667}
Adam Langleyca341142014-12-11 17:26:18 -08003668#else
3669static void NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv*, jclass, jobject, jint)
3670{
3671}
3672#endif
Kenny Root860d2702013-04-23 15:50:31 -07003673
Kenny Root7dc06b92014-11-26 10:07:51 -08003674static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jobject groupRef) {
3675 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003676 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group);
3677
3678 if (group == NULL) {
3679 JNI_TRACE("EC_GROUP_get_curve_name => group == NULL");
Kenny Root860d2702013-04-23 15:50:31 -07003680 return 0;
3681 }
3682
3683 int nid = EC_GROUP_get_curve_name(group);
3684 if (nid == NID_undef) {
3685 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group);
3686 return NULL;
3687 }
3688
3689 const char* shortName = OBJ_nid2sn(nid);
3690 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName);
3691 return env->NewStringUTF(shortName);
3692}
3693
Kenny Root7dc06b92014-11-26 10:07:51 -08003694static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003695{
Kenny Root7dc06b92014-11-26 10:07:51 -08003696 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003697 JNI_TRACE("EC_GROUP_get_curve(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07003698 if (group == NULL) {
3699 JNI_TRACE("EC_GROUP_get_curve => group == NULL");
3700 return NULL;
3701 }
Kenny Root860d2702013-04-23 15:50:31 -07003702
3703 Unique_BIGNUM p(BN_new());
3704 Unique_BIGNUM a(BN_new());
3705 Unique_BIGNUM b(BN_new());
3706
Adam Langleyde5225d2014-10-06 15:55:30 -07003707 if (get_EC_GROUP_type(group) != EC_CURVE_GFP) {
Kenny Root860d2702013-04-23 15:50:31 -07003708 jniThrowRuntimeException(env, "invalid group");
3709 return NULL;
3710 }
Adam Langleyde5225d2014-10-06 15:55:30 -07003711
3712 int ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), (BN_CTX*) NULL);
Kenny Root860d2702013-04-23 15:50:31 -07003713 if (ret != 1) {
3714 throwExceptionIfNecessary(env, "EC_GROUP_get_curve");
3715 return NULL;
3716 }
3717
Kenny Root923e3c52013-05-01 12:17:23 -07003718 jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07003719 if (joa == NULL) {
3720 return NULL;
3721 }
3722
3723 jbyteArray pArray = bignumToArray(env, p.get(), "p");
3724 if (env->ExceptionCheck()) {
3725 return NULL;
3726 }
3727 env->SetObjectArrayElement(joa, 0, pArray);
3728
3729 jbyteArray aArray = bignumToArray(env, a.get(), "a");
3730 if (env->ExceptionCheck()) {
3731 return NULL;
3732 }
3733 env->SetObjectArrayElement(joa, 1, aArray);
3734
3735 jbyteArray bArray = bignumToArray(env, b.get(), "b");
3736 if (env->ExceptionCheck()) {
3737 return NULL;
3738 }
3739 env->SetObjectArrayElement(joa, 2, bArray);
3740
3741 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa);
3742 return joa;
3743}
3744
Kenny Root7dc06b92014-11-26 10:07:51 -08003745static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003746{
Kenny Root7dc06b92014-11-26 10:07:51 -08003747 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003748 JNI_TRACE("EC_GROUP_get_order(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07003749 if (group == NULL) {
3750 return NULL;
3751 }
Kenny Root860d2702013-04-23 15:50:31 -07003752
3753 Unique_BIGNUM order(BN_new());
3754 if (order.get() == NULL) {
3755 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
Kenny Root923e3c52013-05-01 12:17:23 -07003756 jniThrowOutOfMemory(env, "BN_new");
Kenny Root860d2702013-04-23 15:50:31 -07003757 return NULL;
3758 }
3759
3760 if (EC_GROUP_get_order(group, order.get(), NULL) != 1) {
3761 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group);
3762 throwExceptionIfNecessary(env, "EC_GROUP_get_order");
3763 return NULL;
3764 }
3765
3766 jbyteArray orderArray = bignumToArray(env, order.get(), "order");
3767 if (env->ExceptionCheck()) {
3768 return NULL;
3769 }
3770
3771 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray);
3772 return orderArray;
3773}
3774
Kenny Root7dc06b92014-11-26 10:07:51 -08003775static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003776{
Kenny Root7dc06b92014-11-26 10:07:51 -08003777 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003778 JNI_TRACE("EC_GROUP_get_degree(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07003779 if (group == NULL) {
3780 return 0;
3781 }
Kenny Root860d2702013-04-23 15:50:31 -07003782
3783 jint degree = EC_GROUP_get_degree(group);
3784 if (degree == 0) {
3785 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
3786 jniThrowRuntimeException(env, "not supported");
3787 return 0;
3788 }
3789
3790 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
3791 return degree;
3792}
3793
Kenny Root7dc06b92014-11-26 10:07:51 -08003794static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003795{
Kenny Root7dc06b92014-11-26 10:07:51 -08003796 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003797 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07003798 if (group == NULL) {
3799 return NULL;
3800 }
Kenny Root860d2702013-04-23 15:50:31 -07003801
3802 Unique_BIGNUM cofactor(BN_new());
3803 if (cofactor.get() == NULL) {
3804 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
Kenny Root923e3c52013-05-01 12:17:23 -07003805 jniThrowOutOfMemory(env, "BN_new");
Kenny Root860d2702013-04-23 15:50:31 -07003806 return NULL;
3807 }
3808
3809 if (EC_GROUP_get_cofactor(group, cofactor.get(), NULL) != 1) {
3810 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group);
3811 throwExceptionIfNecessary(env, "EC_GROUP_get_cofactor");
3812 return NULL;
3813 }
3814
3815 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor");
3816 if (env->ExceptionCheck()) {
3817 return NULL;
3818 }
3819
3820 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray);
3821 return cofactorArray;
3822}
3823
Kenny Root7dc06b92014-11-26 10:07:51 -08003824static jint NativeCrypto_get_EC_GROUP_type(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003825{
Kenny Root7dc06b92014-11-26 10:07:51 -08003826 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003827 JNI_TRACE("get_EC_GROUP_type(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07003828 if (group == NULL) {
3829 return 0;
3830 }
Kenny Root860d2702013-04-23 15:50:31 -07003831
3832 int type = get_EC_GROUP_type(group);
3833 if (type == 0) {
3834 JNI_TRACE("get_EC_GROUP_type(%p) => curve type", group);
3835 jniThrowRuntimeException(env, "unknown curve type");
3836 } else {
3837 JNI_TRACE("get_EC_GROUP_type(%p) => %d", group, type);
3838 }
3839 return type;
3840}
3841
3842static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef)
3843{
3844 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef);
3845 JNI_TRACE("EC_GROUP_clear_free(%p)", group);
3846
3847 if (group == NULL) {
3848 JNI_TRACE("EC_GROUP_clear_free => group == NULL");
3849 jniThrowNullPointerException(env, "group == NULL");
3850 return;
3851 }
3852
Adam Langleyde5225d2014-10-06 15:55:30 -07003853 EC_GROUP_free(group);
Kenny Root860d2702013-04-23 15:50:31 -07003854 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group);
3855}
3856
Kenny Root7dc06b92014-11-26 10:07:51 -08003857static jboolean NativeCrypto_EC_GROUP_cmp(JNIEnv* env, jclass, jobject group1Ref,
3858 jobject group2Ref)
Kenny Root860d2702013-04-23 15:50:31 -07003859{
Kenny Root8a77c202015-04-24 10:37:11 -07003860 JNI_TRACE("EC_GROUP_cmp(%p, %p)", group1Ref, group2Ref);
Kenny Root7dc06b92014-11-26 10:07:51 -08003861 const EC_GROUP* group1 = fromContextObject<EC_GROUP>(env, group1Ref);
Kenny Root8a77c202015-04-24 10:37:11 -07003862 if (group1 == NULL) {
3863 return JNI_FALSE;
Kenny Root860d2702013-04-23 15:50:31 -07003864 }
Kenny Root8a77c202015-04-24 10:37:11 -07003865 const EC_GROUP* group2 = fromContextObject<EC_GROUP>(env, group2Ref);
3866 if (group2 == NULL) {
3867 return JNI_FALSE;
3868 }
3869 JNI_TRACE("EC_GROUP_cmp(%p, %p) <- ptr", group1, group2);
Kenny Root860d2702013-04-23 15:50:31 -07003870
Adam Langleyde5225d2014-10-06 15:55:30 -07003871 int ret = EC_GROUP_cmp(group1, group2, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07003872
3873 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", group1, group2, ret);
3874 return ret == 0;
3875}
3876
Kenny Root7dc06b92014-11-26 10:07:51 -08003877static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003878{
Kenny Root7dc06b92014-11-26 10:07:51 -08003879 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003880 JNI_TRACE("EC_GROUP_get_generator(%p)", group);
3881
3882 if (group == NULL) {
3883 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group);
Kenny Root860d2702013-04-23 15:50:31 -07003884 return 0;
3885 }
3886
3887 const EC_POINT* generator = EC_GROUP_get0_generator(group);
3888
3889 Unique_EC_POINT dup(EC_POINT_dup(generator, group));
3890 if (dup.get() == NULL) {
3891 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
Kenny Root923e3c52013-05-01 12:17:23 -07003892 jniThrowOutOfMemory(env, "unable to dupe generator");
Kenny Root860d2702013-04-23 15:50:31 -07003893 return 0;
3894 }
3895
3896 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get());
3897 return reinterpret_cast<uintptr_t>(dup.release());
3898}
3899
Kenny Root7dc06b92014-11-26 10:07:51 -08003900static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07003901{
Kenny Root7dc06b92014-11-26 10:07:51 -08003902 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07003903 JNI_TRACE("EC_POINT_new(%p)", group);
3904
3905 if (group == NULL) {
3906 JNI_TRACE("EC_POINT_new(%p) => group == null", group);
Kenny Root860d2702013-04-23 15:50:31 -07003907 return 0;
3908 }
3909
3910 EC_POINT* point = EC_POINT_new(group);
3911 if (point == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07003912 jniThrowOutOfMemory(env, "Unable create an EC_POINT");
Kenny Root860d2702013-04-23 15:50:31 -07003913 return 0;
3914 }
3915
3916 return reinterpret_cast<uintptr_t>(point);
3917}
3918
3919static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) {
3920 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef);
3921 JNI_TRACE("EC_POINT_clear_free(%p)", group);
3922
3923 if (group == NULL) {
3924 JNI_TRACE("EC_POINT_clear_free => group == NULL");
3925 jniThrowNullPointerException(env, "group == NULL");
3926 return;
3927 }
3928
Adam Langleyde5225d2014-10-06 15:55:30 -07003929 EC_POINT_free(group);
Kenny Root860d2702013-04-23 15:50:31 -07003930 JNI_TRACE("EC_POINT_clear_free(%p) => success", group);
3931}
3932
Kenny Root7dc06b92014-11-26 10:07:51 -08003933static jboolean NativeCrypto_EC_POINT_cmp(JNIEnv* env, jclass, jobject groupRef, jobject point1Ref,
3934 jobject point2Ref)
Kenny Root860d2702013-04-23 15:50:31 -07003935{
Kenny Root8a77c202015-04-24 10:37:11 -07003936 JNI_TRACE("EC_POINT_cmp(%p, %p, %p)", groupRef, point1Ref, point2Ref);
Kenny Root7dc06b92014-11-26 10:07:51 -08003937 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root8a77c202015-04-24 10:37:11 -07003938 if (group == NULL) {
3939 return JNI_FALSE;
Kenny Root860d2702013-04-23 15:50:31 -07003940 }
Kenny Root8a77c202015-04-24 10:37:11 -07003941 const EC_POINT* point1 = fromContextObject<EC_POINT>(env, point1Ref);
3942 if (point1 == NULL) {
3943 return JNI_FALSE;
3944 }
3945 const EC_POINT* point2 = fromContextObject<EC_POINT>(env, point2Ref);
3946 if (point2 == NULL) {
3947 return JNI_FALSE;
3948 }
3949 JNI_TRACE("EC_POINT_cmp(%p, %p, %p) <- ptr", group, point1, point2);
Kenny Root860d2702013-04-23 15:50:31 -07003950
3951 int ret = EC_POINT_cmp(group, point1, point2, (BN_CTX*)NULL);
3952
3953 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", point1, point2, ret);
3954 return ret == 0;
3955}
3956
3957static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass,
Kenny Root7dc06b92014-11-26 10:07:51 -08003958 jobject groupRef, jobject pointRef, jbyteArray xjavaBytes, jbyteArray yjavaBytes)
Kenny Root860d2702013-04-23 15:50:31 -07003959{
Kenny Root8a77c202015-04-24 10:37:11 -07003960 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", groupRef, pointRef, xjavaBytes,
Kenny Root860d2702013-04-23 15:50:31 -07003961 yjavaBytes);
Kenny Root8a77c202015-04-24 10:37:11 -07003962 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
3963 if (group == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07003964 return;
3965 }
Kenny Root8a77c202015-04-24 10:37:11 -07003966 EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
3967 if (point == NULL) {
3968 return;
3969 }
3970 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) <- ptr", group, point, xjavaBytes,
3971 yjavaBytes);
Kenny Root860d2702013-04-23 15:50:31 -07003972
Kenny Root1744cf22014-01-30 13:41:26 -08003973 BIGNUM* xRef = NULL;
Kenny Root860d2702013-04-23 15:50:31 -07003974 if (!arrayToBignum(env, xjavaBytes, &xRef)) {
3975 return;
3976 }
3977 Unique_BIGNUM x(xRef);
3978
Kenny Root1744cf22014-01-30 13:41:26 -08003979 BIGNUM* yRef = NULL;
Kenny Root860d2702013-04-23 15:50:31 -07003980 if (!arrayToBignum(env, yjavaBytes, &yRef)) {
3981 return;
3982 }
3983 Unique_BIGNUM y(yRef);
3984
3985 int ret;
3986 switch (get_EC_GROUP_type(group)) {
3987 case EC_CURVE_GFP:
3988 ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
3989 break;
Adam Langleyde5225d2014-10-06 15:55:30 -07003990#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07003991 case EC_CURVE_GF2M:
3992 ret = EC_POINT_set_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL);
3993 break;
Adam Langleyde5225d2014-10-06 15:55:30 -07003994#endif
Kenny Root860d2702013-04-23 15:50:31 -07003995 default:
3996 jniThrowRuntimeException(env, "invalid curve type");
3997 return;
3998 }
3999
4000 if (ret != 1) {
4001 throwExceptionIfNecessary(env, "EC_POINT_set_affine_coordinates");
4002 }
4003
4004 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point,
4005 xjavaBytes, yjavaBytes, ret);
4006}
4007
Kenny Root7dc06b92014-11-26 10:07:51 -08004008static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass,
4009 jobject groupRef, jobject pointRef)
Kenny Root860d2702013-04-23 15:50:31 -07004010{
Kenny Root8a77c202015-04-24 10:37:11 -07004011 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", groupRef, pointRef);
Kenny Root7dc06b92014-11-26 10:07:51 -08004012 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root8a77c202015-04-24 10:37:11 -07004013 if (group == NULL) {
4014 return NULL;
4015 }
Kenny Root7dc06b92014-11-26 10:07:51 -08004016 const EC_POINT* point = fromContextObject<EC_POINT>(env, pointRef);
Kenny Root8a77c202015-04-24 10:37:11 -07004017 if (point == NULL) {
4018 return NULL;
4019 }
4020 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) <- ptr", group, point);
Kenny Root860d2702013-04-23 15:50:31 -07004021
4022 Unique_BIGNUM x(BN_new());
4023 Unique_BIGNUM y(BN_new());
4024
4025 int ret;
4026 switch (get_EC_GROUP_type(group)) {
4027 case EC_CURVE_GFP:
4028 ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL);
4029 break;
Kenny Root860d2702013-04-23 15:50:31 -07004030 default:
4031 jniThrowRuntimeException(env, "invalid curve type");
4032 return NULL;
4033 }
4034 if (ret != 1) {
4035 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point);
4036 throwExceptionIfNecessary(env, "EC_POINT_get_affine_coordinates");
4037 return NULL;
4038 }
4039
Kenny Root923e3c52013-05-01 12:17:23 -07004040 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07004041 if (joa == NULL) {
4042 return NULL;
4043 }
4044
4045 jbyteArray xBytes = bignumToArray(env, x.get(), "x");
4046 if (env->ExceptionCheck()) {
4047 return NULL;
4048 }
4049 env->SetObjectArrayElement(joa, 0, xBytes);
4050
4051 jbyteArray yBytes = bignumToArray(env, y.get(), "y");
4052 if (env->ExceptionCheck()) {
4053 return NULL;
4054 }
4055 env->SetObjectArrayElement(joa, 1, yBytes);
4056
4057 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa);
4058 return joa;
4059}
4060
Kenny Root7dc06b92014-11-26 10:07:51 -08004061static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jobject groupRef)
Kenny Root860d2702013-04-23 15:50:31 -07004062{
Kenny Root7dc06b92014-11-26 10:07:51 -08004063 const EC_GROUP* group = fromContextObject<EC_GROUP>(env, groupRef);
Kenny Root860d2702013-04-23 15:50:31 -07004064 JNI_TRACE("EC_KEY_generate_key(%p)", group);
Kenny Root8a77c202015-04-24 10:37:11 -07004065 if (group == NULL) {
4066 return 0;
4067 }
Kenny Root860d2702013-04-23 15:50:31 -07004068
4069 Unique_EC_KEY eckey(EC_KEY_new());
4070 if (eckey.get() == NULL) {
4071 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
Kenny Root923e3c52013-05-01 12:17:23 -07004072 jniThrowOutOfMemory(env, "Unable to create an EC_KEY");
Kenny Root860d2702013-04-23 15:50:31 -07004073 return 0;
4074 }
4075
4076 if (EC_KEY_set_group(eckey.get(), group) != 1) {
4077 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group);
4078 throwExceptionIfNecessary(env, "EC_KEY_set_group");
4079 return 0;
4080 }
4081
4082 if (EC_KEY_generate_key(eckey.get()) != 1) {
4083 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group);
4084 throwExceptionIfNecessary(env, "EC_KEY_set_group");
4085 return 0;
4086 }
4087
4088 Unique_EVP_PKEY pkey(EVP_PKEY_new());
4089 if (pkey.get() == NULL) {
4090 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group);
4091 throwExceptionIfNecessary(env, "EC_KEY_generate_key");
4092 return 0;
4093 }
4094 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) {
4095 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed");
4096 return 0;
4097 }
4098 OWNERSHIP_TRANSFERRED(eckey);
4099
4100 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get());
4101 return reinterpret_cast<uintptr_t>(pkey.release());
4102}
4103
Kenny Root7dc06b92014-11-26 10:07:51 -08004104static jlong NativeCrypto_EC_KEY_get1_group(JNIEnv* env, jclass, jobject pkeyRef)
Kenny Root860d2702013-04-23 15:50:31 -07004105{
Kenny Root37e58bb2014-11-25 14:29:25 -08004106 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root7dc06b92014-11-26 10:07:51 -08004107 JNI_TRACE("EC_KEY_get1_group(%p)", pkey);
Kenny Root860d2702013-04-23 15:50:31 -07004108
4109 if (pkey == NULL) {
Kenny Root7dc06b92014-11-26 10:07:51 -08004110 JNI_TRACE("EC_KEY_get1_group(%p) => pkey == null", pkey);
Kenny Root860d2702013-04-23 15:50:31 -07004111 return 0;
4112 }
4113
4114 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
4115 jniThrowRuntimeException(env, "not EC key");
Kenny Root7dc06b92014-11-26 10:07:51 -08004116 JNI_TRACE("EC_KEY_get1_group(%p) => not EC key (type == %d)", pkey,
Kenny Root860d2702013-04-23 15:50:31 -07004117 EVP_PKEY_type(pkey->type));
4118 return 0;
4119 }
4120
Kenny Root7dc06b92014-11-26 10:07:51 -08004121 EC_GROUP* group = EC_GROUP_dup(EC_KEY_get0_group(pkey->pkey.ec));
4122 JNI_TRACE("EC_KEY_get1_group(%p) => %p", pkey, group);
Kenny Root860d2702013-04-23 15:50:31 -07004123 return reinterpret_cast<uintptr_t>(group);
4124}
4125
Kenny Root37e58bb2014-11-25 14:29:25 -08004126static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jobject pkeyRef)
Kenny Root860d2702013-04-23 15:50:31 -07004127{
Kenny Root37e58bb2014-11-25 14:29:25 -08004128 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07004129 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey);
4130
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004131 if (pkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004132 JNI_TRACE("EC_KEY_get_private_key => pkey == NULL");
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004133 return NULL;
4134 }
4135
Kenny Root860d2702013-04-23 15:50:31 -07004136 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
4137 if (eckey.get() == NULL) {
4138 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
4139 return NULL;
4140 }
4141
4142 const BIGNUM *privkey = EC_KEY_get0_private_key(eckey.get());
4143
4144 jbyteArray privBytes = bignumToArray(env, privkey, "privkey");
4145 if (env->ExceptionCheck()) {
4146 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey);
4147 return NULL;
4148 }
4149
4150 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes);
4151 return privBytes;
4152}
4153
Kenny Root37e58bb2014-11-25 14:29:25 -08004154static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jobject pkeyRef)
Kenny Root860d2702013-04-23 15:50:31 -07004155{
Kenny Root37e58bb2014-11-25 14:29:25 -08004156 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07004157 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey);
4158
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004159 if (pkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004160 JNI_TRACE("EC_KEY_get_public_key => pkey == NULL");
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004161 return 0;
4162 }
4163
Kenny Root860d2702013-04-23 15:50:31 -07004164 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
4165 if (eckey.get() == NULL) {
4166 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
4167 return 0;
4168 }
4169
4170 Unique_EC_POINT dup(EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()),
4171 EC_KEY_get0_group(eckey.get())));
4172 if (dup.get() == NULL) {
4173 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey);
4174 jniThrowRuntimeException(env, "EC_POINT_dup");
4175 return 0;
4176 }
4177
4178 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get());
4179 return reinterpret_cast<uintptr_t>(dup.release());
4180}
4181
Adam Langleyca341142014-12-11 17:26:18 -08004182#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root37e58bb2014-11-25 14:29:25 -08004183static void NativeCrypto_EC_KEY_set_nonce_from_hash(JNIEnv* env, jclass, jobject pkeyRef,
Alex Klyubin60f83802014-02-03 15:21:56 -08004184 jboolean enabled)
4185{
Kenny Root37e58bb2014-11-25 14:29:25 -08004186 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Alex Klyubin60f83802014-02-03 15:21:56 -08004187 JNI_TRACE("EC_KEY_set_nonce_from_hash(%p, %d)", pkey, enabled ? 1 : 0);
4188
4189 if (pkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004190 JNI_TRACE("EC_KEY_set_nonce_from_hash => pkey == NULL");
Alex Klyubin60f83802014-02-03 15:21:56 -08004191 return;
4192 }
4193
4194 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
4195 if (eckey.get() == NULL) {
4196 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY");
4197 return;
4198 }
4199
4200 EC_KEY_set_nonce_from_hash(eckey.get(), enabled ? 1 : 0);
4201}
Adam Langleyca341142014-12-11 17:26:18 -08004202#else
4203static void NativeCrypto_EC_KEY_set_nonce_from_hash(JNIEnv*, jclass, jobject, jboolean)
4204{
4205}
4206#endif
Alex Klyubin60f83802014-02-03 15:21:56 -08004207
Kenny Root860d2702013-04-23 15:50:31 -07004208static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass,
Kenny Root37e58bb2014-11-25 14:29:25 -08004209 jbyteArray outArray, jint outOffset, jobject pubkeyRef, jobject privkeyRef)
Kenny Root860d2702013-04-23 15:50:31 -07004210{
Kenny Root8a77c202015-04-24 10:37:11 -07004211 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubkeyRef, privkeyRef);
Kenny Root37e58bb2014-11-25 14:29:25 -08004212 EVP_PKEY* pubPkey = fromContextObject<EVP_PKEY>(env, pubkeyRef);
Sergio Giro796ed062015-03-18 17:01:28 +00004213 if (pubPkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004214 JNI_TRACE("ECDH_compute_key => pubPkey == NULL");
Sergio Giro796ed062015-03-18 17:01:28 +00004215 return -1;
4216 }
Kenny Root37e58bb2014-11-25 14:29:25 -08004217 EVP_PKEY* privPkey = fromContextObject<EVP_PKEY>(env, privkeyRef);
Sergio Giro796ed062015-03-18 17:01:28 +00004218 if (privPkey == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004219 JNI_TRACE("ECDH_compute_key => privPkey == NULL");
Sergio Giro796ed062015-03-18 17:01:28 +00004220 return -1;
4221 }
Kenny Root8a77c202015-04-24 10:37:11 -07004222 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) <- ptr", outArray, outOffset, pubPkey, privPkey);
Kenny Root860d2702013-04-23 15:50:31 -07004223
4224 ScopedByteArrayRW out(env, outArray);
4225 if (out.get() == NULL) {
4226 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer",
4227 outArray, outOffset, pubPkey, privPkey);
4228 return -1;
4229 }
4230
4231 if ((outOffset < 0) || ((size_t) outOffset >= out.size())) {
4232 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
4233 return -1;
4234 }
4235
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004236 if (pubPkey == NULL) {
4237 jniThrowNullPointerException(env, "pubPkey == null");
4238 return -1;
4239 }
4240
Kenny Root860d2702013-04-23 15:50:31 -07004241 Unique_EC_KEY pubkey(EVP_PKEY_get1_EC_KEY(pubPkey));
4242 if (pubkey.get() == NULL) {
4243 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey);
4244 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
4245 return -1;
4246 }
4247
4248 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get());
4249 if (pubkeyPoint == NULL) {
4250 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey);
4251 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public");
4252 return -1;
4253 }
4254
Alex Klyubin7c2b4ae2014-02-12 16:36:59 -08004255 if (privPkey == NULL) {
4256 jniThrowNullPointerException(env, "privPkey == null");
4257 return -1;
4258 }
4259
Kenny Root860d2702013-04-23 15:50:31 -07004260 Unique_EC_KEY privkey(EVP_PKEY_get1_EC_KEY(privPkey));
4261 if (privkey.get() == NULL) {
4262 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY private");
4263 return -1;
4264 }
4265
4266 int outputLength = ECDH_compute_key(
4267 &out[outOffset],
4268 out.size() - outOffset,
4269 pubkeyPoint,
4270 privkey.get(),
4271 NULL // No KDF
4272 );
4273 if (outputLength == -1) {
4274 throwExceptionIfNecessary(env, "ECDH_compute_key");
4275 return -1;
4276 }
4277
4278 return outputLength;
4279}
4280
4281static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
Kenny Rootacc950a2014-03-26 13:55:26 -07004282 JNI_TRACE_MD("EVP_MD_CTX_create()");
Kenny Root860d2702013-04-23 15:50:31 -07004283
4284 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
4285 if (ctx.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07004286 jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX");
Kenny Root860d2702013-04-23 15:50:31 -07004287 return 0;
4288 }
4289
Kenny Rootacc950a2014-03-26 13:55:26 -07004290 JNI_TRACE_MD("EVP_MD_CTX_create() => %p", ctx.get());
Kenny Root860d2702013-04-23 15:50:31 -07004291 return reinterpret_cast<uintptr_t>(ctx.release());
4292}
4293
Kenny Root652ff532014-02-24 12:35:11 -08004294static void NativeCrypto_EVP_MD_CTX_init(JNIEnv* env, jclass, jobject ctxRef) {
4295 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
Kenny Rootacc950a2014-03-26 13:55:26 -07004296 JNI_TRACE_MD("EVP_MD_CTX_init(%p)", ctx);
Kenny Root860d2702013-04-23 15:50:31 -07004297
4298 if (ctx != NULL) {
4299 EVP_MD_CTX_init(ctx);
4300 }
4301}
4302
Kenny Root4ccb72f2014-05-30 11:27:32 -07004303static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv*, jclass, jlong ctxRef) {
Kenny Root860d2702013-04-23 15:50:31 -07004304 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef);
Kenny Rootacc950a2014-03-26 13:55:26 -07004305 JNI_TRACE_MD("EVP_MD_CTX_destroy(%p)", ctx);
Kenny Root860d2702013-04-23 15:50:31 -07004306
4307 if (ctx != NULL) {
4308 EVP_MD_CTX_destroy(ctx);
4309 }
4310}
4311
Kenny Root652ff532014-02-24 12:35:11 -08004312static jint NativeCrypto_EVP_MD_CTX_copy(JNIEnv* env, jclass, jobject dstCtxRef, jobject srcCtxRef) {
Kenny Root8a77c202015-04-24 10:37:11 -07004313 JNI_TRACE_MD("EVP_MD_CTX_copy(%p. %p)", dstCtxRef, srcCtxRef);
Kenny Root652ff532014-02-24 12:35:11 -08004314 EVP_MD_CTX* dst_ctx = fromContextObject<EVP_MD_CTX>(env, dstCtxRef);
Kenny Root8a77c202015-04-24 10:37:11 -07004315 if (dst_ctx == NULL) {
4316 JNI_TRACE_MD("EVP_MD_CTX_copy => dst_ctx == NULL");
Kenny Root860d2702013-04-23 15:50:31 -07004317 return 0;
4318 }
Kenny Root8a77c202015-04-24 10:37:11 -07004319 const EVP_MD_CTX* src_ctx = fromContextObject<EVP_MD_CTX>(env, srcCtxRef);
4320 if (src_ctx == NULL) {
4321 JNI_TRACE_MD("EVP_MD_CTX_copy => src_ctx == NULL");
4322 return 0;
4323 }
4324 JNI_TRACE_MD("EVP_MD_CTX_copy(%p. %p) <- ptr", dst_ctx, src_ctx);
Kenny Root860d2702013-04-23 15:50:31 -07004325
Kenny Root652ff532014-02-24 12:35:11 -08004326 int result = EVP_MD_CTX_copy_ex(dst_ctx, src_ctx);
Kenny Root860d2702013-04-23 15:50:31 -07004327 if (result == 0) {
Kenny Root860d2702013-04-23 15:50:31 -07004328 jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX");
4329 freeOpenSslErrorState();
Kenny Root860d2702013-04-23 15:50:31 -07004330 }
4331
Kenny Rootacc950a2014-03-26 13:55:26 -07004332 JNI_TRACE_MD("EVP_MD_CTX_copy(%p, %p) => %d", dst_ctx, src_ctx, result);
Kenny Root652ff532014-02-24 12:35:11 -08004333 return result;
Kenny Root860d2702013-04-23 15:50:31 -07004334}
4335
4336/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004337 * public static native int EVP_DigestFinal(long, byte[], int)
Kenny Root860d2702013-04-23 15:50:31 -07004338 */
Kenny Root652ff532014-02-24 12:35:11 -08004339static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray hash,
4340 jint offset) {
4341 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
Kenny Rootacc950a2014-03-26 13:55:26 -07004342 JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset);
Kenny Root860d2702013-04-23 15:50:31 -07004343
Kenny Root652ff532014-02-24 12:35:11 -08004344 if (ctx == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004345 JNI_TRACE("EVP_DigestFinal => ctx == NULL");
Kenny Root652ff532014-02-24 12:35:11 -08004346 return -1;
4347 } else if (hash == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004348 jniThrowNullPointerException(env, "hash == null");
Kenny Root860d2702013-04-23 15:50:31 -07004349 return -1;
4350 }
4351
4352 ScopedByteArrayRW hashBytes(env, hash);
4353 if (hashBytes.get() == NULL) {
4354 return -1;
4355 }
4356 unsigned int bytesWritten = -1;
Kenny Root652ff532014-02-24 12:35:11 -08004357 int ok = EVP_DigestFinal_ex(ctx,
Kenny Root860d2702013-04-23 15:50:31 -07004358 reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
4359 &bytesWritten);
4360 if (ok == 0) {
Kenny Rootacc950a2014-03-26 13:55:26 -07004361 throwExceptionIfNecessary(env, "EVP_DigestFinal");
Kenny Root860d2702013-04-23 15:50:31 -07004362 }
Kenny Root860d2702013-04-23 15:50:31 -07004363
Kenny Root8a77c202015-04-24 10:37:11 -07004364 JNI_TRACE_MD("EVP_DigestFinal(%p, %p, %d) => %d (%d)", ctx, hash, offset, bytesWritten, ok);
Kenny Root860d2702013-04-23 15:50:31 -07004365 return bytesWritten;
4366}
4367
Kenny Root652ff532014-02-24 12:35:11 -08004368static jint evpInit(JNIEnv* env, jobject evpMdCtxRef, jlong evpMdRef, const char* jniName,
4369 int (*init_func)(EVP_MD_CTX*, const EVP_MD*, ENGINE*)) {
4370 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
Kenny Rootcaceea72013-12-06 13:45:03 -08004371 const EVP_MD* evp_md = reinterpret_cast<const EVP_MD*>(evpMdRef);
Kenny Rootacc950a2014-03-26 13:55:26 -07004372 JNI_TRACE_MD("%s(%p, %p)", jniName, ctx, evp_md);
Kenny Root860d2702013-04-23 15:50:31 -07004373
Kenny Root652ff532014-02-24 12:35:11 -08004374 if (ctx == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004375 JNI_TRACE("%s(%p) => ctx == NULL", jniName, evp_md);
Kenny Root652ff532014-02-24 12:35:11 -08004376 return 0;
4377 } else if (evp_md == NULL) {
4378 jniThrowNullPointerException(env, "evp_md == null");
Kenny Root860d2702013-04-23 15:50:31 -07004379 return 0;
4380 }
4381
Kenny Root652ff532014-02-24 12:35:11 -08004382 int ok = init_func(ctx, evp_md, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07004383 if (ok == 0) {
Kenny Root652ff532014-02-24 12:35:11 -08004384 bool exception = throwExceptionIfNecessary(env, jniName);
Kenny Root860d2702013-04-23 15:50:31 -07004385 if (exception) {
Kenny Root652ff532014-02-24 12:35:11 -08004386 JNI_TRACE("%s(%p) => threw exception", jniName, evp_md);
Kenny Root860d2702013-04-23 15:50:31 -07004387 return 0;
4388 }
4389 }
Kenny Rootacc950a2014-03-26 13:55:26 -07004390 JNI_TRACE_MD("%s(%p, %p) => %d", jniName, ctx, evp_md, ok);
Kenny Root652ff532014-02-24 12:35:11 -08004391 return ok;
4392}
4393
4394static jint NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4395 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_DigestInit", EVP_DigestInit_ex);
4396}
4397
4398static jint NativeCrypto_EVP_SignInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4399 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_SignInit", EVP_DigestInit_ex);
4400}
4401
4402static jint NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, jobject evpMdCtxRef, jlong evpMdRef) {
4403 return evpInit(env, evpMdCtxRef, evpMdRef, "EVP_VerifyInit", EVP_DigestInit_ex);
Kenny Root860d2702013-04-23 15:50:31 -07004404}
4405
4406/*
4407 * public static native int EVP_get_digestbyname(java.lang.String)
4408 */
4409static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) {
4410 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm);
4411
4412 if (algorithm == NULL) {
4413 jniThrowNullPointerException(env, NULL);
4414 return -1;
4415 }
4416
4417 ScopedUtfChars algorithmChars(env, algorithm);
4418 if (algorithmChars.c_str() == NULL) {
4419 return 0;
4420 }
4421 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str());
4422
Adam Langleyde5225d2014-10-06 15:55:30 -07004423#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07004424 const EVP_MD* evp_md = EVP_get_digestbyname(algorithmChars.c_str());
4425 if (evp_md == NULL) {
4426 jniThrowRuntimeException(env, "Hash algorithm not found");
4427 return 0;
4428 }
4429
4430 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => %p", algorithmChars.c_str(), evp_md);
4431 return reinterpret_cast<uintptr_t>(evp_md);
Adam Langleyde5225d2014-10-06 15:55:30 -07004432#else
4433 const char *alg = algorithmChars.c_str();
4434 const EVP_MD *md;
4435
4436 if (strcasecmp(alg, "md4") == 0) {
4437 md = EVP_md4();
4438 } else if (strcasecmp(alg, "md5") == 0) {
4439 md = EVP_md5();
4440 } else if (strcasecmp(alg, "sha1") == 0) {
4441 md = EVP_sha1();
4442 } else if (strcasecmp(alg, "sha224") == 0) {
4443 md = EVP_sha224();
4444 } else if (strcasecmp(alg, "sha256") == 0) {
4445 md = EVP_sha256();
4446 } else if (strcasecmp(alg, "sha384") == 0) {
4447 md = EVP_sha384();
4448 } else if (strcasecmp(alg, "sha512") == 0) {
4449 md = EVP_sha512();
4450 } else {
4451 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
4452 jniThrowRuntimeException(env, "Hash algorithm not found");
4453 return 0;
4454 }
4455
4456 return reinterpret_cast<uintptr_t>(md);
4457#endif
Kenny Root860d2702013-04-23 15:50:31 -07004458}
4459
4460/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004461 * public static native int EVP_MD_size(long)
Kenny Root860d2702013-04-23 15:50:31 -07004462 */
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004463static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jlong evpMdRef) {
Kenny Root860d2702013-04-23 15:50:31 -07004464 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
4465 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md);
4466
4467 if (evp_md == NULL) {
4468 jniThrowNullPointerException(env, NULL);
4469 return -1;
4470 }
4471
4472 int result = EVP_MD_size(evp_md);
4473 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result);
4474 return result;
4475}
4476
4477/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004478 * public static int void EVP_MD_block_size(long)
Kenny Root860d2702013-04-23 15:50:31 -07004479 */
4480static jint NativeCrypto_EVP_MD_block_size(JNIEnv* env, jclass, jlong evpMdRef) {
4481 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef);
4482 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p)", evp_md);
4483
4484 if (evp_md == NULL) {
4485 jniThrowNullPointerException(env, NULL);
4486 return -1;
4487 }
4488
4489 int result = EVP_MD_block_size(evp_md);
4490 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p) => %d", evp_md, result);
4491 return result;
4492}
4493
Kenny Root652ff532014-02-24 12:35:11 -08004494static void NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jobject evpMdCtxRef,
Kenny Root37e58bb2014-11-25 14:29:25 -08004495 const jlong evpMdRef, jobject pkeyRef) {
Kenny Root652ff532014-02-24 12:35:11 -08004496 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
Kenny Root8a77c202015-04-24 10:37:11 -07004497 if (mdCtx == NULL) {
4498 JNI_TRACE("EVP_DigestSignInit => mdCtx == NULL");
4499 return;
4500 }
Kenny Root860d2702013-04-23 15:50:31 -07004501 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef);
Kenny Root37e58bb2014-11-25 14:29:25 -08004502 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root8a77c202015-04-24 10:37:11 -07004503 if (pkey == NULL) {
4504 JNI_TRACE("ctx=%p EVP_DigestSignInit => pkey == NULL", mdCtx);
4505 return;
Kenny Root860d2702013-04-23 15:50:31 -07004506 }
Kenny Root8a77c202015-04-24 10:37:11 -07004507 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p) <- ptr", mdCtx, md, pkey);
Kenny Root860d2702013-04-23 15:50:31 -07004508
4509 if (md == NULL) {
Kenny Root8a77c202015-04-24 10:37:11 -07004510 JNI_TRACE("ctx=%p EVP_DigestSignInit => md == NULL", mdCtx);
4511 jniThrowNullPointerException(env, "md == null");
4512 return;
Kenny Root860d2702013-04-23 15:50:31 -07004513 }
4514
4515 if (EVP_DigestSignInit(mdCtx, (EVP_PKEY_CTX **) NULL, md, (ENGINE *) NULL, pkey) <= 0) {
4516 JNI_TRACE("ctx=%p EVP_DigestSignInit => threw exception", mdCtx);
4517 throwExceptionIfNecessary(env, "EVP_DigestSignInit");
4518 return;
4519 }
4520
4521 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p) => success", mdCtx, md, pkey);
4522}
4523
Kenny Root652ff532014-02-24 12:35:11 -08004524static void evpUpdate(JNIEnv* env, jobject evpMdCtxRef, jbyteArray inJavaBytes, jint inOffset,
4525 jint inLength, const char *jniName, int (*update_func)(EVP_MD_CTX*, const void *,
Kévin PETIT88758d42014-02-27 11:26:45 +00004526 size_t))
Kenny Root860d2702013-04-23 15:50:31 -07004527{
Kenny Root652ff532014-02-24 12:35:11 -08004528 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
Kenny Rootacc950a2014-03-26 13:55:26 -07004529 JNI_TRACE_MD("%s(%p, %p, %d, %d)", jniName, mdCtx, inJavaBytes, inOffset, inLength);
Kenny Root860d2702013-04-23 15:50:31 -07004530
4531 if (mdCtx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004532 return;
4533 }
4534
4535 ScopedByteArrayRO inBytes(env, inJavaBytes);
4536 if (inBytes.get() == NULL) {
4537 return;
4538 }
4539
4540 if (inOffset < 0 || size_t(inOffset) > inBytes.size()) {
Kenny Rootca852132014-02-24 14:13:32 -08004541 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inOffset");
Kenny Root860d2702013-04-23 15:50:31 -07004542 return;
4543 }
4544
4545 const ssize_t inEnd = inOffset + inLength;
Marcus Oakland3f8d6402014-05-14 13:32:50 +01004546 if (inLength < 0 || inEnd < 0 || size_t(inEnd) > inBytes.size()) {
Kenny Rootca852132014-02-24 14:13:32 -08004547 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "inLength");
Kenny Root860d2702013-04-23 15:50:31 -07004548 return;
4549 }
4550
4551 const unsigned char *tmp = reinterpret_cast<const unsigned char *>(inBytes.get());
Kenny Root652ff532014-02-24 12:35:11 -08004552 if (!update_func(mdCtx, tmp + inOffset, inLength)) {
4553 JNI_TRACE("ctx=%p %s => threw exception", mdCtx, jniName);
4554 throwExceptionIfNecessary(env, jniName);
Kenny Root860d2702013-04-23 15:50:31 -07004555 }
4556
Kenny Rootacc950a2014-03-26 13:55:26 -07004557 JNI_TRACE_MD("%s(%p, %p, %d, %d) => success", jniName, mdCtx, inJavaBytes, inOffset, inLength);
Kenny Root860d2702013-04-23 15:50:31 -07004558}
4559
Kenny Root652ff532014-02-24 12:35:11 -08004560static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4561 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4562 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestUpdate",
4563 EVP_DigestUpdate);
4564}
4565
4566static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4567 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4568 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_DigestSignUpdate",
4569 EVP_DigestUpdate);
4570}
4571
4572static void NativeCrypto_EVP_SignUpdate(JNIEnv* env, jclass, jobject evpMdCtxRef,
4573 jbyteArray inJavaBytes, jint inOffset, jint inLength) {
4574 evpUpdate(env, evpMdCtxRef, inJavaBytes, inOffset, inLength, "EVP_SignUpdate",
4575 EVP_DigestUpdate);
4576}
4577
4578static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jobject evpMdCtxRef)
Kenny Root860d2702013-04-23 15:50:31 -07004579{
Kenny Root652ff532014-02-24 12:35:11 -08004580 EVP_MD_CTX* mdCtx = fromContextObject<EVP_MD_CTX>(env, evpMdCtxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004581 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx);
4582
4583 if (mdCtx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004584 return NULL;
4585 }
4586
David Benjaminbca895f2014-07-10 18:12:08 -04004587 size_t len;
4588 if (EVP_DigestSignFinal(mdCtx, NULL, &len) != 1) {
4589 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
4590 throwExceptionIfNecessary(env, "EVP_DigestSignFinal");
4591 return 0;
4592 }
4593 ScopedLocalRef<jbyteArray> outJavaBytes(env, env->NewByteArray(len));
Kenny Root860d2702013-04-23 15:50:31 -07004594 if (outJavaBytes.get() == NULL) {
4595 return NULL;
4596 }
4597 ScopedByteArrayRW outBytes(env, outJavaBytes.get());
4598 if (outBytes.get() == NULL) {
4599 return NULL;
4600 }
4601 unsigned char *tmp = reinterpret_cast<unsigned char*>(outBytes.get());
David Benjaminbca895f2014-07-10 18:12:08 -04004602 if (EVP_DigestSignFinal(mdCtx, tmp, &len) != 1) {
Kenny Root860d2702013-04-23 15:50:31 -07004603 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx);
4604 throwExceptionIfNecessary(env, "EVP_DigestSignFinal");
4605 return 0;
4606 }
4607
Kenny Root860d2702013-04-23 15:50:31 -07004608 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, outJavaBytes.get());
4609 return outJavaBytes.release();
4610}
4611
Kenny Root860d2702013-04-23 15:50:31 -07004612/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004613 * public static native int EVP_SignFinal(long, byte[], int, long)
Kenny Root860d2702013-04-23 15:50:31 -07004614 */
Kenny Root652ff532014-02-24 12:35:11 -08004615static jint NativeCrypto_EVP_SignFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray signature,
Kenny Root37e58bb2014-11-25 14:29:25 -08004616 jint offset, jobject pkeyRef) {
Kenny Root8a77c202015-04-24 10:37:11 -07004617 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p)", ctxRef, signature, offset, pkeyRef);
Kenny Root652ff532014-02-24 12:35:11 -08004618 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
Kenny Root652ff532014-02-24 12:35:11 -08004619 if (ctx == NULL) {
4620 return -1;
Kenny Root8a77c202015-04-24 10:37:11 -07004621 }
4622 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4623 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p) <- ptr", ctx, signature, offset, pkey);
4624
4625 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004626 return -1;
4627 }
4628
4629 ScopedByteArrayRW signatureBytes(env, signature);
4630 if (signatureBytes.get() == NULL) {
4631 return -1;
4632 }
4633 unsigned int bytesWritten = -1;
4634 int ok = EVP_SignFinal(ctx,
4635 reinterpret_cast<unsigned char*>(signatureBytes.get() + offset),
4636 &bytesWritten,
4637 pkey);
Kenny Root1305c132015-05-29 19:33:40 -07004638 if (ok != 1) {
Kenny Root860d2702013-04-23 15:50:31 -07004639 throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignFinal");
4640 }
4641 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p) => %u",
4642 ctx, signature, offset, pkey, bytesWritten);
4643
4644 return bytesWritten;
4645}
4646
4647/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004648 * public static native void EVP_VerifyUpdate(long, byte[], int, int)
Kenny Root860d2702013-04-23 15:50:31 -07004649 */
Kenny Root652ff532014-02-24 12:35:11 -08004650static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, jobject ctxRef,
Kenny Root860d2702013-04-23 15:50:31 -07004651 jbyteArray buffer, jint offset, jint length) {
Kenny Root652ff532014-02-24 12:35:11 -08004652 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004653 JNI_TRACE("NativeCrypto_EVP_VerifyUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length);
4654
Kenny Root652ff532014-02-24 12:35:11 -08004655 if (ctx == NULL) {
4656 return;
4657 } else if (buffer == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004658 jniThrowNullPointerException(env, NULL);
4659 return;
4660 }
4661
Kenny Root652ff532014-02-24 12:35:11 -08004662 if (offset < 0 || length < 0) {
4663 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
4664 return;
4665 }
4666
Kenny Root860d2702013-04-23 15:50:31 -07004667 ScopedByteArrayRO bufferBytes(env, buffer);
4668 if (bufferBytes.get() == NULL) {
4669 return;
4670 }
Kenny Root652ff532014-02-24 12:35:11 -08004671 if (bufferBytes.size() < static_cast<size_t>(offset + length)) {
4672 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
4673 return;
4674 }
4675
Kenny Root860d2702013-04-23 15:50:31 -07004676 int ok = EVP_VerifyUpdate(ctx,
4677 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
4678 length);
4679 if (ok == 0) {
4680 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate");
4681 }
4682}
4683
4684/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004685 * public static native int EVP_VerifyFinal(long, byte[], int, int, long)
Kenny Root860d2702013-04-23 15:50:31 -07004686 */
Kenny Root652ff532014-02-24 12:35:11 -08004687static jint NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray buffer,
Kenny Root37e58bb2014-11-25 14:29:25 -08004688 jint offset, jint length, jobject pkeyRef) {
Kenny Root860d2702013-04-23 15:50:31 -07004689 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p)",
Kenny Root8a77c202015-04-24 10:37:11 -07004690 ctxRef, buffer, offset, length, pkeyRef);
4691 EVP_MD_CTX* ctx = fromContextObject<EVP_MD_CTX>(env, ctxRef);
Kenny Root652ff532014-02-24 12:35:11 -08004692 if (ctx == NULL) {
4693 return -1;
Kenny Root8a77c202015-04-24 10:37:11 -07004694 }
4695 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
4696 if (pkey == NULL) {
4697 return -1;
4698 }
4699 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) <- ptr",
4700 ctx, buffer, offset, length, pkey);
4701
4702 if (buffer == NULL) {
4703 jniThrowNullPointerException(env, "buffer == null");
Kenny Root860d2702013-04-23 15:50:31 -07004704 return -1;
4705 }
4706
4707 ScopedByteArrayRO bufferBytes(env, buffer);
4708 if (bufferBytes.get() == NULL) {
4709 return -1;
4710 }
Kenny Rootcecb4da2015-06-04 12:02:05 -07004711
Kenny Root860d2702013-04-23 15:50:31 -07004712 int ok = EVP_VerifyFinal(ctx,
4713 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
4714 length,
4715 pkey);
Kenny Rootcecb4da2015-06-04 12:02:05 -07004716 // The upper (Java language) layer should take care of throwing the
4717 // expected exceptions before calling to this, so we just clear
4718 // the OpenSSL/BoringSSL error stack here.
4719 freeOpenSslErrorState();
Kenny Root860d2702013-04-23 15:50:31 -07004720
Kenny Root860d2702013-04-23 15:50:31 -07004721 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) => %d",
4722 ctx, buffer, offset, length, pkey, ok);
4723
4724 return ok;
4725}
4726
4727static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) {
4728 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm);
Adam Langleyde5225d2014-10-06 15:55:30 -07004729
4730#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07004731 if (algorithm == NULL) {
4732 JNI_TRACE("EVP_get_cipherbyname(%p) => threw exception algorithm == null", algorithm);
4733 jniThrowNullPointerException(env, NULL);
4734 return -1;
4735 }
4736
4737 ScopedUtfChars algorithmChars(env, algorithm);
4738 if (algorithmChars.c_str() == NULL) {
4739 return 0;
4740 }
4741 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm = %s", algorithm, algorithmChars.c_str());
4742
4743 const EVP_CIPHER* evp_cipher = EVP_get_cipherbyname(algorithmChars.c_str());
4744 if (evp_cipher == NULL) {
4745 freeOpenSslErrorState();
4746 }
4747
4748 JNI_TRACE("EVP_get_cipherbyname(%s) => %p", algorithmChars.c_str(), evp_cipher);
4749 return reinterpret_cast<uintptr_t>(evp_cipher);
Adam Langleyde5225d2014-10-06 15:55:30 -07004750#else
4751 ScopedUtfChars scoped_alg(env, algorithm);
4752 const char *alg = scoped_alg.c_str();
4753 const EVP_CIPHER *cipher;
4754
4755 if (strcasecmp(alg, "rc4") == 0) {
4756 cipher = EVP_rc4();
4757 } else if (strcasecmp(alg, "des-cbc") == 0) {
4758 cipher = EVP_des_cbc();
Adam Langley6ae71b62015-04-23 14:29:23 -07004759 } else if (strcasecmp(alg, "des-ede-cbc") == 0) {
Kenny Rootb839f312016-08-25 12:08:18 -07004760 cipher = EVP_des_ede_cbc();
Adam Langleyde5225d2014-10-06 15:55:30 -07004761 } else if (strcasecmp(alg, "des-ede3-cbc") == 0) {
4762 cipher = EVP_des_ede3_cbc();
4763 } else if (strcasecmp(alg, "aes-128-ecb") == 0) {
4764 cipher = EVP_aes_128_ecb();
4765 } else if (strcasecmp(alg, "aes-128-cbc") == 0) {
4766 cipher = EVP_aes_128_cbc();
4767 } else if (strcasecmp(alg, "aes-128-ctr") == 0) {
4768 cipher = EVP_aes_128_ctr();
4769 } else if (strcasecmp(alg, "aes-128-gcm") == 0) {
4770 cipher = EVP_aes_128_gcm();
Adam Langley34160c52015-04-21 17:25:00 -07004771 } else if (strcasecmp(alg, "aes-192-ecb") == 0) {
4772 cipher = EVP_aes_192_ecb();
4773 } else if (strcasecmp(alg, "aes-192-cbc") == 0) {
4774 cipher = EVP_aes_192_cbc();
4775 } else if (strcasecmp(alg, "aes-192-ctr") == 0) {
4776 cipher = EVP_aes_192_ctr();
4777 } else if (strcasecmp(alg, "aes-192-gcm") == 0) {
4778 cipher = EVP_aes_192_gcm();
Adam Langleyde5225d2014-10-06 15:55:30 -07004779 } else if (strcasecmp(alg, "aes-256-ecb") == 0) {
4780 cipher = EVP_aes_256_ecb();
4781 } else if (strcasecmp(alg, "aes-256-cbc") == 0) {
4782 cipher = EVP_aes_256_cbc();
4783 } else if (strcasecmp(alg, "aes-256-ctr") == 0) {
4784 cipher = EVP_aes_256_ctr();
4785 } else if (strcasecmp(alg, "aes-256-gcm") == 0) {
4786 cipher = EVP_aes_256_gcm();
4787 } else {
4788 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => error", alg);
Adam Langleyde5225d2014-10-06 15:55:30 -07004789 return 0;
4790 }
4791
4792 return reinterpret_cast<uintptr_t>(cipher);
4793#endif
Kenny Root860d2702013-04-23 15:50:31 -07004794}
4795
Kenny Root4757cdb2014-11-26 07:59:41 -08004796static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef, jlong evpCipherRef,
Kenny Root860d2702013-04-23 15:50:31 -07004797 jbyteArray keyArray, jbyteArray ivArray, jboolean encrypting) {
Kenny Root4757cdb2014-11-26 07:59:41 -08004798 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004799 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
4800 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray,
4801 encrypting ? 1 : 0);
4802
4803 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004804 JNI_TRACE("EVP_CipherUpdate => ctx == null");
4805 return;
4806 }
4807
4808 // The key can be null if we need to set extra parameters.
4809 UniquePtr<unsigned char[]> keyPtr;
4810 if (keyArray != NULL) {
4811 ScopedByteArrayRO keyBytes(env, keyArray);
4812 if (keyBytes.get() == NULL) {
4813 return;
4814 }
4815
4816 keyPtr.reset(new unsigned char[keyBytes.size()]);
4817 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size());
4818 }
4819
4820 // The IV can be null if we're using ECB.
4821 UniquePtr<unsigned char[]> ivPtr;
4822 if (ivArray != NULL) {
4823 ScopedByteArrayRO ivBytes(env, ivArray);
4824 if (ivBytes.get() == NULL) {
4825 return;
4826 }
4827
4828 ivPtr.reset(new unsigned char[ivBytes.size()]);
4829 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size());
4830 }
4831
4832 if (!EVP_CipherInit_ex(ctx, evpCipher, NULL, keyPtr.get(), ivPtr.get(), encrypting ? 1 : 0)) {
4833 throwExceptionIfNecessary(env, "EVP_CipherInit_ex");
4834 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher");
4835 return;
4836 }
4837
4838 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray,
4839 encrypting ? 1 : 0);
4840}
4841
4842/*
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00004843 * public static native int EVP_CipherUpdate(long ctx, byte[] out, int outOffset, byte[] in,
4844 * int inOffset, int inLength);
Kenny Root860d2702013-04-23 15:50:31 -07004845 */
Kenny Root4757cdb2014-11-26 07:59:41 -08004846static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
Kenny Root860d2702013-04-23 15:50:31 -07004847 jint outOffset, jbyteArray inArray, jint inOffset, jint inLength) {
Kenny Root4757cdb2014-11-26 07:59:41 -08004848 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004849 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset);
4850
4851 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004852 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx);
4853 return 0;
4854 }
4855
4856 ScopedByteArrayRO inBytes(env, inArray);
4857 if (inBytes.get() == NULL) {
4858 return 0;
4859 }
4860 const size_t inSize = inBytes.size();
4861 if (size_t(inOffset + inLength) > inSize) {
Kenny Rootca852132014-02-24 14:13:32 -08004862 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
Kenny Root860d2702013-04-23 15:50:31 -07004863 "in.length < (inSize + inOffset)");
4864 return 0;
4865 }
4866
4867 ScopedByteArrayRW outBytes(env, outArray);
4868 if (outBytes.get() == NULL) {
4869 return 0;
4870 }
4871 const size_t outSize = outBytes.size();
4872 if (size_t(outOffset + inLength) > outSize) {
Kenny Rootca852132014-02-24 14:13:32 -08004873 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
Kenny Root860d2702013-04-23 15:50:31 -07004874 "out.length < inSize + outOffset + blockSize - 1");
4875 return 0;
4876 }
4877
Kenny Root6c523c02014-11-25 13:33:51 -08004878 JNI_TRACE("ctx=%p EVP_CipherUpdate in=%p in.length=%zd inOffset=%zd inLength=%zd out=%p out.length=%zd outOffset=%zd",
Kenny Root860d2702013-04-23 15:50:31 -07004879 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(), outOffset);
4880
4881 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
4882 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get());
4883
4884 int outl;
4885 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) {
4886 throwExceptionIfNecessary(env, "EVP_CipherUpdate");
4887 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx);
4888 return 0;
4889 }
4890
4891 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray,
4892 inOffset, outl);
4893 return outl;
4894}
4895
Kenny Root4757cdb2014-11-26 07:59:41 -08004896static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jobject ctxRef,
4897 jbyteArray outArray, jint outOffset) {
4898 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004899 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset);
4900
4901 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004902 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx);
4903 return 0;
4904 }
4905
4906 ScopedByteArrayRW outBytes(env, outArray);
4907 if (outBytes.get() == NULL) {
4908 return 0;
4909 }
4910
4911 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get());
4912
4913 int outl;
4914 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) {
Kenny Root058faf12014-12-08 14:12:20 -08004915 if (throwExceptionIfNecessary(env, "EVP_CipherFinal_ex")) {
4916 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx);
4917 } else {
4918 throwBadPaddingException(env, "EVP_CipherFinal_ex");
4919 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw padding exception", ctx);
4920 }
Kenny Root860d2702013-04-23 15:50:31 -07004921 return 0;
4922 }
4923
4924 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl);
4925 return outl;
4926}
4927
4928static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) {
4929 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef);
4930 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher);
4931
4932 if (evpCipher == NULL) {
4933 jniThrowNullPointerException(env, "evpCipher == null");
4934 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null");
4935 return 0;
4936 }
4937
4938 const int ivLength = EVP_CIPHER_iv_length(evpCipher);
4939 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength);
4940 return ivLength;
4941}
4942
4943static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) {
4944 JNI_TRACE("EVP_CIPHER_CTX_new()");
4945
4946 Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
4947 if (ctx.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07004948 jniThrowOutOfMemory(env, "Unable to allocate cipher context");
Kenny Root860d2702013-04-23 15:50:31 -07004949 JNI_TRACE("EVP_CipherInit_ex => context allocation error");
4950 return 0;
4951 }
4952
4953 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get());
4954 return reinterpret_cast<uintptr_t>(ctx.release());
4955}
4956
Kenny Root4757cdb2014-11-26 07:59:41 -08004957static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jobject ctxRef) {
4958 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004959 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx);
4960
4961 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004962 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx);
4963 return 0;
4964 }
4965
4966 int blockSize = EVP_CIPHER_CTX_block_size(ctx);
4967 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize);
4968 return blockSize;
4969}
4970
Kenny Root4757cdb2014-11-26 07:59:41 -08004971static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jobject ctxRef) {
4972 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07004973 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx);
4974
4975 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07004976 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx);
4977 return 0;
4978 }
4979
4980 int buf_len = ctx->buf_len;
4981 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len);
4982 return buf_len;
4983}
4984
Sergio Giro1127c192015-06-08 11:36:14 +01004985static jboolean NativeCrypto_get_EVP_CIPHER_CTX_final_used(JNIEnv* env, jclass, jobject ctxRef) {
4986 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
4987 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p)", ctx);
4988
4989 if (ctx == NULL) {
4990 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_final_used => ctx == null", ctx);
4991 return 0;
4992 }
4993
4994 bool final_used = ctx->final_used != 0;
4995 JNI_TRACE("get_EVP_CIPHER_CTX_final_used(%p) => %d", ctx, final_used);
4996 return final_used;
4997}
4998
Kenny Root4757cdb2014-11-26 07:59:41 -08004999static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jobject ctxRef,
5000 jboolean enablePaddingBool) {
5001 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root860d2702013-04-23 15:50:31 -07005002 jint enablePadding = enablePaddingBool ? 1 : 0;
5003 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding);
5004
5005 if (ctx == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07005006 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx);
5007 return;
5008 }
5009
Elliott Hughesfb822ae2013-08-19 15:45:20 -07005010 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
Kenny Root860d2702013-04-23 15:50:31 -07005011 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
5012}
5013
Kenny Root4757cdb2014-11-26 07:59:41 -08005014static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jobject ctxRef,
Kenny Root153fd442014-11-26 08:03:42 -08005015 jint keySizeBits) {
Kenny Root4757cdb2014-11-26 07:59:41 -08005016 EVP_CIPHER_CTX* ctx = fromContextObject<EVP_CIPHER_CTX>(env, ctxRef);
Kenny Root153fd442014-11-26 08:03:42 -08005017 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits);
5018
5019 if (ctx == NULL) {
Kenny Root153fd442014-11-26 08:03:42 -08005020 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx);
5021 return;
5022 }
5023
5024 if (!EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits)) {
5025 throwExceptionIfNecessary(env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
5026 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
5027 return;
5028 }
5029 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
5030}
5031
Narayan Kamathb578b392014-12-10 14:58:44 +00005032static void NativeCrypto_EVP_CIPHER_CTX_free(JNIEnv*, jclass, jlong ctxRef) {
Kenny Root860d2702013-04-23 15:50:31 -07005033 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
Narayan Kamathb578b392014-12-10 14:58:44 +00005034 JNI_TRACE("EVP_CIPHER_CTX_free(%p)", ctx);
Kenny Root860d2702013-04-23 15:50:31 -07005035
Narayan Kamathb578b392014-12-10 14:58:44 +00005036 EVP_CIPHER_CTX_free(ctx);
Kenny Root860d2702013-04-23 15:50:31 -07005037}
5038
Kenny Root7c0a4c82015-05-12 16:50:19 -07005039static jlong NativeCrypto_EVP_aead_aes_128_gcm(JNIEnv* env, jclass) {
Kenny Rootf6f66202015-05-08 14:01:56 -07005040#if defined(OPENSSL_IS_BORINGSSL)
Kenny Root7c0a4c82015-05-12 16:50:19 -07005041 UNUSED_ARGUMENT(env);
Kenny Rootf6f66202015-05-08 14:01:56 -07005042 const EVP_AEAD* ctx = EVP_aead_aes_128_gcm();
5043 JNI_TRACE("EVP_aead_aes_128_gcm => ctx=%p", ctx);
5044 return reinterpret_cast<jlong>(ctx);
5045#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005046 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005047 return 0;
5048#endif
5049}
5050
Kenny Root7c0a4c82015-05-12 16:50:19 -07005051static jlong NativeCrypto_EVP_aead_aes_256_gcm(JNIEnv* env, jclass) {
Kenny Rootf6f66202015-05-08 14:01:56 -07005052#if defined(OPENSSL_IS_BORINGSSL)
Kenny Root7c0a4c82015-05-12 16:50:19 -07005053 UNUSED_ARGUMENT(env);
Kenny Rootf6f66202015-05-08 14:01:56 -07005054 const EVP_AEAD* ctx = EVP_aead_aes_256_gcm();
5055 JNI_TRACE("EVP_aead_aes_256_gcm => ctx=%p", ctx);
5056 return reinterpret_cast<jlong>(ctx);
5057#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005058 jniThrowRuntimeException(env, "Not supported for OpenSSL");
5059 return 0;
Kenny Rootf6f66202015-05-08 14:01:56 -07005060#endif
5061}
5062
5063static jlong NativeCrypto_EVP_AEAD_CTX_init(JNIEnv* env, jclass, jlong evpAeadRef,
5064 jbyteArray keyArray, jint tagLen) {
5065#if defined(OPENSSL_IS_BORINGSSL)
5066 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
5067 JNI_TRACE("EVP_AEAD_CTX_init(%p, %p, %d)", evpAead, keyArray, tagLen);
5068
5069 ScopedByteArrayRO keyBytes(env, keyArray);
5070 if (keyBytes.get() == NULL) {
5071 return 0;
5072 }
5073
5074 Unique_EVP_AEAD_CTX aeadCtx(reinterpret_cast<EVP_AEAD_CTX*>(
5075 OPENSSL_malloc(sizeof(EVP_AEAD_CTX))));
5076 memset(aeadCtx.get(), 0, sizeof(EVP_AEAD_CTX));
5077
5078 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(keyBytes.get());
5079 int ret = EVP_AEAD_CTX_init(aeadCtx.get(), evpAead, tmp, keyBytes.size(), tagLen, NULL);
5080 if (ret != 1) {
5081 throwExceptionIfNecessary(env, "EVP_AEAD_CTX_init");
5082 JNI_TRACE("EVP_AEAD_CTX_init(%p, %p, %d) => fail EVP_AEAD_CTX_init", evpAead,
5083 keyArray, tagLen);
5084 return 0;
5085 }
5086
5087 JNI_TRACE("EVP_AEAD_CTX_init(%p, %p, %d) => %p", evpAead, keyArray, tagLen, aeadCtx.get());
5088 return reinterpret_cast<jlong>(aeadCtx.release());
5089#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005090 UNUSED_ARGUMENT(env);
5091 UNUSED_ARGUMENT(evpAeadRef);
5092 UNUSED_ARGUMENT(keyArray);
5093 UNUSED_ARGUMENT(tagLen);
5094 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005095 return 0;
5096#endif
5097}
5098
5099static void NativeCrypto_EVP_AEAD_CTX_cleanup(JNIEnv* env, jclass, jlong evpAeadCtxRef) {
5100#if defined(OPENSSL_IS_BORINGSSL)
5101 EVP_AEAD_CTX* evpAeadCtx = reinterpret_cast<EVP_AEAD_CTX*>(evpAeadCtxRef);
5102 JNI_TRACE("EVP_AEAD_CTX_cleanup(%p)", evpAeadCtx);
5103 if (evpAeadCtx == NULL) {
5104 jniThrowNullPointerException(env, "evpAead == null");
5105 return;
5106 }
5107
5108 EVP_AEAD_CTX_cleanup(evpAeadCtx);
5109 OPENSSL_free(evpAeadCtx);
5110#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005111 UNUSED_ARGUMENT(env);
5112 UNUSED_ARGUMENT(evpAeadCtxRef);
5113 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005114#endif
5115}
5116
5117static jint NativeCrypto_EVP_AEAD_max_overhead(JNIEnv* env, jclass, jlong evpAeadRef) {
5118#if defined(OPENSSL_IS_BORINGSSL)
5119 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
5120 JNI_TRACE("EVP_AEAD_max_overhead(%p)", evpAead);
5121 if (evpAead == NULL) {
5122 jniThrowNullPointerException(env, "evpAead == null");
5123 return 0;
5124 }
5125 int maxOverhead = EVP_AEAD_max_overhead(evpAead);
5126 JNI_TRACE("EVP_AEAD_max_overhead(%p) => %d", evpAead, maxOverhead);
5127 return maxOverhead;
5128#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005129 UNUSED_ARGUMENT(env);
5130 UNUSED_ARGUMENT(evpAeadRef);
5131 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005132 return 0;
5133#endif
5134}
5135
5136static jint NativeCrypto_EVP_AEAD_nonce_length(JNIEnv* env, jclass, jlong evpAeadRef) {
5137#if defined(OPENSSL_IS_BORINGSSL)
5138 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
5139 JNI_TRACE("EVP_AEAD_nonce_length(%p)", evpAead);
5140 if (evpAead == NULL) {
5141 jniThrowNullPointerException(env, "evpAead == null");
5142 return 0;
5143 }
5144 int nonceLength = EVP_AEAD_nonce_length(evpAead);
5145 JNI_TRACE("EVP_AEAD_nonce_length(%p) => %d", evpAead, nonceLength);
5146 return nonceLength;
5147#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005148 UNUSED_ARGUMENT(env);
5149 UNUSED_ARGUMENT(evpAeadRef);
5150 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005151 return 0;
5152#endif
5153}
5154
5155static jint NativeCrypto_EVP_AEAD_max_tag_len(JNIEnv* env, jclass, jlong evpAeadRef) {
5156#if defined(OPENSSL_IS_BORINGSSL)
5157 const EVP_AEAD* evpAead = reinterpret_cast<const EVP_AEAD*>(evpAeadRef);
5158 JNI_TRACE("EVP_AEAD_max_tag_len(%p)", evpAead);
5159 if (evpAead == NULL) {
5160 jniThrowNullPointerException(env, "evpAead == null");
5161 return 0;
5162 }
5163 int maxTagLen = EVP_AEAD_max_tag_len(evpAead);
5164 JNI_TRACE("EVP_AEAD_max_tag_len(%p) => %d", evpAead, maxTagLen);
5165 return maxTagLen;
5166#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005167 UNUSED_ARGUMENT(env);
5168 UNUSED_ARGUMENT(evpAeadRef);
5169 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005170 return 0;
5171#endif
5172}
5173
5174#if defined(OPENSSL_IS_BORINGSSL)
5175typedef int (*evp_aead_ctx_op_func)(const EVP_AEAD_CTX *ctx, uint8_t *out,
5176 size_t *out_len, size_t max_out_len,
5177 const uint8_t *nonce, size_t nonce_len,
5178 const uint8_t *in, size_t in_len,
5179 const uint8_t *ad, size_t ad_len);
5180
5181static jint evp_aead_ctx_op(JNIEnv* env, jobject ctxRef, jbyteArray outArray, jint outOffset,
5182 jbyteArray nonceArray, jbyteArray inArray, jint inOffset, jint inLength,
5183 jbyteArray aadArray, evp_aead_ctx_op_func realFunc) {
5184 EVP_AEAD_CTX* ctx = fromContextObject<EVP_AEAD_CTX>(env, ctxRef);
5185 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %d, %d, %p)", ctx, outArray, outOffset,
5186 nonceArray, inArray, inOffset, inLength, aadArray);
5187
5188 ScopedByteArrayRW outBytes(env, outArray);
5189 if (outBytes.get() == NULL) {
5190 return 0;
5191 }
5192
5193 if (ARRAY_OFFSET_INVALID(outBytes, outOffset)) {
Kenny Root203afd82015-05-18 16:36:23 -07005194 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %d, %d, %p)", ctx, outArray, outOffset,
5195 nonceArray, inArray, inOffset, inLength, aadArray);
Kenny Rootf6f66202015-05-08 14:01:56 -07005196 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "out");
5197 return 0;
5198 }
5199
5200 ScopedByteArrayRO inBytes(env, inArray);
5201 if (inBytes.get() == NULL) {
5202 return 0;
5203 }
5204
5205 if (ARRAY_OFFSET_LENGTH_INVALID(inBytes, inOffset, inLength)) {
Kenny Root203afd82015-05-18 16:36:23 -07005206 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %d, %d, %p)", ctx, outArray, outOffset,
5207 nonceArray, inArray, inOffset, inLength, aadArray);
Kenny Rootf6f66202015-05-08 14:01:56 -07005208 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "in");
5209 return 0;
5210 }
5211
5212 UniquePtr<ScopedByteArrayRO> aad;
5213 const uint8_t* aad_chars = NULL;
5214 size_t aad_chars_size = 0;
5215 if (aadArray != NULL) {
5216 aad.reset(new ScopedByteArrayRO(env, aadArray));
5217 aad_chars = reinterpret_cast<const uint8_t*>(aad->get());
5218 if (aad_chars == NULL) {
5219 return 0;
5220 }
5221 aad_chars_size = aad->size();
5222 }
5223
5224 ScopedByteArrayRO nonceBytes(env, nonceArray);
5225 if (nonceBytes.get() == NULL) {
5226 return 0;
5227 }
5228
5229 uint8_t* outTmp = reinterpret_cast<uint8_t*>(outBytes.get());
5230 const uint8_t* inTmp = reinterpret_cast<const uint8_t*>(inBytes.get());
5231 const uint8_t* nonceTmp = reinterpret_cast<const uint8_t*>(nonceBytes.get());
5232 size_t actualOutLength;
5233 int ret = realFunc(ctx, outTmp + outOffset, &actualOutLength, outBytes.size() - outOffset,
5234 nonceTmp, nonceBytes.size(), inTmp + inOffset, inLength, aad_chars, aad_chars_size);
5235 if (ret != 1) {
5236 throwExceptionIfNecessary(env, "evp_aead_ctx_op");
5237 }
5238
5239 JNI_TRACE("evp_aead_ctx_op(%p, %p, %d, %p, %p, %d, %d, %p) => ret=%d, outLength=%zd",
5240 ctx, outArray, outOffset, nonceArray, inArray, inOffset, inLength, aadArray, ret,
5241 actualOutLength);
5242 return static_cast<jlong>(actualOutLength);
5243}
5244#endif
5245
5246static jint NativeCrypto_EVP_AEAD_CTX_seal(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
5247 jint outOffset, jbyteArray nonceArray, jbyteArray inArray, jint inOffset, jint inLength,
5248 jbyteArray aadArray) {
5249#if defined(OPENSSL_IS_BORINGSSL)
5250 return evp_aead_ctx_op(env, ctxRef, outArray, outOffset, nonceArray, inArray, inOffset,
5251 inLength, aadArray, EVP_AEAD_CTX_seal);
5252#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005253 UNUSED_ARGUMENT(env);
5254 UNUSED_ARGUMENT(ctxRef);
5255 UNUSED_ARGUMENT(outArray);
5256 UNUSED_ARGUMENT(outOffset);
5257 UNUSED_ARGUMENT(nonceArray);
5258 UNUSED_ARGUMENT(inArray);
5259 UNUSED_ARGUMENT(inOffset);
5260 UNUSED_ARGUMENT(inLength);
5261 UNUSED_ARGUMENT(aadArray);
5262 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005263 return 0;
5264#endif
5265}
5266
5267static jint NativeCrypto_EVP_AEAD_CTX_open(JNIEnv* env, jclass, jobject ctxRef, jbyteArray outArray,
5268 jint outOffset, jbyteArray nonceArray, jbyteArray inArray, jint inOffset, jint inLength,
5269 jbyteArray aadArray) {
5270#if defined(OPENSSL_IS_BORINGSSL)
5271 return evp_aead_ctx_op(env, ctxRef, outArray, outOffset, nonceArray, inArray, inOffset,
5272 inLength, aadArray, EVP_AEAD_CTX_open);
5273#else
Kenny Root7c0a4c82015-05-12 16:50:19 -07005274 UNUSED_ARGUMENT(env);
5275 UNUSED_ARGUMENT(ctxRef);
5276 UNUSED_ARGUMENT(outArray);
5277 UNUSED_ARGUMENT(outOffset);
5278 UNUSED_ARGUMENT(nonceArray);
5279 UNUSED_ARGUMENT(inArray);
5280 UNUSED_ARGUMENT(inOffset);
5281 UNUSED_ARGUMENT(inLength);
5282 UNUSED_ARGUMENT(aadArray);
5283 jniThrowRuntimeException(env, "Not supported for OpenSSL");
Kenny Rootf6f66202015-05-08 14:01:56 -07005284 return 0;
5285#endif
5286}
5287
Kenny Root860d2702013-04-23 15:50:31 -07005288/**
5289 * public static native void RAND_seed(byte[]);
5290 */
Adam Langleyca341142014-12-11 17:26:18 -08005291#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07005292static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) {
Kenny Root4f81d312014-11-19 13:02:24 -08005293 JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed);
Kenny Root4f81d312014-11-19 13:02:24 -08005294 ScopedByteArrayRO randseed(env, seed);
5295 if (randseed.get() == NULL) {
5296 return;
5297 }
5298 RAND_seed(randseed.get(), randseed.size());
Kenny Root860d2702013-04-23 15:50:31 -07005299}
Adam Langleyca341142014-12-11 17:26:18 -08005300#else
5301static void NativeCrypto_RAND_seed(JNIEnv*, jclass, jbyteArray) {
5302}
5303#endif
Kenny Root860d2702013-04-23 15:50:31 -07005304
5305static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) {
Kenny Root6c523c02014-11-25 13:33:51 -08005306 JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, (long long) max_bytes);
Kenny Root4f81d312014-11-19 13:02:24 -08005307#if !defined(OPENSSL_IS_BORINGSSL)
5308 ScopedUtfChars file(env, filename);
5309 if (file.c_str() == NULL) {
5310 return -1;
5311 }
5312 int result = RAND_load_file(file.c_str(), max_bytes);
5313 JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result);
5314 return result;
5315#else
Adam Langleyca341142014-12-11 17:26:18 -08005316 UNUSED_ARGUMENT(env);
5317 UNUSED_ARGUMENT(filename);
Kenny Root4f81d312014-11-19 13:02:24 -08005318 // OpenSSLRandom calls this and checks the return value.
5319 return static_cast<jint>(max_bytes);
5320#endif
Kenny Root860d2702013-04-23 15:50:31 -07005321}
5322
5323static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) {
5324 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output);
5325
5326 ScopedByteArrayRW outputBytes(env, output);
5327 if (outputBytes.get() == NULL) {
5328 return;
5329 }
5330
5331 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
Elliott Hughesfb822ae2013-08-19 15:45:20 -07005332 if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
Kenny Root860d2702013-04-23 15:50:31 -07005333 throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes");
5334 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
5335 return;
5336 }
5337
5338 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output);
5339}
5340
5341static jint NativeCrypto_OBJ_txt2nid(JNIEnv* env, jclass, jstring oidStr) {
5342 JNI_TRACE("OBJ_txt2nid(%p)", oidStr);
5343
5344 ScopedUtfChars oid(env, oidStr);
5345 if (oid.c_str() == NULL) {
5346 return 0;
5347 }
5348
5349 int nid = OBJ_txt2nid(oid.c_str());
5350 JNI_TRACE("OBJ_txt2nid(%s) => %d", oid.c_str(), nid);
5351 return nid;
5352}
5353
5354static jstring NativeCrypto_OBJ_txt2nid_longName(JNIEnv* env, jclass, jstring oidStr) {
5355 JNI_TRACE("OBJ_txt2nid_longName(%p)", oidStr);
5356
5357 ScopedUtfChars oid(env, oidStr);
5358 if (oid.c_str() == NULL) {
5359 return NULL;
5360 }
5361
5362 JNI_TRACE("OBJ_txt2nid_longName(%s)", oid.c_str());
5363
5364 int nid = OBJ_txt2nid(oid.c_str());
5365 if (nid == NID_undef) {
5366 JNI_TRACE("OBJ_txt2nid_longName(%s) => NID_undef", oid.c_str());
5367 freeOpenSslErrorState();
5368 return NULL;
5369 }
5370
5371 const char* longName = OBJ_nid2ln(nid);
5372 JNI_TRACE("OBJ_txt2nid_longName(%s) => %s", oid.c_str(), longName);
5373 return env->NewStringUTF(longName);
5374}
5375
Adam Langleyde5225d2014-10-06 15:55:30 -07005376static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
Kenny Root860d2702013-04-23 15:50:31 -07005377 /*
5378 * The OBJ_obj2txt API doesn't "measure" if you pass in NULL as the buffer.
5379 * Just make a buffer that's large enough here. The documentation recommends
5380 * 80 characters.
5381 */
5382 char output[128];
5383 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1);
5384 if (ret < 0) {
5385 throwExceptionIfNecessary(env, "ASN1_OBJECT_to_OID_string");
5386 return NULL;
5387 } else if (size_t(ret) >= sizeof(output)) {
5388 jniThrowRuntimeException(env, "ASN1_OBJECT_to_OID_string buffer too small");
5389 return NULL;
5390 }
5391
5392 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output);
5393 return env->NewStringUTF(output);
5394}
5395
Adam Langleyd82dc062015-05-18 17:29:43 -07005396static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass,
5397 jobject streamObj,
5398 jboolean isFinite) {
Kenny Root860d2702013-04-23 15:50:31 -07005399 JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
5400
5401 if (streamObj == NULL) {
5402 jniThrowNullPointerException(env, "stream == null");
5403 return 0;
5404 }
5405
5406 Unique_BIO bio(BIO_new(&stream_bio_method));
5407 if (bio.get() == NULL) {
5408 return 0;
5409 }
5410
Adam Langleyd82dc062015-05-18 17:29:43 -07005411 bio_stream_assign(bio.get(), new BIO_InputStream(streamObj, isFinite));
Kenny Root860d2702013-04-23 15:50:31 -07005412
5413 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
5414 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
5415}
5416
5417static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) {
5418 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj);
5419
5420 if (streamObj == NULL) {
5421 jniThrowNullPointerException(env, "stream == null");
5422 return 0;
5423 }
5424
5425 Unique_BIO bio(BIO_new(&stream_bio_method));
5426 if (bio.get() == NULL) {
5427 return 0;
5428 }
5429
5430 bio_stream_assign(bio.get(), new BIO_OutputStream(streamObj));
5431
5432 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get());
5433 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
5434}
5435
5436static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
5437 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5438 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes);
5439
5440 if (outputJavaBytes == NULL) {
5441 jniThrowNullPointerException(env, "output == null");
5442 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes);
5443 return 0;
5444 }
5445
5446 int outputSize = env->GetArrayLength(outputJavaBytes);
5447
5448 UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
5449 if (buffer.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07005450 jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
Kenny Root860d2702013-04-23 15:50:31 -07005451 return 0;
5452 }
5453
5454 int read = BIO_read(bio, buffer.get(), outputSize);
5455 if (read <= 0) {
5456 jniThrowException(env, "java/io/IOException", "BIO_read");
5457 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes);
5458 return 0;
5459 }
5460
5461 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get()));
5462 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read);
5463 return read;
5464}
5465
5466static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes,
5467 jint offset, jint length) {
5468 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
5469 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length);
5470
5471 if (inputJavaBytes == NULL) {
5472 jniThrowNullPointerException(env, "input == null");
5473 return;
5474 }
5475
5476 if (offset < 0 || length < 0) {
Kenny Rootca852132014-02-24 14:13:32 -08005477 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", "offset < 0 || length < 0");
Kenny Root860d2702013-04-23 15:50:31 -07005478 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
5479 return;
5480 }
5481
5482 int inputSize = env->GetArrayLength(inputJavaBytes);
5483 if (inputSize < offset + length) {
Kenny Rootca852132014-02-24 14:13:32 -08005484 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException",
Kenny Root860d2702013-04-23 15:50:31 -07005485 "input.length < offset + length");
5486 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length);
5487 return;
5488 }
5489
5490 UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
5491 if (buffer.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07005492 jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
Kenny Root860d2702013-04-23 15:50:31 -07005493 return;
5494 }
5495
5496 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
Elliott Hughesfb822ae2013-08-19 15:45:20 -07005497 if (BIO_write(bio, buffer.get(), length) != length) {
Kenny Root860d2702013-04-23 15:50:31 -07005498 freeOpenSslErrorState();
5499 jniThrowException(env, "java/io/IOException", "BIO_write");
5500 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
5501 return;
5502 }
5503
5504 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length);
5505}
5506
Kenny Root19fdf1a2014-04-10 11:45:19 -07005507static void NativeCrypto_BIO_free_all(JNIEnv* env, jclass, jlong bioRef) {
Kenny Root860d2702013-04-23 15:50:31 -07005508 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
Kenny Root19fdf1a2014-04-10 11:45:19 -07005509 JNI_TRACE("BIO_free_all(%p)", bio);
Kenny Root860d2702013-04-23 15:50:31 -07005510
5511 if (bio == NULL) {
5512 jniThrowNullPointerException(env, "bio == null");
5513 return;
5514 }
5515
Kenny Root19fdf1a2014-04-10 11:45:19 -07005516 BIO_free_all(bio);
Kenny Root860d2702013-04-23 15:50:31 -07005517}
5518
5519static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) {
5520 JNI_TRACE("X509_NAME_to_jstring(%p)", name);
5521
5522 Unique_BIO buffer(BIO_new(BIO_s_mem()));
5523 if (buffer.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07005524 jniThrowOutOfMemory(env, "Unable to allocate BIO");
Kenny Root860d2702013-04-23 15:50:31 -07005525 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
5526 return NULL;
5527 }
5528
5529 /* Don't interpret the string. */
5530 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB);
5531
5532 /* Write in given format and null terminate. */
5533 X509_NAME_print_ex(buffer.get(), name, 0, flags);
5534 BIO_write(buffer.get(), "\0", 1);
5535
5536 char *tmp;
5537 BIO_get_mem_data(buffer.get(), &tmp);
5538 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp);
5539 return env->NewStringUTF(tmp);
5540}
5541
5542
5543/**
5544 * Converts GENERAL_NAME items to the output format expected in
5545 * X509Certificate#getSubjectAlternativeNames and
5546 * X509Certificate#getIssuerAlternativeNames return.
5547 */
5548static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
5549 switch (gen->type) {
5550 case GEN_EMAIL:
5551 case GEN_DNS:
5552 case GEN_URI: {
5553 // This must not be a T61String and must not contain NULLs.
5554 const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5));
5555 ssize_t len = ASN1_STRING_length(gen->d.ia5);
5556 if ((len == static_cast<ssize_t>(strlen(data)))
5557 && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) {
5558 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data);
5559 return env->NewStringUTF(data);
5560 } else {
5561 jniThrowException(env, "java/security/cert/CertificateParsingException",
5562 "Invalid dNSName encoding");
5563 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen);
5564 return NULL;
5565 }
5566 }
5567 case GEN_DIRNAME:
5568 /* Write in RFC 2253 format */
5569 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
5570 case GEN_IPADD: {
5571 const void *ip = reinterpret_cast<const void *>(gen->d.ip->data);
5572 if (gen->d.ip->length == 4) {
5573 // IPv4
5574 UniquePtr<char[]> buffer(new char[INET_ADDRSTRLEN]);
5575 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != NULL) {
5576 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get());
5577 return env->NewStringUTF(buffer.get());
5578 } else {
5579 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen, strerror(errno));
5580 }
5581 } else if (gen->d.ip->length == 16) {
5582 // IPv6
5583 UniquePtr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
5584 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != NULL) {
5585 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get());
5586 return env->NewStringUTF(buffer.get());
5587 } else {
5588 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno));
5589 }
5590 }
5591
5592 /* Invalid IP encodings are pruned out without throwing an exception. */
5593 return NULL;
5594 }
5595 case GEN_RID:
5596 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID);
5597 case GEN_OTHERNAME:
5598 case GEN_X400:
5599 default:
Adam Langleyde5225d2014-10-06 15:55:30 -07005600 return ASN1ToByteArray<GENERAL_NAME>(env, gen, i2d_GENERAL_NAME);
Kenny Root860d2702013-04-23 15:50:31 -07005601 }
5602
5603 return NULL;
5604}
5605
5606#define GN_STACK_SUBJECT_ALT_NAME 1
5607#define GN_STACK_ISSUER_ALT_NAME 2
5608
5609static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref,
5610 jint type) {
5611 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5612 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type);
5613
5614 if (x509 == NULL) {
5615 jniThrowNullPointerException(env, "x509 == null");
5616 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type);
5617 return NULL;
5618 }
5619
5620 X509_check_ca(x509);
5621
5622 STACK_OF(GENERAL_NAME)* gn_stack;
5623 Unique_sk_GENERAL_NAME stackHolder;
5624 if (type == GN_STACK_SUBJECT_ALT_NAME) {
5625 gn_stack = x509->altname;
5626 } else if (type == GN_STACK_ISSUER_ALT_NAME) {
5627 stackHolder.reset(
5628 static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, NID_issuer_alt_name,
5629 NULL, NULL)));
5630 gn_stack = stackHolder.get();
5631 } else {
5632 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type);
5633 return NULL;
5634 }
5635
5636 int count = sk_GENERAL_NAME_num(gn_stack);
5637 if (count <= 0) {
5638 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type);
5639 return NULL;
5640 }
5641
5642 /*
5643 * Keep track of how many originally so we can ignore any invalid
5644 * values later.
5645 */
5646 const int origCount = count;
5647
Kenny Root923e3c52013-05-01 12:17:23 -07005648 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
Kenny Root860d2702013-04-23 15:50:31 -07005649 for (int i = 0, j = 0; i < origCount; i++, j++) {
5650 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
5651 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
5652 if (env->ExceptionCheck()) {
5653 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name",
5654 x509, type);
5655 return NULL;
5656 }
5657
5658 /*
5659 * If it's NULL, we'll have to skip this, reduce the number of total
5660 * entries, and fix up the array later.
5661 */
5662 if (val.get() == NULL) {
5663 j--;
5664 count--;
5665 continue;
5666 }
5667
Kenny Root923e3c52013-05-01 12:17:23 -07005668 ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
Kenny Root860d2702013-04-23 15:50:31 -07005669
Kenny Root923e3c52013-05-01 12:17:23 -07005670 ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
Kenny Root860d2702013-04-23 15:50:31 -07005671 integer_valueOfMethod, gen->type));
5672 env->SetObjectArrayElement(item.get(), 0, type.get());
5673 env->SetObjectArrayElement(item.get(), 1, val.get());
5674
5675 env->SetObjectArrayElement(joa.get(), j, item.get());
5676 }
5677
5678 if (count == 0) {
5679 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning NULL",
5680 x509, type, origCount);
5681 joa.reset(NULL);
5682 } else if (origCount != count) {
5683 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
5684 origCount, count);
5685
Kenny Root923e3c52013-05-01 12:17:23 -07005686 ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
5687 NULL));
Kenny Root860d2702013-04-23 15:50:31 -07005688
5689 for (int i = 0; i < count; i++) {
5690 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
5691 env->SetObjectArrayElement(joa_copy.get(), i, item.get());
5692 }
5693
5694 joa.reset(joa_copy.release());
5695 }
5696
5697 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count);
5698 return joa.release();
5699}
5700
5701static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref) {
5702 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5703 JNI_TRACE("X509_get_notBefore(%p)", x509);
5704
5705 if (x509 == NULL) {
5706 jniThrowNullPointerException(env, "x509 == null");
5707 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509);
5708 return 0;
5709 }
5710
5711 ASN1_TIME* notBefore = X509_get_notBefore(x509);
5712 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
5713 return reinterpret_cast<uintptr_t>(notBefore);
5714}
5715
5716static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref) {
5717 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5718 JNI_TRACE("X509_get_notAfter(%p)", x509);
5719
5720 if (x509 == NULL) {
5721 jniThrowNullPointerException(env, "x509 == null");
5722 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509);
5723 return 0;
5724 }
5725
5726 ASN1_TIME* notAfter = X509_get_notAfter(x509);
5727 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
5728 return reinterpret_cast<uintptr_t>(notAfter);
5729}
5730
5731static long NativeCrypto_X509_get_version(JNIEnv*, jclass, jlong x509Ref) {
5732 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5733 JNI_TRACE("X509_get_version(%p)", x509);
5734
5735 long version = X509_get_version(x509);
5736 JNI_TRACE("X509_get_version(%p) => %ld", x509, version);
5737 return version;
5738}
5739
5740template<typename T>
5741static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type, ASN1_INTEGER* (*get_serial_func)(T*)) {
5742 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type);
5743
5744 if (x509Type == NULL) {
5745 jniThrowNullPointerException(env, "x509Type == null");
5746 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type);
5747 return NULL;
5748 }
5749
5750 ASN1_INTEGER* serialNumber = get_serial_func(x509Type);
5751 Unique_BIGNUM serialBn(ASN1_INTEGER_to_BN(serialNumber, NULL));
5752 if (serialBn.get() == NULL) {
5753 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5754 return NULL;
5755 }
5756
5757 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn"));
5758 if (env->ExceptionCheck()) {
5759 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type);
5760 return NULL;
5761 }
5762
5763 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get());
5764 return serialArray.release();
5765}
5766
5767/* OpenSSL includes set_serialNumber but not get. */
5768#if !defined(X509_REVOKED_get_serialNumber)
5769static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) {
5770 return x->serialNumber;
5771}
5772#endif
5773
5774static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref) {
5775 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5776 JNI_TRACE("X509_get_serialNumber(%p)", x509);
5777 return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber);
5778}
5779
5780static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass, jlong x509RevokedRef) {
5781 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
5782 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked);
5783 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber);
5784}
5785
Kenny Root37e58bb2014-11-25 14:29:25 -08005786static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref, jobject pkeyRef) {
Kenny Root860d2702013-04-23 15:50:31 -07005787 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
Kenny Root37e58bb2014-11-25 14:29:25 -08005788 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07005789 JNI_TRACE("X509_verify(%p, %p)", x509, pkey);
5790
5791 if (x509 == NULL) {
5792 jniThrowNullPointerException(env, "x509 == null");
5793 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey);
5794 return;
5795 }
5796
5797 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07005798 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey);
5799 return;
5800 }
5801
5802 if (X509_verify(x509, pkey) != 1) {
5803 throwExceptionIfNecessary(env, "X509_verify");
5804 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey);
5805 } else {
5806 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey);
5807 }
5808}
5809
5810static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref) {
5811 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5812 JNI_TRACE("get_X509_cert_info_enc(%p)", x509);
Adam Langleyde5225d2014-10-06 15:55:30 -07005813 return ASN1ToByteArray<X509_CINF>(env, x509->cert_info, i2d_X509_CINF);
Kenny Root860d2702013-04-23 15:50:31 -07005814}
5815
5816static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) {
5817 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5818 JNI_TRACE("get_X509_ex_flags(%p)", x509);
5819
5820 if (x509 == NULL) {
5821 jniThrowNullPointerException(env, "x509 == null");
5822 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509);
5823 return 0;
5824 }
5825
5826 X509_check_ca(x509);
5827
5828 return x509->ex_flags;
5829}
5830
Elliott Hughesab3c6532013-07-30 15:42:28 -07005831static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
Kenny Root35beb302013-05-06 11:49:28 -07005832 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
5833 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
5834 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
5835
5836 int ret = X509_check_issued(x509_1, x509_2);
5837 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
5838 return ret;
5839}
5840
Kenny Root860d2702013-04-23 15:50:31 -07005841static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
5842 *signature = x509->signature;
5843}
5844
5845static void get_X509_CRL_signature(X509_CRL *crl, ASN1_BIT_STRING** signature) {
5846 *signature = crl->signature;
5847}
5848
5849template<typename T>
5850static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type, void (*get_signature_func)(T*, ASN1_BIT_STRING**)) {
5851 JNI_TRACE("get_X509Type_signature(%p)", x509Type);
5852
5853 if (x509Type == NULL) {
5854 jniThrowNullPointerException(env, "x509Type == null");
5855 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type);
5856 return NULL;
5857 }
5858
5859 ASN1_BIT_STRING* signature;
5860 get_signature_func(x509Type, &signature);
5861
5862 ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length));
5863 if (env->ExceptionCheck()) {
5864 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type);
5865 return NULL;
5866 }
5867
5868 ScopedByteArrayRW signatureBytes(env, signatureArray.get());
5869 if (signatureBytes.get() == NULL) {
5870 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type);
5871 return NULL;
5872 }
5873
5874 memcpy(signatureBytes.get(), signature->data, signature->length);
5875
5876 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(),
5877 signature->length);
5878 return signatureArray.release();
5879}
5880
5881static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref) {
5882 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5883 JNI_TRACE("get_X509_signature(%p)", x509);
5884 return get_X509Type_signature<X509>(env, x509, get_X509_signature);
5885}
5886
5887static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef) {
5888 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5889 JNI_TRACE("get_X509_CRL_signature(%p)", crl);
5890 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature);
5891}
5892
5893static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef, jlong x509Ref) {
5894 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5895 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
5896 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509);
5897
5898 if (x509crl == NULL) {
5899 jniThrowNullPointerException(env, "x509crl == null");
5900 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509);
5901 return 0;
5902 } else if (x509 == NULL) {
5903 jniThrowNullPointerException(env, "x509 == null");
5904 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509);
5905 return 0;
5906 }
5907
5908 X509_REVOKED* revoked = NULL;
5909 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509);
5910 if (ret == 0) {
5911 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509);
5912 return 0;
5913 }
5914
5915 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked);
5916 return reinterpret_cast<uintptr_t>(revoked);
5917}
5918
5919static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef, jbyteArray serialArray) {
5920 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef));
5921 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray);
5922
5923 if (x509crl == NULL) {
5924 jniThrowNullPointerException(env, "x509crl == null");
5925 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray);
5926 return 0;
5927 }
5928
5929 Unique_BIGNUM serialBn(BN_new());
5930 if (serialBn.get() == NULL) {
5931 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray);
5932 return 0;
5933 }
5934
5935 BIGNUM* serialBare = serialBn.get();
5936 if (!arrayToBignum(env, serialArray, &serialBare)) {
5937 if (!env->ExceptionCheck()) {
5938 jniThrowNullPointerException(env, "serial == null");
5939 }
5940 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5941 return 0;
5942 }
5943
5944 Unique_ASN1_INTEGER serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), NULL));
5945 if (serialInteger.get() == NULL) {
5946 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray);
5947 return 0;
5948 }
5949
5950 X509_REVOKED* revoked = NULL;
5951 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get());
5952 if (ret == 0) {
5953 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray);
5954 return 0;
5955 }
5956
5957 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked);
5958 return reinterpret_cast<uintptr_t>(revoked);
5959}
5960
5961
5962/* This appears to be missing from OpenSSL. */
Adam Langley0ccc17a2015-02-25 11:37:23 -08005963#if !defined(X509_REVOKED_dup) && !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07005964X509_REVOKED* X509_REVOKED_dup(X509_REVOKED* x) {
5965 return reinterpret_cast<X509_REVOKED*>(ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), x));
5966}
5967#endif
5968
5969static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef) {
5970 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5971 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl);
5972
5973 if (crl == NULL) {
5974 jniThrowNullPointerException(env, "crl == null");
5975 return NULL;
5976 }
5977
5978 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl);
5979 if (stack == NULL) {
5980 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl);
5981 return NULL;
5982 }
5983
5984 size_t size = sk_X509_REVOKED_num(stack);
5985
5986 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(size));
5987 ScopedLongArrayRW revoked(env, revokedArray.get());
5988 for (size_t i = 0; i < size; i++) {
5989 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i));
5990 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item));
5991 }
5992
Kenny Root6c523c02014-11-25 13:33:51 -08005993 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%zd]", stack, revokedArray.get(), size);
Kenny Root860d2702013-04-23 15:50:31 -07005994 return revokedArray.release();
5995}
5996
5997static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef) {
5998 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
5999 JNI_TRACE("i2d_X509_CRL(%p)", crl);
Adam Langleyde5225d2014-10-06 15:55:30 -07006000 return ASN1ToByteArray<X509_CRL>(env, crl, i2d_X509_CRL);
Kenny Root860d2702013-04-23 15:50:31 -07006001}
6002
6003static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef) {
6004 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6005 JNI_TRACE("X509_CRL_free(%p)", crl);
6006
6007 if (crl == NULL) {
6008 jniThrowNullPointerException(env, "crl == null");
6009 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl);
6010 return;
6011 }
6012
6013 X509_CRL_free(crl);
6014}
6015
6016static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef) {
6017 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6018 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6019 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl);
6020
6021 if (bio == NULL) {
6022 jniThrowNullPointerException(env, "bio == null");
6023 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl);
6024 return;
6025 }
6026
6027 if (crl == NULL) {
6028 jniThrowNullPointerException(env, "crl == null");
6029 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl);
6030 return;
6031 }
6032
Elliott Hughesfb822ae2013-08-19 15:45:20 -07006033 if (!X509_CRL_print(bio, crl)) {
6034 throwExceptionIfNecessary(env, "X509_CRL_print");
6035 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
6036 } else {
6037 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
6038 }
Kenny Root860d2702013-04-23 15:50:31 -07006039}
6040
6041static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) {
6042 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6043 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl);
6044
6045 if (crl == NULL || crl->sig_alg == NULL) {
6046 jniThrowNullPointerException(env, "crl == NULL || crl->sig_alg == NULL");
6047 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == NULL", crl);
6048 return NULL;
6049 }
6050
6051 return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm);
6052}
6053
6054static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef) {
6055 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6056 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl);
6057
6058 if (crl == NULL) {
6059 jniThrowNullPointerException(env, "crl == null");
6060 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl);
6061 return NULL;
6062 }
6063
6064 if (crl->sig_alg->parameter == NULL) {
6065 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl);
6066 return NULL;
6067 }
6068
Adam Langleyde5225d2014-10-06 15:55:30 -07006069 return ASN1ToByteArray<ASN1_TYPE>(env, crl->sig_alg->parameter, i2d_ASN1_TYPE);
Kenny Root860d2702013-04-23 15:50:31 -07006070}
6071
6072static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef) {
6073 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6074 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl);
Adam Langleyde5225d2014-10-06 15:55:30 -07006075 return ASN1ToByteArray<X509_NAME>(env, X509_CRL_get_issuer(crl), i2d_X509_NAME);
Kenny Root860d2702013-04-23 15:50:31 -07006076}
6077
6078static long NativeCrypto_X509_CRL_get_version(JNIEnv*, jclass, jlong x509CrlRef) {
6079 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6080 JNI_TRACE("X509_CRL_get_version(%p)", crl);
6081
6082 long version = X509_CRL_get_version(crl);
6083 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version);
6084 return version;
6085}
6086
6087template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
6088 X509_EXTENSION* (*get_ext_func)(T*, int)>
6089static X509_EXTENSION *X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) {
6090 JNI_TRACE("X509Type_get_ext(%p)", x509Type);
6091
6092 if (x509Type == NULL) {
6093 jniThrowNullPointerException(env, "x509 == null");
6094 return NULL;
6095 }
6096
6097 ScopedUtfChars oid(env, oidString);
6098 if (oid.c_str() == NULL) {
6099 return NULL;
6100 }
6101
6102 Unique_ASN1_OBJECT asn1(OBJ_txt2obj(oid.c_str(), 1));
6103 if (asn1.get() == NULL) {
6104 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str());
6105 freeOpenSslErrorState();
6106 return NULL;
6107 }
6108
Adam Langleyde5225d2014-10-06 15:55:30 -07006109 int extIndex = get_ext_by_OBJ_func(x509Type, (ASN1_OBJECT*) asn1.get(), -1);
Kenny Root860d2702013-04-23 15:50:31 -07006110 if (extIndex == -1) {
6111 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str());
6112 return NULL;
6113 }
6114
6115 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex);
6116 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext);
6117 return ext;
6118}
6119
6120template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int),
6121 X509_EXTENSION* (*get_ext_func)(T*, int)>
6122static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) {
6123 X509_EXTENSION* ext = X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type,
6124 oidString);
6125 if (ext == NULL) {
6126 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString);
6127 return NULL;
6128 }
6129
6130 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value);
Adam Langleyde5225d2014-10-06 15:55:30 -07006131 return ASN1ToByteArray<ASN1_OCTET_STRING>(env, ext->value, i2d_ASN1_OCTET_STRING);
Kenny Root860d2702013-04-23 15:50:31 -07006132}
6133
Bowen Zhaoa770db22015-01-28 17:01:40 +08006134static jlong NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef, jstring oid) {
Kenny Root860d2702013-04-23 15:50:31 -07006135 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6136 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid);
6137 X509_EXTENSION* ext = X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(
6138 env, crl, oid);
6139 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext);
6140 return reinterpret_cast<uintptr_t>(ext);
6141}
6142
Bowen Zhaoa770db22015-01-28 17:01:40 +08006143static jlong NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef,
Kenny Root860d2702013-04-23 15:50:31 -07006144 jstring oid) {
6145 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6146 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid);
6147 X509_EXTENSION* ext = X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ,
6148 X509_REVOKED_get_ext>(env, revoked, oid);
6149 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext);
6150 return reinterpret_cast<uintptr_t>(ext);
6151}
6152
6153static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) {
6154 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6155 JNI_TRACE("X509_REVOKED_dup(%p)", revoked);
6156
6157 if (revoked == NULL) {
6158 jniThrowNullPointerException(env, "revoked == null");
6159 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked);
6160 return 0;
6161 }
6162
6163 X509_REVOKED* dup = X509_REVOKED_dup(revoked);
6164 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup);
6165 return reinterpret_cast<uintptr_t>(dup);
6166}
6167
6168static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass, jlong x509RevokedRef) {
6169 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6170 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked);
6171
6172 if (revoked == NULL) {
6173 jniThrowNullPointerException(env, "revoked == null");
6174 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked);
6175 return 0;
6176 }
6177
6178 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate);
6179 return reinterpret_cast<uintptr_t>(revoked->revocationDate);
6180}
6181
Anwar Ghuloume75878c2013-05-24 09:11:52 -07006182#pragma GCC diagnostic push
6183#pragma GCC diagnostic ignored "-Wwrite-strings"
Kenny Root860d2702013-04-23 15:50:31 -07006184static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) {
6185 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6186 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6187 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked);
6188
6189 if (bio == NULL) {
6190 jniThrowNullPointerException(env, "bio == null");
6191 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked);
6192 return;
6193 }
6194
6195 if (revoked == NULL) {
6196 jniThrowNullPointerException(env, "revoked == null");
6197 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked);
6198 return;
6199 }
6200
Kenny Root860d2702013-04-23 15:50:31 -07006201 BIO_printf(bio, "Serial Number: ");
6202 i2a_ASN1_INTEGER(bio, revoked->serialNumber);
6203 BIO_printf(bio, "\nRevocation Date: ");
6204 ASN1_TIME_print(bio, revoked->revocationDate);
6205 BIO_printf(bio, "\n");
6206 X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
Kenny Root860d2702013-04-23 15:50:31 -07006207}
Anwar Ghuloume75878c2013-05-24 09:11:52 -07006208#pragma GCC diagnostic pop
Kenny Root860d2702013-04-23 15:50:31 -07006209
6210static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) {
6211 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6212 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl);
Adam Langleyde5225d2014-10-06 15:55:30 -07006213 return ASN1ToByteArray<X509_CRL_INFO>(env, crl->crl, i2d_X509_CRL_INFO);
Kenny Root860d2702013-04-23 15:50:31 -07006214}
6215
Kenny Root37e58bb2014-11-25 14:29:25 -08006216static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef, jobject pkeyRef) {
Kenny Root860d2702013-04-23 15:50:31 -07006217 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
Kenny Root37e58bb2014-11-25 14:29:25 -08006218 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root860d2702013-04-23 15:50:31 -07006219 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey);
6220
6221 if (crl == NULL) {
6222 jniThrowNullPointerException(env, "crl == null");
6223 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey);
6224 return;
6225 }
6226
6227 if (pkey == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07006228 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey);
6229 return;
6230 }
6231
6232 if (X509_CRL_verify(crl, pkey) != 1) {
6233 throwExceptionIfNecessary(env, "X509_CRL_verify");
6234 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey);
6235 } else {
6236 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey);
6237 }
6238}
6239
6240static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
6241 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6242 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl);
6243
6244 if (crl == NULL) {
6245 jniThrowNullPointerException(env, "crl == null");
6246 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl);
6247 return 0;
6248 }
6249
6250 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
6251 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
6252 return reinterpret_cast<uintptr_t>(lastUpdate);
6253}
6254
6255static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef) {
6256 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
6257 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl);
6258
6259 if (crl == NULL) {
6260 jniThrowNullPointerException(env, "crl == null");
6261 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl);
6262 return 0;
6263 }
6264
6265 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
6266 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
6267 return reinterpret_cast<uintptr_t>(nextUpdate);
6268}
6269
6270static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
6271 X509_REVOKED* x509Revoked =
6272 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
6273 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked);
Adam Langleyde5225d2014-10-06 15:55:30 -07006274 return ASN1ToByteArray<X509_REVOKED>(env, x509Revoked, i2d_X509_REVOKED);
Kenny Root860d2702013-04-23 15:50:31 -07006275}
6276
6277static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) {
6278 X509_EXTENSION* ext = reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef));
6279
6280 if (ext == NULL) {
6281 jniThrowNullPointerException(env, "ext == NULL");
6282 return 0;
6283 }
6284
6285 return X509_supported_extension(ext);
6286}
6287
6288static inline void get_ASN1_TIME_data(char **data, int* output, size_t len) {
6289 char c = **data;
6290 **data = '\0';
6291 *data -= len;
6292 *output = atoi(*data);
6293 *(*data + len) = c;
6294}
6295
6296static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef, jobject calendar) {
6297 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
6298 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
6299
6300 if (asn1Time == NULL) {
6301 jniThrowNullPointerException(env, "asn1Time == null");
6302 return;
6303 }
6304
6305 Unique_ASN1_GENERALIZEDTIME gen(ASN1_TIME_to_generalizedtime(asn1Time, NULL));
6306 if (gen.get() == NULL) {
6307 jniThrowNullPointerException(env, "asn1Time == null");
6308 return;
6309 }
6310
6311 if (gen->length < 14 || gen->data == NULL) {
6312 jniThrowNullPointerException(env, "gen->length < 14 || gen->data == NULL");
6313 return;
6314 }
6315
6316 int sec, min, hour, mday, mon, year;
6317
6318 char *p = (char*) &gen->data[14];
6319
6320 get_ASN1_TIME_data(&p, &sec, 2);
6321 get_ASN1_TIME_data(&p, &min, 2);
6322 get_ASN1_TIME_data(&p, &hour, 2);
6323 get_ASN1_TIME_data(&p, &mday, 2);
6324 get_ASN1_TIME_data(&p, &mon, 2);
6325 get_ASN1_TIME_data(&p, &year, 4);
6326
6327 env->CallVoidMethod(calendar, calendar_setMethod, year, mon - 1, mday, hour, min, sec);
6328}
6329
6330static jstring NativeCrypto_OBJ_txt2nid_oid(JNIEnv* env, jclass, jstring oidStr) {
6331 JNI_TRACE("OBJ_txt2nid_oid(%p)", oidStr);
6332
6333 ScopedUtfChars oid(env, oidStr);
6334 if (oid.c_str() == NULL) {
6335 return NULL;
6336 }
6337
6338 JNI_TRACE("OBJ_txt2nid_oid(%s)", oid.c_str());
6339
6340 int nid = OBJ_txt2nid(oid.c_str());
6341 if (nid == NID_undef) {
6342 JNI_TRACE("OBJ_txt2nid_oid(%s) => NID_undef", oid.c_str());
6343 freeOpenSslErrorState();
6344 return NULL;
6345 }
6346
Adam Langleyde5225d2014-10-06 15:55:30 -07006347 const ASN1_OBJECT* obj = OBJ_nid2obj(nid);
6348 if (obj == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07006349 throwExceptionIfNecessary(env, "OBJ_nid2obj");
6350 return NULL;
6351 }
6352
Adam Langleyde5225d2014-10-06 15:55:30 -07006353 ScopedLocalRef<jstring> ouputStr(env, ASN1_OBJECT_to_OID_string(env, obj));
Kenny Root860d2702013-04-23 15:50:31 -07006354 JNI_TRACE("OBJ_txt2nid_oid(%s) => %p", oid.c_str(), ouputStr.get());
6355 return ouputStr.release();
6356}
6357
6358static jstring NativeCrypto_X509_NAME_print_ex(JNIEnv* env, jclass, jlong x509NameRef, jlong jflags) {
6359 X509_NAME* x509name = reinterpret_cast<X509_NAME*>(static_cast<uintptr_t>(x509NameRef));
6360 unsigned long flags = static_cast<unsigned long>(jflags);
6361 JNI_TRACE("X509_NAME_print_ex(%p, %ld)", x509name, flags);
6362
6363 if (x509name == NULL) {
6364 jniThrowNullPointerException(env, "x509name == null");
6365 JNI_TRACE("X509_NAME_print_ex(%p, %ld) => x509name == null", x509name, flags);
6366 return NULL;
6367 }
6368
6369 return X509_NAME_to_jstring(env, x509name, flags);
6370}
6371
6372template <typename T, T* (*d2i_func)(BIO*, T**)>
6373static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6374 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6375 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio);
6376
6377 if (bio == NULL) {
6378 jniThrowNullPointerException(env, "bio == null");
6379 return 0;
6380 }
6381
6382 T* x = d2i_func(bio, NULL);
6383 if (x == NULL) {
6384 throwExceptionIfNecessary(env, "d2i_ASN1Object_to_jlong");
6385 return 0;
6386 }
6387
6388 return reinterpret_cast<uintptr_t>(x);
6389}
6390
6391static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) {
6392 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(env, bioRef);
6393}
6394
6395static jlong NativeCrypto_d2i_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6396 return d2i_ASN1Object_to_jlong<X509, d2i_X509_bio>(env, bioRef);
6397}
6398
6399static jlong NativeCrypto_d2i_X509(JNIEnv* env, jclass, jbyteArray certBytes) {
6400 X509* x = ByteArrayToASN1<X509, d2i_X509>(env, certBytes);
6401 return reinterpret_cast<uintptr_t>(x);
6402}
6403
6404static jbyteArray NativeCrypto_i2d_X509(JNIEnv* env, jclass, jlong x509Ref) {
6405 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6406 JNI_TRACE("i2d_X509(%p)", x509);
Adam Langleyde5225d2014-10-06 15:55:30 -07006407 return ASN1ToByteArray<X509>(env, x509, i2d_X509);
Kenny Root860d2702013-04-23 15:50:31 -07006408}
6409
6410static jbyteArray NativeCrypto_i2d_X509_PUBKEY(JNIEnv* env, jclass, jlong x509Ref) {
6411 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6412 JNI_TRACE("i2d_X509_PUBKEY(%p)", x509);
Adam Langleyde5225d2014-10-06 15:55:30 -07006413 return ASN1ToByteArray<X509_PUBKEY>(env, X509_get_X509_PUBKEY(x509), i2d_X509_PUBKEY);
Kenny Root860d2702013-04-23 15:50:31 -07006414}
6415
6416
6417template<typename T, T* (*PEM_read_func)(BIO*, T**, pem_password_cb*, void*)>
6418static jlong PEM_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) {
6419 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6420 JNI_TRACE("PEM_ASN1Object_to_jlong(%p)", bio);
6421
6422 if (bio == NULL) {
6423 jniThrowNullPointerException(env, "bio == null");
6424 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => bio == null", bio);
6425 return 0;
6426 }
6427
6428 T* x = PEM_read_func(bio, NULL, NULL, NULL);
6429 if (x == NULL) {
6430 throwExceptionIfNecessary(env, "PEM_ASN1Object_to_jlong");
6431 // Sometimes the PEM functions fail without pushing an error
6432 if (!env->ExceptionCheck()) {
6433 jniThrowRuntimeException(env, "Failure parsing PEM");
6434 }
6435 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => threw exception", bio);
6436 return 0;
6437 }
6438
6439 JNI_TRACE("PEM_ASN1Object_to_jlong(%p) => %p", bio, x);
6440 return reinterpret_cast<uintptr_t>(x);
6441}
6442
6443static jlong NativeCrypto_PEM_read_bio_X509(JNIEnv* env, jclass, jlong bioRef) {
Kenny Root6c523c02014-11-25 13:33:51 -08006444 JNI_TRACE("PEM_read_bio_X509(0x%llx)", (long long) bioRef);
Kenny Root860d2702013-04-23 15:50:31 -07006445 return PEM_ASN1Object_to_jlong<X509, PEM_read_bio_X509>(env, bioRef);
6446}
6447
6448static jlong NativeCrypto_PEM_read_bio_X509_CRL(JNIEnv* env, jclass, jlong bioRef) {
Kenny Root6c523c02014-11-25 13:33:51 -08006449 JNI_TRACE("PEM_read_bio_X509_CRL(0x%llx)", (long long) bioRef);
Kenny Root860d2702013-04-23 15:50:31 -07006450 return PEM_ASN1Object_to_jlong<X509_CRL, PEM_read_bio_X509_CRL>(env, bioRef);
6451}
6452
Kenny Root860d2702013-04-23 15:50:31 -07006453template <typename T, typename T_stack>
6454static jlongArray PKCS7_to_ItemArray(JNIEnv* env, T_stack* stack, T* (*dup_func)(T*))
6455{
6456 if (stack == NULL) {
6457 return NULL;
6458 }
6459
6460 ScopedLocalRef<jlongArray> ref_array(env, NULL);
6461 size_t size = sk_num(reinterpret_cast<_STACK*>(stack));
6462 ref_array.reset(env->NewLongArray(size));
6463 ScopedLongArrayRW items(env, ref_array.get());
6464 for (size_t i = 0; i < size; i++) {
6465 T* item = reinterpret_cast<T*>(sk_value(reinterpret_cast<_STACK*>(stack), i));
6466 items[i] = reinterpret_cast<uintptr_t>(dup_func(item));
6467 }
6468
Kenny Root8a77c202015-04-24 10:37:11 -07006469 JNI_TRACE("PKCS7_to_ItemArray(%p) => %p [size=%zd]", stack, ref_array.get(), size);
Kenny Root860d2702013-04-23 15:50:31 -07006470 return ref_array.release();
6471}
6472
6473#define PKCS7_CERTS 1
6474#define PKCS7_CRLS 2
6475
Kenny Root860d2702013-04-23 15:50:31 -07006476static jbyteArray NativeCrypto_i2d_PKCS7(JNIEnv* env, jclass, jlongArray certsArray) {
Adam Langleyde5225d2014-10-06 15:55:30 -07006477#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07006478 JNI_TRACE("i2d_PKCS7(%p)", certsArray);
6479
6480 Unique_PKCS7 pkcs7(PKCS7_new());
6481 if (pkcs7.get() == NULL) {
6482 jniThrowNullPointerException(env, "pkcs7 == null");
6483 JNI_TRACE("i2d_PKCS7(%p) => pkcs7 == null", certsArray);
6484 return NULL;
6485 }
6486
6487 if (PKCS7_set_type(pkcs7.get(), NID_pkcs7_signed) != 1) {
6488 throwExceptionIfNecessary(env, "PKCS7_set_type");
6489 return NULL;
6490 }
6491
Kenny Root525df9b2014-12-09 13:46:03 -08006492 // The EncapsulatedContentInfo must be present in the output, but OpenSSL
6493 // will fill in a zero-length OID if you don't call PKCS7_set_content on the
6494 // outer PKCS7 container. So we construct an empty PKCS7 data container and
6495 // set it as the content.
6496 Unique_PKCS7 pkcs7Data(PKCS7_new());
6497 if (PKCS7_set_type(pkcs7Data.get(), NID_pkcs7_data) != 1) {
6498 throwExceptionIfNecessary(env, "PKCS7_set_type data");
6499 return NULL;
6500 }
6501
6502 if (PKCS7_set_content(pkcs7.get(), pkcs7Data.get()) != 1) {
6503 throwExceptionIfNecessary(env, "PKCS7_set_content");
6504 return NULL;
6505 }
6506 OWNERSHIP_TRANSFERRED(pkcs7Data);
6507
Kenny Root860d2702013-04-23 15:50:31 -07006508 ScopedLongArrayRO certs(env, certsArray);
6509 for (size_t i = 0; i < certs.size(); i++) {
6510 X509* item = reinterpret_cast<X509*>(certs[i]);
6511 if (PKCS7_add_certificate(pkcs7.get(), item) != 1) {
6512 throwExceptionIfNecessary(env, "i2d_PKCS7");
6513 return NULL;
6514 }
6515 }
6516
Kenny Root6c523c02014-11-25 13:33:51 -08006517 JNI_TRACE("i2d_PKCS7(%p) => %zd certs", certsArray, certs.size());
Adam Langleyde5225d2014-10-06 15:55:30 -07006518 return ASN1ToByteArray<PKCS7>(env, pkcs7.get(), i2d_PKCS7);
6519#else // OPENSSL_IS_BORINGSSL
6520 STACK_OF(X509) *stack = sk_X509_new_null();
6521
6522 ScopedLongArrayRO certs(env, certsArray);
6523 for (size_t i = 0; i < certs.size(); i++) {
6524 X509* item = reinterpret_cast<X509*>(certs[i]);
6525 if (sk_X509_push(stack, item) == 0) {
6526 sk_X509_free(stack);
6527 throwExceptionIfNecessary(env, "sk_X509_push");
6528 return NULL;
6529 }
6530 }
6531
6532 CBB out;
6533 CBB_init(&out, 1024 * certs.size());
6534 if (!PKCS7_bundle_certificates(&out, stack)) {
6535 CBB_cleanup(&out);
6536 sk_X509_free(stack);
6537 throwExceptionIfNecessary(env, "PKCS7_bundle_certificates");
6538 return NULL;
6539 }
6540
6541 sk_X509_free(stack);
6542
6543 uint8_t *derBytes;
6544 size_t derLen;
6545 if (!CBB_finish(&out, &derBytes, &derLen)) {
6546 CBB_cleanup(&out);
6547 throwExceptionIfNecessary(env, "CBB_finish");
6548 return NULL;
6549 }
6550
6551 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen));
6552 if (byteArray.get() == NULL) {
6553 JNI_TRACE("creating byte array failed");
6554 return NULL;
6555 }
6556
6557 ScopedByteArrayRW bytes(env, byteArray.get());
6558 if (bytes.get() == NULL) {
6559 JNI_TRACE("using byte array failed");
6560 return NULL;
6561 }
6562
6563 uint8_t* p = reinterpret_cast<unsigned char*>(bytes.get());
6564 memcpy(p, derBytes, derLen);
6565
6566 return byteArray.release();
6567#endif // OPENSSL_IS_BORINGSSL
Kenny Root860d2702013-04-23 15:50:31 -07006568}
6569
Adam Langley86733982015-05-18 17:33:35 -07006570#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langley2e68e222015-02-26 17:46:47 -08006571
6572static STACK_OF(X509)* PKCS7_get_certs(PKCS7* pkcs7) {
6573 if (PKCS7_type_is_signed(pkcs7)) {
6574 return pkcs7->d.sign->cert;
6575 } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
6576 return pkcs7->d.signed_and_enveloped->cert;
6577 } else {
6578 JNI_TRACE("PKCS7_get_certs(%p) => unknown PKCS7 type", pkcs7);
6579 return NULL;
6580 }
6581}
6582
6583static STACK_OF(X509_CRL)* PKCS7_get_CRLs(PKCS7* pkcs7) {
6584 if (PKCS7_type_is_signed(pkcs7)) {
6585 return pkcs7->d.sign->crl;
6586 } else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) {
6587 return pkcs7->d.signed_and_enveloped->crl;
6588 } else {
6589 JNI_TRACE("PKCS7_get_CRLs(%p) => unknown PKCS7 type", pkcs7);
6590 return NULL;
6591 }
6592}
6593
6594#endif
6595
6596static jlongArray NativeCrypto_PEM_read_bio_PKCS7(JNIEnv* env, jclass, jlong bioRef, jint which) {
6597 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6598 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p)", bio);
6599
6600 if (bio == NULL) {
6601 jniThrowNullPointerException(env, "bio == null");
6602 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => bio == null", bio);
6603 return 0;
6604 }
6605
Adam Langley811e7ae2015-02-27 13:20:02 -08006606#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langley2e68e222015-02-26 17:46:47 -08006607 Unique_PKCS7 pkcs7(PEM_read_bio_PKCS7(bio, NULL, NULL, NULL));
6608 if (pkcs7.get() == NULL) {
6609 throwExceptionIfNecessary(env, "PEM_read_bio_PKCS7_CRLs");
6610 JNI_TRACE("PEM_read_bio_PKCS7_CRLs(%p) => threw exception", bio);
6611 return 0;
6612 }
6613
6614 switch (which) {
6615 case PKCS7_CERTS:
6616 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
6617 case PKCS7_CRLS:
6618 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
6619 X509_CRL_dup);
6620 default:
6621 jniThrowRuntimeException(env, "unknown PKCS7 field");
6622 return NULL;
6623 }
Adam Langley811e7ae2015-02-27 13:20:02 -08006624#else
6625 if (which == PKCS7_CERTS) {
6626 Unique_sk_X509 outCerts(sk_X509_new_null());
6627 if (!PKCS7_get_PEM_certificates(outCerts.get(), bio)) {
6628 throwExceptionIfNecessary(env, "PKCS7_get_PEM_certificates");
6629 return 0;
6630 }
6631 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, outCerts.get(), X509_dup);
6632 } else if (which == PKCS7_CRLS) {
6633 Unique_sk_X509_CRL outCRLs(sk_X509_CRL_new_null());
6634 if (!PKCS7_get_PEM_CRLs(outCRLs.get(), bio)) {
6635 throwExceptionIfNecessary(env, "PKCS7_get_PEM_CRLs");
6636 return 0;
6637 }
6638 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(
6639 env, outCRLs.get(), X509_CRL_dup);
6640 } else {
6641 jniThrowRuntimeException(env, "unknown PKCS7 field");
6642 return 0;
6643 }
6644#endif
Adam Langley2e68e222015-02-26 17:46:47 -08006645}
6646
6647static jlongArray NativeCrypto_d2i_PKCS7_bio(JNIEnv* env, jclass, jlong bioRef, jint which) {
6648 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6649 JNI_TRACE("d2i_PKCS7_bio(%p, %d)", bio, which);
6650
6651 if (bio == NULL) {
6652 jniThrowNullPointerException(env, "bio == null");
6653 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => bio == null", bio, which);
6654 return 0;
6655 }
6656
6657#if !defined(OPENSSL_IS_BORINGSSL)
6658 Unique_PKCS7 pkcs7(d2i_PKCS7_bio(bio, NULL));
6659 if (pkcs7.get() == NULL) {
6660 throwExceptionIfNecessary(env, "d2i_PKCS7_bio");
6661 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => threw exception", bio, which);
6662 return 0;
6663 }
6664
6665 switch (which) {
6666 case PKCS7_CERTS:
Kenny Rootccb82252015-06-11 12:58:31 -07006667 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => returned", bio, which);
Adam Langley2e68e222015-02-26 17:46:47 -08006668 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, PKCS7_get_certs(pkcs7.get()), X509_dup);
6669 case PKCS7_CRLS:
Kenny Rootccb82252015-06-11 12:58:31 -07006670 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => returned", bio, which);
Adam Langley2e68e222015-02-26 17:46:47 -08006671 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(env, PKCS7_get_CRLs(pkcs7.get()),
6672 X509_CRL_dup);
6673 default:
6674 jniThrowRuntimeException(env, "unknown PKCS7 field");
6675 return NULL;
6676 }
6677#else
Adam Langley86733982015-05-18 17:33:35 -07006678 uint8_t *data;
Adam Langley2e68e222015-02-26 17:46:47 -08006679 size_t len;
Adam Langley86733982015-05-18 17:33:35 -07006680 if (!BIO_read_asn1(bio, &data, &len, 256 * 1024 * 1024 /* max length, 256MB for sanity */)) {
Kenny Rootccb82252015-06-11 12:58:31 -07006681 if (!throwExceptionIfNecessary(env, "Error reading PKCS#7 data")) {
6682 throwParsingException(env, "Error reading PKCS#7 data");
6683 }
6684 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading BIO", bio, which);
Adam Langley2e68e222015-02-26 17:46:47 -08006685 return 0;
6686 }
Adam Langley86733982015-05-18 17:33:35 -07006687 Unique_OPENSSL_str data_storage(data);
Adam Langley2e68e222015-02-26 17:46:47 -08006688
6689 CBS cbs;
Adam Langley86733982015-05-18 17:33:35 -07006690 CBS_init(&cbs, data, len);
Adam Langley2e68e222015-02-26 17:46:47 -08006691
Adam Langley811e7ae2015-02-27 13:20:02 -08006692 if (which == PKCS7_CERTS) {
6693 Unique_sk_X509 outCerts(sk_X509_new_null());
6694 if (!PKCS7_get_certificates(outCerts.get(), &cbs)) {
Kenny Rootccb82252015-06-11 12:58:31 -07006695 if (!throwExceptionIfNecessary(env, "PKCS7_get_certificates")) {
6696 throwParsingException(env, "Error parsing PKCS#7 certificate data");
6697 }
6698 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading certs", bio, which);
Adam Langley811e7ae2015-02-27 13:20:02 -08006699 return 0;
6700 }
Kenny Rootccb82252015-06-11 12:58:31 -07006701 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success certs", bio, which);
Adam Langley811e7ae2015-02-27 13:20:02 -08006702 return PKCS7_to_ItemArray<X509, STACK_OF(X509)>(env, outCerts.get(), X509_dup);
6703 } else if (which == PKCS7_CRLS) {
6704 Unique_sk_X509_CRL outCRLs(sk_X509_CRL_new_null());
6705 if (!PKCS7_get_CRLs(outCRLs.get(), &cbs)) {
Kenny Rootccb82252015-06-11 12:58:31 -07006706 if (!throwExceptionIfNecessary(env, "PKCS7_get_CRLs")) {
6707 throwParsingException(env, "Error parsing PKCS#7 CRL data");
6708 }
6709 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => error reading CRLs", bio, which);
Adam Langley811e7ae2015-02-27 13:20:02 -08006710 return 0;
6711 }
Kenny Rootccb82252015-06-11 12:58:31 -07006712 JNI_TRACE("d2i_PKCS7_bio(%p, %d) => success CRLs", bio, which);
Adam Langley811e7ae2015-02-27 13:20:02 -08006713 return PKCS7_to_ItemArray<X509_CRL, STACK_OF(X509_CRL)>(
6714 env, outCRLs.get(), X509_CRL_dup);
6715 } else {
6716 jniThrowRuntimeException(env, "unknown PKCS7 field");
Adam Langley2e68e222015-02-26 17:46:47 -08006717 return 0;
6718 }
Adam Langley2e68e222015-02-26 17:46:47 -08006719#endif
6720}
6721
6722
Kenny Root860d2702013-04-23 15:50:31 -07006723typedef STACK_OF(X509) PKIPATH;
6724
6725ASN1_ITEM_TEMPLATE(PKIPATH) =
6726 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PkiPath, X509)
6727ASN1_ITEM_TEMPLATE_END(PKIPATH)
6728
6729static jlongArray NativeCrypto_ASN1_seq_unpack_X509_bio(JNIEnv* env, jclass, jlong bioRef) {
6730 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6731 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p)", bio);
6732
6733 Unique_sk_X509 path((PKIPATH*) ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKIPATH), bio, NULL));
6734 if (path.get() == NULL) {
6735 throwExceptionIfNecessary(env, "ASN1_seq_unpack_X509_bio");
Kenny Rootccb82252015-06-11 12:58:31 -07006736 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => threw error", bio);
Kenny Root860d2702013-04-23 15:50:31 -07006737 return NULL;
6738 }
6739
6740 size_t size = sk_X509_num(path.get());
6741
6742 ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(size));
6743 ScopedLongArrayRW certs(env, certArray.get());
6744 for (size_t i = 0; i < size; i++) {
Kenny Rootc58a1862013-09-11 10:05:32 -07006745 X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
Kenny Root860d2702013-04-23 15:50:31 -07006746 certs[i] = reinterpret_cast<uintptr_t>(item);
6747 }
6748
Kenny Root6c523c02014-11-25 13:33:51 -08006749 JNI_TRACE("ASN1_seq_unpack_X509_bio(%p) => returns %zd items", bio, size);
Kenny Root860d2702013-04-23 15:50:31 -07006750 return certArray.release();
6751}
6752
6753static jbyteArray NativeCrypto_ASN1_seq_pack_X509(JNIEnv* env, jclass, jlongArray certs) {
6754 JNI_TRACE("ASN1_seq_pack_X509(%p)", certs);
6755 ScopedLongArrayRO certsArray(env, certs);
6756 if (certsArray.get() == NULL) {
6757 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to get certs array", certs);
6758 return NULL;
6759 }
6760
6761 Unique_sk_X509 certStack(sk_X509_new_null());
6762 if (certStack.get() == NULL) {
6763 JNI_TRACE("ASN1_seq_pack_X509(%p) => failed to make cert stack", certs);
6764 return NULL;
6765 }
6766
Adam Langleyde5225d2014-10-06 15:55:30 -07006767#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07006768 for (size_t i = 0; i < certsArray.size(); i++) {
6769 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
Kenny Rootc58a1862013-09-11 10:05:32 -07006770 sk_X509_push(certStack.get(), X509_dup_nocopy(x509));
Kenny Root860d2702013-04-23 15:50:31 -07006771 }
6772
6773 int len;
6774 Unique_OPENSSL_str encoded(ASN1_seq_pack(
6775 reinterpret_cast<STACK_OF(OPENSSL_BLOCK)*>(
6776 reinterpret_cast<uintptr_t>(certStack.get())),
6777 reinterpret_cast<int (*)(void*, unsigned char**)>(i2d_X509), NULL, &len));
Adam Langleyde5225d2014-10-06 15:55:30 -07006778 if (encoded.get() == NULL || len < 0) {
Kenny Root860d2702013-04-23 15:50:31 -07006779 JNI_TRACE("ASN1_seq_pack_X509(%p) => trouble encoding", certs);
6780 return NULL;
6781 }
6782
Adam Langleyde5225d2014-10-06 15:55:30 -07006783 uint8_t *out = encoded.get();
6784 size_t out_len = len;
6785#else
6786 CBB result, seq_contents;
6787 if (!CBB_init(&result, 2048 * certsArray.size())) {
6788 JNI_TRACE("ASN1_seq_pack_X509(%p) => CBB_init failed", certs);
6789 return NULL;
6790 }
6791 if (!CBB_add_asn1(&result, &seq_contents, CBS_ASN1_SEQUENCE)) {
6792 CBB_cleanup(&result);
6793 return NULL;
6794 }
6795
6796 for (size_t i = 0; i < certsArray.size(); i++) {
6797 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
6798 uint8_t *buf;
6799 int len = i2d_X509(x509, NULL);
6800
6801 if (len < 0 ||
6802 !CBB_add_space(&seq_contents, &buf, len) ||
6803 i2d_X509(x509, &buf) < 0) {
6804 CBB_cleanup(&result);
6805 return NULL;
6806 }
6807 }
6808
6809 uint8_t *out;
6810 size_t out_len;
6811 if (!CBB_finish(&result, &out, &out_len)) {
6812 CBB_cleanup(&result);
6813 return NULL;
6814 }
6815 UniquePtr<uint8_t> out_storage(out);
6816#endif
6817
6818 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(out_len));
Kenny Root860d2702013-04-23 15:50:31 -07006819 if (byteArray.get() == NULL) {
6820 JNI_TRACE("ASN1_seq_pack_X509(%p) => creating byte array failed", certs);
6821 return NULL;
6822 }
6823
6824 ScopedByteArrayRW bytes(env, byteArray.get());
6825 if (bytes.get() == NULL) {
6826 JNI_TRACE("ASN1_seq_pack_X509(%p) => using byte array failed", certs);
6827 return NULL;
6828 }
6829
Adam Langleyde5225d2014-10-06 15:55:30 -07006830 uint8_t *p = reinterpret_cast<uint8_t*>(bytes.get());
6831 memcpy(p, out, out_len);
Kenny Root860d2702013-04-23 15:50:31 -07006832
6833 return byteArray.release();
6834}
6835
6836static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref) {
6837 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6838 JNI_TRACE("X509_free(%p)", x509);
6839
6840 if (x509 == NULL) {
6841 jniThrowNullPointerException(env, "x509 == null");
6842 JNI_TRACE("X509_free(%p) => x509 == null", x509);
6843 return;
6844 }
6845
6846 X509_free(x509);
6847}
6848
6849static jint NativeCrypto_X509_cmp(JNIEnv* env, jclass, jlong x509Ref1, jlong x509Ref2) {
6850 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
6851 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
6852 JNI_TRACE("X509_cmp(%p, %p)", x509_1, x509_2);
6853
6854 if (x509_1 == NULL) {
6855 jniThrowNullPointerException(env, "x509_1 == null");
6856 JNI_TRACE("X509_cmp(%p, %p) => x509_1 == null", x509_1, x509_2);
6857 return -1;
6858 }
6859
6860 if (x509_2 == NULL) {
6861 jniThrowNullPointerException(env, "x509_2 == null");
6862 JNI_TRACE("X509_cmp(%p, %p) => x509_2 == null", x509_1, x509_2);
6863 return -1;
6864 }
6865
6866 int ret = X509_cmp(x509_1, x509_2);
6867 JNI_TRACE("X509_cmp(%p, %p) => %d", x509_1, x509_2, ret);
6868 return ret;
6869}
6870
6871static jint NativeCrypto_get_X509_hashCode(JNIEnv* env, jclass, jlong x509Ref) {
6872 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6873
6874 if (x509 == NULL) {
6875 jniThrowNullPointerException(env, "x509 == null");
6876 JNI_TRACE("get_X509_hashCode(%p) => x509 == null", x509);
6877 return 0;
6878 }
6879
6880 // Force caching extensions.
6881 X509_check_ca(x509);
6882
6883 jint hashCode = 0L;
6884 for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
6885 hashCode = 31 * hashCode + x509->sha1_hash[i];
6886 }
6887 return hashCode;
6888}
6889
6890static void NativeCrypto_X509_print_ex(JNIEnv* env, jclass, jlong bioRef, jlong x509Ref,
6891 jlong nmflagJava, jlong certflagJava) {
6892 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
6893 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6894 long nmflag = static_cast<long>(nmflagJava);
6895 long certflag = static_cast<long>(certflagJava);
6896 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld)", bio, x509, nmflag, certflag);
6897
6898 if (bio == NULL) {
6899 jniThrowNullPointerException(env, "bio == null");
6900 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => bio == null", bio, x509, nmflag, certflag);
6901 return;
6902 }
6903
6904 if (x509 == NULL) {
6905 jniThrowNullPointerException(env, "x509 == null");
6906 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => x509 == null", bio, x509, nmflag, certflag);
6907 return;
6908 }
6909
Elliott Hughesfb822ae2013-08-19 15:45:20 -07006910 if (!X509_print_ex(bio, x509, nmflag, certflag)) {
6911 throwExceptionIfNecessary(env, "X509_print_ex");
6912 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
6913 } else {
6914 JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
6915 }
Kenny Root860d2702013-04-23 15:50:31 -07006916}
6917
6918static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref) {
6919 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6920 JNI_TRACE("X509_get_pubkey(%p)", x509);
6921
6922 if (x509 == NULL) {
6923 jniThrowNullPointerException(env, "x509 == null");
6924 JNI_TRACE("X509_get_pubkey(%p) => x509 == null", x509);
6925 return 0;
6926 }
6927
6928 Unique_EVP_PKEY pkey(X509_get_pubkey(x509));
6929 if (pkey.get() == NULL) {
Adam Langleyde5225d2014-10-06 15:55:30 -07006930#if defined(OPENSSL_IS_BORINGSSL)
6931 const uint32_t last_error = ERR_peek_last_error();
6932 const uint32_t first_error = ERR_peek_error();
6933 if ((ERR_GET_LIB(last_error) == ERR_LIB_EVP &&
6934 ERR_GET_REASON(last_error) == EVP_R_UNKNOWN_PUBLIC_KEY_TYPE) ||
6935 (ERR_GET_LIB(first_error) == ERR_LIB_EC &&
6936 ERR_GET_REASON(first_error) == EC_R_UNKNOWN_GROUP)) {
6937 freeOpenSslErrorState();
6938 throwNoSuchAlgorithmException(env, "X509_get_pubkey");
6939 return 0;
6940 }
6941#endif
6942
Kenny Root860d2702013-04-23 15:50:31 -07006943 throwExceptionIfNecessary(env, "X509_get_pubkey");
6944 return 0;
6945 }
6946
Kenny Root3bcae052014-02-05 11:25:54 -08006947 JNI_TRACE("X509_get_pubkey(%p) => %p", x509, pkey.get());
Kenny Root860d2702013-04-23 15:50:31 -07006948 return reinterpret_cast<uintptr_t>(pkey.release());
6949}
6950
6951static jbyteArray NativeCrypto_X509_get_issuer_name(JNIEnv* env, jclass, jlong x509Ref) {
6952 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6953 JNI_TRACE("X509_get_issuer_name(%p)", x509);
Adam Langleyde5225d2014-10-06 15:55:30 -07006954 return ASN1ToByteArray<X509_NAME>(env, X509_get_issuer_name(x509), i2d_X509_NAME);
Kenny Root860d2702013-04-23 15:50:31 -07006955}
6956
6957static jbyteArray NativeCrypto_X509_get_subject_name(JNIEnv* env, jclass, jlong x509Ref) {
6958 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6959 JNI_TRACE("X509_get_subject_name(%p)", x509);
Adam Langleyde5225d2014-10-06 15:55:30 -07006960 return ASN1ToByteArray<X509_NAME>(env, X509_get_subject_name(x509), i2d_X509_NAME);
Kenny Root860d2702013-04-23 15:50:31 -07006961}
6962
6963static jstring NativeCrypto_get_X509_pubkey_oid(JNIEnv* env, jclass, jlong x509Ref) {
6964 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6965 JNI_TRACE("get_X509_pubkey_oid(%p)", x509);
6966
6967 if (x509 == NULL) {
6968 jniThrowNullPointerException(env, "x509 == null");
6969 JNI_TRACE("get_X509_pubkey_oid(%p) => x509 == null", x509);
6970 return NULL;
6971 }
6972
6973 X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
6974 return ASN1_OBJECT_to_OID_string(env, pubkey->algor->algorithm);
6975}
6976
6977static jstring NativeCrypto_get_X509_sig_alg_oid(JNIEnv* env, jclass, jlong x509Ref) {
6978 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6979 JNI_TRACE("get_X509_sig_alg_oid(%p)", x509);
6980
6981 if (x509 == NULL || x509->sig_alg == NULL) {
6982 jniThrowNullPointerException(env, "x509 == NULL || x509->sig_alg == NULL");
6983 JNI_TRACE("get_X509_sig_alg_oid(%p) => x509 == NULL", x509);
6984 return NULL;
6985 }
6986
6987 return ASN1_OBJECT_to_OID_string(env, x509->sig_alg->algorithm);
6988}
6989
6990static jbyteArray NativeCrypto_get_X509_sig_alg_parameter(JNIEnv* env, jclass, jlong x509Ref) {
6991 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
6992 JNI_TRACE("get_X509_sig_alg_parameter(%p)", x509);
6993
6994 if (x509 == NULL) {
6995 jniThrowNullPointerException(env, "x509 == null");
6996 JNI_TRACE("get_X509_sig_alg_parameter(%p) => x509 == null", x509);
6997 return NULL;
6998 }
6999
7000 if (x509->sig_alg->parameter == NULL) {
7001 JNI_TRACE("get_X509_sig_alg_parameter(%p) => null", x509);
7002 return NULL;
7003 }
7004
Adam Langleyde5225d2014-10-06 15:55:30 -07007005 return ASN1ToByteArray<ASN1_TYPE>(env, x509->sig_alg->parameter, i2d_ASN1_TYPE);
Kenny Root860d2702013-04-23 15:50:31 -07007006}
7007
7008static jbooleanArray NativeCrypto_get_X509_issuerUID(JNIEnv* env, jclass, jlong x509Ref) {
7009 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7010 JNI_TRACE("get_X509_issuerUID(%p)", x509);
7011
7012 if (x509 == NULL) {
7013 jniThrowNullPointerException(env, "x509 == null");
7014 JNI_TRACE("get_X509_issuerUID(%p) => x509 == null", x509);
7015 return NULL;
7016 }
7017
7018 if (x509->cert_info->issuerUID == NULL) {
7019 JNI_TRACE("get_X509_issuerUID(%p) => null", x509);
7020 return NULL;
7021 }
7022
7023 return ASN1BitStringToBooleanArray(env, x509->cert_info->issuerUID);
7024}
7025static jbooleanArray NativeCrypto_get_X509_subjectUID(JNIEnv* env, jclass, jlong x509Ref) {
7026 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7027 JNI_TRACE("get_X509_subjectUID(%p)", x509);
7028
7029 if (x509 == NULL) {
7030 jniThrowNullPointerException(env, "x509 == null");
7031 JNI_TRACE("get_X509_subjectUID(%p) => x509 == null", x509);
7032 return NULL;
7033 }
7034
7035 if (x509->cert_info->subjectUID == NULL) {
7036 JNI_TRACE("get_X509_subjectUID(%p) => null", x509);
7037 return NULL;
7038 }
7039
7040 return ASN1BitStringToBooleanArray(env, x509->cert_info->subjectUID);
7041}
7042
7043static jbooleanArray NativeCrypto_get_X509_ex_kusage(JNIEnv* env, jclass, jlong x509Ref) {
7044 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7045 JNI_TRACE("get_X509_ex_kusage(%p)", x509);
7046
7047 if (x509 == NULL) {
7048 jniThrowNullPointerException(env, "x509 == null");
7049 JNI_TRACE("get_X509_ex_kusage(%p) => x509 == null", x509);
7050 return NULL;
7051 }
7052
7053 Unique_ASN1_BIT_STRING bitStr(static_cast<ASN1_BIT_STRING*>(
7054 X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL)));
7055 if (bitStr.get() == NULL) {
7056 JNI_TRACE("get_X509_ex_kusage(%p) => null", x509);
7057 return NULL;
7058 }
7059
7060 return ASN1BitStringToBooleanArray(env, bitStr.get());
7061}
7062
7063static jobjectArray NativeCrypto_get_X509_ex_xkusage(JNIEnv* env, jclass, jlong x509Ref) {
7064 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7065 JNI_TRACE("get_X509_ex_xkusage(%p)", x509);
7066
7067 if (x509 == NULL) {
7068 jniThrowNullPointerException(env, "x509 == null");
7069 JNI_TRACE("get_X509_ex_xkusage(%p) => x509 == null", x509);
7070 return NULL;
7071 }
7072
7073 Unique_sk_ASN1_OBJECT objArray(static_cast<STACK_OF(ASN1_OBJECT)*>(
7074 X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)));
7075 if (objArray.get() == NULL) {
7076 JNI_TRACE("get_X509_ex_xkusage(%p) => null", x509);
7077 return NULL;
7078 }
7079
7080 size_t size = sk_ASN1_OBJECT_num(objArray.get());
Kenny Root923e3c52013-05-01 12:17:23 -07007081 ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
Kenny Root860d2702013-04-23 15:50:31 -07007082 if (exKeyUsage.get() == NULL) {
7083 return NULL;
7084 }
7085
7086 for (size_t i = 0; i < size; i++) {
7087 ScopedLocalRef<jstring> oidStr(env, ASN1_OBJECT_to_OID_string(env,
7088 sk_ASN1_OBJECT_value(objArray.get(), i)));
7089 env->SetObjectArrayElement(exKeyUsage.get(), i, oidStr.get());
7090 }
7091
Kenny Root6c523c02014-11-25 13:33:51 -08007092 JNI_TRACE("get_X509_ex_xkusage(%p) => success (%zd entries)", x509, size);
Kenny Root860d2702013-04-23 15:50:31 -07007093 return exKeyUsage.release();
7094}
7095
7096static jint NativeCrypto_get_X509_ex_pathlen(JNIEnv* env, jclass, jlong x509Ref) {
7097 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7098 JNI_TRACE("get_X509_ex_pathlen(%p)", x509);
7099
7100 if (x509 == NULL) {
7101 jniThrowNullPointerException(env, "x509 == null");
7102 JNI_TRACE("get_X509_ex_pathlen(%p) => x509 == null", x509);
7103 return 0;
7104 }
7105
7106 /* Just need to do this to cache the ex_* values. */
7107 X509_check_ca(x509);
7108
7109 JNI_TRACE("get_X509_ex_pathlen(%p) => %ld", x509, x509->ex_pathlen);
7110 return x509->ex_pathlen;
7111}
7112
7113static jbyteArray NativeCrypto_X509_get_ext_oid(JNIEnv* env, jclass, jlong x509Ref,
7114 jstring oidString) {
7115 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref));
7116 JNI_TRACE("X509_get_ext_oid(%p, %p)", x509, oidString);
7117 return X509Type_get_ext_oid<X509, X509_get_ext_by_OBJ, X509_get_ext>(env, x509, oidString);
7118}
7119
7120static jbyteArray NativeCrypto_X509_CRL_get_ext_oid(JNIEnv* env, jclass, jlong x509CrlRef,
7121 jstring oidString) {
7122 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
7123 JNI_TRACE("X509_CRL_get_ext_oid(%p, %p)", crl, oidString);
7124 return X509Type_get_ext_oid<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>(env, crl,
7125 oidString);
7126}
7127
7128static jbyteArray NativeCrypto_X509_REVOKED_get_ext_oid(JNIEnv* env, jclass, jlong x509RevokedRef,
7129 jstring oidString) {
7130 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
7131 JNI_TRACE("X509_REVOKED_get_ext_oid(%p, %p)", revoked, oidString);
7132 return X509Type_get_ext_oid<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, X509_REVOKED_get_ext>(
7133 env, revoked, oidString);
7134}
7135
7136template<typename T, int (*get_ext_by_critical_func)(T*, int, int), X509_EXTENSION* (*get_ext_func)(T*, int)>
7137static jobjectArray get_X509Type_ext_oids(JNIEnv* env, jlong x509Ref, jint critical) {
7138 T* x509 = reinterpret_cast<T*>(static_cast<uintptr_t>(x509Ref));
7139 JNI_TRACE("get_X509Type_ext_oids(%p, %d)", x509, critical);
7140
7141 if (x509 == NULL) {
7142 jniThrowNullPointerException(env, "x509 == null");
7143 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => x509 == null", x509, critical);
7144 return NULL;
7145 }
7146
7147 int lastPos = -1;
7148 int count = 0;
7149 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7150 count++;
7151 }
7152
7153 JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
7154
Kenny Root923e3c52013-05-01 12:17:23 -07007155 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
Kenny Root860d2702013-04-23 15:50:31 -07007156 if (joa.get() == NULL) {
7157 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
7158 return NULL;
7159 }
7160
7161 lastPos = -1;
7162 count = 0;
7163 while ((lastPos = get_ext_by_critical_func(x509, critical, lastPos)) != -1) {
7164 X509_EXTENSION* ext = get_ext_func(x509, lastPos);
7165
7166 ScopedLocalRef<jstring> extOid(env, ASN1_OBJECT_to_OID_string(env, ext->object));
7167 if (extOid.get() == NULL) {
7168 JNI_TRACE("get_X509Type_ext_oids(%p) => couldn't get OID", x509);
7169 return NULL;
7170 }
7171
7172 env->SetObjectArrayElement(joa.get(), count++, extOid.get());
7173 }
7174
7175 JNI_TRACE("get_X509Type_ext_oids(%p, %d) => success", x509, critical);
7176 return joa.release();
7177}
7178
7179static jobjectArray NativeCrypto_get_X509_ext_oids(JNIEnv* env, jclass, jlong x509Ref,
7180 jint critical) {
Kenny Root6c523c02014-11-25 13:33:51 -08007181 JNI_TRACE("get_X509_ext_oids(0x%llx, %d)", (long long) x509Ref, critical);
Kenny Root860d2702013-04-23 15:50:31 -07007182 return get_X509Type_ext_oids<X509, X509_get_ext_by_critical, X509_get_ext>(env, x509Ref,
7183 critical);
7184}
7185
7186static jobjectArray NativeCrypto_get_X509_CRL_ext_oids(JNIEnv* env, jclass, jlong x509CrlRef,
7187 jint critical) {
Kenny Root6c523c02014-11-25 13:33:51 -08007188 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long) x509CrlRef, critical);
Kenny Root860d2702013-04-23 15:50:31 -07007189 return get_X509Type_ext_oids<X509_CRL, X509_CRL_get_ext_by_critical, X509_CRL_get_ext>(env,
7190 x509CrlRef, critical);
7191}
7192
7193static jobjectArray NativeCrypto_get_X509_REVOKED_ext_oids(JNIEnv* env, jclass, jlong x509RevokedRef,
7194 jint critical) {
Kenny Root6c523c02014-11-25 13:33:51 -08007195 JNI_TRACE("get_X509_CRL_ext_oids(0x%llx, %d)", (long long) x509RevokedRef, critical);
Kenny Root860d2702013-04-23 15:50:31 -07007196 return get_X509Type_ext_oids<X509_REVOKED, X509_REVOKED_get_ext_by_critical,
7197 X509_REVOKED_get_ext>(env, x509RevokedRef, critical);
7198}
7199
7200#ifdef WITH_JNI_TRACE
7201/**
7202 * Based on example logging call back from SSL_CTX_set_info_callback man page
7203 */
7204static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
7205{
7206 int w = where & ~SSL_ST_MASK;
7207 const char* str;
7208 if (w & SSL_ST_CONNECT) {
7209 str = "SSL_connect";
7210 } else if (w & SSL_ST_ACCEPT) {
7211 str = "SSL_accept";
7212 } else {
7213 str = "undefined";
7214 }
7215
7216 if (where & SSL_CB_LOOP) {
7217 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
7218 } else if (where & SSL_CB_ALERT) {
7219 str = (where & SSL_CB_READ) ? "read" : "write";
7220 JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
7221 s,
7222 str,
7223 SSL_alert_type_string(ret),
7224 SSL_alert_desc_string(ret),
7225 SSL_alert_type_string_long(ret),
7226 SSL_alert_desc_string_long(ret));
7227 } else if (where & SSL_CB_EXIT) {
7228 if (ret == 0) {
7229 JNI_TRACE("ssl=%p %s:failed exit in %s %s",
7230 s, str, SSL_state_string(s), SSL_state_string_long(s));
7231 } else if (ret < 0) {
7232 JNI_TRACE("ssl=%p %s:error exit in %s %s",
7233 s, str, SSL_state_string(s), SSL_state_string_long(s));
7234 } else if (ret == 1) {
7235 JNI_TRACE("ssl=%p %s:ok exit in %s %s",
7236 s, str, SSL_state_string(s), SSL_state_string_long(s));
7237 } else {
7238 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
7239 s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
7240 }
7241 } else if (where & SSL_CB_HANDSHAKE_START) {
7242 JNI_TRACE("ssl=%p handshake start in %s %s",
7243 s, SSL_state_string(s), SSL_state_string_long(s));
7244 } else if (where & SSL_CB_HANDSHAKE_DONE) {
7245 JNI_TRACE("ssl=%p handshake done in %s %s",
7246 s, SSL_state_string(s), SSL_state_string_long(s));
7247 } else {
7248 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
7249 s, str, where, SSL_state_string(s), SSL_state_string_long(s));
7250 }
7251}
7252#endif
7253
7254/**
Kenny Root0e9746b2013-09-12 15:14:48 -07007255 * Returns an array containing all the X509 certificate references
Kenny Root860d2702013-04-23 15:50:31 -07007256 */
Kenny Root0e9746b2013-09-12 15:14:48 -07007257static jlongArray getCertificateRefs(JNIEnv* env, const STACK_OF(X509)* chain)
Kenny Root860d2702013-04-23 15:50:31 -07007258{
7259 if (chain == NULL) {
7260 // Chain can be NULL if the associated cipher doesn't do certs.
7261 return NULL;
7262 }
Kenny Root0e9746b2013-09-12 15:14:48 -07007263 ssize_t count = sk_X509_num(chain);
Kenny Root860d2702013-04-23 15:50:31 -07007264 if (count <= 0) {
7265 return NULL;
7266 }
Kenny Root0e9746b2013-09-12 15:14:48 -07007267 ScopedLocalRef<jlongArray> refArray(env, env->NewLongArray(count));
7268 ScopedLongArrayRW refs(env, refArray.get());
7269 if (refs.get() == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07007270 return NULL;
7271 }
Kenny Root0e9746b2013-09-12 15:14:48 -07007272 for (ssize_t i = 0; i < count; i++) {
7273 refs[i] = reinterpret_cast<uintptr_t>(X509_dup_nocopy(sk_X509_value(chain, i)));
Kenny Root860d2702013-04-23 15:50:31 -07007274 }
Kenny Root0e9746b2013-09-12 15:14:48 -07007275 return refArray.release();
Kenny Root860d2702013-04-23 15:50:31 -07007276}
7277
7278/**
7279 * Returns an array containing all the X500 principal's bytes.
7280 */
7281static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
7282{
7283 if (names == NULL) {
7284 return NULL;
7285 }
7286
7287 int count = sk_X509_NAME_num(names);
7288 if (count <= 0) {
7289 return NULL;
7290 }
7291
Kenny Root923e3c52013-05-01 12:17:23 -07007292 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
Kenny Root860d2702013-04-23 15:50:31 -07007293 if (joa.get() == NULL) {
7294 return NULL;
7295 }
7296
7297 for (int i = 0; i < count; i++) {
7298 X509_NAME* principal = sk_X509_NAME_value(names, i);
7299
Adam Langleyde5225d2014-10-06 15:55:30 -07007300 ScopedLocalRef<jbyteArray> byteArray(env, ASN1ToByteArray<X509_NAME>(env,
7301 principal, i2d_X509_NAME));
Kenny Root860d2702013-04-23 15:50:31 -07007302 if (byteArray.get() == NULL) {
7303 return NULL;
7304 }
7305 env->SetObjectArrayElement(joa.get(), i, byteArray.get());
7306 }
7307
7308 return joa.release();
7309}
7310
7311/**
7312 * Our additional application data needed for getting synchronization right.
7313 * This maybe warrants a bit of lengthy prose:
7314 *
7315 * (1) We use a flag to reflect whether we consider the SSL connection alive.
7316 * Any read or write attempt loops will be cancelled once this flag becomes 0.
7317 *
7318 * (2) We use an int to count the number of threads that are blocked by the
7319 * underlying socket. This may be at most two (one reader and one writer), since
7320 * the Java layer ensures that no more threads will enter the native code at the
7321 * same time.
7322 *
7323 * (3) The pipe is used primarily as a means of cancelling a blocking select()
7324 * when we want to close the connection (aka "emergency button"). It is also
7325 * necessary for dealing with a possible race condition situation: There might
7326 * be cases where both threads see an SSL_ERROR_WANT_READ or
7327 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
7328 * If one leaves the select() successfully before the other enters it, the
7329 * "success" event is already consumed and the second thread will be blocked,
7330 * possibly forever (depending on network conditions).
7331 *
7332 * The idea for solving the problem looks like this: Whenever a thread is
7333 * successful in moving around data on the network, and it knows there is
7334 * another thread stuck in a select(), it will write a byte to the pipe, waking
7335 * up the other thread. A thread that returned from select(), on the other hand,
7336 * knows whether it's been woken up by the pipe. If so, it will consume the
7337 * byte, and the original state of affairs has been restored.
7338 *
7339 * The pipe may seem like a bit of overhead, but it fits in nicely with the
7340 * other file descriptors of the select(), so there's only one condition to wait
7341 * for.
7342 *
7343 * (4) Finally, a mutex is needed to make sure that at most one thread is in
7344 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
7345 * requirement. We use the same mutex to guard the field for counting the
7346 * waiting threads.
7347 *
7348 * Note: The current implementation assumes that we don't have to deal with
7349 * problems induced by multiple cores or processors and their respective
7350 * memory caches. One possible problem is that of inconsistent views on the
7351 * "aliveAndKicking" field. This could be worked around by also enclosing all
7352 * accesses to that field inside a lock/unlock sequence of our mutex, but
7353 * currently this seems a bit like overkill. Marking volatile at the very least.
7354 *
7355 * During handshaking, additional fields are used to up-call into
7356 * Java to perform certificate verification and handshake
7357 * completion. These are also used in any renegotiation.
7358 *
7359 * (5) the JNIEnv so we can invoke the Java callback
7360 *
7361 * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
7362 *
7363 * (7) a java.io.FileDescriptor wrapper to check for socket close
7364 *
7365 * We store the NPN protocols list so we can either send it (from the server) or
7366 * select a protocol (on the client). We eagerly acquire a pointer to the array
7367 * data so the callback doesn't need to acquire resources that it cannot
7368 * release.
7369 *
7370 * Because renegotiation can be requested by the peer at any time,
7371 * care should be taken to maintain an appropriate JNIEnv on any
7372 * downcall to openssl since it could result in an upcall to Java. The
7373 * current code does try to cover these cases by conditionally setting
7374 * the JNIEnv on calls that can read and write to the SSL such as
7375 * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
7376 *
7377 * Finally, we have two emphemeral keys setup by OpenSSL callbacks:
7378 *
7379 * (8) a set of ephemeral RSA keys that is lazily generated if a peer
7380 * wants to use an exportable RSA cipher suite.
7381 *
7382 * (9) a set of ephemeral EC keys that is lazily generated if a peer
7383 * wants to use an TLS_ECDHE_* cipher suite.
7384 *
7385 */
7386class AppData {
7387 public:
7388 volatile int aliveAndKicking;
7389 int waitingThreads;
7390 int fdsEmergency[2];
7391 MUTEX_TYPE mutex;
7392 JNIEnv* env;
7393 jobject sslHandshakeCallbacks;
Kenny Root860d2702013-04-23 15:50:31 -07007394 jbyteArray npnProtocolsArray;
7395 jbyte* npnProtocolsData;
7396 size_t npnProtocolsLength;
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007397 jbyteArray alpnProtocolsArray;
7398 jbyte* alpnProtocolsData;
7399 size_t alpnProtocolsLength;
Kenny Root860d2702013-04-23 15:50:31 -07007400 Unique_RSA ephemeralRsa;
7401 Unique_EC_KEY ephemeralEc;
7402
7403 /**
7404 * Creates the application data context for the SSL*.
7405 */
7406 public:
7407 static AppData* create() {
7408 UniquePtr<AppData> appData(new AppData());
7409 if (pipe(appData.get()->fdsEmergency) == -1) {
7410 ALOGE("AppData::create pipe(2) failed: %s", strerror(errno));
7411 return NULL;
7412 }
7413 if (!setBlocking(appData.get()->fdsEmergency[0], false)) {
7414 ALOGE("AppData::create fcntl(2) failed: %s", strerror(errno));
7415 return NULL;
7416 }
7417 if (MUTEX_SETUP(appData.get()->mutex) == -1) {
7418 ALOGE("pthread_mutex_init(3) failed: %s", strerror(errno));
7419 return NULL;
7420 }
7421 return appData.release();
7422 }
7423
7424 ~AppData() {
7425 aliveAndKicking = 0;
7426 if (fdsEmergency[0] != -1) {
7427 close(fdsEmergency[0]);
7428 }
7429 if (fdsEmergency[1] != -1) {
7430 close(fdsEmergency[1]);
7431 }
Kenny Rootfc7924b2014-03-10 10:29:10 -07007432 clearCallbackState();
Kenny Root860d2702013-04-23 15:50:31 -07007433 MUTEX_CLEANUP(mutex);
7434 }
7435
7436 private:
7437 AppData() :
7438 aliveAndKicking(1),
7439 waitingThreads(0),
7440 env(NULL),
7441 sslHandshakeCallbacks(NULL),
7442 npnProtocolsArray(NULL),
7443 npnProtocolsData(NULL),
7444 npnProtocolsLength(-1),
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007445 alpnProtocolsArray(NULL),
7446 alpnProtocolsData(NULL),
7447 alpnProtocolsLength(-1),
Kenny Root860d2702013-04-23 15:50:31 -07007448 ephemeralRsa(NULL),
7449 ephemeralEc(NULL) {
7450 fdsEmergency[0] = -1;
7451 fdsEmergency[1] = -1;
7452 }
7453
7454 public:
7455 /**
7456 * Used to set the SSL-to-Java callback state before each SSL_*
7457 * call that may result in a callback. It should be cleared after
7458 * the operation returns with clearCallbackState.
7459 *
7460 * @param env The JNIEnv
7461 * @param shc The SSLHandshakeCallbacks
7462 * @param fd The FileDescriptor
7463 * @param npnProtocols NPN protocols so that they may be advertised (by the
7464 * server) or selected (by the client). Has no effect
7465 * unless NPN is enabled.
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007466 * @param alpnProtocols ALPN protocols so that they may be advertised (by the
7467 * server) or selected (by the client). Passing non-NULL
7468 * enables ALPN.
Kenny Root860d2702013-04-23 15:50:31 -07007469 */
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007470 bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
7471 jbyteArray alpnProtocols) {
Kenny Rootf878e432013-11-08 11:37:48 -08007472 UniquePtr<NetFd> netFd;
7473 if (fd != NULL) {
7474 netFd.reset(new NetFd(e, fd));
7475 if (netFd->isClosed()) {
Kenny Root81c66672014-05-19 12:26:16 -07007476 JNI_TRACE("appData=%p setCallbackState => netFd->isClosed() == true", this);
Kenny Rootf878e432013-11-08 11:37:48 -08007477 return false;
7478 }
Kenny Root860d2702013-04-23 15:50:31 -07007479 }
7480 env = e;
7481 sslHandshakeCallbacks = shc;
Kenny Root860d2702013-04-23 15:50:31 -07007482 if (npnProtocols != NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07007483 npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
7484 if (npnProtocolsData == NULL) {
Kenny Rootfc7924b2014-03-10 10:29:10 -07007485 clearCallbackState();
Kenny Root81c66672014-05-19 12:26:16 -07007486 JNI_TRACE("appData=%p setCallbackState => npnProtocolsData == NULL", this);
Kenny Root860d2702013-04-23 15:50:31 -07007487 return false;
7488 }
Kenny Rootfc7924b2014-03-10 10:29:10 -07007489 npnProtocolsArray = npnProtocols;
7490 npnProtocolsLength = e->GetArrayLength(npnProtocols);
Kenny Root860d2702013-04-23 15:50:31 -07007491 }
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007492 if (alpnProtocols != NULL) {
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007493 alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
7494 if (alpnProtocolsData == NULL) {
Kenny Rootfc7924b2014-03-10 10:29:10 -07007495 clearCallbackState();
Kenny Root81c66672014-05-19 12:26:16 -07007496 JNI_TRACE("appData=%p setCallbackState => alpnProtocolsData == NULL", this);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007497 return false;
7498 }
Kenny Rootfc7924b2014-03-10 10:29:10 -07007499 alpnProtocolsArray = alpnProtocols;
7500 alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007501 }
Kenny Root860d2702013-04-23 15:50:31 -07007502 return true;
7503 }
7504
7505 void clearCallbackState() {
7506 sslHandshakeCallbacks = NULL;
Kenny Root860d2702013-04-23 15:50:31 -07007507 if (npnProtocolsArray != NULL) {
7508 env->ReleaseByteArrayElements(npnProtocolsArray, npnProtocolsData, JNI_ABORT);
7509 npnProtocolsArray = NULL;
7510 npnProtocolsData = NULL;
7511 npnProtocolsLength = -1;
7512 }
Kenny Root6fcf0cb2013-06-24 15:54:18 -07007513 if (alpnProtocolsArray != NULL) {
7514 env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
7515 alpnProtocolsArray = NULL;
7516 alpnProtocolsData = NULL;
7517 alpnProtocolsLength = -1;
7518 }
Kenny Root860d2702013-04-23 15:50:31 -07007519 env = NULL;
7520 }
7521
7522};
7523
7524/**
7525 * Dark magic helper function that checks, for a given SSL session, whether it
7526 * can SSL_read() or SSL_write() without blocking. Takes into account any
7527 * concurrent attempts to close the SSLSocket from the Java side. This is
7528 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
7529 * while thread #2 is sitting in a blocking read or write. The type argument
7530 * specifies whether we are waiting for readability or writability. It expects
7531 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
7532 * only need to wait in case one of these problems occurs.
7533 *
7534 * @param env
7535 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
7536 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
7537 * @param appData The application data structure with mutex info etc.
7538 * @param timeout_millis The timeout value for select call, with the special value
7539 * 0 meaning no timeout at all (wait indefinitely). Note: This is
7540 * the Java semantics of the timeout value, not the usual
7541 * select() semantics.
7542 * @return The result of the inner select() call,
7543 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
7544 * additional errors
7545 */
7546static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout_millis) {
7547 // This loop is an expanded version of the NET_FAILURE_RETRY
7548 // macro. It cannot simply be used in this case because select
7549 // cannot be restarted without recreating the fd_sets and timeout
7550 // structure.
7551 int result;
7552 fd_set rfds;
7553 fd_set wfds;
7554 do {
7555 NetFd fd(env, fdObject);
7556 if (fd.isClosed()) {
7557 result = THROWN_EXCEPTION;
7558 break;
7559 }
7560 int intFd = fd.get();
7561 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout_millis=%d",
7562 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout_millis);
7563
7564 FD_ZERO(&rfds);
7565 FD_ZERO(&wfds);
7566
7567 if (type == SSL_ERROR_WANT_READ) {
7568 FD_SET(intFd, &rfds);
7569 } else {
7570 FD_SET(intFd, &wfds);
7571 }
7572
7573 FD_SET(appData->fdsEmergency[0], &rfds);
7574
7575 int maxFd = (intFd > appData->fdsEmergency[0]) ? intFd : appData->fdsEmergency[0];
7576
7577 // Build a struct for the timeout data if we actually want a timeout.
7578 timeval tv;
7579 timeval* ptv;
7580 if (timeout_millis > 0) {
7581 tv.tv_sec = timeout_millis / 1000;
7582 tv.tv_usec = (timeout_millis % 1000) * 1000;
7583 ptv = &tv;
7584 } else {
7585 ptv = NULL;
7586 }
7587
Kenny Root3e46e4e2014-05-23 13:35:10 -07007588#ifndef CONSCRYPT_UNBUNDLED
Neil Fuller798f9442014-04-11 17:26:59 +01007589 AsynchronousCloseMonitor monitor(intFd);
Kenny Root3e46e4e2014-05-23 13:35:10 -07007590#else
7591 CompatibilityCloseMonitor monitor(intFd);
7592#endif
Kenny Root860d2702013-04-23 15:50:31 -07007593 result = select(maxFd + 1, &rfds, &wfds, NULL, ptv);
7594 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout_millis=%d => %d",
7595 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
7596 fd.get(), appData, timeout_millis, result);
7597 if (result == -1) {
7598 if (fd.isClosed()) {
7599 result = THROWN_EXCEPTION;
7600 break;
7601 }
7602 if (errno != EINTR) {
7603 break;
7604 }
7605 }
7606 } while (result == -1);
7607
7608 if (MUTEX_LOCK(appData->mutex) == -1) {
7609 return -1;
7610 }
7611
7612 if (result > 0) {
7613 // We have been woken up by a token in the emergency pipe. We
7614 // can't be sure the token is still in the pipe at this point
7615 // because it could have already been read by the thread that
7616 // originally wrote it if it entered sslSelect and acquired
7617 // the mutex before we did. Thus we cannot safely read from
7618 // the pipe in a blocking way (so we make the pipe
7619 // non-blocking at creation).
7620 if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
7621 char token;
7622 do {
Elliott Hughes57ad13f2015-05-12 21:16:12 -07007623 (void) read(appData->fdsEmergency[0], &token, 1);
Kenny Root860d2702013-04-23 15:50:31 -07007624 } while (errno == EINTR);
7625 }
7626 }
7627
7628 // Tell the world that there is now one thread less waiting for the
7629 // underlying network.
7630 appData->waitingThreads--;
7631
7632 MUTEX_UNLOCK(appData->mutex);
7633
7634 return result;
7635}
7636
7637/**
7638 * Helper function that wakes up a thread blocked in select(), in case there is
7639 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
7640 * before closing the connection.
7641 *
7642 * @param data The application data structure with mutex info etc.
7643 */
7644static void sslNotify(AppData* appData) {
7645 // Write a byte to the emergency pipe, so a concurrent select() can return.
7646 // Note we have to restore the errno of the original system call, since the
7647 // caller relies on it for generating error messages.
7648 int errnoBackup = errno;
7649 char token = '*';
7650 do {
7651 errno = 0;
Elliott Hughes57ad13f2015-05-12 21:16:12 -07007652 (void) write(appData->fdsEmergency[1], &token, 1);
Kenny Root860d2702013-04-23 15:50:31 -07007653 } while (errno == EINTR);
7654 errno = errnoBackup;
7655}
7656
7657static AppData* toAppData(const SSL* ssl) {
7658 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
7659}
7660
7661/**
7662 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
7663 */
7664static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
7665{
7666 /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
7667 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
7668 SSL_get_ex_data_X509_STORE_CTX_idx()));
7669 JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
7670
7671 AppData* appData = toAppData(ssl);
7672 JNIEnv* env = appData->env;
7673 if (env == NULL) {
7674 ALOGE("AppData->env missing in cert_verify_callback");
7675 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
7676 return 0;
7677 }
7678 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7679
7680 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7681 jmethodID methodID
Kenny Rootd2cced82014-03-20 15:03:28 -07007682 = env->GetMethodID(cls, "verifyCertificateChain", "(J[JLjava/lang/String;)V");
Kenny Root860d2702013-04-23 15:50:31 -07007683
Kenny Root0e9746b2013-09-12 15:14:48 -07007684 jlongArray refArray = getCertificateRefs(env, x509_store_ctx->untrusted);
Kenny Root860d2702013-04-23 15:50:31 -07007685
Adam Langleyde5225d2014-10-06 15:55:30 -07007686#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07007687 const char* authMethod = SSL_authentication_method(ssl);
Adam Langleyde5225d2014-10-06 15:55:30 -07007688#else
7689 const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
7690 const char *authMethod = SSL_CIPHER_get_kx_name(cipher);
7691#endif
7692
Kenny Root860d2702013-04-23 15:50:31 -07007693 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
7694 ssl, authMethod);
7695 jstring authMethodString = env->NewStringUTF(authMethod);
Kenny Rootd2cced82014-03-20 15:03:28 -07007696 env->CallVoidMethod(sslHandshakeCallbacks, methodID,
7697 static_cast<jlong>(reinterpret_cast<uintptr_t>(SSL_get1_session(ssl))), refArray,
7698 authMethodString);
Kenny Root860d2702013-04-23 15:50:31 -07007699
7700 int result = (env->ExceptionCheck()) ? 0 : 1;
7701 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
7702 return result;
7703}
7704
7705/**
7706 * Call back to watch for handshake to be completed. This is necessary
7707 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
7708 * returns before the handshake is completed in this case.
7709 */
Kenny Rootf878e432013-11-08 11:37:48 -08007710static void info_callback(const SSL* ssl, int where, int ret) {
Kenny Root860d2702013-04-23 15:50:31 -07007711 JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
7712#ifdef WITH_JNI_TRACE
7713 info_callback_LOG(ssl, where, ret);
7714#endif
Kenny Rootf878e432013-11-08 11:37:48 -08007715 if (!(where & SSL_CB_HANDSHAKE_DONE) && !(where & SSL_CB_HANDSHAKE_START)) {
Kenny Root860d2702013-04-23 15:50:31 -07007716 JNI_TRACE("ssl=%p info_callback ignored", ssl);
7717 return;
7718 }
7719
7720 AppData* appData = toAppData(ssl);
7721 JNIEnv* env = appData->env;
7722 if (env == NULL) {
7723 ALOGE("AppData->env missing in info_callback");
7724 JNI_TRACE("ssl=%p info_callback env error", ssl);
7725 return;
7726 }
7727 if (env->ExceptionCheck()) {
7728 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
7729 return;
7730 }
7731
7732 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7733
7734 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
Kenny Rootf878e432013-11-08 11:37:48 -08007735 jmethodID methodID = env->GetMethodID(cls, "onSSLStateChange", "(JII)V");
Kenny Root860d2702013-04-23 15:50:31 -07007736
Kenny Rootf878e432013-11-08 11:37:48 -08007737 JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
7738 env->CallVoidMethod(sslHandshakeCallbacks, methodID, reinterpret_cast<jlong>(ssl), where, ret);
Kenny Root860d2702013-04-23 15:50:31 -07007739
7740 if (env->ExceptionCheck()) {
7741 JNI_TRACE("ssl=%p info_callback exception", ssl);
7742 }
7743 JNI_TRACE("ssl=%p info_callback completed", ssl);
7744}
7745
7746/**
7747 * Call back to ask for a client certificate. There are three possible exit codes:
7748 *
7749 * 1 is success. x509Out and pkeyOut should point to the correct private key and certificate.
7750 * 0 is unable to find key. x509Out and pkeyOut should be NULL.
7751 * -1 is error and it doesn't matter what x509Out and pkeyOut are.
7752 */
7753static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
7754 JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
7755
7756 /* Clear output of key and certificate in case of early exit due to error. */
7757 *x509Out = NULL;
7758 *pkeyOut = NULL;
7759
7760 AppData* appData = toAppData(ssl);
7761 JNIEnv* env = appData->env;
7762 if (env == NULL) {
7763 ALOGE("AppData->env missing in client_cert_cb");
7764 JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
7765 return 0;
7766 }
7767 if (env->ExceptionCheck()) {
7768 JNI_TRACE("ssl=%p client_cert_cb already pending exception => 0", ssl);
7769 return -1;
7770 }
7771 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7772
7773 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7774 jmethodID methodID
7775 = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
7776
7777 // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
Kenny Root860d2702013-04-23 15:50:31 -07007778 const char* ctype = NULL;
Adam Langleyde5225d2014-10-06 15:55:30 -07007779#if !defined(OPENSSL_IS_BORINGSSL)
Adam Langleyca341142014-12-11 17:26:18 -08007780 char ssl2_ctype = SSL3_CT_RSA_SIGN;
Kenny Root860d2702013-04-23 15:50:31 -07007781 int ctype_num = 0;
7782 jobjectArray issuers = NULL;
7783 switch (ssl->version) {
7784 case SSL2_VERSION:
7785 ctype = &ssl2_ctype;
7786 ctype_num = 1;
7787 break;
7788 case SSL3_VERSION:
7789 case TLS1_VERSION:
7790 case TLS1_1_VERSION:
7791 case TLS1_2_VERSION:
7792 case DTLS1_VERSION:
7793 ctype = ssl->s3->tmp.ctype;
7794 ctype_num = ssl->s3->tmp.ctype_num;
7795 issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
7796 break;
7797 }
Adam Langleyde5225d2014-10-06 15:55:30 -07007798#else
7799 int ctype_num = SSL_get0_certificate_types(ssl, &ctype);
7800 jobjectArray issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
7801#endif
7802
Kenny Root860d2702013-04-23 15:50:31 -07007803#ifdef WITH_JNI_TRACE
7804 for (int i = 0; i < ctype_num; i++) {
7805 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
7806 }
7807#endif
7808
7809 jbyteArray keyTypes = env->NewByteArray(ctype_num);
7810 if (keyTypes == NULL) {
7811 JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
7812 return 0;
7813 }
7814 env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
7815
7816 JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
7817 "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
7818 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
7819
7820 if (env->ExceptionCheck()) {
7821 JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
7822 return -1;
7823 }
7824
7825 // Check for values set from Java
7826 X509* certificate = SSL_get_certificate(ssl);
7827 EVP_PKEY* privatekey = SSL_get_privatekey(ssl);
7828 int result = 0;
7829 if (certificate != NULL && privatekey != NULL) {
7830 *x509Out = certificate;
7831 *pkeyOut = privatekey;
7832 result = 1;
Kenny Rootdb88d052013-06-05 10:01:27 -07007833 } else {
7834 // Some error conditions return NULL, so make sure it doesn't linger.
7835 freeOpenSslErrorState();
Kenny Root860d2702013-04-23 15:50:31 -07007836 }
7837 JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
7838 return result;
7839}
7840
Alex Klyubin01cce892014-05-09 03:44:42 -07007841/**
7842 * Pre-Shared Key (PSK) client callback.
7843 */
7844static unsigned int psk_client_callback(SSL* ssl, const char *hint,
7845 char *identity, unsigned int max_identity_len,
7846 unsigned char *psk, unsigned int max_psk_len) {
7847 JNI_TRACE("ssl=%p psk_client_callback", ssl);
7848
7849 AppData* appData = toAppData(ssl);
7850 JNIEnv* env = appData->env;
7851 if (env == NULL) {
7852 ALOGE("AppData->env missing in psk_client_callback");
7853 JNI_TRACE("ssl=%p psk_client_callback env error", ssl);
7854 return 0;
7855 }
7856 if (env->ExceptionCheck()) {
7857 JNI_TRACE("ssl=%p psk_client_callback already pending exception", ssl);
7858 return 0;
7859 }
7860
7861 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7862 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7863 jmethodID methodID =
7864 env->GetMethodID(cls, "clientPSKKeyRequested", "(Ljava/lang/String;[B[B)I");
7865 JNI_TRACE("ssl=%p psk_client_callback calling clientPSKKeyRequested", ssl);
7866 ScopedLocalRef<jstring> identityHintJava(
7867 env,
7868 (hint != NULL) ? env->NewStringUTF(hint) : NULL);
7869 ScopedLocalRef<jbyteArray> identityJava(env, env->NewByteArray(max_identity_len));
7870 if (identityJava.get() == NULL) {
7871 JNI_TRACE("ssl=%p psk_client_callback failed to allocate identity bufffer", ssl);
7872 return 0;
7873 }
7874 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
7875 if (keyJava.get() == NULL) {
7876 JNI_TRACE("ssl=%p psk_client_callback failed to allocate key bufffer", ssl);
7877 return 0;
7878 }
7879 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
7880 identityHintJava.get(), identityJava.get(), keyJava.get());
7881 if (env->ExceptionCheck()) {
7882 JNI_TRACE("ssl=%p psk_client_callback exception", ssl);
7883 return 0;
7884 }
7885 if (keyLen <= 0) {
7886 JNI_TRACE("ssl=%p psk_client_callback failed to get key", ssl);
7887 return 0;
7888 } else if ((unsigned int) keyLen > max_psk_len) {
7889 JNI_TRACE("ssl=%p psk_client_callback got key which is too long", ssl);
7890 return 0;
7891 }
7892 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7893 if (keyJavaRo.get() == NULL) {
7894 JNI_TRACE("ssl=%p psk_client_callback failed to get key bytes", ssl);
7895 return 0;
7896 }
7897 memcpy(psk, keyJavaRo.get(), keyLen);
7898
7899 ScopedByteArrayRO identityJavaRo(env, identityJava.get());
7900 if (identityJavaRo.get() == NULL) {
7901 JNI_TRACE("ssl=%p psk_client_callback failed to get identity bytes", ssl);
7902 return 0;
7903 }
7904 memcpy(identity, identityJavaRo.get(), max_identity_len);
7905
7906 JNI_TRACE("ssl=%p psk_client_callback completed", ssl);
7907 return keyLen;
7908}
7909
7910/**
7911 * Pre-Shared Key (PSK) server callback.
7912 */
7913static unsigned int psk_server_callback(SSL* ssl, const char *identity,
7914 unsigned char *psk, unsigned int max_psk_len) {
7915 JNI_TRACE("ssl=%p psk_server_callback", ssl);
7916
7917 AppData* appData = toAppData(ssl);
7918 JNIEnv* env = appData->env;
7919 if (env == NULL) {
7920 ALOGE("AppData->env missing in psk_server_callback");
7921 JNI_TRACE("ssl=%p psk_server_callback env error", ssl);
7922 return 0;
7923 }
7924 if (env->ExceptionCheck()) {
7925 JNI_TRACE("ssl=%p psk_server_callback already pending exception", ssl);
7926 return 0;
7927 }
7928
7929 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
7930 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
7931 jmethodID methodID = env->GetMethodID(
7932 cls, "serverPSKKeyRequested", "(Ljava/lang/String;Ljava/lang/String;[B)I");
7933 JNI_TRACE("ssl=%p psk_server_callback calling serverPSKKeyRequested", ssl);
7934 const char* identityHint = SSL_get_psk_identity_hint(ssl);
7935 // identityHint = NULL;
7936 // identity = NULL;
7937 ScopedLocalRef<jstring> identityHintJava(
7938 env,
7939 (identityHint != NULL) ? env->NewStringUTF(identityHint) : NULL);
7940 ScopedLocalRef<jstring> identityJava(
7941 env,
7942 (identity != NULL) ? env->NewStringUTF(identity) : NULL);
7943 ScopedLocalRef<jbyteArray> keyJava(env, env->NewByteArray(max_psk_len));
7944 if (keyJava.get() == NULL) {
7945 JNI_TRACE("ssl=%p psk_server_callback failed to allocate key bufffer", ssl);
7946 return 0;
7947 }
7948 jint keyLen = env->CallIntMethod(sslHandshakeCallbacks, methodID,
7949 identityHintJava.get(), identityJava.get(), keyJava.get());
7950 if (env->ExceptionCheck()) {
7951 JNI_TRACE("ssl=%p psk_server_callback exception", ssl);
7952 return 0;
7953 }
7954 if (keyLen <= 0) {
7955 JNI_TRACE("ssl=%p psk_server_callback failed to get key", ssl);
7956 return 0;
7957 } else if ((unsigned int) keyLen > max_psk_len) {
7958 JNI_TRACE("ssl=%p psk_server_callback got key which is too long", ssl);
7959 return 0;
7960 }
7961 ScopedByteArrayRO keyJavaRo(env, keyJava.get());
7962 if (keyJavaRo.get() == NULL) {
7963 JNI_TRACE("ssl=%p psk_server_callback failed to get key bytes", ssl);
7964 return 0;
7965 }
7966 memcpy(psk, keyJavaRo.get(), keyLen);
7967
7968 JNI_TRACE("ssl=%p psk_server_callback completed", ssl);
7969 return keyLen;
7970}
7971
Kenny Root860d2702013-04-23 15:50:31 -07007972static RSA* rsaGenerateKey(int keylength) {
7973 Unique_BIGNUM bn(BN_new());
7974 if (bn.get() == NULL) {
7975 return NULL;
7976 }
7977 int setWordResult = BN_set_word(bn.get(), RSA_F4);
7978 if (setWordResult != 1) {
7979 return NULL;
7980 }
7981 Unique_RSA rsa(RSA_new());
7982 if (rsa.get() == NULL) {
7983 return NULL;
7984 }
7985 int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
7986 if (generateResult != 1) {
7987 return NULL;
7988 }
7989 return rsa.release();
7990}
7991
7992/**
7993 * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
7994 */
7995static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
7996 int is_export __attribute__ ((unused)),
7997 int keylength) {
7998 JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
7999
8000 AppData* appData = toAppData(ssl);
8001 if (appData->ephemeralRsa.get() == NULL) {
8002 JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
8003 appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
8004 }
8005 JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
8006 return appData->ephemeralRsa.get();
8007}
8008
8009static DH* dhGenerateParameters(int keylength) {
Adam Langleyde5225d2014-10-06 15:55:30 -07008010#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07008011 /*
8012 * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
8013 * different options for generating DH keys. One is generating the
8014 * keys using a single set of DH parameters. However, generating
8015 * DH parameters is slow enough (minutes) that they suggest doing
8016 * it once at install time. The other is to generate DH keys from
8017 * DSA parameters. Generating DSA parameters is faster than DH
8018 * parameters, but to prevent small subgroup attacks, they needed
8019 * to be regenerated for each set of DH keys. Setting the
8020 * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
8021 * for new DH parameters every type it needs to generate DH keys.
8022 */
Adam Langleyde5225d2014-10-06 15:55:30 -07008023
8024 // Fast path but must have SSL_OP_SINGLE_DH_USE set
Kenny Root860d2702013-04-23 15:50:31 -07008025 Unique_DSA dsa(DSA_new());
8026 if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
8027 return NULL;
8028 }
8029 DH* dh = DSA_dup_DH(dsa.get());
8030 return dh;
Adam Langleyde5225d2014-10-06 15:55:30 -07008031#else
8032 /* At the time of writing, OpenSSL and BoringSSL are hard coded to request
8033 * a 1024-bit DH. */
8034 if (keylength <= 1024) {
8035 return DH_get_1024_160(NULL);
8036 }
8037
8038 if (keylength <= 2048) {
8039 return DH_get_2048_224(NULL);
8040 }
8041
8042 /* In the case of a large request, return the strongest DH group that
8043 * we have predefined. Generating a group takes far too long to be
8044 * reasonable. */
8045 return DH_get_2048_256(NULL);
Kenny Root860d2702013-04-23 15:50:31 -07008046#endif
8047}
8048
8049/**
8050 * Call back to ask for Diffie-Hellman parameters
8051 */
8052static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
8053 int is_export __attribute__ ((unused)),
8054 int keylength) {
8055 JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
8056 DH* tmp_dh = dhGenerateParameters(keylength);
8057 JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
8058 return tmp_dh;
8059}
8060
8061static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
8062 // TODO selected curve based on keylength
8063 Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
8064 if (ec.get() == NULL) {
8065 return NULL;
8066 }
8067 return ec.release();
8068}
8069
8070/**
8071 * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
8072 */
8073static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
8074 int is_export __attribute__ ((unused)),
8075 int keylength) {
8076 JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
8077 AppData* appData = toAppData(ssl);
8078 if (appData->ephemeralEc.get() == NULL) {
8079 JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
8080 appData->ephemeralEc.reset(ecGenerateKey(keylength));
8081 }
8082 JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
8083 return appData->ephemeralEc.get();
8084}
8085
8086/*
8087 * public static native int SSL_CTX_new();
8088 */
8089static jlong NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
8090 Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
8091 if (sslCtx.get() == NULL) {
8092 throwExceptionIfNecessary(env, "SSL_CTX_new");
8093 return 0;
8094 }
8095 SSL_CTX_set_options(sslCtx.get(),
8096 SSL_OP_ALL
8097 // Note: We explicitly do not allow SSLv2 to be used.
8098 | SSL_OP_NO_SSLv2
8099 // We also disable session tickets for better compatibility b/2682876
8100 | SSL_OP_NO_TICKET
8101 // We also disable compression for better compatibility b/2710492 b/2710497
8102 | SSL_OP_NO_COMPRESSION
8103 // Because dhGenerateParameters uses DSA_generate_parameters_ex
8104 | SSL_OP_SINGLE_DH_USE
8105 // Because ecGenerateParameters uses a fixed named curve
8106 | SSL_OP_SINGLE_ECDH_USE);
8107
8108 int mode = SSL_CTX_get_mode(sslCtx.get());
8109 /*
8110 * Turn on "partial write" mode. This means that SSL_write() will
8111 * behave like Posix write() and possibly return after only
8112 * writing a partial buffer. Note: The alternative, perhaps
8113 * surprisingly, is not that SSL_write() always does full writes
8114 * but that it will force you to retry write calls having
8115 * preserved the full state of the original call. (This is icky
8116 * and undesirable.)
8117 */
8118 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
8119
8120 // Reuse empty buffers within the SSL_CTX to save memory
8121 mode |= SSL_MODE_RELEASE_BUFFERS;
8122
8123 SSL_CTX_set_mode(sslCtx.get(), mode);
8124
8125 SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
8126 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
8127 SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
8128 SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
8129 SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
8130 SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
8131
Alex Klyubin69c36472014-06-13 13:51:05 -07008132 // When TLS Channel ID extension is used, use the new version of it.
8133 sslCtx.get()->tlsext_channel_id_enabled_new = 1;
8134
Kenny Root860d2702013-04-23 15:50:31 -07008135 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
8136 return (jlong) sslCtx.release();
8137}
8138
8139/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008140 * public static native void SSL_CTX_free(long ssl_ctx)
Kenny Root860d2702013-04-23 15:50:31 -07008141 */
8142static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
8143 jclass, jlong ssl_ctx_address)
8144{
8145 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8146 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
8147 if (ssl_ctx == NULL) {
8148 return;
8149 }
8150 SSL_CTX_free(ssl_ctx);
8151}
8152
8153static void NativeCrypto_SSL_CTX_set_session_id_context(JNIEnv* env, jclass,
8154 jlong ssl_ctx_address, jbyteArray sid_ctx)
8155{
8156 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8157 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context sid_ctx=%p", ssl_ctx, sid_ctx);
8158 if (ssl_ctx == NULL) {
8159 return;
8160 }
8161
8162 ScopedByteArrayRO buf(env, sid_ctx);
8163 if (buf.get() == NULL) {
8164 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => threw exception", ssl_ctx);
8165 return;
8166 }
8167
8168 unsigned int length = buf.size();
8169 if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) {
8170 jniThrowException(env, "java/lang/IllegalArgumentException",
8171 "length > SSL_MAX_SSL_SESSION_ID_LENGTH");
8172 JNI_TRACE("NativeCrypto_SSL_CTX_set_session_id_context => length = %d", length);
8173 return;
8174 }
8175 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buf.get());
8176 int result = SSL_CTX_set_session_id_context(ssl_ctx, bytes, length);
8177 if (result == 0) {
8178 throwExceptionIfNecessary(env, "NativeCrypto_SSL_CTX_set_session_id_context");
8179 return;
8180 }
8181 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_set_session_id_context => ok", ssl_ctx);
8182}
8183
8184/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008185 * public static native int SSL_new(long ssl_ctx) throws SSLException;
Kenny Root860d2702013-04-23 15:50:31 -07008186 */
8187static jlong NativeCrypto_SSL_new(JNIEnv* env, jclass, jlong ssl_ctx_address)
8188{
8189 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
8190 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
8191 if (ssl_ctx == NULL) {
8192 return 0;
8193 }
8194 Unique_SSL ssl(SSL_new(ssl_ctx));
8195 if (ssl.get() == NULL) {
8196 throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
8197 "Unable to create SSL structure");
8198 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
8199 return 0;
8200 }
8201
Kenny Root02fb0572014-03-21 13:53:46 -07008202 /*
Kenny Rootde9b5862014-04-22 09:46:20 -07008203 * Create our special application data.
8204 */
8205 AppData* appData = AppData::create();
8206 if (appData == NULL) {
8207 throwSSLExceptionStr(env, "Unable to create application data");
8208 freeOpenSslErrorState();
8209 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new appData => 0", ssl_ctx);
8210 return 0;
8211 }
8212 SSL_set_app_data(ssl.get(), reinterpret_cast<char*>(appData));
8213
8214 /*
Kenny Root02fb0572014-03-21 13:53:46 -07008215 * Java code in class OpenSSLSocketImpl does the verification. Since
8216 * the callbacks do all the verification of the chain, this flag
8217 * simply controls whether to send protocol-level alerts or not.
8218 * SSL_VERIFY_NONE means don't send alerts and anything else means send
8219 * alerts.
Kenny Root860d2702013-04-23 15:50:31 -07008220 */
Kenny Root02fb0572014-03-21 13:53:46 -07008221 SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
Kenny Root860d2702013-04-23 15:50:31 -07008222
Kenny Rootde9b5862014-04-22 09:46:20 -07008223 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p appData=%p", ssl_ctx, ssl.get(), appData);
Kenny Root860d2702013-04-23 15:50:31 -07008224 return (jlong) ssl.release();
8225}
8226
8227
8228static void NativeCrypto_SSL_enable_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
8229{
8230 SSL* ssl = to_SSL(env, ssl_address, true);
8231 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_enable_tls_channel_id", ssl);
8232 if (ssl == NULL) {
8233 return;
8234 }
8235
8236 long ret = SSL_enable_tls_channel_id(ssl);
8237 if (ret != 1L) {
8238 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8239 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error enabling Channel ID");
Kenny Root86dd8322014-12-01 12:01:44 -08008240 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008241 JNI_TRACE("ssl=%p NativeCrypto_SSL_enable_tls_channel_id => error", ssl);
8242 return;
8243 }
8244}
8245
8246static jbyteArray NativeCrypto_SSL_get_tls_channel_id(JNIEnv* env, jclass, jlong ssl_address)
8247{
8248 SSL* ssl = to_SSL(env, ssl_address, true);
8249 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id", ssl);
8250 if (ssl == NULL) {
8251 return NULL;
8252 }
8253
8254 // Channel ID is 64 bytes long. Unfortunately, OpenSSL doesn't declare this length
8255 // as a constant anywhere.
8256 jbyteArray javaBytes = env->NewByteArray(64);
8257 ScopedByteArrayRW bytes(env, javaBytes);
8258 if (bytes.get() == NULL) {
8259 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => NULL", ssl);
8260 return NULL;
8261 }
8262
8263 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
8264 // Unfortunately, the SSL_get_tls_channel_id method below always returns 64 (upon success)
8265 // regardless of the number of bytes copied into the output buffer "tmp". Thus, the correctness
8266 // of this code currently relies on the "tmp" buffer being exactly 64 bytes long.
8267 long ret = SSL_get_tls_channel_id(ssl, tmp, 64);
8268 if (ret == 0) {
8269 // Channel ID either not set or did not verify
8270 JNI_TRACE("NativeCrypto_SSL_get_tls_channel_id(%p) => not available", ssl);
8271 return NULL;
8272 } else if (ret != 64) {
8273 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8274 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error getting Channel ID");
Kenny Root86dd8322014-12-01 12:01:44 -08008275 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008276 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_tls_channel_id => error, returned %ld", ssl, ret);
8277 return NULL;
8278 }
8279
8280 JNI_TRACE("ssl=%p NativeCrypto_NativeCrypto_SSL_get_tls_channel_id() => %p", ssl, javaBytes);
8281 return javaBytes;
8282}
8283
Kenny Root1ecc0482013-05-03 10:51:56 -07008284static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
Kenny Root37e58bb2014-11-25 14:29:25 -08008285 jlong ssl_address, jobject pkeyRef)
Kenny Root860d2702013-04-23 15:50:31 -07008286{
8287 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root37e58bb2014-11-25 14:29:25 -08008288 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root1ecc0482013-05-03 10:51:56 -07008289 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
Kenny Root860d2702013-04-23 15:50:31 -07008290 if (ssl == NULL) {
8291 return;
8292 }
8293
8294 if (pkey == NULL) {
Kenny Root1ecc0482013-05-03 10:51:56 -07008295 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008296 return;
8297 }
8298
8299 // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
8300 // Unfortunately, the default value is 1 and it's only changed to 0 just
8301 // before the handshake starts (see NativeCrypto_SSL_do_handshake).
8302 ssl->server = 0;
8303 long ret = SSL_set1_tls_channel_id(ssl, pkey);
8304
8305 if (ret != 1L) {
8306 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8307 throwSSLExceptionWithSslErrors(
8308 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
Kenny Root86dd8322014-12-01 12:01:44 -08008309 safeSslClear(ssl);
Kenny Root1ecc0482013-05-03 10:51:56 -07008310 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008311 return;
8312 }
Kenny Root1ecc0482013-05-03 10:51:56 -07008313 // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
8314 // we have an external reference from the caller such as an OpenSSLKey,
8315 // so we manually increment the reference count here.
Adam Langleyca6d8d32015-06-04 18:03:28 -07008316#if defined(OPENSSL_IS_BORINGSSL)
8317 EVP_PKEY_up_ref(pkey);
8318#else
Kenny Root860d2702013-04-23 15:50:31 -07008319 CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
Adam Langleyca6d8d32015-06-04 18:03:28 -07008320#endif
Kenny Root860d2702013-04-23 15:50:31 -07008321
Kenny Root1ecc0482013-05-03 10:51:56 -07008322 JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008323}
8324
Kenny Root37e58bb2014-11-25 14:29:25 -08008325static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address,
8326 jobject pkeyRef) {
Kenny Root860d2702013-04-23 15:50:31 -07008327 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root37e58bb2014-11-25 14:29:25 -08008328 EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
Kenny Root1ecc0482013-05-03 10:51:56 -07008329 JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
Kenny Root860d2702013-04-23 15:50:31 -07008330 if (ssl == NULL) {
8331 return;
8332 }
8333
8334 if (pkey == NULL) {
Kenny Root1ecc0482013-05-03 10:51:56 -07008335 JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008336 return;
8337 }
8338
8339 int ret = SSL_use_PrivateKey(ssl, pkey);
8340 if (ret != 1) {
8341 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8342 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
Kenny Root86dd8322014-12-01 12:01:44 -08008343 safeSslClear(ssl);
Kenny Root1ecc0482013-05-03 10:51:56 -07008344 JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008345 return;
8346 }
8347 // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
8348 // but we have an external reference from the caller such as an
8349 // OpenSSLKey, so we manually increment the reference count here.
Adam Langleyca6d8d32015-06-04 18:03:28 -07008350#if defined(OPENSSL_IS_BORINGSSL)
8351 EVP_PKEY_up_ref(pkey);
8352#else
Kenny Root860d2702013-04-23 15:50:31 -07008353 CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
Adam Langleyca6d8d32015-06-04 18:03:28 -07008354#endif
Kenny Root860d2702013-04-23 15:50:31 -07008355
Kenny Root1ecc0482013-05-03 10:51:56 -07008356 JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008357}
8358
8359static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
Kenny Root0e9746b2013-09-12 15:14:48 -07008360 jlong ssl_address, jlongArray certificatesJava)
Kenny Root860d2702013-04-23 15:50:31 -07008361{
8362 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root0e9746b2013-09-12 15:14:48 -07008363 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificatesJava);
Kenny Root860d2702013-04-23 15:50:31 -07008364 if (ssl == NULL) {
8365 return;
8366 }
8367
Kenny Root0e9746b2013-09-12 15:14:48 -07008368 if (certificatesJava == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -07008369 jniThrowNullPointerException(env, "certificates == null");
8370 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
8371 return;
8372 }
8373
Kenny Root0e9746b2013-09-12 15:14:48 -07008374 size_t length = env->GetArrayLength(certificatesJava);
Kenny Root860d2702013-04-23 15:50:31 -07008375 if (length == 0) {
8376 jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
8377 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
8378 return;
8379 }
8380
Kenny Root0e9746b2013-09-12 15:14:48 -07008381 ScopedLongArrayRO certificates(env, certificatesJava);
8382 if (certificates.get() == NULL) {
8383 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
8384 return;
8385 }
8386
8387 Unique_X509 serverCert(
8388 X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[0]))));
8389 if (serverCert.get() == NULL) {
8390 // Note this shouldn't happen since we checked the number of certificates above.
8391 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
8392 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
8393 return;
8394 }
8395
Adam Langleyde5225d2014-10-06 15:55:30 -07008396 int ret = SSL_use_certificate(ssl, serverCert.get());
8397 if (ret != 1) {
8398 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8399 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
Kenny Root86dd8322014-12-01 12:01:44 -08008400 safeSslClear(ssl);
Adam Langleyde5225d2014-10-06 15:55:30 -07008401 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
8402 return;
8403 }
8404 OWNERSHIP_TRANSFERRED(serverCert);
8405
8406#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root74f1a2a2013-09-11 15:24:38 -07008407 Unique_sk_X509 chain(sk_X509_new_null());
8408 if (chain.get() == NULL) {
8409 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
8410 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
8411 return;
8412 }
8413
Kenny Root0e9746b2013-09-12 15:14:48 -07008414 for (size_t i = 1; i < length; i++) {
8415 Unique_X509 cert(
8416 X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[i]))));
Kenny Root74f1a2a2013-09-11 15:24:38 -07008417 if (cert.get() == NULL || !sk_X509_push(chain.get(), cert.get())) {
Kenny Root860d2702013-04-23 15:50:31 -07008418 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8419 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
Kenny Root86dd8322014-12-01 12:01:44 -08008420 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008421 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
8422 return;
8423 }
Kenny Root74f1a2a2013-09-11 15:24:38 -07008424 OWNERSHIP_TRANSFERRED(cert);
Kenny Root860d2702013-04-23 15:50:31 -07008425 }
8426
Kenny Root860d2702013-04-23 15:50:31 -07008427 int chainResult = SSL_use_certificate_chain(ssl, chain.get());
8428 if (chainResult == 0) {
8429 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
8430 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
8431 ssl);
8432 return;
Kenny Root860d2702013-04-23 15:50:31 -07008433 }
Kenny Root74f1a2a2013-09-11 15:24:38 -07008434 OWNERSHIP_TRANSFERRED(chain);
Adam Langleyde5225d2014-10-06 15:55:30 -07008435#else
8436 for (size_t i = 1; i < length; i++) {
8437 Unique_X509 cert(
8438 X509_dup_nocopy(reinterpret_cast<X509*>(static_cast<uintptr_t>(certificates[i]))));
8439 if (cert.get() == NULL || !SSL_add0_chain_cert(ssl, cert.get())) {
8440 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8441 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
Kenny Root86dd8322014-12-01 12:01:44 -08008442 safeSslClear(ssl);
Adam Langleyde5225d2014-10-06 15:55:30 -07008443 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
8444 return;
8445 }
8446 OWNERSHIP_TRANSFERRED(cert);
8447 }
8448#endif
Kenny Root860d2702013-04-23 15:50:31 -07008449
8450 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
8451}
8452
8453static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jlong ssl_address)
8454{
8455 SSL* ssl = to_SSL(env, ssl_address, true);
8456 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
8457 if (ssl == NULL) {
8458 return;
8459 }
8460 int ret = SSL_check_private_key(ssl);
8461 if (ret != 1) {
8462 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
Kenny Root86dd8322014-12-01 12:01:44 -08008463 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008464 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
8465 return;
8466 }
8467 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
8468}
8469
8470static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
8471 jlong ssl_address, jobjectArray principals)
8472{
8473 SSL* ssl = to_SSL(env, ssl_address, true);
8474 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
8475 if (ssl == NULL) {
8476 return;
8477 }
8478
8479 if (principals == NULL) {
8480 jniThrowNullPointerException(env, "principals == null");
8481 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
8482 return;
8483 }
8484
8485 int length = env->GetArrayLength(principals);
8486 if (length == 0) {
8487 jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
8488 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
8489 return;
8490 }
8491
8492 Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
8493 if (principalsStack.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07008494 jniThrowOutOfMemory(env, "Unable to allocate principal stack");
Kenny Root860d2702013-04-23 15:50:31 -07008495 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
8496 return;
8497 }
8498 for (int i = 0; i < length; i++) {
8499 ScopedLocalRef<jbyteArray> principal(env,
8500 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
8501 if (principal.get() == NULL) {
8502 jniThrowNullPointerException(env, "principals element == null");
8503 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
8504 return;
8505 }
8506
8507 ScopedByteArrayRO buf(env, principal.get());
8508 if (buf.get() == NULL) {
8509 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
8510 return;
8511 }
8512 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
8513 Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
8514
8515 if (principalX509Name.get() == NULL) {
8516 ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
8517 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
Kenny Root86dd8322014-12-01 12:01:44 -08008518 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008519 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
8520 ssl);
8521 return;
8522 }
8523
8524 if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
Kenny Root923e3c52013-05-01 12:17:23 -07008525 jniThrowOutOfMemory(env, "Unable to push principal");
Kenny Root860d2702013-04-23 15:50:31 -07008526 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
8527 return;
8528 }
8529 }
8530
8531 SSL_set_client_CA_list(ssl, principalsStack.release());
8532 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
8533}
8534
8535/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008536 * public static native long SSL_get_mode(long ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008537 */
8538static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jlong ssl_address) {
8539 SSL* ssl = to_SSL(env, ssl_address, true);
8540 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
8541 if (ssl == NULL) {
8542 return 0;
8543 }
8544 long mode = SSL_get_mode(ssl);
8545 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
8546 return mode;
8547}
8548
8549/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008550 * public static native long SSL_set_mode(long ssl, long mode);
Kenny Root860d2702013-04-23 15:50:31 -07008551 */
8552static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
8553 jlong ssl_address, jlong mode) {
8554 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root6c523c02014-11-25 13:33:51 -08008555 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, (long long) mode);
Kenny Root860d2702013-04-23 15:50:31 -07008556 if (ssl == NULL) {
8557 return 0;
8558 }
8559 long result = SSL_set_mode(ssl, mode);
8560 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
8561 return result;
8562}
8563
8564/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008565 * public static native long SSL_clear_mode(long ssl, long mode);
Kenny Root860d2702013-04-23 15:50:31 -07008566 */
8567static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
8568 jlong ssl_address, jlong mode) {
8569 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root6c523c02014-11-25 13:33:51 -08008570 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, (long long) mode);
Kenny Root860d2702013-04-23 15:50:31 -07008571 if (ssl == NULL) {
8572 return 0;
8573 }
8574 long result = SSL_clear_mode(ssl, mode);
8575 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
8576 return result;
8577}
8578
8579/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008580 * public static native long SSL_get_options(long ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008581 */
8582static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
8583 jlong ssl_address) {
8584 SSL* ssl = to_SSL(env, ssl_address, true);
8585 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
8586 if (ssl == NULL) {
8587 return 0;
8588 }
8589 long options = SSL_get_options(ssl);
8590 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
8591 return options;
8592}
8593
8594/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008595 * public static native long SSL_set_options(long ssl, long options);
Kenny Root860d2702013-04-23 15:50:31 -07008596 */
8597static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
8598 jlong ssl_address, jlong options) {
8599 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root6c523c02014-11-25 13:33:51 -08008600 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, (long long) options);
Kenny Root860d2702013-04-23 15:50:31 -07008601 if (ssl == NULL) {
8602 return 0;
8603 }
8604 long result = SSL_set_options(ssl, options);
8605 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
8606 return result;
8607}
8608
8609/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00008610 * public static native long SSL_clear_options(long ssl, long options);
Kenny Root860d2702013-04-23 15:50:31 -07008611 */
8612static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
8613 jlong ssl_address, jlong options) {
8614 SSL* ssl = to_SSL(env, ssl_address, true);
Kenny Root6c523c02014-11-25 13:33:51 -08008615 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, (long long) options);
Kenny Root860d2702013-04-23 15:50:31 -07008616 if (ssl == NULL) {
8617 return 0;
8618 }
8619 long result = SSL_clear_options(ssl, options);
8620 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
8621 return result;
8622}
8623
Alex Klyubin01cce892014-05-09 03:44:42 -07008624
8625static void NativeCrypto_SSL_use_psk_identity_hint(JNIEnv* env, jclass,
8626 jlong ssl_address, jstring identityHintJava)
8627{
8628 SSL* ssl = to_SSL(env, ssl_address, true);
8629 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_psk_identity_hint identityHint=%p",
8630 ssl, identityHintJava);
8631 if (ssl == NULL) {
8632 return;
8633 }
8634
8635 int ret;
8636 if (identityHintJava == NULL) {
8637 ret = SSL_use_psk_identity_hint(ssl, NULL);
8638 } else {
8639 ScopedUtfChars identityHint(env, identityHintJava);
8640 if (identityHint.c_str() == NULL) {
8641 throwSSLExceptionStr(env, "Failed to obtain identityHint bytes");
8642 return;
8643 }
8644 ret = SSL_use_psk_identity_hint(ssl, identityHint.c_str());
8645 }
8646
8647 if (ret != 1) {
8648 int sslErrorCode = SSL_get_error(ssl, ret);
8649 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Failed to set PSK identity hint");
Kenny Root86dd8322014-12-01 12:01:44 -08008650 safeSslClear(ssl);
Alex Klyubin01cce892014-05-09 03:44:42 -07008651 }
8652}
8653
8654static void NativeCrypto_set_SSL_psk_client_callback_enabled(JNIEnv* env, jclass,
8655 jlong ssl_address, jboolean enabled)
8656{
8657 SSL* ssl = to_SSL(env, ssl_address, true);
8658 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_client_callback_enabled(%d)",
8659 ssl, enabled);
8660 if (ssl == NULL) {
8661 return;
8662 }
8663
8664 SSL_set_psk_client_callback(ssl, (enabled) ? psk_client_callback : NULL);
8665}
8666
8667static void NativeCrypto_set_SSL_psk_server_callback_enabled(JNIEnv* env, jclass,
8668 jlong ssl_address, jboolean enabled)
8669{
8670 SSL* ssl = to_SSL(env, ssl_address, true);
8671 JNI_TRACE("ssl=%p NativeCrypto_set_SSL_psk_server_callback_enabled(%d)",
8672 ssl, enabled);
8673 if (ssl == NULL) {
8674 return;
8675 }
8676
8677 SSL_set_psk_server_callback(ssl, (enabled) ? psk_server_callback : NULL);
8678}
8679
Alex Klyubin2d089e12013-11-21 10:28:08 -08008680static jlongArray NativeCrypto_SSL_get_ciphers(JNIEnv* env, jclass, jlong ssl_address)
8681{
8682 SSL* ssl = to_SSL(env, ssl_address, true);
8683 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
8684
8685 STACK_OF(SSL_CIPHER)* cipherStack = SSL_get_ciphers(ssl);
8686 int count = (cipherStack != NULL) ? sk_SSL_CIPHER_num(cipherStack) : 0;
8687 ScopedLocalRef<jlongArray> ciphersArray(env, env->NewLongArray(count));
8688 ScopedLongArrayRW ciphers(env, ciphersArray.get());
8689 for (int i = 0; i < count; i++) {
8690 ciphers[i] = reinterpret_cast<jlong>(sk_SSL_CIPHER_value(cipherStack, i));
8691 }
8692
8693 JNI_TRACE("NativeCrypto_SSL_get_ciphers(%p) => %p [size=%d]", ssl, ciphersArray.get(), count);
8694 return ciphersArray.release();
8695}
8696
8697static jint NativeCrypto_get_SSL_CIPHER_algorithm_mkey(JNIEnv* env, jclass,
8698 jlong ssl_cipher_address)
8699{
8700 SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
Adam Langley8d18c8a2015-05-12 19:23:52 -07008701 JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_mkey => %ld", cipher, (long) cipher->algorithm_mkey);
Alex Klyubin2d089e12013-11-21 10:28:08 -08008702 return cipher->algorithm_mkey;
8703}
8704
8705static jint NativeCrypto_get_SSL_CIPHER_algorithm_auth(JNIEnv* env, jclass,
8706 jlong ssl_cipher_address)
8707{
8708 SSL_CIPHER* cipher = to_SSL_CIPHER(env, ssl_cipher_address, true);
Adam Langley8d18c8a2015-05-12 19:23:52 -07008709 JNI_TRACE("cipher=%p get_SSL_CIPHER_algorithm_auth => %ld", cipher, (long) cipher->algorithm_auth);
Alex Klyubin2d089e12013-11-21 10:28:08 -08008710 return cipher->algorithm_auth;
8711}
8712
Kenny Root860d2702013-04-23 15:50:31 -07008713/**
8714 * Sets the ciphers suites that are enabled in the SSL
8715 */
Kenny Rootd65ea6d2015-06-10 09:52:58 -07008716static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass, jlong ssl_address,
8717 jobjectArray cipherSuites) {
Kenny Root860d2702013-04-23 15:50:31 -07008718 SSL* ssl = to_SSL(env, ssl_address, true);
8719 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
8720 if (ssl == NULL) {
8721 return;
8722 }
8723 if (cipherSuites == NULL) {
8724 jniThrowNullPointerException(env, "cipherSuites == null");
8725 return;
8726 }
8727
Kenny Root860d2702013-04-23 15:50:31 -07008728 int length = env->GetArrayLength(cipherSuites);
Kenny Rootd65ea6d2015-06-10 09:52:58 -07008729
8730 /*
8731 * Special case for empty cipher list. This is considered an error by the
8732 * SSL_set_cipher_list API, but Java allows this silly configuration.
8733 * However, the SSL cipher list is still set even when SSL_set_cipher_list
8734 * returns 0 in this case. Just to make sure, we check the resulting cipher
8735 * list to make sure it's zero length.
8736 */
8737 if (length == 0) {
8738 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty", ssl);
8739 SSL_set_cipher_list(ssl, "");
8740 freeOpenSslErrorState();
8741 if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) != 0) {
8742 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=empty => error", ssl);
8743 jniThrowRuntimeException(env, "SSL_set_cipher_list did not update ciphers!");
8744 }
8745 return;
8746 }
8747
Adam Langleyde5225d2014-10-06 15:55:30 -07008748 static const char noSSLv2[] = "!SSLv2";
8749 size_t cipherStringLen = strlen(noSSLv2);
8750
Kenny Root860d2702013-04-23 15:50:31 -07008751 for (int i = 0; i < length; i++) {
8752 ScopedLocalRef<jstring> cipherSuite(env,
8753 reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8754 ScopedUtfChars c(env, cipherSuite.get());
8755 if (c.c_str() == NULL) {
8756 return;
8757 }
Adam Langleyde5225d2014-10-06 15:55:30 -07008758
8759 if (cipherStringLen + 1 < cipherStringLen) {
8760 jniThrowException(env, "java/lang/IllegalArgumentException",
8761 "Overflow in cipher suite strings");
8762 return;
Kenny Root860d2702013-04-23 15:50:31 -07008763 }
Adam Langleyde5225d2014-10-06 15:55:30 -07008764 cipherStringLen += 1; /* For the separating colon */
8765
8766 if (cipherStringLen + c.size() < cipherStringLen) {
8767 jniThrowException(env, "java/lang/IllegalArgumentException",
8768 "Overflow in cipher suite strings");
8769 return;
Kenny Root860d2702013-04-23 15:50:31 -07008770 }
Adam Langleyde5225d2014-10-06 15:55:30 -07008771 cipherStringLen += c.size();
Kenny Root860d2702013-04-23 15:50:31 -07008772 }
8773
Adam Langleyde5225d2014-10-06 15:55:30 -07008774 if (cipherStringLen + 1 < cipherStringLen) {
8775 jniThrowException(env, "java/lang/IllegalArgumentException",
8776 "Overflow in cipher suite strings");
8777 return;
8778 }
8779 cipherStringLen += 1; /* For final NUL. */
8780
8781 UniquePtr<char[]> cipherString(new char[cipherStringLen]);
8782 if (cipherString.get() == NULL) {
8783 jniThrowOutOfMemory(env, "Unable to alloc cipher string");
8784 return;
8785 }
8786 memcpy(cipherString.get(), noSSLv2, strlen(noSSLv2));
8787 size_t j = strlen(noSSLv2);
8788
8789 for (int i = 0; i < length; i++) {
8790 ScopedLocalRef<jstring> cipherSuite(env,
8791 reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
8792 ScopedUtfChars c(env, cipherSuite.get());
8793
8794 cipherString[j++] = ':';
8795 memcpy(&cipherString[j], c.c_str(), c.size());
8796 j += c.size();
8797 }
8798
8799 cipherString[j++] = 0;
8800 if (j != cipherStringLen) {
8801 jniThrowException(env, "java/lang/IllegalArgumentException",
8802 "Internal error");
8803 return;
8804 }
8805
Kenny Rootd65ea6d2015-06-10 09:52:58 -07008806 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%s", ssl, cipherString.get());
Adam Langleyde5225d2014-10-06 15:55:30 -07008807 if (!SSL_set_cipher_list(ssl, cipherString.get())) {
Kenny Root860d2702013-04-23 15:50:31 -07008808 freeOpenSslErrorState();
8809 jniThrowException(env, "java/lang/IllegalArgumentException",
8810 "Illegal cipher suite strings.");
Adam Langleyde5225d2014-10-06 15:55:30 -07008811 return;
Kenny Root860d2702013-04-23 15:50:31 -07008812 }
8813}
8814
Kenny Rootf878e432013-11-08 11:37:48 -08008815static void NativeCrypto_SSL_set_accept_state(JNIEnv* env, jclass, jlong sslRef) {
8816 SSL* ssl = to_SSL(env, sslRef, true);
8817 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_accept_state", ssl);
8818 if (ssl == NULL) {
8819 return;
8820 }
8821 SSL_set_accept_state(ssl);
8822}
8823
8824static void NativeCrypto_SSL_set_connect_state(JNIEnv* env, jclass, jlong sslRef) {
8825 SSL* ssl = to_SSL(env, sslRef, true);
8826 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_connect_state", ssl);
8827 if (ssl == NULL) {
8828 return;
8829 }
8830 SSL_set_connect_state(ssl);
8831}
8832
Kenny Root860d2702013-04-23 15:50:31 -07008833/**
8834 * Sets certificate expectations, especially for server to request client auth
8835 */
8836static void NativeCrypto_SSL_set_verify(JNIEnv* env,
8837 jclass, jlong ssl_address, jint mode)
8838{
8839 SSL* ssl = to_SSL(env, ssl_address, true);
8840 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
8841 if (ssl == NULL) {
8842 return;
8843 }
8844 SSL_set_verify(ssl, (int)mode, NULL);
8845}
8846
8847/**
8848 * Sets the ciphers suites that are enabled in the SSL
8849 */
8850static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
8851 jlong ssl_address, jlong ssl_session_address)
8852{
8853 SSL* ssl = to_SSL(env, ssl_address, true);
8854 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
8855 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
8856 if (ssl == NULL) {
8857 return;
8858 }
8859
8860 int ret = SSL_set_session(ssl, ssl_session);
8861 if (ret != 1) {
8862 /*
8863 * Translate the error, and throw if it turns out to be a real
8864 * problem.
8865 */
8866 int sslErrorCode = SSL_get_error(ssl, ret);
8867 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
8868 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
Kenny Root86dd8322014-12-01 12:01:44 -08008869 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008870 }
8871 }
8872}
8873
8874/**
8875 * Sets the ciphers suites that are enabled in the SSL
8876 */
8877static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
8878 jlong ssl_address, jboolean creation_enabled)
8879{
8880 SSL* ssl = to_SSL(env, ssl_address, true);
8881 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
8882 ssl, creation_enabled);
8883 if (ssl == NULL) {
8884 return;
8885 }
Adam Langleyde5225d2014-10-06 15:55:30 -07008886
8887#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07008888 SSL_set_session_creation_enabled(ssl, creation_enabled);
Adam Langleyde5225d2014-10-06 15:55:30 -07008889#else
8890 if (creation_enabled) {
8891 SSL_clear_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8892 } else {
8893 SSL_set_mode(ssl, SSL_MODE_NO_SESSION_CREATION);
8894 }
8895#endif
Kenny Root860d2702013-04-23 15:50:31 -07008896}
8897
Kenny Root28328c32016-05-12 14:15:24 -07008898static jboolean NativeCrypto_SSL_session_reused(JNIEnv* env, jclass, jlong ssl_address) {
8899 SSL* ssl = to_SSL(env, ssl_address, true);
8900 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused", ssl);
8901 if (ssl == nullptr) {
8902 return JNI_FALSE;
8903 }
8904
8905 int reused = SSL_session_reused(ssl);
8906 JNI_TRACE("ssl=%p NativeCrypto_SSL_session_reused => %d", ssl, reused);
8907 return reused == 1 ? JNI_TRUE : JNI_FALSE;
8908}
8909
Adam Langley295b30e2015-06-26 17:32:18 -07008910static void NativeCrypto_SSL_set_reject_peer_renegotiations(JNIEnv* env, jclass,
8911 jlong ssl_address, jboolean reject_renegotiations)
8912{
8913 SSL* ssl = to_SSL(env, ssl_address, true);
8914 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_reject_peer_renegotiations reject_renegotiations=%d",
8915 ssl, reject_renegotiations);
8916 if (ssl == NULL) {
8917 return;
8918 }
8919
8920#if defined(OPENSSL_IS_BORINGSSL)
8921 SSL_set_reject_peer_renegotiations(ssl, reject_renegotiations);
8922#else
8923 (void) reject_renegotiations;
8924 /* OpenSSL doesn't support this call and accepts renegotiation requests by
8925 * default. */
8926#endif
8927}
8928
Kenny Root860d2702013-04-23 15:50:31 -07008929static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
8930 jlong ssl_address, jstring hostname)
8931{
8932 SSL* ssl = to_SSL(env, ssl_address, true);
8933 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
8934 ssl, hostname);
8935 if (ssl == NULL) {
8936 return;
8937 }
8938
8939 ScopedUtfChars hostnameChars(env, hostname);
8940 if (hostnameChars.c_str() == NULL) {
8941 return;
8942 }
8943 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s",
8944 ssl, hostnameChars.c_str());
8945
8946 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
8947 if (ret != 1) {
8948 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
Kenny Root86dd8322014-12-01 12:01:44 -08008949 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07008950 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
8951 return;
8952 }
8953 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
8954}
8955
8956static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jlong ssl_address) {
8957 SSL* ssl = to_SSL(env, ssl_address, true);
8958 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
8959 if (ssl == NULL) {
8960 return NULL;
8961 }
8962 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
8963 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
8964 return env->NewStringUTF(servername);
8965}
8966
8967/**
Kenny Root6fcf0cb2013-06-24 15:54:18 -07008968 * A common selection path for both NPN and ALPN since they're essentially the
8969 * same protocol. The list of protocols in "primary" is considered the order
8970 * which should take precedence.
8971 */
Elliott Hughesab3c6532013-07-30 15:42:28 -07008972static int proto_select(SSL* ssl __attribute__ ((unused)),
8973 unsigned char **out, unsigned char *outLength,
Kenny Root6fcf0cb2013-06-24 15:54:18 -07008974 const unsigned char *primary, const unsigned int primaryLength,
8975 const unsigned char *secondary, const unsigned int secondaryLength) {
Kenny Root5a8ca5b2014-08-27 13:53:03 -07008976 if (primary != NULL && secondary != NULL) {
Kenny Root6fcf0cb2013-06-24 15:54:18 -07008977 JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
8978
8979 int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
8980 secondaryLength);
8981 switch (status) {
8982 case OPENSSL_NPN_NEGOTIATED:
8983 JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
Kenny Rootfc7924b2014-03-10 10:29:10 -07008984 return SSL_TLSEXT_ERR_OK;
Kenny Root6fcf0cb2013-06-24 15:54:18 -07008985 break;
8986 case OPENSSL_NPN_UNSUPPORTED:
8987 JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
8988 break;
8989 case OPENSSL_NPN_NO_OVERLAP:
8990 JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
8991 break;
8992 }
8993 } else {
Kenny Rootfc7924b2014-03-10 10:29:10 -07008994 if (out != NULL && outLength != NULL) {
8995 *out = NULL;
8996 *outLength = 0;
8997 }
Kenny Root6fcf0cb2013-06-24 15:54:18 -07008998 JNI_TRACE("protocols=NULL");
8999 }
Kenny Rootfc7924b2014-03-10 10:29:10 -07009000 return SSL_TLSEXT_ERR_NOACK;
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009001}
9002
9003/**
9004 * Callback for the server to select an ALPN protocol.
9005 */
9006static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
9007 const unsigned char *in, unsigned int inlen, void *) {
9008 JNI_TRACE("ssl=%p alpn_select_callback", ssl);
9009
9010 AppData* appData = toAppData(ssl);
9011 JNI_TRACE("AppData=%p", appData);
9012
9013 return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
9014 reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
9015 appData->alpnProtocolsLength, in, inlen);
9016}
9017
9018/**
9019 * Callback for the client to select an NPN protocol.
Kenny Root860d2702013-04-23 15:50:31 -07009020 */
Elliott Hughesab3c6532013-07-30 15:42:28 -07009021static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
9022 const unsigned char* in, unsigned int inlen, void*)
Kenny Root860d2702013-04-23 15:50:31 -07009023{
9024 JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
9025
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009026 AppData* appData = toAppData(ssl);
9027 JNI_TRACE("AppData=%p", appData);
9028
Kenny Root860d2702013-04-23 15:50:31 -07009029 // Enable False Start on the client if the server understands NPN
9030 // http://www.imperialviolet.org/2012/04/11/falsestart.html
9031 SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
9032
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009033 return proto_select(ssl, out, outlen, in, inlen,
9034 reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
9035 appData->npnProtocolsLength);
Kenny Root860d2702013-04-23 15:50:31 -07009036}
9037
9038/**
9039 * Callback for the server to advertise available protocols.
9040 */
9041static int next_protos_advertised_callback(SSL* ssl,
9042 const unsigned char **out, unsigned int *outlen, void *)
9043{
9044 JNI_TRACE("ssl=%p next_protos_advertised_callback", ssl);
9045 AppData* appData = toAppData(ssl);
9046 unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
9047 if (npnProtocols != NULL) {
9048 *out = npnProtocols;
9049 *outlen = appData->npnProtocolsLength;
Kenny Rootfc7924b2014-03-10 10:29:10 -07009050 return SSL_TLSEXT_ERR_OK;
9051 } else {
9052 *out = NULL;
Kenny Root2a5460f2014-03-10 13:04:32 -07009053 *outlen = 0;
Kenny Rootfc7924b2014-03-10 10:29:10 -07009054 return SSL_TLSEXT_ERR_NOACK;
Kenny Root860d2702013-04-23 15:50:31 -07009055 }
Kenny Root860d2702013-04-23 15:50:31 -07009056}
9057
9058static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
9059{
9060 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
9061 if (ssl_ctx == NULL) {
9062 return;
9063 }
9064 SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); // client
9065 SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_protos_advertised_callback, NULL); // server
9066}
9067
9068static void NativeCrypto_SSL_CTX_disable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
9069{
9070 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
9071 if (ssl_ctx == NULL) {
9072 return;
9073 }
9074 SSL_CTX_set_next_proto_select_cb(ssl_ctx, NULL, NULL); // client
9075 SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, NULL, NULL); // server
9076}
9077
9078static jbyteArray NativeCrypto_SSL_get_npn_negotiated_protocol(JNIEnv* env, jclass,
9079 jlong ssl_address)
9080{
9081 SSL* ssl = to_SSL(env, ssl_address, true);
9082 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_npn_negotiated_protocol", ssl);
9083 if (ssl == NULL) {
9084 return NULL;
9085 }
9086 const jbyte* npn;
9087 unsigned npnLength;
9088 SSL_get0_next_proto_negotiated(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
9089 if (npnLength == 0) {
9090 return NULL;
9091 }
9092 jbyteArray result = env->NewByteArray(npnLength);
9093 if (result != NULL) {
9094 env->SetByteArrayRegion(result, 0, npnLength, npn);
9095 }
9096 return result;
9097}
9098
Kenny Rootf8a9b542014-03-31 09:41:48 -07009099static int NativeCrypto_SSL_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_address,
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009100 jbyteArray protos) {
Kenny Rootf8a9b542014-03-31 09:41:48 -07009101 SSL* ssl = to_SSL(env, ssl_address, true);
9102 if (ssl == NULL) {
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009103 return 0;
9104 }
9105
Kenny Rootf8a9b542014-03-31 09:41:48 -07009106 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p", ssl, protos);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009107
9108 if (protos == NULL) {
Kenny Rootf8a9b542014-03-31 09:41:48 -07009109 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=NULL", ssl);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009110 return 1;
9111 }
9112
9113 ScopedByteArrayRO protosBytes(env, protos);
9114 if (protosBytes.get() == NULL) {
Kenny Rootf8a9b542014-03-31 09:41:48 -07009115 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => protosBytes == NULL", ssl,
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009116 protos);
9117 return 0;
9118 }
9119
9120 const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
Kenny Rootf8a9b542014-03-31 09:41:48 -07009121 int ret = SSL_set_alpn_protos(ssl, tmp, protosBytes.size());
9122 JNI_TRACE("ssl=%p SSL_set_alpn_protos protos=%p => ret=%d", ssl, protos, ret);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009123 return ret;
9124}
9125
9126static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
9127 jlong ssl_address)
9128{
9129 SSL* ssl = to_SSL(env, ssl_address, true);
9130 JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
9131 if (ssl == NULL) {
9132 return NULL;
9133 }
9134 const jbyte* npn;
9135 unsigned npnLength;
9136 SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
9137 if (npnLength == 0) {
9138 return NULL;
9139 }
9140 jbyteArray result = env->NewByteArray(npnLength);
9141 if (result != NULL) {
9142 env->SetByteArrayRegion(result, 0, npnLength, npn);
9143 }
9144 return result;
9145}
9146
Kenny Rootbcdb80d2013-05-28 14:51:51 -07009147#ifdef WITH_JNI_TRACE_KEYS
9148static inline char hex_char(unsigned char in)
9149{
9150 if (in < 10) {
9151 return '0' + in;
9152 } else if (in <= 0xF0) {
9153 return 'A' + in - 10;
9154 } else {
9155 return '?';
9156 }
9157}
9158
9159static void hex_string(char **dest, unsigned char* input, int len)
9160{
9161 *dest = (char*) malloc(len * 2 + 1);
9162 char *output = *dest;
9163 for (int i = 0; i < len; i++) {
9164 *output++ = hex_char(input[i] >> 4);
9165 *output++ = hex_char(input[i] & 0xF);
9166 }
9167 *output = '\0';
9168}
9169
9170static void debug_print_session_key(SSL_SESSION* session)
9171{
9172 char *session_id_str;
9173 char *master_key_str;
9174 const char *key_type;
9175 char *keyline;
9176
9177 hex_string(&session_id_str, session->session_id, session->session_id_length);
9178 hex_string(&master_key_str, session->master_key, session->master_key_length);
9179
9180 X509* peer = SSL_SESSION_get0_peer(session);
9181 EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
9182 switch (EVP_PKEY_type(pkey->type)) {
9183 case EVP_PKEY_RSA:
9184 key_type = "RSA";
9185 break;
9186 case EVP_PKEY_DSA:
9187 key_type = "DSA";
9188 break;
9189 case EVP_PKEY_EC:
9190 key_type = "EC";
9191 break;
9192 default:
9193 key_type = "Unknown";
9194 break;
9195 }
9196
9197 asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
9198 master_key_str);
9199 JNI_TRACE("ssl_session=%p %s", session, keyline);
9200
9201 free(session_id_str);
9202 free(master_key_str);
9203 free(keyline);
9204}
9205#endif /* WITH_JNI_TRACE_KEYS */
9206
Kenny Root860d2702013-04-23 15:50:31 -07009207/**
9208 * Perform SSL handshake
9209 */
Kenny Rootf878e432013-11-08 11:37:48 -08009210static jlong NativeCrypto_SSL_do_handshake_bio(JNIEnv* env, jclass, jlong ssl_address,
9211 jlong rbioRef, jlong wbioRef, jobject shc, jboolean client_mode, jbyteArray npnProtocols,
9212 jbyteArray alpnProtocols) {
9213 SSL* ssl = to_SSL(env, ssl_address, true);
9214 BIO* rbio = reinterpret_cast<BIO*>(rbioRef);
9215 BIO* wbio = reinterpret_cast<BIO*>(wbioRef);
Kenny Rootde9b5862014-04-22 09:46:20 -07009216 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio rbio=%p wbio=%p shc=%p client_mode=%d npn=%p",
9217 ssl, rbio, wbio, shc, client_mode, npnProtocols);
Kenny Rootf878e432013-11-08 11:37:48 -08009218 if (ssl == NULL) {
9219 return 0;
9220 }
9221 if (shc == NULL) {
9222 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9223 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio sslHandshakeCallbacks == null => 0", ssl);
9224 return 0;
9225 }
9226
9227 if (rbio == NULL || wbio == NULL) {
9228 jniThrowNullPointerException(env, "rbio == null || wbio == null");
9229 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => rbio == null || wbio == NULL", ssl);
9230 return 0;
9231 }
9232
9233 ScopedSslBio sslBio(ssl, rbio, wbio);
9234
Kenny Rootde9b5862014-04-22 09:46:20 -07009235 AppData* appData = toAppData(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009236 if (appData == NULL) {
Kenny Rootde9b5862014-04-22 09:46:20 -07009237 throwSSLExceptionStr(env, "Unable to retrieve application data");
Kenny Root86dd8322014-12-01 12:01:44 -08009238 safeSslClear(ssl);
Kenny Rootde9b5862014-04-22 09:46:20 -07009239 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009240 return 0;
9241 }
9242
Kenny Rootf878e432013-11-08 11:37:48 -08009243 if (!client_mode && alpnProtocols != NULL) {
9244 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
9245 }
9246
9247 int ret = 0;
9248 errno = 0;
9249
9250 if (!appData->setCallbackState(env, shc, NULL, npnProtocols, alpnProtocols)) {
Kenny Rootf878e432013-11-08 11:37:48 -08009251 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -08009252 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009253 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio setCallbackState => 0", ssl);
9254 return 0;
9255 }
9256 ret = SSL_do_handshake(ssl);
9257 appData->clearCallbackState();
9258 // cert_verify_callback threw exception
9259 if (env->ExceptionCheck()) {
Kenny Rootf878e432013-11-08 11:37:48 -08009260 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -08009261 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009262 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio exception => 0", ssl);
9263 return 0;
9264 }
9265
9266 if (ret <= 0) { // error. See SSL_do_handshake(3SSL) man page.
9267 // error case
Kenny Roota260ee62014-08-12 15:38:10 -07009268 OpenSslError sslError(ssl, ret);
Kenny Rootf878e432013-11-08 11:37:48 -08009269 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio ret=%d errno=%d sslError=%d",
Kenny Roota260ee62014-08-12 15:38:10 -07009270 ssl, ret, errno, sslError.get());
Kenny Rootf878e432013-11-08 11:37:48 -08009271
9272 /*
9273 * If SSL_do_handshake doesn't succeed due to the socket being
9274 * either unreadable or unwritable, we need to exit to allow
9275 * the SSLEngine code to wrap or unwrap.
9276 */
Kenny Roota260ee62014-08-12 15:38:10 -07009277 if (sslError.get() == SSL_ERROR_NONE ||
Narayan Kamathf6c8f8b2015-01-06 15:25:32 +00009278 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
9279 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
Kenny Rootf878e432013-11-08 11:37:48 -08009280 throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
Kenny Root86dd8322014-12-01 12:01:44 -08009281 safeSslClear(ssl);
Kenny Roota260ee62014-08-12 15:38:10 -07009282 } else if (sslError.get() != SSL_ERROR_WANT_READ &&
9283 sslError.get() != SSL_ERROR_WANT_WRITE) {
9284 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9285 "SSL handshake terminated", throwSSLHandshakeExceptionStr);
Kenny Root86dd8322014-12-01 12:01:44 -08009286 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009287 }
9288 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio error => 0", ssl);
9289 return 0;
9290 }
9291
9292 // success. handshake completed
9293 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
9294 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake_bio => ssl_session=%p", ssl, ssl_session);
9295#ifdef WITH_JNI_TRACE_KEYS
9296 debug_print_session_key(ssl_session);
9297#endif
9298 return reinterpret_cast<uintptr_t>(ssl_session);
9299}
9300
9301/**
9302 * Perform SSL handshake
9303 */
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009304static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
9305 jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
9306 jbyteArray alpnProtocols) {
Kenny Root860d2702013-04-23 15:50:31 -07009307 SSL* ssl = to_SSL(env, ssl_address, true);
9308 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
9309 ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
9310 if (ssl == NULL) {
Kenny Root0e9746b2013-09-12 15:14:48 -07009311 return 0;
Kenny Root860d2702013-04-23 15:50:31 -07009312 }
9313 if (fdObject == NULL) {
9314 jniThrowNullPointerException(env, "fd == null");
9315 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd == null => 0", ssl);
9316 return 0;
9317 }
9318 if (shc == NULL) {
9319 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9320 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslHandshakeCallbacks == null => 0", ssl);
9321 return 0;
9322 }
9323
9324 NetFd fd(env, fdObject);
9325 if (fd.isClosed()) {
9326 // SocketException thrown by NetFd.isClosed
Kenny Root86dd8322014-12-01 12:01:44 -08009327 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009328 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd.isClosed() => 0", ssl);
9329 return 0;
9330 }
9331
9332 int ret = SSL_set_fd(ssl, fd.get());
9333 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
9334
9335 if (ret != 1) {
9336 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
9337 "Error setting the file descriptor");
Kenny Root86dd8322014-12-01 12:01:44 -08009338 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009339 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake SSL_set_fd => 0", ssl);
9340 return 0;
9341 }
9342
9343 /*
9344 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
9345 * forever and we can use select() to find out if the socket is ready.
9346 */
9347 if (!setBlocking(fd.get(), false)) {
9348 throwSSLExceptionStr(env, "Unable to make socket non blocking");
Kenny Root86dd8322014-12-01 12:01:44 -08009349 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009350 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setBlocking => 0", ssl);
9351 return 0;
9352 }
9353
Kenny Rootde9b5862014-04-22 09:46:20 -07009354 AppData* appData = toAppData(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009355 if (appData == NULL) {
Kenny Rootde9b5862014-04-22 09:46:20 -07009356 throwSSLExceptionStr(env, "Unable to retrieve application data");
Kenny Root86dd8322014-12-01 12:01:44 -08009357 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009358 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake appData => 0", ssl);
9359 return 0;
9360 }
9361
Kenny Root860d2702013-04-23 15:50:31 -07009362 if (client_mode) {
9363 SSL_set_connect_state(ssl);
9364 } else {
9365 SSL_set_accept_state(ssl);
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009366 if (alpnProtocols != NULL) {
9367 SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
9368 }
Kenny Root860d2702013-04-23 15:50:31 -07009369 }
9370
9371 ret = 0;
Kenny Root2ba24c82014-11-17 11:13:16 -08009372 OpenSslError sslError;
Kenny Root860d2702013-04-23 15:50:31 -07009373 while (appData->aliveAndKicking) {
9374 errno = 0;
9375
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009376 if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
Kenny Root860d2702013-04-23 15:50:31 -07009377 // SocketException thrown by NetFd.isClosed
Kenny Root86dd8322014-12-01 12:01:44 -08009378 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009379 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
9380 return 0;
9381 }
9382 ret = SSL_do_handshake(ssl);
9383 appData->clearCallbackState();
9384 // cert_verify_callback threw exception
9385 if (env->ExceptionCheck()) {
Kenny Root7ca20492014-12-01 12:01:44 -08009386 freeOpenSslErrorState();
9387 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009388 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake exception => 0", ssl);
9389 return 0;
9390 }
9391 // success case
9392 if (ret == 1) {
9393 break;
9394 }
9395 // retry case
9396 if (errno == EINTR) {
9397 continue;
9398 }
9399 // error case
Kenny Root2ba24c82014-11-17 11:13:16 -08009400 sslError.reset(ssl, ret);
Kenny Root860d2702013-04-23 15:50:31 -07009401 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout_millis=%d",
Kenny Roota260ee62014-08-12 15:38:10 -07009402 ssl, ret, errno, sslError.get(), timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -07009403
9404 /*
9405 * If SSL_do_handshake doesn't succeed due to the socket being
9406 * either unreadable or unwritable, we use sslSelect to
9407 * wait for it to become ready. If that doesn't happen
9408 * before the specified timeout or an error occurs, we
9409 * cancel the handshake. Otherwise we try the SSL_connect
9410 * again.
9411 */
Kenny Roota260ee62014-08-12 15:38:10 -07009412 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
Kenny Root860d2702013-04-23 15:50:31 -07009413 appData->waitingThreads++;
Kenny Roota260ee62014-08-12 15:38:10 -07009414 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -07009415
9416 if (selectResult == THROWN_EXCEPTION) {
9417 // SocketException thrown by NetFd.isClosed
Kenny Root86dd8322014-12-01 12:01:44 -08009418 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009419 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake sslSelect => 0", ssl);
9420 return 0;
9421 }
9422 if (selectResult == -1) {
Kenny Roota0c196d2014-03-26 13:56:24 -07009423 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error",
9424 throwSSLHandshakeExceptionStr);
Kenny Root86dd8322014-12-01 12:01:44 -08009425 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009426 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == -1 => 0", ssl);
9427 return 0;
9428 }
9429 if (selectResult == 0) {
9430 throwSocketTimeoutException(env, "SSL handshake timed out");
Kenny Root860d2702013-04-23 15:50:31 -07009431 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -08009432 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009433 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake selectResult == 0 => 0", ssl);
9434 return 0;
9435 }
9436 } else {
9437 // ALOGE("Unknown error %d during handshake", error);
9438 break;
9439 }
9440 }
9441
9442 // clean error. See SSL_do_handshake(3SSL) man page.
9443 if (ret == 0) {
9444 /*
9445 * The other side closed the socket before the handshake could be
9446 * completed, but everything is within the bounds of the TLS protocol.
9447 * We still might want to find out the real reason of the failure.
9448 */
Kenny Roota260ee62014-08-12 15:38:10 -07009449 if (sslError.get() == SSL_ERROR_NONE ||
Narayan Kamathf6c8f8b2015-01-06 15:25:32 +00009450 (sslError.get() == SSL_ERROR_SYSCALL && errno == 0) ||
9451 (sslError.get() == SSL_ERROR_ZERO_RETURN)) {
Kenny Roota0c196d2014-03-26 13:56:24 -07009452 throwSSLHandshakeExceptionStr(env, "Connection closed by peer");
Kenny Root860d2702013-04-23 15:50:31 -07009453 } else {
Kenny Roota260ee62014-08-12 15:38:10 -07009454 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
9455 "SSL handshake terminated", throwSSLHandshakeExceptionStr);
Kenny Root860d2702013-04-23 15:50:31 -07009456 }
Kenny Root86dd8322014-12-01 12:01:44 -08009457 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009458 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake clean error => 0", ssl);
9459 return 0;
9460 }
9461
9462 // unclean error. See SSL_do_handshake(3SSL) man page.
9463 if (ret < 0) {
9464 /*
9465 * Translate the error and throw exception. We are sure it is an error
9466 * at this point.
9467 */
Kenny Roota260ee62014-08-12 15:38:10 -07009468 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "SSL handshake aborted",
Kenny Roota0c196d2014-03-26 13:56:24 -07009469 throwSSLHandshakeExceptionStr);
Kenny Root86dd8322014-12-01 12:01:44 -08009470 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009471 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake unclean error => 0", ssl);
9472 return 0;
9473 }
9474 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
9475 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
Kenny Rootbcdb80d2013-05-28 14:51:51 -07009476#ifdef WITH_JNI_TRACE_KEYS
9477 debug_print_session_key(ssl_session);
9478#endif
Kenny Root860d2702013-04-23 15:50:31 -07009479 return (jlong) ssl_session;
9480}
9481
9482/**
9483 * Perform SSL renegotiation
9484 */
9485static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jlong ssl_address)
9486{
9487 SSL* ssl = to_SSL(env, ssl_address, true);
9488 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
9489 if (ssl == NULL) {
9490 return;
9491 }
9492 int result = SSL_renegotiate(ssl);
9493 if (result != 1) {
9494 throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
9495 return;
9496 }
9497 // first call asks client to perform renegotiation
9498 int ret = SSL_do_handshake(ssl);
9499 if (ret != 1) {
Kenny Roota260ee62014-08-12 15:38:10 -07009500 OpenSslError sslError(ssl, ret);
9501 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(),
Kenny Root860d2702013-04-23 15:50:31 -07009502 "Problem with SSL_do_handshake after SSL_renegotiate");
9503 return;
9504 }
9505 // if client agrees, set ssl state and perform renegotiation
9506 ssl->state = SSL_ST_ACCEPT;
9507 SSL_do_handshake(ssl);
9508 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
9509}
9510
9511/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +00009512 * public static native byte[][] SSL_get_certificate(long ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009513 */
Kenny Root0e9746b2013-09-12 15:14:48 -07009514static jlongArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jlong ssl_address)
Kenny Root860d2702013-04-23 15:50:31 -07009515{
9516 SSL* ssl = to_SSL(env, ssl_address, true);
9517 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
9518 if (ssl == NULL) {
9519 return NULL;
9520 }
9521 X509* certificate = SSL_get_certificate(ssl);
9522 if (certificate == NULL) {
9523 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
Kenny Rootdb88d052013-06-05 10:01:27 -07009524 // SSL_get_certificate can return NULL during an error as well.
9525 freeOpenSslErrorState();
Kenny Root860d2702013-04-23 15:50:31 -07009526 return NULL;
9527 }
9528
9529 Unique_sk_X509 chain(sk_X509_new_null());
9530 if (chain.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07009531 jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
Kenny Root860d2702013-04-23 15:50:31 -07009532 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
9533 return NULL;
9534 }
Kenny Rootc58a1862013-09-11 10:05:32 -07009535 if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
Kenny Root923e3c52013-05-01 12:17:23 -07009536 jniThrowOutOfMemory(env, "Unable to push local certificate");
Kenny Root860d2702013-04-23 15:50:31 -07009537 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
9538 return NULL;
9539 }
Adam Langleyde5225d2014-10-06 15:55:30 -07009540
9541#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -07009542 STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
9543 for (int i=0; i<sk_X509_num(cert_chain); i++) {
Kenny Rootc58a1862013-09-11 10:05:32 -07009544 if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
Kenny Root923e3c52013-05-01 12:17:23 -07009545 jniThrowOutOfMemory(env, "Unable to push local certificate chain");
Kenny Root860d2702013-04-23 15:50:31 -07009546 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
9547 return NULL;
9548 }
9549 }
Adam Langleyde5225d2014-10-06 15:55:30 -07009550#else
9551 STACK_OF(X509) *cert_chain = NULL;
9552 if (!SSL_get0_chain_certs(ssl, &cert_chain)) {
9553 JNI_TRACE("ssl=%p NativeCrypto_SSL_get0_chain_certs => NULL", ssl);
9554 freeOpenSslErrorState();
9555 return NULL;
9556 }
9557
9558 for (size_t i=0; i<sk_X509_num(cert_chain); i++) {
9559 if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
9560 jniThrowOutOfMemory(env, "Unable to push local certificate chain");
9561 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
9562 return NULL;
9563 }
9564 }
9565#endif
Kenny Root860d2702013-04-23 15:50:31 -07009566
Kenny Root0e9746b2013-09-12 15:14:48 -07009567 jlongArray refArray = getCertificateRefs(env, chain.get());
9568 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, refArray);
9569 return refArray;
Kenny Root860d2702013-04-23 15:50:31 -07009570}
9571
Kenny Root0e9746b2013-09-12 15:14:48 -07009572// Fills a long[] with the peer certificates in the chain.
9573static jlongArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jlong ssl_address)
Kenny Root860d2702013-04-23 15:50:31 -07009574{
9575 SSL* ssl = to_SSL(env, ssl_address, true);
9576 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
9577 if (ssl == NULL) {
9578 return NULL;
9579 }
9580 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
9581 Unique_sk_X509 chain_copy(NULL);
9582 if (ssl->server) {
9583 X509* x509 = SSL_get_peer_certificate(ssl);
9584 if (x509 == NULL) {
9585 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
9586 return NULL;
9587 }
Kenny Rootc58a1862013-09-11 10:05:32 -07009588 chain_copy.reset(sk_X509_new_null());
Kenny Root860d2702013-04-23 15:50:31 -07009589 if (chain_copy.get() == NULL) {
Kenny Root923e3c52013-05-01 12:17:23 -07009590 jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
Kenny Root860d2702013-04-23 15:50:31 -07009591 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
9592 return NULL;
9593 }
Kenny Rootc58a1862013-09-11 10:05:32 -07009594 size_t chain_size = sk_X509_num(chain);
9595 for (size_t i = 0; i < chain_size; i++) {
9596 if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
9597 jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
9598 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
9599 return NULL;
9600 }
9601 }
9602 if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
Kenny Root923e3c52013-05-01 12:17:23 -07009603 jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
Kenny Root860d2702013-04-23 15:50:31 -07009604 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
9605 return NULL;
9606 }
9607 chain = chain_copy.get();
9608 }
Kenny Root0e9746b2013-09-12 15:14:48 -07009609 jlongArray refArray = getCertificateRefs(env, chain);
9610 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, refArray);
9611 return refArray;
Kenny Root860d2702013-04-23 15:50:31 -07009612}
9613
Kenny Root860d2702013-04-23 15:50:31 -07009614static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
Kenny Roota260ee62014-08-12 15:38:10 -07009615 OpenSslError& sslError, int read_timeout_millis) {
Kenny Root860d2702013-04-23 15:50:31 -07009616 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
9617
9618 if (len == 0) {
9619 // Don't bother doing anything in this case.
9620 return 0;
9621 }
9622
Kenny Root93cfc3c2014-03-31 17:06:21 -07009623 BIO* rbio = SSL_get_rbio(ssl);
9624 BIO* wbio = SSL_get_wbio(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009625
9626 AppData* appData = toAppData(ssl);
Kenny Rootf43a94f2014-05-12 13:19:28 -07009627 JNI_TRACE("ssl=%p sslRead appData=%p", ssl, appData);
Kenny Root860d2702013-04-23 15:50:31 -07009628 if (appData == NULL) {
9629 return THROW_SSLEXCEPTION;
9630 }
9631
9632 while (appData->aliveAndKicking) {
9633 errno = 0;
9634
9635 if (MUTEX_LOCK(appData->mutex) == -1) {
9636 return -1;
9637 }
9638
Kenny Root0931d512014-08-05 15:45:32 -07009639 if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
9640 !SSL_renegotiate_pending(ssl)) {
9641 JNI_TRACE("ssl=%p sslRead => init is not finished (state=0x%x)", ssl,
9642 SSL_get_state(ssl));
9643 MUTEX_UNLOCK(appData->mutex);
9644 return THROW_SSLEXCEPTION;
9645 }
9646
Kenny Root93cfc3c2014-03-31 17:06:21 -07009647 unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
Kenny Root860d2702013-04-23 15:50:31 -07009648
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009649 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
Kenny Root860d2702013-04-23 15:50:31 -07009650 MUTEX_UNLOCK(appData->mutex);
9651 return THROWN_EXCEPTION;
9652 }
9653 int result = SSL_read(ssl, buf, len);
9654 appData->clearCallbackState();
9655 // callbacks can happen if server requests renegotiation
9656 if (env->ExceptionCheck()) {
Kenny Root86dd8322014-12-01 12:01:44 -08009657 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009658 JNI_TRACE("ssl=%p sslRead => THROWN_EXCEPTION", ssl);
Adam Langleyde5225d2014-10-06 15:55:30 -07009659 MUTEX_UNLOCK(appData->mutex);
Kenny Root860d2702013-04-23 15:50:31 -07009660 return THROWN_EXCEPTION;
9661 }
Kenny Roota260ee62014-08-12 15:38:10 -07009662 sslError.reset(ssl, result);
9663 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError.get());
Kenny Root860d2702013-04-23 15:50:31 -07009664#ifdef WITH_JNI_TRACE_DATA
9665 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
Kenny Root74f1a2a2013-09-11 15:24:38 -07009666 int n = result - i;
9667 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9668 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
9669 }
Kenny Roota084cc72013-05-29 10:33:37 -07009670 JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
Kenny Root860d2702013-04-23 15:50:31 -07009671 }
9672#endif
9673
9674 // If we have been successful in moving data around, check whether it
9675 // might make sense to wake up other blocked threads, so they can give
9676 // it a try, too.
Kenny Root93cfc3c2014-03-31 17:06:21 -07009677 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
Kenny Root860d2702013-04-23 15:50:31 -07009678 && appData->waitingThreads > 0) {
9679 sslNotify(appData);
9680 }
9681
9682 // If we are blocked by the underlying socket, tell the world that
9683 // there will be one more waiting thread now.
Kenny Roota260ee62014-08-12 15:38:10 -07009684 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
Kenny Root860d2702013-04-23 15:50:31 -07009685 appData->waitingThreads++;
9686 }
9687
9688 MUTEX_UNLOCK(appData->mutex);
9689
Kenny Roota260ee62014-08-12 15:38:10 -07009690 switch (sslError.get()) {
Kenny Root860d2702013-04-23 15:50:31 -07009691 // Successfully read at least one byte.
9692 case SSL_ERROR_NONE: {
9693 return result;
9694 }
9695
9696 // Read zero bytes. End of stream reached.
9697 case SSL_ERROR_ZERO_RETURN: {
9698 return -1;
9699 }
9700
9701 // Need to wait for availability of underlying layer, then retry.
9702 case SSL_ERROR_WANT_READ:
9703 case SSL_ERROR_WANT_WRITE: {
Kenny Roota260ee62014-08-12 15:38:10 -07009704 int selectResult = sslSelect(env, sslError.get(), fdObject, appData, read_timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -07009705 if (selectResult == THROWN_EXCEPTION) {
9706 return THROWN_EXCEPTION;
9707 }
9708 if (selectResult == -1) {
Kenny Root860d2702013-04-23 15:50:31 -07009709 return THROW_SSLEXCEPTION;
9710 }
9711 if (selectResult == 0) {
9712 return THROW_SOCKETTIMEOUTEXCEPTION;
9713 }
9714
9715 break;
9716 }
9717
9718 // A problem occurred during a system call, but this is not
9719 // necessarily an error.
9720 case SSL_ERROR_SYSCALL: {
9721 // Connection closed without proper shutdown. Tell caller we
9722 // have reached end-of-stream.
9723 if (result == 0) {
9724 return -1;
9725 }
9726
9727 // System call has been interrupted. Simply retry.
9728 if (errno == EINTR) {
9729 break;
9730 }
9731
9732 // Note that for all other system call errors we fall through
9733 // to the default case, which results in an Exception.
Kenny Root8a9fc462015-04-02 17:06:30 -07009734 FALLTHROUGH_INTENDED;
Kenny Root860d2702013-04-23 15:50:31 -07009735 }
9736
9737 // Everything else is basically an error.
9738 default: {
Kenny Root860d2702013-04-23 15:50:31 -07009739 return THROW_SSLEXCEPTION;
9740 }
9741 }
9742 }
9743
9744 return -1;
9745}
9746
Kenny Rootf878e432013-11-08 11:37:48 -08009747static jint NativeCrypto_SSL_read_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray destJava,
Kenny Root7ed0fae2014-07-22 13:03:09 -07009748 jint destOffset, jint destLength, jlong sourceBioRef, jlong sinkBioRef, jobject shc) {
Kenny Rootf878e432013-11-08 11:37:48 -08009749 SSL* ssl = to_SSL(env, sslRef, true);
9750 BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sourceBioRef));
9751 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
9752 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO dest=%p sourceBio=%p sinkBio=%p shc=%p",
9753 ssl, destJava, rbio, wbio, shc);
9754 if (ssl == NULL) {
9755 return 0;
9756 }
9757 if (rbio == NULL || wbio == NULL) {
9758 jniThrowNullPointerException(env, "rbio == null || wbio == null");
9759 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => rbio == null || wbio == null", ssl);
9760 return -1;
9761 }
9762 if (shc == NULL) {
9763 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9764 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => sslHandshakeCallbacks == null", ssl);
9765 return -1;
9766 }
9767
9768 ScopedByteArrayRW dest(env, destJava);
9769 if (dest.get() == NULL) {
9770 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
9771 return -1;
9772 }
Kenny Root7ed0fae2014-07-22 13:03:09 -07009773 if (destOffset < 0 || destOffset > ssize_t(dest.size()) || destLength < 0
9774 || destLength > (ssize_t) dest.size() - destOffset) {
9775 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => destOffset=%d, destLength=%d, size=%zd",
Kenny Root6c523c02014-11-25 13:33:51 -08009776 ssl, destOffset, destLength, dest.size());
Kenny Root7ed0fae2014-07-22 13:03:09 -07009777 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
9778 return -1;
9779 }
Kenny Rootf878e432013-11-08 11:37:48 -08009780
9781 AppData* appData = toAppData(ssl);
9782 if (appData == NULL) {
9783 throwSSLExceptionStr(env, "Unable to retrieve application data");
Kenny Root86dd8322014-12-01 12:01:44 -08009784 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009785 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => appData == NULL", ssl);
9786 return -1;
9787 }
9788
9789 errno = 0;
9790
9791 if (MUTEX_LOCK(appData->mutex) == -1) {
9792 return -1;
9793 }
9794
9795 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
9796 MUTEX_UNLOCK(appData->mutex);
9797 throwSSLExceptionStr(env, "Unable to set callback state");
Kenny Root86dd8322014-12-01 12:01:44 -08009798 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009799 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => set callback state failed", ssl);
9800 return -1;
9801 }
9802
9803 ScopedSslBio sslBio(ssl, rbio, wbio);
9804
Kenny Root7ed0fae2014-07-22 13:03:09 -07009805 int result = SSL_read(ssl, dest.get() + destOffset, destLength);
Kenny Rootf878e432013-11-08 11:37:48 -08009806 appData->clearCallbackState();
9807 // callbacks can happen if server requests renegotiation
9808 if (env->ExceptionCheck()) {
Kenny Root86dd8322014-12-01 12:01:44 -08009809 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -08009810 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => threw exception", ssl);
9811 return THROWN_EXCEPTION;
9812 }
Kenny Roota260ee62014-08-12 15:38:10 -07009813 OpenSslError sslError(ssl, result);
9814 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO SSL_read result=%d sslError=%d", ssl, result,
9815 sslError.get());
Kenny Rootf878e432013-11-08 11:37:48 -08009816#ifdef WITH_JNI_TRACE_DATA
9817 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9818 int n = result - i;
9819 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9820 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
9821 }
9822 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
9823 }
9824#endif
9825
9826 MUTEX_UNLOCK(appData->mutex);
9827
Kenny Roota260ee62014-08-12 15:38:10 -07009828 switch (sslError.get()) {
Kenny Rootf878e432013-11-08 11:37:48 -08009829 // Successfully read at least one byte.
9830 case SSL_ERROR_NONE:
9831 break;
9832
9833 // Read zero bytes. End of stream reached.
9834 case SSL_ERROR_ZERO_RETURN:
9835 result = -1;
9836 break;
9837
9838 // Need to wait for availability of underlying layer, then retry.
9839 case SSL_ERROR_WANT_READ:
9840 case SSL_ERROR_WANT_WRITE:
9841 result = 0;
9842 break;
9843
9844 // A problem occurred during a system call, but this is not
9845 // necessarily an error.
9846 case SSL_ERROR_SYSCALL: {
9847 // Connection closed without proper shutdown. Tell caller we
9848 // have reached end-of-stream.
9849 if (result == 0) {
9850 result = -1;
9851 break;
9852 } else if (errno == EINTR) {
9853 // System call has been interrupted. Simply retry.
9854 result = 0;
9855 break;
9856 }
9857
9858 // Note that for all other system call errors we fall through
9859 // to the default case, which results in an Exception.
Kenny Root8a9fc462015-04-02 17:06:30 -07009860 FALLTHROUGH_INTENDED;
Kenny Rootf878e432013-11-08 11:37:48 -08009861 }
9862
9863 // Everything else is basically an error.
9864 default: {
Kenny Roota260ee62014-08-12 15:38:10 -07009865 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
Kenny Rootf878e432013-11-08 11:37:48 -08009866 return -1;
9867 }
9868 }
9869 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_BIO => %d", ssl, result);
9870 return result;
9871}
9872
Kenny Root860d2702013-04-23 15:50:31 -07009873/**
9874 * OpenSSL read function (2): read into buffer at offset n chunks.
9875 * Returns 1 (success) or value <= 0 (failure).
9876 */
9877static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
9878 jobject shc, jbyteArray b, jint offset, jint len,
9879 jint read_timeout_millis)
9880{
9881 SSL* ssl = to_SSL(env, ssl_address, true);
9882 JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d read_timeout_millis=%d",
9883 ssl, fdObject, shc, b, offset, len, read_timeout_millis);
9884 if (ssl == NULL) {
9885 return 0;
9886 }
9887 if (fdObject == NULL) {
9888 jniThrowNullPointerException(env, "fd == null");
9889 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
9890 return 0;
9891 }
9892 if (shc == NULL) {
9893 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
9894 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
9895 return 0;
9896 }
9897
9898 ScopedByteArrayRW bytes(env, b);
9899 if (bytes.get() == NULL) {
9900 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
9901 return 0;
9902 }
Kenny Root860d2702013-04-23 15:50:31 -07009903
Kenny Roota260ee62014-08-12 15:38:10 -07009904 OpenSslError sslError;
Kenny Root860d2702013-04-23 15:50:31 -07009905 int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
Kenny Roota260ee62014-08-12 15:38:10 -07009906 sslError, read_timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -07009907
9908 int result;
9909 switch (ret) {
9910 case THROW_SSLEXCEPTION:
9911 // See sslRead() regarding improper failure to handle normal cases.
Kenny Roota260ee62014-08-12 15:38:10 -07009912 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Read error");
Kenny Root860d2702013-04-23 15:50:31 -07009913 result = -1;
9914 break;
9915 case THROW_SOCKETTIMEOUTEXCEPTION:
9916 throwSocketTimeoutException(env, "Read timed out");
9917 result = -1;
9918 break;
9919 case THROWN_EXCEPTION:
9920 // SocketException thrown by NetFd.isClosed
9921 // or RuntimeException thrown by callback
9922 result = -1;
9923 break;
9924 default:
9925 result = ret;
9926 break;
9927 }
9928
9929 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
9930 return result;
9931}
9932
Kenny Root860d2702013-04-23 15:50:31 -07009933static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
Kenny Roota260ee62014-08-12 15:38:10 -07009934 OpenSslError& sslError, int write_timeout_millis) {
Kenny Root860d2702013-04-23 15:50:31 -07009935 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d write_timeout_millis=%d",
9936 ssl, buf, len, write_timeout_millis);
9937
9938 if (len == 0) {
9939 // Don't bother doing anything in this case.
9940 return 0;
9941 }
9942
Kenny Root93cfc3c2014-03-31 17:06:21 -07009943 BIO* rbio = SSL_get_rbio(ssl);
9944 BIO* wbio = SSL_get_wbio(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009945
9946 AppData* appData = toAppData(ssl);
Kenny Rootf43a94f2014-05-12 13:19:28 -07009947 JNI_TRACE("ssl=%p sslWrite appData=%p", ssl, appData);
Kenny Root860d2702013-04-23 15:50:31 -07009948 if (appData == NULL) {
9949 return THROW_SSLEXCEPTION;
9950 }
9951
9952 int count = len;
9953
9954 while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
9955 errno = 0;
9956
9957 if (MUTEX_LOCK(appData->mutex) == -1) {
9958 return -1;
9959 }
9960
Kenny Root0931d512014-08-05 15:45:32 -07009961 if (!SSL_is_init_finished(ssl) && !SSL_cutthrough_complete(ssl) &&
9962 !SSL_renegotiate_pending(ssl)) {
9963 JNI_TRACE("ssl=%p sslWrite => init is not finished (state=0x%x)", ssl,
9964 SSL_get_state(ssl));
9965 MUTEX_UNLOCK(appData->mutex);
9966 return THROW_SSLEXCEPTION;
9967 }
9968
Kenny Root93cfc3c2014-03-31 17:06:21 -07009969 unsigned int bytesMoved = BIO_number_read(rbio) + BIO_number_written(wbio);
Kenny Root860d2702013-04-23 15:50:31 -07009970
Kenny Root6fcf0cb2013-06-24 15:54:18 -07009971 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
Kenny Root860d2702013-04-23 15:50:31 -07009972 MUTEX_UNLOCK(appData->mutex);
9973 return THROWN_EXCEPTION;
9974 }
9975 JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
9976 int result = SSL_write(ssl, buf, len);
9977 appData->clearCallbackState();
9978 // callbacks can happen if server requests renegotiation
9979 if (env->ExceptionCheck()) {
Kenny Root86dd8322014-12-01 12:01:44 -08009980 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -07009981 JNI_TRACE("ssl=%p sslWrite exception => THROWN_EXCEPTION", ssl);
9982 return THROWN_EXCEPTION;
9983 }
Kenny Roota260ee62014-08-12 15:38:10 -07009984 sslError.reset(ssl, result);
Kenny Root860d2702013-04-23 15:50:31 -07009985 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
Kenny Roota260ee62014-08-12 15:38:10 -07009986 ssl, result, sslError.get(), ssl->s3->wbuf.left);
Kenny Root860d2702013-04-23 15:50:31 -07009987#ifdef WITH_JNI_TRACE_DATA
9988 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
Kenny Root74f1a2a2013-09-11 15:24:38 -07009989 int n = result - i;
9990 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
9991 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
9992 }
Kenny Roota084cc72013-05-29 10:33:37 -07009993 JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
Kenny Root860d2702013-04-23 15:50:31 -07009994 }
9995#endif
9996
9997 // If we have been successful in moving data around, check whether it
9998 // might make sense to wake up other blocked threads, so they can give
9999 // it a try, too.
Kenny Root93cfc3c2014-03-31 17:06:21 -070010000 if (BIO_number_read(rbio) + BIO_number_written(wbio) != bytesMoved
Kenny Root860d2702013-04-23 15:50:31 -070010001 && appData->waitingThreads > 0) {
10002 sslNotify(appData);
10003 }
10004
10005 // If we are blocked by the underlying socket, tell the world that
10006 // there will be one more waiting thread now.
Kenny Roota260ee62014-08-12 15:38:10 -070010007 if (sslError.get() == SSL_ERROR_WANT_READ || sslError.get() == SSL_ERROR_WANT_WRITE) {
Kenny Root860d2702013-04-23 15:50:31 -070010008 appData->waitingThreads++;
10009 }
10010
10011 MUTEX_UNLOCK(appData->mutex);
10012
Kenny Roota260ee62014-08-12 15:38:10 -070010013 switch (sslError.get()) {
Kenny Root860d2702013-04-23 15:50:31 -070010014 // Successfully wrote at least one byte.
10015 case SSL_ERROR_NONE: {
10016 buf += result;
10017 len -= result;
10018 break;
10019 }
10020
10021 // Wrote zero bytes. End of stream reached.
10022 case SSL_ERROR_ZERO_RETURN: {
10023 return -1;
10024 }
10025
10026 // Need to wait for availability of underlying layer, then retry.
10027 // The concept of a write timeout doesn't really make sense, and
10028 // it's also not standard Java behavior, so we wait forever here.
10029 case SSL_ERROR_WANT_READ:
10030 case SSL_ERROR_WANT_WRITE: {
Kenny Roota260ee62014-08-12 15:38:10 -070010031 int selectResult = sslSelect(env, sslError.get(), fdObject, appData,
10032 write_timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -070010033 if (selectResult == THROWN_EXCEPTION) {
10034 return THROWN_EXCEPTION;
10035 }
10036 if (selectResult == -1) {
Kenny Root860d2702013-04-23 15:50:31 -070010037 return THROW_SSLEXCEPTION;
10038 }
10039 if (selectResult == 0) {
10040 return THROW_SOCKETTIMEOUTEXCEPTION;
10041 }
10042
10043 break;
10044 }
10045
10046 // A problem occurred during a system call, but this is not
10047 // necessarily an error.
10048 case SSL_ERROR_SYSCALL: {
10049 // Connection closed without proper shutdown. Tell caller we
10050 // have reached end-of-stream.
10051 if (result == 0) {
10052 return -1;
10053 }
10054
10055 // System call has been interrupted. Simply retry.
10056 if (errno == EINTR) {
10057 break;
10058 }
10059
10060 // Note that for all other system call errors we fall through
10061 // to the default case, which results in an Exception.
Kenny Root8a9fc462015-04-02 17:06:30 -070010062 FALLTHROUGH_INTENDED;
Kenny Root860d2702013-04-23 15:50:31 -070010063 }
10064
10065 // Everything else is basically an error.
10066 default: {
Kenny Root860d2702013-04-23 15:50:31 -070010067 return THROW_SSLEXCEPTION;
10068 }
10069 }
10070 }
10071 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
10072
10073 return count;
10074}
10075
10076/**
10077 * OpenSSL write function (2): write into buffer at offset n chunks.
10078 */
Kenny Rootf878e432013-11-08 11:37:48 -080010079static int NativeCrypto_SSL_write_BIO(JNIEnv* env, jclass, jlong sslRef, jbyteArray sourceJava, jint len,
10080 jlong sinkBioRef, jobject shc) {
10081 SSL* ssl = to_SSL(env, sslRef, true);
10082 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(sinkBioRef));
10083 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO source=%p len=%d wbio=%p shc=%p",
10084 ssl, sourceJava, len, wbio, shc);
10085 if (ssl == NULL) {
10086 return -1;
10087 }
10088 if (wbio == NULL) {
10089 jniThrowNullPointerException(env, "wbio == null");
10090 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => wbio == null", ssl);
10091 return -1;
10092 }
10093 if (shc == NULL) {
10094 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
10095 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => sslHandshakeCallbacks == null", ssl);
10096 return -1;
10097 }
10098
10099 AppData* appData = toAppData(ssl);
10100 if (appData == NULL) {
10101 throwSSLExceptionStr(env, "Unable to retrieve application data");
Kenny Root86dd8322014-12-01 12:01:44 -080010102 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010103 freeOpenSslErrorState();
10104 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO appData => NULL", ssl);
10105 return -1;
10106 }
10107
10108 errno = 0;
10109
10110 if (MUTEX_LOCK(appData->mutex) == -1) {
10111 return 0;
10112 }
10113
10114 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
10115 MUTEX_UNLOCK(appData->mutex);
10116 throwSSLExceptionStr(env, "Unable to set appdata callback");
Kenny Rootf878e432013-11-08 11:37:48 -080010117 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010118 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010119 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => appData can't set callback", ssl);
10120 return -1;
10121 }
10122
10123 ScopedByteArrayRO source(env, sourceJava);
10124 if (source.get() == NULL) {
10125 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO => threw exception", ssl);
10126 return -1;
10127 }
10128
Adam Langleydd546212015-01-20 18:27:45 -080010129#if defined(OPENSSL_IS_BORINGSSL)
10130 Unique_BIO nullBio(BIO_new_mem_buf(NULL, 0));
10131#else
Kenny Root2fe55c82014-12-30 14:10:59 -080010132 Unique_BIO nullBio(BIO_new(BIO_s_null()));
Adam Langleydd546212015-01-20 18:27:45 -080010133#endif
Kenny Root2fe55c82014-12-30 14:10:59 -080010134 ScopedSslBio sslBio(ssl, nullBio.get(), wbio);
Kenny Rootf878e432013-11-08 11:37:48 -080010135
10136 int result = SSL_write(ssl, reinterpret_cast<const char*>(source.get()), len);
10137 appData->clearCallbackState();
10138 // callbacks can happen if server requests renegotiation
10139 if (env->ExceptionCheck()) {
Kenny Rootf878e432013-11-08 11:37:48 -080010140 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010141 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010142 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO exception => exception pending (reneg)", ssl);
10143 return -1;
10144 }
Kenny Roota260ee62014-08-12 15:38:10 -070010145 OpenSslError sslError(ssl, result);
Kenny Rootf878e432013-11-08 11:37:48 -080010146 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO SSL_write result=%d sslError=%d left=%d",
Kenny Roota260ee62014-08-12 15:38:10 -070010147 ssl, result, sslError.get(), ssl->s3->wbuf.left);
Kenny Rootf878e432013-11-08 11:37:48 -080010148#ifdef WITH_JNI_TRACE_DATA
10149 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
10150 int n = result - i;
10151 if (n > WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
10152 n = WITH_JNI_TRACE_DATA_CHUNK_SIZE;
10153 }
10154 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_BIO data: %d:\n%.*s", ssl, n, n, buf+i);
10155 }
10156#endif
10157
10158 MUTEX_UNLOCK(appData->mutex);
10159
Kenny Roota260ee62014-08-12 15:38:10 -070010160 switch (sslError.get()) {
Kenny Rootf878e432013-11-08 11:37:48 -080010161 case SSL_ERROR_NONE:
10162 return result;
10163
10164 // Wrote zero bytes. End of stream reached.
10165 case SSL_ERROR_ZERO_RETURN:
10166 return -1;
10167
10168 case SSL_ERROR_WANT_READ:
10169 case SSL_ERROR_WANT_WRITE:
10170 return 0;
10171
10172 case SSL_ERROR_SYSCALL: {
10173 // Connection closed without proper shutdown. Tell caller we
10174 // have reached end-of-stream.
10175 if (result == 0) {
10176 return -1;
10177 }
10178
10179 // System call has been interrupted. Simply retry.
10180 if (errno == EINTR) {
10181 return 0;
10182 }
10183
10184 // Note that for all other system call errors we fall through
10185 // to the default case, which results in an Exception.
Kenny Root8a9fc462015-04-02 17:06:30 -070010186 FALLTHROUGH_INTENDED;
Kenny Rootf878e432013-11-08 11:37:48 -080010187 }
10188
10189 // Everything else is basically an error.
10190 default: {
Kenny Roota260ee62014-08-12 15:38:10 -070010191 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
Kenny Rootf878e432013-11-08 11:37:48 -080010192 break;
10193 }
10194 }
10195 return -1;
10196}
10197
10198/**
10199 * OpenSSL write function (2): write into buffer at offset n chunks.
10200 */
Kenny Root860d2702013-04-23 15:50:31 -070010201static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
10202 jobject shc, jbyteArray b, jint offset, jint len, jint write_timeout_millis)
10203{
10204 SSL* ssl = to_SSL(env, ssl_address, true);
10205 JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d write_timeout_millis=%d",
10206 ssl, fdObject, shc, b, offset, len, write_timeout_millis);
10207 if (ssl == NULL) {
10208 return;
10209 }
10210 if (fdObject == NULL) {
10211 jniThrowNullPointerException(env, "fd == null");
10212 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
10213 return;
10214 }
10215 if (shc == NULL) {
10216 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
10217 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
10218 return;
10219 }
10220
10221 ScopedByteArrayRO bytes(env, b);
10222 if (bytes.get() == NULL) {
10223 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
10224 return;
10225 }
Kenny Roota260ee62014-08-12 15:38:10 -070010226 OpenSslError sslError;
Kenny Root860d2702013-04-23 15:50:31 -070010227 int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
Kenny Roota260ee62014-08-12 15:38:10 -070010228 len, sslError, write_timeout_millis);
Kenny Root860d2702013-04-23 15:50:31 -070010229
10230 switch (ret) {
10231 case THROW_SSLEXCEPTION:
10232 // See sslWrite() regarding improper failure to handle normal cases.
Kenny Roota260ee62014-08-12 15:38:10 -070010233 throwSSLExceptionWithSslErrors(env, ssl, sslError.release(), "Write error");
Kenny Root860d2702013-04-23 15:50:31 -070010234 break;
10235 case THROW_SOCKETTIMEOUTEXCEPTION:
10236 throwSocketTimeoutException(env, "Write timed out");
10237 break;
10238 case THROWN_EXCEPTION:
10239 // SocketException thrown by NetFd.isClosed
10240 break;
10241 default:
10242 break;
10243 }
10244}
10245
10246/**
10247 * Interrupt any pending I/O before closing the socket.
10248 */
10249static void NativeCrypto_SSL_interrupt(
10250 JNIEnv* env, jclass, jlong ssl_address) {
10251 SSL* ssl = to_SSL(env, ssl_address, false);
10252 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
10253 if (ssl == NULL) {
10254 return;
10255 }
10256
10257 /*
10258 * Mark the connection as quasi-dead, then send something to the emergency
10259 * file descriptor, so any blocking select() calls are woken up.
10260 */
10261 AppData* appData = toAppData(ssl);
10262 if (appData != NULL) {
10263 appData->aliveAndKicking = 0;
10264
10265 // At most two threads can be waiting.
10266 sslNotify(appData);
10267 sslNotify(appData);
10268 }
10269}
10270
10271/**
10272 * OpenSSL close SSL socket function.
10273 */
10274static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jlong ssl_address,
10275 jobject fdObject, jobject shc) {
10276 SSL* ssl = to_SSL(env, ssl_address, false);
10277 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
10278 if (ssl == NULL) {
10279 return;
10280 }
10281 if (fdObject == NULL) {
10282 jniThrowNullPointerException(env, "fd == null");
10283 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
10284 return;
10285 }
10286 if (shc == NULL) {
10287 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
10288 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10289 return;
10290 }
10291
10292 AppData* appData = toAppData(ssl);
10293 if (appData != NULL) {
Kenny Root6fcf0cb2013-06-24 15:54:18 -070010294 if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
Kenny Root860d2702013-04-23 15:50:31 -070010295 // SocketException thrown by NetFd.isClosed
Kenny Root860d2702013-04-23 15:50:31 -070010296 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010297 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -070010298 return;
10299 }
10300
10301 /*
10302 * Try to make socket blocking again. OpenSSL literature recommends this.
10303 */
10304 int fd = SSL_get_fd(ssl);
10305 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
10306 if (fd != -1) {
10307 setBlocking(fd, true);
10308 }
10309
10310 int ret = SSL_shutdown(ssl);
10311 appData->clearCallbackState();
10312 // callbacks can happen if server requests renegotiation
10313 if (env->ExceptionCheck()) {
Kenny Root86dd8322014-12-01 12:01:44 -080010314 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -070010315 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
10316 return;
10317 }
10318 switch (ret) {
10319 case 0:
10320 /*
10321 * Shutdown was not successful (yet), but there also
10322 * is no error. Since we can't know whether the remote
10323 * server is actually still there, and we don't want to
10324 * get stuck forever in a second SSL_shutdown() call, we
10325 * simply return. This is not security a problem as long
10326 * as we close the underlying socket, which we actually
10327 * do, because that's where we are just coming from.
10328 */
10329 break;
10330 case 1:
10331 /*
10332 * Shutdown was successful. We can safely return. Hooray!
10333 */
10334 break;
10335 default:
10336 /*
10337 * Everything else is a real error condition. We should
10338 * let the Java layer know about this by throwing an
10339 * exception.
10340 */
10341 int sslError = SSL_get_error(ssl, ret);
10342 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
10343 break;
10344 }
10345 }
10346
Kenny Root860d2702013-04-23 15:50:31 -070010347 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010348 safeSslClear(ssl);
Kenny Root860d2702013-04-23 15:50:31 -070010349}
10350
10351/**
Kenny Rootf878e432013-11-08 11:37:48 -080010352 * OpenSSL close SSL socket function.
10353 */
10354static void NativeCrypto_SSL_shutdown_BIO(JNIEnv* env, jclass, jlong ssl_address, jlong rbioRef,
10355 jlong wbioRef, jobject shc) {
10356 SSL* ssl = to_SSL(env, ssl_address, false);
10357 BIO* rbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(rbioRef));
10358 BIO* wbio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(wbioRef));
10359 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown rbio=%p wbio=%p shc=%p", ssl, rbio, wbio, shc);
10360 if (ssl == NULL) {
10361 return;
10362 }
10363 if (rbio == NULL || wbio == NULL) {
10364 jniThrowNullPointerException(env, "rbio == null || wbio == null");
10365 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => rbio == null || wbio == null", ssl);
10366 return;
10367 }
10368 if (shc == NULL) {
10369 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
10370 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
10371 return;
10372 }
10373
10374 AppData* appData = toAppData(ssl);
10375 if (appData != NULL) {
10376 if (!appData->setCallbackState(env, shc, NULL, NULL, NULL)) {
10377 // SocketException thrown by NetFd.isClosed
Kenny Rootf878e432013-11-08 11:37:48 -080010378 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010379 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010380 return;
10381 }
10382
10383 ScopedSslBio scopedBio(ssl, rbio, wbio);
10384
10385 int ret = SSL_shutdown(ssl);
10386 appData->clearCallbackState();
10387 // callbacks can happen if server requests renegotiation
10388 if (env->ExceptionCheck()) {
Kenny Root86dd8322014-12-01 12:01:44 -080010389 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010390 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => exception", ssl);
10391 return;
10392 }
10393 switch (ret) {
10394 case 0:
10395 /*
10396 * Shutdown was not successful (yet), but there also
10397 * is no error. Since we can't know whether the remote
10398 * server is actually still there, and we don't want to
10399 * get stuck forever in a second SSL_shutdown() call, we
10400 * simply return. This is not security a problem as long
10401 * as we close the underlying socket, which we actually
10402 * do, because that's where we are just coming from.
10403 */
10404 break;
10405 case 1:
10406 /*
10407 * Shutdown was successful. We can safely return. Hooray!
10408 */
10409 break;
10410 default:
10411 /*
10412 * Everything else is a real error condition. We should
10413 * let the Java layer know about this by throwing an
10414 * exception.
10415 */
10416 int sslError = SSL_get_error(ssl, ret);
10417 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
10418 break;
10419 }
10420 }
10421
Kenny Rootf878e432013-11-08 11:37:48 -080010422 freeOpenSslErrorState();
Kenny Root86dd8322014-12-01 12:01:44 -080010423 safeSslClear(ssl);
Kenny Rootf878e432013-11-08 11:37:48 -080010424}
10425
10426static jint NativeCrypto_SSL_get_shutdown(JNIEnv* env, jclass, jlong ssl_address) {
10427 const SSL* ssl = to_SSL(env, ssl_address, true);
10428 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown", ssl);
10429 if (ssl == NULL) {
10430 jniThrowNullPointerException(env, "ssl == null");
10431 return 0;
10432 }
10433
10434 int status = SSL_get_shutdown(ssl);
10435 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_shutdown => %d", ssl, status);
10436 return static_cast<jint>(status);
10437}
10438
10439/**
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +000010440 * public static native void SSL_free(long ssl);
Kenny Root860d2702013-04-23 15:50:31 -070010441 */
10442static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jlong ssl_address)
10443{
10444 SSL* ssl = to_SSL(env, ssl_address, true);
10445 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
10446 if (ssl == NULL) {
10447 return;
10448 }
10449
10450 AppData* appData = toAppData(ssl);
10451 SSL_set_app_data(ssl, NULL);
10452 delete appData;
10453 SSL_free(ssl);
10454}
10455
10456/**
10457 * Gets and returns in a byte array the ID of the actual SSL session.
10458 */
10459static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
10460 jlong ssl_session_address) {
10461 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10462 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
10463 if (ssl_session == NULL) {
10464 return NULL;
10465 }
10466 jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
10467 if (result != NULL) {
10468 jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
10469 env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
10470 }
10471 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
10472 ssl_session, result, ssl_session->session_id_length);
10473 return result;
10474}
10475
10476/**
10477 * Gets and returns in a long integer the creation's time of the
10478 * actual SSL session.
10479 */
10480static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jlong ssl_session_address) {
10481 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10482 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
10483 if (ssl_session == NULL) {
10484 return 0;
10485 }
10486 // result must be jlong, not long or *1000 will overflow
10487 jlong result = SSL_SESSION_get_time(ssl_session);
10488 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
Kenny Root6c523c02014-11-25 13:33:51 -080010489 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, (long long) result);
Kenny Root860d2702013-04-23 15:50:31 -070010490 return result;
10491}
10492
10493/**
10494 * Gets and returns in a string the version of the SSL protocol. If it
10495 * returns the string "unknown" it means that no connection is established.
10496 */
10497static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jlong ssl_session_address) {
10498 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10499 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
10500 if (ssl_session == NULL) {
10501 return NULL;
10502 }
10503 const char* protocol = SSL_SESSION_get_version(ssl_session);
10504 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
10505 return env->NewStringUTF(protocol);
10506}
10507
10508/**
10509 * Gets and returns in a string the cipher negotiated for the SSL session.
10510 */
10511static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jlong ssl_session_address) {
10512 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10513 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
10514 if (ssl_session == NULL) {
10515 return NULL;
10516 }
10517 const SSL_CIPHER* cipher = ssl_session->cipher;
10518 const char* name = SSL_CIPHER_get_name(cipher);
10519 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
10520 return env->NewStringUTF(name);
10521}
10522
10523/**
10524 * Frees the SSL session.
10525 */
10526static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jlong ssl_session_address) {
10527 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10528 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
10529 if (ssl_session == NULL) {
10530 return;
10531 }
10532 SSL_SESSION_free(ssl_session);
10533}
10534
10535
10536/**
10537 * Serializes the native state of the session (ID, cipher, and keys but
10538 * not certificates). Returns a byte[] containing the DER-encoded state.
10539 * See apache mod_ssl.
10540 */
10541static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
10542 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
10543 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
Kenny Roota2b88782013-05-03 13:56:00 -070010544 if (ssl_session == NULL) {
10545 return NULL;
10546 }
Adam Langleyde5225d2014-10-06 15:55:30 -070010547 return ASN1ToByteArray<SSL_SESSION>(env, ssl_session, i2d_SSL_SESSION);
Kenny Root860d2702013-04-23 15:50:31 -070010548}
10549
10550/**
10551 * Deserialize the session.
10552 */
10553static jlong NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
10554 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
10555
10556 ScopedByteArrayRO bytes(env, javaBytes);
10557 if (bytes.get() == NULL) {
10558 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
10559 return 0;
10560 }
10561 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
10562 SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
10563
Adam Langleyde5225d2014-10-06 15:55:30 -070010564#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Root860d2702013-04-23 15:50:31 -070010565 // Initialize SSL_SESSION cipher field based on cipher_id http://b/7091840
10566 if (ssl_session != NULL) {
10567 // based on ssl_get_prev_session
10568 uint32_t cipher_id_network_order = htonl(ssl_session->cipher_id);
10569 uint8_t* cipher_id_byte_pointer = reinterpret_cast<uint8_t*>(&cipher_id_network_order);
10570 if (ssl_session->ssl_version >= SSL3_VERSION_MAJOR) {
10571 cipher_id_byte_pointer += 2; // skip first two bytes for SSL3+
10572 } else {
10573 cipher_id_byte_pointer += 1; // skip first byte for SSL2
10574 }
10575 ssl_session->cipher = SSLv23_method()->get_cipher_by_char(cipher_id_byte_pointer);
10576 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION cipher_id=%lx hton=%x 0=%x 1=%x cipher=%s",
10577 ssl_session->cipher_id, cipher_id_network_order,
10578 cipher_id_byte_pointer[0], cipher_id_byte_pointer[1],
10579 SSL_CIPHER_get_name(ssl_session->cipher));
Adam Langleyde5225d2014-10-06 15:55:30 -070010580 }
10581#endif
10582
10583 if (ssl_session == NULL) {
Kenny Root860d2702013-04-23 15:50:31 -070010584 freeOpenSslErrorState();
10585 }
10586
10587 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
10588 return reinterpret_cast<uintptr_t>(ssl_session);
10589}
10590
10591static jlong NativeCrypto_ERR_peek_last_error(JNIEnv*, jclass) {
10592 return ERR_peek_last_error();
10593}
10594
Adam Langley9b8d0922015-04-24 07:36:32 -070010595static jstring NativeCrypto_SSL_CIPHER_get_kx_name(JNIEnv* env, jclass, jlong cipher_address) {
10596 const SSL_CIPHER* cipher = to_SSL_CIPHER(env, cipher_address, true);
10597 const char *kx_name = NULL;
10598
10599#if defined(OPENSSL_IS_BORINGSSL)
10600 kx_name = SSL_CIPHER_get_kx_name(cipher);
10601#else
10602 kx_name = SSL_CIPHER_authentication_method(cipher);
10603#endif
10604
10605 return env->NewStringUTF(kx_name);
10606}
10607
Adam Langleyd9a68f62015-04-28 13:19:24 -070010608static jobjectArray NativeCrypto_get_cipher_names(JNIEnv *env, jclass, jstring selectorJava) {
10609 ScopedUtfChars selector(env, selectorJava);
10610 if (selector.c_str() == NULL) {
10611 jniThrowException(env, "java/lang/IllegalArgumentException", "selector == NULL");
10612 return 0;
10613 }
10614
10615 JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
10616
10617 Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
10618 Unique_SSL ssl(SSL_new(sslCtx.get()));
10619
10620 if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
10621 jniThrowException(env, "java/lang/IllegalArgumentException", "Unable to set SSL cipher list");
10622 return 0;
10623 }
10624 STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl.get());
10625
10626 size_t size = sk_SSL_CIPHER_num(ciphers);
10627 ScopedLocalRef<jobjectArray> cipherNamesArray(env, env->NewObjectArray(size, stringClass, NULL));
10628 if (cipherNamesArray.get() == NULL) {
10629 return NULL;
10630 }
10631
10632 for (size_t i = 0; i < size; i++) {
10633 const char *name = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciphers, i));
10634 ScopedLocalRef<jstring> cipherName(env, env->NewStringUTF(name));
10635 env->SetObjectArrayElement(cipherNamesArray.get(), i, cipherName.get());
10636 }
10637
10638 JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(), size);
10639 return cipherNamesArray.release();
10640}
10641
Kenny Root860d2702013-04-23 15:50:31 -070010642#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
10643#define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
Kenny Root7dc06b92014-11-26 10:07:51 -080010644#define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
10645#define REF_EC_POINT "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_POINT;"
Kenny Rootf6f66202015-05-08 14:01:56 -070010646#define REF_EVP_AEAD_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_AEAD_CTX;"
Kenny Root4757cdb2014-11-26 07:59:41 -080010647#define REF_EVP_CIPHER_CTX "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_CIPHER_CTX;"
Kenny Root37e58bb2014-11-25 14:29:25 -080010648#define REF_EVP_PKEY "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_PKEY;"
Kenny Root860d2702013-04-23 15:50:31 -070010649static JNINativeMethod sNativeCryptoMethods[] = {
Kenny Root4d7e1f92015-04-22 09:00:29 -070010650 NATIVE_METHOD(NativeCrypto, clinit, "()Z"),
Kenny Root860d2702013-04-23 15:50:31 -070010651 NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
10652 NATIVE_METHOD(NativeCrypto, ENGINE_by_id, "(Ljava/lang/String;)J"),
10653 NATIVE_METHOD(NativeCrypto, ENGINE_add, "(J)I"),
10654 NATIVE_METHOD(NativeCrypto, ENGINE_init, "(J)I"),
10655 NATIVE_METHOD(NativeCrypto, ENGINE_finish, "(J)I"),
10656 NATIVE_METHOD(NativeCrypto, ENGINE_free, "(J)I"),
10657 NATIVE_METHOD(NativeCrypto, ENGINE_load_private_key, "(JLjava/lang/String;)J"),
10658 NATIVE_METHOD(NativeCrypto, ENGINE_get_id, "(J)Ljava/lang/String;"),
10659 NATIVE_METHOD(NativeCrypto, ENGINE_ctrl_cmd_string, "(JLjava/lang/String;Ljava/lang/String;I)I"),
Kenny Root7b27ca72014-05-08 14:27:23 -070010660 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DH, "([B[B[B[B)J"),
Kenny Root860d2702013-04-23 15:50:31 -070010661 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B[B[B[B)J"),
Kenny Root7dc06b92014-11-26 10:07:51 -080010662 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_EC_KEY, "(" REF_EC_GROUP REF_EC_POINT "[B)J"),
Kenny Root860d2702013-04-23 15:50:31 -070010663 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_mac_key, "(I[B)J"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010664 NATIVE_METHOD(NativeCrypto, EVP_PKEY_type, "(" REF_EVP_PKEY ")I"),
10665 NATIVE_METHOD(NativeCrypto, EVP_PKEY_size, "(" REF_EVP_PKEY ")I"),
10666 NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_public, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
10667 NATIVE_METHOD(NativeCrypto, EVP_PKEY_print_private, "(" REF_EVP_PKEY ")Ljava/lang/String;"),
Kenny Root860d2702013-04-23 15:50:31 -070010668 NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(J)V"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010669 NATIVE_METHOD(NativeCrypto, EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
10670 NATIVE_METHOD(NativeCrypto, i2d_PKCS8_PRIV_KEY_INFO, "(" REF_EVP_PKEY ")[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010671 NATIVE_METHOD(NativeCrypto, d2i_PKCS8_PRIV_KEY_INFO, "([B)J"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010672 NATIVE_METHOD(NativeCrypto, i2d_PUBKEY, "(" REF_EVP_PKEY ")[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010673 NATIVE_METHOD(NativeCrypto, d2i_PUBKEY, "([B)J"),
Alex Klyubin7dab2fd2015-02-09 11:32:08 -080010674 NATIVE_METHOD(NativeCrypto, getRSAPrivateKeyWrapper, "(Ljava/security/PrivateKey;[B)J"),
10675 NATIVE_METHOD(NativeCrypto, getECPrivateKeyWrapper, "(Ljava/security/PrivateKey;" REF_EC_GROUP ")J"),
Kenny Root860d2702013-04-23 15:50:31 -070010676 NATIVE_METHOD(NativeCrypto, RSA_generate_key_ex, "(I[B)J"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010677 NATIVE_METHOD(NativeCrypto, RSA_size, "(" REF_EVP_PKEY ")I"),
10678 NATIVE_METHOD(NativeCrypto, RSA_private_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10679 NATIVE_METHOD(NativeCrypto, RSA_public_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10680 NATIVE_METHOD(NativeCrypto, RSA_public_encrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10681 NATIVE_METHOD(NativeCrypto, RSA_private_decrypt, "(I[B[B" REF_EVP_PKEY "I)I"),
10682 NATIVE_METHOD(NativeCrypto, get_RSA_private_params, "(" REF_EVP_PKEY ")[[B"),
10683 NATIVE_METHOD(NativeCrypto, get_RSA_public_params, "(" REF_EVP_PKEY ")[[B"),
Kenny Root9b226f92014-07-10 14:50:48 -070010684 NATIVE_METHOD(NativeCrypto, DH_generate_parameters_ex, "(IJ)J"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010685 NATIVE_METHOD(NativeCrypto, DH_generate_key, "(" REF_EVP_PKEY ")V"),
10686 NATIVE_METHOD(NativeCrypto, get_DH_params, "(" REF_EVP_PKEY ")[[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010687 NATIVE_METHOD(NativeCrypto, EC_GROUP_new_by_curve_name, "(Ljava/lang/String;)J"),
Adam Langley05b8e502015-05-12 19:24:49 -070010688 NATIVE_METHOD(NativeCrypto, EC_GROUP_new_arbitrary, "([B[B[B[B[B[BI)J"),
Kenny Root7dc06b92014-11-26 10:07:51 -080010689 NATIVE_METHOD(NativeCrypto, EC_GROUP_set_asn1_flag, "(" REF_EC_GROUP "I)V"),
10690 NATIVE_METHOD(NativeCrypto, EC_GROUP_set_point_conversion_form, "(" REF_EC_GROUP "I)V"),
10691 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(" REF_EC_GROUP ")Ljava/lang/String;"),
10692 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(" REF_EC_GROUP ")[[B"),
10693 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(" REF_EC_GROUP ")[B"),
10694 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(" REF_EC_GROUP ")I"),
10695 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(" REF_EC_GROUP ")[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010696 NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
Kenny Root7dc06b92014-11-26 10:07:51 -080010697 NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(" REF_EC_GROUP REF_EC_GROUP ")Z"),
10698 NATIVE_METHOD(NativeCrypto, EC_GROUP_get_generator, "(" REF_EC_GROUP ")J"),
10699 NATIVE_METHOD(NativeCrypto, get_EC_GROUP_type, "(" REF_EC_GROUP ")I"),
10700 NATIVE_METHOD(NativeCrypto, EC_POINT_new, "(" REF_EC_GROUP ")J"),
Kenny Root860d2702013-04-23 15:50:31 -070010701 NATIVE_METHOD(NativeCrypto, EC_POINT_clear_free, "(J)V"),
Kenny Root7dc06b92014-11-26 10:07:51 -080010702 NATIVE_METHOD(NativeCrypto, EC_POINT_cmp, "(" REF_EC_GROUP REF_EC_POINT REF_EC_POINT ")Z"),
10703 NATIVE_METHOD(NativeCrypto, EC_POINT_set_affine_coordinates, "(" REF_EC_GROUP REF_EC_POINT "[B[B)V"),
10704 NATIVE_METHOD(NativeCrypto, EC_POINT_get_affine_coordinates, "(" REF_EC_GROUP REF_EC_POINT ")[[B"),
10705 NATIVE_METHOD(NativeCrypto, EC_KEY_generate_key, "(" REF_EC_GROUP ")J"),
10706 NATIVE_METHOD(NativeCrypto, EC_KEY_get1_group, "(" REF_EVP_PKEY ")J"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010707 NATIVE_METHOD(NativeCrypto, EC_KEY_get_private_key, "(" REF_EVP_PKEY ")[B"),
10708 NATIVE_METHOD(NativeCrypto, EC_KEY_get_public_key, "(" REF_EVP_PKEY ")J"),
10709 NATIVE_METHOD(NativeCrypto, EC_KEY_set_nonce_from_hash, "(" REF_EVP_PKEY "Z)V"),
10710 NATIVE_METHOD(NativeCrypto, ECDH_compute_key, "([BI" REF_EVP_PKEY REF_EVP_PKEY ")I"),
Kenny Root860d2702013-04-23 15:50:31 -070010711 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()J"),
Kenny Root4bff0a12014-11-25 12:02:21 -080010712 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_init, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010713 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(J)V"),
Kenny Root4bff0a12014-11-25 12:02:21 -080010714 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_copy, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;)I"),
10715 NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;J)I"),
10716 NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BII)V"),
10717 NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BI)I"),
Kenny Root860d2702013-04-23 15:50:31 -070010718 NATIVE_METHOD(NativeCrypto, EVP_get_digestbyname, "(Ljava/lang/String;)J"),
10719 NATIVE_METHOD(NativeCrypto, EVP_MD_block_size, "(J)I"),
10720 NATIVE_METHOD(NativeCrypto, EVP_MD_size, "(J)I"),
Kenny Root4bff0a12014-11-25 12:02:21 -080010721 NATIVE_METHOD(NativeCrypto, EVP_SignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;J)I"),
10722 NATIVE_METHOD(NativeCrypto, EVP_SignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BII)V"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010723 NATIVE_METHOD(NativeCrypto, EVP_SignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BI" REF_EVP_PKEY ")I"),
Kenny Root4bff0a12014-11-25 12:02:21 -080010724 NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;J)I"),
10725 NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BII)V"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010726 NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[BII" REF_EVP_PKEY ")I"),
10727 NATIVE_METHOD(NativeCrypto, EVP_DigestSignInit, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;J" REF_EVP_PKEY ")V"),
Kenny Root4bff0a12014-11-25 12:02:21 -080010728 NATIVE_METHOD(NativeCrypto, EVP_DigestSignUpdate, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;[B)V"),
10729 NATIVE_METHOD(NativeCrypto, EVP_DigestSignFinal, "(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EVP_MD_CTX;)[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010730 NATIVE_METHOD(NativeCrypto, EVP_get_cipherbyname, "(Ljava/lang/String;)J"),
Kenny Root4757cdb2014-11-26 07:59:41 -080010731 NATIVE_METHOD(NativeCrypto, EVP_CipherInit_ex, "(" REF_EVP_CIPHER_CTX "J[B[BZ)V"),
10732 NATIVE_METHOD(NativeCrypto, EVP_CipherUpdate, "(" REF_EVP_CIPHER_CTX "[BI[BII)I"),
10733 NATIVE_METHOD(NativeCrypto, EVP_CipherFinal_ex, "(" REF_EVP_CIPHER_CTX "[BI)I"),
Kenny Root860d2702013-04-23 15:50:31 -070010734 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_iv_length, "(J)I"),
10735 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_new, "()J"),
Kenny Root4757cdb2014-11-26 07:59:41 -080010736 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_block_size, "(" REF_EVP_CIPHER_CTX ")I"),
10737 NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_buf_len, "(" REF_EVP_CIPHER_CTX ")I"),
Sergio Giro1127c192015-06-08 11:36:14 +010010738 NATIVE_METHOD(NativeCrypto, get_EVP_CIPHER_CTX_final_used, "(" REF_EVP_CIPHER_CTX ")Z"),
Kenny Root4757cdb2014-11-26 07:59:41 -080010739 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_padding, "(" REF_EVP_CIPHER_CTX "Z)V"),
10740 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_set_key_length, "(" REF_EVP_CIPHER_CTX "I)V"),
Narayan Kamathb578b392014-12-10 14:58:44 +000010741 NATIVE_METHOD(NativeCrypto, EVP_CIPHER_CTX_free, "(J)V"),
Kenny Rootf6f66202015-05-08 14:01:56 -070010742 NATIVE_METHOD(NativeCrypto, EVP_aead_aes_128_gcm, "()J"),
10743 NATIVE_METHOD(NativeCrypto, EVP_aead_aes_256_gcm, "()J"),
10744 NATIVE_METHOD(NativeCrypto, EVP_AEAD_CTX_init, "(J[BI)J"),
10745 NATIVE_METHOD(NativeCrypto, EVP_AEAD_CTX_cleanup, "(J)V"),
10746 NATIVE_METHOD(NativeCrypto, EVP_AEAD_max_overhead, "(J)I"),
10747 NATIVE_METHOD(NativeCrypto, EVP_AEAD_nonce_length, "(J)I"),
10748 NATIVE_METHOD(NativeCrypto, EVP_AEAD_max_tag_len, "(J)I"),
10749 NATIVE_METHOD(NativeCrypto, EVP_AEAD_CTX_seal, "(" REF_EVP_AEAD_CTX "[BI[B[BII[B)I"),
10750 NATIVE_METHOD(NativeCrypto, EVP_AEAD_CTX_open, "(" REF_EVP_AEAD_CTX "[BI[B[BII[B)I"),
Kenny Root860d2702013-04-23 15:50:31 -070010751 NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
10752 NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
10753 NATIVE_METHOD(NativeCrypto, RAND_bytes, "([B)V"),
10754 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
10755 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
10756 NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
Adam Langleyd82dc062015-05-18 17:29:43 -070010757 NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;Z)J")),
Kenny Root860d2702013-04-23 15:50:31 -070010758 NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
10759 NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
10760 NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
Kenny Root19fdf1a2014-04-10 11:45:19 -070010761 NATIVE_METHOD(NativeCrypto, BIO_free_all, "(J)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010762 NATIVE_METHOD(NativeCrypto, X509_NAME_print_ex, "(JJ)Ljava/lang/String;"),
10763 NATIVE_METHOD(NativeCrypto, d2i_X509_bio, "(J)J"),
10764 NATIVE_METHOD(NativeCrypto, d2i_X509, "([B)J"),
10765 NATIVE_METHOD(NativeCrypto, i2d_X509, "(J)[B"),
10766 NATIVE_METHOD(NativeCrypto, i2d_X509_PUBKEY, "(J)[B"),
10767 NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509, "(J)J"),
Adam Langley2e68e222015-02-26 17:46:47 -080010768 NATIVE_METHOD(NativeCrypto, PEM_read_bio_PKCS7, "(JI)[J"),
10769 NATIVE_METHOD(NativeCrypto, d2i_PKCS7_bio, "(JI)[J"),
Kenny Root860d2702013-04-23 15:50:31 -070010770 NATIVE_METHOD(NativeCrypto, i2d_PKCS7, "([J)[B"),
10771 NATIVE_METHOD(NativeCrypto, ASN1_seq_unpack_X509_bio, "(J)[J"),
10772 NATIVE_METHOD(NativeCrypto, ASN1_seq_pack_X509, "([J)[B"),
10773 NATIVE_METHOD(NativeCrypto, X509_free, "(J)V"),
10774 NATIVE_METHOD(NativeCrypto, X509_cmp, "(JJ)I"),
10775 NATIVE_METHOD(NativeCrypto, get_X509_hashCode, "(J)I"),
10776 NATIVE_METHOD(NativeCrypto, X509_print_ex, "(JJJJ)V"),
10777 NATIVE_METHOD(NativeCrypto, X509_get_pubkey, "(J)J"),
10778 NATIVE_METHOD(NativeCrypto, X509_get_issuer_name, "(J)[B"),
10779 NATIVE_METHOD(NativeCrypto, X509_get_subject_name, "(J)[B"),
10780 NATIVE_METHOD(NativeCrypto, get_X509_pubkey_oid, "(J)Ljava/lang/String;"),
10781 NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_oid, "(J)Ljava/lang/String;"),
10782 NATIVE_METHOD(NativeCrypto, get_X509_sig_alg_parameter, "(J)[B"),
10783 NATIVE_METHOD(NativeCrypto, get_X509_issuerUID, "(J)[Z"),
10784 NATIVE_METHOD(NativeCrypto, get_X509_subjectUID, "(J)[Z"),
10785 NATIVE_METHOD(NativeCrypto, get_X509_ex_kusage, "(J)[Z"),
10786 NATIVE_METHOD(NativeCrypto, get_X509_ex_xkusage, "(J)[Ljava/lang/String;"),
10787 NATIVE_METHOD(NativeCrypto, get_X509_ex_pathlen, "(J)I"),
10788 NATIVE_METHOD(NativeCrypto, X509_get_ext_oid, "(JLjava/lang/String;)[B"),
10789 NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext_oid, "(JLjava/lang/String;)[B"),
10790 NATIVE_METHOD(NativeCrypto, get_X509_CRL_crl_enc, "(J)[B"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010791 NATIVE_METHOD(NativeCrypto, X509_CRL_verify, "(J" REF_EVP_PKEY ")V"),
Kenny Root860d2702013-04-23 15:50:31 -070010792 NATIVE_METHOD(NativeCrypto, X509_CRL_get_lastUpdate, "(J)J"),
10793 NATIVE_METHOD(NativeCrypto, X509_CRL_get_nextUpdate, "(J)J"),
10794 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext_oid, "(JLjava/lang/String;)[B"),
10795 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_serialNumber, "(J)[B"),
10796 NATIVE_METHOD(NativeCrypto, X509_REVOKED_print, "(JJ)V"),
10797 NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_revocationDate, "(J)J"),
10798 NATIVE_METHOD(NativeCrypto, get_X509_ext_oids, "(JI)[Ljava/lang/String;"),
10799 NATIVE_METHOD(NativeCrypto, get_X509_CRL_ext_oids, "(JI)[Ljava/lang/String;"),
10800 NATIVE_METHOD(NativeCrypto, get_X509_REVOKED_ext_oids, "(JI)[Ljava/lang/String;"),
10801 NATIVE_METHOD(NativeCrypto, get_X509_GENERAL_NAME_stack, "(JI)[[Ljava/lang/Object;"),
10802 NATIVE_METHOD(NativeCrypto, X509_get_notBefore, "(J)J"),
10803 NATIVE_METHOD(NativeCrypto, X509_get_notAfter, "(J)J"),
10804 NATIVE_METHOD(NativeCrypto, X509_get_version, "(J)J"),
10805 NATIVE_METHOD(NativeCrypto, X509_get_serialNumber, "(J)[B"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010806 NATIVE_METHOD(NativeCrypto, X509_verify, "(J" REF_EVP_PKEY ")V"),
Kenny Root860d2702013-04-23 15:50:31 -070010807 NATIVE_METHOD(NativeCrypto, get_X509_cert_info_enc, "(J)[B"),
10808 NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
10809 NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
10810 NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
Kenny Root35beb302013-05-06 11:49:28 -070010811 NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
Kenny Root860d2702013-04-23 15:50:31 -070010812 NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
10813 NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
10814 NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
10815 NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_serial, "(J[B)J"),
10816 NATIVE_METHOD(NativeCrypto, X509_CRL_get_REVOKED, "(J)[J"),
10817 NATIVE_METHOD(NativeCrypto, i2d_X509_CRL, "(J)[B"),
10818 NATIVE_METHOD(NativeCrypto, X509_CRL_free, "(J)V"),
10819 NATIVE_METHOD(NativeCrypto, X509_CRL_print, "(JJ)V"),
10820 NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_oid, "(J)Ljava/lang/String;"),
10821 NATIVE_METHOD(NativeCrypto, get_X509_CRL_sig_alg_parameter, "(J)[B"),
10822 NATIVE_METHOD(NativeCrypto, X509_CRL_get_issuer_name, "(J)[B"),
10823 NATIVE_METHOD(NativeCrypto, X509_CRL_get_version, "(J)J"),
10824 NATIVE_METHOD(NativeCrypto, X509_CRL_get_ext, "(JLjava/lang/String;)J"),
10825 NATIVE_METHOD(NativeCrypto, X509_REVOKED_get_ext, "(JLjava/lang/String;)J"),
10826 NATIVE_METHOD(NativeCrypto, X509_REVOKED_dup, "(J)J"),
10827 NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
10828 NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
10829 NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
10830 NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
10831 NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
10832 NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),
10833 NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
10834 NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
10835 NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
Kenny Root37e58bb2014-11-25 14:29:25 -080010836 NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(J" REF_EVP_PKEY ")V"),
10837 NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(J" REF_EVP_PKEY ")V"),
Kenny Root0e9746b2013-09-12 15:14:48 -070010838 NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[J)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010839 NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
10840 NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
10841 NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(J)J"),
10842 NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(JJ)J"),
10843 NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(JJ)J"),
10844 NATIVE_METHOD(NativeCrypto, SSL_get_options, "(J)J"),
10845 NATIVE_METHOD(NativeCrypto, SSL_set_options, "(JJ)J"),
10846 NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(JJ)J"),
Alex Klyubin01cce892014-05-09 03:44:42 -070010847 NATIVE_METHOD(NativeCrypto, SSL_use_psk_identity_hint, "(JLjava/lang/String;)V"),
10848 NATIVE_METHOD(NativeCrypto, set_SSL_psk_client_callback_enabled, "(JZ)V"),
10849 NATIVE_METHOD(NativeCrypto, set_SSL_psk_server_callback_enabled, "(JZ)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010850 NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(J[Ljava/lang/String;)V"),
Alex Klyubin2d089e12013-11-21 10:28:08 -080010851 NATIVE_METHOD(NativeCrypto, SSL_get_ciphers, "(J)[J"),
10852 NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_auth, "(J)I"),
10853 NATIVE_METHOD(NativeCrypto, get_SSL_CIPHER_algorithm_mkey, "(J)I"),
Kenny Rootf878e432013-11-08 11:37:48 -080010854 NATIVE_METHOD(NativeCrypto, SSL_set_accept_state, "(J)V"),
10855 NATIVE_METHOD(NativeCrypto, SSL_set_connect_state, "(J)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010856 NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(JI)V"),
10857 NATIVE_METHOD(NativeCrypto, SSL_set_session, "(JJ)V"),
10858 NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
Kenny Root28328c32016-05-12 14:15:24 -070010859 NATIVE_METHOD(NativeCrypto, SSL_session_reused, "(J)Z"),
Adam Langley295b30e2015-06-26 17:32:18 -070010860 NATIVE_METHOD(NativeCrypto, SSL_set_reject_peer_renegotiations, "(JZ)V"),
Kenny Root860d2702013-04-23 15:50:31 -070010861 NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
10862 NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
Matteo Franchin7dd8d0b2013-12-09 11:33:10 +000010863 NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)J"),
Kenny Rootf878e432013-11-08 11:37:48 -080010864 NATIVE_METHOD(NativeCrypto, SSL_do_handshake_bio, "(JJJ" SSL_CALLBACKS "Z[B[B)J"),
Kenny Root860d2702013-04-23 15:50:31 -070010865 NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
Kenny Root0e9746b2013-09-12 15:14:48 -070010866 NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[J"),
10867 NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[J"),
Kenny Root860d2702013-04-23 15:50:31 -070010868 NATIVE_METHOD(NativeCrypto, SSL_read, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
Kenny Root7ed0fae2014-07-22 13:03:09 -070010869 NATIVE_METHOD(NativeCrypto, SSL_read_BIO, "(J[BIIJJ" SSL_CALLBACKS ")I"),
Kenny Root860d2702013-04-23 15:50:31 -070010870 NATIVE_METHOD(NativeCrypto, SSL_write, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)V"),
Kenny Rootf878e432013-11-08 11:37:48 -080010871 NATIVE_METHOD(NativeCrypto, SSL_write_BIO, "(J[BIJ" SSL_CALLBACKS ")I"),
Kenny Root860d2702013-04-23 15:50:31 -070010872 NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(J)V"),
10873 NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(J" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
Kenny Rootf878e432013-11-08 11:37:48 -080010874 NATIVE_METHOD(NativeCrypto, SSL_shutdown_BIO, "(JJJ" SSL_CALLBACKS ")V"),
10875 NATIVE_METHOD(NativeCrypto, SSL_get_shutdown, "(J)I"),
Kenny Root860d2702013-04-23 15:50:31 -070010876 NATIVE_METHOD(NativeCrypto, SSL_free, "(J)V"),
10877 NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(J)[B"),
10878 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(J)J"),
10879 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(J)Ljava/lang/String;"),
10880 NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(J)Ljava/lang/String;"),
10881 NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(J)V"),
10882 NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(J)[B"),
10883 NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)J"),
10884 NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
10885 NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
10886 NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
Kenny Rootf8a9b542014-03-31 09:41:48 -070010887 NATIVE_METHOD(NativeCrypto, SSL_set_alpn_protos, "(J[B)I"),
Kenny Root6fcf0cb2013-06-24 15:54:18 -070010888 NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
Kenny Root860d2702013-04-23 15:50:31 -070010889 NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
Adam Langley9b8d0922015-04-24 07:36:32 -070010890 NATIVE_METHOD(NativeCrypto, SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
Adam Langleyd9a68f62015-04-28 13:19:24 -070010891 NATIVE_METHOD(NativeCrypto, get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
Kenny Root860d2702013-04-23 15:50:31 -070010892};
10893
Kenny Root652ff532014-02-24 12:35:11 -080010894static jclass getGlobalRefToClass(JNIEnv* env, const char* className) {
10895 ScopedLocalRef<jclass> localClass(env, env->FindClass(className));
10896 jclass globalRef = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
10897 if (globalRef == NULL) {
10898 ALOGE("failed to find class %s", className);
10899 abort();
10900 }
10901 return globalRef;
10902}
10903
Kenny Rootfee2d0f2014-06-04 11:24:40 -070010904static jmethodID getMethodRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
10905 jmethodID localMethod = env->GetMethodID(clazz, name, sig);
10906 if (localMethod == NULL) {
10907 ALOGE("could not find method %s", name);
10908 abort();
10909 }
10910 return localMethod;
10911}
10912
10913static jfieldID getFieldRef(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
10914 jfieldID localField = env->GetFieldID(clazz, name, sig);
10915 if (localField == NULL) {
10916 ALOGE("could not find field %s", name);
10917 abort();
10918 }
10919 return localField;
10920}
10921
Kenny Root860d2702013-04-23 15:50:31 -070010922static void initialize_conscrypt(JNIEnv* env) {
10923 jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
10924 sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
10925
Kenny Rootf24ba062014-06-09 10:37:46 -070010926 cryptoUpcallsClass = getGlobalRefToClass(env,
10927 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/CryptoUpcalls");
Kenny Root4bff0a12014-11-25 12:02:21 -080010928 nativeRefClass = getGlobalRefToClass(env,
10929 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef");
Kenny Rootfee2d0f2014-06-04 11:24:40 -070010930 openSslInputStreamClass = getGlobalRefToClass(env,
Kenny Root652ff532014-02-24 12:35:11 -080010931 TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream");
10932
Kenny Root4bff0a12014-11-25 12:02:21 -080010933 nativeRef_context = getFieldRef(env, nativeRefClass, "context", "J");
Kenny Root860d2702013-04-23 15:50:31 -070010934
Kenny Rootfee2d0f2014-06-04 11:24:40 -070010935 calendar_setMethod = getMethodRef(env, calendarClass, "set", "(IIIIII)V");
10936 inputStream_readMethod = getMethodRef(env, inputStreamClass, "read", "([B)I");
Kenny Root923e3c52013-05-01 12:17:23 -070010937 integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
Kenny Root860d2702013-04-23 15:50:31 -070010938 "(I)Ljava/lang/Integer;");
Kenny Rootfee2d0f2014-06-04 11:24:40 -070010939 openSslInputStream_readLineMethod = getMethodRef(env, openSslInputStreamClass, "gets",
Kenny Root860d2702013-04-23 15:50:31 -070010940 "([B)I");
Kenny Rootfee2d0f2014-06-04 11:24:40 -070010941 outputStream_writeMethod = getMethodRef(env, outputStreamClass, "write", "([B)V");
10942 outputStream_flushMethod = getMethodRef(env, outputStreamClass, "flush", "()V");
Kenny Root3e46e4e2014-05-23 13:35:10 -070010943
10944#ifdef CONSCRYPT_UNBUNDLED
10945 findAsynchronousCloseMonitorFuncs();
10946#endif
Kenny Root860d2702013-04-23 15:50:31 -070010947}
10948
Kenny Root923e3c52013-05-01 12:17:23 -070010949static jclass findClass(JNIEnv* env, const char* name) {
10950 ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
10951 jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
10952 if (result == NULL) {
10953 ALOGE("failed to find class '%s'", name);
10954 abort();
10955 }
10956 return result;
10957}
10958
Justin Moreye66dbe52014-06-10 14:35:13 -050010959#ifdef STATIC_LIB
10960// Give client libs everything they need to initialize our JNI
10961int libconscrypt_JNI_OnLoad(JavaVM *vm, void*) {
10962#else
Kenny Root860d2702013-04-23 15:50:31 -070010963// Use JNI_OnLoad for when we're standalone
Kenny Rooteaeedc32013-08-29 13:40:35 -070010964int JNI_OnLoad(JavaVM *vm, void*) {
Kenny Root860d2702013-04-23 15:50:31 -070010965 JNI_TRACE("JNI_OnLoad NativeCrypto");
Justin Moreye66dbe52014-06-10 14:35:13 -050010966#endif
Kenny Root860d2702013-04-23 15:50:31 -070010967 gJavaVM = vm;
10968
10969 JNIEnv *env;
Kenny Root923e3c52013-05-01 12:17:23 -070010970 if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
Kenny Root860d2702013-04-23 15:50:31 -070010971 ALOGE("Could not get JNIEnv");
10972 return JNI_ERR;
10973 }
10974
Kenny Root923e3c52013-05-01 12:17:23 -070010975 byteArrayClass = findClass(env, "[B");
10976 calendarClass = findClass(env, "java/util/Calendar");
10977 inputStreamClass = findClass(env, "java/io/InputStream");
10978 integerClass = findClass(env, "java/lang/Integer");
10979 objectClass = findClass(env, "java/lang/Object");
10980 objectArrayClass = findClass(env, "[Ljava/lang/Object;");
10981 outputStreamClass = findClass(env, "java/io/OutputStream");
10982 stringClass = findClass(env, "java/lang/String");
10983
Kenny Root860d2702013-04-23 15:50:31 -070010984 initialize_conscrypt(env);
Kenny Root923e3c52013-05-01 12:17:23 -070010985 return JNI_VERSION_1_6;
Kenny Root860d2702013-04-23 15:50:31 -070010986}
Kenny Root6e1d9d22015-05-11 10:11:53 -070010987
10988/* vim: softtabstop=4:shiftwidth=4:expandtab */
10989
10990/* Local Variables: */
10991/* mode: c++ */
10992/* tab-width: 4 */
10993/* indent-tabs-mode: nil */
10994/* c-basic-offset: 4 */
10995/* End: */