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