blob: 2c8a02a0b2854d8efc15c128991d5eeeb170daa2 [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/*
Brian Carlstrom0348e622010-02-10 22:56:47 -08002 * Copyright (C) 2007-2008 The Android Open Source Project
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08003 *
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.apache.harmony.xnet.provider.jsse.NativeCrypto
19 */
20
21#define LOG_TAG "NativeCrypto"
22
Brian Carlstrom0348e622010-02-10 22:56:47 -080023#include <fcntl.h>
24#include <sys/socket.h>
25#include <unistd.h>
26
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080027#include <jni.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080028
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080029#include <JNIHelp.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080030#include <LocalArray.h>
31
32#include <openssl/dsa.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080033#include <openssl/err.h>
34#include <openssl/evp.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080035#include <openssl/rand.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080036#include <openssl/rsa.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080037#include <openssl/ssl.h>
38
Brian Carlstrom3e24c532010-05-06 00:23:21 -070039#include "ScopedByteArray.h"
40#include "ScopedGlobalRef.h"
41#include "ScopedUtfChars.h"
42#include "UniquePtr.h"
43
Brian Carlstrombcfb3252010-05-02 11:27:52 -070044#undef WITH_JNI_TRACE
45#ifdef WITH_JNI_TRACE
46#define JNI_TRACE(...) \
47 ((void)LOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__)); \
Brian Carlstrom3e24c532010-05-06 00:23:21 -070048/*
49 ((void)printf("I/" LOG_TAG "-jni:")); \
50 ((void)printf(__VA_ARGS__)); \
Brian Carlstrombcfb3252010-05-02 11:27:52 -070051 ((void)printf("\n"))
Brian Carlstrom3e24c532010-05-06 00:23:21 -070052*/
Brian Carlstrombcfb3252010-05-02 11:27:52 -070053#else
54#define JNI_TRACE(...) ((void)0)
55#endif
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080056/**
57 * Frees the SSL error state.
Brian Carlstromecaf7592010-03-02 16:55:35 -080058 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080059 * OpenSSL keeps an "error stack" per thread, and given that this code
60 * can be called from arbitrary threads that we don't keep track of,
61 * we err on the side of freeing the error state promptly (instead of,
62 * say, at thread death).
63 */
64static void freeSslErrorState(void) {
65 ERR_clear_error();
66 ERR_remove_state(0);
67}
68
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080069/*
70 * Checks this thread's OpenSSL error queue and throws a RuntimeException if
71 * necessary.
Brian Carlstromecaf7592010-03-02 16:55:35 -080072 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080073 * @return 1 if an exception was thrown, 0 if not.
74 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -070075static int throwExceptionIfNecessary(JNIEnv* env, const char* /*location*/) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080076 int error = ERR_get_error();
77 int result = 0;
78
79 if (error != 0) {
80 char message[50];
81 ERR_error_string_n(error, message, sizeof(message));
Brian Carlstrom02d23a62010-05-04 22:44:46 -070082 // LOGD("OpenSSL error in %s %d: %s", location, error, message);
Elliott Hughesda4f31d2010-01-28 13:43:39 -080083 jniThrowRuntimeException(env, message);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080084 result = 1;
85 }
86
87 freeSslErrorState();
88 return result;
89}
90
Brian Carlstrom0348e622010-02-10 22:56:47 -080091
92/**
93 * Throws an SocketTimeoutException with the given string as a message.
94 */
95static void throwSocketTimeoutException(JNIEnv* env, const char* message) {
96 if (jniThrowException(env, "java/net/SocketTimeoutException", message)) {
97 LOGE("Unable to throw");
98 }
99}
100
101/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700102 * Throws a javax.net.ssl.SSLException with the given string as a message.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800103 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700104static void throwSSLExceptionStr(JNIEnv* env, const char* message) {
105 if (jniThrowException(env, "javax/net/ssl/SSLException", message)) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800106 LOGE("Unable to throw");
107 }
108}
109
110/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700111 * Throws an SSLException with a message constructed from the current
Brian Carlstrom0348e622010-02-10 22:56:47 -0800112 * SSL errors. This will also log the errors.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800113 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800114 * @param env the JNI environment
Brian Carlstrom0348e622010-02-10 22:56:47 -0800115 * @param sslErrorCode error code returned from SSL_get_error()
116 * @param message null-ok; general error message
117 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700118static void throwSSLExceptionWithSslErrors(JNIEnv* env, int sslErrorCode, const char* message) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800119 const char* messageStr = NULL;
120 char* str;
121 int ret;
122
Brian Carlstromecaf7592010-03-02 16:55:35 -0800123 // First consult the SSL error code for the general message.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800124 switch (sslErrorCode) {
125 case SSL_ERROR_NONE:
126 messageStr = "Ok";
127 break;
128 case SSL_ERROR_SSL:
129 messageStr = "Failure in SSL library, usually a protocol error";
130 break;
131 case SSL_ERROR_WANT_READ:
132 messageStr = "SSL_ERROR_WANT_READ occured. You should never see this.";
133 break;
134 case SSL_ERROR_WANT_WRITE:
135 messageStr = "SSL_ERROR_WANT_WRITE occured. You should never see this.";
136 break;
137 case SSL_ERROR_WANT_X509_LOOKUP:
138 messageStr = "SSL_ERROR_WANT_X509_LOOKUP occured. You should never see this.";
139 break;
140 case SSL_ERROR_SYSCALL:
141 messageStr = "I/O error during system call";
142 break;
143 case SSL_ERROR_ZERO_RETURN:
144 messageStr = "SSL_ERROR_ZERO_RETURN occured. You should never see this.";
145 break;
146 case SSL_ERROR_WANT_CONNECT:
147 messageStr = "SSL_ERROR_WANT_CONNECT occured. You should never see this.";
148 break;
149 case SSL_ERROR_WANT_ACCEPT:
150 messageStr = "SSL_ERROR_WANT_ACCEPT occured. You should never see this.";
151 break;
152 default:
153 messageStr = "Unknown SSL error";
154 }
155
156 // Prepend either our explicit message or a default one.
157 if (asprintf(&str, "%s: %s",
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700158 (message != NULL) ? message : "SSL error", messageStr) <= 0) {
159 // problem with asprintf
160 throwSSLExceptionStr(env, messageStr);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800161 LOGV("%s", messageStr);
162 freeSslErrorState();
163 return;
164 }
165
166 char* allocStr = str;
167
168 // For SSL protocol errors, SSL might have more information.
169 if (sslErrorCode == SSL_ERROR_SSL) {
170 // Append each error as an additional line to the message.
171 for (;;) {
172 char errStr[256];
173 const char* file;
174 int line;
175 const char* data;
176 int flags;
177 unsigned long err =
178 ERR_get_error_line_data(&file, &line, &data, &flags);
179 if (err == 0) {
180 break;
181 }
182
183 ERR_error_string_n(err, errStr, sizeof(errStr));
184
185 ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
186 (allocStr == NULL) ? "" : allocStr,
187 errStr,
188 file,
189 line,
190 data,
191 flags);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800192
193 if (ret < 0) {
194 break;
195 }
196
197 free(allocStr);
198 allocStr = str;
199 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800200 // For errors during system calls, errno might be our friend.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800201 } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
202 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
203 free(allocStr);
204 allocStr = str;
205 }
206 // If the error code is invalid, print it.
207 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
208 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
209 free(allocStr);
210 allocStr = str;
211 }
212 }
213
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700214 throwSSLExceptionStr(env, allocStr);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800215
216 LOGV("%s", allocStr);
217 free(allocStr);
218 freeSslErrorState();
219}
220
221/**
Brian Carlstromecaf7592010-03-02 16:55:35 -0800222 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800223 * If this function returns NULL and <code>throwIfNull</code> is
224 * passed as <code>true</code>, then this function will call
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700225 * <code>throwSSLExceptionStr</code> before returning, so in this case of
Brian Carlstrom0348e622010-02-10 22:56:47 -0800226 * NULL, a caller of this function should simply return and allow JNI
227 * to do its thing.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800228 *
229 * @param env the JNI environment
230 * @param ssl_address; the ssl_address pointer as an integer
Brian Carlstrom0348e622010-02-10 22:56:47 -0800231 * @param throwIfNull whether to throw if the SSL pointer is NULL
232 * @returns the pointer, which may be NULL
233 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700234static SSL* to_SSL(JNIEnv* env, int ssl_address, bool throwIfNull) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800235 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
Brian Carlstrom0348e622010-02-10 22:56:47 -0800236 if ((ssl == NULL) && throwIfNull) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700237 throwSSLExceptionStr(env, "null SSL pointer");
Brian Carlstrom0348e622010-02-10 22:56:47 -0800238 }
239
240 return ssl;
241}
242
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700243static SSL_CTX* to_SSL_CTX(int ssl_ctx_address) {
244 return reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
245}
246
247static SSL_SESSION* to_SSL_SESSION(int ssl_session_address) {
248 return reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
249}
250
Brian Carlstromecaf7592010-03-02 16:55:35 -0800251/**
252 * Converts a Java byte[] to an OpenSSL BIGNUM, allocating the BIGNUM on the
253 * fly.
254 */
255static BIGNUM* arrayToBignum(JNIEnv* env, jbyteArray source) {
256 // LOGD("Entering arrayToBignum()");
257
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700258 ScopedByteArray sourceBytes(env, source);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800259 int sourceLength = env->GetArrayLength(source);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700260 BIGNUM* bignum = BN_bin2bn((unsigned char*) sourceBytes.bytes(), sourceLength, NULL);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800261 return bignum;
262}
Brian Carlstrom0348e622010-02-10 22:56:47 -0800263
264/**
265 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
266 * suppose there are not many other ways to do this on a Linux system (modulo
267 * isomorphism).
268 */
269#define MUTEX_TYPE pthread_mutex_t
270#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
271#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
272#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
273#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
274#define THREAD_ID pthread_self()
275#define THROW_EXCEPTION (-2)
276#define THROW_SOCKETTIMEOUTEXCEPTION (-3)
277
278static MUTEX_TYPE *mutex_buf = NULL;
279
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700280static void locking_function(int mode, int n, const char*, int) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800281 if (mode & CRYPTO_LOCK) {
282 MUTEX_LOCK(mutex_buf[n]);
283 } else {
284 MUTEX_UNLOCK(mutex_buf[n]);
285 }
286}
287
288static unsigned long id_function(void) {
289 return ((unsigned long)THREAD_ID);
290}
291
292int THREAD_setup(void) {
293 int i;
294
295 mutex_buf = (MUTEX_TYPE *)malloc(CRYPTO_num_locks( ) * sizeof(MUTEX_TYPE));
296
297 if(!mutex_buf) {
298 return 0;
299 }
300
301 for (i = 0; i < CRYPTO_num_locks( ); i++) {
302 MUTEX_SETUP(mutex_buf[i]);
303 }
304
305 CRYPTO_set_id_callback(id_function);
306 CRYPTO_set_locking_callback(locking_function);
307
308 return 1;
309}
310
311int THREAD_cleanup(void) {
312 int i;
313
314 if (!mutex_buf) {
315 return 0;
316 }
317
318 CRYPTO_set_id_callback(NULL);
319 CRYPTO_set_locking_callback(NULL);
320
321 for (i = 0; i < CRYPTO_num_locks( ); i++) {
322 MUTEX_CLEANUP(mutex_buf[i]);
323 }
324
325 free(mutex_buf);
326 mutex_buf = NULL;
327
328 return 1;
329}
330
Brian Carlstromecaf7592010-03-02 16:55:35 -0800331/**
332 * Initialization phase for every OpenSSL job: Loads the Error strings, the
333 * crypto algorithms and reset the OpenSSL library
334 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700335static void NativeCrypto_clinit(JNIEnv*, jclass)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800336{
337 SSL_load_error_strings();
338 ERR_load_crypto_strings();
339 SSL_library_init();
340 OpenSSL_add_all_algorithms();
341 THREAD_setup();
342}
343
344/**
345 * public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g, byte[] pub_key, byte[] priv_key);
346 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700347static EVP_PKEY* NativeCrypto_EVP_PKEY_new_DSA(JNIEnv* env, jclass, jbyteArray p, jbyteArray q, jbyteArray g, jbyteArray pub_key, jbyteArray priv_key) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800348 // LOGD("Entering EVP_PKEY_new_DSA()");
349
350 DSA* dsa = DSA_new();
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700351 if (dsa == NULL) {
352 jniThrowRuntimeException(env, "DSA_new failed");
353 return NULL;
354 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800355
356 dsa->p = arrayToBignum(env, p);
357 dsa->q = arrayToBignum(env, q);
358 dsa->g = arrayToBignum(env, g);
359 dsa->pub_key = arrayToBignum(env, pub_key);
360
361 if (priv_key != NULL) {
362 dsa->priv_key = arrayToBignum(env, priv_key);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800363 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800364
Brian Carlstromecaf7592010-03-02 16:55:35 -0800365 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL) {
366 DSA_free(dsa);
367 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
368 return NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800369 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800370
371 EVP_PKEY* pkey = EVP_PKEY_new();
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700372 if (pkey == NULL) {
373 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
374 return NULL;
375 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800376 EVP_PKEY_assign_DSA(pkey, dsa);
377
378 return pkey;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800379}
380
Brian Carlstromecaf7592010-03-02 16:55:35 -0800381/**
382 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
383 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700384static EVP_PKEY* NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jbyteArray e, jbyteArray d, jbyteArray p, jbyteArray q) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800385 // LOGD("Entering EVP_PKEY_new_RSA()");
386
387 RSA* rsa = RSA_new();
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700388 if (rsa == NULL) {
389 jniThrowRuntimeException(env, "RSA_new failed");
390 return NULL;
391 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800392
393 rsa->n = arrayToBignum(env, n);
394 rsa->e = arrayToBignum(env, e);
395
396 if (d != NULL) {
397 rsa->d = arrayToBignum(env, d);
398 }
399
400 if (p != NULL) {
401 rsa->p = arrayToBignum(env, p);
402 }
403
404 if (q != NULL) {
405 rsa->q = arrayToBignum(env, q);
406 }
407
408 // int check = RSA_check_key(rsa);
409 // LOGI("RSA_check_key returns %d", check);
410
411 if (rsa->n == NULL || rsa->e == NULL) {
412 RSA_free(rsa);
413 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
414 return NULL;
415 }
416
417 EVP_PKEY* pkey = EVP_PKEY_new();
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700418 if (pkey == NULL) {
419 RSA_free(rsa);
420 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
421 return NULL;
422 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800423 EVP_PKEY_assign_RSA(pkey, rsa);
424
425 return pkey;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800426}
427
Brian Carlstromecaf7592010-03-02 16:55:35 -0800428/**
429 * private static native void EVP_PKEY_free(int pkey);
430 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700431static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, EVP_PKEY* pkey) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800432 // LOGD("Entering EVP_PKEY_free()");
433
434 if (pkey != NULL) {
435 EVP_PKEY_free(pkey);
436 }
437}
438
439/*
440 * public static native int EVP_new()
441 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700442static jint NativeCrypto_EVP_new(JNIEnv*, jclass) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800443 // LOGI("NativeCrypto_EVP_DigestNew");
444
445 return (jint)EVP_MD_CTX_create();
446}
447
448/*
449 * public static native void EVP_free(int)
450 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700451static void NativeCrypto_EVP_free(JNIEnv*, jclass, EVP_MD_CTX* ctx) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800452 // LOGI("NativeCrypto_EVP_DigestFree");
453
454 if (ctx != NULL) {
455 EVP_MD_CTX_destroy(ctx);
456 }
457}
458
459/*
460 * public static native int EVP_DigestFinal(int, byte[], int)
461 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700462static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jbyteArray hash, jint offset) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800463 // LOGI("NativeCrypto_EVP_DigestFinal%x, %x, %d, %d", ctx, hash, offset);
464
465 if (ctx == NULL || hash == NULL) {
466 jniThrowNullPointerException(env, NULL);
467 return -1;
468 }
469
470 int result = -1;
471
472 jbyte* hashBytes = env->GetByteArrayElements(hash, NULL);
473 EVP_DigestFinal(ctx, (unsigned char*) (hashBytes + offset), (unsigned int*)&result);
474 env->ReleaseByteArrayElements(hash, hashBytes, 0);
475
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700476 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestFinal");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800477
478 return result;
479}
480
481/*
482 * public static native void EVP_DigestInit(int, java.lang.String)
483 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700484static void NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jstring algorithm) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800485 // LOGI("NativeCrypto_EVP_DigestInit");
486
487 if (ctx == NULL || algorithm == NULL) {
488 jniThrowNullPointerException(env, NULL);
489 return;
490 }
491
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700492 ScopedUtfChars algorithmChars(env, algorithm);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800493
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700494 const EVP_MD *digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str()));
Brian Carlstromecaf7592010-03-02 16:55:35 -0800495
496 if (digest == NULL) {
497 jniThrowRuntimeException(env, "Hash algorithm not found");
498 return;
499 }
500
501 EVP_DigestInit(ctx, digest);
502
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700503 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestInit");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800504}
505
506/*
507 * public static native void EVP_DigestSize(int)
508 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700509static jint NativeCrypto_EVP_DigestSize(JNIEnv* env, jclass, EVP_MD_CTX* ctx) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800510 // LOGI("NativeCrypto_EVP_DigestSize");
511
512 if (ctx == NULL) {
513 jniThrowNullPointerException(env, NULL);
514 return -1;
515 }
516
517 int result = EVP_MD_CTX_size(ctx);
518
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700519 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestSize");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800520
521 return result;
522}
523
524/*
525 * public static native void EVP_DigestBlockSize(int)
526 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700527static jint NativeCrypto_EVP_DigestBlockSize(JNIEnv* env, jclass, EVP_MD_CTX* ctx) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800528 // LOGI("NativeCrypto_EVP_DigestBlockSize");
529
530 if (ctx == NULL) {
531 jniThrowNullPointerException(env, NULL);
532 return -1;
533 }
534
535 int result = EVP_MD_CTX_block_size(ctx);
536
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700537 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestBlockSize");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800538
539 return result;
540}
541
542/*
543 * public static native void EVP_DigestUpdate(int, byte[], int, int)
544 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700545static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jbyteArray buffer, jint offset, jint length) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800546 // LOGI("NativeCrypto_EVP_DigestUpdate %x, %x, %d, %d", ctx, buffer, offset, length);
547
548 if (ctx == NULL || buffer == NULL) {
549 jniThrowNullPointerException(env, NULL);
550 return;
551 }
552
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700553 ScopedByteArray bufferBytes(env, buffer);
554 EVP_DigestUpdate(ctx, (unsigned char*) (bufferBytes.bytes() + offset), length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800555
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700556 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestUpdate");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800557}
558
559/*
560 * public static native void EVP_VerifyInit(int, java.lang.String)
561 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700562static void NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jstring algorithm) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800563 // LOGI("NativeCrypto_EVP_VerifyInit");
564
565 if (ctx == NULL || algorithm == NULL) {
566 jniThrowNullPointerException(env, NULL);
567 return;
568 }
569
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700570 ScopedUtfChars algorithmChars(env, algorithm);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800571
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700572 const EVP_MD *digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str()));
Brian Carlstromecaf7592010-03-02 16:55:35 -0800573
574 if (digest == NULL) {
575 jniThrowRuntimeException(env, "Hash algorithm not found");
576 return;
577 }
578
579 EVP_VerifyInit(ctx, digest);
580
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700581 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyInit");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800582}
583
584/*
585 * public static native void EVP_VerifyUpdate(int, byte[], int, int)
586 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700587static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jbyteArray buffer, jint offset, jint length) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800588 // LOGI("NativeCrypto_EVP_VerifyUpdate %x, %x, %d, %d", ctx, buffer, offset, length);
589
590 if (ctx == NULL || buffer == NULL) {
591 jniThrowNullPointerException(env, NULL);
592 return;
593 }
594
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700595 ScopedByteArray bufferBytes(env, buffer);
596 EVP_VerifyUpdate(ctx, (unsigned char*) (bufferBytes.bytes() + offset), length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800597
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700598 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800599}
600
601/*
602 * public static native void EVP_VerifyFinal(int, byte[], int, int, int)
603 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700604static int NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jbyteArray buffer, jint offset, jint length, EVP_PKEY* pkey) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800605 // LOGI("NativeCrypto_EVP_VerifyFinal %x, %x, %d, %d %x", ctx, buffer, offset, length, pkey);
606
607 if (ctx == NULL || buffer == NULL || pkey == NULL) {
608 jniThrowNullPointerException(env, NULL);
609 return -1;
610 }
611
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700612 ScopedByteArray bufferBytes(env, buffer);
613 int result = EVP_VerifyFinal(ctx, (unsigned char*) (bufferBytes.bytes() + offset), length, pkey);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800614
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700615 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyFinal");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800616
617 return result;
618}
619
620/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700621 * Helper function that creates an RSA public key from two buffers containing
622 * the big-endian bit representation of the modulus and the public exponent.
623 *
624 * @param mod The data of the modulus
625 * @param modLen The length of the modulus data
626 * @param exp The data of the exponent
627 * @param expLen The length of the exponent data
628 *
629 * @return A pointer to the new RSA structure, or NULL on error
630 */
631static RSA* rsaCreateKey(unsigned char* mod, int modLen, unsigned char* exp, int expLen) {
632 // LOGD("Entering rsaCreateKey()");
633
634 RSA* rsa = RSA_new();
635 if (rsa == NULL) {
636 return NULL;
637 }
638
639 rsa->n = BN_bin2bn(mod, modLen, NULL);
640 rsa->e = BN_bin2bn(exp, expLen, NULL);
641
642 if (rsa->n == NULL || rsa->e == NULL) {
643 RSA_free(rsa);
644 return NULL;
645 }
646
647 return rsa;
648}
649
650/**
651 * Helper function that verifies a given RSA signature for a given message.
652 *
653 * @param msg The message to verify
654 * @param msgLen The length of the message
655 * @param sig The signature to verify
656 * @param sigLen The length of the signature
657 * @param algorithm The name of the hash/sign algorithm to use, e.g. "RSA-SHA1"
658 * @param rsa The RSA public key to use
659 *
660 * @return 1 on success, 0 on failure, -1 on error (check SSL errors then)
661 *
662 */
663static int rsaVerify(unsigned char* msg, unsigned int msgLen, unsigned char* sig,
664 unsigned int sigLen, char* algorithm, RSA* rsa) {
665
666 // LOGD("Entering rsaVerify(%x, %d, %x, %d, %s, %x)", msg, msgLen, sig, sigLen, algorithm, rsa);
667
668 EVP_PKEY* pkey = EVP_PKEY_new();
669 if (pkey == NULL) {
670 return -1;
671 }
672 EVP_PKEY_set1_RSA(pkey, rsa);
673
674 const EVP_MD *type = EVP_get_digestbyname(algorithm);
675 if (type == NULL) {
676 EVP_PKEY_free(pkey);
677 return -1;
678 }
679
680 EVP_MD_CTX ctx;
681 EVP_MD_CTX_init(&ctx);
682 if (EVP_VerifyInit_ex(&ctx, type, NULL) == 0) {
683 EVP_PKEY_free(pkey);
684 return -1;
685 }
686
687 EVP_VerifyUpdate(&ctx, msg, msgLen);
688 int result = EVP_VerifyFinal(&ctx, sig, sigLen, pkey);
689 EVP_MD_CTX_cleanup(&ctx);
690 EVP_PKEY_free(pkey);
691 return result;
692}
693
694/**
695 * Verifies an RSA signature.
696 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700697static int NativeCrypto_verifysignature(JNIEnv* env, jclass,
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700698 jbyteArray msg, jbyteArray sig, jstring algorithm, jbyteArray mod, jbyteArray exp) {
699
700 JNI_TRACE("NativeCrypto_verifysignature msg=%p sig=%p algorithm=%p mod=%p exp%p",
701 msg, sig, algorithm, mod, exp);
702
703 if (msg == NULL || sig == NULL || algorithm == NULL || mod == NULL || exp == NULL) {
704 jniThrowNullPointerException(env, NULL);
705 JNI_TRACE("NativeCrypto_verifysignature => -1");
706 return -1;
707 }
708
709 int result = -1;
710
711 ScopedByteArray msgBytes(env, msg);
712 jint msgLength = env->GetArrayLength(msg);
713
714 ScopedByteArray sigBytes(env, sig);
715 jint sigLength = env->GetArrayLength(sig);
716
717 ScopedByteArray modBytes(env, mod);
718 jint modLength = env->GetArrayLength(mod);
719
720 ScopedByteArray expBytes(env, exp);
721 jint expLength = env->GetArrayLength(exp);
722
723 ScopedUtfChars algorithmChars(env, algorithm);
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700724 JNI_TRACE("NativeCrypto_verifysignature algorithmChars=%s", algorithmChars.c_str());
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700725
726 RSA* rsa = rsaCreateKey((unsigned char*) modBytes.bytes(), modLength, (unsigned char*) expBytes.bytes(), expLength);
727 if (rsa != NULL) {
728 result = rsaVerify((unsigned char*) msgBytes.bytes(), msgLength, (unsigned char*) sigBytes.bytes(), sigLength,
729 (char*) algorithmChars.c_str(), rsa);
730 RSA_free(rsa);
731 }
732
733 if (result == -1) {
734 if (!throwExceptionIfNecessary(env, "NativeCrypto_verifysignature")) {
735 jniThrowRuntimeException(env, "Internal error during verification");
736 }
737 }
738
739 JNI_TRACE("NativeCrypto_verifysignature => %d", result);
740 return result;
741}
742
743/**
Brian Carlstromecaf7592010-03-02 16:55:35 -0800744 * Convert ssl version constant to string. Based on SSL_get_version
745 */
Brian Carlstromf002bdd2010-05-05 13:23:14 -0700746// TODO move to jsse.patch
Brian Carlstromecaf7592010-03-02 16:55:35 -0800747static const char* get_ssl_version(int ssl_version) {
748 switch (ssl_version) {
749 // newest to oldest
750 case TLS1_VERSION: {
751 return SSL_TXT_TLSV1;
752 }
753 case SSL3_VERSION: {
754 return SSL_TXT_SSLV3;
755 }
756 case SSL2_VERSION: {
757 return SSL_TXT_SSLV2;
758 }
759 default: {
760 return "unknown";
761 }
762 }
763}
764
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700765#ifdef WITH_JNI_TRACE
Brian Carlstromecaf7592010-03-02 16:55:35 -0800766/**
767 * Convert content type constant to string.
768 */
Brian Carlstromf002bdd2010-05-05 13:23:14 -0700769// TODO move to jsse.patch
Brian Carlstromecaf7592010-03-02 16:55:35 -0800770static const char* get_content_type(int content_type) {
771 switch (content_type) {
772 case SSL3_RT_CHANGE_CIPHER_SPEC: {
773 return "SSL3_RT_CHANGE_CIPHER_SPEC";
774 }
775 case SSL3_RT_ALERT: {
776 return "SSL3_RT_ALERT";
777 }
778 case SSL3_RT_HANDSHAKE: {
779 return "SSL3_RT_HANDSHAKE";
780 }
781 case SSL3_RT_APPLICATION_DATA: {
782 return "SSL3_RT_APPLICATION_DATA";
783 }
784 default: {
785 LOGD("Unknown TLS/SSL content type %d", content_type);
786 return "<unknown>";
787 }
788 }
789}
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700790#endif
Brian Carlstromecaf7592010-03-02 16:55:35 -0800791
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700792#ifdef WITH_JNI_TRACE
Brian Carlstromecaf7592010-03-02 16:55:35 -0800793/**
794 * Simple logging call back to show hand shake messages
795 */
796static void ssl_msg_callback_LOG(int write_p, int ssl_version, int content_type,
797 const void *buf, size_t len, SSL* ssl, void* arg) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700798 JNI_TRACE("ssl=%p SSL msg %s %s %s %p %d %p",
799 ssl,
800 (write_p) ? "send" : "recv",
801 get_ssl_version(ssl_version),
802 get_content_type(content_type),
803 buf,
804 len,
805 arg);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800806}
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700807#endif
Brian Carlstromecaf7592010-03-02 16:55:35 -0800808
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700809#ifdef WITH_JNI_TRACE
Brian Carlstromecaf7592010-03-02 16:55:35 -0800810/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700811 * Based on example logging call back from SSL_CTX_set_info_callback man page
Brian Carlstromecaf7592010-03-02 16:55:35 -0800812 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700813static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800814{
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700815 int w = where & ~SSL_ST_MASK;
816 const char* str;
817 if (w & SSL_ST_CONNECT) {
818 str = "SSL_connect";
819 } else if (w & SSL_ST_ACCEPT) {
820 str = "SSL_accept";
Brian Carlstromecaf7592010-03-02 16:55:35 -0800821 } else {
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700822 str = "undefined";
Brian Carlstromecaf7592010-03-02 16:55:35 -0800823 }
824
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700825 if (where & SSL_CB_LOOP) {
826 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
827 } else if (where & SSL_CB_ALERT) {
828 str = (where & SSL_CB_READ) ? "read" : "write";
829 JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
830 s,
831 str,
832 SSL_alert_type_string(ret),
833 SSL_alert_desc_string(ret),
834 SSL_alert_type_string_long(ret),
835 SSL_alert_desc_string_long(ret));
836 } else if (where & SSL_CB_EXIT) {
837 if (ret == 0) {
838 JNI_TRACE("ssl=%p %s:failed exit in %s %s",
839 s, str, SSL_state_string(s), SSL_state_string_long(s));
840 } else if (ret < 0) {
841 JNI_TRACE("ssl=%p %s:error exit in %s %s",
842 s, str, SSL_state_string(s), SSL_state_string_long(s));
843 } else if (ret == 1) {
844 JNI_TRACE("ssl=%p %s:ok exit in %s %s",
845 s, str, SSL_state_string(s), SSL_state_string_long(s));
846 } else {
847 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
848 s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
849 }
850 } else if (where & SSL_CB_HANDSHAKE_START) {
851 JNI_TRACE("ssl=%p handshake start in %s %s",
852 s, SSL_state_string(s), SSL_state_string_long(s));
853 } else if (where & SSL_CB_HANDSHAKE_DONE) {
854 JNI_TRACE("ssl=%p handshake done in %s %s",
855 s, SSL_state_string(s), SSL_state_string_long(s));
856 } else {
857 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
858 s, str, where, SSL_state_string(s), SSL_state_string_long(s));
859 }
860}
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700861#endif
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700862
863/**
864 * Returns an array containing all the X509 certificate's bytes.
865 */
866static jobjectArray getCertificateBytes(JNIEnv* env,
867 const STACK_OF(X509) *chain)
868{
869 if (chain == NULL) {
870 // Chain can be NULL if the associated cipher doesn't do certs.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800871 return NULL;
872 }
873
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700874 int count = sk_X509_num(chain);
875 if (count <= 0) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700876 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700877 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800878
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700879 jobjectArray joa = env->NewObjectArray(count, env->FindClass("[B"), NULL);
880 if (joa == NULL) {
881 return NULL;
882 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800883
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700884 BIO* bio = BIO_new(BIO_s_mem());
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700885 if (bio == NULL) {
886 jniThrowRuntimeException(env, "BIO_new failed");
887 return NULL;
888 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700889
890 // LOGD("Start fetching the certificates");
891 for (int i = 0; i < count; i++) {
892 X509* cert = sk_X509_value(chain, i);
893
894 BIO_reset(bio);
895 PEM_write_bio_X509(bio, cert);
896
897 BUF_MEM* bptr;
898 BIO_get_mem_ptr(bio, &bptr);
899 jbyteArray bytes = env->NewByteArray(bptr->length);
900
901 if (bytes == NULL) {
902 /*
903 * Indicate an error by resetting joa to NULL. It will
904 * eventually get gc'ed.
905 */
906 joa = NULL;
907 break;
Brian Carlstromecaf7592010-03-02 16:55:35 -0800908 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700909 jbyte* src = reinterpret_cast<jbyte*>(bptr->data);
910 env->SetByteArrayRegion(bytes, 0, bptr->length, src);
911 env->SetObjectArrayElement(joa, i, bytes);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800912 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800913
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700914 // LOGD("Certificate fetching complete");
915 BIO_free(bio);
916 return joa;
Brian Carlstromecaf7592010-03-02 16:55:35 -0800917}
Brian Carlstrom0348e622010-02-10 22:56:47 -0800918
919/**
920 * Our additional application data needed for getting synchronization right.
921 * This maybe warrants a bit of lengthy prose:
Brian Carlstromecaf7592010-03-02 16:55:35 -0800922 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800923 * (1) We use a flag to reflect whether we consider the SSL connection alive.
924 * Any read or write attempt loops will be cancelled once this flag becomes 0.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800925 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800926 * (2) We use an int to count the number of threads that are blocked by the
927 * underlying socket. This may be at most two (one reader and one writer), since
928 * the Java layer ensures that no more threads will enter the native code at the
929 * same time.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800930 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800931 * (3) The pipe is used primarily as a means of cancelling a blocking select()
932 * when we want to close the connection (aka "emergency button"). It is also
933 * necessary for dealing with a possible race condition situation: There might
934 * be cases where both threads see an SSL_ERROR_WANT_READ or
935 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
936 * If one leaves the select() successfully before the other enters it, the
937 * "success" event is already consumed and the second thread will be blocked,
938 * possibly forever (depending on network conditions).
Brian Carlstromecaf7592010-03-02 16:55:35 -0800939 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800940 * The idea for solving the problem looks like this: Whenever a thread is
941 * successful in moving around data on the network, and it knows there is
942 * another thread stuck in a select(), it will write a byte to the pipe, waking
943 * up the other thread. A thread that returned from select(), on the other hand,
944 * knows whether it's been woken up by the pipe. If so, it will consume the
945 * byte, and the original state of affairs has been restored.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800946 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800947 * The pipe may seem like a bit of overhead, but it fits in nicely with the
948 * other file descriptors of the select(), so there's only one condition to wait
949 * for.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800950 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800951 * (4) Finally, a mutex is needed to make sure that at most one thread is in
952 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
953 * requirement. We use the same mutex to guard the field for counting the
954 * waiting threads.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800955 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800956 * Note: The current implementation assumes that we don't have to deal with
957 * problems induced by multiple cores or processors and their respective
958 * memory caches. One possible problem is that of inconsistent views on the
959 * "aliveAndKicking" field. This could be worked around by also enclosing all
960 * accesses to that field inside a lock/unlock sequence of our mutex, but
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700961 * currently this seems a bit like overkill. Marking volatile at the very least.
962 *
963 * During handshaking, three additional fields are used to up-call into
964 * Java to perform certificate verification and handshake completion.
965 *
966 * (5) the JNIEnv so we can invoke the Java callback
967 *
968 * (6) a NativeCrypto.CertificateChainVerifier to call with the peer certificate chain
969 *
970 * (7) a NativeCrypto.HandshakeCompletedCallback to call back when handshake is done
971 *
972 * These fields are cleared by the info_callback the handshake has
973 * completed. SSL_VERIFY_CLIENT_ONCE is currently used to disable
974 * renegotiation but if that changes, care would need to be taken to
975 * maintain an appropriate JNIEnv on any downcall to openssl that
976 * could result in an upcall to Java. The current code does try to
977 * cover these cases by conditionally setting the JNIenv on calls that
978 * can read and write to the SSL such as SSL_do_handshake, SSL_read,
979 * SSL_write, and SSL_shutdown if handshaking is not complete.
980 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800981 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700982class AppData {
983 public:
Brian Carlstromecaf7592010-03-02 16:55:35 -0800984 volatile int aliveAndKicking;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800985 int waitingThreads;
986 int fdsEmergency[2];
987 MUTEX_TYPE mutex;
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700988 JNIEnv* env;
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700989 ScopedGlobalRef certificateChainVerifier;
990 ScopedGlobalRef handshakeCompletedCallback;
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700991
992 /**
993 * Creates our application data and attaches it to a given SSL connection.
994 *
995 * @param ssl The SSL connection to attach the data to.
996 * @param env The JNIEnv
997 * @param ccv The CertificateChainVerifier
998 * @param hcc The HandshakeCompletedCallback
999 */
1000 public:
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001001 static AppData* create(JNIEnv* e,
1002 jobject certificateChainVerifier,
1003 jobject handshakeCompletedCallback) {
1004 if (certificateChainVerifier == NULL) {
1005 return NULL;
1006 }
1007 if (handshakeCompletedCallback == NULL) {
1008 return NULL;
1009 }
1010 UniquePtr<AppData> appData(new AppData(e, certificateChainVerifier, handshakeCompletedCallback));
1011 if (appData->certificateChainVerifier.get() == NULL) {
1012 return NULL;
1013 }
1014 if (appData->handshakeCompletedCallback.get() == NULL) {
1015 return NULL;
1016 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001017 if (pipe(appData->fdsEmergency) == -1) {
1018 return NULL;
1019 }
1020 if (MUTEX_SETUP(appData->mutex) == -1) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001021 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001022 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001023 return appData.release();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001024 }
1025
1026 private:
1027 AppData(JNIEnv* e, jobject ccv, jobject hcc) :
1028 aliveAndKicking(1),
1029 waitingThreads(0),
1030 env(e),
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001031 certificateChainVerifier(e, ccv),
1032 handshakeCompletedCallback(e, hcc) {
1033 fdsEmergency[0] = -1;
1034 fdsEmergency[1] = -1;
1035 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001036
1037 /**
1038 * Destroys our application data, cleaning up everything in the process.
1039 */
1040 public:
1041 ~AppData() {
1042 aliveAndKicking = 0;
1043 if (fdsEmergency[0] != -1) {
1044 close(fdsEmergency[0]);
1045 }
1046 if (fdsEmergency[1] != -1) {
1047 close(fdsEmergency[1]);
1048 }
1049 MUTEX_CLEANUP(mutex);
1050 }
1051
1052 void setEnv(JNIEnv* e) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001053 if (handshakeCompletedCallback.get() == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001054 return;
1055 }
1056 env = e;
1057 }
1058 void clearEnv() {
1059 env = NULL;
1060 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001061
1062 void handshakeCompleted() {
1063 certificateChainVerifier.reset();
1064 handshakeCompletedCallback.reset();
1065 clearEnv();
1066 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001067};
Brian Carlstrom0348e622010-02-10 22:56:47 -08001068
1069/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001070 * Dark magic helper function that checks, for a given SSL session, whether it
1071 * can SSL_read() or SSL_write() without blocking. Takes into account any
1072 * concurrent attempts to close the SSL session from the Java side. This is
1073 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
1074 * while thread #2 is sitting in a blocking read or write. The type argument
1075 * specifies whether we are waiting for readability or writability. It expects
1076 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
1077 * only need to wait in case one of these problems occurs.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001078 *
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001079 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
1080 * @param fd The file descriptor to wait for (the underlying socket)
1081 * @param data The application data structure with mutex info etc.
1082 * @param timeout The timeout value for select call, with the special value
1083 * 0 meaning no timeout at all (wait indefinitely). Note: This is
1084 * the Java semantics of the timeout value, not the usual
1085 * select() semantics.
1086 * @return The result of the inner select() call, -1 on additional errors
Brian Carlstrom0348e622010-02-10 22:56:47 -08001087 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001088static int sslSelect(int type, int fd, AppData* appData, int timeout) {
1089 fd_set rfds;
1090 fd_set wfds;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001091
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001092 FD_ZERO(&rfds);
1093 FD_ZERO(&wfds);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001094
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001095 if (type == SSL_ERROR_WANT_READ) {
1096 FD_SET(fd, &rfds);
1097 } else {
1098 FD_SET(fd, &wfds);
1099 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08001100
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001101 FD_SET(appData->fdsEmergency[0], &rfds);
1102
1103 int max = fd > appData->fdsEmergency[0] ? fd : appData->fdsEmergency[0];
1104
1105 // Build a struct for the timeout data if we actually want a timeout.
1106 struct timeval tv;
1107 struct timeval *ptv;
1108 if (timeout > 0) {
1109 tv.tv_sec = timeout / 1000;
1110 tv.tv_usec = 0;
1111 ptv = &tv;
1112 } else {
1113 ptv = NULL;
1114 }
1115
1116 // LOGD("Doing select() for SSL_ERROR_WANT_%s...", type == SSL_ERROR_WANT_READ ? "READ" : "WRITE");
1117 int result = select(max + 1, &rfds, &wfds, NULL, ptv);
1118 // LOGD("Returned from select(), result is %d", result);
1119
1120 // Lock
1121 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08001122 return -1;
1123 }
1124
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001125 // If we have been woken up by the emergency pipe, there must be a token in
1126 // it. Thus we can safely read it (even in a blocking way).
1127 if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
1128 char token;
1129 do {
1130 read(appData->fdsEmergency[0], &token, 1);
1131 } while (errno == EINTR);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001132 }
1133
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001134 // Tell the world that there is now one thread less waiting for the
1135 // underlying network.
1136 appData->waitingThreads--;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001137
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001138 // Unlock
1139 MUTEX_UNLOCK(appData->mutex);
1140 // LOGD("leave sslSelect");
1141 return result;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001142}
1143
1144/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001145 * Helper function that wakes up a thread blocked in select(), in case there is
1146 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
1147 * before closing the connection.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001148 *
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001149 * @param data The application data structure with mutex info etc.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001150 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001151static void sslNotify(AppData* appData) {
1152 // Write a byte to the emergency pipe, so a concurrent select() can return.
1153 // Note we have to restore the errno of the original system call, since the
1154 // caller relies on it for generating error messages.
1155 int errnoBackup = errno;
1156 char token = '*';
1157 do {
1158 errno = 0;
1159 write(appData->fdsEmergency[1], &token, 1);
1160 } while (errno == EINTR);
1161 errno = errnoBackup;
1162}
Brian Carlstrom0348e622010-02-10 22:56:47 -08001163
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001164// From private header file external/openssl/ssl_locl.h
Brian Carlstromf002bdd2010-05-05 13:23:14 -07001165// TODO move dependant code to jsse.patch to avoid dependency
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001166#define SSL_aRSA 0x00000001L
1167#define SSL_aDSS 0x00000002L
1168#define SSL_aNULL 0x00000004L
1169#define SSL_aDH 0x00000008L
1170#define SSL_aECDH 0x00000010L
1171#define SSL_aKRB5 0x00000020L
1172#define SSL_aECDSA 0x00000040L
1173#define SSL_aPSK 0x00000080L
Brian Carlstrom0348e622010-02-10 22:56:47 -08001174
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001175/**
1176 * Converts an SSL_CIPHER's algorithms field to a TrustManager auth argument
1177 */
Brian Carlstromf002bdd2010-05-05 13:23:14 -07001178// TODO move to jsse.patch
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001179static const char* SSL_CIPHER_authentication_method(const SSL_CIPHER* cipher)
1180{
1181 unsigned long alg_auth = cipher->algorithm_auth;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001182
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001183 const char *au;
1184 switch (alg_auth) {
1185 case SSL_aRSA:
1186 au="RSA";
1187 break;
1188 case SSL_aDSS:
1189 au="DSS";
1190 break;
1191 case SSL_aDH:
1192 au="DH";
1193 break;
1194 case SSL_aKRB5:
1195 au="KRB5";
1196 break;
1197 case SSL_aECDH:
1198 au = "ECDH";
1199 break;
1200 case SSL_aNULL:
1201 au="None";
1202 break;
1203 case SSL_aECDSA:
1204 au="ECDSA";
1205 break;
1206 case SSL_aPSK:
1207 au="PSK";
1208 break;
1209 default:
1210 au="unknown";
1211 break;
1212 }
1213 return au;
1214}
1215
1216/**
1217 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
1218 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001219static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001220{
1221 /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
1222 SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(x509_store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1223 JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
1224
1225 AppData* appData = (AppData*) SSL_get_app_data(ssl);
1226 JNIEnv* env = appData->env;
1227 if (env == NULL) {
1228 LOGE("AppData->env missing in cert_verify_callback");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001229 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001230 return 0;
1231 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001232 jobject certificateChainVerifier = appData->certificateChainVerifier.get();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001233
1234 jclass cls = env->GetObjectClass(certificateChainVerifier);
1235 jmethodID methodID = env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
1236
1237 jobjectArray objectArray = getCertificateBytes(env, x509_store_ctx->untrusted);
1238
1239 const char* authMethod;
1240 switch (ssl->version) {
1241 case SSL2_VERSION:
1242 authMethod = "RSA";
1243 break;
1244 case SSL3_VERSION:
1245 case TLS1_VERSION:
1246 case DTLS1_VERSION:
1247 authMethod = SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher);
1248 break;
1249 default:
1250 authMethod = "unknown";
1251 break;
1252 }
1253 jstring authMethodString = env->NewStringUTF(authMethod);
1254
1255 env->CallVoidMethod(certificateChainVerifier, methodID, objectArray, authMethodString);
1256
1257 int result = (env->ExceptionCheck()) ? 0 : 1;
1258 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
1259 return result;
1260}
1261
1262/**
1263 * Call back to watch for handshake to be completed. This is necessary
1264 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
1265 * returns before the handshake is completed in this case.
1266 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001267static void info_callback(const SSL *ssl, int where, int ret __attribute__ ((unused))) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001268 JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
1269#ifdef WITH_JNI_TRACE
1270 info_callback_LOG(ssl, where, ret);
1271#endif
1272 if (!(where & SSL_CB_HANDSHAKE_DONE)) {
1273 JNI_TRACE("ssl=%p info_callback ignored", ssl);
1274 return;
1275 }
1276
1277 AppData* appData = (AppData*) SSL_get_app_data(ssl);
1278 JNIEnv* env = appData->env;
1279 if (env == NULL) {
1280 LOGE("AppData->env missing in info_callback");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001281 JNI_TRACE("ssl=%p info_callback env error", ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001282 return;
1283 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001284 jobject handshakeCompletedCallback = appData->handshakeCompletedCallback.get();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001285
1286 jclass cls = env->GetObjectClass(handshakeCompletedCallback);
1287 jmethodID methodID = env->GetMethodID(cls, "handshakeCompleted", "()V");
1288
1289 JNI_TRACE("ssl=%p info_callback calling handshakeCompleted", ssl);
1290 env->CallVoidMethod(handshakeCompletedCallback, methodID);
1291
1292 if (env->ExceptionCheck()) {
1293 JNI_TRACE("ssl=%p info_callback exception", ssl);
1294 }
1295
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001296 appData->handshakeCompleted();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001297 JNI_TRACE("ssl=%p info_callback completed", ssl);
1298}
1299
1300/*
1301 * public static native int SSL_CTX_new();
1302 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001303static int NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001304 SSL_CTX* sslCtx = SSL_CTX_new(SSLv23_method());
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001305 if (sslCtx == NULL) {
1306 jniThrowRuntimeException(env, "SSL_CTX_new");
1307 return NULL;
1308 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001309 // Note: We explicitly do not allow SSLv2 to be used.
1310 SSL_CTX_set_options(sslCtx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
1311
1312 int mode = SSL_CTX_get_mode(sslCtx);
1313 /*
1314 * Turn on "partial write" mode. This means that SSL_write() will
1315 * behave like Posix write() and possibly return after only
1316 * writing a partial buffer. Note: The alternative, perhaps
1317 * surprisingly, is not that SSL_write() always does full writes
1318 * but that it will force you to retry write calls having
1319 * preserved the full state of the original call. (This is icky
1320 * and undesirable.)
1321 */
1322 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
1323#if defined(SSL_MODE_SMALL_BUFFERS) /* not all SSL versions have this */
1324 mode |= SSL_MODE_SMALL_BUFFERS; /* lazily allocate record buffers; usually saves
1325 * 44k over the default */
1326#endif
1327#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) /* not all SSL versions have this */
1328 mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH; /* enable sending of client data as soon as
1329 * ClientCCS and ClientFinished are sent */
1330#endif
1331 SSL_CTX_set_mode(sslCtx, mode);
1332
1333 SSL_CTX_set_cert_verify_callback(sslCtx, cert_verify_callback, NULL);
1334 SSL_CTX_set_info_callback(sslCtx, info_callback);
1335
1336#ifdef WITH_JNI_TRACE
1337 SSL_CTX_set_msg_callback(sslCtx, ssl_msg_callback_LOG); /* enable for message debug */
1338#endif
1339 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx);
1340 return (jint) sslCtx;
1341}
1342
1343static jobjectArray makeCipherList(JNIEnv* env, STACK_OF(SSL_CIPHER)* cipher_list) {
1344 // Create a String[].
1345 jclass stringClass = env->FindClass("java/lang/String");
1346 if (stringClass == NULL) {
1347 return NULL;
1348 }
1349 int cipherCount = sk_SSL_CIPHER_num(cipher_list);
1350 jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
1351 if (array == NULL) {
1352 return NULL;
1353 }
1354
1355 // Fill in the cipher names.
1356 for (int i = 0; i < cipherCount; ++i) {
1357 const char* c = sk_SSL_CIPHER_value(cipher_list, i)->name;
1358 JNI_TRACE("makeCipherList[i=%d]=%s", i, c);
1359 env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
1360 }
1361 return array;
1362}
1363
1364/**
1365 * Loads the ciphers suites that are supported by an SSL_CTX
1366 * and returns them in a string array.
1367 */
1368static jobjectArray NativeCrypto_SSL_CTX_get_ciphers(JNIEnv* env,
1369 jclass, jint ssl_ctx_address)
1370{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001371 SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001372 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_get_ciphers", ssl_ctx);
1373 if (ssl_ctx == NULL) {
1374 jniThrowNullPointerException(env, "SSL_CTX is null");
1375 return NULL;
1376 }
1377 return makeCipherList(env, ssl_ctx->cipher_list);
1378}
1379
1380/**
1381 * public static native void SSL_CTX_free(int ssl_ctx)
1382 */
1383static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
1384 jclass, jint ssl_ctx_address)
1385{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001386 SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001387 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
1388 if (ssl_ctx == NULL) {
1389 jniThrowNullPointerException(env, "SSL_CTX is null");
1390 return;
1391 }
1392 env->DeleteGlobalRef((jobject) ssl_ctx->app_verify_arg);
1393 SSL_CTX_free(ssl_ctx);
1394}
1395
1396/**
1397 * Gets the chars of a String object as a '\0'-terminated UTF-8 string,
1398 * stored in a freshly-allocated BIO memory buffer.
1399 */
1400static BIO* stringToMemBuf(JNIEnv* env, jstring string) {
1401 jsize byteCount = env->GetStringUTFLength(string);
1402 LocalArray<1024> buf(byteCount + 1);
1403 env->GetStringUTFRegion(string, 0, env->GetStringLength(string), &buf[0]);
1404
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001405 BIO* bio = BIO_new(BIO_s_mem());
1406 if (bio == NULL) {
1407 jniThrowRuntimeException(env, "BIO_new failed");
1408 return NULL;
1409 }
1410 BIO_puts(bio, &buf[0]);
1411 return bio;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001412}
1413
1414/**
1415 * public static native int SSL_new(int ssl_ctx, String privatekey, String certificate, byte[] seed,
1416 * CertificateChainVerifier ccv) throws SSLException;
1417 */
1418static jint NativeCrypto_SSL_new(JNIEnv* env, jclass,
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001419 jint ssl_ctx_address, jstring privatekey, jstring certificates, jbyteArray seed)
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001420{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001421 SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001422 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new privatekey=%p certificates=%p seed=%p",
1423 ssl_ctx, privatekey, certificates, seed);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001424 if (ssl_ctx == NULL) {
1425 jniThrowNullPointerException(env, "SSL_CTX is null");
1426 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1427 return NULL;
1428 }
1429
1430 // 'seed == null' when no SecureRandom Object is set
1431 // in the SSLContext.
1432 if (seed != NULL) {
1433 jbyte* randseed = env->GetByteArrayElements(seed, NULL);
1434 RAND_seed((unsigned char*) randseed, 1024);
1435 env->ReleaseByteArrayElements(seed, randseed, 0);
1436 } else {
1437 RAND_load_file("/dev/urandom", 1024);
1438 }
1439
1440 SSL* ssl = SSL_new(ssl_ctx);
1441 if (ssl == NULL) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001442 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001443 "Unable to create SSL structure");
1444 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1445 return NULL;
1446 }
1447
1448 /* Java code in class OpenSSLSocketImpl does the verification. Meaning of
1449 * SSL_VERIFY_NONE flag in client mode: if not using an anonymous cipher
1450 * (by default disabled), the server will send a certificate which will
1451 * be checked. The result of the certificate verification process can be
1452 * checked after the TLS/SSL handshake using the SSL_get_verify_result(3)
1453 * function. The handshake will be continued regardless of the
1454 * verification result.
1455 */
1456 SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1457
1458 if (privatekey != NULL) {
1459 BIO* privatekeybio = stringToMemBuf(env, (jstring) privatekey);
1460 EVP_PKEY* privatekeyevp =
1461 PEM_read_bio_PrivateKey(privatekeybio, NULL, 0, NULL);
1462 BIO_free(privatekeybio);
1463
1464 if (privatekeyevp == NULL) {
1465 LOGE(ERR_error_string(ERR_get_error(), NULL));
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001466 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001467 "Error parsing the private key");
1468 SSL_free(ssl);
1469 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1470 return NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001471 }
1472
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001473 BIO* certificatesbio = stringToMemBuf(env, (jstring) certificates);
1474 X509* certificatesx509 =
1475 PEM_read_bio_X509(certificatesbio, NULL, 0, NULL);
1476 BIO_free(certificatesbio);
1477
1478 if (certificatesx509 == NULL) {
1479 LOGE(ERR_error_string(ERR_get_error(), NULL));
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001480 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001481 "Error parsing the certificates");
1482 EVP_PKEY_free(privatekeyevp);
1483 SSL_free(ssl);
1484 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1485 return NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001486 }
1487
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001488 int ret = SSL_use_certificate(ssl, certificatesx509);
1489 if (ret != 1) {
1490 LOGE(ERR_error_string(ERR_get_error(), NULL));
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001491 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001492 "Error setting the certificates");
1493 X509_free(certificatesx509);
1494 EVP_PKEY_free(privatekeyevp);
1495 SSL_free(ssl);
1496 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1497 return NULL;
1498 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08001499
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001500 ret = SSL_use_PrivateKey(ssl, privatekeyevp);
1501 if (ret != 1) {
1502 LOGE(ERR_error_string(ERR_get_error(), NULL));
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001503 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001504 "Error setting the private key");
1505 X509_free(certificatesx509);
1506 EVP_PKEY_free(privatekeyevp);
1507 SSL_free(ssl);
1508 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1509 return NULL;
1510 }
1511
1512 ret = SSL_check_private_key(ssl);
1513 if (ret != 1) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001514 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001515 "Error checking the private key");
1516 X509_free(certificatesx509);
1517 EVP_PKEY_free(privatekeyevp);
1518 SSL_free(ssl);
1519 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1520 return NULL;
1521 }
1522 }
1523 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p", ssl_ctx, ssl);
1524 return (jint)ssl;
1525}
1526
1527/**
1528 * public static native long SSL_get_mode(int ssl);
1529 */
1530static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass,
1531 jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001532 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001533 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
1534 if (ssl == NULL) {
1535 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0", ssl);
1536 return 0;
1537 }
1538 long mode = SSL_get_mode(ssl);
1539 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
1540 return mode;
1541}
1542
1543/**
1544 * public static native long SSL_set_mode(int ssl, long mode);
1545 */
1546static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
1547 jint ssl_address, jlong mode) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001548 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001549 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
1550 if (ssl == NULL) {
1551 return 0;
1552 }
1553 long result = SSL_set_mode(ssl, mode);
1554 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
1555 return result;
1556}
1557
1558/**
1559 * public static native long SSL_clear_mode(int ssl, long mode);
1560 */
1561static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
1562 jint ssl_address, jlong mode) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001563 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001564 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
1565 if (ssl == NULL) {
1566 return 0;
1567 }
1568 long result = SSL_clear_mode(ssl, mode);
1569 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
1570 return result;
1571}
1572
1573/**
1574 * public static native long SSL_get_options(int ssl);
1575 */
1576static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
1577 jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001578 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001579 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
1580 if (ssl == NULL) {
1581 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0", ssl);
1582 return 0;
1583 }
1584 long options = SSL_get_options(ssl);
1585 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
1586 return options;
1587}
1588
1589/**
1590 * public static native long SSL_set_options(int ssl, long options);
1591 */
1592static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
1593 jint ssl_address, jlong options) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001594 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001595 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
1596 if (ssl == NULL) {
1597 return 0;
1598 }
1599 long result = SSL_set_options(ssl, options);
1600 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
1601 return result;
1602}
1603
1604/**
1605 * public static native long SSL_clear_options(int ssl, long options);
1606 */
1607static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
1608 jint ssl_address, jlong options) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001609 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001610 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
1611 if (ssl == NULL) {
1612 return 0;
1613 }
1614 long result = SSL_clear_options(ssl, options);
1615 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
1616 return result;
1617}
1618
1619/**
1620 * Loads the ciphers suites that are enabled in the SSL
1621 * and returns them in a string array.
1622 */
1623static jobjectArray NativeCrypto_SSL_get_ciphers(JNIEnv* env,
1624 jclass, jint ssl_address)
1625{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001626 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001627 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
1628 if (ssl == NULL) {
1629 return NULL;
1630 }
1631 return makeCipherList(env, SSL_get_ciphers(ssl));
1632}
1633
1634/**
1635 * Sets the ciphers suites that are enabled in the SSL
1636 */
1637static void NativeCrypto_SSL_set_cipher_list(JNIEnv* env, jclass,
1638 jint ssl_address, jstring controlString)
1639{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001640 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001641 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_list controlString=%p", ssl, controlString);
1642 if (ssl == NULL) {
1643 return;
1644 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001645 ScopedUtfChars str(env, controlString);
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001646 JNI_TRACE("ssl=%p NativeCrypto_SSL_controlString str=%s", ssl, str.c_str());
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001647 int rc = SSL_set_cipher_list(ssl, str.c_str());
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001648 if (rc == 0) {
1649 freeSslErrorState();
1650 jniThrowException(env, "java/lang/IllegalArgumentException",
1651 "Illegal cipher suite strings.");
Brian Carlstrom0348e622010-02-10 22:56:47 -08001652 }
1653}
1654
Brian Carlstrom0348e622010-02-10 22:56:47 -08001655/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001656 * Sets certificate expectations, especially for server to request client auth
1657 */
1658static void NativeCrypto_SSL_set_verify(JNIEnv* env,
1659 jclass, jint ssl_address, jint mode)
1660{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001661 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001662 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify", ssl);
1663 if (ssl == NULL) {
1664 return;
1665 }
1666 SSL_set_verify(ssl, (int)mode, NULL);
1667}
1668
1669/**
1670 * Sets the ciphers suites that are enabled in the SSL
1671 */
1672static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
1673 jint ssl_address, jint ssl_session_address)
1674{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001675 SSL* ssl = to_SSL(env, ssl_address, true);
1676 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001677 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
1678 if (ssl == NULL) {
1679 return;
1680 }
1681
1682 int ret = SSL_set_session(ssl, ssl_session);
1683 if (ret != 1) {
1684 /*
1685 * Translate the error, and throw if it turns out to be a real
1686 * problem.
1687 */
1688 int sslErrorCode = SSL_get_error(ssl, ret);
1689 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001690 throwSSLExceptionWithSslErrors(env, sslErrorCode,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001691 "SSL session set");
1692 SSL_clear(ssl);
1693 }
1694 }
1695}
1696
1697/**
1698 * Sets the ciphers suites that are enabled in the SSL
1699 */
1700static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
1701 jint ssl_address, jboolean creation_enabled)
1702{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001703 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001704 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d", ssl, creation_enabled);
1705 if (ssl == NULL) {
1706 return;
1707 }
1708 SSL_set_session_creation_enabled(ssl, creation_enabled);
1709}
1710
1711/**
1712 * Module scope variables initialized during JNI registration.
1713 */
1714static jfieldID field_Socket_mImpl;
1715static jfieldID field_Socket_mFD;
1716
1717/**
1718 * Perform SSL handshake
1719 */
1720static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass,
1721 jint ssl_address, jobject socketObject, jobject ccv, jobject hcc, jint timeout, jboolean client_mode)
1722{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001723 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001724 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake socketObject=%p ccv=%p timeout=%d client_mode=%d",
1725 ssl, socketObject, ccv, timeout, client_mode);
1726 if (ssl == NULL) {
1727 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1728 return 0;
1729 }
1730
1731 if (socketObject == NULL) {
1732 jniThrowNullPointerException(env, "Socket is null");
1733 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1734 return 0;
1735 }
1736 if (ccv == NULL) {
1737 jniThrowNullPointerException(env, "CertificateChainVerifier is null");
1738 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1739 return 0;
1740 }
1741
1742 jobject socketImplObject = env->GetObjectField(socketObject, field_Socket_mImpl);
1743 if (socketImplObject == NULL) {
1744 throwSSLExceptionStr(env,
1745 "couldn't get the socket impl from the socket");
1746 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1747 return 0;
1748 }
1749
1750 jobject fdObject = env->GetObjectField(socketImplObject, field_Socket_mFD);
1751 if (fdObject == NULL) {
1752 throwSSLExceptionStr(env,
1753 "couldn't get the file descriptor from the socket impl");
1754 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1755 return 0;
1756 }
1757
1758 int fd = jniGetFDFromFileDescriptor(env, fdObject);
1759 if (fd == -1) {
1760 throwSSLExceptionStr(env, "Invalid file descriptor");
1761 SSL_clear(ssl);
1762 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1763 return 0;
1764 }
1765
1766 int ret = SSL_set_fd(ssl, fd);
1767 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd);
1768
1769 if (ret != 1) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001770 throwSSLExceptionWithSslErrors(env, 0,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001771 "Error setting the file descriptor");
1772 SSL_clear(ssl);
1773 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1774 return 0;
1775 }
1776
1777 /*
1778 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
1779 * forever and we can use select() to find out if the socket is ready.
1780 */
1781 int mode = fcntl(fd, F_GETFL);
1782 if (mode == -1 || fcntl(fd, F_SETFL, mode | O_NONBLOCK) == -1) {
1783 throwSSLExceptionStr(env, "Unable to make socket non blocking");
1784 SSL_clear(ssl);
1785 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1786 return 0;
1787 }
1788
1789 /*
1790 * Create our special application data.
1791 */
1792 AppData* appData = AppData::create(env, ccv, hcc);
1793 if (appData == NULL) {
1794 throwSSLExceptionStr(env, "Unable to create application data");
1795 SSL_clear(ssl);
1796 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1797 return 0;
1798 }
1799 SSL_set_app_data(ssl, (char*) appData);
1800
1801 if (client_mode) {
1802 SSL_set_connect_state(ssl);
1803 } else {
1804 SSL_set_accept_state(ssl);
1805 }
1806
1807 while (appData->aliveAndKicking) {
1808 errno = 0;
1809 appData->setEnv(env);
1810 ret = SSL_do_handshake(ssl);
1811 appData->clearEnv();
1812 // cert_verify_callback threw exception
1813 if (env->ExceptionCheck()) {
1814 SSL_clear(ssl);
1815 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1816 return 0;
1817 }
1818 if (ret == 1) {
1819 break;
1820 } else if (errno == EINTR) {
1821 continue;
1822 } else {
1823 // LOGD("SSL_connect: result %d, errno %d, timeout %d", ret, errno, timeout);
1824 int error = SSL_get_error(ssl, ret);
1825
1826 /*
1827 * If SSL_connect doesn't succeed due to the socket being
1828 * either unreadable or unwritable, we use sslSelect to
1829 * wait for it to become ready. If that doesn't happen
1830 * before the specified timeout or an error occurs, we
1831 * cancel the handshake. Otherwise we try the SSL_connect
1832 * again.
1833 */
1834 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
1835 appData->waitingThreads++;
1836 int selectResult = sslSelect(error, fd, appData, timeout);
1837
1838 if (selectResult == -1) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001839 throwSSLExceptionWithSslErrors(env, error, "handshake error");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001840 SSL_clear(ssl);
1841 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1842 return 0;
1843 } else if (selectResult == 0) {
1844 throwSocketTimeoutException(env, "SSL handshake timed out");
1845 SSL_clear(ssl);
1846 freeSslErrorState();
1847 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1848 return 0;
1849 }
1850 } else {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001851 // LOGE("Unknown error %d during handshake", error);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001852 break;
1853 }
1854 }
1855 }
1856
1857 if (ret == 0) {
1858 /*
1859 * The other side closed the socket before the handshake could be
1860 * completed, but everything is within the bounds of the TLS protocol.
1861 * We still might want to find out the real reason of the failure.
1862 */
1863 int sslErrorCode = SSL_get_error(ssl, ret);
1864 if (sslErrorCode == SSL_ERROR_NONE ||
1865 (sslErrorCode == SSL_ERROR_SYSCALL && errno == 0)) {
1866 throwSSLExceptionStr(env, "Connection closed by peer");
1867 } else {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001868 throwSSLExceptionWithSslErrors(env, sslErrorCode,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001869 "Trouble accepting connection");
1870 }
1871 SSL_clear(ssl);
1872 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1873 return 0;
1874 }
1875 if (ret < 0) {
1876 /*
1877 * Translate the error and throw exception. We are sure it is an error
1878 * at this point.
1879 */
1880 int sslErrorCode = SSL_get_error(ssl, ret);
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001881 throwSSLExceptionWithSslErrors(env, sslErrorCode,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001882 "Trouble accepting connection");
1883 SSL_clear(ssl);
1884 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
1885 return 0;
1886 }
1887 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
1888 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
1889 return (jint) ssl_session;
1890}
1891
1892/**
1893 * public static native byte[][] SSL_get_certificate(int ssl);
1894 */
1895static jobjectArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jint ssl_address)
1896{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001897 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001898 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
1899 if (ssl == NULL) {
1900 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
1901 return NULL;
1902 }
1903 X509* certificate = SSL_get_certificate(ssl);
1904 if (certificate == NULL) {
1905 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
1906 return NULL;
1907 }
1908 // TODO convert from single certificate to chain properly. One
1909 // option would be to have the chain remembered where
1910 // SSL_use_certificate is used. Another would be to save the
1911 // intermediate CAs with SSL_CTX SSL_CTX_add_extra_chain_cert.
1912 STACK_OF(X509)* chain = sk_X509_new_null();
1913 if (chain == NULL) {
1914 jniThrowRuntimeException(env, "Unable to allocate local certificate chain");
1915 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
1916 return NULL;
1917 }
1918 sk_X509_push(chain, certificate);
1919 jobjectArray objectArray = getCertificateBytes(env, chain);
1920 sk_X509_free(chain);
1921 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, objectArray);
1922 return objectArray;
1923}
1924
1925
1926/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08001927 * Helper function which does the actual reading. The Java layer guarantees that
1928 * at most one thread will enter this function at any given time.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001929 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001930 * @param ssl non-null; the SSL context
1931 * @param buf non-null; buffer to read into
1932 * @param len length of the buffer, in bytes
1933 * @param sslReturnCode original SSL return code
1934 * @param sslErrorCode filled in with the SSL error code in case of error
1935 * @return number of bytes read on success, -1 if the connection was
1936 * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown.
1937 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001938static int sslRead(JNIEnv* env, SSL* ssl, char* buf, jint len, int* sslReturnCode,
Brian Carlstrom0348e622010-02-10 22:56:47 -08001939 int* sslErrorCode, int timeout) {
1940
1941 // LOGD("Entering sslRead, caller requests to read %d bytes...", len);
Brian Carlstromecaf7592010-03-02 16:55:35 -08001942
Brian Carlstrom0348e622010-02-10 22:56:47 -08001943 if (len == 0) {
1944 // Don't bother doing anything in this case.
1945 return 0;
1946 }
1947
1948 int fd = SSL_get_fd(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001949 BIO* bio = SSL_get_rbio(ssl);
Brian Carlstromecaf7592010-03-02 16:55:35 -08001950
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001951 AppData* appData = (AppData*) SSL_get_app_data(ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001952
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001953 while (appData->aliveAndKicking) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08001954 errno = 0;
1955
1956 // Lock
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001957 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08001958 return -1;
1959 }
1960
1961 unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
Brian Carlstromecaf7592010-03-02 16:55:35 -08001962
Brian Carlstrom0348e622010-02-10 22:56:47 -08001963 // LOGD("Doing SSL_Read()");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001964 AppData* appData = (AppData*) SSL_get_app_data(ssl);
1965 appData->setEnv(env);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001966 int result = SSL_read(ssl, buf, len);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001967 appData->clearEnv();
Brian Carlstrom0348e622010-02-10 22:56:47 -08001968 int error = SSL_ERROR_NONE;
1969 if (result <= 0) {
1970 error = SSL_get_error(ssl, result);
1971 freeSslErrorState();
1972 }
1973 // LOGD("Returned from SSL_Read() with result %d, error code %d", result, error);
1974
1975 // If we have been successful in moving data around, check whether it
1976 // might make sense to wake up other blocked threads, so they can give
1977 // it a try, too.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001978 if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved && appData->waitingThreads > 0) {
1979 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001980 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08001981
Brian Carlstrom0348e622010-02-10 22:56:47 -08001982 // If we are blocked by the underlying socket, tell the world that
1983 // there will be one more waiting thread now.
1984 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001985 appData->waitingThreads++;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001986 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08001987
Brian Carlstrom0348e622010-02-10 22:56:47 -08001988 // Unlock
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001989 MUTEX_UNLOCK(appData->mutex);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001990
1991 switch (error) {
1992 // Sucessfully read at least one byte.
1993 case SSL_ERROR_NONE: {
1994 return result;
1995 }
1996
1997 // Read zero bytes. End of stream reached.
1998 case SSL_ERROR_ZERO_RETURN: {
1999 return -1;
2000 }
2001
Brian Carlstromecaf7592010-03-02 16:55:35 -08002002 // Need to wait for availability of underlying layer, then retry.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002003 case SSL_ERROR_WANT_READ:
2004 case SSL_ERROR_WANT_WRITE: {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002005 int selectResult = sslSelect(error, fd, appData, timeout);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002006 if (selectResult == -1) {
2007 *sslReturnCode = -1;
2008 *sslErrorCode = error;
2009 return THROW_EXCEPTION;
2010 } else if (selectResult == 0) {
2011 return THROW_SOCKETTIMEOUTEXCEPTION;
2012 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002013
Brian Carlstrom0348e622010-02-10 22:56:47 -08002014 break;
2015 }
2016
2017 // A problem occured during a system call, but this is not
2018 // necessarily an error.
2019 case SSL_ERROR_SYSCALL: {
2020 // Connection closed without proper shutdown. Tell caller we
2021 // have reached end-of-stream.
2022 if (result == 0) {
2023 return -1;
2024 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002025
Brian Carlstrom0348e622010-02-10 22:56:47 -08002026 // System call has been interrupted. Simply retry.
2027 if (errno == EINTR) {
2028 break;
2029 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002030
Brian Carlstrom0348e622010-02-10 22:56:47 -08002031 // Note that for all other system call errors we fall through
Brian Carlstromecaf7592010-03-02 16:55:35 -08002032 // to the default case, which results in an Exception.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002033 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002034
Brian Carlstrom0348e622010-02-10 22:56:47 -08002035 // Everything else is basically an error.
2036 default: {
2037 *sslReturnCode = result;
2038 *sslErrorCode = error;
2039 return THROW_EXCEPTION;
2040 }
2041 }
2042 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002043
Brian Carlstrom0348e622010-02-10 22:56:47 -08002044 return -1;
2045}
2046
2047/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002048 * OpenSSL read function (1): only one chunk is read (returned as jint).
2049 */
2050static jint NativeCrypto_SSL_read_byte(JNIEnv* env, jclass, jint ssl_address, jint timeout)
2051{
2052 SSL* ssl = to_SSL(env, ssl_address, true);
2053 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte timeout=%d", ssl, timeout);
2054 if (ssl == NULL) {
2055 return 0;
2056 }
2057
2058 unsigned char byteRead;
2059 int returnCode = 0;
2060 int errorCode = 0;
2061
2062 int ret = sslRead(env, ssl, (char *) &byteRead, 1, &returnCode, &errorCode, timeout);
2063
2064 int result;
2065 switch (ret) {
2066 case THROW_EXCEPTION:
2067 // See sslRead() regarding improper failure to handle normal cases.
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002068 throwSSLExceptionWithSslErrors(env, errorCode, "Read error");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002069 result = -1;
2070 break;
2071 case THROW_SOCKETTIMEOUTEXCEPTION:
2072 throwSocketTimeoutException(env, "Read timed out");
2073 result = -1;
2074 break;
2075 case -1:
2076 // Propagate EOF upwards.
2077 result = -1;
2078 break;
2079 default:
2080 // Return the actual char read, make sure it stays 8 bits wide.
2081 result = ((jint) byteRead) & 0xFF;
2082 break;
2083 }
2084 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => %d", ssl, result);
2085 return result;
2086}
2087
2088/**
2089 * OpenSSL read function (2): read into buffer at offset n chunks.
2090 * Returns 1 (success) or value <= 0 (failure).
2091 */
2092static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint ssl_address, jbyteArray dest, jint offset, jint len, jint timeout)
2093{
2094 SSL* ssl = to_SSL(env, ssl_address, true);
2095 JNI_TRACE("ssl=%p NativeCrypto_SSL_read dest=%p offset=%d len=%d timeout=%d", ssl, dest, offset, len, timeout);
2096 if (ssl == NULL) {
2097 return 0;
2098 }
2099
2100 jbyte* bytes = env->GetByteArrayElements(dest, NULL);
2101 int returnCode = 0;
2102 int errorCode = 0;
2103
2104 int ret = sslRead(env, ssl, (char*) (bytes + offset), len, &returnCode, &errorCode, timeout);
2105
2106 env->ReleaseByteArrayElements(dest, bytes, 0);
2107
2108 int result;
2109 if (ret == THROW_EXCEPTION) {
2110 // See sslRead() regarding improper failure to handle normal cases.
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002111 throwSSLExceptionWithSslErrors(env, errorCode,
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002112 "Read error");
2113 result = -1;
2114 } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
2115 throwSocketTimeoutException(env, "Read timed out");
2116 result = -1;
2117 } else {
2118 result = ret;
2119 }
2120
2121 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
2122 return result;
2123}
2124
2125/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08002126 * Helper function which does the actual writing. The Java layer guarantees that
2127 * at most one thread will enter this function at any given time.
Brian Carlstromecaf7592010-03-02 16:55:35 -08002128 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08002129 * @param ssl non-null; the SSL context
2130 * @param buf non-null; buffer to write
2131 * @param len length of the buffer, in bytes
2132 * @param sslReturnCode original SSL return code
2133 * @param sslErrorCode filled in with the SSL error code in case of error
2134 * @return number of bytes read on success, -1 if the connection was
2135 * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown.
2136 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002137static int sslWrite(JNIEnv* env, SSL* ssl, const char* buf, jint len, int* sslReturnCode,
Brian Carlstrom0348e622010-02-10 22:56:47 -08002138 int* sslErrorCode) {
Brian Carlstromecaf7592010-03-02 16:55:35 -08002139
Brian Carlstrom0348e622010-02-10 22:56:47 -08002140 // LOGD("Entering sslWrite(), caller requests to write %d bytes...", len);
2141
2142 if (len == 0) {
2143 // Don't bother doing anything in this case.
2144 return 0;
2145 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002146
Brian Carlstrom0348e622010-02-10 22:56:47 -08002147 int fd = SSL_get_fd(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002148 BIO* bio = SSL_get_wbio(ssl);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002149
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002150 AppData* appData = (AppData*) SSL_get_app_data(ssl);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002151
Brian Carlstrom0348e622010-02-10 22:56:47 -08002152 int count = len;
Brian Carlstromecaf7592010-03-02 16:55:35 -08002153
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002154 while (appData->aliveAndKicking && len > 0) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002155 errno = 0;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002156 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002157 return -1;
2158 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002159
Brian Carlstrom0348e622010-02-10 22:56:47 -08002160 unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002161
Brian Carlstrom0348e622010-02-10 22:56:47 -08002162 // LOGD("Doing SSL_write() with %d bytes to go", len);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002163 appData->setEnv(env);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002164 int result = SSL_write(ssl, buf, len);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002165 appData->clearEnv();
Brian Carlstrom0348e622010-02-10 22:56:47 -08002166 int error = SSL_ERROR_NONE;
2167 if (result <= 0) {
2168 error = SSL_get_error(ssl, result);
2169 freeSslErrorState();
2170 }
2171 // LOGD("Returned from SSL_write() with result %d, error code %d", result, error);
2172
2173 // If we have been successful in moving data around, check whether it
2174 // might make sense to wake up other blocked threads, so they can give
2175 // it a try, too.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002176 if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved && appData->waitingThreads > 0) {
2177 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002178 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002179
Brian Carlstrom0348e622010-02-10 22:56:47 -08002180 // If we are blocked by the underlying socket, tell the world that
2181 // there will be one more waiting thread now.
2182 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002183 appData->waitingThreads++;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002184 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002185
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002186 MUTEX_UNLOCK(appData->mutex);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002187
Brian Carlstrom0348e622010-02-10 22:56:47 -08002188 switch (error) {
2189 // Sucessfully write at least one byte.
2190 case SSL_ERROR_NONE: {
2191 buf += result;
2192 len -= result;
2193 break;
2194 }
2195
2196 // Wrote zero bytes. End of stream reached.
2197 case SSL_ERROR_ZERO_RETURN: {
2198 return -1;
2199 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002200
Brian Carlstrom0348e622010-02-10 22:56:47 -08002201 // Need to wait for availability of underlying layer, then retry.
2202 // The concept of a write timeout doesn't really make sense, and
2203 // it's also not standard Java behavior, so we wait forever here.
2204 case SSL_ERROR_WANT_READ:
2205 case SSL_ERROR_WANT_WRITE: {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002206 int selectResult = sslSelect(error, fd, appData, 0);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002207 if (selectResult == -1) {
2208 *sslReturnCode = -1;
2209 *sslErrorCode = error;
2210 return THROW_EXCEPTION;
2211 } else if (selectResult == 0) {
2212 return THROW_SOCKETTIMEOUTEXCEPTION;
2213 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002214
Brian Carlstrom0348e622010-02-10 22:56:47 -08002215 break;
2216 }
2217
2218 // An problem occured during a system call, but this is not
2219 // necessarily an error.
2220 case SSL_ERROR_SYSCALL: {
2221 // Connection closed without proper shutdown. Tell caller we
2222 // have reached end-of-stream.
2223 if (result == 0) {
2224 return -1;
2225 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002226
Brian Carlstrom0348e622010-02-10 22:56:47 -08002227 // System call has been interrupted. Simply retry.
2228 if (errno == EINTR) {
2229 break;
2230 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002231
Brian Carlstrom0348e622010-02-10 22:56:47 -08002232 // Note that for all other system call errors we fall through
Brian Carlstromecaf7592010-03-02 16:55:35 -08002233 // to the default case, which results in an Exception.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002234 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002235
Brian Carlstrom0348e622010-02-10 22:56:47 -08002236 // Everything else is basically an error.
2237 default: {
2238 *sslReturnCode = result;
2239 *sslErrorCode = error;
2240 return THROW_EXCEPTION;
2241 }
2242 }
2243 }
2244 // LOGD("Successfully wrote %d bytes", count);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002245
Brian Carlstrom0348e622010-02-10 22:56:47 -08002246 return count;
2247}
2248
2249/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08002250 * OpenSSL write function (1): only one chunk is written.
2251 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002252static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address, jint b)
Brian Carlstrom0348e622010-02-10 22:56:47 -08002253{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002254 SSL* ssl = to_SSL(env, ssl_address, true);
2255 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte b=%d", ssl, b);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002256 if (ssl == NULL) {
2257 return;
2258 }
2259
2260 int returnCode = 0;
2261 int errorCode = 0;
2262 char buf[1] = { (char) b };
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002263 int ret = sslWrite(env, ssl, buf, 1, &returnCode, &errorCode);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002264
2265 if (ret == THROW_EXCEPTION) {
2266 // See sslWrite() regarding improper failure to handle normal cases.
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002267 throwSSLExceptionWithSslErrors(env, errorCode,
Brian Carlstrom0348e622010-02-10 22:56:47 -08002268 "Write error");
2269 } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
2270 throwSocketTimeoutException(env, "Write timed out");
2271 }
2272}
2273
2274/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002275 * OpenSSL write function (2): write into buffer at offset n chunks.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002276 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002277static void NativeCrypto_SSL_write(JNIEnv* env, jclass,
Brian Carlstromecaf7592010-03-02 16:55:35 -08002278 jint ssl_address, jbyteArray dest, jint offset, jint len)
Brian Carlstrom0348e622010-02-10 22:56:47 -08002279{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002280 SSL* ssl = to_SSL(env, ssl_address, true);
2281 JNI_TRACE("ssl=%p NativeCrypto_SSL_write dest=%p offset=%d len=%d", ssl, dest, offset, len);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002282 if (ssl == NULL) {
2283 return;
2284 }
2285
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002286 ScopedByteArray bytes(env, dest);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002287 int returnCode = 0;
2288 int errorCode = 0;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002289 int ret = sslWrite(env, ssl, (const char *) (bytes.bytes() + offset), len, &returnCode, &errorCode);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002290
2291 if (ret == THROW_EXCEPTION) {
2292 // See sslWrite() regarding improper failure to handle normal cases.
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002293 throwSSLExceptionWithSslErrors(env, errorCode,
Brian Carlstrom0348e622010-02-10 22:56:47 -08002294 "Write error");
2295 } else if(ret == THROW_SOCKETTIMEOUTEXCEPTION) {
2296 throwSocketTimeoutException(env, "Write timed out");
2297 }
2298}
2299
2300/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002301 * Interrupt any pending IO before closing the socket.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002302 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002303static void NativeCrypto_SSL_interrupt(
Brian Carlstromecaf7592010-03-02 16:55:35 -08002304 JNIEnv* env, jclass, jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002305 SSL* ssl = to_SSL(env, ssl_address, false);
2306 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002307 if (ssl == NULL) {
2308 return;
2309 }
2310
2311 /*
2312 * Mark the connection as quasi-dead, then send something to the emergency
2313 * file descriptor, so any blocking select() calls are woken up.
2314 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002315 AppData* appData = (AppData*) SSL_get_app_data(ssl);
2316 if (appData != NULL) {
2317 appData->aliveAndKicking = 0;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002318
2319 // At most two threads can be waiting.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002320 sslNotify(appData);
2321 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002322 }
2323}
2324
2325/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002326 * OpenSSL close SSL socket function.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002327 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002328static void NativeCrypto_SSL_shutdown(
Brian Carlstromecaf7592010-03-02 16:55:35 -08002329 JNIEnv* env, jclass, jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002330 SSL* ssl = to_SSL(env, ssl_address, false);
2331 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown", ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002332 if (ssl == NULL) {
2333 return;
2334 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002335 /*
2336 * Try to make socket blocking again. OpenSSL literature recommends this.
2337 */
2338 int fd = SSL_get_fd(ssl);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002339 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002340 if (fd != -1) {
2341 int mode = fcntl(fd, F_GETFL);
2342 if (mode == -1 || fcntl(fd, F_SETFL, mode & ~O_NONBLOCK) == -1) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002343// throwSSLExceptionStr(env, "Unable to make socket blocking again");
Brian Carlstrom0348e622010-02-10 22:56:47 -08002344// LOGW("Unable to make socket blocking again");
2345 }
2346 }
2347
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002348 AppData* appData = (AppData*) SSL_get_app_data(ssl);
2349 appData->setEnv(env);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002350 int ret = SSL_shutdown(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002351 appData->clearEnv();
Brian Carlstrom0348e622010-02-10 22:56:47 -08002352 switch (ret) {
2353 case 0:
2354 /*
2355 * Shutdown was not successful (yet), but there also
2356 * is no error. Since we can't know whether the remote
2357 * server is actually still there, and we don't want to
2358 * get stuck forever in a second SSL_shutdown() call, we
2359 * simply return. This is not security a problem as long
2360 * as we close the underlying socket, which we actually
2361 * do, because that's where we are just coming from.
2362 */
2363 break;
2364 case 1:
2365 /*
2366 * Shutdown was sucessful. We can safely return. Hooray!
2367 */
2368 break;
2369 default:
2370 /*
2371 * Everything else is a real error condition. We should
2372 * let the Java layer know about this by throwing an
2373 * exception.
Brian Carlstromecaf7592010-03-02 16:55:35 -08002374 */
Brian Carlstrom83db3782010-04-09 17:49:11 -07002375 int sslErrorCode = SSL_get_error(ssl, ret);
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002376 throwSSLExceptionWithSslErrors(env, sslErrorCode, "SSL shutdown failed");
Brian Carlstrom0348e622010-02-10 22:56:47 -08002377 break;
2378 }
2379
Brian Carlstromecaf7592010-03-02 16:55:35 -08002380 SSL_clear(ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002381 freeSslErrorState();
Brian Carlstrom0348e622010-02-10 22:56:47 -08002382}
2383
2384/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002385 * public static native void SSL_free(int ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002386 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002387static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jint ssl_address)
2388{
2389 SSL* ssl = to_SSL(env, ssl_address, true);
2390 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
2391 if (ssl == NULL) {
2392 return;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002393 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002394 AppData* appData = (AppData*) SSL_get_app_data(ssl);
2395 SSL_set_app_data(ssl, NULL);
2396 delete appData;
2397 SSL_free(ssl);
2398}
Brian Carlstrom0348e622010-02-10 22:56:47 -08002399
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002400/**
2401 * Gets and returns in a byte array the ID of the actual SSL session.
2402 */
2403static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass, jint ssl_session_address) {
2404 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2405 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
2406 jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
2407 if (result != NULL) {
2408 jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
2409 env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002410 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002411 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
2412 ssl_session, result, ssl_session->session_id_length);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002413 return result;
2414}
2415
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002416/**
2417 * Our implementation of what might be considered
2418 * SSL_SESSION_get_peer_cert_chain
2419 *
2420 */
2421// TODO move to jsse.patch
2422static STACK_OF(X509)* SSL_SESSION_get_peer_cert_chain(SSL_CTX* ssl_ctx, SSL_SESSION* ssl_session) {
2423 SSL* ssl = SSL_new(ssl_ctx);
2424 if (ssl == NULL) {
2425 return NULL;
2426 }
2427 SSL_set_session(ssl, ssl_session);
2428 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
2429 SSL_free(ssl);
2430 return chain;
2431}
2432
2433// Fills a byte[][] with the peer certificates in the chain.
2434static jobjectArray NativeCrypto_SSL_SESSION_get_peer_cert_chain(JNIEnv* env,
2435 jclass, jint ssl_ctx_address, jint ssl_session_address)
Brian Carlstrom0348e622010-02-10 22:56:47 -08002436{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002437 SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
2438 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2439 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_peer_cert_chain ssl_ctx=%p", ssl_session, ssl_ctx);
2440 if (ssl_ctx == NULL) {
2441 jniThrowNullPointerException(env, "SSL_CTX is null");
2442 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_peer_cert_chain => NULL", ssl_session);
2443 return NULL;
2444 }
2445 STACK_OF(X509)* chain = SSL_SESSION_get_peer_cert_chain(ssl_ctx, ssl_session);
2446 jobjectArray objectArray = getCertificateBytes(env, chain);
2447 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_peer_cert_chain => %p", ssl_session, objectArray);
2448 return objectArray;
2449}
2450
2451/**
2452 * Gets and returns in a long integer the creation's time of the
2453 * actual SSL session.
2454 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002455static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv*, jclass, jint ssl_session_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002456 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2457 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
2458 jlong result = SSL_SESSION_get_time(ssl_session); // must be jlong, not long or *1000 will overflow
2459 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
2460 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
2461 return result;
2462}
2463
2464/**
2465 * Our implementation of what might be considered
2466 * SSL_SESSION_get_version, based on SSL_get_version.
2467 * See get_ssl_version above.
2468 */
2469// TODO move to jsse.patch
2470static const char* SSL_SESSION_get_version(SSL_SESSION* ssl_session) {
2471 return get_ssl_version(ssl_session->ssl_version);
2472}
2473
2474/**
2475 * Gets and returns in a string the version of the SSL protocol. If it
2476 * returns the string "unknown" it means that no connection is established.
2477 */
2478static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jint ssl_session_address) {
2479 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2480 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
2481 const char* protocol = SSL_SESSION_get_version(ssl_session);
2482 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
2483 return env->NewStringUTF(protocol);
2484}
2485
2486/**
2487 * Gets and returns in a string the set of ciphers the actual SSL session uses.
2488 */
2489static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jint ssl_session_address) {
2490 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2491 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
2492 const SSL_CIPHER* cipher = ssl_session->cipher;
2493 const char* name = SSL_CIPHER_get_name(cipher);
2494 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
2495 return env->NewStringUTF(name);
2496}
2497
2498/**
2499 * Frees the SSL session.
2500 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07002501static void NativeCrypto_SSL_SESSION_free(JNIEnv*, jclass, jint ssl_session_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002502 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2503 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
2504 SSL_SESSION_free(ssl_session);
2505}
2506
2507
2508/**
2509 * Serializes the native state of the session (ID, cipher, and keys but
2510 * not certificates). Returns a byte[] containing the DER-encoded state.
2511 * See apache mod_ssl.
2512 */
2513static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jint ssl_session_address) {
2514 SSL_SESSION* ssl_session = to_SSL_SESSION(ssl_session_address);
2515 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
2516 if (ssl_session == NULL) {
2517 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => NULL", ssl_session);
2518 return NULL;
2519 }
2520
2521 // Compute the size of the DER data
2522 int size = i2d_SSL_SESSION(ssl_session, NULL);
2523 if (size == 0) {
2524 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => NULL", ssl_session);
2525 return NULL;
2526 }
2527
2528 jbyteArray bytes = env->NewByteArray(size);
2529 if (bytes != NULL) {
2530 jbyte* tmp = env->GetByteArrayElements(bytes, NULL);
2531 unsigned char* ucp = reinterpret_cast<unsigned char*>(tmp);
2532 i2d_SSL_SESSION(ssl_session, &ucp);
2533 env->ReleaseByteArrayElements(bytes, tmp, 0);
2534 }
2535
2536 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => size=%d", ssl_session, size);
2537 return bytes;
2538}
2539
2540/**
2541 * Deserialize the session.
2542 */
2543static jint NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray bytes, jint size) {
2544 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p size=%d", bytes, size);
2545 if (bytes == NULL) {
2546 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => 0");
2547 return 0;
2548 }
2549
2550 ScopedByteArray tmp(env, bytes);
2551 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(tmp.bytes());
2552 SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, size);
2553
2554 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
2555 return static_cast<jint>(reinterpret_cast<uintptr_t>(ssl_session));
2556}
2557
2558/*
2559 * Defines the mapping from Java methods and their signatures
2560 * to native functions. Order is (1) Java name, (2) signature,
2561 * (3) pointer to C function.
2562 */
2563static JNINativeMethod sNativeCryptoMethods[] = {
2564 { "clinit", "()V", (void*)NativeCrypto_clinit},
2565 { "EVP_PKEY_new_DSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_DSA },
2566 { "EVP_PKEY_new_RSA", "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_RSA },
2567 { "EVP_PKEY_free", "(I)V", (void*)NativeCrypto_EVP_PKEY_free },
2568 { "EVP_new", "()I", (void*)NativeCrypto_EVP_new },
2569 { "EVP_free", "(I)V", (void*)NativeCrypto_EVP_free },
2570 { "EVP_DigestFinal", "(I[BI)I", (void*)NativeCrypto_EVP_DigestFinal },
2571 { "EVP_DigestInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_DigestInit },
2572 { "EVP_DigestBlockSize", "(I)I", (void*)NativeCrypto_EVP_DigestBlockSize },
2573 { "EVP_DigestSize", "(I)I", (void*)NativeCrypto_EVP_DigestSize },
2574 { "EVP_DigestUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_DigestUpdate },
2575 { "EVP_VerifyInit", "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_VerifyInit },
2576 { "EVP_VerifyUpdate", "(I[BII)V", (void*)NativeCrypto_EVP_VerifyUpdate },
2577 { "EVP_VerifyFinal", "(I[BIII)I", (void*)NativeCrypto_EVP_VerifyFinal },
2578 { "verifySignature", "([B[BLjava/lang/String;[B[B)I", (void*)NativeCrypto_verifysignature},
2579 { "SSL_CTX_new", "()I", (void*)NativeCrypto_SSL_CTX_new },
2580 { "SSL_CTX_get_ciphers", "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_CTX_get_ciphers},
2581 { "SSL_CTX_free", "(I)V", (void*)NativeCrypto_SSL_CTX_free },
2582 { "SSL_new", "(ILjava/lang/String;Ljava/lang/String;[B)I", (void*)NativeCrypto_SSL_new},
2583 { "SSL_get_mode", "(I)J", (void*)NativeCrypto_SSL_get_mode },
2584 { "SSL_set_mode", "(IJ)J", (void*)NativeCrypto_SSL_set_mode },
2585 { "SSL_clear_mode", "(IJ)J", (void*)NativeCrypto_SSL_clear_mode },
2586 { "SSL_get_options", "(I)J", (void*)NativeCrypto_SSL_get_options },
2587 { "SSL_set_options", "(IJ)J", (void*)NativeCrypto_SSL_set_options },
2588 { "SSL_clear_options", "(IJ)J", (void*)NativeCrypto_SSL_clear_options },
2589 { "SSL_get_ciphers", "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_get_ciphers },
2590 { "SSL_set_cipher_list", "(ILjava/lang/String;)V", (void*)NativeCrypto_SSL_set_cipher_list },
2591 { "SSL_set_verify", "(II)V", (void*)NativeCrypto_SSL_set_verify},
2592 { "SSL_set_session", "(II)V", (void*)NativeCrypto_SSL_set_session },
2593 { "SSL_set_session_creation_enabled", "(IZ)V", (void*)NativeCrypto_SSL_set_session_creation_enabled },
2594 { "SSL_do_handshake", "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$CertificateChainVerifier;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$HandshakeCompletedCallback;IZ)I",(void*)NativeCrypto_SSL_do_handshake},
2595 { "SSL_get_certificate", "(I)[[B", (void*)NativeCrypto_SSL_get_certificate},
2596 { "SSL_read_byte", "(II)I", (void*)NativeCrypto_SSL_read_byte},
2597 { "SSL_read", "(I[BIII)I", (void*)NativeCrypto_SSL_read},
2598 { "SSL_write_byte", "(II)V", (void*)NativeCrypto_SSL_write_byte},
2599 { "SSL_write", "(I[BII)V", (void*)NativeCrypto_SSL_write},
2600 { "SSL_interrupt", "(I)V", (void*)NativeCrypto_SSL_interrupt},
2601 { "SSL_shutdown", "(I)V", (void*)NativeCrypto_SSL_shutdown},
2602 { "SSL_free", "(I)V", (void*)NativeCrypto_SSL_free},
2603 { "SSL_SESSION_session_id", "(I)[B", (void*)NativeCrypto_SSL_SESSION_session_id },
2604 { "SSL_SESSION_get_peer_cert_chain", "(II)[[B", (void*)NativeCrypto_SSL_SESSION_get_peer_cert_chain },
2605 { "SSL_SESSION_get_time", "(I)J", (void*)NativeCrypto_SSL_SESSION_get_time },
2606 { "SSL_SESSION_get_version", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_get_version },
2607 { "SSL_SESSION_cipher", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_cipher },
2608 { "SSL_SESSION_free", "(I)V", (void*)NativeCrypto_SSL_SESSION_free },
2609 { "i2d_SSL_SESSION", "(I)[B", (void*)NativeCrypto_i2d_SSL_SESSION },
2610 { "d2i_SSL_SESSION", "([BI)I", (void*)NativeCrypto_d2i_SSL_SESSION },
Brian Carlstrom0348e622010-02-10 22:56:47 -08002611};
2612
Elliott Hughesc08f9fb2010-04-16 17:44:12 -07002613int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002614 JNI_TRACE("register_org_apache_harmony_xnet_provider_jsse_NativeCrypto");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002615 // Register org.apache.harmony.xnet.provider.jsse.NativeCrypto methods
2616 int result = jniRegisterNativeMethods(env,
2617 "org/apache/harmony/xnet/provider/jsse/NativeCrypto",
2618 sNativeCryptoMethods,
2619 NELEM(sNativeCryptoMethods));
2620 if (result == -1) {
2621 return -1;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002622 }
2623
Brian Carlstrom0348e622010-02-10 22:56:47 -08002624 // java.net.Socket
2625 jclass socket = env->FindClass("java/net/Socket");
2626 if (socket == NULL) {
2627 LOGE("Can't find class java.net.Socket");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08002628 return -1;
2629 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002630 field_Socket_mImpl = env->GetFieldID(socket, "impl", "Ljava/net/SocketImpl;");
2631 if (field_Socket_mImpl == NULL) {
2632 LOGE("Can't find field impl in class java.net.Socket");
2633 return -1;
2634 }
2635
2636 // java.net.SocketImpl
2637 jclass socketImplClass = env->FindClass("java/net/SocketImpl");
2638 if (socketImplClass == NULL) {
2639 LOGE("Can't find class java.net.SocketImpl");
2640 return -1;
2641 }
2642 field_Socket_mFD = env->GetFieldID(socketImplClass, "fd", "Ljava/io/FileDescriptor;");
2643 if (field_Socket_mFD == NULL) {
2644 LOGE("Can't find field fd in java.net.SocketImpl");
2645 return -1;
2646 }
2647
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08002648 return 0;
2649}