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