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