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