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