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