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