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