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 "cutils/log.h" 51 #include "JNIHelp.h" 52 #include "JniConstants.h" 53 #include "JniException.h" 54 #include "NetFd.h" 55 #include "ScopedLocalRef.h" 56 #include "ScopedPrimitiveArray.h" 57 #include "ScopedUtfChars.h" 58 #include "UniquePtr.h" 59 60 #undef WITH_JNI_TRACE 61 #undef WITH_JNI_TRACE_DATA 62 63 /* 64 * How to use this for debugging with Wireshark: 65 * 66 * 1. Pull lines from logcat to a file that looks like (without quotes): 67 * "RSA Session-ID:... Master-Key:..." <CR> 68 * "RSA Session-ID:... Master-Key:..." <CR> 69 * <etc> 70 * 2. Start Wireshark 71 * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in 72 * the file you put the lines in above. 73 * 4. Follow the stream that corresponds to the desired "Session-ID" in 74 * the Server Hello. 75 */ 76 #undef WITH_JNI_TRACE_KEYS 77 78 #ifdef WITH_JNI_TRACE 79 #define JNI_TRACE(...) \ 80 ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__)); \ 81 /* 82 ((void)printf("I/" LOG_TAG "-jni:")); \ 83 ((void)printf(__VA_ARGS__)); \ 84 ((void)printf("\n")) 85 */ 86 #else 87 #define JNI_TRACE(...) ((void)0) 88 #endif 89 // don't overwhelm logcat 90 #define WITH_JNI_TRACE_DATA_CHUNK_SIZE 512 91 92 static JavaVM* gJavaVM; 93 static jclass openSslOutputStreamClass; 94 95 static jclass byteArrayClass; 96 static jclass calendarClass; 97 static jclass objectClass; 98 static jclass objectArrayClass; 99 static jclass integerClass; 100 static jclass inputStreamClass; 101 static jclass outputStreamClass; 102 static jclass stringClass; 103 104 static jmethodID calendar_setMethod; 105 static jmethodID inputStream_readMethod; 106 static jmethodID integer_valueOfMethod; 107 static jmethodID openSslInputStream_readLineMethod; 108 static jmethodID outputStream_writeMethod; 109 static jmethodID outputStream_flushMethod; 110 111 struct OPENSSL_Delete { 112 void operator()(void* p) const { 113 OPENSSL_free(p); 114 } 115 }; 116 typedef UniquePtr<unsigned char, OPENSSL_Delete> Unique_OPENSSL_str; 117 118 struct BIO_Delete { 119 void operator()(BIO* p) const { 120 BIO_free(p); 121 } 122 }; 123 typedef UniquePtr<BIO, BIO_Delete> Unique_BIO; 124 125 struct BIGNUM_Delete { 126 void operator()(BIGNUM* p) const { 127 BN_free(p); 128 } 129 }; 130 typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM; 131 132 struct ASN1_INTEGER_Delete { 133 void operator()(ASN1_INTEGER* p) const { 134 ASN1_INTEGER_free(p); 135 } 136 }; 137 typedef UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> Unique_ASN1_INTEGER; 138 139 struct DH_Delete { 140 void operator()(DH* p) const { 141 DH_free(p); 142 } 143 }; 144 typedef UniquePtr<DH, DH_Delete> Unique_DH; 145 146 struct DSA_Delete { 147 void operator()(DSA* p) const { 148 DSA_free(p); 149 } 150 }; 151 typedef UniquePtr<DSA, DSA_Delete> Unique_DSA; 152 153 struct EC_GROUP_Delete { 154 void operator()(EC_GROUP* p) const { 155 EC_GROUP_clear_free(p); 156 } 157 }; 158 typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP; 159 160 struct EC_POINT_Delete { 161 void operator()(EC_POINT* p) const { 162 EC_POINT_clear_free(p); 163 } 164 }; 165 typedef UniquePtr<EC_POINT, EC_POINT_Delete> Unique_EC_POINT; 166 167 struct EC_KEY_Delete { 168 void operator()(EC_KEY* p) const { 169 EC_KEY_free(p); 170 } 171 }; 172 typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY; 173 174 struct EVP_MD_CTX_Delete { 175 void operator()(EVP_MD_CTX* p) const { 176 EVP_MD_CTX_destroy(p); 177 } 178 }; 179 typedef UniquePtr<EVP_MD_CTX, EVP_MD_CTX_Delete> Unique_EVP_MD_CTX; 180 181 struct EVP_CIPHER_CTX_Delete { 182 void operator()(EVP_CIPHER_CTX* p) const { 183 EVP_CIPHER_CTX_cleanup(p); 184 } 185 }; 186 typedef UniquePtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Delete> Unique_EVP_CIPHER_CTX; 187 188 struct EVP_PKEY_Delete { 189 void operator()(EVP_PKEY* p) const { 190 EVP_PKEY_free(p); 191 } 192 }; 193 typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; 194 195 struct PKCS8_PRIV_KEY_INFO_Delete { 196 void operator()(PKCS8_PRIV_KEY_INFO* p) const { 197 PKCS8_PRIV_KEY_INFO_free(p); 198 } 199 }; 200 typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO; 201 202 struct RSA_Delete { 203 void operator()(RSA* p) const { 204 RSA_free(p); 205 } 206 }; 207 typedef UniquePtr<RSA, RSA_Delete> Unique_RSA; 208 209 struct ASN1_BIT_STRING_Delete { 210 void operator()(ASN1_BIT_STRING* p) const { 211 ASN1_BIT_STRING_free(p); 212 } 213 }; 214 typedef UniquePtr<ASN1_BIT_STRING, ASN1_BIT_STRING_Delete> Unique_ASN1_BIT_STRING; 215 216 struct ASN1_OBJECT_Delete { 217 void operator()(ASN1_OBJECT* p) const { 218 ASN1_OBJECT_free(p); 219 } 220 }; 221 typedef UniquePtr<ASN1_OBJECT, ASN1_OBJECT_Delete> Unique_ASN1_OBJECT; 222 223 struct ASN1_GENERALIZEDTIME_Delete { 224 void operator()(ASN1_GENERALIZEDTIME* p) const { 225 ASN1_GENERALIZEDTIME_free(p); 226 } 227 }; 228 typedef UniquePtr<ASN1_GENERALIZEDTIME, ASN1_GENERALIZEDTIME_Delete> Unique_ASN1_GENERALIZEDTIME; 229 230 struct SSL_Delete { 231 void operator()(SSL* p) const { 232 SSL_free(p); 233 } 234 }; 235 typedef UniquePtr<SSL, SSL_Delete> Unique_SSL; 236 237 struct SSL_CTX_Delete { 238 void operator()(SSL_CTX* p) const { 239 SSL_CTX_free(p); 240 } 241 }; 242 typedef UniquePtr<SSL_CTX, SSL_CTX_Delete> Unique_SSL_CTX; 243 244 struct X509_Delete { 245 void operator()(X509* p) const { 246 X509_free(p); 247 } 248 }; 249 typedef UniquePtr<X509, X509_Delete> Unique_X509; 250 251 class X509Chain { 252 public: 253 X509Chain(size_t n) : x509s_(n) {} 254 255 ~X509Chain() { 256 for (const auto& x509 : x509s_) { 257 X509_free(x509); 258 } 259 } 260 261 X509*& operator[](size_t n) { 262 return x509s_[n]; 263 } 264 265 X509* operator[](size_t n) const { 266 return x509s_[n]; 267 } 268 269 X509* release(size_t i) { 270 X509* x = x509s_[i]; 271 x509s_[i] = NULL; 272 return x; 273 } 274 275 private: 276 std::vector<X509*> x509s_; 277 }; 278 279 struct X509_NAME_Delete { 280 void operator()(X509_NAME* p) const { 281 X509_NAME_free(p); 282 } 283 }; 284 typedef UniquePtr<X509_NAME, X509_NAME_Delete> Unique_X509_NAME; 285 286 struct PKCS7_Delete { 287 void operator()(PKCS7* p) const { 288 PKCS7_free(p); 289 } 290 }; 291 typedef UniquePtr<PKCS7, PKCS7_Delete> Unique_PKCS7; 292 293 struct sk_SSL_CIPHER_Delete { 294 void operator()(STACK_OF(SSL_CIPHER)* p) const { 295 // We don't own SSL_CIPHER references, so no need for pop_free 296 sk_SSL_CIPHER_free(p); 297 } 298 }; 299 typedef UniquePtr<STACK_OF(SSL_CIPHER), sk_SSL_CIPHER_Delete> Unique_sk_SSL_CIPHER; 300 301 struct sk_X509_Delete { 302 void operator()(STACK_OF(X509)* p) const { 303 sk_X509_pop_free(p, X509_free); 304 } 305 }; 306 typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509; 307 308 struct sk_X509_NAME_Delete { 309 void operator()(STACK_OF(X509_NAME)* p) const { 310 sk_X509_NAME_pop_free(p, X509_NAME_free); 311 } 312 }; 313 typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME; 314 315 struct sk_ASN1_OBJECT_Delete { 316 void operator()(STACK_OF(ASN1_OBJECT)* p) const { 317 sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free); 318 } 319 }; 320 typedef UniquePtr<STACK_OF(ASN1_OBJECT), sk_ASN1_OBJECT_Delete> Unique_sk_ASN1_OBJECT; 321 322 struct sk_GENERAL_NAME_Delete { 323 void operator()(STACK_OF(GENERAL_NAME)* p) const { 324 sk_GENERAL_NAME_pop_free(p, GENERAL_NAME_free); 325 } 326 }; 327 typedef UniquePtr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_Delete> Unique_sk_GENERAL_NAME; 328 329 /** 330 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument 331 * on failure. This means we need to tell our scoped pointers when we've transferred ownership, 332 * without triggering a warning by not using the result of release(). 333 */ 334 #define OWNERSHIP_TRANSFERRED(obj) \ 335 typeof (obj.release()) _dummy __attribute__((unused)) = obj.release() 336 337 /** 338 * Frees the SSL error state. 339 * 340 * OpenSSL keeps an "error stack" per thread, and given that this code 341 * can be called from arbitrary threads that we don't keep track of, 342 * we err on the side of freeing the error state promptly (instead of, 343 * say, at thread death). 344 */ 345 static void freeOpenSslErrorState(void) { 346 ERR_clear_error(); 347 ERR_remove_state(0); 348 } 349 350 /** 351 * Throws a OutOfMemoryError with the given string as a message. 352 */ 353 static void jniThrowOutOfMemory(JNIEnv* env, const char* message) { 354 jniThrowException(env, "java/lang/OutOfMemoryError", message); 355 } 356 357 /** 358 * Throws a BadPaddingException with the given string as a message. 359 */ 360 static void throwBadPaddingException(JNIEnv* env, const char* message) { 361 JNI_TRACE("throwBadPaddingException %s", message); 362 jniThrowException(env, "javax/crypto/BadPaddingException", message); 363 } 364 365 /** 366 * Throws a SignatureException with the given string as a message. 367 */ 368 static void throwSignatureException(JNIEnv* env, const char* message) { 369 JNI_TRACE("throwSignatureException %s", message); 370 jniThrowException(env, "java/security/SignatureException", message); 371 } 372 373 /** 374 * Throws a InvalidKeyException with the given string as a message. 375 */ 376 static void throwInvalidKeyException(JNIEnv* env, const char* message) { 377 JNI_TRACE("throwInvalidKeyException %s", message); 378 jniThrowException(env, "java/security/InvalidKeyException", message); 379 } 380 381 /** 382 * Throws a SignatureException with the given string as a message. 383 */ 384 static void throwIllegalBlockSizeException(JNIEnv* env, const char* message) { 385 JNI_TRACE("throwIllegalBlockSizeException %s", message); 386 jniThrowException(env, "javax/crypto/IllegalBlockSizeException", message); 387 } 388 389 /** 390 * Throws a NoSuchAlgorithmException with the given string as a message. 391 */ 392 static void throwNoSuchAlgorithmException(JNIEnv* env, const char* message) { 393 JNI_TRACE("throwUnknownAlgorithmException %s", message); 394 jniThrowException(env, "java/security/NoSuchAlgorithmException", message); 395 } 396 397 static void throwForAsn1Error(JNIEnv* env, int reason, const char *message) { 398 switch (reason) { 399 case ASN1_R_UNABLE_TO_DECODE_RSA_KEY: 400 case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY: 401 case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE: 402 case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE: 403 case ASN1_R_WRONG_PUBLIC_KEY_TYPE: 404 throwInvalidKeyException(env, message); 405 break; 406 case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM: 407 throwNoSuchAlgorithmException(env, message); 408 break; 409 default: 410 jniThrowRuntimeException(env, message); 411 break; 412 } 413 } 414 415 static void throwForEvpError(JNIEnv* env, int reason, const char *message) { 416 switch (reason) { 417 case EVP_R_BAD_DECRYPT: 418 throwBadPaddingException(env, message); 419 break; 420 case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: 421 case EVP_R_WRONG_FINAL_BLOCK_LENGTH: 422 throwIllegalBlockSizeException(env, message); 423 break; 424 case EVP_R_BAD_KEY_LENGTH: 425 case EVP_R_BN_DECODE_ERROR: 426 case EVP_R_BN_PUBKEY_ERROR: 427 case EVP_R_INVALID_KEY_LENGTH: 428 case EVP_R_MISSING_PARAMETERS: 429 case EVP_R_UNSUPPORTED_KEY_SIZE: 430 case EVP_R_UNSUPPORTED_KEYLENGTH: 431 throwInvalidKeyException(env, message); 432 break; 433 case EVP_R_WRONG_PUBLIC_KEY_TYPE: 434 throwSignatureException(env, message); 435 break; 436 case EVP_R_UNSUPPORTED_ALGORITHM: 437 throwNoSuchAlgorithmException(env, message); 438 break; 439 default: 440 jniThrowRuntimeException(env, message); 441 break; 442 } 443 } 444 445 static void throwForRsaError(JNIEnv* env, int reason, const char *message) { 446 switch (reason) { 447 case RSA_R_BLOCK_TYPE_IS_NOT_01: 448 case RSA_R_BLOCK_TYPE_IS_NOT_02: 449 throwBadPaddingException(env, message); 450 break; 451 case RSA_R_ALGORITHM_MISMATCH: 452 case RSA_R_BAD_SIGNATURE: 453 case RSA_R_DATA_GREATER_THAN_MOD_LEN: 454 case RSA_R_DATA_TOO_LARGE_FOR_MODULUS: 455 case RSA_R_INVALID_MESSAGE_LENGTH: 456 case RSA_R_WRONG_SIGNATURE_LENGTH: 457 throwSignatureException(env, message); 458 break; 459 case RSA_R_UNKNOWN_ALGORITHM_TYPE: 460 throwNoSuchAlgorithmException(env, message); 461 break; 462 case RSA_R_MODULUS_TOO_LARGE: 463 case RSA_R_NO_PUBLIC_EXPONENT: 464 throwInvalidKeyException(env, message); 465 break; 466 default: 467 jniThrowRuntimeException(env, message); 468 break; 469 } 470 } 471 472 static void throwForX509Error(JNIEnv* env, int reason, const char *message) { 473 switch (reason) { 474 case X509_R_UNSUPPORTED_ALGORITHM: 475 throwNoSuchAlgorithmException(env, message); 476 break; 477 default: 478 jniThrowRuntimeException(env, message); 479 break; 480 } 481 } 482 483 /* 484 * Checks this thread's OpenSSL error queue and throws a RuntimeException if 485 * necessary. 486 * 487 * @return true if an exception was thrown, false if not. 488 */ 489 static bool throwExceptionIfNecessary(JNIEnv* env, const char* location __attribute__ ((unused))) { 490 const char* file; 491 int line; 492 const char* data; 493 int flags; 494 unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags); 495 int result = false; 496 497 if (error != 0) { 498 char message[256]; 499 ERR_error_string_n(error, message, sizeof(message)); 500 int library = ERR_GET_LIB(error); 501 int reason = ERR_GET_REASON(error); 502 JNI_TRACE("OpenSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s", 503 location, error, library, reason, file, line, message, 504 (flags & ERR_TXT_STRING) ? data : "(no data)"); 505 switch (library) { 506 case ERR_LIB_RSA: 507 throwForRsaError(env, reason, message); 508 break; 509 case ERR_LIB_ASN1: 510 throwForAsn1Error(env, reason, message); 511 break; 512 case ERR_LIB_EVP: 513 throwForEvpError(env, reason, message); 514 break; 515 case ERR_LIB_X509: 516 throwForX509Error(env, reason, message); 517 break; 518 case ERR_LIB_DSA: 519 throwInvalidKeyException(env, message); 520 break; 521 default: 522 jniThrowRuntimeException(env, message); 523 break; 524 } 525 result = true; 526 } 527 528 freeOpenSslErrorState(); 529 return result; 530 } 531 532 /** 533 * Throws an SocketTimeoutException with the given string as a message. 534 */ 535 static void throwSocketTimeoutException(JNIEnv* env, const char* message) { 536 JNI_TRACE("throwSocketTimeoutException %s", message); 537 jniThrowException(env, "java/net/SocketTimeoutException", message); 538 } 539 540 /** 541 * Throws a javax.net.ssl.SSLException with the given string as a message. 542 */ 543 static void throwSSLExceptionStr(JNIEnv* env, const char* message) { 544 JNI_TRACE("throwSSLExceptionStr %s", message); 545 jniThrowException(env, "javax/net/ssl/SSLException", message); 546 } 547 548 /** 549 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message. 550 */ 551 static void throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) { 552 JNI_TRACE("throwSSLProtocolExceptionStr %s", message); 553 jniThrowException(env, "javax/net/ssl/SSLProtocolException", message); 554 } 555 556 /** 557 * Throws an SSLException with a message constructed from the current 558 * SSL errors. This will also log the errors. 559 * 560 * @param env the JNI environment 561 * @param ssl the possibly NULL SSL 562 * @param sslErrorCode error code returned from SSL_get_error() or 563 * SSL_ERROR_NONE to probe with ERR_get_error 564 * @param message null-ok; general error message 565 */ 566 static void throwSSLExceptionWithSslErrors( 567 JNIEnv* env, SSL* ssl, int sslErrorCode, const char* message) { 568 569 if (message == NULL) { 570 message = "SSL error"; 571 } 572 573 // First consult the SSL error code for the general message. 574 const char* sslErrorStr = NULL; 575 switch (sslErrorCode) { 576 case SSL_ERROR_NONE: 577 if (ERR_peek_error() == 0) { 578 sslErrorStr = "OK"; 579 } else { 580 sslErrorStr = ""; 581 } 582 break; 583 case SSL_ERROR_SSL: 584 sslErrorStr = "Failure in SSL library, usually a protocol error"; 585 break; 586 case SSL_ERROR_WANT_READ: 587 sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this."; 588 break; 589 case SSL_ERROR_WANT_WRITE: 590 sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this."; 591 break; 592 case SSL_ERROR_WANT_X509_LOOKUP: 593 sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this."; 594 break; 595 case SSL_ERROR_SYSCALL: 596 sslErrorStr = "I/O error during system call"; 597 break; 598 case SSL_ERROR_ZERO_RETURN: 599 sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this."; 600 break; 601 case SSL_ERROR_WANT_CONNECT: 602 sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this."; 603 break; 604 case SSL_ERROR_WANT_ACCEPT: 605 sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this."; 606 break; 607 default: 608 sslErrorStr = "Unknown SSL error"; 609 } 610 611 // Prepend either our explicit message or a default one. 612 char* str; 613 if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) { 614 // problem with asprintf, just throw argument message, log everything 615 throwSSLExceptionStr(env, message); 616 ALOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr); 617 freeOpenSslErrorState(); 618 return; 619 } 620 621 char* allocStr = str; 622 623 // For protocol errors, SSL might have more information. 624 if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) { 625 // Append each error as an additional line to the message. 626 for (;;) { 627 char errStr[256]; 628 const char* file; 629 int line; 630 const char* data; 631 int flags; 632 unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags); 633 if (err == 0) { 634 break; 635 } 636 637 ERR_error_string_n(err, errStr, sizeof(errStr)); 638 639 int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)", 640 (allocStr == NULL) ? "" : allocStr, 641 errStr, 642 file, 643 line, 644 (flags & ERR_TXT_STRING) ? data : "(no data)", 645 flags); 646 647 if (ret < 0) { 648 break; 649 } 650 651 free(allocStr); 652 allocStr = str; 653 } 654 // For errors during system calls, errno might be our friend. 655 } else if (sslErrorCode == SSL_ERROR_SYSCALL) { 656 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) { 657 free(allocStr); 658 allocStr = str; 659 } 660 // If the error code is invalid, print it. 661 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) { 662 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) { 663 free(allocStr); 664 allocStr = str; 665 } 666 } 667 668 if (sslErrorCode == SSL_ERROR_SSL) { 669 throwSSLProtocolExceptionStr(env, allocStr); 670 } else { 671 throwSSLExceptionStr(env, allocStr); 672 } 673 674 ALOGV("%s", allocStr); 675 free(allocStr); 676 freeOpenSslErrorState(); 677 } 678 679 /** 680 * Helper function that grabs the casts an ssl pointer and then checks for nullness. 681 * If this function returns NULL and <code>throwIfNull</code> is 682 * passed as <code>true</code>, then this function will call 683 * <code>throwSSLExceptionStr</code> before returning, so in this case of 684 * NULL, a caller of this function should simply return and allow JNI 685 * to do its thing. 686 * 687 * @param env the JNI environment 688 * @param ssl_address; the ssl_address pointer as an integer 689 * @param throwIfNull whether to throw if the SSL pointer is NULL 690 * @returns the pointer, which may be NULL 691 */ 692 static SSL_CTX* to_SSL_CTX(JNIEnv* env, jlong ssl_ctx_address, bool throwIfNull) { 693 SSL_CTX* ssl_ctx = reinterpret_cast<SSL_CTX*>(static_cast<uintptr_t>(ssl_ctx_address)); 694 if ((ssl_ctx == NULL) && throwIfNull) { 695 JNI_TRACE("ssl_ctx == null"); 696 jniThrowNullPointerException(env, "ssl_ctx == null"); 697 } 698 return ssl_ctx; 699 } 700 701 static SSL* to_SSL(JNIEnv* env, jlong ssl_address, bool throwIfNull) { 702 SSL* ssl = reinterpret_cast<SSL*>(static_cast<uintptr_t>(ssl_address)); 703 if ((ssl == NULL) && throwIfNull) { 704 JNI_TRACE("ssl == null"); 705 jniThrowNullPointerException(env, "ssl == null"); 706 } 707 return ssl; 708 } 709 710 static SSL_SESSION* to_SSL_SESSION(JNIEnv* env, jlong ssl_session_address, bool throwIfNull) { 711 SSL_SESSION* ssl_session 712 = reinterpret_cast<SSL_SESSION*>(static_cast<uintptr_t>(ssl_session_address)); 713 if ((ssl_session == NULL) && throwIfNull) { 714 JNI_TRACE("ssl_session == null"); 715 jniThrowNullPointerException(env, "ssl_session == null"); 716 } 717 return ssl_session; 718 } 719 720 /** 721 * Converts a Java byte[] to an OpenSSL BIGNUM, allocating the BIGNUM on the 722 * fly. Returns true on success. If the return value is false, there is a 723 * pending exception. 724 */ 725 static bool arrayToBignum(JNIEnv* env, jbyteArray source, BIGNUM** dest) { 726 JNI_TRACE("arrayToBignum(%p, %p)", source, *dest); 727 728 ScopedByteArrayRO sourceBytes(env, source); 729 if (sourceBytes.get() == NULL) { 730 JNI_TRACE("arrayToBignum(%p) => NULL", source); 731 return false; 732 } 733 *dest = BN_bin2bn(reinterpret_cast<const unsigned char*>(sourceBytes.get()), 734 sourceBytes.size(), 735 NULL); 736 if (*dest == NULL) { 737 jniThrowRuntimeException(env, "Conversion to BIGNUM failed"); 738 JNI_TRACE("arrayToBignum(%p) => threw exception", source); 739 return false; 740 } 741 742 JNI_TRACE("arrayToBignum(%p) => %p", source, *dest); 743 return true; 744 } 745 746 /** 747 * Converts an OpenSSL BIGNUM to a Java byte[] array. 748 */ 749 static jbyteArray bignumToArray(JNIEnv* env, const BIGNUM* source, const char* sourceName) { 750 JNI_TRACE("bignumToArray(%p, %s)", source, sourceName); 751 752 if (source == NULL) { 753 jniThrowNullPointerException(env, sourceName); 754 return NULL; 755 } 756 757 jbyteArray javaBytes = env->NewByteArray(BN_num_bytes(source) + 1); 758 ScopedByteArrayRW bytes(env, javaBytes); 759 if (bytes.get() == NULL) { 760 JNI_TRACE("bignumToArray(%p, %s) => NULL", source, sourceName); 761 return NULL; 762 } 763 764 unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get()); 765 766 // Set the sign for the Java code. 767 if (BN_is_negative(source)) { 768 *tmp = 0xFF; 769 } else { 770 *tmp = 0x00; 771 } 772 773 if (BN_num_bytes(source) > 0 && BN_bn2bin(source, tmp + 1) <= 0) { 774 throwExceptionIfNecessary(env, "bignumToArray"); 775 return NULL; 776 } 777 778 JNI_TRACE("bignumToArray(%p, %s) => %p", source, sourceName, javaBytes); 779 return javaBytes; 780 } 781 782 /** 783 * Converts various OpenSSL ASN.1 types to a jbyteArray with DER-encoded data 784 * inside. The "i2d_func" function pointer is a function of the "i2d_<TYPE>" 785 * from the OpenSSL ASN.1 API. 786 */ 787 template<typename T, int (*i2d_func)(T*, unsigned char**)> 788 jbyteArray ASN1ToByteArray(JNIEnv* env, T* obj) { 789 if (obj == NULL) { 790 jniThrowNullPointerException(env, "ASN1 input == null"); 791 JNI_TRACE("ASN1ToByteArray(%p) => null input", obj); 792 return NULL; 793 } 794 795 int derLen = i2d_func(obj, NULL); 796 if (derLen < 0) { 797 throwExceptionIfNecessary(env, "ASN1ToByteArray"); 798 JNI_TRACE("ASN1ToByteArray(%p) => measurement failed", obj); 799 return NULL; 800 } 801 802 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(derLen)); 803 if (byteArray.get() == NULL) { 804 JNI_TRACE("ASN1ToByteArray(%p) => creating byte array failed", obj); 805 return NULL; 806 } 807 808 ScopedByteArrayRW bytes(env, byteArray.get()); 809 if (bytes.get() == NULL) { 810 JNI_TRACE("ASN1ToByteArray(%p) => using byte array failed", obj); 811 return NULL; 812 } 813 814 unsigned char* p = reinterpret_cast<unsigned char*>(bytes.get()); 815 int ret = i2d_func(obj, &p); 816 if (ret < 0) { 817 throwExceptionIfNecessary(env, "ASN1ToByteArray"); 818 JNI_TRACE("ASN1ToByteArray(%p) => final conversion failed", obj); 819 return NULL; 820 } 821 822 JNI_TRACE("ASN1ToByteArray(%p) => success (%d bytes written)", obj, ret); 823 return byteArray.release(); 824 } 825 826 template<typename T, T* (*d2i_func)(T**, const unsigned char**, long)> 827 T* ByteArrayToASN1(JNIEnv* env, jbyteArray byteArray) { 828 ScopedByteArrayRO bytes(env, byteArray); 829 if (bytes.get() == NULL) { 830 JNI_TRACE("ByteArrayToASN1(%p) => using byte array failed", byteArray); 831 return 0; 832 } 833 834 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get()); 835 return d2i_func(NULL, &tmp, bytes.size()); 836 } 837 838 /** 839 * Converts ASN.1 BIT STRING to a jbooleanArray. 840 */ 841 jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, ASN1_BIT_STRING* bitStr) { 842 int size = bitStr->length * 8; 843 if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) { 844 size -= bitStr->flags & 0x07; 845 } 846 847 ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size)); 848 if (bitsRef.get() == NULL) { 849 return NULL; 850 } 851 852 ScopedBooleanArrayRW bitsArray(env, bitsRef.get()); 853 for (int i = 0; i < static_cast<int>(bitsArray.size()); i++) { 854 bitsArray[i] = ASN1_BIT_STRING_get_bit(bitStr, i); 855 } 856 857 return bitsRef.release(); 858 } 859 860 /** 861 * To avoid the round-trip to ASN.1 and back in X509_dup, we just up the reference count. 862 */ 863 static X509* X509_dup_nocopy(X509* x509) { 864 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); 865 return x509; 866 } 867 868 /** 869 * BIO for InputStream 870 */ 871 class BIO_Stream { 872 public: 873 BIO_Stream(jobject stream) : 874 mEof(false) { 875 JNIEnv* env = getEnv(); 876 mStream = env->NewGlobalRef(stream); 877 } 878 879 ~BIO_Stream() { 880 JNIEnv* env = getEnv(); 881 882 env->DeleteGlobalRef(mStream); 883 } 884 885 bool isEof() const { 886 JNI_TRACE("isEof? %s", mEof ? "yes" : "no"); 887 return mEof; 888 } 889 890 int flush() { 891 JNIEnv* env = getEnv(); 892 if (env == NULL) { 893 return -1; 894 } 895 896 env->CallVoidMethod(mStream, outputStream_flushMethod); 897 if (env->ExceptionCheck()) { 898 return -1; 899 } 900 901 return 1; 902 } 903 904 protected: 905 jobject getStream() { 906 return mStream; 907 } 908 909 void setEof(bool eof) { 910 mEof = eof; 911 } 912 913 JNIEnv* getEnv() { 914 JNIEnv* env; 915 916 if (gJavaVM->AttachCurrentThread(&env, NULL) < 0) { 917 return NULL; 918 } 919 920 return env; 921 } 922 923 private: 924 jobject mStream; 925 bool mEof; 926 }; 927 928 class BIO_InputStream : public BIO_Stream { 929 public: 930 BIO_InputStream(jobject stream) : 931 BIO_Stream(stream) { 932 } 933 934 int read(char *buf, int len) { 935 return read_internal(buf, len, inputStream_readMethod); 936 } 937 938 int gets(char *buf, int len) { 939 if (len > PEM_LINE_LENGTH) { 940 len = PEM_LINE_LENGTH; 941 } 942 943 int read = read_internal(buf, len - 1, openSslInputStream_readLineMethod); 944 buf[read] = '\0'; 945 JNI_TRACE("BIO::gets \"%s\"", buf); 946 return read; 947 } 948 949 private: 950 int read_internal(char *buf, int len, jmethodID method) { 951 JNIEnv* env = getEnv(); 952 if (env == NULL) { 953 JNI_TRACE("BIO_InputStream::read could not get JNIEnv"); 954 return -1; 955 } 956 957 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len)); 958 if (javaBytes.get() == NULL) { 959 JNI_TRACE("BIO_InputStream::read failed call to NewByteArray"); 960 return -1; 961 } 962 963 jint read = env->CallIntMethod(getStream(), method, javaBytes.get()); 964 if (env->ExceptionCheck()) { 965 JNI_TRACE("BIO_InputStream::read failed call to InputStream#read"); 966 return -1; 967 } 968 969 /* Java uses -1 to indicate EOF condition. */ 970 if (read == -1) { 971 setEof(true); 972 read = 0; 973 } else if (read > 0) { 974 env->GetByteArrayRegion(javaBytes.get(), 0, read, reinterpret_cast<jbyte*>(buf)); 975 } 976 977 return read; 978 } 979 980 public: 981 /** Length of PEM-encoded line (64) plus CR plus NULL */ 982 static const int PEM_LINE_LENGTH = 66; 983 }; 984 985 class BIO_OutputStream : public BIO_Stream { 986 public: 987 BIO_OutputStream(jobject stream) : 988 BIO_Stream(stream) { 989 } 990 991 int write(const char *buf, int len) { 992 JNIEnv* env = getEnv(); 993 if (env == NULL) { 994 JNI_TRACE("BIO_OutputStream::write => could not get JNIEnv"); 995 return -1; 996 } 997 998 ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len)); 999 if (javaBytes.get() == NULL) { 1000 JNI_TRACE("BIO_OutputStream::write => failed call to NewByteArray"); 1001 return -1; 1002 } 1003 1004 env->SetByteArrayRegion(javaBytes.get(), 0, len, reinterpret_cast<const jbyte*>(buf)); 1005 1006 env->CallVoidMethod(getStream(), outputStream_writeMethod, javaBytes.get()); 1007 if (env->ExceptionCheck()) { 1008 JNI_TRACE("BIO_OutputStream::write => failed call to OutputStream#write"); 1009 return -1; 1010 } 1011 1012 return len; 1013 } 1014 }; 1015 1016 static int bio_stream_create(BIO *b) { 1017 b->init = 1; 1018 b->num = 0; 1019 b->ptr = NULL; 1020 b->flags = 0; 1021 return 1; 1022 } 1023 1024 static int bio_stream_destroy(BIO *b) { 1025 if (b == NULL) { 1026 return 0; 1027 } 1028 1029 if (b->ptr != NULL) { 1030 delete static_cast<BIO_Stream*>(b->ptr); 1031 b->ptr = NULL; 1032 } 1033 1034 b->init = 0; 1035 b->flags = 0; 1036 return 1; 1037 } 1038 1039 static int bio_stream_read(BIO *b, char *buf, int len) { 1040 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr); 1041 return stream->read(buf, len); 1042 } 1043 1044 static int bio_stream_write(BIO *b, const char *buf, int len) { 1045 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr); 1046 return stream->write(buf, len); 1047 } 1048 1049 static int bio_stream_puts(BIO *b, const char *buf) { 1050 BIO_OutputStream* stream = static_cast<BIO_OutputStream*>(b->ptr); 1051 return stream->write(buf, strlen(buf)); 1052 } 1053 1054 static int bio_stream_gets(BIO *b, char *buf, int len) { 1055 BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr); 1056 return stream->gets(buf, len); 1057 } 1058 1059 static void bio_stream_assign(BIO *b, BIO_Stream* stream) { 1060 b->ptr = static_cast<void*>(stream); 1061 } 1062 1063 static long bio_stream_ctrl(BIO *b, int cmd, long, void *) { 1064 BIO_Stream* stream = static_cast<BIO_Stream*>(b->ptr); 1065 1066 switch (cmd) { 1067 case BIO_CTRL_EOF: 1068 return stream->isEof() ? 1 : 0; 1069 case BIO_CTRL_FLUSH: 1070 return stream->flush(); 1071 default: 1072 return 0; 1073 } 1074 } 1075 1076 static BIO_METHOD stream_bio_method = { 1077 ( 100 | 0x0400 ), /* source/sink BIO */ 1078 "InputStream/OutputStream BIO", 1079 bio_stream_write, /* bio_write */ 1080 bio_stream_read, /* bio_read */ 1081 bio_stream_puts, /* bio_puts */ 1082 bio_stream_gets, /* bio_gets */ 1083 bio_stream_ctrl, /* bio_ctrl */ 1084 bio_stream_create, /* bio_create */ 1085 bio_stream_destroy, /* bio_free */ 1086 NULL, /* no bio_callback_ctrl */ 1087 }; 1088 1089 /** 1090 * Copied from libnativehelper NetworkUtilites.cpp 1091 */ 1092 static bool setBlocking(int fd, bool blocking) { 1093 int flags = fcntl(fd, F_GETFL); 1094 if (flags == -1) { 1095 return false; 1096 } 1097 1098 if (!blocking) { 1099 flags |= O_NONBLOCK; 1100 } else { 1101 flags &= ~O_NONBLOCK; 1102 } 1103 1104 int rc = fcntl(fd, F_SETFL, flags); 1105 return (rc != -1); 1106 } 1107 1108 /** 1109 * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I 1110 * suppose there are not many other ways to do this on a Linux system (modulo 1111 * isomorphism). 1112 */ 1113 #define MUTEX_TYPE pthread_mutex_t 1114 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) 1115 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) 1116 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) 1117 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) 1118 #define THREAD_ID pthread_self() 1119 #define THROW_SSLEXCEPTION (-2) 1120 #define THROW_SOCKETTIMEOUTEXCEPTION (-3) 1121 #define THROWN_EXCEPTION (-4) 1122 1123 static MUTEX_TYPE* mutex_buf = NULL; 1124 1125 static void locking_function(int mode, int n, const char*, int) { 1126 if (mode & CRYPTO_LOCK) { 1127 MUTEX_LOCK(mutex_buf[n]); 1128 } else { 1129 MUTEX_UNLOCK(mutex_buf[n]); 1130 } 1131 } 1132 1133 static unsigned long id_function(void) { 1134 return ((unsigned long)THREAD_ID); 1135 } 1136 1137 int THREAD_setup(void) { 1138 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()]; 1139 if (!mutex_buf) { 1140 return 0; 1141 } 1142 1143 for (int i = 0; i < CRYPTO_num_locks(); ++i) { 1144 MUTEX_SETUP(mutex_buf[i]); 1145 } 1146 1147 CRYPTO_set_id_callback(id_function); 1148 CRYPTO_set_locking_callback(locking_function); 1149 1150 return 1; 1151 } 1152 1153 int THREAD_cleanup(void) { 1154 if (!mutex_buf) { 1155 return 0; 1156 } 1157 1158 CRYPTO_set_id_callback(NULL); 1159 CRYPTO_set_locking_callback(NULL); 1160 1161 for (int i = 0; i < CRYPTO_num_locks( ); i++) { 1162 MUTEX_CLEANUP(mutex_buf[i]); 1163 } 1164 1165 free(mutex_buf); 1166 mutex_buf = NULL; 1167 1168 return 1; 1169 } 1170 1171 /** 1172 * Initialization phase for every OpenSSL job: Loads the Error strings, the 1173 * crypto algorithms and reset the OpenSSL library 1174 */ 1175 static void NativeCrypto_clinit(JNIEnv*, jclass) 1176 { 1177 SSL_load_error_strings(); 1178 ERR_load_crypto_strings(); 1179 SSL_library_init(); 1180 OpenSSL_add_all_algorithms(); 1181 THREAD_setup(); 1182 } 1183 1184 static void NativeCrypto_ENGINE_load_dynamic(JNIEnv*, jclass) { 1185 JNI_TRACE("ENGINE_load_dynamic()"); 1186 1187 ENGINE_load_dynamic(); 1188 } 1189 1190 static jlong NativeCrypto_ENGINE_by_id(JNIEnv* env, jclass, jstring idJava) { 1191 JNI_TRACE("ENGINE_by_id(%p)", idJava); 1192 1193 ScopedUtfChars id(env, idJava); 1194 if (id.c_str() == NULL) { 1195 JNI_TRACE("ENGINE_by_id(%p) => id == null", idJava); 1196 return 0; 1197 } 1198 JNI_TRACE("ENGINE_by_id(\"%s\")", id.c_str()); 1199 1200 ENGINE* e = ENGINE_by_id(id.c_str()); 1201 if (e == NULL) { 1202 freeOpenSslErrorState(); 1203 } 1204 1205 JNI_TRACE("ENGINE_by_id(\"%s\") => %p", id.c_str(), e); 1206 return reinterpret_cast<uintptr_t>(e); 1207 } 1208 1209 static jint NativeCrypto_ENGINE_add(JNIEnv* env, jclass, jlong engineRef) { 1210 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1211 JNI_TRACE("ENGINE_add(%p)", e); 1212 1213 if (e == NULL) { 1214 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0"); 1215 return 0; 1216 } 1217 1218 int ret = ENGINE_add(e); 1219 1220 /* 1221 * We tolerate errors, because the most likely error is that 1222 * the ENGINE is already in the list. 1223 */ 1224 freeOpenSslErrorState(); 1225 1226 JNI_TRACE("ENGINE_add(%p) => %d", e, ret); 1227 return ret; 1228 } 1229 1230 static jint NativeCrypto_ENGINE_init(JNIEnv* env, jclass, jlong engineRef) { 1231 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1232 JNI_TRACE("ENGINE_init(%p)", e); 1233 1234 if (e == NULL) { 1235 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0"); 1236 return 0; 1237 } 1238 1239 int ret = ENGINE_init(e); 1240 JNI_TRACE("ENGINE_init(%p) => %d", e, ret); 1241 return ret; 1242 } 1243 1244 static jint NativeCrypto_ENGINE_finish(JNIEnv* env, jclass, jlong engineRef) { 1245 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1246 JNI_TRACE("ENGINE_finish(%p)", e); 1247 1248 if (e == NULL) { 1249 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0"); 1250 return 0; 1251 } 1252 1253 int ret = ENGINE_finish(e); 1254 JNI_TRACE("ENGINE_finish(%p) => %d", e, ret); 1255 return ret; 1256 } 1257 1258 static jint NativeCrypto_ENGINE_free(JNIEnv* env, jclass, jlong engineRef) { 1259 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1260 JNI_TRACE("ENGINE_free(%p)", e); 1261 1262 if (e == NULL) { 1263 jniThrowException(env, "java/lang/IllegalArgumentException", "engineRef == 0"); 1264 return 0; 1265 } 1266 1267 int ret = ENGINE_free(e); 1268 JNI_TRACE("ENGINE_free(%p) => %d", e, ret); 1269 return ret; 1270 } 1271 1272 static jlong NativeCrypto_ENGINE_load_private_key(JNIEnv* env, jclass, jlong engineRef, 1273 jstring idJava) { 1274 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1275 JNI_TRACE("ENGINE_load_private_key(%p, %p)", e, idJava); 1276 1277 ScopedUtfChars id(env, idJava); 1278 if (id.c_str() == NULL) { 1279 jniThrowException(env, "java/lang/IllegalArgumentException", "id == NULL"); 1280 return 0; 1281 } 1282 1283 Unique_EVP_PKEY pkey(ENGINE_load_private_key(e, id.c_str(), NULL, NULL)); 1284 if (pkey.get() == NULL) { 1285 throwExceptionIfNecessary(env, "ENGINE_load_private_key"); 1286 return 0; 1287 } 1288 1289 JNI_TRACE("ENGINE_load_private_key(%p, %p) => %p", e, idJava, pkey.get()); 1290 return reinterpret_cast<uintptr_t>(pkey.release()); 1291 } 1292 1293 static jstring NativeCrypto_ENGINE_get_id(JNIEnv* env, jclass, jlong engineRef) 1294 { 1295 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1296 JNI_TRACE("ENGINE_get_id(%p)", e); 1297 1298 if (e == NULL) { 1299 jniThrowNullPointerException(env, "engine == null"); 1300 JNI_TRACE("ENGINE_get_id(%p) => engine == null", e); 1301 return NULL; 1302 } 1303 1304 const char *id = ENGINE_get_id(e); 1305 ScopedLocalRef<jstring> idJava(env, env->NewStringUTF(id)); 1306 1307 JNI_TRACE("ENGINE_get_id(%p) => \"%s\"", e, id); 1308 return idJava.release(); 1309 } 1310 1311 static jint NativeCrypto_ENGINE_ctrl_cmd_string(JNIEnv* env, jclass, jlong engineRef, 1312 jstring cmdJava, jstring argJava, jint cmd_optional) 1313 { 1314 ENGINE* e = reinterpret_cast<ENGINE*>(static_cast<uintptr_t>(engineRef)); 1315 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d)", e, cmdJava, argJava, cmd_optional); 1316 1317 if (e == NULL) { 1318 jniThrowNullPointerException(env, "engine == null"); 1319 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, %p, %p, %d) => engine == null", e, cmdJava, argJava, 1320 cmd_optional); 1321 return 0; 1322 } 1323 1324 ScopedUtfChars cmdChars(env, cmdJava); 1325 if (cmdChars.c_str() == NULL) { 1326 return 0; 1327 } 1328 1329 UniquePtr<ScopedUtfChars> arg; 1330 const char* arg_c_str = NULL; 1331 if (argJava != NULL) { 1332 arg.reset(new ScopedUtfChars(env, argJava)); 1333 arg_c_str = arg->c_str(); 1334 if (arg_c_str == NULL) { 1335 return 0; 1336 } 1337 } 1338 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d)", e, cmdChars.c_str(), arg_c_str, 1339 cmd_optional); 1340 1341 int ret = ENGINE_ctrl_cmd_string(e, cmdChars.c_str(), arg_c_str, cmd_optional); 1342 if (ret != 1) { 1343 throwExceptionIfNecessary(env, "ENGINE_ctrl_cmd_string"); 1344 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => threw error", e, 1345 cmdChars.c_str(), arg_c_str, cmd_optional); 1346 return 0; 1347 } 1348 1349 JNI_TRACE("ENGINE_ctrl_cmd_string(%p, \"%s\", \"%s\", %d) => %d", e, cmdChars.c_str(), 1350 arg_c_str, cmd_optional, ret); 1351 return ret; 1352 } 1353 1354 /** 1355 * public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g, 1356 * byte[] pub_key, byte[] priv_key); 1357 */ 1358 static jlong NativeCrypto_EVP_PKEY_new_DSA(JNIEnv* env, jclass, 1359 jbyteArray p, jbyteArray q, jbyteArray g, 1360 jbyteArray pub_key, jbyteArray priv_key) { 1361 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p)", 1362 p, q, g, pub_key, priv_key); 1363 1364 Unique_DSA dsa(DSA_new()); 1365 if (dsa.get() == NULL) { 1366 jniThrowRuntimeException(env, "DSA_new failed"); 1367 return 0; 1368 } 1369 1370 if (!arrayToBignum(env, p, &dsa->p)) { 1371 return 0; 1372 } 1373 1374 if (!arrayToBignum(env, q, &dsa->q)) { 1375 return 0; 1376 } 1377 1378 if (!arrayToBignum(env, g, &dsa->g)) { 1379 return 0; 1380 } 1381 1382 if (pub_key != NULL && !arrayToBignum(env, pub_key, &dsa->pub_key)) { 1383 return 0; 1384 } 1385 1386 if (priv_key != NULL && !arrayToBignum(env, priv_key, &dsa->priv_key)) { 1387 return 0; 1388 } 1389 1390 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL 1391 || (dsa->pub_key == NULL && dsa->priv_key == NULL)) { 1392 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM"); 1393 return 0; 1394 } 1395 1396 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 1397 if (pkey.get() == NULL) { 1398 jniThrowRuntimeException(env, "EVP_PKEY_new failed"); 1399 return 0; 1400 } 1401 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) { 1402 jniThrowRuntimeException(env, "EVP_PKEY_assign_DSA failed"); 1403 return 0; 1404 } 1405 OWNERSHIP_TRANSFERRED(dsa); 1406 JNI_TRACE("EVP_PKEY_new_DSA(p=%p, q=%p, g=%p, pub_key=%p, priv_key=%p) => %p", 1407 p, q, g, pub_key, priv_key, pkey.get()); 1408 return reinterpret_cast<jlong>(pkey.release()); 1409 } 1410 1411 /** 1412 * private static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q); 1413 */ 1414 static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, 1415 jbyteArray n, jbyteArray e, jbyteArray d, 1416 jbyteArray p, jbyteArray q, 1417 jbyteArray dmp1, jbyteArray dmq1, 1418 jbyteArray iqmp) { 1419 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p, dmp1=%p, dmq1=%p, iqmp=%p)", 1420 n, e, d, p, q, dmp1, dmq1, iqmp); 1421 1422 Unique_RSA rsa(RSA_new()); 1423 if (rsa.get() == NULL) { 1424 jniThrowRuntimeException(env, "RSA_new failed"); 1425 return 0; 1426 } 1427 1428 if (e == NULL && d == NULL) { 1429 jniThrowException(env, "java/lang/IllegalArgumentException", "e == NULL && d == NULL"); 1430 JNI_TRACE("NativeCrypto_EVP_PKEY_new_RSA => e == NULL && d == NULL"); 1431 return 0; 1432 } 1433 1434 if (!arrayToBignum(env, n, &rsa->n)) { 1435 return 0; 1436 } 1437 1438 if (e != NULL && !arrayToBignum(env, e, &rsa->e)) { 1439 return 0; 1440 } 1441 1442 if (d != NULL && !arrayToBignum(env, d, &rsa->d)) { 1443 return 0; 1444 } 1445 1446 if (p != NULL && !arrayToBignum(env, p, &rsa->p)) { 1447 return 0; 1448 } 1449 1450 if (q != NULL && !arrayToBignum(env, q, &rsa->q)) { 1451 return 0; 1452 } 1453 1454 if (dmp1 != NULL && !arrayToBignum(env, dmp1, &rsa->dmp1)) { 1455 return 0; 1456 } 1457 1458 if (dmq1 != NULL && !arrayToBignum(env, dmq1, &rsa->dmq1)) { 1459 return 0; 1460 } 1461 1462 if (iqmp != NULL && !arrayToBignum(env, iqmp, &rsa->iqmp)) { 1463 return 0; 1464 } 1465 1466 #ifdef WITH_JNI_TRACE 1467 if (p != NULL && q != NULL) { 1468 int check = RSA_check_key(rsa.get()); 1469 JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check); 1470 } 1471 #endif 1472 1473 if (rsa->n == NULL || (rsa->e == NULL && rsa->d == NULL)) { 1474 jniThrowRuntimeException(env, "Unable to convert BigInteger to BIGNUM"); 1475 return 0; 1476 } 1477 1478 /* 1479 * If the private exponent is available, there is the potential to do signing 1480 * operations. If the public exponent is also available, OpenSSL will do RSA 1481 * blinding. Enable it if possible. 1482 */ 1483 if (rsa->d != NULL) { 1484 if (rsa->e != NULL) { 1485 JNI_TRACE("EVP_PKEY_new_RSA(...) enabling RSA blinding => %p", rsa.get()); 1486 RSA_blinding_on(rsa.get(), NULL); 1487 } else { 1488 JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get()); 1489 RSA_blinding_off(rsa.get()); 1490 } 1491 } 1492 1493 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 1494 if (pkey.get() == NULL) { 1495 jniThrowRuntimeException(env, "EVP_PKEY_new failed"); 1496 return 0; 1497 } 1498 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) { 1499 jniThrowRuntimeException(env, "EVP_PKEY_new failed"); 1500 return 0; 1501 } 1502 OWNERSHIP_TRANSFERRED(rsa); 1503 JNI_TRACE("EVP_PKEY_new_RSA(n=%p, e=%p, d=%p, p=%p, q=%p dmp1=%p, dmq1=%p, iqmp=%p) => %p", 1504 n, e, d, p, q, dmp1, dmq1, iqmp, pkey.get()); 1505 return reinterpret_cast<uintptr_t>(pkey.release()); 1506 } 1507 1508 static jlong NativeCrypto_EVP_PKEY_new_EC_KEY(JNIEnv* env, jclass, jlong groupRef, 1509 jlong pubkeyRef, jbyteArray keyJavaBytes) { 1510 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 1511 const EC_POINT* pubkey = reinterpret_cast<const EC_POINT*>(pubkeyRef); 1512 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p)", group, pubkey, keyJavaBytes); 1513 1514 Unique_BIGNUM key(NULL); 1515 if (keyJavaBytes != NULL) { 1516 BIGNUM* keyRef; 1517 if (!arrayToBignum(env, keyJavaBytes, &keyRef)) { 1518 return 0; 1519 } 1520 key.reset(keyRef); 1521 } 1522 1523 Unique_EC_KEY eckey(EC_KEY_new()); 1524 if (eckey.get() == NULL) { 1525 jniThrowRuntimeException(env, "EC_KEY_new failed"); 1526 return 0; 1527 } 1528 1529 if (EC_KEY_set_group(eckey.get(), group) != 1) { 1530 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) > EC_KEY_set_group failed", group, pubkey, 1531 keyJavaBytes); 1532 throwExceptionIfNecessary(env, "EC_KEY_set_group"); 1533 return 0; 1534 } 1535 1536 if (pubkey != NULL) { 1537 if (EC_KEY_set_public_key(eckey.get(), pubkey) != 1) { 1538 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group, 1539 pubkey, keyJavaBytes); 1540 throwExceptionIfNecessary(env, "EC_KEY_set_public_key"); 1541 return 0; 1542 } 1543 } 1544 1545 if (key.get() != NULL) { 1546 if (EC_KEY_set_private_key(eckey.get(), key.get()) != 1) { 1547 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => EC_KEY_set_private_key failed", group, 1548 pubkey, keyJavaBytes); 1549 throwExceptionIfNecessary(env, "EC_KEY_set_private_key"); 1550 return 0; 1551 } 1552 if (pubkey == NULL) { 1553 Unique_EC_POINT calcPubkey(EC_POINT_new(group)); 1554 if (!EC_POINT_mul(group, calcPubkey.get(), key.get(), NULL, NULL, NULL)) { 1555 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => can't calulate public key", group, 1556 pubkey, keyJavaBytes); 1557 throwExceptionIfNecessary(env, "EC_KEY_set_private_key"); 1558 return 0; 1559 } 1560 EC_KEY_set_public_key(eckey.get(), calcPubkey.get()); 1561 } 1562 } 1563 1564 if (!EC_KEY_check_key(eckey.get())) { 1565 JNI_TRACE("EVP_KEY_new_EC_KEY(%p, %p, %p) => invalid key created", group, pubkey, keyJavaBytes); 1566 throwExceptionIfNecessary(env, "EC_KEY_check_key"); 1567 return 0; 1568 } 1569 1570 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 1571 if (pkey.get() == NULL) { 1572 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes); 1573 throwExceptionIfNecessary(env, "EVP_PKEY_new failed"); 1574 return 0; 1575 } 1576 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) { 1577 JNI_TRACE("EVP_PKEY_new_EC(%p, %p, %p) => threw error", group, pubkey, keyJavaBytes); 1578 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed"); 1579 return 0; 1580 } 1581 OWNERSHIP_TRANSFERRED(eckey); 1582 1583 JNI_TRACE("EVP_PKEY_new_EC_KEY(%p, %p, %p) => %p", group, pubkey, keyJavaBytes, pkey.get()); 1584 return reinterpret_cast<uintptr_t>(pkey.release()); 1585 } 1586 1587 static jlong NativeCrypto_EVP_PKEY_new_mac_key(JNIEnv* env, jclass, jint pkeyType, 1588 jbyteArray keyJavaBytes) 1589 { 1590 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p)", pkeyType, keyJavaBytes); 1591 1592 ScopedByteArrayRO key(env, keyJavaBytes); 1593 if (key.get() == NULL) { 1594 return 0; 1595 } 1596 1597 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(key.get()); 1598 Unique_EVP_PKEY pkey(EVP_PKEY_new_mac_key(pkeyType, (ENGINE *) NULL, tmp, key.size())); 1599 if (pkey.get() == NULL) { 1600 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => threw error", pkeyType, keyJavaBytes); 1601 throwExceptionIfNecessary(env, "ENGINE_load_private_key"); 1602 return 0; 1603 } 1604 1605 JNI_TRACE("EVP_PKEY_new_mac_key(%d, %p) => %p", pkeyType, keyJavaBytes, pkey.get()); 1606 return reinterpret_cast<uintptr_t>(pkey.release()); 1607 } 1608 1609 static int NativeCrypto_EVP_PKEY_type(JNIEnv* env, jclass, jlong pkeyRef) { 1610 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1611 JNI_TRACE("EVP_PKEY_type(%p)", pkey); 1612 1613 if (pkey == NULL) { 1614 jniThrowNullPointerException(env, NULL); 1615 return -1; 1616 } 1617 1618 int result = EVP_PKEY_type(pkey->type); 1619 JNI_TRACE("EVP_PKEY_type(%p) => %d", pkey, result); 1620 return result; 1621 } 1622 1623 /** 1624 * private static native int EVP_PKEY_size(int pkey); 1625 */ 1626 static int NativeCrypto_EVP_PKEY_size(JNIEnv* env, jclass, jlong pkeyRef) { 1627 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1628 JNI_TRACE("EVP_PKEY_size(%p)", pkey); 1629 1630 if (pkey == NULL) { 1631 jniThrowNullPointerException(env, NULL); 1632 return -1; 1633 } 1634 1635 int result = EVP_PKEY_size(pkey); 1636 JNI_TRACE("EVP_PKEY_size(%p) => %d", pkey, result); 1637 return result; 1638 } 1639 1640 static jstring NativeCrypto_EVP_PKEY_print_public(JNIEnv* env, jclass, jlong pkeyRef) { 1641 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1642 JNI_TRACE("EVP_PKEY_print_public(%p)", pkey); 1643 1644 if (pkey == NULL) { 1645 jniThrowNullPointerException(env, "pkey == null"); 1646 return NULL; 1647 } 1648 1649 Unique_BIO buffer(BIO_new(BIO_s_mem())); 1650 if (buffer.get() == NULL) { 1651 jniThrowOutOfMemory(env, "Unable to allocate BIO"); 1652 return NULL; 1653 } 1654 1655 if (EVP_PKEY_print_public(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) { 1656 throwExceptionIfNecessary(env, "EVP_PKEY_print_public"); 1657 return NULL; 1658 } 1659 // Null terminate this 1660 BIO_write(buffer.get(), "\0", 1); 1661 1662 char *tmp; 1663 BIO_get_mem_data(buffer.get(), &tmp); 1664 jstring description = env->NewStringUTF(tmp); 1665 1666 JNI_TRACE("EVP_PKEY_print_public(%p) => \"%s\"", pkey, tmp); 1667 return description; 1668 } 1669 1670 static jstring NativeCrypto_EVP_PKEY_print_private(JNIEnv* env, jclass, jlong pkeyRef) { 1671 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1672 JNI_TRACE("EVP_PKEY_print_private(%p)", pkey); 1673 1674 if (pkey == NULL) { 1675 jniThrowNullPointerException(env, "pkey == null"); 1676 return NULL; 1677 } 1678 1679 Unique_BIO buffer(BIO_new(BIO_s_mem())); 1680 if (buffer.get() == NULL) { 1681 jniThrowOutOfMemory(env, "Unable to allocate BIO"); 1682 return NULL; 1683 } 1684 1685 if (EVP_PKEY_print_private(buffer.get(), pkey, 0, (ASN1_PCTX*) NULL) != 1) { 1686 throwExceptionIfNecessary(env, "EVP_PKEY_print_private"); 1687 return NULL; 1688 } 1689 // Null terminate this 1690 BIO_write(buffer.get(), "\0", 1); 1691 1692 char *tmp; 1693 BIO_get_mem_data(buffer.get(), &tmp); 1694 jstring description = env->NewStringUTF(tmp); 1695 1696 JNI_TRACE("EVP_PKEY_print_private(%p) => \"%s\"", pkey, tmp); 1697 return description; 1698 } 1699 1700 static void NativeCrypto_EVP_PKEY_free(JNIEnv*, jclass, jlong pkeyRef) { 1701 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1702 JNI_TRACE("EVP_PKEY_free(%p)", pkey); 1703 1704 if (pkey != NULL) { 1705 EVP_PKEY_free(pkey); 1706 } 1707 } 1708 1709 static jint NativeCrypto_EVP_PKEY_cmp(JNIEnv* env, jclass, jlong pkey1Ref, jlong pkey2Ref) { 1710 EVP_PKEY* pkey1 = reinterpret_cast<EVP_PKEY*>(pkey1Ref); 1711 EVP_PKEY* pkey2 = reinterpret_cast<EVP_PKEY*>(pkey2Ref); 1712 JNI_TRACE("EVP_PKEY_cmp(%p, %p)", pkey1, pkey2); 1713 1714 if (pkey1 == NULL) { 1715 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey1 == NULL", pkey1, pkey2); 1716 jniThrowNullPointerException(env, "pkey1 == NULL"); 1717 return -1; 1718 } else if (pkey2 == NULL) { 1719 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => failed pkey2 == NULL", pkey1, pkey2); 1720 jniThrowNullPointerException(env, "pkey2 == NULL"); 1721 return -1; 1722 } 1723 1724 int result = EVP_PKEY_cmp(pkey1, pkey2); 1725 JNI_TRACE("EVP_PKEY_cmp(%p, %p) => %d", pkey1, pkey2, result); 1726 return result; 1727 } 1728 1729 /* 1730 * static native byte[] i2d_PKCS8_PRIV_KEY_INFO(int, byte[]) 1731 */ 1732 static jbyteArray NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jlong pkeyRef) { 1733 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1734 JNI_TRACE("i2d_PKCS8_PRIV_KEY_INFO(%p)", pkey); 1735 1736 if (pkey == NULL) { 1737 jniThrowNullPointerException(env, NULL); 1738 return NULL; 1739 } 1740 1741 Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey)); 1742 if (pkcs8.get() == NULL) { 1743 throwExceptionIfNecessary(env, "NativeCrypto_i2d_PKCS8_PRIV_KEY_INFO"); 1744 JNI_TRACE("key=%p i2d_PKCS8_PRIV_KEY_INFO => error from key to PKCS8", pkey); 1745 return NULL; 1746 } 1747 1748 return ASN1ToByteArray<PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO>(env, pkcs8.get()); 1749 } 1750 1751 /* 1752 * static native int d2i_PKCS8_PRIV_KEY_INFO(byte[]) 1753 */ 1754 static jlong NativeCrypto_d2i_PKCS8_PRIV_KEY_INFO(JNIEnv* env, jclass, jbyteArray keyJavaBytes) { 1755 JNI_TRACE("d2i_PKCS8_PRIV_KEY_INFO(%p)", keyJavaBytes); 1756 1757 ScopedByteArrayRO bytes(env, keyJavaBytes); 1758 if (bytes.get() == NULL) { 1759 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => threw exception", keyJavaBytes); 1760 return 0; 1761 } 1762 1763 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get()); 1764 Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, bytes.size())); 1765 if (pkcs8.get() == NULL) { 1766 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO"); 1767 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from DER to PKCS8", keyJavaBytes); 1768 return 0; 1769 } 1770 1771 Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get())); 1772 if (pkey.get() == NULL) { 1773 throwExceptionIfNecessary(env, "d2i_PKCS8_PRIV_KEY_INFO"); 1774 JNI_TRACE("ssl=%p d2i_PKCS8_PRIV_KEY_INFO => error from PKCS8 to key", keyJavaBytes); 1775 return 0; 1776 } 1777 1778 JNI_TRACE("bytes=%p d2i_PKCS8_PRIV_KEY_INFO => %p", keyJavaBytes, pkey.get()); 1779 return reinterpret_cast<uintptr_t>(pkey.release()); 1780 } 1781 1782 /* 1783 * static native byte[] i2d_PUBKEY(int) 1784 */ 1785 static jbyteArray NativeCrypto_i2d_PUBKEY(JNIEnv* env, jclass, jlong pkeyRef) { 1786 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1787 JNI_TRACE("i2d_PUBKEY(%p)", pkey); 1788 return ASN1ToByteArray<EVP_PKEY, i2d_PUBKEY>(env, pkey); 1789 } 1790 1791 /* 1792 * static native int d2i_PUBKEY(byte[]) 1793 */ 1794 static jlong NativeCrypto_d2i_PUBKEY(JNIEnv* env, jclass, jbyteArray javaBytes) { 1795 JNI_TRACE("d2i_PUBKEY(%p)", javaBytes); 1796 1797 ScopedByteArrayRO bytes(env, javaBytes); 1798 if (bytes.get() == NULL) { 1799 JNI_TRACE("d2i_PUBKEY(%p) => threw error", javaBytes); 1800 return 0; 1801 } 1802 1803 const unsigned char* tmp = reinterpret_cast<const unsigned char*>(bytes.get()); 1804 Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, bytes.size())); 1805 if (pkey.get() == NULL) { 1806 JNI_TRACE("bytes=%p d2i_PUBKEY => threw exception", javaBytes); 1807 throwExceptionIfNecessary(env, "d2i_PUBKEY"); 1808 return 0; 1809 } 1810 1811 return reinterpret_cast<uintptr_t>(pkey.release()); 1812 } 1813 1814 /* 1815 * public static native int RSA_generate_key(int modulusBits, byte[] publicExponent); 1816 */ 1817 static jlong NativeCrypto_RSA_generate_key_ex(JNIEnv* env, jclass, jint modulusBits, 1818 jbyteArray publicExponent) { 1819 JNI_TRACE("RSA_generate_key_ex(%d, %p)", modulusBits, publicExponent); 1820 1821 BIGNUM* eRef; 1822 if (!arrayToBignum(env, publicExponent, &eRef)) { 1823 return 0; 1824 } 1825 Unique_BIGNUM e(eRef); 1826 1827 Unique_RSA rsa(RSA_new()); 1828 if (rsa.get() == NULL) { 1829 jniThrowOutOfMemory(env, "Unable to allocate RSA key"); 1830 return 0; 1831 } 1832 1833 if (RSA_generate_key_ex(rsa.get(), modulusBits, e.get(), NULL) < 0) { 1834 throwExceptionIfNecessary(env, "RSA_generate_key_ex"); 1835 return 0; 1836 } 1837 1838 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 1839 if (pkey.get() == NULL) { 1840 jniThrowRuntimeException(env, "RSA_generate_key_ex failed"); 1841 return 0; 1842 } 1843 1844 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) { 1845 jniThrowRuntimeException(env, "RSA_generate_key_ex failed"); 1846 return 0; 1847 } 1848 1849 OWNERSHIP_TRANSFERRED(rsa); 1850 JNI_TRACE("RSA_generate_key_ex(n=%d, e=%p) => %p", modulusBits, publicExponent, pkey.get()); 1851 return reinterpret_cast<uintptr_t>(pkey.release()); 1852 } 1853 1854 static jint NativeCrypto_RSA_size(JNIEnv* env, jclass, jlong pkeyRef) { 1855 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1856 JNI_TRACE("RSA_size(%p)", pkey); 1857 1858 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey)); 1859 if (rsa.get() == NULL) { 1860 jniThrowRuntimeException(env, "RSA_size failed"); 1861 return 0; 1862 } 1863 1864 return static_cast<jint>(RSA_size(rsa.get())); 1865 } 1866 1867 typedef int RSACryptOperation(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, 1868 int padding); 1869 1870 static jint RSA_crypt_operation(RSACryptOperation operation, 1871 const char* caller __attribute__ ((unused)), JNIEnv* env, jint flen, 1872 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) { 1873 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1874 JNI_TRACE("%s(%d, %p, %p, %p)", caller, flen, fromJavaBytes, toJavaBytes, pkey); 1875 1876 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey)); 1877 if (rsa.get() == NULL) { 1878 return -1; 1879 } 1880 1881 ScopedByteArrayRO from(env, fromJavaBytes); 1882 if (from.get() == NULL) { 1883 return -1; 1884 } 1885 1886 ScopedByteArrayRW to(env, toJavaBytes); 1887 if (to.get() == NULL) { 1888 return -1; 1889 } 1890 1891 int resultSize = operation(static_cast<int>(flen), 1892 reinterpret_cast<const unsigned char*>(from.get()), 1893 reinterpret_cast<unsigned char*>(to.get()), rsa.get(), padding); 1894 if (resultSize == -1) { 1895 JNI_TRACE("%s => failed", caller); 1896 throwExceptionIfNecessary(env, "RSA_crypt_operation"); 1897 return -1; 1898 } 1899 1900 JNI_TRACE("%s(%d, %p, %p, %p) => %d", caller, flen, fromJavaBytes, toJavaBytes, pkey, 1901 resultSize); 1902 return static_cast<jint>(resultSize); 1903 } 1904 1905 static jint NativeCrypto_RSA_private_encrypt(JNIEnv* env, jclass, jint flen, 1906 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) { 1907 return RSA_crypt_operation(RSA_private_encrypt, __FUNCTION__, 1908 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding); 1909 } 1910 static jint NativeCrypto_RSA_public_decrypt(JNIEnv* env, jclass, jint flen, 1911 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) { 1912 return RSA_crypt_operation(RSA_public_decrypt, __FUNCTION__, 1913 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding); 1914 } 1915 static jint NativeCrypto_RSA_public_encrypt(JNIEnv* env, jclass, jint flen, 1916 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) { 1917 return RSA_crypt_operation(RSA_public_encrypt, __FUNCTION__, 1918 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding); 1919 } 1920 static jint NativeCrypto_RSA_private_decrypt(JNIEnv* env, jclass, jint flen, 1921 jbyteArray fromJavaBytes, jbyteArray toJavaBytes, jlong pkeyRef, jint padding) { 1922 return RSA_crypt_operation(RSA_private_decrypt, __FUNCTION__, 1923 env, flen, fromJavaBytes, toJavaBytes, pkeyRef, padding); 1924 } 1925 1926 /* 1927 * public static native byte[][] get_RSA_public_params(int); 1928 */ 1929 static jobjectArray NativeCrypto_get_RSA_public_params(JNIEnv* env, jclass, jlong pkeyRef) { 1930 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1931 JNI_TRACE("get_RSA_public_params(%p)", pkey); 1932 1933 if (pkey == NULL) { 1934 jniThrowNullPointerException(env, "pkey == null"); 1935 return 0; 1936 } 1937 1938 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey)); 1939 if (rsa.get() == NULL) { 1940 throwExceptionIfNecessary(env, "get_RSA_public_params failed"); 1941 return 0; 1942 } 1943 1944 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL); 1945 if (joa == NULL) { 1946 return NULL; 1947 } 1948 1949 jbyteArray n = bignumToArray(env, rsa->n, "n"); 1950 if (env->ExceptionCheck()) { 1951 return NULL; 1952 } 1953 env->SetObjectArrayElement(joa, 0, n); 1954 1955 jbyteArray e = bignumToArray(env, rsa->e, "e"); 1956 if (env->ExceptionCheck()) { 1957 return NULL; 1958 } 1959 env->SetObjectArrayElement(joa, 1, e); 1960 1961 return joa; 1962 } 1963 1964 /* 1965 * public static native byte[][] get_RSA_private_params(int); 1966 */ 1967 static jobjectArray NativeCrypto_get_RSA_private_params(JNIEnv* env, jclass, jlong pkeyRef) { 1968 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 1969 JNI_TRACE("get_RSA_public_params(%p)", pkey); 1970 1971 if (pkey == NULL) { 1972 jniThrowNullPointerException(env, "pkey == null"); 1973 return 0; 1974 } 1975 1976 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey)); 1977 if (rsa.get() == NULL) { 1978 throwExceptionIfNecessary(env, "get_RSA_public_params failed"); 1979 return 0; 1980 } 1981 1982 jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL); 1983 if (joa == NULL) { 1984 return NULL; 1985 } 1986 1987 jbyteArray n = bignumToArray(env, rsa->n, "n"); 1988 if (env->ExceptionCheck()) { 1989 return NULL; 1990 } 1991 env->SetObjectArrayElement(joa, 0, n); 1992 1993 if (rsa->e != NULL) { 1994 jbyteArray e = bignumToArray(env, rsa->e, "e"); 1995 if (env->ExceptionCheck()) { 1996 return NULL; 1997 } 1998 env->SetObjectArrayElement(joa, 1, e); 1999 } 2000 2001 if (rsa->d != NULL) { 2002 jbyteArray d = bignumToArray(env, rsa->d, "d"); 2003 if (env->ExceptionCheck()) { 2004 return NULL; 2005 } 2006 env->SetObjectArrayElement(joa, 2, d); 2007 } 2008 2009 if (rsa->p != NULL) { 2010 jbyteArray p = bignumToArray(env, rsa->p, "p"); 2011 if (env->ExceptionCheck()) { 2012 return NULL; 2013 } 2014 env->SetObjectArrayElement(joa, 3, p); 2015 } 2016 2017 if (rsa->q != NULL) { 2018 jbyteArray q = bignumToArray(env, rsa->q, "q"); 2019 if (env->ExceptionCheck()) { 2020 return NULL; 2021 } 2022 env->SetObjectArrayElement(joa, 4, q); 2023 } 2024 2025 if (rsa->dmp1 != NULL) { 2026 jbyteArray dmp1 = bignumToArray(env, rsa->dmp1, "dmp1"); 2027 if (env->ExceptionCheck()) { 2028 return NULL; 2029 } 2030 env->SetObjectArrayElement(joa, 5, dmp1); 2031 } 2032 2033 if (rsa->dmq1 != NULL) { 2034 jbyteArray dmq1 = bignumToArray(env, rsa->dmq1, "dmq1"); 2035 if (env->ExceptionCheck()) { 2036 return NULL; 2037 } 2038 env->SetObjectArrayElement(joa, 6, dmq1); 2039 } 2040 2041 if (rsa->iqmp != NULL) { 2042 jbyteArray iqmp = bignumToArray(env, rsa->iqmp, "iqmp"); 2043 if (env->ExceptionCheck()) { 2044 return NULL; 2045 } 2046 env->SetObjectArrayElement(joa, 7, iqmp); 2047 } 2048 2049 return joa; 2050 } 2051 2052 /* 2053 * public static native int DSA_generate_key(int, byte[]); 2054 */ 2055 static jlong NativeCrypto_DSA_generate_key(JNIEnv* env, jclass, jint primeBits, 2056 jbyteArray seedJavaBytes, jbyteArray gBytes, jbyteArray pBytes, jbyteArray qBytes) { 2057 JNI_TRACE("DSA_generate_key(%d, %p, %p, %p, %p)", primeBits, seedJavaBytes, 2058 gBytes, pBytes, qBytes); 2059 2060 UniquePtr<unsigned char[]> seedPtr; 2061 unsigned long seedSize = 0; 2062 if (seedJavaBytes != NULL) { 2063 ScopedByteArrayRO seed(env, seedJavaBytes); 2064 if (seed.get() == NULL) { 2065 return 0; 2066 } 2067 2068 seedSize = seed.size(); 2069 seedPtr.reset(new unsigned char[seedSize]); 2070 2071 memcpy(seedPtr.get(), seed.get(), seedSize); 2072 } 2073 2074 Unique_DSA dsa(DSA_new()); 2075 if (dsa.get() == NULL) { 2076 JNI_TRACE("DSA_generate_key failed"); 2077 jniThrowOutOfMemory(env, "Unable to allocate DSA key"); 2078 freeOpenSslErrorState(); 2079 return 0; 2080 } 2081 2082 if (gBytes != NULL && pBytes != NULL && qBytes != NULL) { 2083 JNI_TRACE("DSA_generate_key parameters specified"); 2084 2085 if (!arrayToBignum(env, gBytes, &dsa->g)) { 2086 return 0; 2087 } 2088 2089 if (!arrayToBignum(env, pBytes, &dsa->p)) { 2090 return 0; 2091 } 2092 2093 if (!arrayToBignum(env, qBytes, &dsa->q)) { 2094 return 0; 2095 } 2096 } else { 2097 JNI_TRACE("DSA_generate_key generating parameters"); 2098 2099 if (!DSA_generate_parameters_ex(dsa.get(), primeBits, seedPtr.get(), seedSize, NULL, NULL, NULL)) { 2100 JNI_TRACE("DSA_generate_key => param generation failed"); 2101 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_parameters_ex failed"); 2102 return 0; 2103 } 2104 } 2105 2106 if (!DSA_generate_key(dsa.get())) { 2107 JNI_TRACE("DSA_generate_key failed"); 2108 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed"); 2109 return 0; 2110 } 2111 2112 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 2113 if (pkey.get() == NULL) { 2114 JNI_TRACE("DSA_generate_key failed"); 2115 jniThrowRuntimeException(env, "NativeCrypto_DSA_generate_key failed"); 2116 freeOpenSslErrorState(); 2117 return 0; 2118 } 2119 2120 if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) { 2121 JNI_TRACE("DSA_generate_key failed"); 2122 throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed"); 2123 return 0; 2124 } 2125 2126 OWNERSHIP_TRANSFERRED(dsa); 2127 JNI_TRACE("DSA_generate_key(n=%d, e=%p) => %p", primeBits, seedPtr.get(), pkey.get()); 2128 return reinterpret_cast<uintptr_t>(pkey.release()); 2129 } 2130 2131 /* 2132 * public static native byte[][] get_DSA_params(int); 2133 */ 2134 static jobjectArray NativeCrypto_get_DSA_params(JNIEnv* env, jclass, jlong pkeyRef) { 2135 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 2136 JNI_TRACE("get_DSA_params(%p)", pkey); 2137 2138 Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey)); 2139 if (dsa.get() == NULL) { 2140 throwExceptionIfNecessary(env, "get_DSA_params failed"); 2141 return 0; 2142 } 2143 2144 jobjectArray joa = env->NewObjectArray(5, byteArrayClass, NULL); 2145 if (joa == NULL) { 2146 return NULL; 2147 } 2148 2149 if (dsa->g != NULL) { 2150 jbyteArray g = bignumToArray(env, dsa->g, "g"); 2151 if (env->ExceptionCheck()) { 2152 return NULL; 2153 } 2154 env->SetObjectArrayElement(joa, 0, g); 2155 } 2156 2157 if (dsa->p != NULL) { 2158 jbyteArray p = bignumToArray(env, dsa->p, "p"); 2159 if (env->ExceptionCheck()) { 2160 return NULL; 2161 } 2162 env->SetObjectArrayElement(joa, 1, p); 2163 } 2164 2165 if (dsa->q != NULL) { 2166 jbyteArray q = bignumToArray(env, dsa->q, "q"); 2167 if (env->ExceptionCheck()) { 2168 return NULL; 2169 } 2170 env->SetObjectArrayElement(joa, 2, q); 2171 } 2172 2173 if (dsa->pub_key != NULL) { 2174 jbyteArray pub_key = bignumToArray(env, dsa->pub_key, "pub_key"); 2175 if (env->ExceptionCheck()) { 2176 return NULL; 2177 } 2178 env->SetObjectArrayElement(joa, 3, pub_key); 2179 } 2180 2181 if (dsa->priv_key != NULL) { 2182 jbyteArray priv_key = bignumToArray(env, dsa->priv_key, "priv_key"); 2183 if (env->ExceptionCheck()) { 2184 return NULL; 2185 } 2186 env->SetObjectArrayElement(joa, 4, priv_key); 2187 } 2188 2189 return joa; 2190 } 2191 2192 #define EC_CURVE_GFP 1 2193 #define EC_CURVE_GF2M 2 2194 2195 /** 2196 * Return group type or 0 if unknown group. 2197 * EC_GROUP_GFP or EC_GROUP_GF2M 2198 */ 2199 static int get_EC_GROUP_type(const EC_GROUP* group) 2200 { 2201 const EC_METHOD* method = EC_GROUP_method_of(group); 2202 if (method == EC_GFp_nist_method() 2203 || method == EC_GFp_mont_method() 2204 || method == EC_GFp_simple_method()) { 2205 return EC_CURVE_GFP; 2206 } else if (method == EC_GF2m_simple_method()) { 2207 return EC_CURVE_GF2M; 2208 } 2209 2210 return 0; 2211 } 2212 2213 static jlong NativeCrypto_EC_GROUP_new_by_curve_name(JNIEnv* env, jclass, jstring curveNameJava) 2214 { 2215 JNI_TRACE("EC_GROUP_new_by_curve_name(%p)", curveNameJava); 2216 2217 ScopedUtfChars curveName(env, curveNameJava); 2218 if (curveName.c_str() == NULL) { 2219 return 0; 2220 } 2221 JNI_TRACE("EC_GROUP_new_by_curve_name(%s)", curveName.c_str()); 2222 2223 int nid = OBJ_sn2nid(curveName.c_str()); 2224 if (nid == NID_undef) { 2225 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID name", curveName.c_str()); 2226 return 0; 2227 } 2228 2229 EC_GROUP* group = EC_GROUP_new_by_curve_name(nid); 2230 if (group == NULL) { 2231 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => unknown NID %d", curveName.c_str(), nid); 2232 freeOpenSslErrorState(); 2233 return 0; 2234 } 2235 2236 JNI_TRACE("EC_GROUP_new_by_curve_name(%s) => %p", curveName.c_str(), group); 2237 return reinterpret_cast<uintptr_t>(group); 2238 } 2239 2240 static void NativeCrypto_EC_GROUP_set_asn1_flag(JNIEnv* env, jclass, jlong groupRef, 2241 jint flag) 2242 { 2243 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef); 2244 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d)", group, flag); 2245 2246 if (group == NULL) { 2247 JNI_TRACE("EC_GROUP_set_asn1_flag => group == NULL"); 2248 jniThrowNullPointerException(env, "group == NULL"); 2249 return; 2250 } 2251 2252 EC_GROUP_set_asn1_flag(group, flag); 2253 JNI_TRACE("EC_GROUP_set_asn1_flag(%p, %d) => success", group, flag); 2254 } 2255 2256 static void NativeCrypto_EC_GROUP_set_point_conversion_form(JNIEnv* env, jclass, 2257 jlong groupRef, jint form) 2258 { 2259 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef); 2260 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d)", group, form); 2261 2262 if (group == NULL) { 2263 JNI_TRACE("EC_GROUP_set_point_conversion_form => group == NULL"); 2264 jniThrowNullPointerException(env, "group == NULL"); 2265 return; 2266 } 2267 2268 EC_GROUP_set_point_conversion_form(group, static_cast<point_conversion_form_t>(form)); 2269 JNI_TRACE("EC_GROUP_set_point_conversion_form(%p, %d) => success", group, form); 2270 } 2271 2272 static jlong NativeCrypto_EC_GROUP_new_curve(JNIEnv* env, jclass, jint type, jbyteArray pJava, 2273 jbyteArray aJava, jbyteArray bJava) 2274 { 2275 JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p)", type, pJava, aJava, bJava); 2276 2277 BIGNUM* pRef; 2278 if (!arrayToBignum(env, pJava, &pRef)) { 2279 return 0; 2280 } 2281 Unique_BIGNUM p(pRef); 2282 2283 BIGNUM* aRef; 2284 if (!arrayToBignum(env, aJava, &aRef)) { 2285 return 0; 2286 } 2287 Unique_BIGNUM a(aRef); 2288 2289 BIGNUM* bRef; 2290 if (!arrayToBignum(env, bJava, &bRef)) { 2291 return 0; 2292 } 2293 Unique_BIGNUM b(bRef); 2294 2295 EC_GROUP* group; 2296 switch (type) { 2297 case EC_CURVE_GFP: 2298 group = EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), (BN_CTX*) NULL); 2299 break; 2300 case EC_CURVE_GF2M: 2301 group = EC_GROUP_new_curve_GF2m(p.get(), a.get(), b.get(), (BN_CTX*) NULL); 2302 break; 2303 default: 2304 jniThrowRuntimeException(env, "invalid group"); 2305 return 0; 2306 } 2307 2308 if (group == NULL) { 2309 throwExceptionIfNecessary(env, "EC_GROUP_new_curve"); 2310 } 2311 2312 JNI_TRACE("EC_GROUP_new_curve(%d, %p, %p, %p) => %p", type, pJava, aJava, bJava, group); 2313 return reinterpret_cast<uintptr_t>(group); 2314 } 2315 2316 static jlong NativeCrypto_EC_GROUP_dup(JNIEnv* env, jclass, jlong groupRef) { 2317 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2318 JNI_TRACE("EC_GROUP_dup(%p)", group); 2319 2320 if (group == NULL) { 2321 JNI_TRACE("EC_GROUP_dup => group == NULL"); 2322 jniThrowNullPointerException(env, "group == NULL"); 2323 return 0; 2324 } 2325 2326 EC_GROUP* groupDup = EC_GROUP_dup(group); 2327 JNI_TRACE("EC_GROUP_dup(%p) => %p", group, groupDup); 2328 return reinterpret_cast<uintptr_t>(groupDup); 2329 } 2330 2331 static jstring NativeCrypto_EC_GROUP_get_curve_name(JNIEnv* env, jclass, jlong groupRef) { 2332 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2333 JNI_TRACE("EC_GROUP_get_curve_name(%p)", group); 2334 2335 if (group == NULL) { 2336 JNI_TRACE("EC_GROUP_get_curve_name => group == NULL"); 2337 jniThrowNullPointerException(env, "group == NULL"); 2338 return 0; 2339 } 2340 2341 int nid = EC_GROUP_get_curve_name(group); 2342 if (nid == NID_undef) { 2343 JNI_TRACE("EC_GROUP_get_curve_name(%p) => unnamed curve", group); 2344 return NULL; 2345 } 2346 2347 const char* shortName = OBJ_nid2sn(nid); 2348 JNI_TRACE("EC_GROUP_get_curve_name(%p) => \"%s\"", group, shortName); 2349 return env->NewStringUTF(shortName); 2350 } 2351 2352 static jobjectArray NativeCrypto_EC_GROUP_get_curve(JNIEnv* env, jclass, jlong groupRef) 2353 { 2354 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2355 JNI_TRACE("EC_GROUP_get_curve(%p)", group); 2356 2357 Unique_BIGNUM p(BN_new()); 2358 Unique_BIGNUM a(BN_new()); 2359 Unique_BIGNUM b(BN_new()); 2360 2361 int ret; 2362 switch (get_EC_GROUP_type(group)) { 2363 case EC_CURVE_GFP: 2364 ret = EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), (BN_CTX*) NULL); 2365 break; 2366 case EC_CURVE_GF2M: 2367 ret = EC_GROUP_get_curve_GF2m(group, p.get(), a.get(), b.get(), (BN_CTX*)NULL); 2368 break; 2369 default: 2370 jniThrowRuntimeException(env, "invalid group"); 2371 return NULL; 2372 } 2373 if (ret != 1) { 2374 throwExceptionIfNecessary(env, "EC_GROUP_get_curve"); 2375 return NULL; 2376 } 2377 2378 jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL); 2379 if (joa == NULL) { 2380 return NULL; 2381 } 2382 2383 jbyteArray pArray = bignumToArray(env, p.get(), "p"); 2384 if (env->ExceptionCheck()) { 2385 return NULL; 2386 } 2387 env->SetObjectArrayElement(joa, 0, pArray); 2388 2389 jbyteArray aArray = bignumToArray(env, a.get(), "a"); 2390 if (env->ExceptionCheck()) { 2391 return NULL; 2392 } 2393 env->SetObjectArrayElement(joa, 1, aArray); 2394 2395 jbyteArray bArray = bignumToArray(env, b.get(), "b"); 2396 if (env->ExceptionCheck()) { 2397 return NULL; 2398 } 2399 env->SetObjectArrayElement(joa, 2, bArray); 2400 2401 JNI_TRACE("EC_GROUP_get_curve(%p) => %p", group, joa); 2402 return joa; 2403 } 2404 2405 static jbyteArray NativeCrypto_EC_GROUP_get_order(JNIEnv* env, jclass, jlong groupRef) 2406 { 2407 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2408 JNI_TRACE("EC_GROUP_get_order(%p)", group); 2409 2410 Unique_BIGNUM order(BN_new()); 2411 if (order.get() == NULL) { 2412 JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group); 2413 jniThrowOutOfMemory(env, "BN_new"); 2414 return NULL; 2415 } 2416 2417 if (EC_GROUP_get_order(group, order.get(), NULL) != 1) { 2418 JNI_TRACE("EC_GROUP_get_order(%p) => threw error", group); 2419 throwExceptionIfNecessary(env, "EC_GROUP_get_order"); 2420 return NULL; 2421 } 2422 2423 jbyteArray orderArray = bignumToArray(env, order.get(), "order"); 2424 if (env->ExceptionCheck()) { 2425 return NULL; 2426 } 2427 2428 JNI_TRACE("EC_GROUP_get_order(%p) => %p", group, orderArray); 2429 return orderArray; 2430 } 2431 2432 static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jlong groupRef) 2433 { 2434 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2435 JNI_TRACE("EC_GROUP_get_degree(%p)", group); 2436 2437 jint degree = EC_GROUP_get_degree(group); 2438 if (degree == 0) { 2439 JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group); 2440 jniThrowRuntimeException(env, "not supported"); 2441 return 0; 2442 } 2443 2444 JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree); 2445 return degree; 2446 } 2447 2448 static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jlong groupRef) 2449 { 2450 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2451 JNI_TRACE("EC_GROUP_get_cofactor(%p)", group); 2452 2453 Unique_BIGNUM cofactor(BN_new()); 2454 if (cofactor.get() == NULL) { 2455 JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group); 2456 jniThrowOutOfMemory(env, "BN_new"); 2457 return NULL; 2458 } 2459 2460 if (EC_GROUP_get_cofactor(group, cofactor.get(), NULL) != 1) { 2461 JNI_TRACE("EC_GROUP_get_cofactor(%p) => threw error", group); 2462 throwExceptionIfNecessary(env, "EC_GROUP_get_cofactor"); 2463 return NULL; 2464 } 2465 2466 jbyteArray cofactorArray = bignumToArray(env, cofactor.get(), "cofactor"); 2467 if (env->ExceptionCheck()) { 2468 return NULL; 2469 } 2470 2471 JNI_TRACE("EC_GROUP_get_cofactor(%p) => %p", group, cofactorArray); 2472 return cofactorArray; 2473 } 2474 2475 static jint NativeCrypto_get_EC_GROUP_type(JNIEnv* env, jclass, jlong groupRef) 2476 { 2477 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2478 JNI_TRACE("get_EC_GROUP_type(%p)", group); 2479 2480 int type = get_EC_GROUP_type(group); 2481 if (type == 0) { 2482 JNI_TRACE("get_EC_GROUP_type(%p) => curve type", group); 2483 jniThrowRuntimeException(env, "unknown curve type"); 2484 } else { 2485 JNI_TRACE("get_EC_GROUP_type(%p) => %d", group, type); 2486 } 2487 return type; 2488 } 2489 2490 static void NativeCrypto_EC_GROUP_clear_free(JNIEnv* env, jclass, jlong groupRef) 2491 { 2492 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef); 2493 JNI_TRACE("EC_GROUP_clear_free(%p)", group); 2494 2495 if (group == NULL) { 2496 JNI_TRACE("EC_GROUP_clear_free => group == NULL"); 2497 jniThrowNullPointerException(env, "group == NULL"); 2498 return; 2499 } 2500 2501 EC_GROUP_clear_free(group); 2502 JNI_TRACE("EC_GROUP_clear_free(%p) => success", group); 2503 } 2504 2505 static jboolean NativeCrypto_EC_GROUP_cmp(JNIEnv* env, jclass, jlong group1Ref, jlong group2Ref) 2506 { 2507 const EC_GROUP* group1 = reinterpret_cast<const EC_GROUP*>(group1Ref); 2508 const EC_GROUP* group2 = reinterpret_cast<const EC_GROUP*>(group2Ref); 2509 JNI_TRACE("EC_GROUP_cmp(%p, %p)", group1, group2); 2510 2511 if (group1 == NULL || group2 == NULL) { 2512 JNI_TRACE("EC_GROUP_cmp(%p, %p) => group1 == null || group2 == null", group1, group2); 2513 jniThrowNullPointerException(env, "group1 == null || group2 == null"); 2514 return false; 2515 } 2516 2517 int ret = EC_GROUP_cmp(group1, group2, (BN_CTX*)NULL); 2518 2519 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", group1, group2, ret); 2520 return ret == 0; 2521 } 2522 2523 static void NativeCrypto_EC_GROUP_set_generator(JNIEnv* env, jclass, jlong groupRef, jlong pointRef, jbyteArray njavaBytes, jbyteArray hjavaBytes) 2524 { 2525 EC_GROUP* group = reinterpret_cast<EC_GROUP*>(groupRef); 2526 const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef); 2527 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p)", group, point, njavaBytes, hjavaBytes); 2528 2529 if (group == NULL || point == NULL) { 2530 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => group == null || point == null", 2531 group, point, njavaBytes, hjavaBytes); 2532 jniThrowNullPointerException(env, "group == null || point == null"); 2533 return; 2534 } 2535 2536 BIGNUM* nRef; 2537 if (!arrayToBignum(env, njavaBytes, &nRef)) { 2538 return; 2539 } 2540 Unique_BIGNUM n(nRef); 2541 2542 BIGNUM* hRef; 2543 if (!arrayToBignum(env, hjavaBytes, &hRef)) { 2544 return; 2545 } 2546 Unique_BIGNUM h(hRef); 2547 2548 int ret = EC_GROUP_set_generator(group, point, n.get(), h.get()); 2549 if (ret == 0) { 2550 throwExceptionIfNecessary(env, "EC_GROUP_set_generator"); 2551 } 2552 2553 JNI_TRACE("EC_GROUP_set_generator(%p, %p, %p, %p) => %d", group, point, njavaBytes, hjavaBytes, ret); 2554 } 2555 2556 static jlong NativeCrypto_EC_GROUP_get_generator(JNIEnv* env, jclass, jlong groupRef) 2557 { 2558 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2559 JNI_TRACE("EC_GROUP_get_generator(%p)", group); 2560 2561 if (group == NULL) { 2562 JNI_TRACE("EC_POINT_get_generator(%p) => group == null", group); 2563 jniThrowNullPointerException(env, "group == null"); 2564 return 0; 2565 } 2566 2567 const EC_POINT* generator = EC_GROUP_get0_generator(group); 2568 2569 Unique_EC_POINT dup(EC_POINT_dup(generator, group)); 2570 if (dup.get() == NULL) { 2571 JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group); 2572 jniThrowOutOfMemory(env, "unable to dupe generator"); 2573 return 0; 2574 } 2575 2576 JNI_TRACE("EC_GROUP_get_generator(%p) => %p", group, dup.get()); 2577 return reinterpret_cast<uintptr_t>(dup.release()); 2578 } 2579 2580 static jlong NativeCrypto_EC_POINT_new(JNIEnv* env, jclass, jlong groupRef) 2581 { 2582 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2583 JNI_TRACE("EC_POINT_new(%p)", group); 2584 2585 if (group == NULL) { 2586 JNI_TRACE("EC_POINT_new(%p) => group == null", group); 2587 jniThrowNullPointerException(env, "group == null"); 2588 return 0; 2589 } 2590 2591 EC_POINT* point = EC_POINT_new(group); 2592 if (point == NULL) { 2593 jniThrowOutOfMemory(env, "Unable create an EC_POINT"); 2594 return 0; 2595 } 2596 2597 return reinterpret_cast<uintptr_t>(point); 2598 } 2599 2600 static void NativeCrypto_EC_POINT_clear_free(JNIEnv* env, jclass, jlong groupRef) { 2601 EC_POINT* group = reinterpret_cast<EC_POINT*>(groupRef); 2602 JNI_TRACE("EC_POINT_clear_free(%p)", group); 2603 2604 if (group == NULL) { 2605 JNI_TRACE("EC_POINT_clear_free => group == NULL"); 2606 jniThrowNullPointerException(env, "group == NULL"); 2607 return; 2608 } 2609 2610 EC_POINT_clear_free(group); 2611 JNI_TRACE("EC_POINT_clear_free(%p) => success", group); 2612 } 2613 2614 static jboolean NativeCrypto_EC_POINT_cmp(JNIEnv* env, jclass, jlong groupRef, jlong point1Ref, jlong point2Ref) 2615 { 2616 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2617 const EC_POINT* point1 = reinterpret_cast<const EC_POINT*>(point1Ref); 2618 const EC_POINT* point2 = reinterpret_cast<const EC_POINT*>(point2Ref); 2619 JNI_TRACE("EC_POINT_cmp(%p, %p, %p)", group, point1, point2); 2620 2621 if (group == NULL || point1 == NULL || point2 == NULL) { 2622 JNI_TRACE("EC_POINT_cmp(%p, %p, %p) => group == null || point1 == null || point2 == null", 2623 group, point1, point2); 2624 jniThrowNullPointerException(env, "group == null || point1 == null || point2 == null"); 2625 return false; 2626 } 2627 2628 int ret = EC_POINT_cmp(group, point1, point2, (BN_CTX*)NULL); 2629 2630 JNI_TRACE("ECP_GROUP_cmp(%p, %p) => %d", point1, point2, ret); 2631 return ret == 0; 2632 } 2633 2634 static void NativeCrypto_EC_POINT_set_affine_coordinates(JNIEnv* env, jclass, 2635 jlong groupRef, jlong pointRef, jbyteArray xjavaBytes, jbyteArray yjavaBytes) 2636 { 2637 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2638 EC_POINT* point = reinterpret_cast<EC_POINT*>(pointRef); 2639 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p)", group, point, xjavaBytes, 2640 yjavaBytes); 2641 2642 if (group == NULL || point == NULL) { 2643 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => group == null || point == null", 2644 group, point, xjavaBytes, yjavaBytes); 2645 jniThrowNullPointerException(env, "group == null || point == null"); 2646 return; 2647 } 2648 2649 BIGNUM* xRef; 2650 if (!arrayToBignum(env, xjavaBytes, &xRef)) { 2651 return; 2652 } 2653 Unique_BIGNUM x(xRef); 2654 2655 BIGNUM* yRef; 2656 if (!arrayToBignum(env, yjavaBytes, &yRef)) { 2657 return; 2658 } 2659 Unique_BIGNUM y(yRef); 2660 2661 int ret; 2662 switch (get_EC_GROUP_type(group)) { 2663 case EC_CURVE_GFP: 2664 ret = EC_POINT_set_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL); 2665 break; 2666 case EC_CURVE_GF2M: 2667 ret = EC_POINT_set_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL); 2668 break; 2669 default: 2670 jniThrowRuntimeException(env, "invalid curve type"); 2671 return; 2672 } 2673 2674 if (ret != 1) { 2675 throwExceptionIfNecessary(env, "EC_POINT_set_affine_coordinates"); 2676 } 2677 2678 JNI_TRACE("EC_POINT_set_affine_coordinates(%p, %p, %p, %p) => %d", group, point, 2679 xjavaBytes, yjavaBytes, ret); 2680 } 2681 2682 static jobjectArray NativeCrypto_EC_POINT_get_affine_coordinates(JNIEnv* env, jclass, jlong groupRef, 2683 jlong pointRef) 2684 { 2685 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2686 const EC_POINT* point = reinterpret_cast<const EC_POINT*>(pointRef); 2687 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point); 2688 2689 Unique_BIGNUM x(BN_new()); 2690 Unique_BIGNUM y(BN_new()); 2691 2692 int ret; 2693 switch (get_EC_GROUP_type(group)) { 2694 case EC_CURVE_GFP: 2695 ret = EC_POINT_get_affine_coordinates_GFp(group, point, x.get(), y.get(), NULL); 2696 break; 2697 case EC_CURVE_GF2M: 2698 ret = EC_POINT_get_affine_coordinates_GF2m(group, point, x.get(), y.get(), NULL); 2699 break; 2700 default: 2701 jniThrowRuntimeException(env, "invalid curve type"); 2702 return NULL; 2703 } 2704 if (ret != 1) { 2705 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p)", group, point); 2706 throwExceptionIfNecessary(env, "EC_POINT_get_affine_coordinates"); 2707 return NULL; 2708 } 2709 2710 jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL); 2711 if (joa == NULL) { 2712 return NULL; 2713 } 2714 2715 jbyteArray xBytes = bignumToArray(env, x.get(), "x"); 2716 if (env->ExceptionCheck()) { 2717 return NULL; 2718 } 2719 env->SetObjectArrayElement(joa, 0, xBytes); 2720 2721 jbyteArray yBytes = bignumToArray(env, y.get(), "y"); 2722 if (env->ExceptionCheck()) { 2723 return NULL; 2724 } 2725 env->SetObjectArrayElement(joa, 1, yBytes); 2726 2727 JNI_TRACE("EC_POINT_get_affine_coordinates(%p, %p) => %p", group, point, joa); 2728 return joa; 2729 } 2730 2731 static jlong NativeCrypto_EC_KEY_generate_key(JNIEnv* env, jclass, jlong groupRef) 2732 { 2733 const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef); 2734 JNI_TRACE("EC_KEY_generate_key(%p)", group); 2735 2736 Unique_EC_KEY eckey(EC_KEY_new()); 2737 if (eckey.get() == NULL) { 2738 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group); 2739 jniThrowOutOfMemory(env, "Unable to create an EC_KEY"); 2740 return 0; 2741 } 2742 2743 if (EC_KEY_set_group(eckey.get(), group) != 1) { 2744 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_set_group error", group); 2745 throwExceptionIfNecessary(env, "EC_KEY_set_group"); 2746 return 0; 2747 } 2748 2749 if (EC_KEY_generate_key(eckey.get()) != 1) { 2750 JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_generate_key error", group); 2751 throwExceptionIfNecessary(env, "EC_KEY_set_group"); 2752 return 0; 2753 } 2754 2755 Unique_EVP_PKEY pkey(EVP_PKEY_new()); 2756 if (pkey.get() == NULL) { 2757 JNI_TRACE("EC_KEY_generate_key(%p) => threw error", group); 2758 throwExceptionIfNecessary(env, "EC_KEY_generate_key"); 2759 return 0; 2760 } 2761 if (EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()) != 1) { 2762 jniThrowRuntimeException(env, "EVP_PKEY_assign_EC_KEY failed"); 2763 return 0; 2764 } 2765 OWNERSHIP_TRANSFERRED(eckey); 2766 2767 JNI_TRACE("EC_KEY_generate_key(%p) => %p", group, pkey.get()); 2768 return reinterpret_cast<uintptr_t>(pkey.release()); 2769 } 2770 2771 static jlong NativeCrypto_EC_KEY_get0_group(JNIEnv* env, jclass, jlong pkeyRef) 2772 { 2773 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 2774 JNI_TRACE("EC_KEY_get0_group(%p)", pkey); 2775 2776 if (pkey == NULL) { 2777 jniThrowNullPointerException(env, "pkey == null"); 2778 JNI_TRACE("EC_KEY_get0_group(%p) => pkey == null", pkey); 2779 return 0; 2780 } 2781 2782 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { 2783 jniThrowRuntimeException(env, "not EC key"); 2784 JNI_TRACE("EC_KEY_get0_group(%p) => not EC key (type == %d)", pkey, 2785 EVP_PKEY_type(pkey->type)); 2786 return 0; 2787 } 2788 2789 const EC_GROUP* group = EC_KEY_get0_group(pkey->pkey.ec); 2790 JNI_TRACE("EC_KEY_get0_group(%p) => %p", pkey, group); 2791 return reinterpret_cast<uintptr_t>(group); 2792 } 2793 2794 static jbyteArray NativeCrypto_EC_KEY_get_private_key(JNIEnv* env, jclass, jlong pkeyRef) 2795 { 2796 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 2797 JNI_TRACE("EC_KEY_get_private_key(%p)", pkey); 2798 2799 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey)); 2800 if (eckey.get() == NULL) { 2801 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY"); 2802 return NULL; 2803 } 2804 2805 const BIGNUM *privkey = EC_KEY_get0_private_key(eckey.get()); 2806 2807 jbyteArray privBytes = bignumToArray(env, privkey, "privkey"); 2808 if (env->ExceptionCheck()) { 2809 JNI_TRACE("EC_KEY_get_private_key(%p) => threw error", pkey); 2810 return NULL; 2811 } 2812 2813 JNI_TRACE("EC_KEY_get_private_key(%p) => %p", pkey, privBytes); 2814 return privBytes; 2815 } 2816 2817 static jlong NativeCrypto_EC_KEY_get_public_key(JNIEnv* env, jclass, jlong pkeyRef) 2818 { 2819 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 2820 JNI_TRACE("EC_KEY_get_public_key(%p)", pkey); 2821 2822 Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey)); 2823 if (eckey.get() == NULL) { 2824 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY"); 2825 return 0; 2826 } 2827 2828 Unique_EC_POINT dup(EC_POINT_dup(EC_KEY_get0_public_key(eckey.get()), 2829 EC_KEY_get0_group(eckey.get()))); 2830 if (dup.get() == NULL) { 2831 JNI_TRACE("EC_KEY_get_public_key(%p) => can't dup public key", pkey); 2832 jniThrowRuntimeException(env, "EC_POINT_dup"); 2833 return 0; 2834 } 2835 2836 JNI_TRACE("EC_KEY_get_public_key(%p) => %p", pkey, dup.get()); 2837 return reinterpret_cast<uintptr_t>(dup.release()); 2838 } 2839 2840 static jint NativeCrypto_ECDH_compute_key(JNIEnv* env, jclass, 2841 jbyteArray outArray, jint outOffset, jlong pubkeyRef, jlong privkeyRef) 2842 { 2843 EVP_PKEY* pubPkey = reinterpret_cast<EVP_PKEY*>(pubkeyRef); 2844 EVP_PKEY* privPkey = reinterpret_cast<EVP_PKEY*>(privkeyRef); 2845 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p)", outArray, outOffset, pubPkey, privPkey); 2846 2847 ScopedByteArrayRW out(env, outArray); 2848 if (out.get() == NULL) { 2849 JNI_TRACE("ECDH_compute_key(%p, %d, %p, %p) can't get output buffer", 2850 outArray, outOffset, pubPkey, privPkey); 2851 return -1; 2852 } 2853 2854 if ((outOffset < 0) || ((size_t) outOffset >= out.size())) { 2855 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 2856 return -1; 2857 } 2858 2859 Unique_EC_KEY pubkey(EVP_PKEY_get1_EC_KEY(pubPkey)); 2860 if (pubkey.get() == NULL) { 2861 JNI_TRACE("ECDH_compute_key(%p) => can't get public key", pubPkey); 2862 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public"); 2863 return -1; 2864 } 2865 2866 const EC_POINT* pubkeyPoint = EC_KEY_get0_public_key(pubkey.get()); 2867 if (pubkeyPoint == NULL) { 2868 JNI_TRACE("ECDH_compute_key(%p) => can't get public key point", pubPkey); 2869 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY public"); 2870 return -1; 2871 } 2872 2873 Unique_EC_KEY privkey(EVP_PKEY_get1_EC_KEY(privPkey)); 2874 if (privkey.get() == NULL) { 2875 throwExceptionIfNecessary(env, "EVP_PKEY_get1_EC_KEY private"); 2876 return -1; 2877 } 2878 2879 int outputLength = ECDH_compute_key( 2880 &out[outOffset], 2881 out.size() - outOffset, 2882 pubkeyPoint, 2883 privkey.get(), 2884 NULL // No KDF 2885 ); 2886 if (outputLength == -1) { 2887 throwExceptionIfNecessary(env, "ECDH_compute_key"); 2888 return -1; 2889 } 2890 2891 return outputLength; 2892 } 2893 2894 static jlong NativeCrypto_EVP_MD_CTX_create(JNIEnv* env, jclass) { 2895 JNI_TRACE("EVP_MD_CTX_create()"); 2896 2897 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create()); 2898 if (ctx.get() == NULL) { 2899 jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX"); 2900 return 0; 2901 } 2902 2903 JNI_TRACE("EVP_MD_CTX_create() => %p", ctx.get()); 2904 return reinterpret_cast<uintptr_t>(ctx.release()); 2905 } 2906 2907 static void NativeCrypto_EVP_MD_CTX_init(JNIEnv*, jclass, jlong ctxRef) { 2908 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 2909 JNI_TRACE("NativeCrypto_EVP_MD_CTX_init(%p)", ctx); 2910 2911 if (ctx != NULL) { 2912 EVP_MD_CTX_init(ctx); 2913 } 2914 } 2915 2916 static void NativeCrypto_EVP_MD_CTX_destroy(JNIEnv*, jclass, jlong ctxRef) { 2917 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 2918 JNI_TRACE("NativeCrypto_EVP_MD_CTX_destroy(%p)", ctx); 2919 2920 if (ctx != NULL) { 2921 EVP_MD_CTX_destroy(ctx); 2922 } 2923 } 2924 2925 static jlong NativeCrypto_EVP_MD_CTX_copy(JNIEnv* env, jclass, jlong ctxRef) { 2926 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 2927 JNI_TRACE("NativeCrypto_EVP_MD_CTX_copy(%p)", ctx); 2928 2929 if (ctx == NULL) { 2930 jniThrowNullPointerException(env, "ctx == null"); 2931 return 0; 2932 } 2933 2934 EVP_MD_CTX* copy = EVP_MD_CTX_create(); 2935 if (copy == NULL) { 2936 jniThrowOutOfMemory(env, "Unable to allocate copy of EVP_MD_CTX"); 2937 return 0; 2938 } 2939 2940 EVP_MD_CTX_init(copy); 2941 int result = EVP_MD_CTX_copy_ex(copy, ctx); 2942 if (result == 0) { 2943 EVP_MD_CTX_destroy(copy); 2944 jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX"); 2945 freeOpenSslErrorState(); 2946 return 0; 2947 } 2948 2949 JNI_TRACE("NativeCrypto_EVP_MD_CTX_copy(%p) => %p", ctx, copy); 2950 return reinterpret_cast<uintptr_t>(copy); 2951 } 2952 2953 /* 2954 * public static native int EVP_DigestFinal(int, byte[], int) 2955 */ 2956 static jint NativeCrypto_EVP_DigestFinal(JNIEnv* env, jclass, jlong ctxRef, 2957 jbyteArray hash, jint offset) { 2958 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 2959 JNI_TRACE("NativeCrypto_EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset); 2960 2961 if (ctx == NULL || hash == NULL) { 2962 jniThrowNullPointerException(env, "ctx == null || hash == null"); 2963 return -1; 2964 } 2965 2966 ScopedByteArrayRW hashBytes(env, hash); 2967 if (hashBytes.get() == NULL) { 2968 return -1; 2969 } 2970 unsigned int bytesWritten = -1; 2971 int ok = EVP_DigestFinal(ctx, 2972 reinterpret_cast<unsigned char*>(hashBytes.get() + offset), 2973 &bytesWritten); 2974 if (ok == 0) { 2975 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestFinal"); 2976 } 2977 EVP_MD_CTX_destroy(ctx); 2978 2979 JNI_TRACE("NativeCrypto_EVP_DigestFinal(%p, %p, %d) => %d", ctx, hash, offset, bytesWritten); 2980 return bytesWritten; 2981 } 2982 2983 /* 2984 * public static native int EVP_DigestInit(int) 2985 */ 2986 static jlong NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, jlong evpMdRef) { 2987 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef); 2988 JNI_TRACE("NativeCrypto_EVP_DigestInit(%p)", evp_md); 2989 2990 if (evp_md == NULL) { 2991 jniThrowNullPointerException(env, NULL); 2992 return 0; 2993 } 2994 2995 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create()); 2996 if (ctx.get() == NULL) { 2997 jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX"); 2998 return 0; 2999 } 3000 JNI_TRACE("NativeCrypto_EVP_DigestInit ctx=%p", ctx.get()); 3001 3002 int ok = EVP_DigestInit(ctx.get(), evp_md); 3003 if (ok == 0) { 3004 bool exception = throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestInit"); 3005 if (exception) { 3006 return 0; 3007 } 3008 } 3009 return reinterpret_cast<uintptr_t>(ctx.release()); 3010 } 3011 3012 /* 3013 * public static native int EVP_get_digestbyname(java.lang.String) 3014 */ 3015 static jlong NativeCrypto_EVP_get_digestbyname(JNIEnv* env, jclass, jstring algorithm) { 3016 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%p)", algorithm); 3017 3018 if (algorithm == NULL) { 3019 jniThrowNullPointerException(env, NULL); 3020 return -1; 3021 } 3022 3023 ScopedUtfChars algorithmChars(env, algorithm); 3024 if (algorithmChars.c_str() == NULL) { 3025 return 0; 3026 } 3027 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s)", algorithmChars.c_str()); 3028 3029 const EVP_MD* evp_md = EVP_get_digestbyname(algorithmChars.c_str()); 3030 if (evp_md == NULL) { 3031 jniThrowRuntimeException(env, "Hash algorithm not found"); 3032 return 0; 3033 } 3034 3035 JNI_TRACE("NativeCrypto_EVP_get_digestbyname(%s) => %p", algorithmChars.c_str(), evp_md); 3036 return reinterpret_cast<uintptr_t>(evp_md); 3037 } 3038 3039 /* 3040 * public static native int EVP_MD_size(int) 3041 */ 3042 static jint NativeCrypto_EVP_MD_size(JNIEnv* env, jclass, jint evpMdRef) { 3043 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef); 3044 JNI_TRACE("NativeCrypto_EVP_MD_size(%p)", evp_md); 3045 3046 if (evp_md == NULL) { 3047 jniThrowNullPointerException(env, NULL); 3048 return -1; 3049 } 3050 3051 int result = EVP_MD_size(evp_md); 3052 JNI_TRACE("NativeCrypto_EVP_MD_size(%p) => %d", evp_md, result); 3053 return result; 3054 } 3055 3056 /* 3057 * public static int void EVP_MD_block_size(int) 3058 */ 3059 static jint NativeCrypto_EVP_MD_block_size(JNIEnv* env, jclass, jlong evpMdRef) { 3060 EVP_MD* evp_md = reinterpret_cast<EVP_MD*>(evpMdRef); 3061 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p)", evp_md); 3062 3063 if (evp_md == NULL) { 3064 jniThrowNullPointerException(env, NULL); 3065 return -1; 3066 } 3067 3068 int result = EVP_MD_block_size(evp_md); 3069 JNI_TRACE("NativeCrypto_EVP_MD_block_size(%p) => %d", evp_md, result); 3070 return result; 3071 } 3072 3073 /* 3074 * public static native void EVP_DigestUpdate(int, byte[], int, int) 3075 */ 3076 static void NativeCrypto_EVP_DigestUpdate(JNIEnv* env, jclass, jlong ctxRef, 3077 jbyteArray buffer, jint offset, jint length) { 3078 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 3079 JNI_TRACE("NativeCrypto_EVP_DigestUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length); 3080 3081 if (offset < 0 || length < 0) { 3082 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 3083 return; 3084 } 3085 3086 if (ctx == NULL || buffer == NULL) { 3087 jniThrowNullPointerException(env, NULL); 3088 return; 3089 } 3090 3091 ScopedByteArrayRO bufferBytes(env, buffer); 3092 if (bufferBytes.get() == NULL) { 3093 return; 3094 } 3095 int ok = EVP_DigestUpdate(ctx, 3096 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset), 3097 length); 3098 if (ok == 0) { 3099 throwExceptionIfNecessary(env, "NativeCrypto_EVP_DigestUpdate"); 3100 } 3101 } 3102 3103 static void NativeCrypto_EVP_DigestSignInit(JNIEnv* env, jclass, jlong evpMdCtxRef, 3104 const jlong evpMdRef, jlong pkeyRef) { 3105 EVP_MD_CTX* mdCtx = reinterpret_cast<EVP_MD_CTX*>(evpMdCtxRef); 3106 const EVP_MD* md = reinterpret_cast<const EVP_MD*>(evpMdRef); 3107 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 3108 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p)", mdCtx, md, pkey); 3109 3110 if (mdCtx == NULL) { 3111 jniThrowNullPointerException(env, "mdCtx == null"); 3112 return; 3113 } 3114 3115 if (md == NULL) { 3116 jniThrowNullPointerException(env, "md == null"); 3117 return; 3118 } 3119 3120 if (pkey == NULL) { 3121 jniThrowNullPointerException(env, "pkey == null"); 3122 return; 3123 } 3124 3125 if (EVP_DigestSignInit(mdCtx, (EVP_PKEY_CTX **) NULL, md, (ENGINE *) NULL, pkey) <= 0) { 3126 JNI_TRACE("ctx=%p EVP_DigestSignInit => threw exception", mdCtx); 3127 throwExceptionIfNecessary(env, "EVP_DigestSignInit"); 3128 return; 3129 } 3130 3131 JNI_TRACE("EVP_DigestSignInit(%p, %p, %p) => success", mdCtx, md, pkey); 3132 } 3133 3134 static void NativeCrypto_EVP_DigestSignUpdate(JNIEnv* env, jclass, jint evpMdCtxRef, 3135 jbyteArray inJavaBytes, jint inOffset, jint inLength) 3136 { 3137 EVP_MD_CTX* mdCtx = reinterpret_cast<EVP_MD_CTX*>(evpMdCtxRef); 3138 JNI_TRACE("EVP_DigestSignUpdate(%p, %p, %d, %d)", mdCtx, inJavaBytes, inOffset, inLength); 3139 3140 if (mdCtx == NULL) { 3141 jniThrowNullPointerException(env, "mdCtx == null"); 3142 return; 3143 } 3144 3145 ScopedByteArrayRO inBytes(env, inJavaBytes); 3146 if (inBytes.get() == NULL) { 3147 return; 3148 } 3149 3150 if (inOffset < 0 || size_t(inOffset) > inBytes.size()) { 3151 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "inOffset"); 3152 return; 3153 } 3154 3155 const ssize_t inEnd = inOffset + inLength; 3156 if (inEnd < 0 || size_t(inEnd) >= inBytes.size()) { 3157 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "inLength"); 3158 return; 3159 } 3160 3161 const unsigned char *tmp = reinterpret_cast<const unsigned char *>(inBytes.get()); 3162 if (!EVP_DigestSignUpdate(mdCtx, tmp + inOffset, inLength)) { 3163 JNI_TRACE("ctx=%p EVP_DigestSignUpdate => threw exception", mdCtx); 3164 throwExceptionIfNecessary(env, "EVP_DigestSignUpdate"); 3165 } 3166 3167 JNI_TRACE("EVP_DigestSignUpdate(%p, %p, %d, %d) => success", mdCtx, inJavaBytes, inOffset, 3168 inLength); 3169 } 3170 3171 static jbyteArray NativeCrypto_EVP_DigestSignFinal(JNIEnv* env, jclass, jlong evpMdCtxRef) 3172 { 3173 EVP_MD_CTX* mdCtx = reinterpret_cast<EVP_MD_CTX*>(evpMdCtxRef); 3174 JNI_TRACE("EVP_DigestSignFinal(%p)", mdCtx); 3175 3176 if (mdCtx == NULL) { 3177 jniThrowNullPointerException(env, "mdCtx == null"); 3178 return NULL; 3179 } 3180 3181 const size_t expectedSize = EVP_MD_CTX_size(mdCtx); 3182 ScopedLocalRef<jbyteArray> outJavaBytes(env, env->NewByteArray(expectedSize)); 3183 if (outJavaBytes.get() == NULL) { 3184 return NULL; 3185 } 3186 ScopedByteArrayRW outBytes(env, outJavaBytes.get()); 3187 if (outBytes.get() == NULL) { 3188 return NULL; 3189 } 3190 unsigned char *tmp = reinterpret_cast<unsigned char*>(outBytes.get()); 3191 size_t len; 3192 if (!EVP_DigestSignFinal(mdCtx, tmp, &len)) { 3193 JNI_TRACE("ctx=%p EVP_DigestSignFinal => threw exception", mdCtx); 3194 throwExceptionIfNecessary(env, "EVP_DigestSignFinal"); 3195 return 0; 3196 } 3197 3198 if (len != expectedSize) { 3199 jniThrowRuntimeException(env, "hash size unexpected"); 3200 return 0; 3201 } 3202 3203 JNI_TRACE("EVP_DigestSignFinal(%p) => %p", mdCtx, outJavaBytes.get()); 3204 return outJavaBytes.release(); 3205 } 3206 3207 static jlong NativeCrypto_EVP_SignInit(JNIEnv* env, jclass, jstring algorithm) { 3208 JNI_TRACE("NativeCrypto_EVP_SignInit(%p)", algorithm); 3209 3210 if (algorithm == NULL) { 3211 jniThrowNullPointerException(env, NULL); 3212 return 0; 3213 } 3214 3215 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create()); 3216 if (ctx.get() == NULL) { 3217 jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX"); 3218 return 0; 3219 } 3220 JNI_TRACE("NativeCrypto_EVP_SignInit ctx=%p", ctx.get()); 3221 3222 ScopedUtfChars algorithmChars(env, algorithm); 3223 if (algorithmChars.c_str() == NULL) { 3224 return 0; 3225 } 3226 JNI_TRACE("NativeCrypto_EVP_SignInit algorithmChars=%s", algorithmChars.c_str()); 3227 3228 const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); 3229 if (digest == NULL) { 3230 JNI_TRACE("NativeCrypto_EVP_SignInit(%s) => hash not found", algorithmChars.c_str()); 3231 throwExceptionIfNecessary(env, "Hash algorithm not found"); 3232 return 0; 3233 } 3234 3235 int ok = EVP_SignInit(ctx.get(), digest); 3236 if (ok == 0) { 3237 bool exception = throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignInit"); 3238 if (exception) { 3239 JNI_TRACE("NativeCrypto_EVP_SignInit(%s) => threw exception", algorithmChars.c_str()); 3240 return 0; 3241 } 3242 } 3243 3244 JNI_TRACE("NativeCrypto_EVP_SignInit(%s) => %p", algorithmChars.c_str(), ctx.get()); 3245 return reinterpret_cast<uintptr_t>(ctx.release()); 3246 } 3247 3248 /* 3249 * public static native void EVP_SignUpdate(int, byte[], int, int) 3250 */ 3251 static void NativeCrypto_EVP_SignUpdate(JNIEnv* env, jclass, jlong ctxRef, 3252 jbyteArray buffer, jint offset, jint length) { 3253 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 3254 JNI_TRACE("NativeCrypto_EVP_SignUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length); 3255 3256 if (ctx == NULL || buffer == NULL) { 3257 jniThrowNullPointerException(env, NULL); 3258 return; 3259 } 3260 3261 ScopedByteArrayRO bufferBytes(env, buffer); 3262 if (bufferBytes.get() == NULL) { 3263 return; 3264 } 3265 int ok = EVP_SignUpdate(ctx, 3266 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset), 3267 length); 3268 if (ok == 0) { 3269 throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignUpdate"); 3270 } 3271 } 3272 3273 /* 3274 * public static native int EVP_SignFinal(int, byte[], int, int) 3275 */ 3276 static jint NativeCrypto_EVP_SignFinal(JNIEnv* env, jclass, jlong ctxRef, jbyteArray signature, 3277 jint offset, jlong pkeyRef) { 3278 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 3279 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 3280 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p)", ctx, signature, offset, pkey); 3281 3282 if (ctx == NULL || pkey == NULL) { 3283 jniThrowNullPointerException(env, NULL); 3284 return -1; 3285 } 3286 3287 ScopedByteArrayRW signatureBytes(env, signature); 3288 if (signatureBytes.get() == NULL) { 3289 return -1; 3290 } 3291 unsigned int bytesWritten = -1; 3292 int ok = EVP_SignFinal(ctx, 3293 reinterpret_cast<unsigned char*>(signatureBytes.get() + offset), 3294 &bytesWritten, 3295 pkey); 3296 if (ok == 0) { 3297 throwExceptionIfNecessary(env, "NativeCrypto_EVP_SignFinal"); 3298 } 3299 JNI_TRACE("NativeCrypto_EVP_SignFinal(%p, %p, %d, %p) => %u", 3300 ctx, signature, offset, pkey, bytesWritten); 3301 3302 return bytesWritten; 3303 } 3304 3305 /* 3306 * public static native int EVP_VerifyInit(java.lang.String) 3307 */ 3308 static jlong NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, jstring algorithm) { 3309 JNI_TRACE("NativeCrypto_EVP_VerifyInit(%p)", algorithm); 3310 3311 if (algorithm == NULL) { 3312 jniThrowNullPointerException(env, NULL); 3313 return 0; 3314 } 3315 3316 Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create()); 3317 if (ctx.get() == NULL) { 3318 jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX"); 3319 return 0; 3320 } 3321 JNI_TRACE("NativeCrypto_EVP_VerifyInit ctx=%p", ctx.get()); 3322 3323 ScopedUtfChars algorithmChars(env, algorithm); 3324 if (algorithmChars.c_str() == NULL) { 3325 return 0; 3326 } 3327 JNI_TRACE("NativeCrypto_EVP_VerifyInit algorithmChars=%s", algorithmChars.c_str()); 3328 3329 const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); 3330 if (digest == NULL) { 3331 jniThrowRuntimeException(env, "Hash algorithm not found"); 3332 return 0; 3333 } 3334 3335 int ok = EVP_VerifyInit(ctx.get(), digest); 3336 if (ok == 0) { 3337 bool exception = throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyInit"); 3338 if (exception) { 3339 return 0; 3340 } 3341 } 3342 return reinterpret_cast<uintptr_t>(ctx.release()); 3343 } 3344 3345 /* 3346 * public static native void EVP_VerifyUpdate(int, byte[], int, int) 3347 */ 3348 static void NativeCrypto_EVP_VerifyUpdate(JNIEnv* env, jclass, jlong ctxRef, 3349 jbyteArray buffer, jint offset, jint length) { 3350 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 3351 JNI_TRACE("NativeCrypto_EVP_VerifyUpdate(%p, %p, %d, %d)", ctx, buffer, offset, length); 3352 3353 if (ctx == NULL || buffer == NULL) { 3354 jniThrowNullPointerException(env, NULL); 3355 return; 3356 } 3357 3358 ScopedByteArrayRO bufferBytes(env, buffer); 3359 if (bufferBytes.get() == NULL) { 3360 return; 3361 } 3362 int ok = EVP_VerifyUpdate(ctx, 3363 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset), 3364 length); 3365 if (ok == 0) { 3366 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyUpdate"); 3367 } 3368 } 3369 3370 /* 3371 * public static native int EVP_VerifyFinal(int, byte[], int, int, int) 3372 */ 3373 static jint NativeCrypto_EVP_VerifyFinal(JNIEnv* env, jclass, jlong ctxRef, jbyteArray buffer, 3374 jint offset, jint length, jlong pkeyRef) { 3375 EVP_MD_CTX* ctx = reinterpret_cast<EVP_MD_CTX*>(ctxRef); 3376 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 3377 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p)", 3378 ctx, buffer, offset, length, pkey); 3379 3380 if (ctx == NULL || buffer == NULL || pkey == NULL) { 3381 jniThrowNullPointerException(env, NULL); 3382 return -1; 3383 } 3384 3385 ScopedByteArrayRO bufferBytes(env, buffer); 3386 if (bufferBytes.get() == NULL) { 3387 return -1; 3388 } 3389 int ok = EVP_VerifyFinal(ctx, 3390 reinterpret_cast<const unsigned char*>(bufferBytes.get() + offset), 3391 length, 3392 pkey); 3393 if (ok < 0) { 3394 throwExceptionIfNecessary(env, "NativeCrypto_EVP_VerifyFinal"); 3395 } 3396 3397 /* 3398 * For DSA keys, OpenSSL appears to have a bug where it returns 3399 * errors for any result != 1. See dsa_ossl.c in dsa_do_verify 3400 */ 3401 freeOpenSslErrorState(); 3402 3403 JNI_TRACE("NativeCrypto_EVP_VerifyFinal(%p, %p, %d, %d, %p) => %d", 3404 ctx, buffer, offset, length, pkey, ok); 3405 3406 return ok; 3407 } 3408 3409 static jlong NativeCrypto_EVP_get_cipherbyname(JNIEnv* env, jclass, jstring algorithm) { 3410 JNI_TRACE("EVP_get_cipherbyname(%p)", algorithm); 3411 if (algorithm == NULL) { 3412 JNI_TRACE("EVP_get_cipherbyname(%p) => threw exception algorithm == null", algorithm); 3413 jniThrowNullPointerException(env, NULL); 3414 return -1; 3415 } 3416 3417 ScopedUtfChars algorithmChars(env, algorithm); 3418 if (algorithmChars.c_str() == NULL) { 3419 return 0; 3420 } 3421 JNI_TRACE("EVP_get_cipherbyname(%p) => algorithm = %s", algorithm, algorithmChars.c_str()); 3422 3423 const EVP_CIPHER* evp_cipher = EVP_get_cipherbyname(algorithmChars.c_str()); 3424 if (evp_cipher == NULL) { 3425 freeOpenSslErrorState(); 3426 } 3427 3428 JNI_TRACE("EVP_get_cipherbyname(%s) => %p", algorithmChars.c_str(), evp_cipher); 3429 return reinterpret_cast<uintptr_t>(evp_cipher); 3430 } 3431 3432 static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jlong ctxRef, jlong evpCipherRef, 3433 jbyteArray keyArray, jbyteArray ivArray, jboolean encrypting) { 3434 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3435 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef); 3436 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d)", ctx, evpCipher, keyArray, ivArray, 3437 encrypting ? 1 : 0); 3438 3439 if (ctx == NULL) { 3440 jniThrowNullPointerException(env, "ctx == null"); 3441 JNI_TRACE("EVP_CipherUpdate => ctx == null"); 3442 return; 3443 } 3444 3445 // The key can be null if we need to set extra parameters. 3446 UniquePtr<unsigned char[]> keyPtr; 3447 if (keyArray != NULL) { 3448 ScopedByteArrayRO keyBytes(env, keyArray); 3449 if (keyBytes.get() == NULL) { 3450 return; 3451 } 3452 3453 keyPtr.reset(new unsigned char[keyBytes.size()]); 3454 memcpy(keyPtr.get(), keyBytes.get(), keyBytes.size()); 3455 } 3456 3457 // The IV can be null if we're using ECB. 3458 UniquePtr<unsigned char[]> ivPtr; 3459 if (ivArray != NULL) { 3460 ScopedByteArrayRO ivBytes(env, ivArray); 3461 if (ivBytes.get() == NULL) { 3462 return; 3463 } 3464 3465 ivPtr.reset(new unsigned char[ivBytes.size()]); 3466 memcpy(ivPtr.get(), ivBytes.get(), ivBytes.size()); 3467 } 3468 3469 if (!EVP_CipherInit_ex(ctx, evpCipher, NULL, keyPtr.get(), ivPtr.get(), encrypting ? 1 : 0)) { 3470 throwExceptionIfNecessary(env, "EVP_CipherInit_ex"); 3471 JNI_TRACE("EVP_CipherInit_ex => error initializing cipher"); 3472 return; 3473 } 3474 3475 JNI_TRACE("EVP_CipherInit_ex(%p, %p, %p, %p, %d) => success", ctx, evpCipher, keyArray, ivArray, 3476 encrypting ? 1 : 0); 3477 } 3478 3479 /* 3480 * public static native int EVP_CipherUpdate(int ctx, byte[] out, int outOffset, byte[] in, 3481 * int inOffset); 3482 */ 3483 static jint NativeCrypto_EVP_CipherUpdate(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray, 3484 jint outOffset, jbyteArray inArray, jint inOffset, jint inLength) { 3485 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3486 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d)", ctx, outArray, outOffset, inArray, inOffset); 3487 3488 if (ctx == NULL) { 3489 jniThrowNullPointerException(env, "ctx == null"); 3490 JNI_TRACE("ctx=%p EVP_CipherUpdate => ctx == null", ctx); 3491 return 0; 3492 } 3493 3494 ScopedByteArrayRO inBytes(env, inArray); 3495 if (inBytes.get() == NULL) { 3496 return 0; 3497 } 3498 const size_t inSize = inBytes.size(); 3499 if (size_t(inOffset + inLength) > inSize) { 3500 jniThrowException(env, "java/lang/IndexOutOfBoundsException", 3501 "in.length < (inSize + inOffset)"); 3502 return 0; 3503 } 3504 3505 ScopedByteArrayRW outBytes(env, outArray); 3506 if (outBytes.get() == NULL) { 3507 return 0; 3508 } 3509 const size_t outSize = outBytes.size(); 3510 if (size_t(outOffset + inLength) > outSize) { 3511 jniThrowException(env, "java/lang/IndexOutOfBoundsException", 3512 "out.length < inSize + outOffset + blockSize - 1"); 3513 return 0; 3514 } 3515 3516 JNI_TRACE("ctx=%p EVP_CipherUpdate in=%p in.length=%d inOffset=%d inLength=%d out=%p out.length=%d outOffset=%d", 3517 ctx, inBytes.get(), inBytes.size(), inOffset, inLength, outBytes.get(), outBytes.size(), outOffset); 3518 3519 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get()); 3520 const unsigned char* in = reinterpret_cast<const unsigned char*>(inBytes.get()); 3521 3522 int outl; 3523 if (!EVP_CipherUpdate(ctx, out + outOffset, &outl, in + inOffset, inLength)) { 3524 throwExceptionIfNecessary(env, "EVP_CipherUpdate"); 3525 JNI_TRACE("ctx=%p EVP_CipherUpdate => threw error", ctx); 3526 return 0; 3527 } 3528 3529 JNI_TRACE("EVP_CipherUpdate(%p, %p, %d, %p, %d) => %d", ctx, outArray, outOffset, inArray, 3530 inOffset, outl); 3531 return outl; 3532 } 3533 3534 static jint NativeCrypto_EVP_CipherFinal_ex(JNIEnv* env, jclass, jlong ctxRef, jbyteArray outArray, 3535 jint outOffset) { 3536 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3537 JNI_TRACE("EVP_CipherFinal_ex(%p, %p, %d)", ctx, outArray, outOffset); 3538 3539 if (ctx == NULL) { 3540 jniThrowNullPointerException(env, "ctx == null"); 3541 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => ctx == null", ctx); 3542 return 0; 3543 } 3544 3545 ScopedByteArrayRW outBytes(env, outArray); 3546 if (outBytes.get() == NULL) { 3547 return 0; 3548 } 3549 3550 unsigned char* out = reinterpret_cast<unsigned char*>(outBytes.get()); 3551 3552 int outl; 3553 if (!EVP_CipherFinal_ex(ctx, out + outOffset, &outl)) { 3554 throwExceptionIfNecessary(env, "EVP_CipherFinal_ex"); 3555 JNI_TRACE("ctx=%p EVP_CipherFinal_ex => threw error", ctx); 3556 return 0; 3557 } 3558 3559 JNI_TRACE("EVP_CipherFinal(%p, %p, %d) => %d", ctx, outArray, outOffset, outl); 3560 return outl; 3561 } 3562 3563 static jint NativeCrypto_EVP_CIPHER_iv_length(JNIEnv* env, jclass, jlong evpCipherRef) { 3564 const EVP_CIPHER* evpCipher = reinterpret_cast<const EVP_CIPHER*>(evpCipherRef); 3565 JNI_TRACE("EVP_CIPHER_iv_length(%p)", evpCipher); 3566 3567 if (evpCipher == NULL) { 3568 jniThrowNullPointerException(env, "evpCipher == null"); 3569 JNI_TRACE("EVP_CIPHER_iv_length => evpCipher == null"); 3570 return 0; 3571 } 3572 3573 const int ivLength = EVP_CIPHER_iv_length(evpCipher); 3574 JNI_TRACE("EVP_CIPHER_iv_length(%p) => %d", evpCipher, ivLength); 3575 return ivLength; 3576 } 3577 3578 static jlong NativeCrypto_EVP_CIPHER_CTX_new(JNIEnv* env, jclass) { 3579 JNI_TRACE("EVP_CIPHER_CTX_new()"); 3580 3581 Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new()); 3582 if (ctx.get() == NULL) { 3583 jniThrowOutOfMemory(env, "Unable to allocate cipher context"); 3584 JNI_TRACE("EVP_CipherInit_ex => context allocation error"); 3585 return 0; 3586 } 3587 3588 JNI_TRACE("EVP_CIPHER_CTX_new() => %p", ctx.get()); 3589 return reinterpret_cast<uintptr_t>(ctx.release()); 3590 } 3591 3592 static jint NativeCrypto_EVP_CIPHER_CTX_block_size(JNIEnv* env, jclass, jlong ctxRef) { 3593 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3594 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p)", ctx); 3595 3596 if (ctx == NULL) { 3597 jniThrowNullPointerException(env, "ctx == null"); 3598 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_block_size => ctx == null", ctx); 3599 return 0; 3600 } 3601 3602 int blockSize = EVP_CIPHER_CTX_block_size(ctx); 3603 JNI_TRACE("EVP_CIPHER_CTX_block_size(%p) => %d", ctx, blockSize); 3604 return blockSize; 3605 } 3606 3607 static jint NativeCrypto_get_EVP_CIPHER_CTX_buf_len(JNIEnv* env, jclass, jlong ctxRef) { 3608 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3609 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p)", ctx); 3610 3611 if (ctx == NULL) { 3612 jniThrowNullPointerException(env, "ctx == null"); 3613 JNI_TRACE("ctx=%p get_EVP_CIPHER_CTX_buf_len => ctx == null", ctx); 3614 return 0; 3615 } 3616 3617 int buf_len = ctx->buf_len; 3618 JNI_TRACE("get_EVP_CIPHER_CTX_buf_len(%p) => %d", ctx, buf_len); 3619 return buf_len; 3620 } 3621 3622 static void NativeCrypto_EVP_CIPHER_CTX_set_padding(JNIEnv* env, jclass, jlong ctxRef, jboolean enablePaddingBool) { 3623 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3624 jint enablePadding = enablePaddingBool ? 1 : 0; 3625 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d)", ctx, enablePadding); 3626 3627 if (ctx == NULL) { 3628 jniThrowNullPointerException(env, "ctx == null"); 3629 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_padding => ctx == null", ctx); 3630 return; 3631 } 3632 3633 EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1. 3634 JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding); 3635 } 3636 3637 static void NativeCrypto_EVP_CIPHER_CTX_set_key_length(JNIEnv* env, jclass, jlong ctxRef, 3638 jint keySizeBits) { 3639 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3640 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d)", ctx, keySizeBits); 3641 3642 if (ctx == NULL) { 3643 jniThrowNullPointerException(env, "ctx == null"); 3644 JNI_TRACE("ctx=%p EVP_CIPHER_CTX_set_key_length => ctx == null", ctx); 3645 return; 3646 } 3647 3648 if (!EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits)) { 3649 throwExceptionIfNecessary(env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length"); 3650 JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error"); 3651 return; 3652 } 3653 JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits); 3654 } 3655 3656 static void NativeCrypto_EVP_CIPHER_CTX_cleanup(JNIEnv* env, jclass, jlong ctxRef) { 3657 EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef); 3658 JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p)", ctx); 3659 3660 if (ctx != NULL) { 3661 if (!EVP_CIPHER_CTX_cleanup(ctx)) { 3662 throwExceptionIfNecessary(env, "EVP_CIPHER_CTX_cleanup"); 3663 JNI_TRACE("EVP_CIPHER_CTX_cleanup => threw error"); 3664 return; 3665 } 3666 } 3667 JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p) => success", ctx); 3668 } 3669 3670 /** 3671 * public static native void RAND_seed(byte[]); 3672 */ 3673 static void NativeCrypto_RAND_seed(JNIEnv* env, jclass, jbyteArray seed) { 3674 JNI_TRACE("NativeCrypto_RAND_seed seed=%p", seed); 3675 ScopedByteArrayRO randseed(env, seed); 3676 if (randseed.get() == NULL) { 3677 return; 3678 } 3679 RAND_seed(randseed.get(), randseed.size()); 3680 } 3681 3682 static jint NativeCrypto_RAND_load_file(JNIEnv* env, jclass, jstring filename, jlong max_bytes) { 3683 JNI_TRACE("NativeCrypto_RAND_load_file filename=%p max_bytes=%lld", filename, max_bytes); 3684 ScopedUtfChars file(env, filename); 3685 if (file.c_str() == NULL) { 3686 return -1; 3687 } 3688 int result = RAND_load_file(file.c_str(), max_bytes); 3689 JNI_TRACE("NativeCrypto_RAND_load_file file=%s => %d", file.c_str(), result); 3690 return result; 3691 } 3692 3693 static void NativeCrypto_RAND_bytes(JNIEnv* env, jclass, jbyteArray output) { 3694 JNI_TRACE("NativeCrypto_RAND_bytes(%p)", output); 3695 3696 ScopedByteArrayRW outputBytes(env, output); 3697 if (outputBytes.get() == NULL) { 3698 return; 3699 } 3700 3701 unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get()); 3702 if (RAND_bytes(tmp, outputBytes.size()) <= 0) { 3703 throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes"); 3704 JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp); 3705 return; 3706 } 3707 3708 JNI_TRACE("NativeCrypto_RAND_bytes(%p) => success", output); 3709 } 3710 3711 static jint NativeCrypto_OBJ_txt2nid(JNIEnv* env, jclass, jstring oidStr) { 3712 JNI_TRACE("OBJ_txt2nid(%p)", oidStr); 3713 3714 ScopedUtfChars oid(env, oidStr); 3715 if (oid.c_str() == NULL) { 3716 return 0; 3717 } 3718 3719 int nid = OBJ_txt2nid(oid.c_str()); 3720 JNI_TRACE("OBJ_txt2nid(%s) => %d", oid.c_str(), nid); 3721 return nid; 3722 } 3723 3724 static jstring NativeCrypto_OBJ_txt2nid_longName(JNIEnv* env, jclass, jstring oidStr) { 3725 JNI_TRACE("OBJ_txt2nid_longName(%p)", oidStr); 3726 3727 ScopedUtfChars oid(env, oidStr); 3728 if (oid.c_str() == NULL) { 3729 return NULL; 3730 } 3731 3732 JNI_TRACE("OBJ_txt2nid_longName(%s)", oid.c_str()); 3733 3734 int nid = OBJ_txt2nid(oid.c_str()); 3735 if (nid == NID_undef) { 3736 JNI_TRACE("OBJ_txt2nid_longName(%s) => NID_undef", oid.c_str()); 3737 freeOpenSslErrorState(); 3738 return NULL; 3739 } 3740 3741 const char* longName = OBJ_nid2ln(nid); 3742 JNI_TRACE("OBJ_txt2nid_longName(%s) => %s", oid.c_str(), longName); 3743 return env->NewStringUTF(longName); 3744 } 3745 3746 static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, ASN1_OBJECT* obj) { 3747 /* 3748 * The OBJ_obj2txt API doesn't "measure" if you pass in NULL as the buffer. 3749 * Just make a buffer that's large enough here. The documentation recommends 3750 * 80 characters. 3751 */ 3752 char output[128]; 3753 int ret = OBJ_obj2txt(output, sizeof(output), obj, 1); 3754 if (ret < 0) { 3755 throwExceptionIfNecessary(env, "ASN1_OBJECT_to_OID_string"); 3756 return NULL; 3757 } else if (size_t(ret) >= sizeof(output)) { 3758 jniThrowRuntimeException(env, "ASN1_OBJECT_to_OID_string buffer too small"); 3759 return NULL; 3760 } 3761 3762 JNI_TRACE("ASN1_OBJECT_to_OID_string(%p) => %s", obj, output); 3763 return env->NewStringUTF(output); 3764 } 3765 3766 static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj) { 3767 JNI_TRACE("create_BIO_InputStream(%p)", streamObj); 3768 3769 if (streamObj == NULL) { 3770 jniThrowNullPointerException(env, "stream == null"); 3771 return 0; 3772 } 3773 3774 Unique_BIO bio(BIO_new(&stream_bio_method)); 3775 if (bio.get() == NULL) { 3776 return 0; 3777 } 3778 3779 bio_stream_assign(bio.get(), new BIO_InputStream(streamObj)); 3780 3781 JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get()); 3782 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release())); 3783 } 3784 3785 static jlong NativeCrypto_create_BIO_OutputStream(JNIEnv* env, jclass, jobject streamObj) { 3786 JNI_TRACE("create_BIO_OutputStream(%p)", streamObj); 3787 3788 if (streamObj == NULL) { 3789 jniThrowNullPointerException(env, "stream == null"); 3790 return 0; 3791 } 3792 3793 Unique_BIO bio(BIO_new(&stream_bio_method)); 3794 if (bio.get() == NULL) { 3795 return 0; 3796 } 3797 3798 bio_stream_assign(bio.get(), new BIO_OutputStream(streamObj)); 3799 3800 JNI_TRACE("create_BIO_OutputStream(%p) => %p", streamObj, bio.get()); 3801 return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release())); 3802 } 3803 3804 static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) { 3805 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 3806 JNI_TRACE("BIO_read(%p, %p)", bio, outputJavaBytes); 3807 3808 if (outputJavaBytes == NULL) { 3809 jniThrowNullPointerException(env, "output == null"); 3810 JNI_TRACE("BIO_read(%p, %p) => output == null", bio, outputJavaBytes); 3811 return 0; 3812 } 3813 3814 int outputSize = env->GetArrayLength(outputJavaBytes); 3815 3816 UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]); 3817 if (buffer.get() == NULL) { 3818 jniThrowOutOfMemory(env, "Unable to allocate buffer for read"); 3819 return 0; 3820 } 3821 3822 int read = BIO_read(bio, buffer.get(), outputSize); 3823 if (read <= 0) { 3824 jniThrowException(env, "java/io/IOException", "BIO_read"); 3825 JNI_TRACE("BIO_read(%p, %p) => threw IO exception", bio, outputJavaBytes); 3826 return 0; 3827 } 3828 3829 env->SetByteArrayRegion(outputJavaBytes, 0, read, reinterpret_cast<jbyte*>(buffer.get())); 3830 JNI_TRACE("BIO_read(%p, %p) => %d", bio, outputJavaBytes, read); 3831 return read; 3832 } 3833 3834 static void NativeCrypto_BIO_write(JNIEnv* env, jclass, jlong bioRef, jbyteArray inputJavaBytes, 3835 jint offset, jint length) { 3836 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 3837 JNI_TRACE("BIO_write(%p, %p, %d, %d)", bio, inputJavaBytes, offset, length); 3838 3839 if (inputJavaBytes == NULL) { 3840 jniThrowNullPointerException(env, "input == null"); 3841 return; 3842 } 3843 3844 if (offset < 0 || length < 0) { 3845 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "offset < 0 || length < 0"); 3846 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length); 3847 return; 3848 } 3849 3850 int inputSize = env->GetArrayLength(inputJavaBytes); 3851 if (inputSize < offset + length) { 3852 jniThrowException(env, "java/lang/IndexOutOfBoundsException", 3853 "input.length < offset + length"); 3854 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IOOB", bio, inputJavaBytes, offset, length); 3855 return; 3856 } 3857 3858 UniquePtr<unsigned char[]> buffer(new unsigned char[length]); 3859 if (buffer.get() == NULL) { 3860 jniThrowOutOfMemory(env, "Unable to allocate buffer for write"); 3861 return; 3862 } 3863 3864 env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get())); 3865 if (BIO_write(bio, buffer.get(), length) != length) { 3866 freeOpenSslErrorState(); 3867 jniThrowException(env, "java/io/IOException", "BIO_write"); 3868 JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length); 3869 return; 3870 } 3871 3872 JNI_TRACE("BIO_write(%p, %p, %d, %d) => success", bio, inputJavaBytes, offset, length); 3873 } 3874 3875 static void NativeCrypto_BIO_free(JNIEnv* env, jclass, jlong bioRef) { 3876 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 3877 JNI_TRACE("BIO_free(%p)", bio); 3878 3879 if (bio == NULL) { 3880 jniThrowNullPointerException(env, "bio == null"); 3881 return; 3882 } 3883 3884 BIO_free(bio); 3885 } 3886 3887 static jstring X509_NAME_to_jstring(JNIEnv* env, X509_NAME* name, unsigned long flags) { 3888 JNI_TRACE("X509_NAME_to_jstring(%p)", name); 3889 3890 Unique_BIO buffer(BIO_new(BIO_s_mem())); 3891 if (buffer.get() == NULL) { 3892 jniThrowOutOfMemory(env, "Unable to allocate BIO"); 3893 JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name); 3894 return NULL; 3895 } 3896 3897 /* Don't interpret the string. */ 3898 flags &= ~(ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_MSB); 3899 3900 /* Write in given format and null terminate. */ 3901 X509_NAME_print_ex(buffer.get(), name, 0, flags); 3902 BIO_write(buffer.get(), "\0", 1); 3903 3904 char *tmp; 3905 BIO_get_mem_data(buffer.get(), &tmp); 3906 JNI_TRACE("X509_NAME_to_jstring(%p) => \"%s\"", name, tmp); 3907 return env->NewStringUTF(tmp); 3908 } 3909 3910 3911 /** 3912 * Converts GENERAL_NAME items to the output format expected in 3913 * X509Certificate#getSubjectAlternativeNames and 3914 * X509Certificate#getIssuerAlternativeNames return. 3915 */ 3916 static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) { 3917 switch (gen->type) { 3918 case GEN_EMAIL: 3919 case GEN_DNS: 3920 case GEN_URI: { 3921 // This must not be a T61String and must not contain NULLs. 3922 const char* data = reinterpret_cast<const char*>(ASN1_STRING_data(gen->d.ia5)); 3923 ssize_t len = ASN1_STRING_length(gen->d.ia5); 3924 if ((len == static_cast<ssize_t>(strlen(data))) 3925 && (ASN1_PRINTABLE_type(ASN1_STRING_data(gen->d.ia5), len) != V_ASN1_T61STRING)) { 3926 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI \"%s\"", gen, data); 3927 return env->NewStringUTF(data); 3928 } else { 3929 jniThrowException(env, "java/security/cert/CertificateParsingException", 3930 "Invalid dNSName encoding"); 3931 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => Email/DNS/URI invalid", gen); 3932 return NULL; 3933 } 3934 } 3935 case GEN_DIRNAME: 3936 /* Write in RFC 2253 format */ 3937 return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253); 3938 case GEN_IPADD: { 3939 const void *ip = reinterpret_cast<const void *>(gen->d.ip->data); 3940 if (gen->d.ip->length == 4) { 3941 // IPv4 3942 UniquePtr<char[]> buffer(new char[INET_ADDRSTRLEN]); 3943 if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != NULL) { 3944 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 %s", gen, buffer.get()); 3945 return env->NewStringUTF(buffer.get()); 3946 } else { 3947 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen, strerror(errno)); 3948 } 3949 } else if (gen->d.ip->length == 16) { 3950 // IPv6 3951 UniquePtr<char[]> buffer(new char[INET6_ADDRSTRLEN]); 3952 if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != NULL) { 3953 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 %s", gen, buffer.get()); 3954 return env->NewStringUTF(buffer.get()); 3955 } else { 3956 JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv6 failed %s", gen, strerror(errno)); 3957 } 3958 } 3959 3960 /* Invalid IP encodings are pruned out without throwing an exception. */ 3961 return NULL; 3962 } 3963 case GEN_RID: 3964 return ASN1_OBJECT_to_OID_string(env, gen->d.registeredID); 3965 case GEN_OTHERNAME: 3966 case GEN_X400: 3967 default: 3968 return ASN1ToByteArray<GENERAL_NAME, i2d_GENERAL_NAME>(env, gen); 3969 } 3970 3971 return NULL; 3972 } 3973 3974 #define GN_STACK_SUBJECT_ALT_NAME 1 3975 #define GN_STACK_ISSUER_ALT_NAME 2 3976 3977 static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass, jlong x509Ref, 3978 jint type) { 3979 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 3980 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d)", x509, type); 3981 3982 if (x509 == NULL) { 3983 jniThrowNullPointerException(env, "x509 == null"); 3984 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => x509 == null", x509, type); 3985 return NULL; 3986 } 3987 3988 X509_check_ca(x509); 3989 3990 STACK_OF(GENERAL_NAME)* gn_stack; 3991 Unique_sk_GENERAL_NAME stackHolder; 3992 if (type == GN_STACK_SUBJECT_ALT_NAME) { 3993 gn_stack = x509->altname; 3994 } else if (type == GN_STACK_ISSUER_ALT_NAME) { 3995 stackHolder.reset( 3996 static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(x509, NID_issuer_alt_name, 3997 NULL, NULL))); 3998 gn_stack = stackHolder.get(); 3999 } else { 4000 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => unknown type", x509, type); 4001 return NULL; 4002 } 4003 4004 int count = sk_GENERAL_NAME_num(gn_stack); 4005 if (count <= 0) { 4006 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => null (no entries)", x509, type); 4007 return NULL; 4008 } 4009 4010 /* 4011 * Keep track of how many originally so we can ignore any invalid 4012 * values later. 4013 */ 4014 const int origCount = count; 4015 4016 ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL)); 4017 for (int i = 0, j = 0; i < origCount; i++, j++) { 4018 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i); 4019 ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen)); 4020 if (env->ExceptionCheck()) { 4021 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => threw exception parsing gen name", 4022 x509, type); 4023 return NULL; 4024 } 4025 4026 /* 4027 * If it's NULL, we'll have to skip this, reduce the number of total 4028 * entries, and fix up the array later. 4029 */ 4030 if (val.get() == NULL) { 4031 j--; 4032 count--; 4033 continue; 4034 } 4035 4036 ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL)); 4037 4038 ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass, 4039 integer_valueOfMethod, gen->type)); 4040 env->SetObjectArrayElement(item.get(), 0, type.get()); 4041 env->SetObjectArrayElement(item.get(), 1, val.get()); 4042 4043 env->SetObjectArrayElement(joa.get(), j, item.get()); 4044 } 4045 4046 if (count == 0) { 4047 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to 0; returning NULL", 4048 x509, type, origCount); 4049 joa.reset(NULL); 4050 } else if (origCount != count) { 4051 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type, 4052 origCount, count); 4053 4054 ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass, 4055 NULL)); 4056 4057 for (int i = 0; i < count; i++) { 4058 ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i)); 4059 env->SetObjectArrayElement(joa_copy.get(), i, item.get()); 4060 } 4061 4062 joa.reset(joa_copy.release()); 4063 } 4064 4065 JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) => %d entries", x509, type, count); 4066 return joa.release(); 4067 } 4068 4069 static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref) { 4070 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4071 JNI_TRACE("X509_get_notBefore(%p)", x509); 4072 4073 if (x509 == NULL) { 4074 jniThrowNullPointerException(env, "x509 == null"); 4075 JNI_TRACE("X509_get_notBefore(%p) => x509 == null", x509); 4076 return 0; 4077 } 4078 4079 ASN1_TIME* notBefore = X509_get_notBefore(x509); 4080 JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore); 4081 return reinterpret_cast<uintptr_t>(notBefore); 4082 } 4083 4084 static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref) { 4085 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4086 JNI_TRACE("X509_get_notAfter(%p)", x509); 4087 4088 if (x509 == NULL) { 4089 jniThrowNullPointerException(env, "x509 == null"); 4090 JNI_TRACE("X509_get_notAfter(%p) => x509 == null", x509); 4091 return 0; 4092 } 4093 4094 ASN1_TIME* notAfter = X509_get_notAfter(x509); 4095 JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter); 4096 return reinterpret_cast<uintptr_t>(notAfter); 4097 } 4098 4099 static long NativeCrypto_X509_get_version(JNIEnv*, jclass, jlong x509Ref) { 4100 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4101 JNI_TRACE("X509_get_version(%p)", x509); 4102 4103 long version = X509_get_version(x509); 4104 JNI_TRACE("X509_get_version(%p) => %ld", x509, version); 4105 return version; 4106 } 4107 4108 template<typename T> 4109 static jbyteArray get_X509Type_serialNumber(JNIEnv* env, T* x509Type, ASN1_INTEGER* (*get_serial_func)(T*)) { 4110 JNI_TRACE("get_X509Type_serialNumber(%p)", x509Type); 4111 4112 if (x509Type == NULL) { 4113 jniThrowNullPointerException(env, "x509Type == null"); 4114 JNI_TRACE("get_X509Type_serialNumber(%p) => x509Type == null", x509Type); 4115 return NULL; 4116 } 4117 4118 ASN1_INTEGER* serialNumber = get_serial_func(x509Type); 4119 Unique_BIGNUM serialBn(ASN1_INTEGER_to_BN(serialNumber, NULL)); 4120 if (serialBn.get() == NULL) { 4121 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type); 4122 return NULL; 4123 } 4124 4125 ScopedLocalRef<jbyteArray> serialArray(env, bignumToArray(env, serialBn.get(), "serialBn")); 4126 if (env->ExceptionCheck()) { 4127 JNI_TRACE("X509_get_serialNumber(%p) => threw exception", x509Type); 4128 return NULL; 4129 } 4130 4131 JNI_TRACE("X509_get_serialNumber(%p) => %p", x509Type, serialArray.get()); 4132 return serialArray.release(); 4133 } 4134 4135 /* OpenSSL includes set_serialNumber but not get. */ 4136 #if !defined(X509_REVOKED_get_serialNumber) 4137 static ASN1_INTEGER* X509_REVOKED_get_serialNumber(X509_REVOKED* x) { 4138 return x->serialNumber; 4139 } 4140 #endif 4141 4142 static jbyteArray NativeCrypto_X509_get_serialNumber(JNIEnv* env, jclass, jlong x509Ref) { 4143 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4144 JNI_TRACE("X509_get_serialNumber(%p)", x509); 4145 return get_X509Type_serialNumber<X509>(env, x509, X509_get_serialNumber); 4146 } 4147 4148 static jbyteArray NativeCrypto_X509_REVOKED_get_serialNumber(JNIEnv* env, jclass, jlong x509RevokedRef) { 4149 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4150 JNI_TRACE("X509_REVOKED_get_serialNumber(%p)", revoked); 4151 return get_X509Type_serialNumber<X509_REVOKED>(env, revoked, X509_REVOKED_get_serialNumber); 4152 } 4153 4154 static void NativeCrypto_X509_verify(JNIEnv* env, jclass, jlong x509Ref, jlong pkeyRef) { 4155 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4156 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 4157 JNI_TRACE("X509_verify(%p, %p)", x509, pkey); 4158 4159 if (x509 == NULL) { 4160 jniThrowNullPointerException(env, "x509 == null"); 4161 JNI_TRACE("X509_verify(%p, %p) => x509 == null", x509, pkey); 4162 return; 4163 } 4164 4165 if (pkey == NULL) { 4166 jniThrowNullPointerException(env, "pkey == null"); 4167 JNI_TRACE("X509_verify(%p, %p) => pkey == null", x509, pkey); 4168 return; 4169 } 4170 4171 if (X509_verify(x509, pkey) != 1) { 4172 throwExceptionIfNecessary(env, "X509_verify"); 4173 JNI_TRACE("X509_verify(%p, %p) => verify failure", x509, pkey); 4174 } else { 4175 JNI_TRACE("X509_verify(%p, %p) => verify success", x509, pkey); 4176 } 4177 } 4178 4179 static jbyteArray NativeCrypto_get_X509_cert_info_enc(JNIEnv* env, jclass, jlong x509Ref) { 4180 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4181 JNI_TRACE("get_X509_cert_info_enc(%p)", x509); 4182 return ASN1ToByteArray<X509_CINF, i2d_X509_CINF>(env, x509->cert_info); 4183 } 4184 4185 static jint NativeCrypto_get_X509_ex_flags(JNIEnv* env, jclass, jlong x509Ref) { 4186 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4187 JNI_TRACE("get_X509_ex_flags(%p)", x509); 4188 4189 if (x509 == NULL) { 4190 jniThrowNullPointerException(env, "x509 == null"); 4191 JNI_TRACE("get_X509_ex_flags(%p) => x509 == null", x509); 4192 return 0; 4193 } 4194 4195 X509_check_ca(x509); 4196 4197 return x509->ex_flags; 4198 } 4199 4200 static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) { 4201 X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1)); 4202 X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2)); 4203 JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2); 4204 4205 int ret = X509_check_issued(x509_1, x509_2); 4206 JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret); 4207 return ret; 4208 } 4209 4210 static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) { 4211 *signature = x509->signature; 4212 } 4213 4214 static void get_X509_CRL_signature(X509_CRL *crl, ASN1_BIT_STRING** signature) { 4215 *signature = crl->signature; 4216 } 4217 4218 template<typename T> 4219 static jbyteArray get_X509Type_signature(JNIEnv* env, T* x509Type, void (*get_signature_func)(T*, ASN1_BIT_STRING**)) { 4220 JNI_TRACE("get_X509Type_signature(%p)", x509Type); 4221 4222 if (x509Type == NULL) { 4223 jniThrowNullPointerException(env, "x509Type == null"); 4224 JNI_TRACE("get_X509Type_signature(%p) => x509Type == null", x509Type); 4225 return NULL; 4226 } 4227 4228 ASN1_BIT_STRING* signature; 4229 get_signature_func(x509Type, &signature); 4230 4231 ScopedLocalRef<jbyteArray> signatureArray(env, env->NewByteArray(signature->length)); 4232 if (env->ExceptionCheck()) { 4233 JNI_TRACE("get_X509Type_signature(%p) => threw exception", x509Type); 4234 return NULL; 4235 } 4236 4237 ScopedByteArrayRW signatureBytes(env, signatureArray.get()); 4238 if (signatureBytes.get() == NULL) { 4239 JNI_TRACE("get_X509Type_signature(%p) => using byte array failed", x509Type); 4240 return NULL; 4241 } 4242 4243 memcpy(signatureBytes.get(), signature->data, signature->length); 4244 4245 JNI_TRACE("get_X509Type_signature(%p) => %p (%d bytes)", x509Type, signatureArray.get(), 4246 signature->length); 4247 return signatureArray.release(); 4248 } 4249 4250 static jbyteArray NativeCrypto_get_X509_signature(JNIEnv* env, jclass, jlong x509Ref) { 4251 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4252 JNI_TRACE("get_X509_signature(%p)", x509); 4253 return get_X509Type_signature<X509>(env, x509, get_X509_signature); 4254 } 4255 4256 static jbyteArray NativeCrypto_get_X509_CRL_signature(JNIEnv* env, jclass, jlong x509CrlRef) { 4257 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4258 JNI_TRACE("get_X509_CRL_signature(%p)", crl); 4259 return get_X509Type_signature<X509_CRL>(env, crl, get_X509_CRL_signature); 4260 } 4261 4262 static jlong NativeCrypto_X509_CRL_get0_by_cert(JNIEnv* env, jclass, jlong x509crlRef, jlong x509Ref) { 4263 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef)); 4264 X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); 4265 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p)", x509crl, x509); 4266 4267 if (x509crl == NULL) { 4268 jniThrowNullPointerException(env, "x509crl == null"); 4269 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509crl == null", x509crl, x509); 4270 return 0; 4271 } else if (x509 == NULL) { 4272 jniThrowNullPointerException(env, "x509 == null"); 4273 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => x509 == null", x509crl, x509); 4274 return 0; 4275 } 4276 4277 X509_REVOKED* revoked = NULL; 4278 int ret = X509_CRL_get0_by_cert(x509crl, &revoked, x509); 4279 if (ret == 0) { 4280 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => none", x509crl, x509); 4281 return 0; 4282 } 4283 4284 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, x509, revoked); 4285 return reinterpret_cast<uintptr_t>(revoked); 4286 } 4287 4288 static jlong NativeCrypto_X509_CRL_get0_by_serial(JNIEnv* env, jclass, jlong x509crlRef, jbyteArray serialArray) { 4289 X509_CRL* x509crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509crlRef)); 4290 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p)", x509crl, serialArray); 4291 4292 if (x509crl == NULL) { 4293 jniThrowNullPointerException(env, "x509crl == null"); 4294 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => crl == null", x509crl, serialArray); 4295 return 0; 4296 } 4297 4298 Unique_BIGNUM serialBn(BN_new()); 4299 if (serialBn.get() == NULL) { 4300 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN allocation failed", x509crl, serialArray); 4301 return 0; 4302 } 4303 4304 BIGNUM* serialBare = serialBn.get(); 4305 if (!arrayToBignum(env, serialArray, &serialBare)) { 4306 if (!env->ExceptionCheck()) { 4307 jniThrowNullPointerException(env, "serial == null"); 4308 } 4309 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray); 4310 return 0; 4311 } 4312 4313 Unique_ASN1_INTEGER serialInteger(BN_to_ASN1_INTEGER(serialBn.get(), NULL)); 4314 if (serialInteger.get() == NULL) { 4315 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => BN conversion failed", x509crl, serialArray); 4316 return 0; 4317 } 4318 4319 X509_REVOKED* revoked = NULL; 4320 int ret = X509_CRL_get0_by_serial(x509crl, &revoked, serialInteger.get()); 4321 if (ret == 0) { 4322 JNI_TRACE("X509_CRL_get0_by_serial(%p, %p) => none", x509crl, serialArray); 4323 return 0; 4324 } 4325 4326 JNI_TRACE("X509_CRL_get0_by_cert(%p, %p) => %p", x509crl, serialArray, revoked); 4327 return reinterpret_cast<uintptr_t>(revoked); 4328 } 4329 4330 4331 /* This appears to be missing from OpenSSL. */ 4332 #if !defined(X509_REVOKED_dup) 4333 X509_REVOKED* X509_REVOKED_dup(X509_REVOKED* x) { 4334 return reinterpret_cast<X509_REVOKED*>(ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), x)); 4335 } 4336 #endif 4337 4338 static jlongArray NativeCrypto_X509_CRL_get_REVOKED(JNIEnv* env, jclass, jlong x509CrlRef) { 4339 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4340 JNI_TRACE("X509_CRL_get_REVOKED(%p)", crl); 4341 4342 if (crl == NULL) { 4343 jniThrowNullPointerException(env, "crl == null"); 4344 return NULL; 4345 } 4346 4347 STACK_OF(X509_REVOKED)* stack = X509_CRL_get_REVOKED(crl); 4348 if (stack == NULL) { 4349 JNI_TRACE("X509_CRL_get_REVOKED(%p) => stack is null", crl); 4350 return NULL; 4351 } 4352 4353 size_t size = sk_X509_REVOKED_num(stack); 4354 4355 ScopedLocalRef<jlongArray> revokedArray(env, env->NewLongArray(size)); 4356 ScopedLongArrayRW revoked(env, revokedArray.get()); 4357 for (size_t i = 0; i < size; i++) { 4358 X509_REVOKED* item = reinterpret_cast<X509_REVOKED*>(sk_X509_REVOKED_value(stack, i)); 4359 revoked[i] = reinterpret_cast<uintptr_t>(X509_REVOKED_dup(item)); 4360 } 4361 4362 JNI_TRACE("X509_CRL_get_REVOKED(%p) => %p [size=%d]", stack, revokedArray.get(), size); 4363 return revokedArray.release(); 4364 } 4365 4366 static jbyteArray NativeCrypto_i2d_X509_CRL(JNIEnv* env, jclass, jlong x509CrlRef) { 4367 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4368 JNI_TRACE("i2d_X509_CRL(%p)", crl); 4369 return ASN1ToByteArray<X509_CRL, i2d_X509_CRL>(env, crl); 4370 } 4371 4372 static void NativeCrypto_X509_CRL_free(JNIEnv* env, jclass, jlong x509CrlRef) { 4373 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4374 JNI_TRACE("X509_CRL_free(%p)", crl); 4375 4376 if (crl == NULL) { 4377 jniThrowNullPointerException(env, "crl == null"); 4378 JNI_TRACE("X509_CRL_free(%p) => crl == null", crl); 4379 return; 4380 } 4381 4382 X509_CRL_free(crl); 4383 } 4384 4385 static void NativeCrypto_X509_CRL_print(JNIEnv* env, jclass, jlong bioRef, jlong x509CrlRef) { 4386 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 4387 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4388 JNI_TRACE("X509_CRL_print(%p, %p)", bio, crl); 4389 4390 if (bio == NULL) { 4391 jniThrowNullPointerException(env, "bio == null"); 4392 JNI_TRACE("X509_CRL_print(%p, %p) => bio == null", bio, crl); 4393 return; 4394 } 4395 4396 if (crl == NULL) { 4397 jniThrowNullPointerException(env, "crl == null"); 4398 JNI_TRACE("X509_CRL_print(%p, %p) => crl == null", bio, crl); 4399 return; 4400 } 4401 4402 if (!X509_CRL_print(bio, crl)) { 4403 throwExceptionIfNecessary(env, "X509_CRL_print"); 4404 JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl); 4405 } else { 4406 JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl); 4407 } 4408 } 4409 4410 static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) { 4411 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4412 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p)", crl); 4413 4414 if (crl == NULL || crl->sig_alg == NULL) { 4415 jniThrowNullPointerException(env, "crl == NULL || crl->sig_alg == NULL"); 4416 JNI_TRACE("get_X509_CRL_sig_alg_oid(%p) => crl == NULL", crl); 4417 return NULL; 4418 } 4419 4420 return ASN1_OBJECT_to_OID_string(env, crl->sig_alg->algorithm); 4421 } 4422 4423 static jbyteArray NativeCrypto_get_X509_CRL_sig_alg_parameter(JNIEnv* env, jclass, jlong x509CrlRef) { 4424 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4425 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p)", crl); 4426 4427 if (crl == NULL) { 4428 jniThrowNullPointerException(env, "crl == null"); 4429 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => crl == null", crl); 4430 return NULL; 4431 } 4432 4433 if (crl->sig_alg->parameter == NULL) { 4434 JNI_TRACE("get_X509_CRL_sig_alg_parameter(%p) => null", crl); 4435 return NULL; 4436 } 4437 4438 return ASN1ToByteArray<ASN1_TYPE, i2d_ASN1_TYPE>(env, crl->sig_alg->parameter); 4439 } 4440 4441 static jbyteArray NativeCrypto_X509_CRL_get_issuer_name(JNIEnv* env, jclass, jlong x509CrlRef) { 4442 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4443 JNI_TRACE("X509_CRL_get_issuer_name(%p)", crl); 4444 return ASN1ToByteArray<X509_NAME, i2d_X509_NAME>(env, X509_CRL_get_issuer(crl)); 4445 } 4446 4447 static long NativeCrypto_X509_CRL_get_version(JNIEnv*, jclass, jlong x509CrlRef) { 4448 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4449 JNI_TRACE("X509_CRL_get_version(%p)", crl); 4450 4451 long version = X509_CRL_get_version(crl); 4452 JNI_TRACE("X509_CRL_get_version(%p) => %ld", crl, version); 4453 return version; 4454 } 4455 4456 template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int), 4457 X509_EXTENSION* (*get_ext_func)(T*, int)> 4458 static X509_EXTENSION *X509Type_get_ext(JNIEnv* env, T* x509Type, jstring oidString) { 4459 JNI_TRACE("X509Type_get_ext(%p)", x509Type); 4460 4461 if (x509Type == NULL) { 4462 jniThrowNullPointerException(env, "x509 == null"); 4463 return NULL; 4464 } 4465 4466 ScopedUtfChars oid(env, oidString); 4467 if (oid.c_str() == NULL) { 4468 return NULL; 4469 } 4470 4471 Unique_ASN1_OBJECT asn1(OBJ_txt2obj(oid.c_str(), 1)); 4472 if (asn1.get() == NULL) { 4473 JNI_TRACE("X509Type_get_ext(%p, %s) => oid conversion failed", x509Type, oid.c_str()); 4474 freeOpenSslErrorState(); 4475 return NULL; 4476 } 4477 4478 int extIndex = get_ext_by_OBJ_func(x509Type, asn1.get(), -1); 4479 if (extIndex == -1) { 4480 JNI_TRACE("X509Type_get_ext(%p, %s) => ext not found", x509Type, oid.c_str()); 4481 return NULL; 4482 } 4483 4484 X509_EXTENSION* ext = get_ext_func(x509Type, extIndex); 4485 JNI_TRACE("X509Type_get_ext(%p, %s) => %p", x509Type, oid.c_str(), ext); 4486 return ext; 4487 } 4488 4489 template<typename T, int (*get_ext_by_OBJ_func)(T*, ASN1_OBJECT*, int), 4490 X509_EXTENSION* (*get_ext_func)(T*, int)> 4491 static jbyteArray X509Type_get_ext_oid(JNIEnv* env, T* x509Type, jstring oidString) { 4492 X509_EXTENSION* ext = X509Type_get_ext<T, get_ext_by_OBJ_func, get_ext_func>(env, x509Type, 4493 oidString); 4494 if (ext == NULL) { 4495 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => fetching extension failed", x509Type, oidString); 4496 return NULL; 4497 } 4498 4499 JNI_TRACE("X509Type_get_ext_oid(%p, %p) => %p", x509Type, oidString, ext->value); 4500 return ASN1ToByteArray<ASN1_OCTET_STRING, i2d_ASN1_OCTET_STRING>(env, ext->value); 4501 } 4502 4503 static jint NativeCrypto_X509_CRL_get_ext(JNIEnv* env, jclass, jlong x509CrlRef, jstring oid) { 4504 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4505 JNI_TRACE("X509_CRL_get_ext(%p, %p)", crl, oid); 4506 X509_EXTENSION* ext = X509Type_get_ext<X509_CRL, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext>( 4507 env, crl, oid); 4508 JNI_TRACE("X509_CRL_get_ext(%p, %p) => %p", crl, oid, ext); 4509 return reinterpret_cast<uintptr_t>(ext); 4510 } 4511 4512 static jint NativeCrypto_X509_REVOKED_get_ext(JNIEnv* env, jclass, jlong x509RevokedRef, 4513 jstring oid) { 4514 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4515 JNI_TRACE("X509_REVOKED_get_ext(%p, %p)", revoked, oid); 4516 X509_EXTENSION* ext = X509Type_get_ext<X509_REVOKED, X509_REVOKED_get_ext_by_OBJ, 4517 X509_REVOKED_get_ext>(env, revoked, oid); 4518 JNI_TRACE("X509_REVOKED_get_ext(%p, %p) => %p", revoked, oid, ext); 4519 return reinterpret_cast<uintptr_t>(ext); 4520 } 4521 4522 static jlong NativeCrypto_X509_REVOKED_dup(JNIEnv* env, jclass, jlong x509RevokedRef) { 4523 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4524 JNI_TRACE("X509_REVOKED_dup(%p)", revoked); 4525 4526 if (revoked == NULL) { 4527 jniThrowNullPointerException(env, "revoked == null"); 4528 JNI_TRACE("X509_REVOKED_dup(%p) => revoked == null", revoked); 4529 return 0; 4530 } 4531 4532 X509_REVOKED* dup = X509_REVOKED_dup(revoked); 4533 JNI_TRACE("X509_REVOKED_dup(%p) => %p", revoked, dup); 4534 return reinterpret_cast<uintptr_t>(dup); 4535 } 4536 4537 static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass, jlong x509RevokedRef) { 4538 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4539 JNI_TRACE("get_X509_REVOKED_revocationDate(%p)", revoked); 4540 4541 if (revoked == NULL) { 4542 jniThrowNullPointerException(env, "revoked == null"); 4543 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => revoked == null", revoked); 4544 return 0; 4545 } 4546 4547 JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked, revoked->revocationDate); 4548 return reinterpret_cast<uintptr_t>(revoked->revocationDate); 4549 } 4550 4551 #pragma GCC diagnostic push 4552 #pragma GCC diagnostic ignored "-Wwrite-strings" 4553 static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) { 4554 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 4555 X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4556 JNI_TRACE("X509_REVOKED_print(%p, %p)", bio, revoked); 4557 4558 if (bio == NULL) { 4559 jniThrowNullPointerException(env, "bio == null"); 4560 JNI_TRACE("X509_REVOKED_print(%p, %p) => bio == null", bio, revoked); 4561 return; 4562 } 4563 4564 if (revoked == NULL) { 4565 jniThrowNullPointerException(env, "revoked == null"); 4566 JNI_TRACE("X509_REVOKED_print(%p, %p) => revoked == null", bio, revoked); 4567 return; 4568 } 4569 4570 BIO_printf(bio, "Serial Number: "); 4571 i2a_ASN1_INTEGER(bio, revoked->serialNumber); 4572 BIO_printf(bio, "\nRevocation Date: "); 4573 ASN1_TIME_print(bio, revoked->revocationDate); 4574 BIO_printf(bio, "\n"); 4575 X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0); 4576 } 4577 #pragma GCC diagnostic pop 4578 4579 static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) { 4580 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4581 JNI_TRACE("get_X509_CRL_crl_enc(%p)", crl); 4582 return ASN1ToByteArray<X509_CRL_INFO, i2d_X509_CRL_INFO>(env, crl->crl); 4583 } 4584 4585 static void NativeCrypto_X509_CRL_verify(JNIEnv* env, jclass, jlong x509CrlRef, jlong pkeyRef) { 4586 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4587 EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); 4588 JNI_TRACE("X509_CRL_verify(%p, %p)", crl, pkey); 4589 4590 if (crl == NULL) { 4591 jniThrowNullPointerException(env, "crl == null"); 4592 JNI_TRACE("X509_CRL_verify(%p, %p) => crl == null", crl, pkey); 4593 return; 4594 } 4595 4596 if (pkey == NULL) { 4597 jniThrowNullPointerException(env, "pkey == null"); 4598 JNI_TRACE("X509_CRL_verify(%p, %p) => pkey == null", crl, pkey); 4599 return; 4600 } 4601 4602 if (X509_CRL_verify(crl, pkey) != 1) { 4603 throwExceptionIfNecessary(env, "X509_CRL_verify"); 4604 JNI_TRACE("X509_CRL_verify(%p, %p) => verify failure", crl, pkey); 4605 } else { 4606 JNI_TRACE("X509_CRL_verify(%p, %p) => verify success", crl, pkey); 4607 } 4608 } 4609 4610 static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x509CrlRef) { 4611 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4612 JNI_TRACE("X509_CRL_get_lastUpdate(%p)", crl); 4613 4614 if (crl == NULL) { 4615 jniThrowNullPointerException(env, "crl == null"); 4616 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => crl == null", crl); 4617 return 0; 4618 } 4619 4620 ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl); 4621 JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate); 4622 return reinterpret_cast<uintptr_t>(lastUpdate); 4623 } 4624 4625 static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef) { 4626 X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef)); 4627 JNI_TRACE("X509_CRL_get_nextUpdate(%p)", crl); 4628 4629 if (crl == NULL) { 4630 jniThrowNullPointerException(env, "crl == null"); 4631 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => crl == null", crl); 4632 return 0; 4633 } 4634 4635 ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl); 4636 JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate); 4637 return reinterpret_cast<uintptr_t>(nextUpdate); 4638 } 4639 4640 static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) { 4641 X509_REVOKED* x509Revoked = 4642 reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef)); 4643 JNI_TRACE("i2d_X509_REVOKED(%p)", x509Revoked); 4644 return ASN1ToByteArray<X509_REVOKED, i2d_X509_REVOKED>(env, x509Revoked); 4645 } 4646 4647 static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x509ExtensionRef) { 4648 X509_EXTENSION* ext = reinterpret_cast<X509_EXTENSION*>(static_cast<uintptr_t>(x509ExtensionRef)); 4649 4650 if (ext == NULL) { 4651 jniThrowNullPointerException(env, "ext == NULL"); 4652 return 0; 4653 } 4654 4655 return X509_supported_extension(ext); 4656 } 4657 4658 static inline void get_ASN1_TIME_data(char **data, int* output, size_t len) { 4659 char c = **data; 4660 **data = '\0'; 4661 *data -= len; 4662 *output = atoi(*data); 4663 *(*data + len) = c; 4664 } 4665 4666 static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef, jobject calendar) { 4667 ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef)); 4668 JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar); 4669 4670 if (asn1Time == NULL) { 4671 jniThrowNullPointerException(env, "asn1Time == null"); 4672 return; 4673 } 4674 4675 Unique_ASN1_GENERALIZEDTIME gen(ASN1_TIME_to_generalizedtime(asn1Time, NULL)); 4676 if (gen.get() == NULL) { 4677 jniThrowNullPointerException(env, "asn1Time == null"); 4678 return; 4679 } 4680 4681 if (gen->length < 14 || gen->data == NULL) { 4682 jniThrowNullPointerException(env, "gen->length < 14 || gen->data == NULL"); 4683 return; 4684 } 4685 4686 int sec, min, hour, mday, mon, year; 4687 4688 char *p = (char*) &gen->data[14]; 4689 4690 get_ASN1_TIME_data(&p, &sec, 2); 4691 get_ASN1_TIME_data(&p, &min, 2); 4692 get_ASN1_TIME_data(&p, &hour, 2); 4693 get_ASN1_TIME_data(&p, &mday, 2); 4694 get_ASN1_TIME_data(&p, &mon, 2); 4695 get_ASN1_TIME_data(&p, &year, 4); 4696 4697 env->CallVoidMethod(calendar, calendar_setMethod, year, mon - 1, mday, hour, min, sec); 4698 } 4699 4700 static jstring NativeCrypto_OBJ_txt2nid_oid(JNIEnv* env, jclass, jstring oidStr) { 4701 JNI_TRACE("OBJ_txt2nid_oid(%p)", oidStr); 4702 4703 ScopedUtfChars oid(env, oidStr); 4704 if (oid.c_str() == NULL) { 4705 return NULL; 4706 } 4707 4708 JNI_TRACE("OBJ_txt2nid_oid(%s)", oid.c_str()); 4709 4710 int nid = OBJ_txt2nid(oid.c_str()); 4711 if (nid == NID_undef) { 4712 JNI_TRACE("OBJ_txt2nid_oid(%s) => NID_undef", oid.c_str()); 4713 freeOpenSslErrorState(); 4714 return NULL; 4715 } 4716 4717 Unique_ASN1_OBJECT obj(OBJ_nid2obj(nid)); 4718 if (obj.get() == NULL) { 4719 throwExceptionIfNecessary(env, "OBJ_nid2obj"); 4720 return NULL; 4721 } 4722 4723 ScopedLocalRef<jstring> ouputStr(env, ASN1_OBJECT_to_OID_string(env, obj.get())); 4724 JNI_TRACE("OBJ_txt2nid_oid(%s) => %p", oid.c_str(), ouputStr.get()); 4725 return ouputStr.release(); 4726 } 4727 4728 static jstring NativeCrypto_X509_NAME_print_ex(JNIEnv* env, jclass, jlong x509NameRef, jlong jflags) { 4729 X509_NAME* x509name = reinterpret_cast<X509_NAME*>(static_cast<uintptr_t>(x509NameRef)); 4730 unsigned long flags = static_cast<unsigned long>(jflags); 4731 JNI_TRACE("X509_NAME_print_ex(%p, %ld)", x509name, flags); 4732 4733 if (x509name == NULL) { 4734 jniThrowNullPointerException(env, "x509name == null"); 4735 JNI_TRACE("X509_NAME_print_ex(%p, %ld) => x509name == null", x509name, flags); 4736 return NULL; 4737 } 4738 4739 return X509_NAME_to_jstring(env, x509name, flags); 4740 } 4741 4742 template <typename T, T* (*d2i_func)(BIO*, T**)> 4743 static jlong d2i_ASN1Object_to_jlong(JNIEnv* env, jlong bioRef) { 4744 BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef)); 4745 JNI_TRACE("d2i_ASN1Object_to_jlong(%p)", bio); 4746 4747 if (bio == NULL) { 4748 jniThrowNullPointerException(env, "bio == null"); 4749 return 0; 4750 } 4751 4752 T* x = d2i_func(bio, NULL); 4753 if (x == NULL) { 4754 throwExceptionIfNecessary(env, "d2i_ASN1Object_to_jlong"); 4755 return 0; 4756 } 4757 4758 return reinterpret_cast<uintptr_t>(x); 4759 } 4760 4761 static jlong NativeCrypto_d2i_X509_CRL_bio(JNIEnv* env, jclass, jlong bioRef) { 4762 return d2i_ASN1Object_to_jlong<X509_CRL, d2i_X509_CRL_bio>(