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