blob: 99fb1b94ffec85754a06ca54eac142a4c3f54075 [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 Carlstrom3900e262010-11-10 10:56:21 -080023#include <algorithm>
Brian Carlstrom0348e622010-02-10 22:56:47 -080024#include <fcntl.h>
25#include <sys/socket.h>
26#include <unistd.h>
27
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080028#include <jni.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080029
Brian Carlstrom0348e622010-02-10 22:56:47 -080030#include <openssl/dsa.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080031#include <openssl/err.h>
32#include <openssl/evp.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080033#include <openssl/rand.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080034#include <openssl/rsa.h>
Brian Carlstrom0348e622010-02-10 22:56:47 -080035#include <openssl/ssl.h>
36
Brian Carlstrom84f16122010-09-21 02:09:29 -070037#include "AsynchronousSocketCloseMonitor.h"
Elliott Hughesa9f5c162010-06-16 16:32:18 -070038#include "JNIHelp.h"
39#include "JniConstants.h"
Elliott Hughes221d0cc2010-07-15 11:09:45 -070040#include "JniException.h"
Elliott Hughesa9f5c162010-06-16 16:32:18 -070041#include "LocalArray.h"
Brian Carlstrom84f16122010-09-21 02:09:29 -070042#include "NetFd.h"
Elliott Hughes3b0a5b92010-07-22 15:06:54 -070043#include "NetworkUtilities.h"
Brian Carlstrom3534c7c2010-05-14 21:49:34 -070044#include "ScopedLocalRef.h"
Elliott Hughes99c59bf2010-05-17 16:22:04 -070045#include "ScopedPrimitiveArray.h"
Brian Carlstrom3e24c532010-05-06 00:23:21 -070046#include "ScopedUtfChars.h"
47#include "UniquePtr.h"
48
Brian Carlstrombcfb3252010-05-02 11:27:52 -070049#undef WITH_JNI_TRACE
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -080050#undef WITH_JNI_TRACE_DATA
51
Brian Carlstrombcfb3252010-05-02 11:27:52 -070052#ifdef WITH_JNI_TRACE
53#define JNI_TRACE(...) \
54 ((void)LOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__)); \
Brian Carlstrom3e24c532010-05-06 00:23:21 -070055/*
56 ((void)printf("I/" LOG_TAG "-jni:")); \
57 ((void)printf(__VA_ARGS__)); \
Brian Carlstrombcfb3252010-05-02 11:27:52 -070058 ((void)printf("\n"))
Brian Carlstrom3e24c532010-05-06 00:23:21 -070059*/
Brian Carlstrombcfb3252010-05-02 11:27:52 -070060#else
61#define JNI_TRACE(...) ((void)0)
62#endif
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -080063// don't overwhelm logcat
Brian Carlstrom3900e262010-11-10 10:56:21 -080064#define WITH_JNI_TRACE_DATA_CHUNK_SIZE 512
Brian Carlstromb5b39e42010-05-19 15:29:11 -070065
66struct BIO_Delete {
67 void operator()(BIO* p) const {
68 BIO_free(p);
69 }
70};
71typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
72
73struct BIGNUM_Delete {
74 void operator()(BIGNUM* p) const {
75 BN_free(p);
76 }
77};
78typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
79
Brian Carlstromaacf6f92010-05-20 01:02:17 -070080struct DH_Delete {
81 void operator()(DH* p) const {
82 DH_free(p);
83 }
84};
85typedef UniquePtr<DH, DH_Delete> Unique_DH;
86
Brian Carlstromb5b39e42010-05-19 15:29:11 -070087struct DSA_Delete {
88 void operator()(DSA* p) const {
89 DSA_free(p);
90 }
91};
92typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
93
94struct EVP_PKEY_Delete {
95 void operator()(EVP_PKEY* p) const {
96 EVP_PKEY_free(p);
97 }
98};
99typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
100
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700101struct PKCS8_PRIV_KEY_INFO_Delete {
102 void operator()(PKCS8_PRIV_KEY_INFO* p) const {
103 PKCS8_PRIV_KEY_INFO_free(p);
104 }
105};
106typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
107
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700108struct RSA_Delete {
109 void operator()(RSA* p) const {
110 RSA_free(p);
111 }
112};
113typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
114
115struct SSL_Delete {
116 void operator()(SSL* p) const {
117 SSL_free(p);
118 }
119};
120typedef UniquePtr<SSL, SSL_Delete> Unique_SSL;
121
122struct SSL_CTX_Delete {
123 void operator()(SSL_CTX* p) const {
124 SSL_CTX_free(p);
125 }
126};
127typedef UniquePtr<SSL_CTX, SSL_CTX_Delete> Unique_SSL_CTX;
128
129struct X509_Delete {
130 void operator()(X509* p) const {
131 X509_free(p);
132 }
133};
134typedef UniquePtr<X509, X509_Delete> Unique_X509;
135
Brian Carlstromef628d12010-07-19 13:52:03 -0700136struct X509_NAME_Delete {
137 void operator()(X509_NAME* p) const {
138 X509_NAME_free(p);
139 }
140};
141typedef UniquePtr<X509_NAME, X509_NAME_Delete> Unique_X509_NAME;
142
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700143struct sk_SSL_CIPHER_Delete {
144 void operator()(STACK_OF(SSL_CIPHER)* p) const {
145 sk_SSL_CIPHER_free(p);
146 }
147};
148typedef UniquePtr<STACK_OF(SSL_CIPHER), sk_SSL_CIPHER_Delete> Unique_sk_SSL_CIPHER;
149
150struct sk_X509_Delete {
151 void operator()(STACK_OF(X509)* p) const {
152 sk_X509_free(p);
153 }
154};
155typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509;
156
Brian Carlstromef628d12010-07-19 13:52:03 -0700157struct sk_X509_NAME_Delete {
158 void operator()(STACK_OF(X509_NAME)* p) const {
159 sk_X509_NAME_free(p);
160 }
161};
162typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME;
163
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800164/**
165 * Frees the SSL error state.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800166 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800167 * OpenSSL keeps an "error stack" per thread, and given that this code
168 * can be called from arbitrary threads that we don't keep track of,
169 * we err on the side of freeing the error state promptly (instead of,
170 * say, at thread death).
171 */
172static void freeSslErrorState(void) {
173 ERR_clear_error();
174 ERR_remove_state(0);
175}
176
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800177/*
178 * Checks this thread's OpenSSL error queue and throws a RuntimeException if
179 * necessary.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800180 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800181 * @return 1 if an exception was thrown, 0 if not.
182 */
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700183static int throwExceptionIfNecessary(JNIEnv* env, const char* location __attribute__ ((unused))) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800184 int error = ERR_get_error();
185 int result = 0;
186
187 if (error != 0) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700188 char message[256];
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800189 ERR_error_string_n(error, message, sizeof(message));
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700190 JNI_TRACE("OpenSSL error in %s %d: %s", location, error, message);
Elliott Hughesda4f31d2010-01-28 13:43:39 -0800191 jniThrowRuntimeException(env, message);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800192 result = 1;
193 }
194
195 freeSslErrorState();
196 return result;
197}
198
Brian Carlstrom0348e622010-02-10 22:56:47 -0800199/**
200 * Throws an SocketTimeoutException with the given string as a message.
201 */
202static void throwSocketTimeoutException(JNIEnv* env, const char* message) {
Brian Carlstromef628d12010-07-19 13:52:03 -0700203 JNI_TRACE("throwSocketTimeoutException %s", message);
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700204 jniThrowException(env, "java/net/SocketTimeoutException", message);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800205}
206
207/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700208 * Throws a javax.net.ssl.SSLException with the given string as a message.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800209 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700210static void throwSSLExceptionStr(JNIEnv* env, const char* message) {
Brian Carlstromef628d12010-07-19 13:52:03 -0700211 JNI_TRACE("throwSSLExceptionStr %s", message);
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700212 jniThrowException(env, "javax/net/ssl/SSLException", message);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800213}
214
215/**
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700216 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message.
217 */
218static void throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) {
Brian Carlstromef628d12010-07-19 13:52:03 -0700219 JNI_TRACE("throwSSLProtocolExceptionStr %s", message);
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700220 jniThrowException(env, "javax/net/ssl/SSLProtocolException", message);
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700221}
222
223/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700224 * Throws an SSLException with a message constructed from the current
Brian Carlstrom0348e622010-02-10 22:56:47 -0800225 * SSL errors. This will also log the errors.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800226 *
Brian Carlstrom0348e622010-02-10 22:56:47 -0800227 * @param env the JNI environment
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700228 * @param ssl the possibly NULL SSL
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700229 * @param sslErrorCode error code returned from SSL_get_error() or
230 * SSL_ERROR_NONE to probe with ERR_get_error
Brian Carlstrom0348e622010-02-10 22:56:47 -0800231 * @param message null-ok; general error message
232 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700233static void throwSSLExceptionWithSslErrors(
234 JNIEnv* env, SSL* ssl, int sslErrorCode, const char* message) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700235
236 if (message == NULL) {
237 message = "SSL error";
238 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800239
Brian Carlstromecaf7592010-03-02 16:55:35 -0800240 // First consult the SSL error code for the general message.
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700241 const char* sslErrorStr = NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800242 switch (sslErrorCode) {
243 case SSL_ERROR_NONE:
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700244 if (ERR_peek_error() == 0) {
245 sslErrorStr = "OK";
246 } else {
247 sslErrorStr = "";
248 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800249 break;
250 case SSL_ERROR_SSL:
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700251 sslErrorStr = "Failure in SSL library, usually a protocol error";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800252 break;
253 case SSL_ERROR_WANT_READ:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700254 sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800255 break;
256 case SSL_ERROR_WANT_WRITE:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700257 sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800258 break;
259 case SSL_ERROR_WANT_X509_LOOKUP:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700260 sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800261 break;
262 case SSL_ERROR_SYSCALL:
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700263 sslErrorStr = "I/O error during system call";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800264 break;
265 case SSL_ERROR_ZERO_RETURN:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700266 sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800267 break;
268 case SSL_ERROR_WANT_CONNECT:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700269 sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800270 break;
271 case SSL_ERROR_WANT_ACCEPT:
Elliott Hughes3b0a5b92010-07-22 15:06:54 -0700272 sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this.";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800273 break;
274 default:
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700275 sslErrorStr = "Unknown SSL error";
Brian Carlstrom0348e622010-02-10 22:56:47 -0800276 }
277
278 // Prepend either our explicit message or a default one.
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700279 char* str;
280 if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) {
281 // problem with asprintf, just throw argument message, log everything
282 throwSSLExceptionStr(env, message);
283 LOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800284 freeSslErrorState();
285 return;
286 }
287
288 char* allocStr = str;
289
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700290 // For protocol errors, SSL might have more information.
291 if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800292 // Append each error as an additional line to the message.
293 for (;;) {
294 char errStr[256];
295 const char* file;
296 int line;
297 const char* data;
298 int flags;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700299 unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800300 if (err == 0) {
301 break;
302 }
303
304 ERR_error_string_n(err, errStr, sizeof(errStr));
305
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700306 int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
307 (allocStr == NULL) ? "" : allocStr,
308 errStr,
309 file,
310 line,
311 (flags & ERR_TXT_STRING) ? data : "(no data)",
312 flags);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800313
314 if (ret < 0) {
315 break;
316 }
317
318 free(allocStr);
319 allocStr = str;
320 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800321 // For errors during system calls, errno might be our friend.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800322 } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
323 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
324 free(allocStr);
325 allocStr = str;
326 }
327 // If the error code is invalid, print it.
328 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
329 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
330 free(allocStr);
331 allocStr = str;
332 }
333 }
334
Brian Carlstromf3f7cc72010-05-19 11:06:59 -0700335 if (sslErrorCode == SSL_ERROR_SSL) {
336 throwSSLProtocolExceptionStr(env, allocStr);
337 } else {
338 throwSSLExceptionStr(env, allocStr);
339 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800340
341 LOGV("%s", allocStr);
342 free(allocStr);
343 freeSslErrorState();
344}
345
346/**
Brian Carlstromecaf7592010-03-02 16:55:35 -0800347 * Helper function that grabs the casts an ssl pointer and then checks for nullness.
Brian Carlstrom0348e622010-02-10 22:56:47 -0800348 * If this function returns NULL and <code>throwIfNull</code> is
349 * passed as <code>true</code>, then this function will call
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700350 * <code>throwSSLExceptionStr</code> before returning, so in this case of
Brian Carlstrom0348e622010-02-10 22:56:47 -0800351 * NULL, a caller of this function should simply return and allow JNI
352 * to do its thing.
Brian Carlstromecaf7592010-03-02 16:55:35 -0800353 *
354 * @param env the JNI environment
355 * @param ssl_address; the ssl_address pointer as an integer
Brian Carlstrom0348e622010-02-10 22:56:47 -0800356 * @param throwIfNull whether to throw if the SSL pointer is NULL
357 * @returns the pointer, which may be NULL
358 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700359static SSL_CTX* to_SSL_CTX(JNIEnv* env, int ssl_ctx_address, bool throwIfNull) {
360 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address));
361 if ((ssl_ctx == NULL) && throwIfNull) {
362 JNI_TRACE("ssl_ctx == null");
Brian Carlstromef628d12010-07-19 13:52:03 -0700363 jniThrowNullPointerException(env, "ssl_ctx == null");
Brian Carlstrom6df63392010-05-18 11:33:13 -0700364 }
365 return ssl_ctx;
366}
367
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700368static SSL* to_SSL(JNIEnv* env, int ssl_address, bool throwIfNull) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800369 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address));
Brian Carlstrom0348e622010-02-10 22:56:47 -0800370 if ((ssl == NULL) && throwIfNull) {
Brian Carlstrom6df63392010-05-18 11:33:13 -0700371 JNI_TRACE("ssl == null");
Brian Carlstromef628d12010-07-19 13:52:03 -0700372 jniThrowNullPointerException(env, "ssl == null");
Brian Carlstrom0348e622010-02-10 22:56:47 -0800373 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800374 return ssl;
375}
376
Brian Carlstrom6df63392010-05-18 11:33:13 -0700377static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, int ssl_session_address, bool throwIfNull) {
378 SSL_SESSION* ssl_session
379 = reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address));
380 if ((ssl_session == NULL) && throwIfNull) {
381 JNI_TRACE("ssl_session == null");
Brian Carlstromef628d12010-07-19 13:52:03 -0700382 jniThrowNullPointerException(env, "ssl_session == null");
Brian Carlstrom6df63392010-05-18 11:33:13 -0700383 }
384 return ssl_session;
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700385}
386
Brian Carlstromecaf7592010-03-02 16:55:35 -0800387/**
388 * Converts a Java byte[] to an OpenSSL BIGNUM, allocating the BIGNUM on the
389 * fly.
390 */
391static BIGNUM* arrayToBignum(JNIEnv* env, jbyteArray source) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700392 JNI_TRACE("arrayToBignum(%p)", source);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800393
Elliott Hughesebca53a2010-05-20 20:54:45 -0700394 ScopedByteArrayRO sourceBytes(env, source);
Elliott Hughes64101122010-07-12 09:53:54 -0700395 if (sourceBytes.get() == NULL) {
Brian Carlstromf62b5032010-09-22 10:25:39 -0700396 JNI_TRACE("arrayToBignum(%p) => NULL", source);
Elliott Hughes64101122010-07-12 09:53:54 -0700397 return NULL;
398 }
Brian Carlstromf62b5032010-09-22 10:25:39 -0700399 BIGNUM* bn = BN_bin2bn(reinterpret_cast<const unsigned char*>(sourceBytes.get()),
400 sourceBytes.size(),
401 NULL);
402 JNI_TRACE("arrayToBignum(%p) => %p", source, bn);
403 return bn;
Brian Carlstromecaf7592010-03-02 16:55:35 -0800404}
Brian Carlstrom0348e622010-02-10 22:56:47 -0800405
406/**
407 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
408 * suppose there are not many other ways to do this on a Linux system (modulo
409 * isomorphism).
410 */
411#define MUTEX_TYPE pthread_mutex_t
412#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
413#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
414#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
415#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
416#define THREAD_ID pthread_self()
417#define THROW_EXCEPTION (-2)
418#define THROW_SOCKETTIMEOUTEXCEPTION (-3)
Brian Carlstrom84f16122010-09-21 02:09:29 -0700419#define THROWN_SOCKETEXCEPTION (-4)
Brian Carlstrom0348e622010-02-10 22:56:47 -0800420
Elliott Hughesacce5ff2010-08-13 16:14:21 -0700421static MUTEX_TYPE* mutex_buf = NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800422
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700423static void locking_function(int mode, int n, const char*, int) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800424 if (mode & CRYPTO_LOCK) {
425 MUTEX_LOCK(mutex_buf[n]);
426 } else {
427 MUTEX_UNLOCK(mutex_buf[n]);
428 }
429}
430
431static unsigned long id_function(void) {
432 return ((unsigned long)THREAD_ID);
433}
434
435int THREAD_setup(void) {
Elliott Hughes583ce472010-07-22 10:23:42 -0700436 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700437 if (!mutex_buf) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800438 return 0;
439 }
440
Elliott Hughes583ce472010-07-22 10:23:42 -0700441 for (int i = 0; i < CRYPTO_num_locks(); ++i) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800442 MUTEX_SETUP(mutex_buf[i]);
443 }
444
445 CRYPTO_set_id_callback(id_function);
446 CRYPTO_set_locking_callback(locking_function);
447
448 return 1;
449}
450
451int THREAD_cleanup(void) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800452 if (!mutex_buf) {
Brian Carlstrom6df63392010-05-18 11:33:13 -0700453 return 0;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800454 }
455
456 CRYPTO_set_id_callback(NULL);
457 CRYPTO_set_locking_callback(NULL);
458
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700459 for (int i = 0; i < CRYPTO_num_locks( ); i++) {
Brian Carlstrom0348e622010-02-10 22:56:47 -0800460 MUTEX_CLEANUP(mutex_buf[i]);
461 }
462
463 free(mutex_buf);
464 mutex_buf = NULL;
465
466 return 1;
467}
468
Brian Carlstromecaf7592010-03-02 16:55:35 -0800469/**
470 * Initialization phase for every OpenSSL job: Loads the Error strings, the
471 * crypto algorithms and reset the OpenSSL library
472 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700473static void NativeCrypto_clinit(JNIEnv*, jclass)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800474{
475 SSL_load_error_strings();
476 ERR_load_crypto_strings();
477 SSL_library_init();
478 OpenSSL_add_all_algorithms();
479 THREAD_setup();
480}
481
482/**
Brian Carlstrom6df63392010-05-18 11:33:13 -0700483 * public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g,
484 * byte[] pub_key, byte[] priv_key);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800485 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700486static EVP_PKEY* NativeCrypto_EVP_PKEY_new_DSA(JNIEnv* env, jclass,
487 jbyteArray p, jbyteArray q, jbyteArray g,
488 jbyteArray pub_key, jbyteArray priv_key) {
Brian Carlstromf62b5032010-09-22 10:25:39 -0700489 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p)",
490 p, q, g, pub_key, priv_key);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800491
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700492 Unique_DSA dsa(DSA_new());
493 if (dsa.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700494 jniThrowRuntimeException(env, "DSA_new failed");
495 return NULL;
496 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800497
498 dsa->p = arrayToBignum(env, p);
499 dsa->q = arrayToBignum(env, q);
500 dsa->g = arrayToBignum(env, g);
501 dsa->pub_key = arrayToBignum(env, pub_key);
502
503 if (priv_key != NULL) {
504 dsa->priv_key = arrayToBignum(env, priv_key);
Brian Carlstrom0348e622010-02-10 22:56:47 -0800505 }
Brian Carlstrom0348e622010-02-10 22:56:47 -0800506
Brian Carlstromecaf7592010-03-02 16:55:35 -0800507 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || dsa->pub_key == NULL) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800508 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
509 return NULL;
Brian Carlstrom0348e622010-02-10 22:56:47 -0800510 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800511
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700512 Unique_EVP_PKEY pkey(EVP_PKEY_new());
513 if (pkey.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700514 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
515 return NULL;
516 }
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700517 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
518 jniThrowRuntimeException(env, "EVP_PKEY_assign_DSA failed");
519 return NULL;
520 }
521 dsa.release();
Brian Carlstromf62b5032010-09-22 10:25:39 -0700522 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p) => %p",
523 p, q, g, pub_key, priv_key, pkey.get());
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700524 return pkey.release();
Brian Carlstrom0348e622010-02-10 22:56:47 -0800525}
526
Brian Carlstromecaf7592010-03-02 16:55:35 -0800527/**
528 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
529 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700530static EVP_PKEY* NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass,
531 jbyteArray n, jbyteArray e, jbyteArray d,
532 jbyteArray p, jbyteArray q) {
Brian Carlstromf62b5032010-09-22 10:25:39 -0700533 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p)", n, e, d, p, q);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800534
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700535 Unique_RSA rsa(RSA_new());
536 if (rsa.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700537 jniThrowRuntimeException(env, "RSA_new failed");
538 return NULL;
539 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800540
541 rsa->n = arrayToBignum(env, n);
542 rsa->e = arrayToBignum(env, e);
543
544 if (d != NULL) {
545 rsa->d = arrayToBignum(env, d);
546 }
547
548 if (p != NULL) {
549 rsa->p = arrayToBignum(env, p);
550 }
551
552 if (q != NULL) {
553 rsa->q = arrayToBignum(env, q);
554 }
555
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700556#ifdef WITH_JNI_TRACE
Brian Carlstromf62b5032010-09-22 10:25:39 -0700557 if (p != NULL && q != NULL) {
558 int check = RSA_check_key(rsa.get());
559 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
560 }
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700561#endif
Brian Carlstromecaf7592010-03-02 16:55:35 -0800562
563 if (rsa->n == NULL || rsa->e == NULL) {
Brian Carlstromecaf7592010-03-02 16:55:35 -0800564 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
565 return NULL;
566 }
567
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700568 Unique_EVP_PKEY pkey(EVP_PKEY_new());
569 if (pkey.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700570 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
571 return NULL;
572 }
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700573 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
574 jniThrowRuntimeException(env, "EVP_PKEY_new failed");
575 return NULL;
576 }
577 rsa.release();
Brian Carlstromf62b5032010-09-22 10:25:39 -0700578 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p) => %p", n, e, d, p, q, pkey.get());
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700579 return pkey.release();
Brian Carlstrom0348e622010-02-10 22:56:47 -0800580}
581
Brian Carlstromecaf7592010-03-02 16:55:35 -0800582/**
583 * private static native void EVP_PKEY_free(int pkey);
584 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700585static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, EVP_PKEY* pkey) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700586 JNI_TRACE("EVP_PKEY_free(%p)", pkey);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800587
588 if (pkey != NULL) {
589 EVP_PKEY_free(pkey);
590 }
591}
592
593/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700594 * public static native int EVP_MD_CTX_create()
Brian Carlstromecaf7592010-03-02 16:55:35 -0800595 */
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700596static jint NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) {
597 JNI_TRACE("NativeCrypto_EVP_MD_CTX_create");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800598
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700599 EVP_MD_CTX* ctx = EVP_MD_CTX_create();
600 if (ctx == NULL) {
601 jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
602 }
603 JNI_TRACE("NativeCrypto_EVP_MD_CTX_create => %p", ctx);
604 return (jint) ctx;
605
Brian Carlstromecaf7592010-03-02 16:55:35 -0800606}
607
608/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700609 * public static native void EVP_MD_CTX_destroy(int)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800610 */
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700611static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv*, jclass, EVP_MD_CTX* ctx) {
612 JNI_TRACE("NativeCrypto_EVP_MD_CTX_destroy(%p)", ctx);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800613
614 if (ctx != NULL) {
615 EVP_MD_CTX_destroy(ctx);
616 }
617}
618
619/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700620 * public static native int EVP_MD_CTX_copy(int)
621 */
622static jint NativeCrypto_EVP_MD_CTX_copy(JNIEnv* env, jclass, EVP_MD_CTX* ctx) {
623 JNI_TRACE("NativeCrypto_EVP_MD_CTX_copy(%p)", ctx);
624
625 if (ctx == NULL) {
626 jniThrowNullPointerException(env, NULL);
627 return NULL;
628 }
629 EVP_MD_CTX* copy = EVP_MD_CTX_create();
630 if (copy == NULL) {
631 jniThrowOutOfMemoryError(env, "Unable to allocate copy of EVP_MD_CTX");
632 return NULL;
633 }
634 EVP_MD_CTX_init(copy);
635 int result = EVP_MD_CTX_copy_ex(copy, ctx);
636 if (result == 0) {
637 EVP_MD_CTX_destroy(copy);
638 jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX");
639 return NULL;
640 }
641 JNI_TRACE("NativeCrypto_EVP_MD_CTX_copy(%p) => %p", ctx, copy);
642 return (jint) copy;
643}
644
645/*
Brian Carlstromecaf7592010-03-02 16:55:35 -0800646 * public static native int EVP_DigestFinal(int, byte[], int)
647 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700648static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, EVP_MD_CTX* ctx,
649 jbyteArray hash, jint offset) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700650 JNI_TRACE("NativeCrypto_EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800651
652 if (ctx == NULL || hash == NULL) {
653 jniThrowNullPointerException(env, NULL);
654 return -1;
655 }
656
657 int result = -1;
658
Elliott Hughesebca53a2010-05-20 20:54:45 -0700659 ScopedByteArrayRW hashBytes(env, hash);
Elliott Hughes64101122010-07-12 09:53:54 -0700660 if (hashBytes.get() == NULL) {
661 return -1;
662 }
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700663 EVP_DigestFinal(ctx,
664 reinterpret_cast<unsigned char*>(hashBytes.get() + offset),
665 reinterpret_cast<unsigned int*>(&result));
Brian Carlstromecaf7592010-03-02 16:55:35 -0800666
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700667 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestFinal");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800668
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700669 JNI_TRACE("NativeCrypto_EVP_DigestFinal(%p, %p, %d) => %d", ctx, hash, offset, result);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800670 return result;
671}
672
673/*
674 * public static native void EVP_DigestInit(int, java.lang.String)
675 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700676static void NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jstring algorithm) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700677 JNI_TRACE("NativeCrypto_EVP_DigestInit(%p, %p)", ctx, algorithm);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800678
679 if (ctx == NULL || algorithm == NULL) {
680 jniThrowNullPointerException(env, NULL);
681 return;
682 }
683
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700684 ScopedUtfChars algorithmChars(env, algorithm);
Elliott Hughes05960872010-05-26 17:45:07 -0700685 if (algorithmChars.c_str() == NULL) {
686 return;
687 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800688
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700689 JNI_TRACE("NativeCrypto_EVP_DigestInit(%p, %s)", ctx, algorithmChars.c_str());
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700690 const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str()));
Brian Carlstromecaf7592010-03-02 16:55:35 -0800691
692 if (digest == NULL) {
693 jniThrowRuntimeException(env, "Hash algorithm not found");
694 return;
695 }
696
697 EVP_DigestInit(ctx, digest);
698
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700699 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestInit");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800700}
701
702/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700703 * public static native int EVP_MD_CTX_size(int)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800704 */
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700705static jint NativeCrypto_EVP_MD_CTX_size(JNIEnv* env, jclass, EVP_MD_CTX* ctx) {
706 JNI_TRACE("NativeCrypto_EVP_MD_CTX_size(%p)", ctx);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800707
708 if (ctx == NULL) {
709 jniThrowNullPointerException(env, NULL);
710 return -1;
711 }
712
713 int result = EVP_MD_CTX_size(ctx);
714
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700715 throwExceptionIfNecessary(env, "NativeCrypto_EVP_MD_CTX_size");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800716
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700717 JNI_TRACE("NativeCrypto_EVP_MD_CTX_size(%p) => %d", ctx, result);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800718 return result;
719}
720
721/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700722 * public static int void EVP_MD_CTX_block_size(int)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800723 */
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700724static jint NativeCrypto_EVP_MD_CTX_block_size(JNIEnv* env, jclass, EVP_MD_CTX* ctx) {
725 JNI_TRACE("NativeCrypto_EVP_MD_CTX_block_size(%p)", ctx);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800726
727 if (ctx == NULL) {
728 jniThrowNullPointerException(env, NULL);
729 return -1;
730 }
731
732 int result = EVP_MD_CTX_block_size(ctx);
733
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700734 throwExceptionIfNecessary(env, "NativeCrypto_EVP_MD_CTX_block_size");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800735
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700736 JNI_TRACE("NativeCrypto_EVP_MD_CTX_block_size(%p) => %d", ctx, result);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800737 return result;
738}
739
740/*
741 * public static native void EVP_DigestUpdate(int, byte[], int, int)
742 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700743static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, EVP_MD_CTX* ctx,
744 jbyteArray buffer, jint offset, jint length) {
Brian Carlstrom760b6832010-09-17 02:59:55 -0700745 JNI_TRACE("NativeCrypto_EVP_DigestUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800746
Brian Carlstrom44e4b132010-09-15 00:28:06 -0700747 if (offset < 0 || length < 0) {
748 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
749 return;
750 }
751
Brian Carlstromecaf7592010-03-02 16:55:35 -0800752 if (ctx == NULL || buffer == NULL) {
753 jniThrowNullPointerException(env, NULL);
754 return;
755 }
756
Elliott Hughesebca53a2010-05-20 20:54:45 -0700757 ScopedByteArrayRO bufferBytes(env, buffer);
Elliott Hughes64101122010-07-12 09:53:54 -0700758 if (bufferBytes.get() == NULL) {
759 return;
760 }
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700761 EVP_DigestUpdate(ctx,
762 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
763 length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800764
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700765 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestUpdate");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800766}
767
768/*
769 * public static native void EVP_VerifyInit(int, java.lang.String)
770 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700771static void NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jstring algorithm) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700772 JNI_TRACE("NativeCrypto_EVP_VerifyInit(%p, %p)", ctx, algorithm);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800773
774 if (ctx == NULL || algorithm == NULL) {
775 jniThrowNullPointerException(env, NULL);
776 return;
777 }
778
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700779 ScopedUtfChars algorithmChars(env, algorithm);
Elliott Hughes05960872010-05-26 17:45:07 -0700780 if (algorithmChars.c_str() == NULL) {
781 return;
782 }
Brian Carlstromecaf7592010-03-02 16:55:35 -0800783
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700784 JNI_TRACE("NativeCrypto_EVP_VerifyInit(%p, %s)", ctx, algorithmChars.c_str());
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700785 const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str()));
Brian Carlstromecaf7592010-03-02 16:55:35 -0800786
787 if (digest == NULL) {
788 jniThrowRuntimeException(env, "Hash algorithm not found");
789 return;
790 }
791
792 EVP_VerifyInit(ctx, digest);
793
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700794 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyInit");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800795}
796
797/*
798 * public static native void EVP_VerifyUpdate(int, byte[], int, int)
799 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700800static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, EVP_MD_CTX* ctx,
801 jbyteArray buffer, jint offset, jint length) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700802 JNI_TRACE("NativeCrypto_EVP_VerifyUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800803
804 if (ctx == NULL || buffer == NULL) {
805 jniThrowNullPointerException(env, NULL);
806 return;
807 }
808
Elliott Hughesebca53a2010-05-20 20:54:45 -0700809 ScopedByteArrayRO bufferBytes(env, buffer);
Elliott Hughes64101122010-07-12 09:53:54 -0700810 if (bufferBytes.get() == NULL) {
811 return;
812 }
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700813 EVP_VerifyUpdate(ctx,
814 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
815 length);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800816
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700817 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800818}
819
820/*
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700821 * public static native int EVP_VerifyFinal(int, byte[], int, int, int)
Brian Carlstromecaf7592010-03-02 16:55:35 -0800822 */
Brian Carlstrom6df63392010-05-18 11:33:13 -0700823static int NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, EVP_MD_CTX* ctx, jbyteArray buffer,
824 jint offset, jint length, EVP_PKEY* pkey) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700825 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p)",
826 ctx, buffer, offset, length, pkey);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800827
828 if (ctx == NULL || buffer == NULL || pkey == NULL) {
829 jniThrowNullPointerException(env, NULL);
830 return -1;
831 }
832
Elliott Hughesebca53a2010-05-20 20:54:45 -0700833 ScopedByteArrayRO bufferBytes(env, buffer);
Elliott Hughes64101122010-07-12 09:53:54 -0700834 if (bufferBytes.get() == NULL) {
835 return -1;
836 }
Elliott Hughes583ce472010-07-22 10:23:42 -0700837 int result = EVP_VerifyFinal(ctx,
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700838 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset),
839 length,
840 pkey);
Brian Carlstromecaf7592010-03-02 16:55:35 -0800841
Brian Carlstrom02d23a62010-05-04 22:44:46 -0700842 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyFinal");
Brian Carlstromecaf7592010-03-02 16:55:35 -0800843
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700844 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) => %d",
845 ctx, buffer, offset, length, pkey, result);
846
Brian Carlstromecaf7592010-03-02 16:55:35 -0800847 return result;
848}
849
850/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700851 * Helper function that creates an RSA public key from two buffers containing
852 * the big-endian bit representation of the modulus and the public exponent.
853 *
854 * @param mod The data of the modulus
855 * @param modLen The length of the modulus data
856 * @param exp The data of the exponent
857 * @param expLen The length of the exponent data
858 *
859 * @return A pointer to the new RSA structure, or NULL on error
860 */
Elliott Hughes583ce472010-07-22 10:23:42 -0700861static RSA* rsaCreateKey(const jbyte* mod, int modLen, const jbyte* exp, int expLen) {
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700862 JNI_TRACE("rsaCreateKey(..., %d, ..., %d)", modLen, expLen);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700863
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700864 Unique_RSA rsa(RSA_new());
865 if (rsa.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700866 return NULL;
867 }
868
Elliott Hughes583ce472010-07-22 10:23:42 -0700869 rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(mod), modLen, NULL);
870 rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(exp), expLen, NULL);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700871
872 if (rsa->n == NULL || rsa->e == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700873 return NULL;
874 }
875
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700876 JNI_TRACE("rsaCreateKey(..., %d, ..., %d) => %p", modLen, expLen, rsa.get());
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700877 return rsa.release();
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700878}
879
880/**
881 * Helper function that verifies a given RSA signature for a given message.
882 *
883 * @param msg The message to verify
884 * @param msgLen The length of the message
885 * @param sig The signature to verify
886 * @param sigLen The length of the signature
887 * @param algorithm The name of the hash/sign algorithm to use, e.g. "RSA-SHA1"
888 * @param rsa The RSA public key to use
889 *
890 * @return 1 on success, 0 on failure, -1 on error (check SSL errors then)
891 *
892 */
Elliott Hughes583ce472010-07-22 10:23:42 -0700893static int rsaVerify(const jbyte* msg, unsigned int msgLen, const jbyte* sig,
894 unsigned int sigLen, const char* algorithm, RSA* rsa) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700895
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700896 JNI_TRACE("rsaVerify(%p, %d, %p, %d, %s, %p)",
897 msg, msgLen, sig, sigLen, algorithm, rsa);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700898
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700899 Unique_EVP_PKEY pkey(EVP_PKEY_new());
900 if (pkey.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700901 return -1;
902 }
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700903 EVP_PKEY_set1_RSA(pkey.get(), rsa);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700904
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700905 const EVP_MD* type = EVP_get_digestbyname(algorithm);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700906 if (type == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700907 return -1;
908 }
909
910 EVP_MD_CTX ctx;
911 EVP_MD_CTX_init(&ctx);
912 if (EVP_VerifyInit_ex(&ctx, type, NULL) == 0) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700913 return -1;
914 }
915
916 EVP_VerifyUpdate(&ctx, msg, msgLen);
Elliott Hughes583ce472010-07-22 10:23:42 -0700917 int result = EVP_VerifyFinal(&ctx, reinterpret_cast<const unsigned char*>(sig), sigLen,
918 pkey.get());
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700919 EVP_MD_CTX_cleanup(&ctx);
Brian Carlstroma3de55d2010-09-16 01:32:17 -0700920
921 JNI_TRACE("rsaVerify(%p, %d, %p, %d, %s, %p) => %d",
922 msg, msgLen, sig, sigLen, algorithm, rsa, result);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700923 return result;
924}
925
926/**
927 * Verifies an RSA signature.
928 */
Elliott Hughese22935d2010-08-12 17:27:27 -0700929static int NativeCrypto_verifySignature(JNIEnv* env, jclass,
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700930 jbyteArray msg, jbyteArray sig, jstring algorithm, jbyteArray mod, jbyteArray exp) {
931
Elliott Hughese22935d2010-08-12 17:27:27 -0700932 JNI_TRACE("NativeCrypto_verifySignature msg=%p sig=%p algorithm=%p mod=%p exp%p",
Brian Carlstrom6df63392010-05-18 11:33:13 -0700933 msg, sig, algorithm, mod, exp);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700934
Elliott Hughes64101122010-07-12 09:53:54 -0700935 ScopedByteArrayRO msgBytes(env, msg);
936 if (msgBytes.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700937 return -1;
938 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700939 ScopedByteArrayRO sigBytes(env, sig);
Elliott Hughes64101122010-07-12 09:53:54 -0700940 if (sigBytes.get() == NULL) {
941 return -1;
942 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700943 ScopedByteArrayRO modBytes(env, mod);
Elliott Hughes64101122010-07-12 09:53:54 -0700944 if (modBytes.get() == NULL) {
945 return -1;
946 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700947 ScopedByteArrayRO expBytes(env, exp);
Elliott Hughes64101122010-07-12 09:53:54 -0700948 if (expBytes.get() == NULL) {
949 return -1;
950 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700951
952 ScopedUtfChars algorithmChars(env, algorithm);
Elliott Hughes05960872010-05-26 17:45:07 -0700953 if (algorithmChars.c_str() == NULL) {
954 return -1;
955 }
Elliott Hughese22935d2010-08-12 17:27:27 -0700956 JNI_TRACE("NativeCrypto_verifySignature algorithmChars=%s", algorithmChars.c_str());
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700957
Elliott Hughes583ce472010-07-22 10:23:42 -0700958 Unique_RSA rsa(rsaCreateKey(modBytes.get(), modBytes.size(), expBytes.get(), expBytes.size()));
Elliott Hughes05960872010-05-26 17:45:07 -0700959 int result = -1;
Brian Carlstromb5b39e42010-05-19 15:29:11 -0700960 if (rsa.get() != NULL) {
Elliott Hughes583ce472010-07-22 10:23:42 -0700961 result = rsaVerify(msgBytes.get(), msgBytes.size(), sigBytes.get(), sigBytes.size(),
962 algorithmChars.c_str(), rsa.get());
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700963 }
964
965 if (result == -1) {
Elliott Hughese22935d2010-08-12 17:27:27 -0700966 if (!throwExceptionIfNecessary(env, "NativeCrypto_verifySignature")) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700967 jniThrowRuntimeException(env, "Internal error during verification");
968 }
969 }
970
Elliott Hughese22935d2010-08-12 17:27:27 -0700971 JNI_TRACE("NativeCrypto_verifySignature => %d", result);
Brian Carlstrom3e24c532010-05-06 00:23:21 -0700972 return result;
973}
974
Brian Carlstrom6df63392010-05-18 11:33:13 -0700975static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) {
976 JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed);
Elliott Hughes64101122010-07-12 09:53:54 -0700977 ScopedByteArrayRO randseed(env, seed);
978 if (randseed.get() == NULL) {
Brian Carlstrom6df63392010-05-18 11:33:13 -0700979 return;
980 }
Brian Carlstrom6df63392010-05-18 11:33:13 -0700981 RAND_seed(randseed.get(), randseed.size());
982}
983
984static int NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) {
985 JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, max_bytes);
Elliott Hughes05960872010-05-26 17:45:07 -0700986 ScopedUtfChars file(env, filename);
987 if (file.c_str() == NULL) {
Brian Carlstrom6df63392010-05-18 11:33:13 -0700988 return -1;
989 }
Brian Carlstrom6df63392010-05-18 11:33:13 -0700990 int result = RAND_load_file(file.c_str(), max_bytes);
991 JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result);
992 return result;
993}
994
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700995#ifdef WITH_JNI_TRACE
Brian Carlstromecaf7592010-03-02 16:55:35 -0800996/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -0700997 * Based on example logging call back from SSL_CTX_set_info_callback man page
Brian Carlstromecaf7592010-03-02 16:55:35 -0800998 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -0700999static void info_callback_LOG(const SSL* s __attribute__ ((unused)), int where, int ret)
Brian Carlstromecaf7592010-03-02 16:55:35 -08001000{
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001001 int w = where & ~SSL_ST_MASK;
1002 const char* str;
1003 if (w & SSL_ST_CONNECT) {
1004 str = "SSL_connect";
1005 } else if (w & SSL_ST_ACCEPT) {
1006 str = "SSL_accept";
Brian Carlstromecaf7592010-03-02 16:55:35 -08001007 } else {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001008 str = "undefined";
Brian Carlstromecaf7592010-03-02 16:55:35 -08001009 }
1010
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001011 if (where & SSL_CB_LOOP) {
1012 JNI_TRACE("ssl=%p %s:%s %s", s, str, SSL_state_string(s), SSL_state_string_long(s));
1013 } else if (where & SSL_CB_ALERT) {
1014 str = (where & SSL_CB_READ) ? "read" : "write";
1015 JNI_TRACE("ssl=%p SSL3 alert %s:%s:%s %s %s",
1016 s,
1017 str,
1018 SSL_alert_type_string(ret),
1019 SSL_alert_desc_string(ret),
1020 SSL_alert_type_string_long(ret),
1021 SSL_alert_desc_string_long(ret));
1022 } else if (where & SSL_CB_EXIT) {
1023 if (ret == 0) {
1024 JNI_TRACE("ssl=%p %s:failed exit in %s %s",
1025 s, str, SSL_state_string(s), SSL_state_string_long(s));
1026 } else if (ret < 0) {
1027 JNI_TRACE("ssl=%p %s:error exit in %s %s",
1028 s, str, SSL_state_string(s), SSL_state_string_long(s));
1029 } else if (ret == 1) {
1030 JNI_TRACE("ssl=%p %s:ok exit in %s %s",
1031 s, str, SSL_state_string(s), SSL_state_string_long(s));
1032 } else {
1033 JNI_TRACE("ssl=%p %s:unknown exit %d in %s %s",
1034 s, str, ret, SSL_state_string(s), SSL_state_string_long(s));
1035 }
1036 } else if (where & SSL_CB_HANDSHAKE_START) {
1037 JNI_TRACE("ssl=%p handshake start in %s %s",
1038 s, SSL_state_string(s), SSL_state_string_long(s));
1039 } else if (where & SSL_CB_HANDSHAKE_DONE) {
1040 JNI_TRACE("ssl=%p handshake done in %s %s",
1041 s, SSL_state_string(s), SSL_state_string_long(s));
1042 } else {
1043 JNI_TRACE("ssl=%p %s:unknown where %d in %s %s",
1044 s, str, where, SSL_state_string(s), SSL_state_string_long(s));
1045 }
1046}
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001047#endif
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001048
1049/**
1050 * Returns an array containing all the X509 certificate's bytes.
1051 */
Elliott Hughesa9f5c162010-06-16 16:32:18 -07001052static jobjectArray getCertificateBytes(JNIEnv* env, const STACK_OF(X509)* chain)
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001053{
1054 if (chain == NULL) {
1055 // Chain can be NULL if the associated cipher doesn't do certs.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001056 return NULL;
1057 }
1058
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001059 int count = sk_X509_num(chain);
1060 if (count <= 0) {
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001061 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001062 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08001063
Elliott Hughesa9f5c162010-06-16 16:32:18 -07001064 jobjectArray joa = env->NewObjectArray(count, JniConstants::byteArrayClass, NULL);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001065 if (joa == NULL) {
1066 return NULL;
1067 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08001068
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001069 for (int i = 0; i < count; i++) {
1070 X509* cert = sk_X509_value(chain, i);
1071
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001072 int len = i2d_X509(cert, NULL);
1073 if (len < 0) {
1074 return NULL;
Brian Carlstromecaf7592010-03-02 16:55:35 -08001075 }
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001076 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
1077 if (byteArray.get() == NULL) {
1078 return NULL;
1079 }
1080 ScopedByteArrayRW bytes(env, byteArray.get());
1081 if (bytes.get() == NULL) {
1082 return NULL;
1083 }
1084 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
1085 int n = i2d_X509(cert, &p);
1086 if (n < 0) {
1087 return NULL;
1088 }
1089 env->SetObjectArrayElement(joa, i, byteArray.get());
Brian Carlstromecaf7592010-03-02 16:55:35 -08001090 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08001091
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001092 return joa;
1093}
1094
1095/**
1096 * Returns an array containing all the X500 principal's bytes.
1097 */
1098static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* names)
1099{
1100 if (names == NULL) {
1101 return NULL;
1102 }
1103
1104 int count = sk_X509_NAME_num(names);
1105 if (count <= 0) {
1106 return NULL;
1107 }
1108
1109 jobjectArray joa = env->NewObjectArray(count, JniConstants::byteArrayClass, NULL);
1110 if (joa == NULL) {
1111 return NULL;
1112 }
1113
1114 for (int i = 0; i < count; i++) {
1115 X509_NAME* principal = sk_X509_NAME_value(names, i);
1116
1117 int len = i2d_X509_NAME(principal, NULL);
1118 if (len < 0) {
1119 return NULL;
1120 }
1121 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(len));
1122 if (byteArray.get() == NULL) {
1123 return NULL;
1124 }
1125 ScopedByteArrayRW bytes(env, byteArray.get());
1126 if (bytes.get() == NULL) {
1127 return NULL;
1128 }
1129 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get());
1130 int n = i2d_X509_NAME(principal, &p);
1131 if (n < 0) {
1132 return NULL;
1133 }
1134 env->SetObjectArrayElement(joa, i, byteArray.get());
1135 }
1136
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001137 return joa;
Brian Carlstromecaf7592010-03-02 16:55:35 -08001138}
Brian Carlstrom0348e622010-02-10 22:56:47 -08001139
1140/**
1141 * Our additional application data needed for getting synchronization right.
1142 * This maybe warrants a bit of lengthy prose:
Brian Carlstromecaf7592010-03-02 16:55:35 -08001143 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001144 * (1) We use a flag to reflect whether we consider the SSL connection alive.
1145 * Any read or write attempt loops will be cancelled once this flag becomes 0.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001146 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001147 * (2) We use an int to count the number of threads that are blocked by the
1148 * underlying socket. This may be at most two (one reader and one writer), since
1149 * the Java layer ensures that no more threads will enter the native code at the
1150 * same time.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001151 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001152 * (3) The pipe is used primarily as a means of cancelling a blocking select()
1153 * when we want to close the connection (aka "emergency button"). It is also
1154 * necessary for dealing with a possible race condition situation: There might
1155 * be cases where both threads see an SSL_ERROR_WANT_READ or
1156 * SSL_ERROR_WANT_WRITE. Both will enter a select() with the proper argument.
1157 * If one leaves the select() successfully before the other enters it, the
1158 * "success" event is already consumed and the second thread will be blocked,
1159 * possibly forever (depending on network conditions).
Brian Carlstromecaf7592010-03-02 16:55:35 -08001160 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001161 * The idea for solving the problem looks like this: Whenever a thread is
1162 * successful in moving around data on the network, and it knows there is
1163 * another thread stuck in a select(), it will write a byte to the pipe, waking
1164 * up the other thread. A thread that returned from select(), on the other hand,
1165 * knows whether it's been woken up by the pipe. If so, it will consume the
1166 * byte, and the original state of affairs has been restored.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001167 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001168 * The pipe may seem like a bit of overhead, but it fits in nicely with the
1169 * other file descriptors of the select(), so there's only one condition to wait
1170 * for.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001171 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001172 * (4) Finally, a mutex is needed to make sure that at most one thread is in
1173 * either SSL_read() or SSL_write() at any given time. This is an OpenSSL
1174 * requirement. We use the same mutex to guard the field for counting the
1175 * waiting threads.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001176 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001177 * Note: The current implementation assumes that we don't have to deal with
1178 * problems induced by multiple cores or processors and their respective
1179 * memory caches. One possible problem is that of inconsistent views on the
1180 * "aliveAndKicking" field. This could be worked around by also enclosing all
1181 * accesses to that field inside a lock/unlock sequence of our mutex, but
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001182 * currently this seems a bit like overkill. Marking volatile at the very least.
1183 *
Brian Carlstrom84f16122010-09-21 02:09:29 -07001184 * During handshaking, additional fields are used to up-call into
Brian Carlstrome3a18712010-07-13 22:54:39 -07001185 * Java to perform certificate verification and handshake
1186 * completion. These are also used in any renegotiation.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001187 *
1188 * (5) the JNIEnv so we can invoke the Java callback
1189 *
Brian Carlstrom6df63392010-05-18 11:33:13 -07001190 * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001191 *
Brian Carlstrom84f16122010-09-21 02:09:29 -07001192 * (7) a java.io.FileDescriptor wrapper to check for socket close
1193 *
Brian Carlstrome3a18712010-07-13 22:54:39 -07001194 * Because renegotiation can be requested by the peer at any time,
1195 * care should be taken to maintain an appropriate JNIEnv on any
1196 * downcall to openssl since it could result in an upcall to Java. The
1197 * current code does try to cover these cases by conditionally setting
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07001198 * the JNIEnv on calls that can read and write to the SSL such as
Brian Carlstrome3a18712010-07-13 22:54:39 -07001199 * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001200 *
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001201 * Finally, we have one other piece of state setup by OpenSSL callbacks:
1202 *
Brian Carlstrom84f16122010-09-21 02:09:29 -07001203 * (8) a set of ephemeral RSA keys that is lazily generated if a peer
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001204 * wants to use an exportable RSA cipher suite.
1205 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08001206 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001207class AppData {
1208 public:
Brian Carlstromecaf7592010-03-02 16:55:35 -08001209 volatile int aliveAndKicking;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001210 int waitingThreads;
1211 int fdsEmergency[2];
1212 MUTEX_TYPE mutex;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001213 JNIEnv* env;
Brian Carlstrom6df63392010-05-18 11:33:13 -07001214 jobject sslHandshakeCallbacks;
Brian Carlstrom84f16122010-09-21 02:09:29 -07001215 jobject fileDescriptor;
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001216 Unique_RSA ephemeralRsa;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001217
1218 /**
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001219 * Creates the application data context for the SSL*.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001220 */
1221 public:
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001222 static AppData* create() {
1223 UniquePtr<AppData> appData(new AppData());
1224 if (pipe(appData.get()->fdsEmergency) == -1) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001225 return NULL;
1226 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001227 if (MUTEX_SETUP(appData.get()->mutex) == -1) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07001228 return NULL;
1229 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001230 return appData.release();
Brian Carlstrom3534c7c2010-05-14 21:49:34 -07001231 }
1232
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001233 ~AppData() {
1234 aliveAndKicking = 0;
1235 if (fdsEmergency[0] != -1) {
1236 close(fdsEmergency[0]);
1237 }
1238 if (fdsEmergency[1] != -1) {
1239 close(fdsEmergency[1]);
1240 }
1241 MUTEX_CLEANUP(mutex);
1242 }
1243
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001244 private:
1245 AppData() :
1246 aliveAndKicking(1),
1247 waitingThreads(0),
1248 env(NULL),
1249 sslHandshakeCallbacks(NULL),
1250 ephemeralRsa(NULL) {
1251 fdsEmergency[0] = -1;
1252 fdsEmergency[1] = -1;
Brian Carlstrom3534c7c2010-05-14 21:49:34 -07001253 }
1254
1255 public:
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001256 /**
1257 * Used to set the SSL-to-Java callback state before each SSL_*
1258 * call that may result in a callback. It should be cleared after
1259 * the operation returns with clearCallbackState.
1260 *
1261 * @param env The JNIEnv
1262 * @param shc The SSLHandshakeCallbacks
1263 * @param fd The FileDescriptor
1264 */
1265 bool setCallbackState(JNIEnv* e, jobject shc, jobject fd) {
1266 NetFd netFd(e, fd);
1267 if (netFd.isClosed()) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07001268 return false;
1269 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001270 env = e;
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001271 sslHandshakeCallbacks = shc;
1272 fileDescriptor = fd;
Brian Carlstrom84f16122010-09-21 02:09:29 -07001273 return true;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001274 }
Brian Carlstrom3534c7c2010-05-14 21:49:34 -07001275
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001276 void clearCallbackState() {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001277 env = NULL;
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001278 sslHandshakeCallbacks = NULL;
1279 fileDescriptor = NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001280 }
Brian Carlstrom84f16122010-09-21 02:09:29 -07001281
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001282};
Brian Carlstrom0348e622010-02-10 22:56:47 -08001283
1284/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001285 * Dark magic helper function that checks, for a given SSL session, whether it
1286 * can SSL_read() or SSL_write() without blocking. Takes into account any
1287 * concurrent attempts to close the SSL session from the Java side. This is
1288 * needed to get rid of the hangs that occur when thread #1 closes the SSLSocket
1289 * while thread #2 is sitting in a blocking read or write. The type argument
1290 * specifies whether we are waiting for readability or writability. It expects
1291 * to be passed either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, since we
1292 * only need to wait in case one of these problems occurs.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001293 *
Brian Carlstrom84f16122010-09-21 02:09:29 -07001294 * @param env
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001295 * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001296 * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL
Brian Carlstrom84f16122010-09-21 02:09:29 -07001297 * @param appData The application data structure with mutex info etc.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001298 * @param timeout The timeout value for select call, with the special value
1299 * 0 meaning no timeout at all (wait indefinitely). Note: This is
1300 * the Java semantics of the timeout value, not the usual
1301 * select() semantics.
Brian Carlstrom84f16122010-09-21 02:09:29 -07001302 * @return The result of the inner select() call,
1303 * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on
1304 * additional errors
Brian Carlstrom0348e622010-02-10 22:56:47 -08001305 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001306static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07001307 // This loop is an expanded version of the NET_FAILURE_RETRY
1308 // macro. It cannot simply be used in this case because select
1309 // cannot be restarted without recreating the fd_sets and timeout
1310 // structure.
1311 int result;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001312 fd_set rfds;
1313 fd_set wfds;
Brian Carlstrom84f16122010-09-21 02:09:29 -07001314 do {
Brian Carlstromdf9c0902010-09-30 19:22:21 -07001315 NetFd fd(env, fdObject);
Brian Carlstrom84f16122010-09-21 02:09:29 -07001316 if (fd.isClosed()) {
1317 result = THROWN_SOCKETEXCEPTION;
1318 break;
1319 }
1320 int intFd = fd.get();
1321 JNI_TRACE("sslSelect type=%s fd=%d appData=%p timeout=%d",
1322 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE", intFd, appData, timeout);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001323
Brian Carlstrom84f16122010-09-21 02:09:29 -07001324 FD_ZERO(&rfds);
1325 FD_ZERO(&wfds);
Brian Carlstrom0348e622010-02-10 22:56:47 -08001326
Brian Carlstrom84f16122010-09-21 02:09:29 -07001327 if (type == SSL_ERROR_WANT_READ) {
1328 FD_SET(intFd, &rfds);
1329 } else {
1330 FD_SET(intFd, &wfds);
1331 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08001332
Brian Carlstrom84f16122010-09-21 02:09:29 -07001333 FD_SET(appData->fdsEmergency[0], &rfds);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001334
Brian Carlstrom84f16122010-09-21 02:09:29 -07001335 int max = intFd > appData->fdsEmergency[0] ? intFd : appData->fdsEmergency[0];
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001336
Brian Carlstrom84f16122010-09-21 02:09:29 -07001337 // Build a struct for the timeout data if we actually want a timeout.
1338 timeval tv;
1339 timeval* ptv;
1340 if (timeout > 0) {
1341 tv.tv_sec = timeout / 1000;
1342 tv.tv_usec = 0;
1343 ptv = &tv;
1344 } else {
1345 ptv = NULL;
1346 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001347
Brian Carlstrom84f16122010-09-21 02:09:29 -07001348 {
1349 AsynchronousSocketCloseMonitor monitor(intFd);
1350 result = select(max + 1, &rfds, &wfds, NULL, ptv);
Brian Carlstrom1be19cf2010-09-21 22:32:21 -07001351 JNI_TRACE("sslSelect %s fd=%d appData=%p timeout=%d => %d",
1352 (type == SSL_ERROR_WANT_READ) ? "READ" : "WRITE",
1353 fd.get(), appData, timeout, result);
Brian Carlstrom84f16122010-09-21 02:09:29 -07001354 if (result == -1) {
1355 if (fd.isClosed()) {
1356 result = THROWN_SOCKETEXCEPTION;
1357 break;
1358 }
1359 if (errno != EINTR) {
1360 break;
1361 }
1362 }
1363 }
1364 } while (result == -1);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001365
1366 // Lock
1367 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08001368 return -1;
1369 }
1370
Brian Carlstrom84f16122010-09-21 02:09:29 -07001371 if (result > 0) {
1372 // If we have been woken up by the emergency pipe, there must be a token in
1373 // it. Thus we can safely read it (even in a blocking way).
1374 if (FD_ISSET(appData->fdsEmergency[0], &rfds)) {
1375 char token;
1376 do {
1377 read(appData->fdsEmergency[0], &token, 1);
1378 } while (errno == EINTR);
1379 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08001380 }
1381
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001382 // Tell the world that there is now one thread less waiting for the
1383 // underlying network.
1384 appData->waitingThreads--;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001385
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001386 // Unlock
1387 MUTEX_UNLOCK(appData->mutex);
Brian Carlstrom84f16122010-09-21 02:09:29 -07001388
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001389 return result;
Brian Carlstrom0348e622010-02-10 22:56:47 -08001390}
1391
1392/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001393 * Helper function that wakes up a thread blocked in select(), in case there is
1394 * one. Is being called by sslRead() and sslWrite() as well as by JNI glue
1395 * before closing the connection.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001396 *
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001397 * @param data The application data structure with mutex info etc.
Brian Carlstromecaf7592010-03-02 16:55:35 -08001398 */
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001399static void sslNotify(AppData* appData) {
1400 // Write a byte to the emergency pipe, so a concurrent select() can return.
1401 // Note we have to restore the errno of the original system call, since the
1402 // caller relies on it for generating error messages.
1403 int errnoBackup = errno;
1404 char token = '*';
1405 do {
1406 errno = 0;
1407 write(appData->fdsEmergency[1], &token, 1);
1408 } while (errno == EINTR);
1409 errno = errnoBackup;
1410}
Brian Carlstrom0348e622010-02-10 22:56:47 -08001411
Elliott Hughes583ce472010-07-22 10:23:42 -07001412static AppData* toAppData(const SSL* ssl) {
1413 return reinterpret_cast<AppData*>(SSL_get_app_data(ssl));
1414}
1415
Brian Carlstrom6df63392010-05-18 11:33:13 -07001416/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001417 * Verify the X509 certificate via SSL_CTX_set_cert_verify_callback
1418 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001419static int cert_verify_callback(X509_STORE_CTX* x509_store_ctx, void* arg __attribute__ ((unused)))
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001420{
1421 /* Get the correct index to the SSLobject stored into X509_STORE_CTX. */
Elliott Hughes583ce472010-07-22 10:23:42 -07001422 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(x509_store_ctx,
1423 SSL_get_ex_data_X509_STORE_CTX_idx()));
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001424 JNI_TRACE("ssl=%p cert_verify_callback x509_store_ctx=%p arg=%p", ssl, x509_store_ctx, arg);
1425
Elliott Hughes583ce472010-07-22 10:23:42 -07001426 AppData* appData = toAppData(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001427 JNIEnv* env = appData->env;
1428 if (env == NULL) {
1429 LOGE("AppData->env missing in cert_verify_callback");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001430 JNI_TRACE("ssl=%p cert_verify_callback => 0", ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001431 return 0;
1432 }
Brian Carlstrom6df63392010-05-18 11:33:13 -07001433 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001434
Brian Carlstrom6df63392010-05-18 11:33:13 -07001435 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
1436 jmethodID methodID
1437 = env->GetMethodID(cls, "verifyCertificateChain", "([[BLjava/lang/String;)V");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001438
1439 jobjectArray objectArray = getCertificateBytes(env, x509_store_ctx->untrusted);
1440
Brian Carlstrom6df63392010-05-18 11:33:13 -07001441 const char* authMethod = SSL_authentication_method(ssl);
1442 JNI_TRACE("ssl=%p cert_verify_callback calling verifyCertificateChain authMethod=%s",
1443 ssl, authMethod);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001444 jstring authMethodString = env->NewStringUTF(authMethod);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001445 env->CallVoidMethod(sslHandshakeCallbacks, methodID, objectArray, authMethodString);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001446
1447 int result = (env->ExceptionCheck()) ? 0 : 1;
1448 JNI_TRACE("ssl=%p cert_verify_callback => %d", ssl, result);
1449 return result;
1450}
1451
1452/**
1453 * Call back to watch for handshake to be completed. This is necessary
1454 * for SSL_MODE_HANDSHAKE_CUTTHROUGH support, since SSL_do_handshake
1455 * returns before the handshake is completed in this case.
1456 */
Elliott Hughesacce5ff2010-08-13 16:14:21 -07001457static void info_callback(const SSL* ssl, int where, int ret __attribute__ ((unused))) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001458 JNI_TRACE("ssl=%p info_callback where=0x%x ret=%d", ssl, where, ret);
1459#ifdef WITH_JNI_TRACE
1460 info_callback_LOG(ssl, where, ret);
1461#endif
1462 if (!(where & SSL_CB_HANDSHAKE_DONE)) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07001463 JNI_TRACE("ssl=%p info_callback ignored", ssl);
1464 return;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001465 }
1466
Elliott Hughes583ce472010-07-22 10:23:42 -07001467 AppData* appData = toAppData(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001468 JNIEnv* env = appData->env;
1469 if (env == NULL) {
1470 LOGE("AppData->env missing in info_callback");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001471 JNI_TRACE("ssl=%p info_callback env error", ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001472 return;
1473 }
Brian Carlstrom0c131a22010-05-20 15:27:31 -07001474 if (env->ExceptionCheck()) {
1475 JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
1476 return;
1477 }
1478
Brian Carlstrom6df63392010-05-18 11:33:13 -07001479 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001480
Brian Carlstrom6df63392010-05-18 11:33:13 -07001481 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001482 jmethodID methodID = env->GetMethodID(cls, "handshakeCompleted", "()V");
1483
1484 JNI_TRACE("ssl=%p info_callback calling handshakeCompleted", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001485 env->CallVoidMethod(sslHandshakeCallbacks, methodID);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001486
1487 if (env->ExceptionCheck()) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07001488 JNI_TRACE("ssl=%p info_callback exception", ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001489 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001490 JNI_TRACE("ssl=%p info_callback completed", ssl);
1491}
1492
Brian Carlstrom6df63392010-05-18 11:33:13 -07001493/**
1494 * Call back to ask for a client certificate
1495 */
1496static int client_cert_cb(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
1497 JNI_TRACE("ssl=%p client_cert_cb x509Out=%p pkeyOut=%p", ssl, x509Out, pkeyOut);
1498
Elliott Hughes583ce472010-07-22 10:23:42 -07001499 AppData* appData = toAppData(ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001500 JNIEnv* env = appData->env;
1501 if (env == NULL) {
1502 LOGE("AppData->env missing in client_cert_cb");
1503 JNI_TRACE("ssl=%p client_cert_cb env error => 0", ssl);
1504 return 0;
1505 }
Brian Carlstrom30a77f32010-11-04 22:37:27 -07001506 if (env->ExceptionCheck()) {
1507 JNI_TRACE("ssl=%p client_cert_cb already pending exception", ssl);
1508 return 0;
1509 }
Brian Carlstrom6df63392010-05-18 11:33:13 -07001510 jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
1511
1512 jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
1513 jmethodID methodID
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001514 = env->GetMethodID(cls, "clientCertificateRequested", "([B[[B)V");
Brian Carlstrom6df63392010-05-18 11:33:13 -07001515
1516 // Call Java callback which can use SSL_use_certificate and SSL_use_PrivateKey to set values
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001517 char ssl2_ctype = SSL3_CT_RSA_SIGN;
1518 const char* ctype = NULL;
1519 int ctype_num = 0;
1520 jobjectArray issuers = NULL;
1521 switch (ssl->version) {
1522 case SSL2_VERSION:
1523 ctype = &ssl2_ctype;
1524 ctype_num = 1;
1525 break;
1526 case SSL3_VERSION:
1527 case TLS1_VERSION:
1528 case DTLS1_VERSION:
1529 ctype = ssl->s3->tmp.ctype;
1530 ctype_num = ssl->s3->tmp.ctype_num;
1531 issuers = getPrincipalBytes(env, ssl->s3->tmp.ca_names);
1532 break;
1533 }
Brian Carlstromef628d12010-07-19 13:52:03 -07001534#ifdef WITH_JNI_TRACE
1535 for (int i = 0; i < ctype_num; i++) {
1536 JNI_TRACE("ssl=%p clientCertificateRequested keyTypes[%d]=%d", ssl, i, ctype[i]);
1537 }
1538#endif
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001539
1540 jbyteArray keyTypes = env->NewByteArray(ctype_num);
1541 if (keyTypes == NULL) {
1542 JNI_TRACE("ssl=%p client_cert_cb bytes == null => 0", ssl);
1543 return 0;
1544 }
1545 env->SetByteArrayRegion(keyTypes, 0, ctype_num, reinterpret_cast<const jbyte*>(ctype));
1546
1547 JNI_TRACE("ssl=%p clientCertificateRequested calling clientCertificateRequested "
1548 "keyTypes=%p issuers=%p", ssl, keyTypes, issuers);
1549 env->CallVoidMethod(sslHandshakeCallbacks, methodID, keyTypes, issuers);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001550
1551 if (env->ExceptionCheck()) {
1552 JNI_TRACE("ssl=%p client_cert_cb exception => 0", ssl);
1553 return 0;
1554 }
1555
1556 // Check for values set from Java
1557 X509* certificate = SSL_get_certificate(ssl);
1558 EVP_PKEY* privatekey = SSL_get_privatekey(ssl);
1559 int result;
1560 if (certificate != NULL && privatekey != NULL) {
1561 *x509Out = certificate;
1562 *pkeyOut = privatekey;
1563 result = 1;
1564 } else {
1565 *x509Out = NULL;
1566 *pkeyOut = NULL;
1567 result = 0;
1568 }
1569 JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
1570 return result;
1571}
1572
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001573static RSA* rsaGenerateKey(int keylength) {
1574 Unique_BIGNUM bn(BN_new());
1575 if (bn.get() == NULL) {
1576 return NULL;
1577 }
1578 int setWordResult = BN_set_word(bn.get(), RSA_F4);
1579 if (setWordResult != 1) {
1580 return NULL;
1581 }
1582 Unique_RSA rsa(RSA_new());
1583 if (rsa.get() == NULL) {
1584 return NULL;
1585 }
1586 int generateResult = RSA_generate_key_ex(rsa.get(), keylength, bn.get(), NULL);
1587 if (generateResult != 1) {
1588 return NULL;
1589 }
1590 return rsa.release();
1591}
1592
1593/**
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001594 * Call back to ask for an ephemeral RSA key for SSL_RSA_EXPORT_WITH_RC4_40_MD5 (aka EXP-RC4-MD5)
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001595 */
1596static RSA* tmp_rsa_callback(SSL* ssl __attribute__ ((unused)),
1597 int is_export __attribute__ ((unused)),
1598 int keylength) {
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001599 JNI_TRACE("ssl=%p tmp_rsa_callback is_export=%d keylength=%d", ssl, is_export, keylength);
1600
Elliott Hughes583ce472010-07-22 10:23:42 -07001601 AppData* appData = toAppData(ssl);
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001602 if (appData->ephemeralRsa.get() == NULL) {
1603 JNI_TRACE("ssl=%p tmp_rsa_callback generating ephemeral RSA key", ssl);
1604 appData->ephemeralRsa.reset(rsaGenerateKey(keylength));
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001605 }
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001606 JNI_TRACE("ssl=%p tmp_rsa_callback => %p", ssl, appData->ephemeralRsa.get());
1607 return appData->ephemeralRsa.get();
1608}
1609
1610static DH* dhGenerateParameters(int keylength) {
1611
1612 /*
1613 * The SSL_CTX_set_tmp_dh_callback(3SSL) man page discusses two
1614 * different options for generating DH keys. One is generating the
1615 * keys using a single set of DH parameters. However, generating
1616 * DH parameters is slow enough (minutes) that they suggest doing
1617 * it once at install time. The other is to generate DH keys from
1618 * DSA parameters. Generating DSA parameters is faster than DH
1619 * parameters, but to prevent small subgroup attacks, they needed
1620 * to be regenerated for each set of DH keys. Setting the
1621 * SSL_OP_SINGLE_DH_USE option make sure OpenSSL will call back
1622 * for new DH parameters every type it needs to generate DH keys.
1623 */
1624#if 0
1625 // Slow path that takes minutes but could be cached
1626 Unique_DH dh(DH_new());
1627 if (!DH_generate_parameters_ex(dh.get(), keylength, 2, NULL)) {
1628 return NULL;
1629 }
1630 return dh.release();
1631#else
1632 // Faster path but must have SSL_OP_SINGLE_DH_USE set
1633 Unique_DSA dsa(DSA_new());
1634 if (!DSA_generate_parameters_ex(dsa.get(), keylength, NULL, 0, NULL, NULL, NULL)) {
1635 return NULL;
1636 }
1637 DH* dh = DSA_dup_DH(dsa.get());
1638 return dh;
1639#endif
1640}
1641
1642/**
1643 * Call back to ask for Diffie-Hellman parameters
1644 */
1645static DH* tmp_dh_callback(SSL* ssl __attribute__ ((unused)),
1646 int is_export __attribute__ ((unused)),
1647 int keylength) {
1648 JNI_TRACE("ssl=%p tmp_dh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
1649 DH* tmp_dh = dhGenerateParameters(keylength);
1650 JNI_TRACE("ssl=%p tmp_dh_callback => %p", ssl, tmp_dh);
1651 return tmp_dh;
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001652}
1653
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001654/*
1655 * public static native int SSL_CTX_new();
1656 */
Brian Carlstrom44e0e562010-05-06 23:44:16 -07001657static int NativeCrypto_SSL_CTX_new(JNIEnv* env, jclass) {
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001658 Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
1659 if (sslCtx.get() == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001660 jniThrowRuntimeException(env, "SSL_CTX_new");
1661 return NULL;
1662 }
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001663 SSL_CTX_set_options(sslCtx.get(),
Brian Carlstromf7b8b352010-05-21 15:45:11 -07001664 SSL_OP_ALL
1665 // Note: We explicitly do not allow SSLv2 to be used.
1666 | SSL_OP_NO_SSLv2
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07001667 // We also disable session tickets for better compatibility b/2682876
Brian Carlstromf7b8b352010-05-21 15:45:11 -07001668 | SSL_OP_NO_TICKET
Brian Carlstrom4559b1d2010-07-22 16:33:48 -07001669 // We also disable compression for better compatibility b/2710492 b/2710497
1670 | SSL_OP_NO_COMPRESSION
Brian Carlstromf7b8b352010-05-21 15:45:11 -07001671 // Because dhGenerateParameters uses DSA_generate_parameters_ex
1672 | SSL_OP_SINGLE_DH_USE);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001673
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001674 int mode = SSL_CTX_get_mode(sslCtx.get());
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001675 /*
1676 * Turn on "partial write" mode. This means that SSL_write() will
1677 * behave like Posix write() and possibly return after only
1678 * writing a partial buffer. Note: The alternative, perhaps
1679 * surprisingly, is not that SSL_write() always does full writes
1680 * but that it will force you to retry write calls having
1681 * preserved the full state of the original call. (This is icky
1682 * and undesirable.)
1683 */
1684 mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
1685#if defined(SSL_MODE_SMALL_BUFFERS) /* not all SSL versions have this */
1686 mode |= SSL_MODE_SMALL_BUFFERS; /* lazily allocate record buffers; usually saves
1687 * 44k over the default */
1688#endif
1689#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) /* not all SSL versions have this */
1690 mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH; /* enable sending of client data as soon as
1691 * ClientCCS and ClientFinished are sent */
1692#endif
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001693 SSL_CTX_set_mode(sslCtx.get(), mode);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001694
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001695 SSL_CTX_set_cert_verify_callback(sslCtx.get(), cert_verify_callback, NULL);
1696 SSL_CTX_set_info_callback(sslCtx.get(), info_callback);
1697 SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
1698 SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
Brian Carlstromaacf6f92010-05-20 01:02:17 -07001699 SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001700
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001701 JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
1702 return (jint) sslCtx.release();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001703}
1704
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001705/**
1706 * public static native void SSL_CTX_free(int ssl_ctx)
1707 */
1708static void NativeCrypto_SSL_CTX_free(JNIEnv* env,
1709 jclass, jint ssl_ctx_address)
1710{
Brian Carlstrom6df63392010-05-18 11:33:13 -07001711 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001712 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_free", ssl_ctx);
1713 if (ssl_ctx == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001714 return;
1715 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001716 SSL_CTX_free(ssl_ctx);
1717}
1718
1719/**
Brian Carlstrom6df63392010-05-18 11:33:13 -07001720 * public static native int SSL_new(int ssl_ctx) throws SSLException;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001721 */
Brian Carlstrom6df63392010-05-18 11:33:13 -07001722static jint NativeCrypto_SSL_new(JNIEnv* env, jclass, jint ssl_ctx_address)
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001723{
Brian Carlstrom6df63392010-05-18 11:33:13 -07001724 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
1725 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new", ssl_ctx);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001726 if (ssl_ctx == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001727 return NULL;
1728 }
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001729 Unique_SSL ssl(SSL_new(ssl_ctx));
1730 if (ssl.get() == NULL) {
1731 throwSSLExceptionWithSslErrors(env, NULL, SSL_ERROR_NONE,
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001732 "Unable to create SSL structure");
1733 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => NULL", ssl_ctx);
1734 return NULL;
1735 }
1736
1737 /* Java code in class OpenSSLSocketImpl does the verification. Meaning of
1738 * SSL_VERIFY_NONE flag in client mode: if not using an anonymous cipher
1739 * (by default disabled), the server will send a certificate which will
1740 * be checked. The result of the certificate verification process can be
1741 * checked after the TLS/SSL handshake using the SSL_get_verify_result(3)
1742 * function. The handshake will be continued regardless of the
1743 * verification result.
1744 */
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001745 SSL_set_verify(ssl.get(), SSL_VERIFY_NONE, NULL);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001746
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001747 JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_new => ssl=%p", ssl_ctx, ssl.get());
Brian Carlstroma3de55d2010-09-16 01:32:17 -07001748 return (jint) ssl.release();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001749}
1750
Brian Carlstrom6df63392010-05-18 11:33:13 -07001751static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass,
1752 jint ssl_address, jbyteArray privatekey)
1753{
1754 SSL* ssl = to_SSL(env, ssl_address, true);
1755 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey privatekey=%p", ssl, privatekey);
1756 if (ssl == NULL) {
1757 return;
1758 }
1759
Elliott Hughes64101122010-07-12 09:53:54 -07001760 ScopedByteArrayRO buf(env, privatekey);
1761 if (buf.get() == NULL) {
1762 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => threw exception", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001763 return;
1764 }
Brian Carlstromef628d12010-07-19 13:52:03 -07001765 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001766 Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size()));
1767 if (pkcs8.get() == NULL) {
1768 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
1769 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
1770 "Error parsing private key from DER to PKCS8");
1771 SSL_clear(ssl);
1772 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl);
1773 return;
1774 }
1775
1776 Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get()));
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001777 if (privatekeyevp.get() == NULL) {
Brian Carlstrombf87c562010-05-27 23:09:59 -07001778 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
Elliott Hughesccbe3402010-07-09 16:39:48 -07001779 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001780 "Error creating private key from PKCS8");
Brian Carlstrom6df63392010-05-18 11:33:13 -07001781 SSL_clear(ssl);
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001782 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from PKCS8 to key", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001783 return;
1784 }
1785
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001786 int ret = SSL_use_PrivateKey(ssl, privatekeyevp.get());
1787 if (ret == 1) {
1788 privatekeyevp.release();
1789 } else {
Brian Carlstrombf87c562010-05-27 23:09:59 -07001790 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001791 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
Brian Carlstrom6df63392010-05-18 11:33:13 -07001792 SSL_clear(ssl);
1793 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error", ssl);
1794 return;
1795 }
1796
1797 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => ok", ssl);
1798}
1799
1800static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001801 jint ssl_address, jobjectArray certificates)
Brian Carlstrom6df63392010-05-18 11:33:13 -07001802{
1803 SSL* ssl = to_SSL(env, ssl_address, true);
1804 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificates);
1805 if (ssl == NULL) {
1806 return;
1807 }
1808
1809 if (certificates == NULL) {
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001810 jniThrowNullPointerException(env, "certificates == null");
1811 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001812 return;
1813 }
1814
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001815 int length = env->GetArrayLength(certificates);
1816 if (length == 0) {
1817 jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0");
1818 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001819 return;
1820 }
1821
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001822 Unique_X509 certificatesX509[length];
1823 for (int i = 0; i < length; i++) {
1824 ScopedLocalRef<jbyteArray> certificate(env,
1825 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(certificates, i)));
1826 if (certificate.get() == NULL) {
1827 jniThrowNullPointerException(env, "certificates element == null");
1828 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates element null", ssl);
1829 return;
1830 }
1831
1832 ScopedByteArrayRO buf(env, certificate.get());
Elliott Hughes64101122010-07-12 09:53:54 -07001833 if (buf.get() == NULL) {
1834 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => threw exception", ssl);
1835 return;
1836 }
Brian Carlstromef628d12010-07-19 13:52:03 -07001837 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001838 certificatesX509[i].reset(d2i_X509(NULL, &tmp, buf.size()));
1839
1840 if (certificatesX509[i].get() == NULL) {
1841 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
1842 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
1843 SSL_clear(ssl);
1844 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl);
1845 return;
1846 }
1847 }
1848
1849 int ret = SSL_use_certificate(ssl, certificatesX509[0].get());
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001850 if (ret == 1) {
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001851 certificatesX509[0].release();
Brian Carlstromb5b39e42010-05-19 15:29:11 -07001852 } else {
Brian Carlstrombf87c562010-05-27 23:09:59 -07001853 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001854 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
Brian Carlstrom6df63392010-05-18 11:33:13 -07001855 SSL_clear(ssl);
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001856 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07001857 return;
1858 }
1859
Brian Carlstrom059dbc02010-07-08 14:44:44 -07001860 Unique_sk_X509 chain(sk_X509_new_null());
1861 if (chain.get() == NULL) {
1862 jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
1863 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
1864 return;
1865 }
1866 for (int i = 1; i < length; i++) {
1867 if (!sk_X509_push(chain.get(), certificatesX509[i].release())) {
1868 jniThrowOutOfMemoryError(env, "Unable to push certificate");
1869 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
1870 return;
1871 }
1872 }
1873 int chainResult = SSL_use_certificate_chain(ssl, chain.get());
1874 if (chainResult == 0) {
1875 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate chain");
1876 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate_chain error",
1877 ssl);
1878 return;
1879 } else {
1880 chain.release();
1881 }
1882
Brian Carlstrom6df63392010-05-18 11:33:13 -07001883 JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => ok", ssl);
1884}
1885
1886static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jint ssl_address)
1887{
1888 SSL* ssl = to_SSL(env, ssl_address, true);
1889 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key", ssl);
1890 if (ssl == NULL) {
1891 return;
1892 }
1893 int ret = SSL_check_private_key(ssl);
1894 if (ret != 1) {
Brian Carlstrom12cd1f02010-06-22 23:43:20 -07001895 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key");
Brian Carlstrom6df63392010-05-18 11:33:13 -07001896 SSL_clear(ssl);
1897 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl);
1898 return;
1899 }
1900 JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => ok", ssl);
1901}
1902
Brian Carlstromef628d12010-07-19 13:52:03 -07001903static void NativeCrypto_SSL_set_client_CA_list(JNIEnv* env, jclass,
1904 jint ssl_address, jobjectArray principals)
1905{
1906 SSL* ssl = to_SSL(env, ssl_address, true);
1907 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list principals=%p", ssl, principals);
1908 if (ssl == NULL) {
1909 return;
1910 }
1911
1912 if (principals == NULL) {
1913 jniThrowNullPointerException(env, "principals == null");
1914 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals == null", ssl);
1915 return;
1916 }
1917
1918 int length = env->GetArrayLength(principals);
1919 if (length == 0) {
1920 jniThrowException(env, "java/lang/IllegalArgumentException", "principals.length == 0");
1921 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals.length == 0", ssl);
1922 return;
1923 }
1924
1925 Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
1926 if (principalsStack.get() == NULL) {
1927 jniThrowOutOfMemoryError(env, "Unable to allocate principal stack");
1928 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
1929 return;
1930 }
1931 for (int i = 0; i < length; i++) {
1932 ScopedLocalRef<jbyteArray> principal(env,
1933 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(principals, i)));
1934 if (principal.get() == NULL) {
1935 jniThrowNullPointerException(env, "principals element == null");
1936 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals element null", ssl);
1937 return;
1938 }
1939
1940 ScopedByteArrayRO buf(env, principal.get());
1941 if (buf.get() == NULL) {
1942 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => threw exception", ssl);
1943 return;
1944 }
1945 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
1946 Unique_X509_NAME principalX509Name(d2i_X509_NAME(NULL, &tmp, buf.size()));
1947
1948 if (principalX509Name.get() == NULL) {
1949 LOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
1950 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing principal");
1951 SSL_clear(ssl);
1952 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principals parsing error",
1953 ssl);
1954 return;
1955 }
1956
1957 if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
1958 jniThrowOutOfMemoryError(env, "Unable to push principal");
1959 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
1960 return;
1961 }
1962 }
1963
1964 SSL_set_client_CA_list(ssl, principalsStack.release());
1965 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => ok", ssl);
1966}
1967
Brian Carlstrom6df63392010-05-18 11:33:13 -07001968/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001969 * public static native long SSL_get_mode(int ssl);
1970 */
Brian Carlstrom6df63392010-05-18 11:33:13 -07001971static jlong NativeCrypto_SSL_get_mode(JNIEnv* env, jclass, jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001972 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001973 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode", ssl);
1974 if (ssl == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001975 return 0;
1976 }
1977 long mode = SSL_get_mode(ssl);
1978 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_mode => 0x%lx", ssl, mode);
1979 return mode;
1980}
1981
1982/**
1983 * public static native long SSL_set_mode(int ssl, long mode);
1984 */
1985static jlong NativeCrypto_SSL_set_mode(JNIEnv* env, jclass,
1986 jint ssl_address, jlong mode) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07001987 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07001988 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode mode=0x%llx", ssl, mode);
1989 if (ssl == NULL) {
1990 return 0;
1991 }
1992 long result = SSL_set_mode(ssl, mode);
1993 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_mode => 0x%lx", ssl, result);
1994 return result;
1995}
1996
1997/**
1998 * public static native long SSL_clear_mode(int ssl, long mode);
1999 */
2000static jlong NativeCrypto_SSL_clear_mode(JNIEnv* env, jclass,
2001 jint ssl_address, jlong mode) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002002 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002003 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode mode=0x%llx", ssl, mode);
2004 if (ssl == NULL) {
2005 return 0;
2006 }
2007 long result = SSL_clear_mode(ssl, mode);
2008 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_mode => 0x%lx", ssl, result);
2009 return result;
2010}
2011
2012/**
2013 * public static native long SSL_get_options(int ssl);
2014 */
2015static jlong NativeCrypto_SSL_get_options(JNIEnv* env, jclass,
2016 jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002017 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002018 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options", ssl);
2019 if (ssl == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002020 return 0;
2021 }
2022 long options = SSL_get_options(ssl);
2023 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_options => 0x%lx", ssl, options);
2024 return options;
2025}
2026
2027/**
2028 * public static native long SSL_set_options(int ssl, long options);
2029 */
2030static jlong NativeCrypto_SSL_set_options(JNIEnv* env, jclass,
2031 jint ssl_address, jlong options) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002032 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002033 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options options=0x%llx", ssl, options);
2034 if (ssl == NULL) {
2035 return 0;
2036 }
2037 long result = SSL_set_options(ssl, options);
2038 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_options => 0x%lx", ssl, result);
2039 return result;
2040}
2041
2042/**
2043 * public static native long SSL_clear_options(int ssl, long options);
2044 */
2045static jlong NativeCrypto_SSL_clear_options(JNIEnv* env, jclass,
2046 jint ssl_address, jlong options) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002047 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002048 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options options=0x%llx", ssl, options);
2049 if (ssl == NULL) {
2050 return 0;
2051 }
2052 long result = SSL_clear_options(ssl, options);
2053 JNI_TRACE("ssl=%p NativeCrypto_SSL_clear_options => 0x%lx", ssl, result);
2054 return result;
2055}
2056
2057/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002058 * Sets the ciphers suites that are enabled in the SSL
2059 */
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002060static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
2061 jint ssl_address, jobjectArray cipherSuites)
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002062{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002063 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002064 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002065 if (ssl == NULL) {
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002066 return;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002067 }
Brian Carlstromef628d12010-07-19 13:52:03 -07002068 if (cipherSuites == NULL) {
2069 jniThrowNullPointerException(env, "cipherSuites == null");
2070 return;
2071 }
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002072
Brian Carlstromb5b39e42010-05-19 15:29:11 -07002073 Unique_sk_SSL_CIPHER cipherstack(sk_SSL_CIPHER_new_null());
2074 if (cipherstack.get() == NULL) {
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002075 jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
2076 return;
2077 }
2078
2079 const SSL_METHOD* ssl_method = ssl->method;
2080 int num_ciphers = ssl_method->num_ciphers();
2081
2082 int length = env->GetArrayLength(cipherSuites);
2083 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
2084 for (int i = 0; i < length; i++) {
Elliott Hughes8044bf62010-05-17 22:34:46 -07002085 ScopedLocalRef<jstring> cipherSuite(env,
2086 reinterpret_cast<jstring>(env->GetObjectArrayElement(cipherSuites, i)));
2087 ScopedUtfChars c(env, cipherSuite.get());
Elliott Hughes05960872010-05-26 17:45:07 -07002088 if (c.c_str() == NULL) {
2089 return;
2090 }
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002091 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
2092 bool found = false;
2093 for (int j = 0; j < num_ciphers; j++) {
2094 const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
2095 if ((strcmp(c.c_str(), cipher->name) == 0)
2096 && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
Brian Carlstrom059dbc02010-07-08 14:44:44 -07002097 if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
2098 jniThrowOutOfMemoryError(env, "Unable to push cipher");
2099 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
2100 return;
2101 }
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002102 found = true;
2103 }
2104 }
2105 if (!found) {
Brian Carlstrom9acacc32010-05-14 11:14:18 -07002106 jniThrowException(env, "java/lang/IllegalArgumentException",
2107 "Could not find cipher suite.");
2108 return;
2109 }
2110 }
2111
Brian Carlstromb5b39e42010-05-19 15:29:11 -07002112 int rc = SSL_set_cipher_lists(ssl, cipherstack.get());
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002113 if (rc == 0) {
2114 freeSslErrorState();
2115 jniThrowException(env, "java/lang/IllegalArgumentException",
2116 "Illegal cipher suite strings.");
Brian Carlstromb5b39e42010-05-19 15:29:11 -07002117 } else {
2118 cipherstack.release();
Brian Carlstrom0348e622010-02-10 22:56:47 -08002119 }
2120}
2121
Brian Carlstrom0348e622010-02-10 22:56:47 -08002122/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002123 * Sets certificate expectations, especially for server to request client auth
2124 */
2125static void NativeCrypto_SSL_set_verify(JNIEnv* env,
2126 jclass, jint ssl_address, jint mode)
2127{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002128 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf349b32010-09-13 22:04:32 -07002129 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_verify mode=%x", ssl, mode);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002130 if (ssl == NULL) {
2131 return;
2132 }
2133 SSL_set_verify(ssl, (int)mode, NULL);
2134}
2135
2136/**
2137 * Sets the ciphers suites that are enabled in the SSL
2138 */
2139static void NativeCrypto_SSL_set_session(JNIEnv* env, jclass,
2140 jint ssl_address, jint ssl_session_address)
2141{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002142 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrom6df63392010-05-18 11:33:13 -07002143 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, false);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002144 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session ssl_session=%p", ssl, ssl_session);
2145 if (ssl == NULL) {
2146 return;
2147 }
2148
2149 int ret = SSL_set_session(ssl, ssl_session);
2150 if (ret != 1) {
2151 /*
2152 * Translate the error, and throw if it turns out to be a real
2153 * problem.
2154 */
2155 int sslErrorCode = SSL_get_error(ssl, ret);
2156 if (sslErrorCode != SSL_ERROR_ZERO_RETURN) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002157 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "SSL session set");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002158 SSL_clear(ssl);
2159 }
2160 }
2161}
2162
2163/**
2164 * Sets the ciphers suites that are enabled in the SSL
2165 */
2166static void NativeCrypto_SSL_set_session_creation_enabled(JNIEnv* env, jclass,
2167 jint ssl_address, jboolean creation_enabled)
2168{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002169 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrom6df63392010-05-18 11:33:13 -07002170 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_session_creation_enabled creation_enabled=%d",
2171 ssl, creation_enabled);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002172 if (ssl == NULL) {
2173 return;
2174 }
2175 SSL_set_session_creation_enabled(ssl, creation_enabled);
2176}
2177
Brian Carlstrom4559b1d2010-07-22 16:33:48 -07002178static void NativeCrypto_SSL_set_tlsext_host_name(JNIEnv* env, jclass,
2179 jint ssl_address, jstring hostname)
2180{
2181 SSL* ssl = to_SSL(env, ssl_address, true);
2182 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name hostname=%p",
2183 ssl, hostname);
2184 if (ssl == NULL) {
2185 return;
2186 }
2187
2188 ScopedUtfChars hostnameChars(env, hostname);
2189 if (hostnameChars.c_str() == NULL) {
2190 return;
2191 }
2192 JNI_TRACE("NativeCrypto_SSL_set_tlsext_host_name hostnameChars=%s", hostnameChars.c_str());
2193
2194 int ret = SSL_set_tlsext_host_name(ssl, hostnameChars.c_str());
2195 if (ret != 1) {
2196 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting host name");
2197 SSL_clear(ssl);
2198 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => error", ssl);
2199 return;
2200 }
2201 JNI_TRACE("ssl=%p NativeCrypto_SSL_set_tlsext_host_name => ok", ssl);
2202}
2203
2204static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jint ssl_address) {
2205 SSL* ssl = to_SSL(env, ssl_address, true);
2206 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername", ssl);
2207 if (ssl == NULL) {
2208 return NULL;
2209 }
2210 const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2211 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_servername => %s", ssl, servername);
2212 return env->NewStringUTF(servername);
2213}
2214
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002215/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002216 * Perform SSL handshake
2217 */
2218static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass,
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002219 jint ssl_address, jobject fdObject, jobject shc, jint timeout, jboolean client_mode)
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002220{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002221 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002222 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout=%d client_mode=%d",
2223 ssl, fdObject, shc, timeout, client_mode);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002224 if (ssl == NULL) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002225 return 0;
2226 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002227 if (fdObject == NULL) {
2228 jniThrowNullPointerException(env, "fd == null");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002229 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2230 return 0;
2231 }
Brian Carlstrom6df63392010-05-18 11:33:13 -07002232 if (shc == NULL) {
2233 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002234 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2235 return 0;
2236 }
2237
Brian Carlstrom84f16122010-09-21 02:09:29 -07002238 NetFd fd(env, fdObject);
2239 if (fd.isClosed()) {
2240 // SocketException thrown by NetFd.isClosed
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002241 SSL_clear(ssl);
2242 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2243 return 0;
2244 }
2245
Brian Carlstrom84f16122010-09-21 02:09:29 -07002246 int ret = SSL_set_fd(ssl, fd.get());
Brian Carlstrom1be19cf2010-09-21 22:32:21 -07002247 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake s=%d", ssl, fd.get());
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002248
2249 if (ret != 1) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002250 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
2251 "Error setting the file descriptor");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002252 SSL_clear(ssl);
2253 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2254 return 0;
2255 }
2256
2257 /*
2258 * Make socket non-blocking, so SSL_connect SSL_read() and SSL_write() don't hang
2259 * forever and we can use select() to find out if the socket is ready.
2260 */
Brian Carlstrom84f16122010-09-21 02:09:29 -07002261 if (!setBlocking(fd.get(), false)) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002262 throwSSLExceptionStr(env, "Unable to make socket non blocking");
2263 SSL_clear(ssl);
2264 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2265 return 0;
2266 }
2267
2268 /*
2269 * Create our special application data.
2270 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002271 AppData* appData = AppData::create();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002272 if (appData == NULL) {
2273 throwSSLExceptionStr(env, "Unable to create application data");
2274 SSL_clear(ssl);
2275 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2276 return 0;
2277 }
Elliott Hughes583ce472010-07-22 10:23:42 -07002278 SSL_set_app_data(ssl, reinterpret_cast<char*>(appData));
Brian Carlstrom3534c7c2010-05-14 21:49:34 -07002279 JNI_TRACE("ssl=%p AppData::create => %p", ssl, appData);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002280
2281 if (client_mode) {
2282 SSL_set_connect_state(ssl);
2283 } else {
2284 SSL_set_accept_state(ssl);
2285 }
2286
Brian Carlstrom84f16122010-09-21 02:09:29 -07002287 ret = 0;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002288 while (appData->aliveAndKicking) {
2289 errno = 0;
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002290 if (!appData->setCallbackState(env, shc, fdObject)) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07002291 // SocketException thrown by NetFd.isClosed
2292 SSL_clear(ssl);
2293 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2294 return 0;
2295 }
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002296 ret = SSL_do_handshake(ssl);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002297 appData->clearCallbackState();
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002298 // cert_verify_callback threw exception
2299 if (env->ExceptionCheck()) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07002300 SSL_clear(ssl);
2301 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2302 return 0;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002303 }
Brian Carlstromef628d12010-07-19 13:52:03 -07002304 // success case
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002305 if (ret == 1) {
2306 break;
Brian Carlstromef628d12010-07-19 13:52:03 -07002307 }
2308 // retry case
2309 if (errno == EINTR) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002310 continue;
Brian Carlstromef628d12010-07-19 13:52:03 -07002311 }
2312 // error case
Brian Carlstromef628d12010-07-19 13:52:03 -07002313 int sslError = SSL_get_error(ssl, ret);
Brian Carlstrom84f16122010-09-21 02:09:29 -07002314 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake ret=%d errno=%d sslError=%d timeout=%d",
2315 ssl, ret, errno, sslError, timeout);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002316
Brian Carlstromef628d12010-07-19 13:52:03 -07002317 /*
Brian Carlstrom84f16122010-09-21 02:09:29 -07002318 * If SSL_do_handshake doesn't succeed due to the socket being
Brian Carlstromef628d12010-07-19 13:52:03 -07002319 * either unreadable or unwritable, we use sslSelect to
2320 * wait for it to become ready. If that doesn't happen
2321 * before the specified timeout or an error occurs, we
2322 * cancel the handshake. Otherwise we try the SSL_connect
2323 * again.
2324 */
2325 if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
2326 appData->waitingThreads++;
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002327 int selectResult = sslSelect(env, sslError, fdObject, appData, timeout);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002328
Brian Carlstrom84f16122010-09-21 02:09:29 -07002329 if (selectResult == THROWN_SOCKETEXCEPTION) {
2330 // SocketException thrown by NetFd.isClosed
2331 SSL_clear(ssl);
2332 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2333 return 0;
2334 }
Brian Carlstromef628d12010-07-19 13:52:03 -07002335 if (selectResult == -1) {
2336 throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_SYSCALL, "handshake error");
2337 SSL_clear(ssl);
2338 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2339 return 0;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002340 }
Brian Carlstromef628d12010-07-19 13:52:03 -07002341 if (selectResult == 0) {
2342 throwSocketTimeoutException(env, "SSL handshake timed out");
2343 SSL_clear(ssl);
2344 freeSslErrorState();
2345 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2346 return 0;
2347 }
2348 } else {
2349 // LOGE("Unknown error %d during handshake", error);
2350 break;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002351 }
2352 }
2353
Brian Carlstromef628d12010-07-19 13:52:03 -07002354 // clean error. See SSL_do_handshake(3SSL) man page.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002355 if (ret == 0) {
2356 /*
2357 * The other side closed the socket before the handshake could be
2358 * completed, but everything is within the bounds of the TLS protocol.
2359 * We still might want to find out the real reason of the failure.
2360 */
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002361 int sslError = SSL_get_error(ssl, ret);
2362 if (sslError == SSL_ERROR_NONE || (sslError == SSL_ERROR_SYSCALL && errno == 0)) {
2363 throwSSLExceptionStr(env, "Connection closed by peer");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002364 } else {
Brian Carlstrom84f16122010-09-21 02:09:29 -07002365 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake terminated");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002366 }
2367 SSL_clear(ssl);
2368 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2369 return 0;
2370 }
Brian Carlstromef628d12010-07-19 13:52:03 -07002371
2372 // unclean error. See SSL_do_handshake(3SSL) man page.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002373 if (ret < 0) {
2374 /*
2375 * Translate the error and throw exception. We are sure it is an error
2376 * at this point.
2377 */
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002378 int sslError = SSL_get_error(ssl, ret);
Brian Carlstrom84f16122010-09-21 02:09:29 -07002379 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL handshake aborted");
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002380 SSL_clear(ssl);
2381 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl);
2382 return 0;
2383 }
2384 SSL_SESSION* ssl_session = SSL_get1_session(ssl);
2385 JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
2386 return (jint) ssl_session;
2387}
2388
2389/**
Brian Carlstromef628d12010-07-19 13:52:03 -07002390 * Perform SSL renegotiation
2391 */
2392static void NativeCrypto_SSL_renegotiate(JNIEnv* env, jclass, jint ssl_address)
2393{
2394 SSL* ssl = to_SSL(env, ssl_address, true);
2395 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate", ssl);
2396 if (ssl == NULL) {
2397 return;
2398 }
2399 int result = SSL_renegotiate(ssl);
2400 if (result != 1) {
2401 throwSSLExceptionStr(env, "Problem with SSL_renegotiate");
2402 return;
2403 }
2404 int ret = SSL_do_handshake(ssl);
2405 if (ret != 1) {
2406 int sslError = SSL_get_error(ssl, ret);
2407 throwSSLExceptionWithSslErrors(env, ssl, sslError,
2408 "Problem with SSL_do_handshake after SSL_renegotiate");
2409
2410 return;
2411 }
2412 JNI_TRACE("ssl=%p NativeCrypto_SSL_renegotiate =>", ssl);
2413}
2414
2415/**
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002416 * public static native byte[][] SSL_get_certificate(int ssl);
2417 */
2418static jobjectArray NativeCrypto_SSL_get_certificate(JNIEnv* env, jclass, jint ssl_address)
2419{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002420 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002421 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate", ssl);
2422 if (ssl == NULL) {
Brian Carlstromef628d12010-07-19 13:52:03 -07002423 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002424 }
2425 X509* certificate = SSL_get_certificate(ssl);
2426 if (certificate == NULL) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07002427 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
2428 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002429 }
Brian Carlstrom059dbc02010-07-08 14:44:44 -07002430
Brian Carlstromb5b39e42010-05-19 15:29:11 -07002431 Unique_sk_X509 chain(sk_X509_new_null());
2432 if (chain.get() == NULL) {
Brian Carlstrom059dbc02010-07-08 14:44:44 -07002433 jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
Elliott Hughes64101122010-07-12 09:53:54 -07002434 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
Brian Carlstrom6df63392010-05-18 11:33:13 -07002435 return NULL;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002436 }
Brian Carlstrom059dbc02010-07-08 14:44:44 -07002437 if (!sk_X509_push(chain.get(), certificate)) {
2438 jniThrowOutOfMemoryError(env, "Unable to push local certificate");
2439 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
2440 return NULL;
2441 }
2442 STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
2443 for (int i=0; i<sk_X509_num(cert_chain); i++) {
Brian Carlstrom4559b1d2010-07-22 16:33:48 -07002444 if (!sk_X509_push(chain.get(), sk_X509_value(cert_chain, i))) {
Brian Carlstrom059dbc02010-07-08 14:44:44 -07002445 jniThrowOutOfMemoryError(env, "Unable to push local certificate chain");
2446 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
2447 return NULL;
2448 }
2449 }
2450
Brian Carlstromb5b39e42010-05-19 15:29:11 -07002451 jobjectArray objectArray = getCertificateBytes(env, chain.get());
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002452 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => %p", ssl, objectArray);
2453 return objectArray;
2454}
2455
Brian Carlstromdf349b32010-09-13 22:04:32 -07002456// Fills a byte[][] with the peer certificates in the chain.
2457static jobjectArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, jint ssl_address)
2458{
2459 SSL* ssl = to_SSL(env, ssl_address, true);
2460 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain", ssl);
2461 if (ssl == NULL) {
2462 return NULL;
2463 }
2464 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
2465 Unique_sk_X509 chain_copy(NULL);
2466 if (ssl->server) {
2467 X509* x509 = SSL_get_peer_certificate(ssl);
2468 if (x509 == NULL) {
2469 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
2470 return NULL;
2471 }
2472 chain_copy.reset(sk_X509_dup(chain));
2473 if (chain_copy.get() == NULL) {
2474 jniThrowOutOfMemoryError(env, "Unable to allocate peer certificate chain");
2475 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
2476 return NULL;
2477 }
2478 if (!sk_X509_push(chain_copy.get(), x509)) {
2479 jniThrowOutOfMemoryError(env, "Unable to push server's peer certificate");
2480 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
2481 return NULL;
2482 }
2483 chain = chain_copy.get();
2484 }
2485 jobjectArray objectArray = getCertificateBytes(env, chain);
2486 JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => %p", ssl, objectArray);
2487 return objectArray;
2488}
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002489
2490/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08002491 * Helper function which does the actual reading. The Java layer guarantees that
2492 * at most one thread will enter this function at any given time.
Brian Carlstromecaf7592010-03-02 16:55:35 -08002493 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08002494 * @param ssl non-null; the SSL context
2495 * @param buf non-null; buffer to read into
2496 * @param len length of the buffer, in bytes
2497 * @param sslReturnCode original SSL return code
2498 * @param sslErrorCode filled in with the SSL error code in case of error
2499 * @return number of bytes read on success, -1 if the connection was
2500 * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown.
2501 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002502static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len,
2503 int* sslReturnCode, int* sslErrorCode, int timeout) {
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002504 JNI_TRACE("ssl=%p sslRead buf=%p len=%d", ssl, buf, len);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002505
Brian Carlstrom0348e622010-02-10 22:56:47 -08002506 if (len == 0) {
2507 // Don't bother doing anything in this case.
2508 return 0;
2509 }
2510
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002511 BIO* bio = SSL_get_rbio(ssl);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002512
Elliott Hughes583ce472010-07-22 10:23:42 -07002513 AppData* appData = toAppData(ssl);
Brian Carlstromef628d12010-07-19 13:52:03 -07002514 if (appData == NULL) {
2515 return THROW_EXCEPTION;
2516 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002517
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002518 while (appData->aliveAndKicking) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002519 errno = 0;
2520
2521 // Lock
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002522 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002523 return -1;
2524 }
2525
2526 unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002527
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002528 if (!appData->setCallbackState(env, shc, fdObject)) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07002529 MUTEX_UNLOCK(appData->mutex);
2530 return THROWN_SOCKETEXCEPTION;
2531 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002532 int result = SSL_read(ssl, buf, len);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002533 appData->clearCallbackState();
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002534 int sslError = SSL_ERROR_NONE;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002535 if (result <= 0) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002536 sslError = SSL_get_error(ssl, result);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002537 freeSslErrorState();
2538 }
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002539 JNI_TRACE("ssl=%p sslRead SSL_read result=%d sslError=%d", ssl, result, sslError);
2540#ifdef WITH_JNI_TRACE_DATA
Brian Carlstrom3900e262010-11-10 10:56:21 -08002541 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
2542 int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002543 JNI_TRACE("ssl=%p sslRead data: %d: %*s", ssl, n, n, buf+i);
2544 }
2545#endif
Brian Carlstrom0348e622010-02-10 22:56:47 -08002546
2547 // If we have been successful in moving data around, check whether it
2548 // might make sense to wake up other blocked threads, so they can give
2549 // it a try, too.
Brian Carlstrom6df63392010-05-18 11:33:13 -07002550 if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved
2551 && appData->waitingThreads > 0) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002552 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002553 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002554
Brian Carlstrom0348e622010-02-10 22:56:47 -08002555 // If we are blocked by the underlying socket, tell the world that
2556 // there will be one more waiting thread now.
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002557 if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002558 appData->waitingThreads++;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002559 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002560
Brian Carlstrom0348e622010-02-10 22:56:47 -08002561 // Unlock
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002562 MUTEX_UNLOCK(appData->mutex);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002563
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002564 switch (sslError) {
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07002565 // Successfully read at least one byte.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002566 case SSL_ERROR_NONE: {
2567 return result;
2568 }
2569
2570 // Read zero bytes. End of stream reached.
2571 case SSL_ERROR_ZERO_RETURN: {
2572 return -1;
2573 }
2574
Brian Carlstromecaf7592010-03-02 16:55:35 -08002575 // Need to wait for availability of underlying layer, then retry.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002576 case SSL_ERROR_WANT_READ:
2577 case SSL_ERROR_WANT_WRITE: {
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002578 int selectResult = sslSelect(env, sslError, fdObject, appData, timeout);
Brian Carlstrom84f16122010-09-21 02:09:29 -07002579 if (selectResult == THROWN_SOCKETEXCEPTION) {
2580 return THROWN_SOCKETEXCEPTION;
2581 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002582 if (selectResult == -1) {
2583 *sslReturnCode = -1;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002584 *sslErrorCode = sslError;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002585 return THROW_EXCEPTION;
Brian Carlstromef628d12010-07-19 13:52:03 -07002586 }
2587 if (selectResult == 0) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002588 return THROW_SOCKETTIMEOUTEXCEPTION;
2589 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002590
Brian Carlstrom0348e622010-02-10 22:56:47 -08002591 break;
2592 }
2593
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07002594 // A problem occurred during a system call, but this is not
Brian Carlstrom0348e622010-02-10 22:56:47 -08002595 // necessarily an error.
2596 case SSL_ERROR_SYSCALL: {
2597 // Connection closed without proper shutdown. Tell caller we
2598 // have reached end-of-stream.
2599 if (result == 0) {
2600 return -1;
2601 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002602
Brian Carlstrom0348e622010-02-10 22:56:47 -08002603 // System call has been interrupted. Simply retry.
2604 if (errno == EINTR) {
2605 break;
2606 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002607
Brian Carlstrom0348e622010-02-10 22:56:47 -08002608 // Note that for all other system call errors we fall through
Brian Carlstromecaf7592010-03-02 16:55:35 -08002609 // to the default case, which results in an Exception.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002610 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002611
Brian Carlstrom0348e622010-02-10 22:56:47 -08002612 // Everything else is basically an error.
2613 default: {
2614 *sslReturnCode = result;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002615 *sslErrorCode = sslError;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002616 return THROW_EXCEPTION;
2617 }
2618 }
2619 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002620
Brian Carlstrom0348e622010-02-10 22:56:47 -08002621 return -1;
2622}
2623
2624/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002625 * OpenSSL read function (1): only one chunk is read (returned as jint).
2626 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002627static jint NativeCrypto_SSL_read_byte(JNIEnv* env, jclass, jint ssl_address,
2628 jobject fdObject, jobject shc, jint timeout)
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002629{
2630 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002631 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte fd=%p shc=%p timeout=%d",
2632 ssl, fdObject, shc, timeout);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002633 if (ssl == NULL) {
2634 return 0;
2635 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002636 if (fdObject == NULL) {
2637 jniThrowNullPointerException(env, "fd == null");
2638 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => 0", ssl);
2639 return 0;
2640 }
2641 if (shc == NULL) {
2642 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
2643 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => 0", ssl);
2644 return 0;
2645 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002646
2647 unsigned char byteRead;
2648 int returnCode = 0;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002649 int sslErrorCode = SSL_ERROR_NONE;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002650
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002651 int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(&byteRead), 1,
Brian Carlstrom4559b1d2010-07-22 16:33:48 -07002652 &returnCode, &sslErrorCode, timeout);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002653
2654 int result;
2655 switch (ret) {
2656 case THROW_EXCEPTION:
2657 // See sslRead() regarding improper failure to handle normal cases.
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002658 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Read error");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002659 result = -1;
2660 break;
2661 case THROW_SOCKETTIMEOUTEXCEPTION:
2662 throwSocketTimeoutException(env, "Read timed out");
2663 result = -1;
2664 break;
Brian Carlstrom84f16122010-09-21 02:09:29 -07002665 case THROWN_SOCKETEXCEPTION:
2666 // SocketException thrown by NetFd.isClosed
2667 result = -1;
2668 break;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002669 case -1:
2670 // Propagate EOF upwards.
2671 result = -1;
2672 break;
2673 default:
2674 // Return the actual char read, make sure it stays 8 bits wide.
2675 result = ((jint) byteRead) & 0xFF;
2676 break;
2677 }
2678 JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => %d", ssl, result);
2679 return result;
2680}
2681
2682/**
2683 * OpenSSL read function (2): read into buffer at offset n chunks.
2684 * Returns 1 (success) or value <= 0 (failure).
2685 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002686static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint ssl_address, jobject fdObject,
2687 jobject shc, jbyteArray b, jint offset, jint len, jint timeout)
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002688{
2689 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002690 JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d timeout=%d",
2691 ssl, fdObject, shc, b, offset, len, timeout);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002692 if (ssl == NULL) {
2693 return 0;
2694 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002695 if (fdObject == NULL) {
2696 jniThrowNullPointerException(env, "fd == null");
2697 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl);
2698 return 0;
2699 }
2700 if (shc == NULL) {
2701 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
2702 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl);
2703 return 0;
2704 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002705
Elliott Hughesccbe3402010-07-09 16:39:48 -07002706 ScopedByteArrayRW bytes(env, b);
Elliott Hughes64101122010-07-12 09:53:54 -07002707 if (bytes.get() == NULL) {
2708 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => threw exception", ssl);
2709 return 0;
2710 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002711 int returnCode = 0;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002712 int sslErrorCode = SSL_ERROR_NONE;;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002713
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002714 int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast<char*>(bytes.get() + offset), len,
Brian Carlstromf7b8b352010-05-21 15:45:11 -07002715 &returnCode, &sslErrorCode, timeout);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002716
2717 int result;
Brian Carlstrom84f16122010-09-21 02:09:29 -07002718 switch (ret) {
2719 case THROW_EXCEPTION:
2720 // See sslRead() regarding improper failure to handle normal cases.
2721 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Read error");
2722 result = -1;
2723 break;
2724 case THROW_SOCKETTIMEOUTEXCEPTION:
2725 throwSocketTimeoutException(env, "Read timed out");
2726 result = -1;
2727 break;
2728 case THROWN_SOCKETEXCEPTION:
2729 // SocketException thrown by NetFd.isClosed
2730 result = -1;
2731 break;
2732 default:
2733 result = ret;
2734 break;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002735 }
2736
2737 JNI_TRACE("ssl=%p NativeCrypto_SSL_read => %d", ssl, result);
2738 return result;
2739}
2740
2741/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08002742 * Helper function which does the actual writing. The Java layer guarantees that
2743 * at most one thread will enter this function at any given time.
Brian Carlstromecaf7592010-03-02 16:55:35 -08002744 *
Brian Carlstrom0348e622010-02-10 22:56:47 -08002745 * @param ssl non-null; the SSL context
2746 * @param buf non-null; buffer to write
2747 * @param len length of the buffer, in bytes
2748 * @param sslReturnCode original SSL return code
2749 * @param sslErrorCode filled in with the SSL error code in case of error
2750 * @return number of bytes read on success, -1 if the connection was
2751 * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown.
2752 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002753static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len,
2754 int* sslReturnCode, int* sslErrorCode) {
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002755 JNI_TRACE("ssl=%p sslWrite buf=%p len=%d", ssl, buf, len);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002756
2757 if (len == 0) {
2758 // Don't bother doing anything in this case.
2759 return 0;
2760 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002761
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002762 BIO* bio = SSL_get_wbio(ssl);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002763
Elliott Hughes583ce472010-07-22 10:23:42 -07002764 AppData* appData = toAppData(ssl);
Brian Carlstromef628d12010-07-19 13:52:03 -07002765 if (appData == NULL) {
2766 return THROW_EXCEPTION;
2767 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002768
Brian Carlstrom0348e622010-02-10 22:56:47 -08002769 int count = len;
Brian Carlstromecaf7592010-03-02 16:55:35 -08002770
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002771 while (appData->aliveAndKicking && len > 0) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002772 errno = 0;
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002773 if (MUTEX_LOCK(appData->mutex) == -1) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002774 return -1;
2775 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002776
Brian Carlstrom0348e622010-02-10 22:56:47 -08002777 unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002778
Brian Carlstrom0348e622010-02-10 22:56:47 -08002779 // LOGD("Doing SSL_write() with %d bytes to go", len);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002780 if (!appData->setCallbackState(env, shc, fdObject)) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07002781 MUTEX_UNLOCK(appData->mutex);
2782 return THROWN_SOCKETEXCEPTION;
2783 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002784 int result = SSL_write(ssl, buf, len);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002785 appData->clearCallbackState();
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002786 int sslError = SSL_ERROR_NONE;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002787 if (result <= 0) {
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002788 sslError = SSL_get_error(ssl, result);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002789 freeSslErrorState();
2790 }
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002791 JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError);
2792#ifdef WITH_JNI_TRACE_DATA
Brian Carlstrom3900e262010-11-10 10:56:21 -08002793 for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
2794 int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002795 JNI_TRACE("ssl=%p sslWrite data: %d: %*s", ssl, n, n, buf+i);
2796 }
2797#endif
Brian Carlstrom0348e622010-02-10 22:56:47 -08002798
2799 // If we have been successful in moving data around, check whether it
2800 // might make sense to wake up other blocked threads, so they can give
2801 // it a try, too.
Brian Carlstrom6df63392010-05-18 11:33:13 -07002802 if (BIO_number_read(bio) + BIO_number_written(bio) != bytesMoved
2803 && appData->waitingThreads > 0) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002804 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002805 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002806
Brian Carlstrom0348e622010-02-10 22:56:47 -08002807 // If we are blocked by the underlying socket, tell the world that
2808 // there will be one more waiting thread now.
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002809 if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002810 appData->waitingThreads++;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002811 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002812
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002813 MUTEX_UNLOCK(appData->mutex);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002814
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002815 switch (sslError) {
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07002816 // Successfully write at least one byte.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002817 case SSL_ERROR_NONE: {
2818 buf += result;
2819 len -= result;
2820 break;
2821 }
2822
2823 // Wrote zero bytes. End of stream reached.
2824 case SSL_ERROR_ZERO_RETURN: {
2825 return -1;
2826 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002827
Brian Carlstrom0348e622010-02-10 22:56:47 -08002828 // Need to wait for availability of underlying layer, then retry.
2829 // The concept of a write timeout doesn't really make sense, and
2830 // it's also not standard Java behavior, so we wait forever here.
2831 case SSL_ERROR_WANT_READ:
2832 case SSL_ERROR_WANT_WRITE: {
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002833 int selectResult = sslSelect(env, sslError, fdObject, appData, 0);
Brian Carlstrom84f16122010-09-21 02:09:29 -07002834 if (selectResult == THROWN_SOCKETEXCEPTION) {
2835 return THROWN_SOCKETEXCEPTION;
2836 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002837 if (selectResult == -1) {
2838 *sslReturnCode = -1;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002839 *sslErrorCode = sslError;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002840 return THROW_EXCEPTION;
Brian Carlstromef628d12010-07-19 13:52:03 -07002841 }
2842 if (selectResult == 0) {
Brian Carlstrom0348e622010-02-10 22:56:47 -08002843 return THROW_SOCKETTIMEOUTEXCEPTION;
2844 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002845
Brian Carlstrom0348e622010-02-10 22:56:47 -08002846 break;
2847 }
2848
Elliott Hughes3b0a5b92010-07-22 15:06:54 -07002849 // An problem occurred during a system call, but this is not
Brian Carlstrom0348e622010-02-10 22:56:47 -08002850 // necessarily an error.
2851 case SSL_ERROR_SYSCALL: {
2852 // Connection closed without proper shutdown. Tell caller we
2853 // have reached end-of-stream.
2854 if (result == 0) {
2855 return -1;
2856 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002857
Brian Carlstrom0348e622010-02-10 22:56:47 -08002858 // System call has been interrupted. Simply retry.
2859 if (errno == EINTR) {
2860 break;
2861 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002862
Brian Carlstrom0348e622010-02-10 22:56:47 -08002863 // Note that for all other system call errors we fall through
Brian Carlstromecaf7592010-03-02 16:55:35 -08002864 // to the default case, which results in an Exception.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002865 }
Brian Carlstromecaf7592010-03-02 16:55:35 -08002866
Brian Carlstrom0348e622010-02-10 22:56:47 -08002867 // Everything else is basically an error.
2868 default: {
2869 *sslReturnCode = result;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002870 *sslErrorCode = sslError;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002871 return THROW_EXCEPTION;
2872 }
2873 }
2874 }
Brian Carlstrom0cbd33d2010-11-09 22:01:58 -08002875 JNI_TRACE("ssl=%p sslWrite => count=%d", ssl, count);
Brian Carlstromecaf7592010-03-02 16:55:35 -08002876
Brian Carlstrom0348e622010-02-10 22:56:47 -08002877 return count;
2878}
2879
2880/**
Brian Carlstrom0348e622010-02-10 22:56:47 -08002881 * OpenSSL write function (1): only one chunk is written.
2882 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002883static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address,
2884 jobject fdObject, jobject shc, jint b)
Brian Carlstrom0348e622010-02-10 22:56:47 -08002885{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002886 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002887 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte fd=%p shc=%p b=%d", ssl, fdObject, shc, b);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002888 if (ssl == NULL) {
2889 return;
2890 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002891 if (fdObject == NULL) {
2892 jniThrowNullPointerException(env, "fd == null");
2893 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte => fd == null", ssl);
2894 return;
2895 }
2896 if (shc == NULL) {
2897 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
2898 JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte => sslHandshakeCallbacks == null", ssl);
2899 return;
2900 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002901
2902 int returnCode = 0;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002903 int sslErrorCode = SSL_ERROR_NONE;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002904 char buf[1] = { (char) b };
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002905 int ret = sslWrite(env, ssl, fdObject, shc, buf, 1, &returnCode, &sslErrorCode);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002906
Brian Carlstrom84f16122010-09-21 02:09:29 -07002907 switch (ret) {
2908 case THROW_EXCEPTION:
2909 // See sslWrite() regarding improper failure to handle normal cases.
2910 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
2911 break;
2912 case THROW_SOCKETTIMEOUTEXCEPTION:
2913 throwSocketTimeoutException(env, "Write timed out");
2914 break;
2915 case THROWN_SOCKETEXCEPTION:
2916 // SocketException thrown by NetFd.isClosed
2917 break;
2918 default:
2919 break;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002920 }
2921}
2922
2923/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002924 * OpenSSL write function (2): write into buffer at offset n chunks.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002925 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002926static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jint ssl_address, jobject fdObject,
2927 jobject shc, jbyteArray b, jint offset, jint len)
Brian Carlstrom0348e622010-02-10 22:56:47 -08002928{
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002929 SSL* ssl = to_SSL(env, ssl_address, true);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002930 JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d",
2931 ssl, fdObject, shc, b, offset, len);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002932 if (ssl == NULL) {
2933 return;
2934 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002935 if (fdObject == NULL) {
2936 jniThrowNullPointerException(env, "fd == null");
2937 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl);
2938 return;
2939 }
2940 if (shc == NULL) {
2941 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
2942 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl);
2943 return;
2944 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002945
Elliott Hughesccbe3402010-07-09 16:39:48 -07002946 ScopedByteArrayRO bytes(env, b);
Elliott Hughes64101122010-07-12 09:53:54 -07002947 if (bytes.get() == NULL) {
2948 JNI_TRACE("ssl=%p NativeCrypto_SSL_write => threw exception", ssl);
2949 return;
2950 }
Brian Carlstrom0348e622010-02-10 22:56:47 -08002951 int returnCode = 0;
Brian Carlstromf3f7cc72010-05-19 11:06:59 -07002952 int sslErrorCode = SSL_ERROR_NONE;
Brian Carlstromdf9c0902010-09-30 19:22:21 -07002953 int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast<const char*>(bytes.get() + offset),
2954 len, &returnCode, &sslErrorCode);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002955
Brian Carlstrom84f16122010-09-21 02:09:29 -07002956 switch (ret) {
2957 case THROW_EXCEPTION:
2958 // See sslWrite() regarding improper failure to handle normal cases.
2959 throwSSLExceptionWithSslErrors(env, ssl, sslErrorCode, "Write error");
2960 break;
2961 case THROW_SOCKETTIMEOUTEXCEPTION:
2962 throwSocketTimeoutException(env, "Write timed out");
2963 break;
2964 case THROWN_SOCKETEXCEPTION:
2965 // SocketException thrown by NetFd.isClosed
2966 break;
2967 default:
2968 break;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002969 }
2970}
2971
2972/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002973 * Interrupt any pending IO before closing the socket.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002974 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002975static void NativeCrypto_SSL_interrupt(
Brian Carlstromecaf7592010-03-02 16:55:35 -08002976 JNIEnv* env, jclass, jint ssl_address) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07002977 SSL* ssl = to_SSL(env, ssl_address, false);
2978 JNI_TRACE("ssl=%p NativeCrypto_SSL_interrupt", ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002979 if (ssl == NULL) {
2980 return;
2981 }
2982
2983 /*
2984 * Mark the connection as quasi-dead, then send something to the emergency
2985 * file descriptor, so any blocking select() calls are woken up.
2986 */
Elliott Hughes583ce472010-07-22 10:23:42 -07002987 AppData* appData = toAppData(ssl);
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002988 if (appData != NULL) {
2989 appData->aliveAndKicking = 0;
Brian Carlstrom0348e622010-02-10 22:56:47 -08002990
2991 // At most two threads can be waiting.
Brian Carlstrombcfb3252010-05-02 11:27:52 -07002992 sslNotify(appData);
2993 sslNotify(appData);
Brian Carlstrom0348e622010-02-10 22:56:47 -08002994 }
2995}
2996
2997/**
Brian Carlstromecaf7592010-03-02 16:55:35 -08002998 * OpenSSL close SSL socket function.
Brian Carlstrom0348e622010-02-10 22:56:47 -08002999 */
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003000static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jint ssl_address,
3001 jobject fdObject, jobject shc) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003002 SSL* ssl = to_SSL(env, ssl_address, false);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003003 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc);
Brian Carlstrom0348e622010-02-10 22:56:47 -08003004 if (ssl == NULL) {
3005 return;
3006 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003007 if (fdObject == NULL) {
3008 jniThrowNullPointerException(env, "fd == null");
3009 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl);
3010 return;
3011 }
3012 if (shc == NULL) {
3013 jniThrowNullPointerException(env, "sslHandshakeCallbacks == null");
3014 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl);
3015 return;
3016 }
3017
Elliott Hughes583ce472010-07-22 10:23:42 -07003018 AppData* appData = toAppData(ssl);
Brian Carlstromef628d12010-07-19 13:52:03 -07003019 if (appData != NULL) {
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003020 if (!appData->setCallbackState(env, shc, fdObject)) {
Brian Carlstrom84f16122010-09-21 02:09:29 -07003021 // SocketException thrown by NetFd.isClosed
3022 SSL_clear(ssl);
3023 freeSslErrorState();
3024 return;
3025 }
3026
3027 /*
3028 * Try to make socket blocking again. OpenSSL literature recommends this.
3029 */
3030 int fd = SSL_get_fd(ssl);
3031 JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown s=%d", ssl, fd);
3032 if (fd != -1) {
3033 setBlocking(fd, true);
3034 }
3035
3036 int ret = SSL_shutdown(ssl);
3037 switch (ret) {
3038 case 0:
3039 /*
3040 * Shutdown was not successful (yet), but there also
3041 * is no error. Since we can't know whether the remote
3042 * server is actually still there, and we don't want to
3043 * get stuck forever in a second SSL_shutdown() call, we
3044 * simply return. This is not security a problem as long
3045 * as we close the underlying socket, which we actually
3046 * do, because that's where we are just coming from.
3047 */
3048 break;
3049 case 1:
3050 /*
3051 * Shutdown was successful. We can safely return. Hooray!
3052 */
3053 break;
3054 default:
3055 /*
3056 * Everything else is a real error condition. We should
3057 * let the Java layer know about this by throwing an
3058 * exception.
3059 */
3060 int sslError = SSL_get_error(ssl, ret);
3061 throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed");
3062 break;
3063 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003064 appData->clearCallbackState();
Brian Carlstromef628d12010-07-19 13:52:03 -07003065 }
Brian Carlstrom84f16122010-09-21 02:09:29 -07003066
Brian Carlstromecaf7592010-03-02 16:55:35 -08003067 SSL_clear(ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08003068 freeSslErrorState();
Brian Carlstrom0348e622010-02-10 22:56:47 -08003069}
3070
3071/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003072 * public static native void SSL_free(int ssl);
Brian Carlstrom0348e622010-02-10 22:56:47 -08003073 */
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003074static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jint ssl_address)
3075{
3076 SSL* ssl = to_SSL(env, ssl_address, true);
3077 JNI_TRACE("ssl=%p NativeCrypto_SSL_free", ssl);
3078 if (ssl == NULL) {
Brian Carlstrom3534c7c2010-05-14 21:49:34 -07003079 return;
Brian Carlstrom0348e622010-02-10 22:56:47 -08003080 }
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003081
Elliott Hughes583ce472010-07-22 10:23:42 -07003082 AppData* appData = toAppData(ssl);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003083 SSL_set_app_data(ssl, NULL);
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003084 delete appData;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003085 SSL_free(ssl);
3086}
Brian Carlstrom0348e622010-02-10 22:56:47 -08003087
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003088/**
3089 * Gets and returns in a byte array the ID of the actual SSL session.
3090 */
Brian Carlstrom6df63392010-05-18 11:33:13 -07003091static jbyteArray NativeCrypto_SSL_SESSION_session_id(JNIEnv* env, jclass,
3092 jint ssl_session_address) {
3093 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003094 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id", ssl_session);
Brian Carlstrom6df63392010-05-18 11:33:13 -07003095 if (ssl_session == NULL) {
3096 return NULL;
3097 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003098 jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
3099 if (result != NULL) {
3100 jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
3101 env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
Brian Carlstrom0348e622010-02-10 22:56:47 -08003102 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003103 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_session_id => %p session_id_length=%d",
3104 ssl_session, result, ssl_session->session_id_length);
Brian Carlstrom0348e622010-02-10 22:56:47 -08003105 return result;
3106}
3107
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003108/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003109 * Gets and returns in a long integer the creation's time of the
3110 * actual SSL session.
3111 */
Brian Carlstrom6df63392010-05-18 11:33:13 -07003112static jlong NativeCrypto_SSL_SESSION_get_time(JNIEnv* env, jclass, jint ssl_session_address) {
3113 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003114 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time", ssl_session);
Brian Carlstrom6df63392010-05-18 11:33:13 -07003115 if (ssl_session == NULL) {
3116 return 0;
3117 }
3118 // result must be jlong, not long or *1000 will overflow
3119 jlong result = SSL_SESSION_get_time(ssl_session);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003120 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
3121 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_time => %lld", ssl_session, result);
3122 return result;
3123}
3124
3125/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003126 * Gets and returns in a string the version of the SSL protocol. If it
3127 * returns the string "unknown" it means that no connection is established.
3128 */
3129static jstring NativeCrypto_SSL_SESSION_get_version(JNIEnv* env, jclass, jint ssl_session_address) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07003130 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003131 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version", ssl_session);
Brian Carlstrom6df63392010-05-18 11:33:13 -07003132 if (ssl_session == NULL) {
3133 return NULL;
3134 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003135 const char* protocol = SSL_SESSION_get_version(ssl_session);
3136 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_get_version => %s", ssl_session, protocol);
3137 return env->NewStringUTF(protocol);
3138}
3139
3140/**
Brian Carlstrom6df63392010-05-18 11:33:13 -07003141 * Gets and returns in a string the cipher negotiated for the SSL session.
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003142 */
3143static jstring NativeCrypto_SSL_SESSION_cipher(JNIEnv* env, jclass, jint ssl_session_address) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07003144 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003145 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher", ssl_session);
Brian Carlstrom6df63392010-05-18 11:33:13 -07003146 if (ssl_session == NULL) {
3147 return NULL;
3148 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003149 const SSL_CIPHER* cipher = ssl_session->cipher;
3150 const char* name = SSL_CIPHER_get_name(cipher);
3151 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_cipher => %s", ssl_session, name);
3152 return env->NewStringUTF(name);
3153}
3154
3155/**
Brian Carlstrom4559b1d2010-07-22 16:33:48 -07003156 * Gets and returns in a string the compression method negotiated for the SSL session.
3157 */
3158static jstring NativeCrypto_SSL_SESSION_compress_meth(JNIEnv* env, jclass,
3159 jint ssl_ctx_address,
3160 jint ssl_session_address) {
3161 SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
3162 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
3163 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_compress_meth ssl_ctx=%p",
3164 ssl_session, ssl_ctx);
3165 if (ssl_ctx == NULL || ssl_session == NULL) {
3166 return NULL;
3167 }
3168
3169 int compress_meth = ssl_session->compress_meth;
3170 if (compress_meth == 0) {
3171 const char* name = "NULL";
3172 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_compress_meth => %s", ssl_session, name);
3173 return env->NewStringUTF(name);
3174 }
3175
3176 int num_comp_methods = sk_SSL_COMP_num(ssl_ctx->comp_methods);
3177 for (int i = 0; i < num_comp_methods; i++) {
3178 SSL_COMP* comp = sk_SSL_COMP_value(ssl_ctx->comp_methods, i);
3179 if (comp->id != compress_meth) {
3180 continue;
3181 }
3182 const char* name = ((comp->method && comp->method->type == NID_zlib_compression)
3183 ? SN_zlib_compression
3184 : (comp->name ? comp->name : "UNKNOWN"));
3185 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_compress_meth => %s", ssl_session, name);
3186 return env->NewStringUTF(name);
3187 }
3188 throwSSLExceptionStr(env, "Unknown compression method");
3189 return NULL;
3190}
3191
3192/**
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003193 * Frees the SSL session.
3194 */
Brian Carlstrom6df63392010-05-18 11:33:13 -07003195static void NativeCrypto_SSL_SESSION_free(JNIEnv* env, jclass, jint ssl_session_address) {
3196 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003197 JNI_TRACE("ssl_session=%p NativeCrypto_SSL_SESSION_free", ssl_session);
Brian Carlstrom6df63392010-05-18 11:33:13 -07003198 if (ssl_session == NULL) {
3199 return;
3200 }
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003201 SSL_SESSION_free(ssl_session);
3202}
3203
3204
3205/**
3206 * Serializes the native state of the session (ID, cipher, and keys but
3207 * not certificates). Returns a byte[] containing the DER-encoded state.
3208 * See apache mod_ssl.
3209 */
3210static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jint ssl_session_address) {
Brian Carlstrom6df63392010-05-18 11:33:13 -07003211 SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003212 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
3213 if (ssl_session == NULL) {
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003214 return NULL;
3215 }
3216
3217 // Compute the size of the DER data
3218 int size = i2d_SSL_SESSION(ssl_session, NULL);
3219 if (size == 0) {
3220 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => NULL", ssl_session);
3221 return NULL;
3222 }
3223
Brian Carlstromef628d12010-07-19 13:52:03 -07003224 jbyteArray javaBytes = env->NewByteArray(size);
3225 if (javaBytes != NULL) {
3226 ScopedByteArrayRW bytes(env, javaBytes);
3227 if (bytes.get() == NULL) {
Brian Carlstrom059dbc02010-07-08 14:44:44 -07003228 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => threw exception",
3229 ssl_session);
Elliott Hughes64101122010-07-12 09:53:54 -07003230 return NULL;
3231 }
Brian Carlstromef628d12010-07-19 13:52:03 -07003232 unsigned char* ucp = reinterpret_cast<unsigned char*>(bytes.get());
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003233 i2d_SSL_SESSION(ssl_session, &ucp);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003234 }
3235
3236 JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION => size=%d", ssl_session, size);
Brian Carlstromef628d12010-07-19 13:52:03 -07003237 return javaBytes;
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003238}
3239
3240/**
3241 * Deserialize the session.
3242 */
Brian Carlstromef628d12010-07-19 13:52:03 -07003243static jint NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaBytes) {
3244 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION bytes=%p", javaBytes);
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003245
Brian Carlstromef628d12010-07-19 13:52:03 -07003246 ScopedByteArrayRO bytes(env, javaBytes);
3247 if (bytes.get() == NULL) {
Elliott Hughes64101122010-07-12 09:53:54 -07003248 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => threw exception");
3249 return 0;
3250 }
Brian Carlstromef628d12010-07-19 13:52:03 -07003251 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(bytes.get());
3252 SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, bytes.size());
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003253
3254 JNI_TRACE("NativeCrypto_d2i_SSL_SESSION => %p", ssl_session);
3255 return static_cast<jint>(reinterpret_cast<uintptr_t>(ssl_session));
3256}
3257
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003258#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
3259#define SSL_CALLBACKS "Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$SSLHandshakeCallbacks;"
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003260static JNINativeMethod sNativeCryptoMethods[] = {
Elliott Hughese22935d2010-08-12 17:27:27 -07003261 NATIVE_METHOD(NativeCrypto, clinit, "()V"),
3262 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)I"),
3263 NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_RSA, "([B[B[B[B[B)I"),
3264 NATIVE_METHOD(NativeCrypto, EVP_PKEY_free, "(I)V"),
Brian Carlstroma3de55d2010-09-16 01:32:17 -07003265 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_create, "()I"),
3266 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_destroy, "(I)V"),
3267 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_copy, "(I)I"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003268 NATIVE_METHOD(NativeCrypto, EVP_DigestFinal, "(I[BI)I"),
3269 NATIVE_METHOD(NativeCrypto, EVP_DigestInit, "(ILjava/lang/String;)V"),
Brian Carlstroma3de55d2010-09-16 01:32:17 -07003270 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_block_size, "(I)I"),
3271 NATIVE_METHOD(NativeCrypto, EVP_MD_CTX_size, "(I)I"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003272 NATIVE_METHOD(NativeCrypto, EVP_DigestUpdate, "(I[BII)V"),
3273 NATIVE_METHOD(NativeCrypto, EVP_VerifyInit, "(ILjava/lang/String;)V"),
3274 NATIVE_METHOD(NativeCrypto, EVP_VerifyUpdate, "(I[BII)V"),
3275 NATIVE_METHOD(NativeCrypto, EVP_VerifyFinal, "(I[BIII)I"),
3276 NATIVE_METHOD(NativeCrypto, verifySignature, "([B[BLjava/lang/String;[B[B)I"),
3277 NATIVE_METHOD(NativeCrypto, RAND_seed, "([B)V"),
3278 NATIVE_METHOD(NativeCrypto, RAND_load_file, "(Ljava/lang/String;J)I"),
3279 NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()I"),
3280 NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(I)V"),
3281 NATIVE_METHOD(NativeCrypto, SSL_new, "(I)I"),
3282 NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(I[B)V"),
3283 NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(I[[B)V"),
3284 NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(I)V"),
3285 NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(I[[B)V"),
3286 NATIVE_METHOD(NativeCrypto, SSL_get_mode, "(I)J"),
3287 NATIVE_METHOD(NativeCrypto, SSL_set_mode, "(IJ)J"),
3288 NATIVE_METHOD(NativeCrypto, SSL_clear_mode, "(IJ)J"),
3289 NATIVE_METHOD(NativeCrypto, SSL_get_options, "(I)J"),
3290 NATIVE_METHOD(NativeCrypto, SSL_set_options, "(IJ)J"),
3291 NATIVE_METHOD(NativeCrypto, SSL_clear_options, "(IJ)J"),
3292 NATIVE_METHOD(NativeCrypto, SSL_set_cipher_lists, "(I[Ljava/lang/String;)V"),
3293 NATIVE_METHOD(NativeCrypto, SSL_set_verify, "(II)V"),
3294 NATIVE_METHOD(NativeCrypto, SSL_set_session, "(II)V"),
3295 NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(IZ)V"),
3296 NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(ILjava/lang/String;)V"),
3297 NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(I)Ljava/lang/String;"),
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003298 NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "IZ)I"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003299 NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(I)V"),
3300 NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(I)[[B"),
Brian Carlstromdf349b32010-09-13 22:04:32 -07003301 NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(I)[[B"),
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003302 NATIVE_METHOD(NativeCrypto, SSL_read_byte, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "I)I"),
3303 NATIVE_METHOD(NativeCrypto, SSL_read, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"),
3304 NATIVE_METHOD(NativeCrypto, SSL_write_byte, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "I)V"),
3305 NATIVE_METHOD(NativeCrypto, SSL_write, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "[BII)V"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003306 NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(I)V"),
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003307 NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(I" FILE_DESCRIPTOR SSL_CALLBACKS ")V"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003308 NATIVE_METHOD(NativeCrypto, SSL_free, "(I)V"),
3309 NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(I)[B"),
Elliott Hughese22935d2010-08-12 17:27:27 -07003310 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(I)J"),
3311 NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_version, "(I)Ljava/lang/String;"),
3312 NATIVE_METHOD(NativeCrypto, SSL_SESSION_cipher, "(I)Ljava/lang/String;"),
3313 NATIVE_METHOD(NativeCrypto, SSL_SESSION_compress_meth, "(II)Ljava/lang/String;"),
3314 NATIVE_METHOD(NativeCrypto, SSL_SESSION_free, "(I)V"),
3315 NATIVE_METHOD(NativeCrypto, i2d_SSL_SESSION, "(I)[B"),
3316 NATIVE_METHOD(NativeCrypto, d2i_SSL_SESSION, "([B)I"),
Brian Carlstrom0348e622010-02-10 22:56:47 -08003317};
3318
Elliott Hughesc08f9fb2010-04-16 17:44:12 -07003319int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
Brian Carlstrombcfb3252010-05-02 11:27:52 -07003320 JNI_TRACE("register_org_apache_harmony_xnet_provider_jsse_NativeCrypto");
Brian Carlstrom3e24c532010-05-06 00:23:21 -07003321 // Register org.apache.harmony.xnet.provider.jsse.NativeCrypto methods
Brian Carlstromdf9c0902010-09-30 19:22:21 -07003322 return jniRegisterNativeMethods(env,
3323 "org/apache/harmony/xnet/provider/jsse/NativeCrypto",
3324 sNativeCryptoMethods,
3325 NELEM(sNativeCryptoMethods));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08003326}