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