1 /*
   2  * Copyright (c) 2005, 2020, 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 #include "sun_security_mscapi_CKey.h"
  41 #include "sun_security_mscapi_CKeyStore.h"
  42 #include "sun_security_mscapi_PRNG.h"
  43 #include "sun_security_mscapi_CRSACipher.h"
  44 #include "sun_security_mscapi_CKeyPairGenerator_RSA.h"
  45 #include "sun_security_mscapi_CPublicKey.h"
  46 #include "sun_security_mscapi_CPublicKey_CRSAPublicKey.h"
  47 #include "sun_security_mscapi_CSignature.h"
  48 #include "sun_security_mscapi_CSignature_RSA.h"
  49 
  50 #define OID_EKU_ANY         "2.5.29.37.0"
  51 
  52 #define CERTIFICATE_PARSING_EXCEPTION \
  53                             "java/security/cert/CertificateParsingException"
  54 #define INVALID_KEY_EXCEPTION \
  55                             "java/security/InvalidKeyException"
  56 #define KEY_EXCEPTION       "java/security/KeyException"
  57 #define KEYSTORE_EXCEPTION  "java/security/KeyStoreException"
  58 #define PROVIDER_EXCEPTION  "java/security/ProviderException"
  59 #define SIGNATURE_EXCEPTION "java/security/SignatureException"
  60 #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
  61 
  62 #define SS_CHECK(Status) \
  63         if (Status != ERROR_SUCCESS) { \
  64             ThrowException(env, SIGNATURE_EXCEPTION, Status); \
  65             __leave; \
  66         }
  67 
  68 #define PP(fmt, ...) \
  69         if (trace) { \
  70             fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
  71             fprintf(stdout, fmt, ##__VA_ARGS__); \
  72             fprintf(stdout, "\n"); \
  73             fflush(stdout); \
  74         }
  75 
  76 extern "C" {
  77 
  78 char* trace = getenv("CAPI_TRACE");
  79 
  80 /*
  81  * Declare library specific JNI_Onload entry if static build
  82  */
  83 DEF_STATIC_JNI_OnLoad
  84 
  85 void showProperty(NCRYPT_HANDLE hKey);
  86 
  87 void dump(LPSTR title, PBYTE data, DWORD len)
  88 {
  89     if (trace) {
  90         printf("==== %s ====\n", title);
  91         for (DWORD i = 0; i < len; i+=16) {
  92             printf("%04x: ", i);
  93             for (int j = 0; j < 16; j++) {
  94                 if (j == 8) {
  95                     printf("  ");
  96                 }
  97                 if (i + j < len) {
  98                     printf("%02X ", *(data + i + j) & 0xff);
  99                 } else {
 100                     printf("   ");
 101                 }
 102             }
 103             for (int j = 0; j < 16; j++) {
 104                 if (i + j < len) {
 105                     int k = *(data + i + j) & 0xff;
 106                     if (k < 32 || k > 127) printf(".");
 107                     else printf("%c", (char)k);
 108                 }
 109             }
 110             printf("\n");
 111         }
 112         fflush(stdout);
 113     }
 114 }
 115 
 116 /*
 117  * Throws an arbitrary Java exception with the given message.
 118  */
 119 void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,
 120                                const char *szMessage)
 121 {
 122     jclass exceptionClazz = env->FindClass(exceptionName);
 123     if (exceptionClazz != NULL) {
 124         env->ThrowNew(exceptionClazz, szMessage);
 125     }
 126 }
 127 
 128 /*
 129  * Throws an arbitrary Java exception.
 130  * The exception message is a Windows system error message.
 131  */
 132 void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)
 133 {
 134     char szMessage[1024];
 135     szMessage[0] = '\0';
 136 
 137     DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
 138         NULL, szMessage, sizeof(szMessage), NULL);
 139     if (res == 0) {
 140         strcpy(szMessage, "Unknown error");
 141     }
 142 
 143     ThrowExceptionWithMessage(env, exceptionName, szMessage);
 144 }
 145 
 146 /*
 147  * Overloaded 'operator new[]' variant, which will raise Java's
 148  * OutOfMemoryError in the case of a failure.
 149  */
 150 void* operator new[](std::size_t size, JNIEnv *env)
 151 {
 152     void* buf = ::operator new[](size, std::nothrow);
 153     if (buf == NULL) {
 154         ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,
 155                 "Native memory allocation failed");
 156     }
 157     return buf;
 158 }
 159 
 160 /*
 161  * Maps the name of a hash algorithm to an algorithm identifier.
 162  */
 163 ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
 164 
 165     const char* pszHashAlgorithm = NULL;
 166     ALG_ID algId = 0;
 167 
 168     if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
 169         == NULL) {
 170         return algId;
 171     }
 172 
 173     if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
 174         (strcmp("SHA1", pszHashAlgorithm) == 0) ||
 175         (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
 176 
 177         algId = CALG_SHA1;
 178     } else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {
 179         algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5
 180     } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
 181         algId = CALG_SHA_256;
 182     } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
 183         algId = CALG_SHA_384;
 184     } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
 185         algId = CALG_SHA_512;
 186     } else if (strcmp("MD5", pszHashAlgorithm) == 0) {
 187         algId = CALG_MD5;
 188     } else if (strcmp("MD2", pszHashAlgorithm) == 0) {
 189         algId = CALG_MD2;
 190     }
 191 
 192     if (pszHashAlgorithm)
 193         env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
 194 
 195    return algId;
 196 }
 197 
 198 /*
 199  * Maps the name of a hash algorithm to a CNG Algorithm Identifier.
 200  */
 201 LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {
 202 
 203     const char* pszHashAlgorithm = NULL;
 204     LPCWSTR id = NULL;
 205 
 206     if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
 207             == NULL) {
 208         return id;
 209     }
 210 
 211     if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
 212         (strcmp("SHA1", pszHashAlgorithm) == 0) ||
 213         (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
 214 
 215         id = BCRYPT_SHA1_ALGORITHM;
 216     } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
 217         id = BCRYPT_SHA256_ALGORITHM;
 218     } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
 219         id = BCRYPT_SHA384_ALGORITHM;
 220     } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
 221         id = BCRYPT_SHA512_ALGORITHM;
 222     }
 223 
 224     if (pszHashAlgorithm)
 225         env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
 226 
 227     return id;
 228 }
 229 
 230 /*
 231  * Returns a certificate chain context given a certificate context and key
 232  * usage identifier.
 233  */
 234 bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)
 235 {
 236     CERT_ENHKEY_USAGE        EnhkeyUsage;
 237     CERT_USAGE_MATCH         CertUsage;
 238     CERT_CHAIN_PARA          ChainPara;
 239     DWORD                    dwFlags = 0;
 240     LPSTR                    szUsageIdentifierArray[1];
 241 
 242     szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;
 243     EnhkeyUsage.cUsageIdentifier = 1;
 244     EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;
 245     CertUsage.dwType = USAGE_MATCH_TYPE_AND;
 246     CertUsage.Usage  = EnhkeyUsage;
 247     ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
 248     ChainPara.RequestedUsage=CertUsage;
 249 
 250     // Build a chain using CertGetCertificateChain
 251     // and the certificate retrieved.
 252     return (::CertGetCertificateChain(NULL,     // use the default chain engine
 253                 pCertContext,   // pointer to the end certificate
 254                 NULL,           // use the default time
 255                 NULL,           // search no additional stores
 256                 &ChainPara,     // use AND logic and enhanced key usage
 257                                 //  as indicated in the ChainPara
 258                                 //  data structure
 259                 dwFlags,
 260                 NULL,           // currently reserved
 261                 ppChainContext) == TRUE);       // return a pointer to the chain created
 262 }
 263 
 264 
 265 /////////////////////////////////////////////////////////////////////////////
 266 //
 267 
 268 /*
 269  * Class:     sun_security_mscapi_PRNG
 270  * Method:    getContext
 271  * Signature: ()J
 272  */
 273 JNIEXPORT jlong JNICALL Java_sun_security_mscapi_PRNG_getContext
 274         (JNIEnv *env, jclass clazz) {
 275     HCRYPTPROV hCryptProv = NULL;
 276     if(::CryptAcquireContext( //deprecated
 277        &hCryptProv,
 278        NULL,
 279        NULL,
 280        PROV_RSA_FULL,
 281        CRYPT_VERIFYCONTEXT) == FALSE)
 282     {
 283         ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
 284     }
 285     return hCryptProv;
 286 }
 287 
 288 
 289 /*
 290  * Class:     sun_security_mscapi_PRNG
 291  * Method:    releaseContext
 292  * Signature: (J)V
 293  */
 294 JNIEXPORT void JNICALL Java_sun_security_mscapi_PRNG_releaseContext
 295         (JNIEnv *env, jclass clazz, jlong ctxt) {
 296     if (ctxt) {
 297         ::CryptReleaseContext((HCRYPTPROV)ctxt, 0); //deprecated
 298     }
 299 }
 300 
 301 
 302 /*
 303  * Class:     sun_security_mscapi_PRNG
 304  * Method:    generateSeed
 305  * Signature: (JI[B)[B
 306  */
 307 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
 308   (JNIEnv *env, jclass clazz, jlong ctxt, jint length, jbyteArray seed)
 309 {
 310 
 311     HCRYPTPROV hCryptProv = (HCRYPTPROV)ctxt;
 312     jbyte*     reseedBytes = NULL;
 313     jbyte*     seedBytes = NULL;
 314     jbyteArray result = NULL;
 315 
 316     __try
 317     {
 318         /*
 319          * If length is negative then use the supplied seed to re-seed the
 320          * generator and return null.
 321          * If length is non-zero then generate a new seed according to the
 322          * requested length and return the new seed.
 323          * If length is zero then overwrite the supplied seed with a new
 324          * seed of the same length and return the seed.
 325          */
 326         if (length < 0) {
 327             length = env->GetArrayLength(seed);
 328             if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
 329                 __leave;
 330             }
 331 
 332             if (::CryptGenRandom( //deprecated
 333                 hCryptProv,
 334                 length,
 335                 (BYTE *) reseedBytes) == FALSE) {
 336 
 337                 ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
 338                 __leave;
 339             }
 340 
 341             result = NULL;
 342 
 343         } else {
 344 
 345             if (length > 0) {
 346                 seed = env->NewByteArray(length);
 347                 if (seed == NULL) {
 348                     __leave;
 349                 }
 350             } else {
 351                 length = env->GetArrayLength(seed);
 352             }
 353 
 354             if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
 355                 __leave;
 356             }
 357 
 358             if (::CryptGenRandom( //deprecated
 359                 hCryptProv,
 360                 length,
 361                 (BYTE *) seedBytes) == FALSE) {
 362 
 363                 ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
 364                 __leave;
 365             }
 366 
 367             result = seed; // seed will be updated when seedBytes gets released
 368         }
 369     }
 370     __finally
 371     {
 372         //--------------------------------------------------------------------
 373         // Clean up.
 374 
 375         if (reseedBytes)
 376             env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);
 377 
 378         if (seedBytes)
 379             env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
 380     }
 381 
 382     return result;
 383 }
 384 
 385 
 386 /*
 387  * Class:     sun_security_mscapi_CKeyStore
 388  * Method:    loadKeysOrCertificateChains
 389  * Signature: (Ljava/lang/String;)V
 390  */
 391 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains
 392   (JNIEnv *env, jobject obj, jstring jCertStoreName)
 393 {
 394     /**
 395      * Certificate in cert store has enhanced key usage extension
 396      * property (or EKU property) that is not part of the certificate itself. To determine
 397      * if the certificate should be returned, both the enhanced key usage in certificate
 398      * extension block and the extension property stored along with the certificate in
 399      * certificate store should be examined. Otherwise, we won't be able to determine
 400      * the proper key usage from the Java side because the information is not stored as
 401      * part of the encoded certificate.
 402      */
 403 
 404     const char* pszCertStoreName = NULL;
 405     HCERTSTORE hCertStore = NULL;
 406     PCCERT_CONTEXT pCertContext = NULL;
 407     char* pszNameString = NULL; // certificate's friendly name
 408     DWORD cchNameString = 0;
 409 
 410 
 411     __try
 412     {
 413         // Open a system certificate store.
 414         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
 415             == NULL) {
 416             __leave;
 417         }
 418         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))
 419             == NULL) {
 420 
 421             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
 422             __leave;
 423         }
 424 
 425         // Determine clazz and method ID to generate certificate
 426         jclass clazzArrayList = env->FindClass("java/util/ArrayList");
 427         if (clazzArrayList == NULL) {
 428             __leave;
 429         }
 430 
 431         jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");
 432         if (mNewArrayList == NULL) {
 433             __leave;
 434         }
 435 
 436         jclass clazzOfThis = env->GetObjectClass(obj);
 437         if (clazzOfThis == NULL) {
 438             __leave;
 439         }
 440 
 441         jmethodID mGenCert = env->GetMethodID(clazzOfThis,
 442                                               "generateCertificate",
 443                                               "([BLjava/util/Collection;)V");
 444         if (mGenCert == NULL) {
 445             __leave;
 446         }
 447 
 448         // Determine method ID to generate certificate chain
 449         jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,
 450                                                    "generateCertificateChain",
 451                                                    "(Ljava/lang/String;Ljava/util/Collection;)V");
 452         if (mGenCertChain == NULL) {
 453             __leave;
 454         }
 455 
 456         // Determine method ID to generate RSA certificate chain
 457         jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,
 458                                                    "generateKeyAndCertificateChain",
 459                                                    "(ZLjava/lang/String;JJILjava/util/Collection;)V");
 460         if (mGenKeyAndCertChain == NULL) {
 461             __leave;
 462         }
 463 
 464         // Use CertEnumCertificatesInStore to get the certificates
 465         // from the open store. pCertContext must be reset to
 466         // NULL to retrieve the first certificate in the store.
 467         while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
 468         {
 469             PP("--------------------------");
 470             // Check if private key available - client authentication certificate
 471             // must have private key available.
 472             HCRYPTPROV hCryptProv = NULL;
 473             DWORD dwKeySpec = 0;
 474             HCRYPTKEY hUserKey = NULL;
 475             BOOL bCallerFreeProv = FALSE;
 476             BOOL bHasNoPrivateKey = FALSE;
 477             DWORD dwPublicKeyLength = 0;
 478 
 479             // First, probe it silently
 480             if (::CryptAcquireCertificatePrivateKey(pCertContext,
 481                     CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,
 482                     &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
 483                 && GetLastError() != NTE_SILENT_CONTEXT)
 484             {
 485                 PP("bHasNoPrivateKey = TRUE!");
 486                 bHasNoPrivateKey = TRUE;
 487             }
 488             else
 489             {
 490                 if (bCallerFreeProv == TRUE) {
 491                     ::CryptReleaseContext(hCryptProv, NULL); // deprecated
 492                     bCallerFreeProv = FALSE;
 493                 }
 494 
 495                 // Second, acquire the key normally (not silently)
 496                 if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,
 497                         &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
 498                 {
 499                     PP("bHasNoPrivateKey = TRUE!!");
 500                     bHasNoPrivateKey = TRUE;
 501                 }
 502                 else
 503                 {
 504                     if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
 505                         PP("CNG %I64d", (__int64)hCryptProv);
 506                     } else {
 507                         // Private key is available
 508                         BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
 509 
 510                         // Skip certificate if cannot find private key
 511                         if (bGetUserKey == FALSE) {
 512                             if (bCallerFreeProv)
 513                                 ::CryptReleaseContext(hCryptProv, NULL); // deprecated
 514                             continue;
 515                         }
 516 
 517                         // Set cipher mode to ECB
 518                         DWORD dwCipherMode = CRYPT_MODE_ECB;
 519                         ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
 520                         PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);
 521                     }
 522                     // If the private key is present in smart card, we may not be able to
 523                     // determine the key length by using the private key handle. However,
 524                     // since public/private key pairs must have the same length, we could
 525                     // determine the key length of the private key by using the public key
 526                     // in the certificate.
 527                     dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
 528                             &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
 529                 }
 530             }
 531             PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
 532 
 533             // Build certificate chain by using system certificate store.
 534             // Add cert chain into collection for any key usage.
 535             //
 536             if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
 537             {
 538                 for (DWORD i = 0; i < pCertChainContext->cChain; i++)
 539                 {
 540                     // Found cert chain
 541                     PCERT_SIMPLE_CHAIN rgpChain =
 542                         pCertChainContext->rgpChain[i];
 543 
 544                     // Create ArrayList to store certs in each chain
 545                     jobject jArrayList =
 546                         env->NewObject(clazzArrayList, mNewArrayList);
 547                     if (jArrayList == NULL) {
 548                         __leave;
 549                     }
 550 
 551                     // Cleanup the previous allocated name
 552                     if (pszNameString) {
 553                         delete [] pszNameString;
 554                         pszNameString = NULL;
 555                     }
 556 
 557                     for (unsigned int j=0; j < rgpChain->cElement; j++)
 558                     {
 559                         PCERT_CHAIN_ELEMENT rgpElement =
 560                             rgpChain->rgpElement[j];
 561                         PCCERT_CONTEXT pc = rgpElement->pCertContext;
 562 
 563                         // Retrieve the friendly name of the first certificate
 564                         // in the chain
 565                         if (j == 0) {
 566 
 567                             // If the cert's name cannot be retrieved then
 568                             // pszNameString remains set to NULL.
 569                             // (An alias name will be generated automatically
 570                             // when storing this cert in the keystore.)
 571 
 572                             // Get length of friendly name
 573                             if ((cchNameString = CertGetNameString(pc,
 574                                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
 575                                 NULL, 0)) > 1) {
 576 
 577                                 // Found friendly name
 578                                 pszNameString = new (env) char[cchNameString];
 579                                 if (pszNameString == NULL) {
 580                                     __leave;
 581                                 }
 582 
 583                                 CertGetNameString(pc,
 584                                     CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
 585                                     pszNameString, cchNameString);
 586                             }
 587                         }
 588 
 589                         BYTE* pbCertEncoded = pc->pbCertEncoded;
 590                         DWORD cbCertEncoded = pc->cbCertEncoded;
 591 
 592                         // Allocate and populate byte array
 593                         jbyteArray byteArray = env->NewByteArray(cbCertEncoded);
 594                         if (byteArray == NULL) {
 595                             __leave;
 596                         }
 597                         env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,
 598                             (jbyte*) pbCertEncoded);
 599 
 600                         // Generate certificate from byte array and store into
 601                         // cert collection
 602                         env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
 603                     }
 604 
 605                     // Usually pszNameString should be non-NULL. It's either
 606                     // the friendly name or an element from the subject name
 607                     // or SAN.
 608                     if (pszNameString)
 609                     {
 610                         PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
 611                         if (bHasNoPrivateKey)
 612                         {
 613                             // Generate certificate chain and store into cert chain
 614                             // collection
 615                             jstring name = env->NewStringUTF(pszNameString);
 616                             if (name == NULL) {
 617                                 __leave;
 618                             }
 619                             env->CallVoidMethod(obj, mGenCertChain,
 620                                 name,
 621                                 jArrayList);
 622                         }
 623                         else
 624                         {
 625                             if (hUserKey) {
 626                                 // Only accept RSA for CAPI
 627                                 DWORD dwData = CALG_RSA_KEYX;
 628                                 DWORD dwSize = sizeof(DWORD);
 629                                 ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
 630                                         &dwSize, NULL);
 631                                 if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
 632                                 {
 633                                     // Generate RSA certificate chain and store into cert
 634                                     // chain collection
 635                                     jstring name = env->NewStringUTF(pszNameString);
 636                                     if (name == NULL) {
 637                                         __leave;
 638                                     }
 639                                     env->CallVoidMethod(obj, mGenKeyAndCertChain,
 640                                             1,
 641                                             name,
 642                                             (jlong) hCryptProv, (jlong) hUserKey,
 643                                             dwPublicKeyLength, jArrayList);
 644                                 }
 645                             } else {
 646                                 // Only accept EC for CNG
 647                                 BYTE buffer[32];
 648                                 DWORD len = 0;
 649                                 if (::NCryptGetProperty(
 650                                         hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
 651                                         (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
 652                                     jstring name = env->NewStringUTF(pszNameString);
 653                                     if (name == NULL) {
 654                                         __leave;
 655                                     }
 656                                     if (buffer[0] == 'E' && buffer[2] == 'C'
 657                                             && (dwPublicKeyLength == 256
 658                                                     || dwPublicKeyLength == 384
 659                                                     || dwPublicKeyLength == 521)) {
 660                                         env->CallVoidMethod(obj, mGenKeyAndCertChain,
 661                                             0,
 662                                             name,
 663                                             (jlong) hCryptProv, (jlong) 0,
 664                                             dwPublicKeyLength, jArrayList);
 665                                     } else if (buffer[0] == 'R' && buffer[2] == 'S'
 666                                             && buffer[4] == 'A') {
 667                                         env->CallVoidMethod(obj, mGenKeyAndCertChain,
 668                                             1,
 669                                             name,
 670                                             (jlong) hCryptProv, (jlong) 0,
 671                                             dwPublicKeyLength, jArrayList);
 672                                     } else {
 673                                         dump("Unknown NCRYPT_ALGORITHM_PROPERTY", buffer, len);
 674                                     }
 675                                 }
 676                             }
 677                         }
 678                     }
 679                 }
 680 
 681                 // Free cert chain
 682                 if (pCertChainContext)
 683                     ::CertFreeCertificateChain(pCertChainContext);
 684             } else {
 685                 PP("GetCertificateChain failed %d", GetLastError());
 686             }
 687         }
 688     }
 689     __finally
 690     {
 691         if (hCertStore)
 692             ::CertCloseStore(hCertStore, 0);
 693 
 694         if (pszCertStoreName)
 695             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
 696 
 697         if (pszNameString)
 698             delete [] pszNameString;
 699     }
 700 }
 701 
 702 
 703 /*
 704  * Class:     sun_security_mscapi_CKey
 705  * Method:    cleanUp
 706  * Signature: (JJ)V
 707  */
 708 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp
 709   (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)
 710 {
 711     if (hCryptKey == NULL && hCryptProv != NULL) {
 712         NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);
 713     } else {
 714         if (hCryptKey != NULL)
 715             ::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated
 716 
 717         if (hCryptProv != NULL)
 718             ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated
 719     }
 720 }
 721 
 722 /*
 723  * Class:     sun_security_mscapi_CSignature
 724  * Method:    signHash
 725  * Signature: (Z[BILjava/lang/String;JJ)[B
 726  */
 727 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash
 728   (JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,
 729         jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,
 730         jlong hCryptKey)
 731 {
 732     HCRYPTHASH hHash = NULL;
 733     jbyte* pHashBuffer = NULL;
 734     jbyte* pSignedHashBuffer = NULL;
 735     jbyteArray jSignedHash = NULL;
 736     HCRYPTPROV hCryptProvAlt = NULL;
 737 
 738     __try
 739     {
 740         // Map hash algorithm
 741         ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
 742 
 743         // Acquire a hash object handle.
 744         if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) //deprecated
 745         {
 746             // Failover to using the PROV_RSA_AES CSP
 747 
 748             DWORD cbData = 256;
 749             BYTE pbData[256];
 750             pbData[0] = '\0';
 751 
 752             // Get name of the key container
 753             ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
 754                 (BYTE *)pbData, &cbData, 0);
 755 
 756             // Acquire an alternative CSP handle
 757             if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
 758                 PROV_RSA_AES, 0) == FALSE)
 759             {
 760 
 761                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 762                 __leave;
 763             }
 764 
 765             // Acquire a hash object handle.
 766             if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, //deprecated
 767                 &hHash) == FALSE)
 768             {
 769                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 770                 __leave;
 771             }
 772         }
 773 
 774         // Copy hash from Java to native buffer
 775         pHashBuffer = new (env) jbyte[jHashSize];
 776         if (pHashBuffer == NULL) {
 777             __leave;
 778         }
 779         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
 780 
 781         // Set hash value in the hash object
 782         if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) //deprecated
 783         {
 784             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 785             __leave;
 786         }
 787 
 788         // Determine key spec.
 789         DWORD dwKeySpec = AT_SIGNATURE;
 790         ALG_ID dwAlgId;
 791         DWORD dwAlgIdLen = sizeof(ALG_ID);
 792 
 793         if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated
 794             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 795             __leave;
 796 
 797         }
 798         if (CALG_RSA_KEYX == dwAlgId) {
 799             dwKeySpec = AT_KEYEXCHANGE;
 800         }
 801 
 802         // Determine size of buffer
 803         DWORD dwBufLen = 0;
 804         DWORD dwFlags = 0;
 805 
 806         if (noHashOID == JNI_TRUE) {
 807             dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature
 808         }
 809 
 810         if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) //deprecated
 811         {
 812             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 813             __leave;
 814         }
 815 
 816         pSignedHashBuffer = new (env) jbyte[dwBufLen];
 817         if (pSignedHashBuffer == NULL) {
 818             __leave;
 819         }
 820         if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) //deprecated
 821         {
 822             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
 823             __leave;
 824         }
 825 
 826         // Create new byte array
 827         jbyteArray temp = env->NewByteArray(dwBufLen);
 828         if (temp == NULL) {
 829             __leave;
 830         }
 831 
 832         // Copy data from native buffer
 833         env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
 834 
 835         jSignedHash = temp;
 836     }
 837     __finally
 838     {
 839         if (pSignedHashBuffer)
 840             delete [] pSignedHashBuffer;
 841 
 842         if (pHashBuffer)
 843             delete [] pHashBuffer;
 844 
 845         if (hHash)
 846             ::CryptDestroyHash(hHash); //deprecated
 847 
 848         if (hCryptProvAlt)
 849             ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
 850     }
 851 
 852     return jSignedHash;
 853 }
 854 
 855 /*
 856  * Class:     sun_security_mscapi_CSignature
 857  * Method:    signCngHash
 858  * Signature: (I[BIILjava/lang/String;JJ)[B
 859  */
 860 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
 861   (JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,
 862         jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
 863         jlong hCryptKey)
 864 {
 865     jbyteArray jSignedHash = NULL;
 866 
 867     jbyte* pHashBuffer = NULL;
 868     jbyte* pSignedHashBuffer = NULL;
 869     NCRYPT_KEY_HANDLE hk = NULL;
 870 
 871     __try
 872     {
 873         if (hCryptKey == 0) {
 874             hk = (NCRYPT_KEY_HANDLE)hCryptProv;
 875         } else {
 876             SS_CHECK(::NCryptTranslateHandle(
 877                 NULL,
 878                 &hk,
 879                 (HCRYPTPROV)hCryptProv,
 880                 (HCRYPTKEY)hCryptKey,
 881                 NULL,
 882                 0));
 883         }
 884 
 885         // Copy hash from Java to native buffer
 886         pHashBuffer = new (env) jbyte[jHashSize];
 887         if (pHashBuffer == NULL) {
 888             __leave;
 889         }
 890         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
 891 
 892         VOID* param;
 893         DWORD dwFlags;
 894 
 895         switch (type) {
 896         case 0:
 897             param = NULL;
 898             dwFlags = 0;
 899             break;
 900         case 1:
 901             BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
 902             if (jHashAlgorithm) {
 903                 pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
 904                 if (pkcs1Info.pszAlgId == NULL) {
 905                     ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
 906                             "Unrecognised hash algorithm");
 907                     __leave;
 908                 }
 909             } else {
 910                 pkcs1Info.pszAlgId = NULL;
 911             }
 912             param = &pkcs1Info;
 913             dwFlags = BCRYPT_PAD_PKCS1;
 914             break;
 915         case 2:
 916             BCRYPT_PSS_PADDING_INFO pssInfo;
 917             pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
 918             pssInfo.cbSalt = saltLen;
 919             if (pssInfo.pszAlgId == NULL) {
 920                 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
 921                         "Unrecognised hash algorithm");
 922                 __leave;
 923             }
 924             param = &pssInfo;
 925             dwFlags = BCRYPT_PAD_PSS;
 926             break;
 927         }
 928 
 929         DWORD jSignedHashSize = 0;
 930         SS_CHECK(::NCryptSignHash(
 931                 hk,
 932                 param,
 933                 (BYTE*)pHashBuffer, jHashSize,
 934                 NULL, 0, &jSignedHashSize,
 935                 dwFlags
 936                 ));
 937 
 938         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
 939         if (pSignedHashBuffer == NULL) {
 940             __leave;
 941         }
 942 
 943         SS_CHECK(::NCryptSignHash(
 944                 hk,
 945                 param,
 946                 (BYTE*)pHashBuffer, jHashSize,
 947                 (BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,
 948                 dwFlags
 949                 ));
 950 
 951         // Create new byte array
 952         jbyteArray temp = env->NewByteArray(jSignedHashSize);
 953         if (temp == NULL) {
 954             __leave;
 955         }
 956 
 957         // Copy data from native buffer
 958         env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);
 959 
 960         jSignedHash = temp;
 961     }
 962     __finally
 963     {
 964         if (pSignedHashBuffer)
 965             delete [] pSignedHashBuffer;
 966 
 967         if (pHashBuffer)
 968             delete [] pHashBuffer;
 969 
 970         if (hCryptKey != 0 && hk != NULL)
 971             ::NCryptFreeObject(hk);
 972     }
 973 
 974     return jSignedHash;
 975 }
 976 
 977 /*
 978  * Class:     sun_security_mscapi_CSignature
 979  * Method:    verifySignedHash
 980  * Signature: ([BIL/java/lang/String;[BIJJ)Z
 981  */
 982 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash
 983   (JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,
 984         jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,
 985         jlong hCryptProv, jlong hCryptKey)
 986 {
 987     HCRYPTHASH hHash = NULL;
 988     jbyte* pHashBuffer = NULL;
 989     jbyte* pSignedHashBuffer = NULL;
 990     DWORD dwSignedHashBufferLen = jSignedHashSize;
 991     jboolean result = JNI_FALSE;
 992     HCRYPTPROV hCryptProvAlt = NULL;
 993 
 994     __try
 995     {
 996         // Map hash algorithm
 997         ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
 998 
 999         // Acquire a hash object handle.
1000         if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)
1001             == FALSE)
1002         {
1003             // Failover to using the PROV_RSA_AES CSP
1004 
1005             DWORD cbData = 256;
1006             BYTE pbData[256];
1007             pbData[0] = '\0';
1008 
1009             // Get name of the key container
1010             ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
1011                 (BYTE *)pbData, &cbData, 0);
1012 
1013             // Acquire an alternative CSP handle
1014             if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
1015                 PROV_RSA_AES, 0) == FALSE)
1016             {
1017 
1018                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
1019                 __leave;
1020             }
1021 
1022             // Acquire a hash object handle.
1023             if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,
1024                 &hHash) == FALSE)
1025             {
1026                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
1027                 __leave;
1028             }
1029         }
1030 
1031         // Copy hash and signedHash from Java to native buffer
1032         pHashBuffer = new (env) jbyte[jHashSize];
1033         if (pHashBuffer == NULL) {
1034             __leave;
1035         }
1036         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
1037 
1038         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
1039         if (pSignedHashBuffer == NULL) {
1040             __leave;
1041         }
1042         env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
1043             pSignedHashBuffer);
1044 
1045         // Set hash value in the hash object
1046         if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) //deprecated
1047             == FALSE)
1048         {
1049             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
1050             __leave;
1051         }
1052 
1053         // For RSA, the hash encryption algorithm is normally the same as the
1054         // public key algorithm, so AT_SIGNATURE is used.
1055 
1056         // Verify the signature
1057         if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, //deprecated
1058             dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)
1059         {
1060             result = JNI_TRUE;
1061         }
1062     }
1063 
1064     __finally
1065     {
1066         if (pSignedHashBuffer)
1067             delete [] pSignedHashBuffer;
1068 
1069         if (pHashBuffer)
1070             delete [] pHashBuffer;
1071 
1072         if (hHash)
1073             ::CryptDestroyHash(hHash); //deprecated
1074 
1075         if (hCryptProvAlt)
1076             ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
1077     }
1078 
1079     return result;
1080 }
1081 
1082 /*
1083  * Class:     sun_security_mscapi_CSignature
1084  * Method:    verifyCngSignedHash
1085  * Signature: (I[BI[BIILjava/lang/String;JJ)Z
1086  */
1087 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash
1088   (JNIEnv *env, jclass clazz, jint type,
1089         jbyteArray jHash, jint jHashSize,
1090         jbyteArray jSignedHash, jint jSignedHashSize,
1091         jint saltLen, jstring jHashAlgorithm,
1092         jlong hCryptProv, jlong hCryptKey)
1093 {
1094     jbyte* pHashBuffer = NULL;
1095     jbyte* pSignedHashBuffer = NULL;
1096     jboolean result = JNI_FALSE;
1097     NCRYPT_KEY_HANDLE hk = NULL;
1098 
1099     __try
1100     {
1101         if (hCryptKey == 0) {
1102             hk = (NCRYPT_KEY_HANDLE)hCryptProv;
1103         } else {
1104             SS_CHECK(::NCryptTranslateHandle(
1105                 NULL,
1106                 &hk,
1107                 (HCRYPTPROV)hCryptProv,
1108                 (HCRYPTKEY)hCryptKey,
1109                 NULL,
1110                 0));
1111         }
1112 
1113         // Copy hash and signedHash from Java to native buffer
1114         pHashBuffer = new (env) jbyte[jHashSize];
1115         if (pHashBuffer == NULL) {
1116             __leave;
1117         }
1118         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
1119 
1120         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
1121         if (pSignedHashBuffer == NULL) {
1122             __leave;
1123         }
1124         env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
1125             pSignedHashBuffer);
1126 
1127         VOID* param;
1128         DWORD dwFlags;
1129 
1130         switch (type) {
1131         case 0:
1132             param = NULL;
1133             dwFlags = 0;
1134             break;
1135         case 1:
1136             BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
1137             if (jHashAlgorithm) {
1138                 pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
1139                 if (pkcs1Info.pszAlgId == NULL) {
1140                     ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
1141                             "Unrecognised hash algorithm");
1142                     __leave;
1143                 }
1144             } else {
1145                 pkcs1Info.pszAlgId = NULL;
1146             }
1147             param = &pkcs1Info;
1148             dwFlags = NCRYPT_PAD_PKCS1_FLAG;
1149             break;
1150         case 2:
1151             BCRYPT_PSS_PADDING_INFO pssInfo;
1152             pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
1153             pssInfo.cbSalt = saltLen;
1154             if (pssInfo.pszAlgId == NULL) {
1155                 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
1156                         "Unrecognised hash algorithm");
1157                 __leave;
1158             }
1159             param = &pssInfo;
1160             dwFlags = NCRYPT_PAD_PSS_FLAG;
1161             break;
1162         }
1163 
1164         if (::NCryptVerifySignature(hk, param,
1165                 (BYTE *) pHashBuffer, jHashSize,
1166                 (BYTE *) pSignedHashBuffer, jSignedHashSize,
1167                 dwFlags) == ERROR_SUCCESS)
1168         {
1169             result = JNI_TRUE;
1170         }
1171     }
1172 
1173     __finally
1174     {
1175         if (pSignedHashBuffer)
1176             delete [] pSignedHashBuffer;
1177 
1178         if (pHashBuffer)
1179             delete [] pHashBuffer;
1180 
1181         if (hCryptKey != 0 && hk != NULL)
1182             ::NCryptFreeObject(hk);
1183     }
1184 
1185     return result;
1186 }
1187 
1188 #define DUMP_PROP(p) \
1189     if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
1190         sprintf(header, "%s %ls", #p, p); \
1191         dump(header, buffer, len); \
1192     }
1193 
1194 #define EXPORT_BLOB(p) \
1195     desc.cBuffers = 0; \
1196     if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
1197         sprintf(header, "%s %ls (%ld)", #p, p, desc.cBuffers); \
1198         dump(header, buffer, len); \
1199         for (int i = 0; i < (int)desc.cBuffers; i++) { \
1200             sprintf(header, "desc %ld", desc.pBuffers[i].BufferType); \
1201             dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \
1202         } \
1203     }
1204 
1205 void showProperty(NCRYPT_HANDLE hKey) {
1206     char header[100];
1207     BYTE buffer[8192];
1208     DWORD len = 9;
1209     NCryptBufferDesc desc;
1210     DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);
1211     DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);
1212     DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);
1213     DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);
1214     DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);
1215     DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);
1216     DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);
1217     DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);
1218     DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);
1219     DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);
1220     DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);
1221     DUMP_PROP(NCRYPT_LENGTH_PROPERTY);
1222     DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);
1223     DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);
1224     DUMP_PROP(NCRYPT_NAME_PROPERTY);
1225     DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);
1226     DUMP_PROP(NCRYPT_PIN_PROPERTY);
1227     DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);
1228     DUMP_PROP(NCRYPT_READER_PROPERTY);
1229     DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);
1230     DUMP_PROP(NCRYPT_SCARD_PIN_ID);
1231     DUMP_PROP(NCRYPT_SCARD_PIN_INFO);
1232     DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);
1233     DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);
1234     DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);
1235     DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);
1236     DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);
1237     DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);
1238     DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);
1239     DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);
1240     DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);
1241     DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);
1242     DUMP_PROP(NCRYPT_VERSION_PROPERTY);
1243     DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);
1244 
1245     EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);
1246     EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);
1247     EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);
1248     EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);
1249     EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);
1250     EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);
1251     EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);
1252     EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);
1253     EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);
1254     EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);
1255     EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);
1256     EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);
1257     EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);
1258     EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);
1259     EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);
1260     EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);
1261     EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);
1262     EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);
1263     EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);
1264     EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);
1265     //EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);
1266     //EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
1267     BCryptBuffer bb;
1268     bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;
1269     bb.cbBuffer = 18;
1270     bb.pvBuffer = L"changeit";
1271     BCryptBufferDesc bbd;
1272     bbd.ulVersion = 0;
1273     bbd.cBuffers = 1;
1274     bbd.pBuffers = &bb;
1275     if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,
1276             (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
1277         sprintf(header, "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
1278         dump(header, buffer, len);
1279     }
1280     EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);
1281 }
1282 
1283 /*
1284  * Class:     sun_security_mscapi_CKeyPairGenerator_RSA
1285  * Method:    generateCKeyPair
1286  * Signature: (Ljava/lang/String;ILjava/lang/String;)Lsun/security/mscapi/CKeyPair;
1287  */
1288 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair
1289   (JNIEnv *env, jclass clazz, jstring alg, jint keySize, jstring keyContainerName)
1290 {
1291     HCRYPTPROV hCryptProv = NULL;
1292     HCRYPTKEY hKeyPair;
1293     DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;
1294     jobject keypair = NULL;
1295     const char* pszKeyContainerName = NULL; // UUID
1296 
1297     __try
1298     {
1299         if ((pszKeyContainerName =
1300             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
1301             __leave;
1302         }
1303 
1304         // Acquire a CSP context (create a new key container).
1305         // Prefer a PROV_RSA_AES CSP, when available, due to its support
1306         // for SHA-2-based signatures.
1307         if (::CryptAcquireContext( //deprecated
1308             &hCryptProv,
1309             pszKeyContainerName,
1310             NULL,
1311             PROV_RSA_AES,
1312             CRYPT_NEWKEYSET) == FALSE)
1313         {
1314             // Failover to using the default CSP (PROV_RSA_FULL)
1315 
1316             if (::CryptAcquireContext( //deprecated
1317                 &hCryptProv,
1318                 pszKeyContainerName,
1319                 NULL,
1320                 PROV_RSA_FULL,
1321                 CRYPT_NEWKEYSET) == FALSE)
1322             {
1323                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1324                 __leave;
1325             }
1326         }
1327 
1328         // Generate an keypair
1329         if(::CryptGenKey( //deprecated
1330            hCryptProv,
1331            AT_KEYEXCHANGE,
1332            dwFlags,
1333            &hKeyPair) == FALSE)
1334         {
1335             ThrowException(env, KEY_EXCEPTION, GetLastError());
1336             __leave;
1337         }
1338 
1339         // Get the method ID for the CKeyPair constructor
1340         jclass clazzCKeyPair =
1341             env->FindClass("sun/security/mscapi/CKeyPair");
1342         if (clazzCKeyPair == NULL) {
1343             __leave;
1344         }
1345 
1346         jmethodID mNewCKeyPair =
1347             env->GetMethodID(clazzCKeyPair, "<init>", "(Ljava/lang/String;JJI)V");
1348         if (mNewCKeyPair == NULL) {
1349             __leave;
1350         }
1351 
1352         // Create a new keypair
1353         keypair = env->NewObject(clazzCKeyPair, mNewCKeyPair,
1354             alg, (jlong) hCryptProv, (jlong) hKeyPair, keySize);
1355 
1356     }
1357     __finally
1358     {
1359         //--------------------------------------------------------------------
1360         // Clean up.
1361 
1362         if (pszKeyContainerName)
1363             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
1364     }
1365 
1366     return keypair;
1367 }
1368 
1369 /*
1370  * Class:     sun_security_mscapi_CKey
1371  * Method:    getContainerName
1372  * Signature: (J)Ljava/lang/String;
1373  */
1374 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getContainerName
1375   (JNIEnv *env, jclass jclazz, jlong hCryptProv)
1376 {
1377     DWORD cbData = 256;
1378     BYTE pbData[256];
1379     pbData[0] = '\0';
1380 
1381     ::CryptGetProvParam( //deprecated
1382         (HCRYPTPROV)hCryptProv,
1383         PP_CONTAINER,
1384         (BYTE *)pbData,
1385         &cbData,
1386         0);
1387 
1388     return env->NewStringUTF((const char*)pbData);
1389 }
1390 
1391 /*
1392  * Class:     sun_security_mscapi_CKey
1393  * Method:    getKeyType
1394  * Signature: (J)Ljava/lang/String;
1395  */
1396 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getKeyType
1397   (JNIEnv *env, jclass jclazz, jlong hCryptKey)
1398 {
1399     ALG_ID dwAlgId;
1400     DWORD dwAlgIdLen = sizeof(ALG_ID);
1401 
1402     if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated
1403 
1404         if (CALG_RSA_SIGN == dwAlgId) {
1405             return env->NewStringUTF("Signature");
1406 
1407         } else if (CALG_RSA_KEYX == dwAlgId) {
1408             return env->NewStringUTF("Exchange");
1409 
1410         } else {
1411             char buffer[64];
1412             if (sprintf(buffer, "%lu", dwAlgId)) {
1413                 return env->NewStringUTF(buffer);
1414             }
1415         }
1416     }
1417 
1418     return env->NewStringUTF("<Unknown>");
1419 }
1420 
1421 /*
1422  * Class:     sun_security_mscapi_CKeyStore
1423  * Method:    storeCertificate
1424  * Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V
1425  */
1426 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_storeCertificate
1427   (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
1428         jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,
1429         jlong hCryptKey)
1430 {
1431     const char* pszCertStoreName = NULL;
1432     HCERTSTORE hCertStore = NULL;
1433     PCCERT_CONTEXT pCertContext = NULL;
1434     PWCHAR pszCertAliasName = NULL;
1435     jbyte* pbCertEncoding = NULL;
1436     const jchar* jCertAliasChars = NULL;
1437     const char* pszContainerName = NULL;
1438     const char* pszProviderName = NULL;
1439     WCHAR * pwszContainerName = NULL;
1440     WCHAR * pwszProviderName = NULL;
1441 
1442     __try
1443     {
1444         // Open a system certificate store.
1445         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
1446             == NULL) {
1447             __leave;
1448         }
1449         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
1450             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1451             __leave;
1452         }
1453 
1454         // Copy encoding from Java to native buffer
1455         pbCertEncoding = new (env) jbyte[jCertEncodingSize];
1456         if (pbCertEncoding == NULL) {
1457             __leave;
1458         }
1459         env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
1460 
1461         // Create a certificate context from the encoded cert
1462         if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
1463             (BYTE*) pbCertEncoding, jCertEncodingSize))) {
1464 
1465             ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
1466             __leave;
1467         }
1468 
1469         // Set the certificate's friendly name
1470         int size = env->GetStringLength(jCertAliasName);
1471         pszCertAliasName = new (env) WCHAR[size + 1];
1472         if (pszCertAliasName == NULL) {
1473             __leave;
1474         }
1475 
1476         jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
1477         if (jCertAliasChars == NULL) {
1478             __leave;
1479         }
1480         memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
1481         pszCertAliasName[size] = 0; // append the string terminator
1482 
1483         CRYPT_DATA_BLOB friendlyName = {
1484             sizeof(WCHAR) * (size + 1),
1485             (BYTE *) pszCertAliasName
1486         };
1487 
1488         env->ReleaseStringChars(jCertAliasName, jCertAliasChars);
1489 
1490         if (! ::CertSetCertificateContextProperty(pCertContext,
1491             CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {
1492 
1493             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1494             __leave;
1495         }
1496 
1497         // Attach the certificate's private key (if supplied)
1498         if (hCryptProv != 0 && hCryptKey != 0) {
1499 
1500             CRYPT_KEY_PROV_INFO keyProviderInfo;
1501             DWORD dwDataLen;
1502 
1503             // Get the name of the key container
1504             if (! ::CryptGetProvParam( //deprecated
1505                 (HCRYPTPROV) hCryptProv,
1506                 PP_CONTAINER,
1507                 NULL,
1508                 &dwDataLen,
1509                 0)) {
1510 
1511                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1512                 __leave;
1513             }
1514 
1515             pszContainerName = new (env) char[dwDataLen];
1516             if (pszContainerName == NULL) {
1517                 __leave;
1518             }
1519 
1520             if (! ::CryptGetProvParam( //deprecated
1521                 (HCRYPTPROV) hCryptProv,
1522                 PP_CONTAINER,
1523                 (BYTE *) pszContainerName,
1524                 &dwDataLen,
1525                 0)) {
1526 
1527                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1528                 __leave;
1529             }
1530 
1531             // Convert to a wide char string
1532             pwszContainerName = new (env) WCHAR[dwDataLen];
1533             if (pwszContainerName == NULL) {
1534                 __leave;
1535             }
1536 
1537             if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {
1538                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1539                 __leave;
1540             }
1541 
1542             // Set the name of the key container
1543             keyProviderInfo.pwszContainerName = pwszContainerName;
1544 
1545 
1546             // Get the name of the provider
1547             if (! ::CryptGetProvParam( //deprecated
1548                 (HCRYPTPROV) hCryptProv,
1549                 PP_NAME,
1550                 NULL,
1551                 &dwDataLen,
1552                 0)) {
1553 
1554                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1555                 __leave;
1556             }
1557 
1558             pszProviderName = new (env) char[dwDataLen];
1559             if (pszProviderName == NULL) {
1560                 __leave;
1561             }
1562 
1563             if (! ::CryptGetProvParam( //deprecated
1564                 (HCRYPTPROV) hCryptProv,
1565                 PP_NAME,
1566                 (BYTE *) pszProviderName,
1567                 &dwDataLen,
1568                 0)) {
1569 
1570                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1571                 __leave;
1572             }
1573 
1574             // Convert to a wide char string
1575             pwszProviderName = new (env) WCHAR[dwDataLen];
1576             if (pwszProviderName == NULL) {
1577                 __leave;
1578             }
1579 
1580             if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {
1581                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1582                 __leave;
1583             }
1584 
1585             // Set the name of the provider
1586             keyProviderInfo.pwszProvName = pwszProviderName;
1587 
1588             // Get and set the type of the provider
1589             if (! ::CryptGetProvParam( //deprecated
1590                 (HCRYPTPROV) hCryptProv,
1591                 PP_PROVTYPE,
1592                 (LPBYTE) &keyProviderInfo.dwProvType,
1593                 &dwDataLen,
1594                 0)) {
1595 
1596                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1597                 __leave;
1598             }
1599 
1600             // Set no provider flags
1601             keyProviderInfo.dwFlags = 0;
1602 
1603             // Set no provider parameters
1604             keyProviderInfo.cProvParam = 0;
1605             keyProviderInfo.rgProvParam = NULL;
1606 
1607             // Get the key's algorithm ID
1608             if (! ::CryptGetKeyParam( //deprecated
1609                 (HCRYPTKEY) hCryptKey,
1610                 KP_ALGID,
1611                 (LPBYTE) &keyProviderInfo.dwKeySpec,
1612                 &dwDataLen,
1613                 0)) {
1614 
1615                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1616                 __leave;
1617             }
1618             // Set the key spec (using the algorithm ID).
1619             switch (keyProviderInfo.dwKeySpec) {
1620             case CALG_RSA_KEYX:
1621             case CALG_DH_SF:
1622                 keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;
1623                 break;
1624 
1625             case CALG_RSA_SIGN:
1626             case CALG_DSS_SIGN:
1627                 keyProviderInfo.dwKeySpec = AT_SIGNATURE;
1628                 break;
1629 
1630             default:
1631                 ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);
1632                 __leave;
1633             }
1634 
1635             if (! ::CertSetCertificateContextProperty(pCertContext,
1636                 CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {
1637 
1638                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1639                 __leave;
1640             }
1641         }
1642 
1643         // Import encoded certificate
1644         if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,
1645             CERT_STORE_ADD_REPLACE_EXISTING, NULL))
1646         {
1647             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1648             __leave;
1649         }
1650 
1651     }
1652     __finally
1653     {
1654         //--------------------------------------------------------------------
1655         // Clean up.
1656 
1657         if (hCertStore)
1658             ::CertCloseStore(hCertStore, 0);
1659 
1660         if (pszCertStoreName)
1661             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
1662 
1663         if (pbCertEncoding)
1664             delete [] pbCertEncoding;
1665 
1666         if (pszCertAliasName)
1667             delete [] pszCertAliasName;
1668 
1669         if (pszContainerName)
1670             delete [] pszContainerName;
1671 
1672         if (pwszContainerName)
1673             delete [] pwszContainerName;
1674 
1675         if (pszProviderName)
1676             delete [] pszProviderName;
1677 
1678         if (pwszProviderName)
1679             delete [] pwszProviderName;
1680 
1681         if (pCertContext)
1682             ::CertFreeCertificateContext(pCertContext);
1683     }
1684 }
1685 
1686 /*
1687  * Class:     sun_security_mscapi_CKeyStore
1688  * Method:    removeCertificate
1689  * Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V
1690  */
1691 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCertificate
1692   (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
1693   jbyteArray jCertEncoding, jint jCertEncodingSize) {
1694 
1695     const char* pszCertStoreName = NULL;
1696     const char* pszCertAliasName = NULL;
1697     HCERTSTORE hCertStore = NULL;
1698     PCCERT_CONTEXT pCertContext = NULL;
1699     PCCERT_CONTEXT pTBDCertContext = NULL;
1700     jbyte* pbCertEncoding = NULL;
1701     DWORD cchNameString = 0;
1702     char* pszNameString = NULL; // certificate's friendly name
1703     BOOL bDeleteAttempted = FALSE;
1704 
1705     __try
1706     {
1707         // Open a system certificate store.
1708         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
1709             == NULL) {
1710             __leave;
1711         }
1712         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
1713             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1714             __leave;
1715         }
1716 
1717         // Copy encoding from Java to native buffer
1718         pbCertEncoding = new (env) jbyte[jCertEncodingSize];
1719         if (pbCertEncoding == NULL) {
1720             __leave;
1721         }
1722         env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
1723 
1724         // Create a certificate context from the encoded cert
1725         if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
1726             (BYTE*) pbCertEncoding, jCertEncodingSize))) {
1727 
1728             ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
1729             __leave;
1730         }
1731 
1732         // Find the certificate to be deleted
1733         if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,
1734             X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {
1735 
1736             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1737             __leave;
1738         }
1739 
1740         // Check that its friendly name matches the supplied alias
1741         if ((cchNameString = ::CertGetNameString(pTBDCertContext,
1742                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {
1743 
1744             pszNameString = new (env) char[cchNameString];
1745             if (pszNameString == NULL) {
1746                 __leave;
1747             }
1748 
1749             ::CertGetNameString(pTBDCertContext,
1750                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
1751                 cchNameString);
1752 
1753             // Compare the certificate's friendly name with supplied alias name
1754             if ((pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL))
1755                 == NULL) {
1756                 __leave;
1757             }
1758             if (strcmp(pszCertAliasName, pszNameString) == 0) {
1759 
1760                 // Only delete the certificate if the alias names matches
1761                 if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {
1762 
1763                     // pTBDCertContext is always freed by the
1764                     //  CertDeleteCertificateFromStore method
1765                     bDeleteAttempted = TRUE;
1766 
1767                     ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1768                     __leave;
1769                 }
1770             }
1771         }
1772 
1773     }
1774     __finally
1775     {
1776         //--------------------------------------------------------------------
1777         // Clean up.
1778 
1779         if (hCertStore)
1780             ::CertCloseStore(hCertStore, 0);
1781 
1782         if (pszCertStoreName)
1783             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
1784 
1785         if (pszCertAliasName)
1786             env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);
1787 
1788         if (pbCertEncoding)
1789             delete [] pbCertEncoding;
1790 
1791         if (pszNameString)
1792             delete [] pszNameString;
1793 
1794         if (pCertContext)
1795             ::CertFreeCertificateContext(pCertContext);
1796 
1797         if (bDeleteAttempted && pTBDCertContext)
1798             ::CertFreeCertificateContext(pTBDCertContext);
1799     }
1800 }
1801 
1802 /*
1803  * Class:     sun_security_mscapi_CKeyStore
1804  * Method:    destroyKeyContainer
1805  * Signature: (Ljava/lang/String;)V
1806  */
1807 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer
1808   (JNIEnv *env, jobject clazz, jstring keyContainerName)
1809 {
1810     HCRYPTPROV hCryptProv = NULL;
1811     const char* pszKeyContainerName = NULL;
1812 
1813     __try
1814     {
1815         if ((pszKeyContainerName =
1816             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
1817             __leave;
1818         }
1819 
1820         // Destroying the default key container is not permitted
1821         // (because it may contain more one keypair).
1822         if (pszKeyContainerName == NULL) {
1823 
1824             ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM);
1825             __leave;
1826         }
1827 
1828         // Acquire a CSP context (to the key container).
1829         if (::CryptAcquireContext( //deprecated
1830             &hCryptProv,
1831             pszKeyContainerName,
1832             NULL,
1833             PROV_RSA_FULL,
1834             CRYPT_DELETEKEYSET) == FALSE)
1835         {
1836             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1837             __leave;
1838         }
1839 
1840     }
1841     __finally
1842     {
1843         //--------------------------------------------------------------------
1844         // Clean up.
1845 
1846         if (pszKeyContainerName)
1847             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
1848     }
1849 }
1850 
1851 /*
1852  * Class:     sun_security_mscapi_CRSACipher
1853  * Method:    encryptDecrypt
1854  * Signature: ([BIJZ)[B
1855  */
1856 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
1857   (JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
1858    jboolean doEncrypt)
1859 {
1860     jbyteArray result = NULL;
1861     jbyte* pData = NULL;
1862     DWORD dwDataLen = jDataSize;
1863     DWORD dwBufLen = env->GetArrayLength(jData);
1864     DWORD i;
1865     BYTE tmp;
1866 
1867     __try
1868     {
1869         // Copy data from Java buffer to native buffer
1870         pData = new (env) jbyte[dwBufLen];
1871         if (pData == NULL) {
1872             __leave;
1873         }
1874         env->GetByteArrayRegion(jData, 0, dwBufLen, pData);
1875 
1876         if (doEncrypt == JNI_TRUE) {
1877             // encrypt
1878             if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1879                 &dwDataLen, dwBufLen)) {
1880 
1881                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1882                 __leave;
1883             }
1884             dwBufLen = dwDataLen;
1885 
1886             // convert from little-endian
1887             for (i = 0; i < dwBufLen / 2; i++) {
1888                 tmp = pData[i];
1889                 pData[i] = pData[dwBufLen - i -1];
1890                 pData[dwBufLen - i - 1] = tmp;
1891             }
1892         } else {
1893             // convert to little-endian
1894             for (i = 0; i < dwBufLen / 2; i++) {
1895                 tmp = pData[i];
1896                 pData[i] = pData[dwBufLen - i -1];
1897                 pData[dwBufLen - i - 1] = tmp;
1898             }
1899 
1900             // decrypt
1901             if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1902                 &dwBufLen)) {
1903 
1904                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1905                 __leave;
1906             }
1907         }
1908 
1909         // Create new byte array
1910         if ((result = env->NewByteArray(dwBufLen)) == NULL) {
1911             __leave;
1912         }
1913 
1914         // Copy data from native buffer to Java buffer
1915         env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
1916     }
1917     __finally
1918     {
1919         if (pData)
1920             delete [] pData;
1921     }
1922 
1923     return result;
1924 }
1925 
1926 /*
1927  * Class:     sun_security_mscapi_CPublicKey
1928  * Method:    getPublicKeyBlob
1929  * Signature: (JJ)[B
1930  */
1931 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob
1932     (JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {
1933 
1934     jbyteArray blob = NULL;
1935     DWORD dwBlobLen;
1936     BYTE* pbKeyBlob = NULL;
1937 
1938     __try
1939     {
1940 
1941         // Determine the size of the blob
1942         if (hCryptKey == 0) {
1943             SS_CHECK(::NCryptExportKey(
1944                 (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
1945                 NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));
1946         } else {
1947             if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
1948                 &dwBlobLen)) {
1949 
1950                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1951                 __leave;
1952             }
1953         }
1954 
1955         pbKeyBlob = new (env) BYTE[dwBlobLen];
1956         if (pbKeyBlob == NULL) {
1957             __leave;
1958         }
1959 
1960         // Generate key blob
1961         if (hCryptKey == 0) {
1962             SS_CHECK(::NCryptExportKey(
1963                 (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
1964                 NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));
1965         } else {
1966             if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
1967                 pbKeyBlob, &dwBlobLen)) {
1968 
1969                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1970                 __leave;
1971             }
1972         }
1973 
1974         // Create new byte array
1975         if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {
1976             __leave;
1977         }
1978 
1979         // Copy data from native buffer to Java buffer
1980         env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);
1981     }
1982     __finally
1983     {
1984         if (pbKeyBlob)
1985             delete [] pbKeyBlob;
1986     }
1987 
1988     return blob;
1989 }
1990 
1991 /*
1992  * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
1993  * Method:    getExponent
1994  * Signature: ([B)[B
1995  */
1996 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent
1997     (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {
1998 
1999     jbyteArray exponent = NULL;
2000     jbyte*     exponentBytes = NULL;
2001     jbyte*     keyBlob = NULL;
2002 
2003     __try {
2004 
2005         jsize length = env->GetArrayLength(jKeyBlob);
2006         jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
2007 
2008         if (length < headerLength) {
2009             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
2010             __leave;
2011         }
2012 
2013         if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
2014             __leave;
2015         }
2016 
2017         PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
2018 
2019         // Check BLOB type
2020         if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
2021             ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
2022             __leave;
2023         }
2024 
2025         RSAPUBKEY* pRsaPubKey =
2026             (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
2027 
2028         int len = sizeof(pRsaPubKey->pubexp);
2029         exponentBytes = new (env) jbyte[len];
2030         if (exponentBytes == NULL) {
2031             __leave;
2032         }
2033 
2034         // convert from little-endian while copying from blob
2035         for (int i = 0, j = len - 1; i < len; i++, j--) {
2036             exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];
2037         }
2038 
2039         if ((exponent = env->NewByteArray(len)) == NULL) {
2040             __leave;
2041         }
2042         env->SetByteArrayRegion(exponent, 0, len, exponentBytes);
2043     }
2044     __finally
2045     {
2046         if (keyBlob)
2047             env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
2048 
2049         if (exponentBytes)
2050             delete [] exponentBytes;
2051     }
2052 
2053     return exponent;
2054 }
2055 
2056 /*
2057  * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
2058  * Method:    getModulus
2059  * Signature: ([B)[B
2060  */
2061 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus
2062     (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {
2063 
2064     jbyteArray modulus = NULL;
2065     jbyte*     modulusBytes = NULL;
2066     jbyte*     keyBlob = NULL;
2067 
2068     __try {
2069 
2070         jsize length = env->GetArrayLength(jKeyBlob);
2071         jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
2072 
2073         if (length < headerLength) {
2074             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
2075             __leave;
2076         }
2077 
2078         if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
2079             __leave;
2080         }
2081 
2082         PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
2083 
2084         // Check BLOB type
2085         if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
2086             ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
2087             __leave;
2088         }
2089 
2090         RSAPUBKEY* pRsaPubKey =
2091             (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
2092 
2093         int len = pRsaPubKey->bitlen / 8;
2094         if (len < 0 || len > length - headerLength) {
2095             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");
2096             __leave;
2097         }
2098 
2099         modulusBytes = new (env) jbyte[len];
2100         if (modulusBytes == NULL) {
2101             __leave;
2102         }
2103         BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);
2104 
2105         // convert from little-endian while copying from blob
2106         for (int i = 0, j = len - 1; i < len; i++, j--) {
2107             modulusBytes[i] = pbModulus[j];
2108         }
2109 
2110         if ((modulus = env->NewByteArray(len)) == NULL) {
2111             __leave;
2112         }
2113         env->SetByteArrayRegion(modulus, 0, len, modulusBytes);
2114     }
2115     __finally
2116     {
2117         if (keyBlob)
2118             env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
2119 
2120         if (modulusBytes)
2121             delete [] modulusBytes;
2122     }
2123 
2124     return modulus;
2125 }
2126 
2127 /*
2128  * Convert an array in big-endian byte order into little-endian byte order.
2129  */
2130 int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
2131         int destinationLength) {
2132 
2133     int result = -1;
2134     jbyte* sourceBytes = NULL;
2135 
2136     __try {
2137         int sourceLength = env->GetArrayLength(source);
2138 
2139         sourceBytes = env->GetByteArrayElements(source, 0);
2140         if (sourceBytes == NULL) {
2141             __leave;
2142         }
2143 
2144         int copyLen = sourceLength;
2145         if (sourceLength > destinationLength) {
2146             // source might include an extra sign byte
2147             if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) {
2148                 copyLen--;
2149             } else {
2150                 __leave;
2151             }
2152         }
2153 
2154         // Copy bytes from the end of the source array to the beginning of the
2155         // destination array (until the destination array is full).
2156         // This ensures that the sign byte from the source array will be excluded.
2157         for (int i = 0; i < copyLen; i++) {
2158             destination[i] = sourceBytes[sourceLength - 1 - i];
2159         }
2160         if (copyLen < destinationLength) {
2161             memset(destination + copyLen, 0, destinationLength - copyLen);
2162         }
2163         result = destinationLength;
2164     } __finally {
2165         // Clean up.
2166         if (sourceBytes) {
2167             env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);
2168         }
2169     }
2170 
2171     return result;
2172 }
2173 
2174 /*
2175  * The Microsoft Base Cryptographic Provider supports public-key BLOBs
2176  * that have the following format:
2177  *
2178  *     PUBLICKEYSTRUC publickeystruc;
2179  *     RSAPUBKEY rsapubkey;
2180  *     BYTE modulus[rsapubkey.bitlen/8];
2181  *
2182  * and private-key BLOBs that have the following format:
2183  *
2184  *     PUBLICKEYSTRUC publickeystruc;
2185  *     RSAPUBKEY rsapubkey;
2186  *     BYTE modulus[rsapubkey.bitlen/8];
2187  *     BYTE prime1[rsapubkey.bitlen/16];
2188  *     BYTE prime2[rsapubkey.bitlen/16];
2189  *     BYTE exponent1[rsapubkey.bitlen/16];
2190  *     BYTE exponent2[rsapubkey.bitlen/16];
2191  *     BYTE coefficient[rsapubkey.bitlen/16];
2192  *     BYTE privateExponent[rsapubkey.bitlen/8];
2193  *
2194  * This method generates such BLOBs from the key elements supplied.
2195  */
2196 jbyteArray generateKeyBlob(
2197         JNIEnv *env,
2198         jint jKeyBitLength,
2199         jbyteArray jModulus,
2200         jbyteArray jPublicExponent,
2201         jbyteArray jPrivateExponent,
2202         jbyteArray jPrimeP,
2203         jbyteArray jPrimeQ,
2204         jbyteArray jExponentP,
2205         jbyteArray jExponentQ,
2206         jbyteArray jCrtCoefficient)
2207 {
2208     jsize jKeyByteLength = jKeyBitLength / 8;
2209     jsize jBlobLength;
2210     BOOL bGeneratePrivateKeyBlob;
2211 
2212     // Determine whether to generate a public-key or a private-key BLOB
2213     if (jPrivateExponent != NULL &&
2214         jPrimeP != NULL &&
2215         jPrimeQ != NULL &&
2216         jExponentP != NULL &&
2217         jExponentQ != NULL &&
2218         jCrtCoefficient != NULL) {
2219 
2220         bGeneratePrivateKeyBlob = TRUE;
2221         jBlobLength = sizeof(BLOBHEADER) +
2222                         sizeof(RSAPUBKEY) +
2223                         ((jKeyBitLength / 8) * 4) +
2224                         (jKeyBitLength / 16);
2225 
2226     } else {
2227         bGeneratePrivateKeyBlob = FALSE;
2228         jBlobLength = sizeof(BLOBHEADER) +
2229                         sizeof(RSAPUBKEY) +
2230                         (jKeyBitLength / 8);
2231     }
2232 
2233     jbyte* jBlobBytes = NULL;
2234     jbyte* jBlobElement;
2235     jbyteArray jBlob = NULL;
2236     jsize  jElementLength;
2237 
2238     __try {
2239         jBlobBytes = new (env) jbyte[jBlobLength];
2240         if (jBlobBytes == NULL) {
2241             __leave;
2242         }
2243 
2244         BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;
2245         if (bGeneratePrivateKeyBlob) {
2246             pBlobHeader->bType = PRIVATEKEYBLOB;  // 0x07
2247         } else {
2248             pBlobHeader->bType = PUBLICKEYBLOB;   // 0x06
2249         }
2250         pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02
2251         pBlobHeader->reserved = 0;                // 0x0000
2252         pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;    // 0x0000a400
2253 
2254         RSAPUBKEY *pRsaPubKey =
2255             (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));
2256         if (bGeneratePrivateKeyBlob) {
2257             pRsaPubKey->magic = 0x32415352;       // "RSA2"
2258         } else {
2259             pRsaPubKey->magic = 0x31415352;       // "RSA1"
2260         }
2261         pRsaPubKey->bitlen = jKeyBitLength;
2262         pRsaPubKey->pubexp = 0; // init
2263 
2264         // Sanity check
2265         jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
2266         if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
2267             ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);
2268             __leave;
2269         }
2270         // The length argument must be the smaller of jPublicExponentLength
2271         // and sizeof(pRsaPubKey->pubkey)
2272         if ((jElementLength = convertToLittleEndian(env, jPublicExponent,
2273             (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) {
2274             __leave;
2275         }
2276 
2277         // Modulus n
2278         jBlobElement =
2279             (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
2280         if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,
2281             jKeyByteLength)) < 0) {
2282             __leave;
2283         }
2284 
2285         if (bGeneratePrivateKeyBlob) {
2286             // Prime p
2287             jBlobElement += jElementLength;
2288             if ((jElementLength = convertToLittleEndian(env, jPrimeP,
2289                 jBlobElement, jKeyByteLength / 2)) < 0) {
2290                 __leave;
2291             }
2292 
2293             // Prime q
2294             jBlobElement += jElementLength;
2295             if ((jElementLength = convertToLittleEndian(env, jPrimeQ,
2296                 jBlobElement, jKeyByteLength / 2)) < 0) {
2297                 __leave;
2298             }
2299 
2300             // Prime exponent p
2301             jBlobElement += jElementLength;
2302             if ((jElementLength = convertToLittleEndian(env, jExponentP,
2303                 jBlobElement, jKeyByteLength / 2)) < 0) {
2304                 __leave;
2305             }
2306 
2307             // Prime exponent q
2308             jBlobElement += jElementLength;
2309             if ((jElementLength = convertToLittleEndian(env, jExponentQ,
2310                 jBlobElement, jKeyByteLength / 2)) < 0) {
2311                 __leave;
2312             }
2313 
2314             // CRT coefficient
2315             jBlobElement += jElementLength;
2316             if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient,
2317                 jBlobElement, jKeyByteLength / 2)) < 0) {
2318                 __leave;
2319             }
2320 
2321             // Private exponent
2322             jBlobElement += jElementLength;
2323             if ((jElementLength = convertToLittleEndian(env, jPrivateExponent,
2324                 jBlobElement, jKeyByteLength)) < 0) {
2325                 __leave;
2326             }
2327         }
2328 
2329         if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {
2330             __leave;
2331         }
2332         env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);
2333 
2334     }
2335     __finally
2336     {
2337         if (jBlobBytes)
2338             delete [] jBlobBytes;
2339     }
2340 
2341     return jBlob;
2342 }
2343 
2344 /*
2345  * Class:     sun_security_mscapi_CKeyStore
2346  * Method:    generateRSAPrivateKeyBlob
2347  * Signature: (I[B[B[B[B[B[B[B[B)[B
2348  */
2349 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob
2350     (JNIEnv *env, jobject clazz,
2351         jint jKeyBitLength,
2352         jbyteArray jModulus,
2353         jbyteArray jPublicExponent,
2354         jbyteArray jPrivateExponent,
2355         jbyteArray jPrimeP,
2356         jbyteArray jPrimeQ,
2357         jbyteArray jExponentP,
2358         jbyteArray jExponentQ,
2359         jbyteArray jCrtCoefficient)
2360 {
2361     return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
2362         jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,
2363         jCrtCoefficient);
2364 }
2365 
2366 /*
2367  * Class:     sun_security_mscapi_CSignature_RSA
2368  * Method:    generatePublicKeyBlob
2369  * Signature: (I[B[B)[B
2370  */
2371 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob
2372     (JNIEnv *env, jclass clazz,
2373         jint jKeyBitLength,
2374         jbyteArray jModulus,
2375         jbyteArray jPublicExponent)
2376 {
2377     return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
2378         NULL, NULL, NULL, NULL, NULL, NULL);
2379 }
2380 
2381 /*
2382  * Class:     sun_security_mscapi_CKeyStore
2383  * Method:    storePrivateKey
2384  * Signature: (Ljava/lang/String;[BLjava/lang/String;I)Lsun/security/mscapi/CPrivateKey;
2385  */
2386 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey
2387     (JNIEnv *env, jobject clazz, jstring alg, jbyteArray keyBlob,
2388      jstring keyContainerName, jint keySize)
2389 {
2390     HCRYPTPROV hCryptProv = NULL;
2391     HCRYPTKEY hKey = NULL;
2392     DWORD dwBlobLen;
2393     BYTE * pbKeyBlob = NULL;
2394     const char* pszKeyContainerName = NULL; // UUID
2395     jobject privateKey = NULL;
2396 
2397     __try
2398     {
2399         if ((pszKeyContainerName =
2400             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
2401             __leave;
2402         }
2403         dwBlobLen = env->GetArrayLength(keyBlob);
2404         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2405             == NULL) {
2406             __leave;
2407         }
2408 
2409         // Acquire a CSP context (create a new key container).
2410         if (::CryptAcquireContext( //deprecated
2411             &hCryptProv,
2412             pszKeyContainerName,
2413             NULL,
2414             PROV_RSA_FULL,
2415             CRYPT_NEWKEYSET) == FALSE)
2416         {
2417             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2418             __leave;
2419         }
2420 
2421         // Import the private key
2422         if (::CryptImportKey( //deprecated
2423             hCryptProv,
2424             pbKeyBlob,
2425             dwBlobLen,
2426             0,
2427             CRYPT_EXPORTABLE,
2428             &hKey) == FALSE)
2429         {
2430             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2431             __leave;
2432         }
2433 
2434         // Get the method ID for the CPrivateKey constructor
2435         jclass clazzCPrivateKey =
2436             env->FindClass("sun/security/mscapi/CPrivateKey");
2437         if (clazzCPrivateKey == NULL) {
2438             __leave;
2439         }
2440 
2441         jmethodID mNewCPrivateKey =
2442             env->GetStaticMethodID(clazzCPrivateKey, "of",
2443             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPrivateKey;");
2444         if (mNewCPrivateKey == NULL) {
2445             __leave;
2446         }
2447 
2448         // Create a new private key
2449         privateKey = env->CallStaticObjectMethod(clazzCPrivateKey, mNewCPrivateKey,
2450             alg, (jlong) hCryptProv, (jlong) hKey, keySize);
2451 
2452     }
2453     __finally
2454     {
2455         //--------------------------------------------------------------------
2456         // Clean up.
2457 
2458         if (pszKeyContainerName)
2459             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
2460 
2461         if (pbKeyBlob)
2462             env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
2463                 JNI_ABORT);
2464     }
2465 
2466     return privateKey;
2467 }
2468 
2469 /*
2470  * Class:     sun_security_mscapi_CSignature
2471  * Method:    importECPublicKey
2472  * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
2473  */
2474 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey
2475     (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
2476 {
2477     BCRYPT_ALG_HANDLE hSignAlg = NULL;
2478     NCRYPT_KEY_HANDLE       hTmpKey         = NULL;
2479     DWORD dwBlobLen;
2480     BYTE * pbKeyBlob = NULL;
2481     jobject publicKey = NULL;
2482 
2483     __try
2484     {
2485         dwBlobLen = env->GetArrayLength(keyBlob);
2486         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2487             == NULL) {
2488             __leave;
2489         }
2490         dump("NCryptImportKey", pbKeyBlob, dwBlobLen);
2491         NCRYPT_PROV_HANDLE hProv;
2492         SS_CHECK(NCryptOpenStorageProvider(
2493                 &hProv, L"Microsoft Software Key Storage Provider", 0 ));
2494         SS_CHECK(NCryptImportKey(
2495                                                     hProv,
2496                                                     NULL,
2497                                                     BCRYPT_ECCPUBLIC_BLOB,
2498                                                     NULL,
2499                                                     &hTmpKey,
2500                                                     pbKeyBlob,
2501                                                     dwBlobLen,
2502                                                     0));
2503         NCryptFreeObject( hProv );
2504         // Get the method ID for the CPublicKey constructor
2505         jclass clazzCPublicKey =
2506             env->FindClass("sun/security/mscapi/CPublicKey");
2507         if (clazzCPublicKey == NULL) {
2508             __leave;
2509         }
2510 
2511         jmethodID mNewCPublicKey =
2512             env->GetStaticMethodID(clazzCPublicKey, "of",
2513             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
2514         if (mNewCPublicKey == NULL) {
2515             __leave;
2516         }
2517 
2518         // Create a new public key
2519         publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
2520             alg, (jlong) hTmpKey, (jlong) 0, keySize);
2521     }
2522     __finally
2523     {
2524     }
2525 
2526     return publicKey;
2527 }
2528 
2529 /*
2530  * Class:     sun_security_mscapi_CSignature
2531  * Method:    importPublicKey
2532  * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
2533  */
2534 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importPublicKey
2535     (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
2536 {
2537     HCRYPTPROV hCryptProv = NULL;
2538     HCRYPTKEY hKey = NULL;
2539     DWORD dwBlobLen;
2540     BYTE * pbKeyBlob = NULL;
2541     jobject publicKey = NULL;
2542 
2543     __try
2544     {
2545         dwBlobLen = env->GetArrayLength(keyBlob);
2546         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2547             == NULL) {
2548             __leave;
2549         }
2550 
2551         // Acquire a CSP context (create a new key container).
2552         // Prefer a PROV_RSA_AES CSP, when available, due to its support
2553         // for SHA-2-based signatures.
2554         if (::CryptAcquireContext( //deprecated
2555             &hCryptProv,
2556             NULL,
2557             NULL,
2558             PROV_RSA_AES,
2559             CRYPT_VERIFYCONTEXT) == FALSE)
2560         {
2561             // Failover to using the default CSP (PROV_RSA_FULL)
2562 
2563             if (::CryptAcquireContext( //deprecated
2564                 &hCryptProv,
2565                 NULL,
2566                 NULL,
2567                 PROV_RSA_FULL,
2568                 CRYPT_VERIFYCONTEXT) == FALSE)
2569             {
2570                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2571                 __leave;
2572             }
2573         }
2574 
2575         // Import the public key
2576         if (::CryptImportKey( //deprecated
2577             hCryptProv,
2578             pbKeyBlob,
2579             dwBlobLen,
2580             0,
2581             CRYPT_EXPORTABLE,
2582             &hKey) == FALSE)
2583         {
2584             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2585             __leave;
2586         }
2587 
2588         // Get the method ID for the CPublicKey constructor
2589         jclass clazzCPublicKey =
2590             env->FindClass("sun/security/mscapi/CPublicKey");
2591         if (clazzCPublicKey == NULL) {
2592             __leave;
2593         }
2594 
2595         jmethodID mNewCPublicKey =
2596             env->GetStaticMethodID(clazzCPublicKey, "of",
2597             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
2598         if (mNewCPublicKey == NULL) {
2599             __leave;
2600         }
2601 
2602         // Create a new public key
2603         publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
2604             alg, (jlong) hCryptProv, (jlong) hKey, keySize);
2605 
2606     }
2607     __finally
2608     {
2609         //--------------------------------------------------------------------
2610         // Clean up.
2611 
2612         if (pbKeyBlob)
2613             env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
2614                 JNI_ABORT);
2615     }
2616 
2617     return publicKey;
2618 }
2619 
2620 } /* extern "C" */