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