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