1 /* 2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 //=--------------------------------------------------------------------------= 27 // security.cpp by Stanley Man-Kit Ho 28 //=--------------------------------------------------------------------------= 29 // 30 31 #include <jni.h> 32 #include "jni_util.h" 33 #include <stdlib.h> 34 #include <string.h> 35 #include <windows.h> 36 #include <BaseTsd.h> 37 #include <wincrypt.h> 38 #include <stdio.h> 39 #include <memory> 40 #include "sun_security_mscapi_Key.h" 41 #include "sun_security_mscapi_KeyStore.h" 42 #include "sun_security_mscapi_PRNG.h" 43 #include "sun_security_mscapi_RSACipher.h" 44 #include "sun_security_mscapi_RSAKeyPairGenerator.h" 45 #include "sun_security_mscapi_RSAPublicKey.h" 46 #include "sun_security_mscapi_RSASignature.h" 47 48 #define OID_EKU_ANY "2.5.29.37.0" 49 50 #define CERTIFICATE_PARSING_EXCEPTION \ 51 "java/security/cert/CertificateParsingException" 52 #define INVALID_KEY_EXCEPTION \ 53 "java/security/InvalidKeyException" 54 #define KEY_EXCEPTION "java/security/KeyException" 55 #define KEYSTORE_EXCEPTION "java/security/KeyStoreException" 56 #define PROVIDER_EXCEPTION "java/security/ProviderException" 57 #define SIGNATURE_EXCEPTION "java/security/SignatureException" 58 #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError" 59 60 extern "C" { 61 62 /* 63 * Declare library specific JNI_Onload entry if static build 64 */ 65 DEF_STATIC_JNI_OnLoad 66 67 /* 68 * Throws an arbitrary Java exception with the given message. 69 */ 70 void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName, 71 const char *szMessage) 72 { 73 jclass exceptionClazz = env->FindClass(exceptionName); 74 if (exceptionClazz != NULL) { 75 env->ThrowNew(exceptionClazz, szMessage); 76 } 77 } 78 79 /* 80 * Throws an arbitrary Java exception. 81 * The exception message is a Windows system error message. 82 */ 83 void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError) 84 { 85 char szMessage[1024]; 86 szMessage[0] = '\0'; 87 88 DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 89 NULL, szMessage, sizeof(szMessage), NULL); 90 if (res == 0) { 91 strcpy(szMessage, "Unknown error"); 92 } 93 94 ThrowExceptionWithMessage(env, exceptionName, szMessage); 95 } 96 97 /* 98 * Overloaded 'operator new[]' variant, which will raise Java's 99 * OutOfMemoryError in the case of a failure. 100 */ 101 void* operator new[](std::size_t size, JNIEnv *env) 102 { 103 void* buf = ::operator new[](size, std::nothrow); 104 if (buf == NULL) { 105 ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR, 106 "Native memory allocation failed"); 107 } 108 return buf; 109 } 110 111 /* 112 * Maps the name of a hash algorithm to an algorithm identifier. 113 */ 114 ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) { 115 116 const char* pszHashAlgorithm = NULL; 117 ALG_ID algId = 0; 118 119 if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL)) 120 == NULL) { 121 return algId; 122 } 123 124 if ((strcmp("SHA", pszHashAlgorithm) == 0) || 125 (strcmp("SHA1", pszHashAlgorithm) == 0) || 126 (strcmp("SHA-1", pszHashAlgorithm) == 0)) { 127 128 algId = CALG_SHA1; 129 } else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) { 130 algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5 131 } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) { 132 algId = CALG_SHA_256; 133 } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) { 134 algId = CALG_SHA_384; 135 } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) { 136 algId = CALG_SHA_512; 137 } else if (strcmp("MD5", pszHashAlgorithm) == 0) { 138 algId = CALG_MD5; 139 } else if (strcmp("MD2", pszHashAlgorithm) == 0) { 140 algId = CALG_MD2; 141 } 142 143 if (pszHashAlgorithm) 144 env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm); 145 146 return algId; 147 } 148 149 150 /* 151 * Returns a certificate chain context given a certificate context and key 152 * usage identifier. 153 */ 154 bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext) 155 { 156 CERT_ENHKEY_USAGE EnhkeyUsage; 157 CERT_USAGE_MATCH CertUsage; 158 CERT_CHAIN_PARA ChainPara; 159 DWORD dwFlags = 0; 160 LPSTR szUsageIdentifierArray[1]; 161 162 szUsageIdentifierArray[0] = lpszKeyUsageIdentifier; 163 EnhkeyUsage.cUsageIdentifier = 1; 164 EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray; 165 CertUsage.dwType = USAGE_MATCH_TYPE_AND; 166 CertUsage.Usage = EnhkeyUsage; 167 ChainPara.cbSize = sizeof(CERT_CHAIN_PARA); 168 ChainPara.RequestedUsage=CertUsage; 169 170 // Build a chain using CertGetCertificateChain 171 // and the certificate retrieved. 172 return (::CertGetCertificateChain(NULL, // use the default chain engine 173 pCertContext, // pointer to the end certificate 174 NULL, // use the default time 175 NULL, // search no additional stores 176 &ChainPara, // use AND logic and enhanced key usage 177 // as indicated in the ChainPara 178 // data structure 179 dwFlags, 180 NULL, // currently reserved 181 ppChainContext) == TRUE); // return a pointer to the chain created 182 } 183 184 185 ///////////////////////////////////////////////////////////////////////////// 186 // 187 188 /* 189 * Class: sun_security_mscapi_PRNG 190 * Method: generateSeed 191 * Signature: (I[B)[B 192 */ 193 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed 194 (JNIEnv *env, jclass clazz, jint length, jbyteArray seed) 195 { 196 197 HCRYPTPROV hCryptProv = NULL; 198 BYTE* pbData = NULL; 199 jbyte* reseedBytes = NULL; 200 jbyte* seedBytes = NULL; 201 jbyteArray result = NULL; 202 203 __try 204 { 205 // Acquire a CSP context. 206 if(::CryptAcquireContext( 207 &hCryptProv, 208 NULL, 209 NULL, 210 PROV_RSA_FULL, 211 CRYPT_VERIFYCONTEXT) == FALSE) 212 { 213 ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); 214 __leave; 215 } 216 217 /* 218 * If length is negative then use the supplied seed to re-seed the 219 * generator and return null. 220 * If length is non-zero then generate a new seed according to the 221 * requested length and return the new seed. 222 * If length is zero then overwrite the supplied seed with a new 223 * seed of the same length and return the seed. 224 */ 225 if (length < 0) { 226 length = env->GetArrayLength(seed); 227 if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) { 228 __leave; 229 } 230 231 if (::CryptGenRandom( 232 hCryptProv, 233 length, 234 (BYTE *) reseedBytes) == FALSE) { 235 236 ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); 237 __leave; 238 } 239 240 result = NULL; 241 242 } else if (length > 0) { 243 244 pbData = new (env) BYTE[length]; 245 if (pbData == NULL) { 246 __leave; 247 } 248 249 if (::CryptGenRandom( 250 hCryptProv, 251 length, 252 pbData) == FALSE) { 253 254 ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); 255 __leave; 256 } 257 258 result = env->NewByteArray(length); 259 env->SetByteArrayRegion(result, 0, length, (jbyte*) pbData); 260 261 } else { // length == 0 262 263 length = env->GetArrayLength(seed); 264 if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) { 265 __leave; 266 } 267 268 if (::CryptGenRandom( 269 hCryptProv, 270 length, 271 (BYTE *) seedBytes) == FALSE) { 272 273 ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); 274 __leave; 275 } 276 277 result = seed; // seed will be updated when seedBytes gets released 278 } 279 } 280 __finally 281 { 282 //-------------------------------------------------------------------- 283 // Clean up. 284 285 if (reseedBytes) 286 env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT); 287 288 if (pbData) 289 delete [] pbData; 290 291 if (seedBytes) 292 env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig 293 294 if (hCryptProv) 295 ::CryptReleaseContext(hCryptProv, 0); 296 } 297 298 return result; 299 } 300 301 302 /* 303 * Class: sun_security_mscapi_KeyStore 304 * Method: loadKeysOrCertificateChains 305 * Signature: (Ljava/lang/String;Ljava/util/Collection;)V 306 */ 307 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateChains 308 (JNIEnv *env, jobject obj, jstring jCertStoreName) 309 { 310 /** 311 * Certificate in cert store has enhanced key usage extension 312 * property (or EKU property) that is not part of the certificate itself. To determine 313 * if the certificate should be returned, both the enhanced key usage in certificate 314 * extension block and the extension property stored along with the certificate in 315 * certificate store should be examined. Otherwise, we won't be able to determine 316 * the proper key usage from the Java side because the information is not stored as 317 * part of the encoded certificate. 318 */ 319 320 const char* pszCertStoreName = NULL; 321 HCERTSTORE hCertStore = NULL; 322 PCCERT_CONTEXT pCertContext = NULL; 323 char* pszNameString = NULL; // certificate's friendly name 324 DWORD cchNameString = 0; 325 326 327 __try 328 { 329 // Open a system certificate store. 330 if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL)) 331 == NULL) { 332 __leave; 333 } 334 if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) 335 == NULL) { 336 337 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 338 __leave; 339 } 340 341 // Determine clazz and method ID to generate certificate 342 jclass clazzArrayList = env->FindClass("java/util/ArrayList"); 343 if (clazzArrayList == NULL) { 344 __leave; 345 } 346 347 jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V"); 348 if (mNewArrayList == NULL) { 349 __leave; 350 } 351 352 jclass clazzOfThis = env->GetObjectClass(obj); 353 if (clazzOfThis == NULL) { 354 __leave; 355 } 356 357 jmethodID mGenCert = env->GetMethodID(clazzOfThis, 358 "generateCertificate", 359 "([BLjava/util/Collection;)V"); 360 if (mGenCert == NULL) { 361 __leave; 362 } 363 364 // Determine method ID to generate certificate chain 365 jmethodID mGenCertChain = env->GetMethodID(clazzOfThis, 366 "generateCertificateChain", 367 "(Ljava/lang/String;Ljava/util/Collection;)V"); 368 if (mGenCertChain == NULL) { 369 __leave; 370 } 371 372 // Determine method ID to generate RSA certificate chain 373 jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(clazzOfThis, 374 "generateRSAKeyAndCertificateChain", 375 "(Ljava/lang/String;JJILjava/util/Collection;)V"); 376 if (mGenRSAKeyAndCertChain == NULL) { 377 __leave; 378 } 379 380 // Use CertEnumCertificatesInStore to get the certificates 381 // from the open store. pCertContext must be reset to 382 // NULL to retrieve the first certificate in the store. 383 while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext)) 384 { 385 // Check if private key available - client authentication certificate 386 // must have private key available. 387 HCRYPTPROV hCryptProv = NULL; 388 DWORD dwKeySpec = 0; 389 HCRYPTKEY hUserKey = NULL; 390 BOOL bCallerFreeProv = FALSE; 391 BOOL bHasNoPrivateKey = FALSE; 392 DWORD dwPublicKeyLength = 0; 393 394 // First, probe it silently 395 if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL, 396 &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE 397 && GetLastError() != NTE_SILENT_CONTEXT) 398 { 399 bHasNoPrivateKey = TRUE; 400 } 401 else 402 { 403 if (bCallerFreeProv == TRUE) { 404 ::CryptReleaseContext(hCryptProv, NULL); 405 bCallerFreeProv = FALSE; 406 } 407 408 // Second, acquire the key normally (not silently) 409 if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, 410 &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE) 411 { 412 bHasNoPrivateKey = TRUE; 413 } 414 else 415 { 416 // Private key is available 417 BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); 418 419 // Skip certificate if cannot find private key 420 if (bGetUserKey == FALSE) { 421 if (bCallerFreeProv) 422 ::CryptReleaseContext(hCryptProv, NULL); 423 continue; 424 } 425 426 // Set cipher mode to ECB 427 DWORD dwCipherMode = CRYPT_MODE_ECB; 428 ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); 429 430 // If the private key is present in smart card, we may not be able to 431 // determine the key length by using the private key handle. However, 432 // since public/private key pairs must have the same length, we could 433 // determine the key length of the private key by using the public key 434 // in the certificate. 435 dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 436 &(pCertContext->pCertInfo->SubjectPublicKeyInfo)); 437 } 438 } 439 PCCERT_CHAIN_CONTEXT pCertChainContext = NULL; 440 441 // Build certificate chain by using system certificate store. 442 // Add cert chain into collection for any key usage. 443 // 444 if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext)) 445 { 446 for (DWORD i = 0; i < pCertChainContext->cChain; i++) 447 { 448 // Found cert chain 449 PCERT_SIMPLE_CHAIN rgpChain = 450 pCertChainContext->rgpChain[i]; 451 452 // Create ArrayList to store certs in each chain 453 jobject jArrayList = 454 env->NewObject(clazzArrayList, mNewArrayList); 455 456 for (unsigned int j=0; j < rgpChain->cElement; j++) 457 { 458 PCERT_CHAIN_ELEMENT rgpElement = 459 rgpChain->rgpElement[j]; 460 PCCERT_CONTEXT pc = rgpElement->pCertContext; 461 462 // Retrieve the friendly name of the first certificate 463 // in the chain 464 if (j == 0) { 465 466 // If the cert's name cannot be retrieved then 467 // pszNameString remains set to NULL. 468 // (An alias name will be generated automatically 469 // when storing this cert in the keystore.) 470 471 // Get length of friendly name 472 if ((cchNameString = CertGetNameString(pc, 473 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, 474 NULL, 0)) > 1) { 475 476 // Found friendly name 477 pszNameString = new (env) char[cchNameString]; 478 if (pszNameString == NULL) { 479 __leave; 480 } 481 482 CertGetNameString(pc, 483 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, 484 pszNameString, cchNameString); 485 } 486 } 487 488 BYTE* pbCertEncoded = pc->pbCertEncoded; 489 DWORD cbCertEncoded = pc->cbCertEncoded; 490 491 // Allocate and populate byte array 492 jbyteArray byteArray = env->NewByteArray(cbCertEncoded); 493 env->SetByteArrayRegion(byteArray, 0, cbCertEncoded, 494 (jbyte*) pbCertEncoded); 495 496 // Generate certificate from byte array and store into 497 // cert collection 498 env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList); 499 } 500 501 if (bHasNoPrivateKey) 502 { 503 // Generate certificate chain and store into cert chain 504 // collection 505 env->CallVoidMethod(obj, mGenCertChain, 506 env->NewStringUTF(pszNameString), 507 jArrayList); 508 } 509 else 510 { 511 // Determine key type: RSA or DSA 512 DWORD dwData = CALG_RSA_KEYX; 513 DWORD dwSize = sizeof(DWORD); 514 ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, 515 &dwSize, NULL); 516 517 if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA) 518 { 519 // Generate RSA certificate chain and store into cert 520 // chain collection 521 env->CallVoidMethod(obj, mGenRSAKeyAndCertChain, 522 env->NewStringUTF(pszNameString), 523 (jlong) hCryptProv, (jlong) hUserKey, 524 dwPublicKeyLength, jArrayList); 525 } 526 } 527 } 528 529 // Free cert chain 530 if (pCertChainContext) 531 ::CertFreeCertificateChain(pCertChainContext); 532 } 533 } 534 } 535 __finally 536 { 537 if (hCertStore) 538 ::CertCloseStore(hCertStore, 0); 539 540 if (pszCertStoreName) 541 env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName); 542 543 if (pszNameString) 544 delete [] pszNameString; 545 } 546 } 547 548 549 /* 550 * Class: sun_security_mscapi_Key 551 * Method: cleanUp 552 * Signature: (JJ)V 553 */ 554 JNIEXPORT void JNICALL Java_sun_security_mscapi_Key_cleanUp 555 (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey) 556 { 557 if (hCryptKey != NULL) 558 ::CryptDestroyKey((HCRYPTKEY) hCryptKey); 559 560 if (hCryptProv != NULL) 561 ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); 562 } 563 564 565 /* 566 * Class: sun_security_mscapi_RSASignature 567 * Method: signHash 568 * Signature: (Z[BILjava/lang/String;JJ)[B 569 */ 570 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_signHash 571 (JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash, 572 jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv, 573 jlong hCryptKey) 574 { 575 HCRYPTHASH hHash = NULL; 576 jbyte* pHashBuffer = NULL; 577 jbyte* pSignedHashBuffer = NULL; 578 jbyteArray jSignedHash = NULL; 579 HCRYPTPROV hCryptProvAlt = NULL; 580 581 __try 582 { 583 // Map hash algorithm 584 ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm); 585 586 // Acquire a hash object handle. 587 if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) 588 { 589 // Failover to using the PROV_RSA_AES CSP 590 591 DWORD cbData = 256; 592 BYTE pbData[256]; 593 pbData[0] = '\0'; 594 595 // Get name of the key container 596 ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, 597 (BYTE *)pbData, &cbData, 0); 598 599 // Acquire an alternative CSP handle 600 if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, 601 PROV_RSA_AES, 0) == FALSE) 602 { 603 604 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 605 __leave; 606 } 607 608 // Acquire a hash object handle. 609 if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, 610 &hHash) == FALSE) 611 { 612 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 613 __leave; 614 } 615 } 616 617 // Copy hash from Java to native buffer 618 pHashBuffer = new (env) jbyte[jHashSize]; 619 if (pHashBuffer == NULL) { 620 __leave; 621 } 622 env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer); 623 624 // Set hash value in the hash object 625 if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) 626 { 627 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 628 __leave; 629 } 630 631 // Determine key spec. 632 DWORD dwKeySpec = AT_SIGNATURE; 633 ALG_ID dwAlgId; 634 DWORD dwAlgIdLen = sizeof(ALG_ID); 635 636 if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { 637 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 638 __leave; 639 640 } 641 if (CALG_RSA_KEYX == dwAlgId) { 642 dwKeySpec = AT_KEYEXCHANGE; 643 } 644 645 // Determine size of buffer 646 DWORD dwBufLen = 0; 647 DWORD dwFlags = 0; 648 649 if (noHashOID == JNI_TRUE) { 650 dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature 651 } 652 653 if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) 654 { 655 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 656 __leave; 657 } 658 659 pSignedHashBuffer = new (env) jbyte[dwBufLen]; 660 if (pSignedHashBuffer == NULL) { 661 __leave; 662 } 663 if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) 664 { 665 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 666 __leave; 667 } 668 669 // Create new byte array 670 jbyteArray temp = env->NewByteArray(dwBufLen); 671 672 // Copy data from native buffer 673 env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer); 674 675 jSignedHash = temp; 676 } 677 __finally 678 { 679 if (pSignedHashBuffer) 680 delete [] pSignedHashBuffer; 681 682 if (pHashBuffer) 683 delete [] pHashBuffer; 684 685 if (hHash) 686 ::CryptDestroyHash(hHash); 687 688 if (hCryptProvAlt) 689 ::CryptReleaseContext(hCryptProvAlt, 0); 690 } 691 692 return jSignedHash; 693 } 694 695 /* 696 * Class: sun_security_mscapi_RSASignature 697 * Method: verifySignedHash 698 * Signature: ([BIL/java/lang/String;[BIJJ)Z 699 */ 700 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_verifySignedHash 701 (JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize, 702 jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize, 703 jlong hCryptProv, jlong hCryptKey) 704 { 705 HCRYPTHASH hHash = NULL; 706 jbyte* pHashBuffer = NULL; 707 jbyte* pSignedHashBuffer = NULL; 708 DWORD dwSignedHashBufferLen = jSignedHashSize; 709 jboolean result = JNI_FALSE; 710 HCRYPTPROV hCryptProvAlt = NULL; 711 712 __try 713 { 714 // Map hash algorithm 715 ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm); 716 717 // Acquire a hash object handle. 718 if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) 719 == FALSE) 720 { 721 // Failover to using the PROV_RSA_AES CSP 722 723 DWORD cbData = 256; 724 BYTE pbData[256]; 725 pbData[0] = '\0'; 726 727 // Get name of the key container 728 ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, 729 (BYTE *)pbData, &cbData, 0); 730 731 // Acquire an alternative CSP handle 732 if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, 733 PROV_RSA_AES, 0) == FALSE) 734 { 735 736 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 737 __leave; 738 } 739 740 // Acquire a hash object handle. 741 if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, 742 &hHash) == FALSE) 743 { 744 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 745 __leave; 746 } 747 } 748 749 // Copy hash and signedHash from Java to native buffer 750 pHashBuffer = new (env) jbyte[jHashSize]; 751 if (pHashBuffer == NULL) { 752 __leave; 753 } 754 env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer); 755 756 pSignedHashBuffer = new (env) jbyte[jSignedHashSize]; 757 if (pSignedHashBuffer == NULL) { 758 __leave; 759 } 760 env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize, 761 pSignedHashBuffer); 762 763 // Set hash value in the hash object 764 if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) 765 == FALSE) 766 { 767 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); 768 __leave; 769 } 770 771 // For RSA, the hash encryption algorithm is normally the same as the 772 // public key algorithm, so AT_SIGNATURE is used. 773 774 // Verify the signature 775 if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, 776 dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE) 777 { 778 result = JNI_TRUE; 779 } 780 } 781 782 __finally 783 { 784 if (pSignedHashBuffer) 785 delete [] pSignedHashBuffer; 786 787 if (pHashBuffer) 788 delete [] pHashBuffer; 789 790 if (hHash) 791 ::CryptDestroyHash(hHash); 792 793 if (hCryptProvAlt) 794 ::CryptReleaseContext(hCryptProvAlt, 0); 795 } 796 797 return result; 798 } 799 800 /* 801 * Class: sun_security_mscapi_RSAKeyPairGenerator 802 * Method: generateRSAKeyPair 803 * Signature: (ILjava/lang/String;)Lsun/security/mscapi/RSAKeyPair; 804 */ 805 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSAKeyPairGenerator_generateRSAKeyPair 806 (JNIEnv *env, jclass clazz, jint keySize, jstring keyContainerName) 807 { 808 HCRYPTPROV hCryptProv = NULL; 809 HCRYPTKEY hKeyPair; 810 DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE; 811 jobject keypair = NULL; 812 const char* pszKeyContainerName = NULL; // UUID 813 814 __try 815 { 816 if ((pszKeyContainerName = 817 env->GetStringUTFChars(keyContainerName, NULL)) == NULL) { 818 __leave; 819 } 820 821 // Acquire a CSP context (create a new key container). 822 // Prefer a PROV_RSA_AES CSP, when available, due to its support 823 // for SHA-2-based signatures. 824 if (::CryptAcquireContext( 825 &hCryptProv, 826 pszKeyContainerName, 827 NULL, 828 PROV_RSA_AES, 829 CRYPT_NEWKEYSET) == FALSE) 830 { 831 // Failover to using the default CSP (PROV_RSA_FULL) 832 833 if (::CryptAcquireContext( 834 &hCryptProv, 835 pszKeyContainerName, 836 NULL, 837 PROV_RSA_FULL, 838 CRYPT_NEWKEYSET) == FALSE) 839 { 840 ThrowException(env, KEY_EXCEPTION, GetLastError()); 841 __leave; 842 } 843 } 844 845 // Generate an RSA keypair 846 if(::CryptGenKey( 847 hCryptProv, 848 AT_KEYEXCHANGE, 849 dwFlags, 850 &hKeyPair) == FALSE) 851 { 852 ThrowException(env, KEY_EXCEPTION, GetLastError()); 853 __leave; 854 } 855 856 // Get the method ID for the RSAKeyPair constructor 857 jclass clazzRSAKeyPair = 858 env->FindClass("sun/security/mscapi/RSAKeyPair"); 859 if (clazzRSAKeyPair == NULL) { 860 __leave; 861 } 862 863 jmethodID mNewRSAKeyPair = 864 env->GetMethodID(clazzRSAKeyPair, "<init>", "(JJI)V"); 865 if (mNewRSAKeyPair == NULL) { 866 __leave; 867 } 868 869 // Create a new RSA keypair 870 keypair = env->NewObject(clazzRSAKeyPair, mNewRSAKeyPair, 871 (jlong) hCryptProv, (jlong) hKeyPair, keySize); 872 873 } 874 __finally 875 { 876 //-------------------------------------------------------------------- 877 // Clean up. 878 879 if (pszKeyContainerName) 880 env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName); 881 } 882 883 return keypair; 884 } 885 886 /* 887 * Class: sun_security_mscapi_Key 888 * Method: getContainerName 889 * Signature: (J)Ljava/lang/String; 890 */ 891 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_Key_getContainerName 892 (JNIEnv *env, jclass jclazz, jlong hCryptProv) 893 { 894 DWORD cbData = 256; 895 BYTE pbData[256]; 896 pbData[0] = '\0'; 897 898 ::CryptGetProvParam( 899 (HCRYPTPROV)hCryptProv, 900 PP_CONTAINER, 901 (BYTE *)pbData, 902 &cbData, 903 0); 904 905 return env->NewStringUTF((const char*)pbData); 906 } 907 908 /* 909 * Class: sun_security_mscapi_Key 910 * Method: getKeyType 911 * Signature: (J)Ljava/lang/String; 912 */ 913 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_Key_getKeyType 914 (JNIEnv *env, jclass jclazz, jlong hCryptKey) 915 { 916 ALG_ID dwAlgId; 917 DWORD dwAlgIdLen = sizeof(ALG_ID); 918 919 if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { 920 921 if (CALG_RSA_SIGN == dwAlgId) { 922 return env->NewStringUTF("Signature"); 923 924 } else if (CALG_RSA_KEYX == dwAlgId) { 925 return env->NewStringUTF("Exchange"); 926 927 } else { 928 char buffer[64]; 929 if (sprintf(buffer, "%lu", dwAlgId)) { 930 return env->NewStringUTF(buffer); 931 } 932 } 933 } 934 935 return env->NewStringUTF("<Unknown>"); 936 } 937 938 /* 939 * Class: sun_security_mscapi_KeyStore 940 * Method: storeCertificate 941 * Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V 942 */ 943 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate 944 (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName, 945 jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv, 946 jlong hCryptKey) 947 { 948 const char* pszCertStoreName = NULL; 949 HCERTSTORE hCertStore = NULL; 950 PCCERT_CONTEXT pCertContext = NULL; 951 PWCHAR pszCertAliasName = NULL; 952 jbyte* pbCertEncoding = NULL; 953 const jchar* jCertAliasChars = NULL; 954 const char* pszContainerName = NULL; 955 const char* pszProviderName = NULL; 956 WCHAR * pwszContainerName = NULL; 957 WCHAR * pwszProviderName = NULL; 958 959 __try 960 { 961 // Open a system certificate store. 962 if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL)) 963 == NULL) { 964 __leave; 965 } 966 if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) { 967 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 968 __leave; 969 } 970 971 // Copy encoding from Java to native buffer 972 pbCertEncoding = new (env) jbyte[jCertEncodingSize]; 973 if (pbCertEncoding == NULL) { 974 __leave; 975 } 976 env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding); 977 978 // Create a certificate context from the encoded cert 979 if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING, 980 (BYTE*) pbCertEncoding, jCertEncodingSize))) { 981 982 ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError()); 983 __leave; 984 } 985 986 // Set the certificate's friendly name 987 int size = env->GetStringLength(jCertAliasName); 988 pszCertAliasName = new (env) WCHAR[size + 1]; 989 if (pszCertAliasName == NULL) { 990 __leave; 991 } 992 993 jCertAliasChars = env->GetStringChars(jCertAliasName, NULL); 994 memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR)); 995 pszCertAliasName[size] = 0; // append the string terminator 996 997 CRYPT_DATA_BLOB friendlyName = { 998 sizeof(WCHAR) * (size + 1), 999 (BYTE *) pszCertAliasName 1000 }; 1001 1002 env->ReleaseStringChars(jCertAliasName, jCertAliasChars); 1003 1004 if (! ::CertSetCertificateContextProperty(pCertContext, 1005 CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) { 1006 1007 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1008 __leave; 1009 } 1010 1011 // Attach the certificate's private key (if supplied) 1012 if (hCryptProv != 0 && hCryptKey != 0) { 1013 1014 CRYPT_KEY_PROV_INFO keyProviderInfo; 1015 DWORD dwDataLen; 1016 1017 // Get the name of the key container 1018 if (! ::CryptGetProvParam( 1019 (HCRYPTPROV) hCryptProv, 1020 PP_CONTAINER, 1021 NULL, 1022 &dwDataLen, 1023 0)) { 1024 1025 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1026 __leave; 1027 } 1028 1029 pszContainerName = new (env) char[dwDataLen]; 1030 if (pszContainerName == NULL) { 1031 __leave; 1032 } 1033 1034 if (! ::CryptGetProvParam( 1035 (HCRYPTPROV) hCryptProv, 1036 PP_CONTAINER, 1037 (BYTE *) pszContainerName, 1038 &dwDataLen, 1039 0)) { 1040 1041 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1042 __leave; 1043 } 1044 1045 // Convert to a wide char string 1046 pwszContainerName = new (env) WCHAR[dwDataLen]; 1047 if (pwszContainerName == NULL) { 1048 __leave; 1049 } 1050 1051 if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) { 1052 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1053 __leave; 1054 } 1055 1056 // Set the name of the key container 1057 keyProviderInfo.pwszContainerName = pwszContainerName; 1058 1059 1060 // Get the name of the provider 1061 if (! ::CryptGetProvParam( 1062 (HCRYPTPROV) hCryptProv, 1063 PP_NAME, 1064 NULL, 1065 &dwDataLen, 1066 0)) { 1067 1068 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1069 __leave; 1070 } 1071 1072 pszProviderName = new (env) char[dwDataLen]; 1073 if (pszProviderName == NULL) { 1074 __leave; 1075 } 1076 1077 if (! ::CryptGetProvParam( 1078 (HCRYPTPROV) hCryptProv, 1079 PP_NAME, 1080 (BYTE *) pszProviderName, 1081 &dwDataLen, 1082 0)) { 1083 1084 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1085 __leave; 1086 } 1087 1088 // Convert to a wide char string 1089 pwszProviderName = new (env) WCHAR[dwDataLen]; 1090 if (pwszProviderName == NULL) { 1091 __leave; 1092 } 1093 1094 if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) { 1095 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1096 __leave; 1097 } 1098 1099 // Set the name of the provider 1100 keyProviderInfo.pwszProvName = pwszProviderName; 1101 1102 // Get and set the type of the provider 1103 if (! ::CryptGetProvParam( 1104 (HCRYPTPROV) hCryptProv, 1105 PP_PROVTYPE, 1106 (LPBYTE) &keyProviderInfo.dwProvType, 1107 &dwDataLen, 1108 0)) { 1109 1110 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1111 __leave; 1112 } 1113 1114 // Set no provider flags 1115 keyProviderInfo.dwFlags = 0; 1116 1117 // Set no provider parameters 1118 keyProviderInfo.cProvParam = 0; 1119 keyProviderInfo.rgProvParam = NULL; 1120 1121 // Get the key's algorithm ID 1122 if (! ::CryptGetKeyParam( 1123 (HCRYPTKEY) hCryptKey, 1124 KP_ALGID, 1125 (LPBYTE) &keyProviderInfo.dwKeySpec, 1126 &dwDataLen, 1127 0)) { 1128 1129 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1130 __leave; 1131 } 1132 // Set the key spec (using the algorithm ID). 1133 switch (keyProviderInfo.dwKeySpec) { 1134 case CALG_RSA_KEYX: 1135 case CALG_DH_SF: 1136 keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE; 1137 break; 1138 1139 case CALG_RSA_SIGN: 1140 case CALG_DSS_SIGN: 1141 keyProviderInfo.dwKeySpec = AT_SIGNATURE; 1142 break; 1143 1144 default: 1145 ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID); 1146 __leave; 1147 } 1148 1149 if (! ::CertSetCertificateContextProperty(pCertContext, 1150 CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) { 1151 1152 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1153 __leave; 1154 } 1155 } 1156 1157 // Import encoded certificate 1158 if (!::CertAddCertificateContextToStore(hCertStore, pCertContext, 1159 CERT_STORE_ADD_REPLACE_EXISTING, NULL)) 1160 { 1161 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1162 __leave; 1163 } 1164 1165 } 1166 __finally 1167 { 1168 //-------------------------------------------------------------------- 1169 // Clean up. 1170 1171 if (hCertStore) 1172 ::CertCloseStore(hCertStore, 0); 1173 1174 if (pszCertStoreName) 1175 env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName); 1176 1177 if (pbCertEncoding) 1178 delete [] pbCertEncoding; 1179 1180 if (pszCertAliasName) 1181 delete [] pszCertAliasName; 1182 1183 if (pszContainerName) 1184 delete [] pszContainerName; 1185 1186 if (pwszContainerName) 1187 delete [] pwszContainerName; 1188 1189 if (pszProviderName) 1190 delete [] pszProviderName; 1191 1192 if (pwszProviderName) 1193 delete [] pwszProviderName; 1194 1195 if (pCertContext) 1196 ::CertFreeCertificateContext(pCertContext); 1197 } 1198 } 1199 1200 /* 1201 * Class: sun_security_mscapi_KeyStore 1202 * Method: removeCertificate 1203 * Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V 1204 */ 1205 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate 1206 (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName, 1207 jbyteArray jCertEncoding, jint jCertEncodingSize) { 1208 1209 const char* pszCertStoreName = NULL; 1210 const char* pszCertAliasName = NULL; 1211 HCERTSTORE hCertStore = NULL; 1212 PCCERT_CONTEXT pCertContext = NULL; 1213 PCCERT_CONTEXT pTBDCertContext = NULL; 1214 jbyte* pbCertEncoding = NULL; 1215 DWORD cchNameString = 0; 1216 char* pszNameString = NULL; // certificate's friendly name 1217 BOOL bDeleteAttempted = FALSE; 1218 1219 __try 1220 { 1221 // Open a system certificate store. 1222 if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL)) 1223 == NULL) { 1224 __leave; 1225 } 1226 if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) { 1227 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1228 __leave; 1229 } 1230 1231 // Copy encoding from Java to native buffer 1232 pbCertEncoding = new (env) jbyte[jCertEncodingSize]; 1233 if (pbCertEncoding == NULL) { 1234 __leave; 1235 } 1236 env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding); 1237 1238 // Create a certificate context from the encoded cert 1239 if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING, 1240 (BYTE*) pbCertEncoding, jCertEncodingSize))) { 1241 1242 ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError()); 1243 __leave; 1244 } 1245 1246 // Find the certificate to be deleted 1247 if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore, 1248 X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) { 1249 1250 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1251 __leave; 1252 } 1253 1254 // Check that its friendly name matches the supplied alias 1255 if ((cchNameString = ::CertGetNameString(pTBDCertContext, 1256 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) { 1257 1258 pszNameString = new (env) char[cchNameString]; 1259 if (pszNameString == NULL) { 1260 __leave; 1261 } 1262 1263 ::CertGetNameString(pTBDCertContext, 1264 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString, 1265 cchNameString); 1266 1267 // Compare the certificate's friendly name with supplied alias name 1268 if ((pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL)) 1269 == NULL) { 1270 __leave; 1271 } 1272 if (strcmp(pszCertAliasName, pszNameString) == 0) { 1273 1274 // Only delete the certificate if the alias names matches 1275 if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) { 1276 1277 // pTBDCertContext is always freed by the 1278 // CertDeleteCertificateFromStore method 1279 bDeleteAttempted = TRUE; 1280 1281 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1282 __leave; 1283 } 1284 } 1285 } 1286 1287 } 1288 __finally 1289 { 1290 //-------------------------------------------------------------------- 1291 // Clean up. 1292 1293 if (hCertStore) 1294 ::CertCloseStore(hCertStore, 0); 1295 1296 if (pszCertStoreName) 1297 env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName); 1298 1299 if (pszCertAliasName) 1300 env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName); 1301 1302 if (pbCertEncoding) 1303 delete [] pbCertEncoding; 1304 1305 if (pszNameString) 1306 delete [] pszNameString; 1307 1308 if (pCertContext) 1309 ::CertFreeCertificateContext(pCertContext); 1310 1311 if (bDeleteAttempted && pTBDCertContext) 1312 ::CertFreeCertificateContext(pTBDCertContext); 1313 } 1314 } 1315 1316 /* 1317 * Class: sun_security_mscapi_KeyStore 1318 * Method: destroyKeyContainer 1319 * Signature: (Ljava/lang/String;)V 1320 */ 1321 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer 1322 (JNIEnv *env, jobject clazz, jstring keyContainerName) 1323 { 1324 HCRYPTPROV hCryptProv = NULL; 1325 const char* pszKeyContainerName = NULL; 1326 1327 __try 1328 { 1329 if ((pszKeyContainerName = 1330 env->GetStringUTFChars(keyContainerName, NULL)) == NULL) { 1331 __leave; 1332 } 1333 1334 // Destroying the default key container is not permitted 1335 // (because it may contain more one keypair). 1336 if (pszKeyContainerName == NULL) { 1337 1338 ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM); 1339 __leave; 1340 } 1341 1342 // Acquire a CSP context (to the key container). 1343 if (::CryptAcquireContext( 1344 &hCryptProv, 1345 pszKeyContainerName, 1346 NULL, 1347 PROV_RSA_FULL, 1348 CRYPT_DELETEKEYSET) == FALSE) 1349 { 1350 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1351 __leave; 1352 } 1353 1354 } 1355 __finally 1356 { 1357 //-------------------------------------------------------------------- 1358 // Clean up. 1359 1360 if (pszKeyContainerName) 1361 env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName); 1362 } 1363 } 1364 1365 /* 1366 * Class: sun_security_mscapi_RSACipher 1367 * Method: encryptDecrypt 1368 * Signature: ([BIJZ)[B 1369 */ 1370 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt 1371 (JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey, 1372 jboolean doEncrypt) 1373 { 1374 jbyteArray result = NULL; 1375 jbyte* pData = NULL; 1376 DWORD dwDataLen = jDataSize; 1377 DWORD dwBufLen = env->GetArrayLength(jData); 1378 DWORD i; 1379 BYTE tmp; 1380 1381 __try 1382 { 1383 // Copy data from Java buffer to native buffer 1384 pData = new (env) jbyte[dwBufLen]; 1385 if (pData == NULL) { 1386 __leave; 1387 } 1388 env->GetByteArrayRegion(jData, 0, dwBufLen, pData); 1389 1390 if (doEncrypt == JNI_TRUE) { 1391 // encrypt 1392 if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, 1393 &dwDataLen, dwBufLen)) { 1394 1395 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1396 __leave; 1397 } 1398 dwBufLen = dwDataLen; 1399 1400 // convert from little-endian 1401 for (i = 0; i < dwBufLen / 2; i++) { 1402 tmp = pData[i]; 1403 pData[i] = pData[dwBufLen - i -1]; 1404 pData[dwBufLen - i - 1] = tmp; 1405 } 1406 } else { 1407 // convert to little-endian 1408 for (i = 0; i < dwBufLen / 2; i++) { 1409 tmp = pData[i]; 1410 pData[i] = pData[dwBufLen - i -1]; 1411 pData[dwBufLen - i - 1] = tmp; 1412 } 1413 1414 // decrypt 1415 if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, 1416 &dwBufLen)) { 1417 1418 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1419 __leave; 1420 } 1421 } 1422 1423 // Create new byte array 1424 result = env->NewByteArray(dwBufLen); 1425 1426 // Copy data from native buffer to Java buffer 1427 env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData); 1428 } 1429 __finally 1430 { 1431 if (pData) 1432 delete [] pData; 1433 } 1434 1435 return result; 1436 } 1437 1438 /* 1439 * Class: sun_security_mscapi_RSAPublicKey 1440 * Method: getPublicKeyBlob 1441 * Signature: (J)[B 1442 */ 1443 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyBlob 1444 (JNIEnv *env, jobject clazz, jlong hCryptKey) { 1445 1446 jbyteArray blob = NULL; 1447 DWORD dwBlobLen; 1448 BYTE* pbKeyBlob = NULL; 1449 1450 __try 1451 { 1452 1453 // Determine the size of the blob 1454 if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, 1455 &dwBlobLen)) { 1456 1457 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1458 __leave; 1459 } 1460 1461 pbKeyBlob = new (env) BYTE[dwBlobLen]; 1462 if (pbKeyBlob == NULL) { 1463 __leave; 1464 } 1465 1466 // Generate key blob 1467 if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, 1468 pbKeyBlob, &dwBlobLen)) { 1469 1470 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1471 __leave; 1472 } 1473 1474 // Create new byte array 1475 blob = env->NewByteArray(dwBlobLen); 1476 1477 // Copy data from native buffer to Java buffer 1478 env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob); 1479 } 1480 __finally 1481 { 1482 if (pbKeyBlob) 1483 delete [] pbKeyBlob; 1484 } 1485 1486 return blob; 1487 } 1488 1489 /* 1490 * Class: sun_security_mscapi_RSAPublicKey 1491 * Method: getExponent 1492 * Signature: ([B)[B 1493 */ 1494 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent 1495 (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { 1496 1497 jbyteArray exponent = NULL; 1498 jbyte* exponentBytes = NULL; 1499 jbyte* keyBlob = NULL; 1500 1501 __try { 1502 1503 jsize length = env->GetArrayLength(jKeyBlob); 1504 if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) { 1505 __leave; 1506 } 1507 1508 PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob; 1509 1510 // Check BLOB type 1511 if (pPublicKeyStruc->bType != PUBLICKEYBLOB) { 1512 ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE); 1513 __leave; 1514 } 1515 1516 RSAPUBKEY* pRsaPubKey = 1517 (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); 1518 1519 int len = sizeof(pRsaPubKey->pubexp); 1520 exponentBytes = new (env) jbyte[len]; 1521 if (exponentBytes == NULL) { 1522 __leave; 1523 } 1524 1525 // convert from little-endian while copying from blob 1526 for (int i = 0, j = len - 1; i < len; i++, j--) { 1527 exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j]; 1528 } 1529 1530 exponent = env->NewByteArray(len); 1531 env->SetByteArrayRegion(exponent, 0, len, exponentBytes); 1532 } 1533 __finally 1534 { 1535 if (keyBlob) 1536 env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT); 1537 1538 if (exponentBytes) 1539 delete [] exponentBytes; 1540 } 1541 1542 return exponent; 1543 } 1544 1545 /* 1546 * Class: sun_security_mscapi_RSAPublicKey 1547 * Method: getModulus 1548 * Signature: ([B)[B 1549 */ 1550 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus 1551 (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { 1552 1553 jbyteArray modulus = NULL; 1554 jbyte* modulusBytes = NULL; 1555 jbyte* keyBlob = NULL; 1556 1557 __try { 1558 1559 jsize length = env->GetArrayLength(jKeyBlob); 1560 if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) { 1561 __leave; 1562 } 1563 1564 PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob; 1565 1566 // Check BLOB type 1567 if (pPublicKeyStruc->bType != PUBLICKEYBLOB) { 1568 ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE); 1569 __leave; 1570 } 1571 1572 RSAPUBKEY* pRsaPubKey = 1573 (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); 1574 1575 int len = pRsaPubKey->bitlen / 8; 1576 modulusBytes = new (env) jbyte[len]; 1577 if (modulusBytes == NULL) { 1578 __leave; 1579 } 1580 BYTE * pbModulus = 1581 (BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); 1582 1583 // convert from little-endian while copying from blob 1584 for (int i = 0, j = len - 1; i < len; i++, j--) { 1585 modulusBytes[i] = pbModulus[j]; 1586 } 1587 1588 modulus = env->NewByteArray(len); 1589 env->SetByteArrayRegion(modulus, 0, len, modulusBytes); 1590 } 1591 __finally 1592 { 1593 if (keyBlob) 1594 env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT); 1595 1596 if (modulusBytes) 1597 delete [] modulusBytes; 1598 } 1599 1600 return modulus; 1601 } 1602 1603 /* 1604 * Convert an array in big-endian byte order into little-endian byte order. 1605 */ 1606 int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination, 1607 int destinationLength) { 1608 1609 int result = -1; 1610 jbyte* sourceBytes = NULL; 1611 1612 __try { 1613 int sourceLength = env->GetArrayLength(source); 1614 1615 sourceBytes = env->GetByteArrayElements(source, 0); 1616 if (sourceBytes == NULL) { 1617 __leave; 1618 } 1619 1620 int copyLen = sourceLength; 1621 if (sourceLength > destinationLength) { 1622 // source might include an extra sign byte 1623 if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) { 1624 copyLen--; 1625 } else { 1626 __leave; 1627 } 1628 } 1629 1630 // Copy bytes from the end of the source array to the beginning of the 1631 // destination array (until the destination array is full). 1632 // This ensures that the sign byte from the source array will be excluded. 1633 for (int i = 0; i < copyLen; i++) { 1634 destination[i] = sourceBytes[sourceLength - 1 - i]; 1635 } 1636 if (copyLen < destinationLength) { 1637 memset(destination + copyLen, 0, destinationLength - copyLen); 1638 } 1639 result = destinationLength; 1640 } __finally { 1641 // Clean up. 1642 if (sourceBytes) { 1643 env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT); 1644 } 1645 } 1646 1647 return result; 1648 } 1649 1650 /* 1651 * The Microsoft Base Cryptographic Provider supports public-key BLOBs 1652 * that have the following format: 1653 * 1654 * PUBLICKEYSTRUC publickeystruc; 1655 * RSAPUBKEY rsapubkey; 1656 * BYTE modulus[rsapubkey.bitlen/8]; 1657 * 1658 * and private-key BLOBs that have the following format: 1659 * 1660 * PUBLICKEYSTRUC publickeystruc; 1661 * RSAPUBKEY rsapubkey; 1662 * BYTE modulus[rsapubkey.bitlen/8]; 1663 * BYTE prime1[rsapubkey.bitlen/16]; 1664 * BYTE prime2[rsapubkey.bitlen/16]; 1665 * BYTE exponent1[rsapubkey.bitlen/16]; 1666 * BYTE exponent2[rsapubkey.bitlen/16]; 1667 * BYTE coefficient[rsapubkey.bitlen/16]; 1668 * BYTE privateExponent[rsapubkey.bitlen/8]; 1669 * 1670 * This method generates such BLOBs from the key elements supplied. 1671 */ 1672 jbyteArray generateKeyBlob( 1673 JNIEnv *env, 1674 jint jKeyBitLength, 1675 jbyteArray jModulus, 1676 jbyteArray jPublicExponent, 1677 jbyteArray jPrivateExponent, 1678 jbyteArray jPrimeP, 1679 jbyteArray jPrimeQ, 1680 jbyteArray jExponentP, 1681 jbyteArray jExponentQ, 1682 jbyteArray jCrtCoefficient) 1683 { 1684 jsize jKeyByteLength = jKeyBitLength / 8; 1685 jsize jBlobLength; 1686 BOOL bGeneratePrivateKeyBlob; 1687 1688 // Determine whether to generate a public-key or a private-key BLOB 1689 if (jPrivateExponent != NULL && 1690 jPrimeP != NULL && 1691 jPrimeQ != NULL && 1692 jExponentP != NULL && 1693 jExponentQ != NULL && 1694 jCrtCoefficient != NULL) { 1695 1696 bGeneratePrivateKeyBlob = TRUE; 1697 jBlobLength = sizeof(BLOBHEADER) + 1698 sizeof(RSAPUBKEY) + 1699 ((jKeyBitLength / 8) * 4) + 1700 (jKeyBitLength / 16); 1701 1702 } else { 1703 bGeneratePrivateKeyBlob = FALSE; 1704 jBlobLength = sizeof(BLOBHEADER) + 1705 sizeof(RSAPUBKEY) + 1706 (jKeyBitLength / 8); 1707 } 1708 1709 jbyte* jBlobBytes = NULL; 1710 jbyte* jBlobElement; 1711 jbyteArray jBlob = NULL; 1712 jsize jElementLength; 1713 1714 __try { 1715 jBlobBytes = new (env) jbyte[jBlobLength]; 1716 if (jBlobBytes == NULL) { 1717 __leave; 1718 } 1719 1720 BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes; 1721 if (bGeneratePrivateKeyBlob) { 1722 pBlobHeader->bType = PRIVATEKEYBLOB; // 0x07 1723 } else { 1724 pBlobHeader->bType = PUBLICKEYBLOB; // 0x06 1725 } 1726 pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02 1727 pBlobHeader->reserved = 0; // 0x0000 1728 pBlobHeader->aiKeyAlg = CALG_RSA_KEYX; // 0x0000a400 1729 1730 RSAPUBKEY *pRsaPubKey = 1731 (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC)); 1732 if (bGeneratePrivateKeyBlob) { 1733 pRsaPubKey->magic = 0x32415352; // "RSA2" 1734 } else { 1735 pRsaPubKey->magic = 0x31415352; // "RSA1" 1736 } 1737 pRsaPubKey->bitlen = jKeyBitLength; 1738 pRsaPubKey->pubexp = 0; // init 1739 1740 // Sanity check 1741 jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent); 1742 if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) { 1743 ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE); 1744 __leave; 1745 } 1746 // The length argument must be the smaller of jPublicExponentLength 1747 // and sizeof(pRsaPubKey->pubkey) 1748 if ((jElementLength = convertToLittleEndian(env, jPublicExponent, 1749 (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) { 1750 __leave; 1751 } 1752 1753 // Modulus n 1754 jBlobElement = 1755 (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); 1756 if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement, 1757 jKeyByteLength)) < 0) { 1758 __leave; 1759 } 1760 1761 if (bGeneratePrivateKeyBlob) { 1762 // Prime p 1763 jBlobElement += jElementLength; 1764 if ((jElementLength = convertToLittleEndian(env, jPrimeP, 1765 jBlobElement, jKeyByteLength / 2)) < 0) { 1766 __leave; 1767 } 1768 1769 // Prime q 1770 jBlobElement += jElementLength; 1771 if ((jElementLength = convertToLittleEndian(env, jPrimeQ, 1772 jBlobElement, jKeyByteLength / 2)) < 0) { 1773 __leave; 1774 } 1775 1776 // Prime exponent p 1777 jBlobElement += jElementLength; 1778 if ((jElementLength = convertToLittleEndian(env, jExponentP, 1779 jBlobElement, jKeyByteLength / 2)) < 0) { 1780 __leave; 1781 } 1782 1783 // Prime exponent q 1784 jBlobElement += jElementLength; 1785 if ((jElementLength = convertToLittleEndian(env, jExponentQ, 1786 jBlobElement, jKeyByteLength / 2)) < 0) { 1787 __leave; 1788 } 1789 1790 // CRT coefficient 1791 jBlobElement += jElementLength; 1792 if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient, 1793 jBlobElement, jKeyByteLength / 2)) < 0) { 1794 __leave; 1795 } 1796 1797 // Private exponent 1798 jBlobElement += jElementLength; 1799 if ((jElementLength = convertToLittleEndian(env, jPrivateExponent, 1800 jBlobElement, jKeyByteLength)) < 0) { 1801 __leave; 1802 } 1803 } 1804 1805 jBlob = env->NewByteArray(jBlobLength); 1806 env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes); 1807 1808 } 1809 __finally 1810 { 1811 if (jBlobBytes) 1812 delete [] jBlobBytes; 1813 } 1814 1815 return jBlob; 1816 } 1817 1818 /* 1819 * Class: sun_security_mscapi_KeyStore 1820 * Method: generatePrivateKeyBlob 1821 * Signature: (I[B[B[B[B[B[B[B[B)[B 1822 */ 1823 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_KeyStore_generatePrivateKeyBlob 1824 (JNIEnv *env, jobject clazz, 1825 jint jKeyBitLength, 1826 jbyteArray jModulus, 1827 jbyteArray jPublicExponent, 1828 jbyteArray jPrivateExponent, 1829 jbyteArray jPrimeP, 1830 jbyteArray jPrimeQ, 1831 jbyteArray jExponentP, 1832 jbyteArray jExponentQ, 1833 jbyteArray jCrtCoefficient) 1834 { 1835 return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent, 1836 jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ, 1837 jCrtCoefficient); 1838 } 1839 1840 /* 1841 * Class: sun_security_mscapi_RSASignature 1842 * Method: generatePublicKeyBlob 1843 * Signature: (I[B[B)[B 1844 */ 1845 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_generatePublicKeyBlob 1846 (JNIEnv *env, jclass clazz, 1847 jint jKeyBitLength, 1848 jbyteArray jModulus, 1849 jbyteArray jPublicExponent) 1850 { 1851 return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent, 1852 NULL, NULL, NULL, NULL, NULL, NULL); 1853 } 1854 1855 /* 1856 * Class: sun_security_mscapi_KeyStore 1857 * Method: storePrivateKey 1858 * Signature: ([BLjava/lang/String;I)Lsun/security/mscapi/RSAPrivateKey; 1859 */ 1860 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey 1861 (JNIEnv *env, jobject clazz, jbyteArray keyBlob, jstring keyContainerName, 1862 jint keySize) 1863 { 1864 HCRYPTPROV hCryptProv = NULL; 1865 HCRYPTKEY hKey = NULL; 1866 DWORD dwBlobLen; 1867 BYTE * pbKeyBlob = NULL; 1868 const char* pszKeyContainerName = NULL; // UUID 1869 jobject privateKey = NULL; 1870 1871 __try 1872 { 1873 if ((pszKeyContainerName = 1874 env->GetStringUTFChars(keyContainerName, NULL)) == NULL) { 1875 __leave; 1876 } 1877 dwBlobLen = env->GetArrayLength(keyBlob); 1878 if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0)) 1879 == NULL) { 1880 __leave; 1881 } 1882 1883 // Acquire a CSP context (create a new key container). 1884 if (::CryptAcquireContext( 1885 &hCryptProv, 1886 pszKeyContainerName, 1887 NULL, 1888 PROV_RSA_FULL, 1889 CRYPT_NEWKEYSET) == FALSE) 1890 { 1891 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1892 __leave; 1893 } 1894 1895 // Import the private key 1896 if (::CryptImportKey( 1897 hCryptProv, 1898 pbKeyBlob, 1899 dwBlobLen, 1900 0, 1901 CRYPT_EXPORTABLE, 1902 &hKey) == FALSE) 1903 { 1904 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1905 __leave; 1906 } 1907 1908 // Get the method ID for the RSAPrivateKey constructor 1909 jclass clazzRSAPrivateKey = 1910 env->FindClass("sun/security/mscapi/RSAPrivateKey"); 1911 if (clazzRSAPrivateKey == NULL) { 1912 __leave; 1913 } 1914 1915 jmethodID mNewRSAPrivateKey = 1916 env->GetMethodID(clazzRSAPrivateKey, "<init>", "(JJI)V"); 1917 if (mNewRSAPrivateKey == NULL) { 1918 __leave; 1919 } 1920 1921 // Create a new RSA private key 1922 privateKey = env->NewObject(clazzRSAPrivateKey, mNewRSAPrivateKey, 1923 (jlong) hCryptProv, (jlong) hKey, keySize); 1924 1925 } 1926 __finally 1927 { 1928 //-------------------------------------------------------------------- 1929 // Clean up. 1930 1931 if (pszKeyContainerName) 1932 env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName); 1933 1934 if (pbKeyBlob) 1935 env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob, 1936 JNI_ABORT); 1937 } 1938 1939 return privateKey; 1940 } 1941 1942 /* 1943 * Class: sun_security_mscapi_RSASignature 1944 * Method: importPublicKey 1945 * Signature: ([BI)Lsun/security/mscapi/RSAPublicKey; 1946 */ 1947 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSASignature_importPublicKey 1948 (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jint keySize) 1949 { 1950 HCRYPTPROV hCryptProv = NULL; 1951 HCRYPTKEY hKey = NULL; 1952 DWORD dwBlobLen; 1953 BYTE * pbKeyBlob = NULL; 1954 jobject publicKey = NULL; 1955 1956 __try 1957 { 1958 dwBlobLen = env->GetArrayLength(keyBlob); 1959 if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0)) 1960 == NULL) { 1961 __leave; 1962 } 1963 1964 // Acquire a CSP context (create a new key container). 1965 // Prefer a PROV_RSA_AES CSP, when available, due to its support 1966 // for SHA-2-based signatures. 1967 if (::CryptAcquireContext( 1968 &hCryptProv, 1969 NULL, 1970 NULL, 1971 PROV_RSA_AES, 1972 CRYPT_VERIFYCONTEXT) == FALSE) 1973 { 1974 // Failover to using the default CSP (PROV_RSA_FULL) 1975 1976 if (::CryptAcquireContext( 1977 &hCryptProv, 1978 NULL, 1979 NULL, 1980 PROV_RSA_FULL, 1981 CRYPT_VERIFYCONTEXT) == FALSE) 1982 { 1983 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1984 __leave; 1985 } 1986 } 1987 1988 // Import the public key 1989 if (::CryptImportKey( 1990 hCryptProv, 1991 pbKeyBlob, 1992 dwBlobLen, 1993 0, 1994 CRYPT_EXPORTABLE, 1995 &hKey) == FALSE) 1996 { 1997 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1998 __leave; 1999 } 2000 2001 // Get the method ID for the RSAPublicKey constructor 2002 jclass clazzRSAPublicKey = 2003 env->FindClass("sun/security/mscapi/RSAPublicKey"); 2004 if (clazzRSAPublicKey == NULL) { 2005 __leave; 2006 } 2007 2008 jmethodID mNewRSAPublicKey = 2009 env->GetMethodID(clazzRSAPublicKey, "<init>", "(JJI)V"); 2010 if (mNewRSAPublicKey == NULL) { 2011 __leave; 2012 } 2013 2014 // Create a new RSA public key 2015 publicKey = env->NewObject(clazzRSAPublicKey, mNewRSAPublicKey, 2016 (jlong) hCryptProv, (jlong) hKey, keySize); 2017 2018 } 2019 __finally 2020 { 2021 //-------------------------------------------------------------------- 2022 // Clean up. 2023 2024 if (pbKeyBlob) 2025 env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob, 2026 JNI_ABORT); 2027 } 2028 2029 return publicKey; 2030 } 2031 2032 } /* extern "C" */