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