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