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