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 DWORD length = 0; 1447 1448 __try 1449 { 1450 // Get key length (in bits) 1451 //TODO - may need to use KP_BLOCKLEN instead? 1452 // pbData must be a pointer to a DWORD value with KP_KEYLEN 1453 if (!(::CryptGetKeyParam((HCRYPTKEY) hKey, KP_KEYLEN, (BYTE *)&length, &dwDataLen, 1454 0))) { 1455 1456 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1457 __leave; 1458 } 1459 } 1460 __finally 1461 { 1462 // no cleanup required 1463 } 1464 1465 return (jint) length; 1466 } 1467 1468 /* 1469 * Class: sun_security_mscapi_RSACipher 1470 * Method: encryptDecrypt 1471 * Signature: ([BIJZ)[B 1472 */ 1473 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt 1474 (JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey, 1475 jboolean doEncrypt) 1476 { 1477 jbyteArray result = NULL; 1478 jbyte* pData = NULL; 1479 DWORD dwDataLen = jDataSize; 1480 DWORD dwBufLen = env->GetArrayLength(jData); 1481 DWORD i; 1482 BYTE tmp; 1483 1484 __try 1485 { 1486 // Copy data from Java buffer to native buffer 1487 pData = new jbyte[dwBufLen]; 1488 env->GetByteArrayRegion(jData, 0, dwBufLen, pData); 1489 1490 if (doEncrypt == JNI_TRUE) { 1491 // encrypt 1492 if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, 1493 &dwDataLen, dwBufLen)) { 1494 1495 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1496 __leave; 1497 } 1498 dwBufLen = dwDataLen; 1499 1500 // convert from little-endian 1501 for (i = 0; i < dwBufLen / 2; i++) { 1502 tmp = pData[i]; 1503 pData[i] = pData[dwBufLen - i -1]; 1504 pData[dwBufLen - i - 1] = tmp; 1505 } 1506 } else { 1507 // convert to little-endian 1508 for (i = 0; i < dwBufLen / 2; i++) { 1509 tmp = pData[i]; 1510 pData[i] = pData[dwBufLen - i -1]; 1511 pData[dwBufLen - i - 1] = tmp; 1512 } 1513 1514 // decrypt 1515 if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, 1516 &dwBufLen)) { 1517 1518 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1519 __leave; 1520 } 1521 } 1522 1523 // Create new byte array 1524 result = env->NewByteArray(dwBufLen); 1525 1526 // Copy data from native buffer to Java buffer 1527 env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData); 1528 } 1529 __finally 1530 { 1531 if (pData) 1532 delete [] pData; 1533 } 1534 1535 return result; 1536 } 1537 1538 /* 1539 * Class: sun_security_mscapi_RSAPublicKey 1540 * Method: getPublicKeyBlob 1541 * Signature: (J)[B 1542 */ 1543 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyBlob 1544 (JNIEnv *env, jclass clazz, jlong hCryptKey) { 1545 1546 jbyteArray blob = NULL; 1547 DWORD dwBlobLen; 1548 BYTE* pbKeyBlob = NULL; 1549 1550 __try 1551 { 1552 1553 // Determine the size of the blob 1554 if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, 1555 &dwBlobLen)) { 1556 1557 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1558 __leave; 1559 } 1560 1561 pbKeyBlob = new BYTE[dwBlobLen]; 1562 1563 // Generate key blob 1564 if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, 1565 pbKeyBlob, &dwBlobLen)) { 1566 1567 ThrowException(env, KEY_EXCEPTION, GetLastError()); 1568 __leave; 1569 } 1570 1571 // Create new byte array 1572 blob = env->NewByteArray(dwBlobLen); 1573 1574 // Copy data from native buffer to Java buffer 1575 env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob); 1576 } 1577 __finally 1578 { 1579 if (pbKeyBlob) 1580 delete [] pbKeyBlob; 1581 } 1582 1583 return blob; 1584 } 1585 1586 /* 1587 * Class: sun_security_mscapi_RSAPublicKey 1588 * Method: getExponent 1589 * Signature: ([B)[B 1590 */ 1591 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent 1592 (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { 1593 1594 jbyteArray exponent = NULL; 1595 jbyte* exponentBytes = NULL; 1596 jbyte* keyBlob = NULL; 1597 1598 __try { 1599 1600 jsize length = env->GetArrayLength(jKeyBlob); 1601 if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) { 1602 __leave; 1603 } 1604 1605 PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob; 1606 1607 // Check BLOB type 1608 if (pPublicKeyStruc->bType != PUBLICKEYBLOB) { 1609 ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE); 1610 __leave; 1611 } 1612 1613 RSAPUBKEY* pRsaPubKey = 1614 (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); 1615 int len = sizeof(pRsaPubKey->pubexp); 1616 exponentBytes = new jbyte[len]; 1617 1618 // convert from little-endian while copying from blob 1619 for (int i = 0, j = len - 1; i < len; i++, j--) { 1620 exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j]; 1621 } 1622 1623 exponent = env->NewByteArray(len); 1624 env->SetByteArrayRegion(exponent, 0, len, exponentBytes); 1625 } 1626 __finally 1627 { 1628 if (keyBlob) 1629 env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT); 1630 1631 if (exponentBytes) 1632 delete [] exponentBytes; 1633 } 1634 1635 return exponent; 1636 } 1637 1638 /* 1639 * Class: sun_security_mscapi_RSAPublicKey 1640 * Method: getModulus 1641 * Signature: ([B)[B 1642 */ 1643 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus 1644 (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { 1645 1646 jbyteArray modulus = NULL; 1647 jbyte* modulusBytes = NULL; 1648 jbyte* keyBlob = NULL; 1649 1650 __try { 1651 1652 jsize length = env->GetArrayLength(jKeyBlob); 1653 if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) { 1654 __leave; 1655 } 1656 1657 PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob; 1658 1659 // Check BLOB type 1660 if (pPublicKeyStruc->bType != PUBLICKEYBLOB) { 1661 ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE); 1662 __leave; 1663 } 1664 1665 RSAPUBKEY* pRsaPubKey = 1666 (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); 1667 int len = pRsaPubKey->bitlen / 8; 1668 1669 modulusBytes = new jbyte[len]; 1670 BYTE * pbModulus = 1671 (BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); 1672 1673 // convert from little-endian while copying from blob 1674 for (int i = 0, j = len - 1; i < len; i++, j--) { 1675 modulusBytes[i] = pbModulus[j]; 1676 } 1677 1678 modulus = env->NewByteArray(len); 1679 env->SetByteArrayRegion(modulus, 0, len, modulusBytes); 1680 } 1681 __finally 1682 { 1683 if (keyBlob) 1684 env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT); 1685 1686 if (modulusBytes) 1687 delete [] modulusBytes; 1688 } 1689 1690 return modulus; 1691 } 1692 1693 /* 1694 * Convert an array in big-endian byte order into little-endian byte order. 1695 */ 1696 int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination, 1697 int destinationLength) { 1698 1699 int sourceLength = env->GetArrayLength(source); 1700 1701 jbyte* sourceBytes = env->GetByteArrayElements(source, 0); 1702 if (sourceBytes == NULL) { 1703 return -1; 1704 } 1705 1706 int copyLen = sourceLength; 1707 if (sourceLength > destinationLength) { 1708 // source might include an extra sign byte 1709 if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) { 1710 copyLen--; 1711 } else { 1712 return -1; 1713 } 1714 } 1715 1716 // Copy bytes from the end of the source array to the beginning of the 1717 // destination array (until the destination array is full). 1718 // This ensures that the sign byte from the source array will be excluded. 1719 for (int i = 0; i < copyLen; i++) { 1720 destination[i] = sourceBytes[sourceLength - 1 - i]; 1721 } 1722 if (copyLen < destinationLength) { 1723 memset(destination + copyLen, 0, destinationLength - copyLen); 1724 } 1725 1726 env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT); 1727 1728 return destinationLength; 1729 } 1730 1731 /* 1732 * The Microsoft Base Cryptographic Provider supports public-key BLOBs 1733 * that have the following format: 1734 * 1735 * PUBLICKEYSTRUC publickeystruc; 1736 * RSAPUBKEY rsapubkey; 1737 * BYTE modulus[rsapubkey.bitlen/8]; 1738 * 1739 * and private-key BLOBs that have the following format: 1740 * 1741 * PUBLICKEYSTRUC publickeystruc; 1742 * RSAPUBKEY rsapubkey; 1743 * BYTE modulus[rsapubkey.bitlen/8]; 1744 * BYTE prime1[rsapubkey.bitlen/16]; 1745 * BYTE prime2[rsapubkey.bitlen/16]; 1746 * BYTE exponent1[rsapubkey.bitlen/16]; 1747 * BYTE exponent2[rsapubkey.bitlen/16]; 1748 * BYTE coefficient[rsapubkey.bitlen/16]; 1749 * BYTE privateExponent[rsapubkey.bitlen/8]; 1750 * 1751 * This method generates such BLOBs from the key elements supplied. 1752 */ 1753 jbyteArray generateKeyBlob( 1754 JNIEnv *env, 1755 jint jKeyBitLength, 1756 jbyteArray jModulus, 1757 jbyteArray jPublicExponent, 1758 jbyteArray jPrivateExponent, 1759 jbyteArray jPrimeP, 1760 jbyteArray jPrimeQ, 1761 jbyteArray jExponentP, 1762 jbyteArray jExponentQ, 1763 jbyteArray jCrtCoefficient) 1764 { 1765 jsize jKeyByteLength = jKeyBitLength / 8; 1766 jsize jBlobLength; 1767 BOOL bGeneratePrivateKeyBlob; 1768 1769 // Determine whether to generate a public-key or a private-key BLOB 1770 if (jPrivateExponent != NULL && 1771 jPrimeP != NULL && 1772 jPrimeQ != NULL && 1773 jExponentP != NULL && 1774 jExponentQ != NULL && 1775 jCrtCoefficient != NULL) { 1776 1777 bGeneratePrivateKeyBlob = TRUE; 1778 jBlobLength = sizeof(BLOBHEADER) + 1779 sizeof(RSAPUBKEY) + 1780 ((jKeyBitLength / 8) * 4) + 1781 (jKeyBitLength / 16); 1782 1783 } else { 1784 bGeneratePrivateKeyBlob = FALSE; 1785 jBlobLength = sizeof(BLOBHEADER) + 1786 sizeof(RSAPUBKEY) + 1787 (jKeyBitLength / 8); 1788 } 1789 1790 jbyte* jBlobBytes = new jbyte[jBlobLength]; 1791 jbyte* jBlobElement; 1792 jbyteArray jBlob = NULL; 1793 jsize jElementLength; 1794 1795 __try { 1796 1797 BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes; 1798 if (bGeneratePrivateKeyBlob) { 1799 pBlobHeader->bType = PRIVATEKEYBLOB; // 0x07 1800 } else { 1801 pBlobHeader->bType = PUBLICKEYBLOB; // 0x06 1802 } 1803 pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02 1804 pBlobHeader->reserved = 0; // 0x0000 1805 pBlobHeader->aiKeyAlg = CALG_RSA_KEYX; // 0x0000a400 1806 1807 RSAPUBKEY *pRsaPubKey = 1808 (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC)); 1809 if (bGeneratePrivateKeyBlob) { 1810 pRsaPubKey->magic = 0x32415352; // "RSA2" 1811 } else { 1812 pRsaPubKey->magic = 0x31415352; // "RSA1" 1813 } 1814 pRsaPubKey->bitlen = jKeyBitLength; 1815 pRsaPubKey->pubexp = 0; // init 1816 1817 // Sanity check 1818 jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent); 1819 if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) { 1820 ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE); 1821 __leave; 1822 } 1823 // The length argument must be the smaller of jPublicExponentLength 1824 // and sizeof(pRsaPubKey->pubkey) 1825 if ((jElementLength = convertToLittleEndian(env, jPublicExponent, 1826 (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) { 1827 __leave; 1828 } 1829 1830 // Modulus n 1831 jBlobElement = 1832 (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); 1833 if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement, 1834 jKeyByteLength)) < 0) { 1835 __leave; 1836 } 1837 1838 if (bGeneratePrivateKeyBlob) { 1839 // Prime p 1840 jBlobElement += jElementLength; 1841 if ((jElementLength = convertToLittleEndian(env, jPrimeP, 1842 jBlobElement, jKeyByteLength / 2)) < 0) { 1843 __leave; 1844 } 1845 1846 // Prime q 1847 jBlobElement += jElementLength; 1848 if ((jElementLength = convertToLittleEndian(env, jPrimeQ, 1849 jBlobElement, jKeyByteLength / 2)) < 0) { 1850 __leave; 1851 } 1852 1853 // Prime exponent p 1854 jBlobElement += jElementLength; 1855 if ((jElementLength = convertToLittleEndian(env, jExponentP, 1856 jBlobElement, jKeyByteLength / 2)) < 0) { 1857 __leave; 1858 } 1859 1860 // Prime exponent q 1861 jBlobElement += jElementLength; 1862 if ((jElementLength = convertToLittleEndian(env, jExponentQ, 1863 jBlobElement, jKeyByteLength / 2)) < 0) { 1864 __leave; 1865 } 1866 1867 // CRT coefficient 1868 jBlobElement += jElementLength; 1869 if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient, 1870 jBlobElement, jKeyByteLength / 2)) < 0) { 1871 __leave; 1872 } 1873 1874 // Private exponent 1875 jBlobElement += jElementLength; 1876 if ((jElementLength = convertToLittleEndian(env, jPrivateExponent, 1877 jBlobElement, jKeyByteLength)) < 0) { 1878 __leave; 1879 } 1880 } 1881 1882 jBlob = env->NewByteArray(jBlobLength); 1883 env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes); 1884 1885 } 1886 __finally 1887 { 1888 if (jBlobBytes) 1889 delete [] jBlobBytes; 1890 } 1891 1892 return jBlob; 1893 } 1894 1895 /* 1896 * Class: sun_security_mscapi_KeyStore 1897 * Method: generatePrivateKeyBlob 1898 * Signature: (I[B[B[B[B[B[B[B[B)[B 1899 */ 1900 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_KeyStore_generatePrivateKeyBlob 1901 (JNIEnv *env, jclass clazz, 1902 jint jKeyBitLength, 1903 jbyteArray jModulus, 1904 jbyteArray jPublicExponent, 1905 jbyteArray jPrivateExponent, 1906 jbyteArray jPrimeP, 1907 jbyteArray jPrimeQ, 1908 jbyteArray jExponentP, 1909 jbyteArray jExponentQ, 1910 jbyteArray jCrtCoefficient) 1911 { 1912 return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent, 1913 jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ, 1914 jCrtCoefficient); 1915 } 1916 1917 /* 1918 * Class: sun_security_mscapi_RSASignature 1919 * Method: generatePublicKeyBlob 1920 * Signature: (I[B[B)[B 1921 */ 1922 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_generatePublicKeyBlob 1923 (JNIEnv *env, jclass clazz, 1924 jint jKeyBitLength, 1925 jbyteArray jModulus, 1926 jbyteArray jPublicExponent) 1927 { 1928 return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent, 1929 NULL, NULL, NULL, NULL, NULL, NULL); 1930 } 1931 1932 /* 1933 * Class: sun_security_mscapi_KeyStore 1934 * Method: storePrivateKey 1935 * Signature: ([BLjava/lang/String;I)Lsun/security/mscapi/RSAPrivateKey; 1936 */ 1937 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey 1938 (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jstring keyContainerName, 1939 jint keySize) 1940 { 1941 HCRYPTPROV hCryptProv = NULL; 1942 HCRYPTKEY hKey = NULL; 1943 DWORD dwBlobLen; 1944 BYTE * pbKeyBlob = NULL; 1945 const char* pszKeyContainerName = NULL; // UUID 1946 jobject privateKey = NULL; 1947 1948 __try 1949 { 1950 if ((pszKeyContainerName = 1951 env->GetStringUTFChars(keyContainerName, NULL)) == NULL) { 1952 __leave; 1953 } 1954 dwBlobLen = env->GetArrayLength(keyBlob); 1955 if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0)) 1956 == NULL) { 1957 __leave; 1958 } 1959 1960 // Acquire a CSP context (create a new key container). 1961 if (::CryptAcquireContext( 1962 &hCryptProv, 1963 pszKeyContainerName, 1964 NULL, 1965 PROV_RSA_FULL, 1966 CRYPT_NEWKEYSET) == FALSE) 1967 { 1968 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1969 __leave; 1970 } 1971 1972 // Import the private key 1973 if (::CryptImportKey( 1974 hCryptProv, 1975 pbKeyBlob, 1976 dwBlobLen, 1977 0, 1978 CRYPT_EXPORTABLE, 1979 &hKey) == FALSE) 1980 { 1981 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 1982 __leave; 1983 } 1984 1985 // Get the method ID for the RSAPrivateKey constructor 1986 jclass clazzRSAPrivateKey = 1987 env->FindClass("sun/security/mscapi/RSAPrivateKey"); 1988 if (clazzRSAPrivateKey == NULL) { 1989 __leave; 1990 } 1991 1992 jmethodID mNewRSAPrivateKey = 1993 env->GetMethodID(clazzRSAPrivateKey, "<init>", "(JJI)V"); 1994 if (mNewRSAPrivateKey == NULL) { 1995 __leave; 1996 } 1997 1998 // Create a new RSA private key 1999 privateKey = env->NewObject(clazzRSAPrivateKey, mNewRSAPrivateKey, 2000 (jlong) hCryptProv, (jlong) hKey, keySize); 2001 2002 } 2003 __finally 2004 { 2005 //-------------------------------------------------------------------- 2006 // Clean up. 2007 2008 if (pszKeyContainerName) 2009 env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName); 2010 2011 if (pbKeyBlob) 2012 env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob, 2013 JNI_ABORT); 2014 } 2015 2016 return privateKey; 2017 } 2018 2019 /* 2020 * Class: sun_security_mscapi_RSASignature 2021 * Method: importPublicKey 2022 * Signature: ([BI)Lsun/security/mscapi/RSAPublicKey; 2023 */ 2024 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSASignature_importPublicKey 2025 (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jint keySize) 2026 { 2027 HCRYPTPROV hCryptProv = NULL; 2028 HCRYPTKEY hKey = NULL; 2029 DWORD dwBlobLen; 2030 BYTE * pbKeyBlob = NULL; 2031 jobject publicKey = NULL; 2032 2033 __try 2034 { 2035 dwBlobLen = env->GetArrayLength(keyBlob); 2036 if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0)) 2037 == NULL) { 2038 __leave; 2039 } 2040 2041 // Acquire a CSP context (create a new key container). 2042 // Prefer a PROV_RSA_AES CSP, when available, due to its support 2043 // for SHA-2-based signatures. 2044 if (::CryptAcquireContext( 2045 &hCryptProv, 2046 NULL, 2047 NULL, 2048 PROV_RSA_AES, 2049 CRYPT_VERIFYCONTEXT) == FALSE) 2050 { 2051 // Failover to using the default CSP (PROV_RSA_FULL) 2052 2053 if (::CryptAcquireContext( 2054 &hCryptProv, 2055 NULL, 2056 NULL, 2057 PROV_RSA_FULL, 2058 CRYPT_VERIFYCONTEXT) == FALSE) 2059 { 2060 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 2061 __leave; 2062 } 2063 } 2064 2065 // Import the public key 2066 if (::CryptImportKey( 2067 hCryptProv, 2068 pbKeyBlob, 2069 dwBlobLen, 2070 0, 2071 CRYPT_EXPORTABLE, 2072 &hKey) == FALSE) 2073 { 2074 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); 2075 __leave; 2076 } 2077 2078 // Get the method ID for the RSAPublicKey constructor 2079 jclass clazzRSAPublicKey = 2080 env->FindClass("sun/security/mscapi/RSAPublicKey"); 2081 if (clazzRSAPublicKey == NULL) { 2082 __leave; 2083 } 2084 2085 jmethodID mNewRSAPublicKey = 2086 env->GetMethodID(clazzRSAPublicKey, "<init>", "(JJI)V"); 2087 if (mNewRSAPublicKey == NULL) { 2088 __leave; 2089 } 2090 2091 // Create a new RSA public key 2092 publicKey = env->NewObject(clazzRSAPublicKey, mNewRSAPublicKey, 2093 (jlong) hCryptProv, (jlong) hKey, keySize); 2094 2095 } 2096 __finally 2097 { 2098 //-------------------------------------------------------------------- 2099 // Clean up. 2100 2101 if (pbKeyBlob) 2102 env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob, 2103 JNI_ABORT); 2104 } 2105 2106 return publicKey; 2107 } 2108 2109 } /* extern "C" */