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