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