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