/*
 * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

//=--------------------------------------------------------------------------=
// security.cpp    by Stanley Man-Kit Ho
//=--------------------------------------------------------------------------=
//

#include <jni.h>
#include "jni_util.h"
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <BaseTsd.h>
#include <wincrypt.h>
#include <stdio.h>
#include <memory>
#include "sun_security_mscapi_CKey.h"
#include "sun_security_mscapi_CKeyStore.h"
#include "sun_security_mscapi_PRNG.h"
#include "sun_security_mscapi_CRSACipher.h"
#include "sun_security_mscapi_CKeyPairGenerator_RSA.h"
#include "sun_security_mscapi_CPublicKey.h"
#include "sun_security_mscapi_CPublicKey_CRSAPublicKey.h"
#include "sun_security_mscapi_CSignature.h"
#include "sun_security_mscapi_CSignature_RSA.h"

#define OID_EKU_ANY         "2.5.29.37.0"

#define CERTIFICATE_PARSING_EXCEPTION \
                            "java/security/cert/CertificateParsingException"
#define INVALID_KEY_EXCEPTION \
                            "java/security/InvalidKeyException"
#define KEY_EXCEPTION       "java/security/KeyException"
#define KEYSTORE_EXCEPTION  "java/security/KeyStoreException"
#define PROVIDER_EXCEPTION  "java/security/ProviderException"
#define SIGNATURE_EXCEPTION "java/security/SignatureException"
#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"

#define KEYSTORE_LOCATION_CURRENTUSER  0
#define KEYSTORE_LOCATION_LOCALMACHINE 1

#define SS_CHECK(Status) \
        if (Status != ERROR_SUCCESS) { \
            ThrowException(env, SIGNATURE_EXCEPTION, Status); \
            __leave; \
        }

#define PP(fmt, ...) \
        if (trace) { \
            fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
            fprintf(stdout, fmt, ##__VA_ARGS__); \
            fprintf(stdout, "\n"); \
            fflush(stdout); \
        }

extern "C" {

char* trace = getenv("CAPI_TRACE");

/*
 * Declare library specific JNI_Onload entry if static build
 */
DEF_STATIC_JNI_OnLoad

void showProperty(NCRYPT_HANDLE hKey);

void dump(LPCSTR title, PBYTE data, DWORD len)
{
    if (trace) {
        printf("==== %s ====\n", title);
        for (DWORD i = 0; i < len; i+=16) {
            printf("%04x: ", i);
            for (int j = 0; j < 16; j++) {
                if (j == 8) {
                    printf("  ");
                }
                if (i + j < len) {
                    printf("%02X ", *(data + i + j) & 0xff);
                } else {
                    printf("   ");
                }
            }
            for (int j = 0; j < 16; j++) {
                if (i + j < len) {
                    int k = *(data + i + j) & 0xff;
                    if (k < 32 || k > 127) printf(".");
                    else printf("%c", (char)k);
                }
            }
            printf("\n");
        }
        fflush(stdout);
    }
}

/*
 * Throws an arbitrary Java exception with the given message.
 */
void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,
                               const char *szMessage)
{
    jclass exceptionClazz = env->FindClass(exceptionName);
    if (exceptionClazz != NULL) {
        env->ThrowNew(exceptionClazz, szMessage);
    }
}

void ThrowExceptionWithMessageAndErrcode(JNIEnv *env, const char *exceptionName,
                                         const char *msg, DWORD dwError) {
    char szMessage[500];
    szMessage[0] = '\0';
    char szMessage2[1024];
    szMessage2[0] = '\0';

    DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
        NULL, szMessage, sizeof(szMessage), NULL);
    if (res == 0) {
        strcpy(szMessage, "Unknown error");
    }
    snprintf(szMessage2, sizeof(szMessage2), "%s: error %lu, %s", msg, dwError, szMessage);

    ThrowExceptionWithMessage(env, exceptionName, szMessage2);
}


/*
 * Throws an arbitrary Java exception.
 * The exception message is a Windows system error message.
 */
void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)
{
    char szMessage[500];
    szMessage[0] = '\0';
    char szMessage2[1024];
    szMessage2[0] = '\0';

    DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
        NULL, szMessage, sizeof(szMessage), NULL);
    if (res == 0) {
        strcpy(szMessage, "Unknown error");
    }
    snprintf(szMessage2, sizeof(szMessage2), "error %lu, %s", dwError, szMessage);

    ThrowExceptionWithMessage(env, exceptionName, szMessage2);
}

/*
 * Overloaded 'operator new[]' variant, which will raise Java's
 * OutOfMemoryError in the case of a failure.
 */
void* operator new[](std::size_t size, JNIEnv *env)
{
    void* buf = ::operator new[](size, std::nothrow);
    if (buf == NULL) {
        ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,
                "Native memory allocation failed");
    }
    return buf;
}

/*
 * Maps the name of a hash algorithm to an algorithm identifier.
 */
ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {

    const char* pszHashAlgorithm = NULL;
    ALG_ID algId = 0;

    if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
        == NULL) {
        return algId;
    }

    if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
        (strcmp("SHA1", pszHashAlgorithm) == 0) ||
        (strcmp("SHA-1", pszHashAlgorithm) == 0)) {

        algId = CALG_SHA1;
    } else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {
        algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5
    } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
        algId = CALG_SHA_256;
    } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
        algId = CALG_SHA_384;
    } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
        algId = CALG_SHA_512;
    } else if (strcmp("MD5", pszHashAlgorithm) == 0) {
        algId = CALG_MD5;
    } else if (strcmp("MD2", pszHashAlgorithm) == 0) {
        algId = CALG_MD2;
    }

    if (pszHashAlgorithm)
        env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);

   return algId;
}

/*
 * Maps the name of a hash algorithm to a CNG Algorithm Identifier.
 */
LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {

    const char* pszHashAlgorithm = NULL;
    LPCWSTR id = NULL;

    if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
            == NULL) {
        return id;
    }

    if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
        (strcmp("SHA1", pszHashAlgorithm) == 0) ||
        (strcmp("SHA-1", pszHashAlgorithm) == 0)) {

        id = BCRYPT_SHA1_ALGORITHM;
    } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
        id = BCRYPT_SHA256_ALGORITHM;
    } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
        id = BCRYPT_SHA384_ALGORITHM;
    } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
        id = BCRYPT_SHA512_ALGORITHM;
    }

    if (pszHashAlgorithm)
        env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);

    return id;
}

/*
 * Returns a certificate chain context given a certificate context and key
 * usage identifier.
 */
bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)
{
    CERT_ENHKEY_USAGE        EnhkeyUsage;
    CERT_USAGE_MATCH         CertUsage;
    CERT_CHAIN_PARA          ChainPara;
    DWORD                    dwFlags = 0;
    LPSTR                    szUsageIdentifierArray[1];

    szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;
    EnhkeyUsage.cUsageIdentifier = 1;
    EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;
    CertUsage.dwType = USAGE_MATCH_TYPE_AND;
    CertUsage.Usage  = EnhkeyUsage;
    ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
    ChainPara.RequestedUsage=CertUsage;

    // Build a chain using CertGetCertificateChain
    // and the certificate retrieved.
    return (::CertGetCertificateChain(NULL,     // use the default chain engine
                pCertContext,   // pointer to the end certificate
                NULL,           // use the default time
                NULL,           // search no additional stores
                &ChainPara,     // use AND logic and enhanced key usage
                                //  as indicated in the ChainPara
                                //  data structure
                dwFlags,
                NULL,           // currently reserved
                ppChainContext) == TRUE);       // return a pointer to the chain created
}


/////////////////////////////////////////////////////////////////////////////
//

/*
 * Class:     sun_security_mscapi_PRNG
 * Method:    getContext
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_sun_security_mscapi_PRNG_getContext
        (JNIEnv *env, jclass clazz) {
    HCRYPTPROV hCryptProv = NULL;
    if(::CryptAcquireContext( //deprecated
       &hCryptProv,
       NULL,
       NULL,
       PROV_RSA_FULL,
       CRYPT_VERIFYCONTEXT) == FALSE)
    {
        ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
    }
    return hCryptProv;
}


/*
 * Class:     sun_security_mscapi_PRNG
 * Method:    releaseContext
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_PRNG_releaseContext
        (JNIEnv *env, jclass clazz, jlong ctxt) {
    if (ctxt) {
        ::CryptReleaseContext((HCRYPTPROV)ctxt, 0); //deprecated
    }
}


/*
 * Class:     sun_security_mscapi_PRNG
 * Method:    generateSeed
 * Signature: (JI[B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
  (JNIEnv *env, jclass clazz, jlong ctxt, jint length, jbyteArray seed)
{

    HCRYPTPROV hCryptProv = (HCRYPTPROV)ctxt;
    jbyte*     reseedBytes = NULL;
    jbyte*     seedBytes = NULL;
    jbyteArray result = NULL;

    __try
    {
        /*
         * If length is negative then use the supplied seed to re-seed the
         * generator and return null.
         * If length is non-zero then generate a new seed according to the
         * requested length and return the new seed.
         * If length is zero then overwrite the supplied seed with a new
         * seed of the same length and return the seed.
         */
        if (length < 0) {
            length = env->GetArrayLength(seed);
            if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
                __leave;
            }

            if (::CryptGenRandom( //deprecated
                hCryptProv,
                length,
                (BYTE *) reseedBytes) == FALSE) {

                ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
                __leave;
            }

            result = NULL;

        } else {

            if (length > 0) {
                seed = env->NewByteArray(length);
                if (seed == NULL) {
                    __leave;
                }
            } else {
                length = env->GetArrayLength(seed);
            }

            if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
                __leave;
            }

            if (::CryptGenRandom( //deprecated
                hCryptProv,
                length,
                (BYTE *) seedBytes) == FALSE) {

                ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
                __leave;
            }

            result = seed; // seed will be updated when seedBytes gets released
        }
    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (reseedBytes)
            env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);

        if (seedBytes)
            env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
    }

    return result;
}


/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    loadKeysOrCertificateChains
 * Signature: (Ljava/lang/String;I)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains
  (JNIEnv *env, jobject obj, jstring jCertStoreName, jint jCertStoreLocation)
{
    /**
     * Certificate in cert store has enhanced key usage extension
     * property (or EKU property) that is not part of the certificate itself. To determine
     * if the certificate should be returned, both the enhanced key usage in certificate
     * extension block and the extension property stored along with the certificate in
     * certificate store should be examined. Otherwise, we won't be able to determine
     * the proper key usage from the Java side because the information is not stored as
     * part of the encoded certificate.
     */

    const char* pszCertStoreName = NULL;
    HCERTSTORE hCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    wchar_t* pszNameString = NULL; // certificate's friendly name
    DWORD cchNameString = 0;

    __try
    {
        // Open a system certificate store.
        if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
            == NULL) {
            __leave;
        }

        if (jCertStoreLocation == KEYSTORE_LOCATION_CURRENTUSER) {
            hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName);
        }
        else if (jCertStoreLocation == KEYSTORE_LOCATION_LOCALMACHINE) {
            hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
                CERT_SYSTEM_STORE_LOCAL_MACHINE, pszCertStoreName);
        }
        else {
            PP("jCertStoreLocation is not a valid value");
            __leave;
        }

        if (hCertStore == NULL) {

            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Determine clazz and method ID to generate certificate
        jclass clazzArrayList = env->FindClass("java/util/ArrayList");
        if (clazzArrayList == NULL) {
            __leave;
        }

        jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");
        if (mNewArrayList == NULL) {
            __leave;
        }

        jclass clazzOfThis = env->GetObjectClass(obj);
        if (clazzOfThis == NULL) {
            __leave;
        }

        jmethodID mGenCert = env->GetMethodID(clazzOfThis,
                                              "generateCertificate",
                                              "([BLjava/util/Collection;)V");
        if (mGenCert == NULL) {
            __leave;
        }

        // Determine method ID to generate certificate chain
        jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,
                                                   "generateCertificateChain",
                                                   "(Ljava/lang/String;Ljava/util/Collection;)V");
        if (mGenCertChain == NULL) {
            __leave;
        }

        // Determine method ID to generate RSA certificate chain
        jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,
                                                   "generateKeyAndCertificateChain",
                                                   "(ZLjava/lang/String;JJILjava/util/Collection;)V");
        if (mGenKeyAndCertChain == NULL) {
            __leave;
        }

        // Use CertEnumCertificatesInStore to get the certificates
        // from the open store. pCertContext must be reset to
        // NULL to retrieve the first certificate in the store.
        while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
        {
            PP("--------------------------");
            // Check if private key available - client authentication certificate
            // must have private key available.
            HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv = NULL;
            DWORD dwKeySpec = 0;
            HCRYPTKEY hUserKey = NULL;
            BOOL bCallerFreeProv = FALSE;
            BOOL bHasNoPrivateKey = FALSE;
            DWORD dwPublicKeyLength = 0;

            // First, probe it silently
            if (::CryptAcquireCertificatePrivateKey(pCertContext,
                    CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,
                    &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
                && GetLastError() != NTE_SILENT_CONTEXT)
            {
                PP("bHasNoPrivateKey = TRUE!");
                bHasNoPrivateKey = TRUE;
            }
            else
            {
                if (bCallerFreeProv == TRUE) {
                    if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
                        NCryptFreeObject(hCryptProv);
                    } else {
                        ::CryptReleaseContext(hCryptProv, NULL); // deprecated
                    }
                    bCallerFreeProv = FALSE;
                }

                // Second, acquire the key normally (not silently)
                if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,
                        &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
                {
                    PP("bHasNoPrivateKey = TRUE!!");
                    bHasNoPrivateKey = TRUE;
                }
                else
                {
                    if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
                        PP("CNG %I64d", (__int64)hCryptProv);
                    } else {
                        // Private key is available
                        BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated

                        // Skip certificate if cannot find private key
                        if (bGetUserKey == FALSE) {
                            if (bCallerFreeProv)
                                ::CryptReleaseContext(hCryptProv, NULL); // deprecated
                            continue;
                        }

                        // Set cipher mode to ECB
                        DWORD dwCipherMode = CRYPT_MODE_ECB;
                        ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
                        PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);
                    }
                    // If the private key is present in smart card, we may not be able to
                    // determine the key length by using the private key handle. However,
                    // since public/private key pairs must have the same length, we could
                    // determine the key length of the private key by using the public key
                    // in the certificate.
                    dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                            &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
                }
            }
            PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;

            // Build certificate chain by using system certificate store.
            // Add cert chain into collection for any key usage.
            //
            if (GetCertificateChain((LPSTR)OID_EKU_ANY, pCertContext, &pCertChainContext))
            {
                for (DWORD i = 0; i < pCertChainContext->cChain; i++)
                {
                    // Found cert chain
                    PCERT_SIMPLE_CHAIN rgpChain =
                        pCertChainContext->rgpChain[i];

                    // Create ArrayList to store certs in each chain
                    jobject jArrayList =
                        env->NewObject(clazzArrayList, mNewArrayList);
                    if (jArrayList == NULL) {
                        __leave;
                    }

                    // Cleanup the previous allocated name
                    if (pszNameString) {
                        delete [] pszNameString;
                        pszNameString = NULL;
                    }

                    for (unsigned int j=0; j < rgpChain->cElement; j++)
                    {
                        PCERT_CHAIN_ELEMENT rgpElement =
                            rgpChain->rgpElement[j];
                        PCCERT_CONTEXT pc = rgpElement->pCertContext;

                        // Retrieve the friendly name of the first certificate
                        // in the chain
                        if (j == 0) {

                            // If the cert's name cannot be retrieved then
                            // pszNameString remains set to NULL.
                            // (An alias name will be generated automatically
                            // when storing this cert in the keystore.)

                            // Get length of friendly name
                            if ((cchNameString = CertGetNameStringW(pc,
                                CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
                                NULL, 0)) > 1) {

                                // Found friendly name
                                pszNameString = new (env) wchar_t[cchNameString];
                                if (pszNameString == NULL) {
                                    __leave;
                                }

                                CertGetNameStringW(pc,
                                    CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
                                    pszNameString, cchNameString);
                            }
                        }

                        BYTE* pbCertEncoded = pc->pbCertEncoded;
                        DWORD cbCertEncoded = pc->cbCertEncoded;

                        // Allocate and populate byte array
                        jbyteArray byteArray = env->NewByteArray(cbCertEncoded);
                        if (byteArray == NULL) {
                            __leave;
                        }
                        env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,
                            (jbyte*) pbCertEncoded);

                        // Generate certificate from byte array and store into
                        // cert collection
                        env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
                    }

                    // Usually pszNameString should be non-NULL. It's either
                    // the friendly name or an element from the subject name
                    // or SAN.
                    if (pszNameString)
                    {
                        PP("%S: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
                        jsize nameLen = (jsize)wcslen(pszNameString);
                        if (bHasNoPrivateKey)
                        {
                            // Generate certificate chain and store into cert chain
                            // collection
                            jstring name = env->NewString(pszNameString, nameLen);
                            if (name == NULL) {
                                __leave;
                            }
                            env->CallVoidMethod(obj, mGenCertChain,
                                name,
                                jArrayList);
                        }
                        else
                        {
                            if (hUserKey) {
                                // Only accept RSA for CAPI
                                DWORD dwData = CALG_RSA_KEYX;
                                DWORD dwSize = sizeof(DWORD);
                                ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
                                        &dwSize, NULL);
                                if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
                                {
                                    // Generate RSA certificate chain and store into cert
                                    // chain collection
                                    jstring name = env->NewString(pszNameString, nameLen);
                                    if (name == NULL) {
                                        __leave;
                                    }
                                    env->CallVoidMethod(obj, mGenKeyAndCertChain,
                                            1,
                                            name,
                                            (jlong) hCryptProv, (jlong) hUserKey,
                                            dwPublicKeyLength, jArrayList);
                                }
                            } else {
                                // Only accept EC for CNG
                                BYTE buffer[32];
                                DWORD len = 0;
                                if (::NCryptGetProperty(
                                        hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
                                        (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
                                    jstring name = env->NewString(pszNameString, nameLen);
                                    if (name == NULL) {
                                        __leave;
                                    }
                                    if (buffer[0] == 'E' && buffer[2] == 'C'
                                            && (dwPublicKeyLength == 256
                                                    || dwPublicKeyLength == 384
                                                    || dwPublicKeyLength == 521)) {
                                        env->CallVoidMethod(obj, mGenKeyAndCertChain,
                                            0,
                                            name,
                                            (jlong) hCryptProv, (jlong) 0,
                                            dwPublicKeyLength, jArrayList);
                                    } else if (buffer[0] == 'R' && buffer[2] == 'S'
                                            && buffer[4] == 'A') {
                                        env->CallVoidMethod(obj, mGenKeyAndCertChain,
                                            1,
                                            name,
                                            (jlong) hCryptProv, (jlong) 0,
                                            dwPublicKeyLength, jArrayList);
                                    } else {
                                        dump("Unknown NCRYPT_ALGORITHM_PROPERTY", buffer, len);
                                    }
                                }
                            }
                        }
                    }
                }

                // Free cert chain
                if (pCertChainContext)
                    ::CertFreeCertificateChain(pCertChainContext);
            } else {
                PP("GetCertificateChain failed %d", GetLastError());
            }
        }
    }
    __finally
    {
        if (hCertStore)
            ::CertCloseStore(hCertStore, 0);

        if (pszCertStoreName)
            env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);

        if (pszNameString)
            delete [] pszNameString;
    }
}


/*
 * Class:     sun_security_mscapi_CKey
 * Method:    cleanUp
 * Signature: (JJ)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp
  (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)
{
    if (hCryptKey == NULL && hCryptProv != NULL) {
        NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);
    } else {
        if (hCryptKey != NULL)
            ::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated

        if (hCryptProv != NULL)
            ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated
    }
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    signHash
 * Signature: (Z[BILjava/lang/String;JJ)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash
  (JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,
        jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,
        jlong hCryptKey)
{
    HCRYPTHASH hHash = NULL;
    jbyte* pHashBuffer = NULL;
    jbyte* pSignedHashBuffer = NULL;
    jbyteArray jSignedHash = NULL;
    HCRYPTPROV hCryptProvAlt = NULL;

    __try
    {
        // Map hash algorithm
        ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);

        // Acquire a hash object handle.
        if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) //deprecated
        {
            // Failover to using the PROV_RSA_AES CSP

            DWORD cbData = 256;
            BYTE pbData[256];
            pbData[0] = '\0';

            // Get name of the key container
            ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
                (BYTE *)pbData, &cbData, 0);

            // Acquire an alternative CSP handle
            if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
                PROV_RSA_AES, 0) == FALSE)
            {

                ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
                __leave;
            }

            // Acquire a hash object handle.
            if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, //deprecated
                &hHash) == FALSE)
            {
                ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Copy hash from Java to native buffer
        pHashBuffer = new (env) jbyte[jHashSize];
        if (pHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);

        // Set hash value in the hash object
        if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) //deprecated
        {
            ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
            __leave;
        }

        // Determine key spec.
        DWORD dwKeySpec = AT_SIGNATURE;
        ALG_ID dwAlgId;
        DWORD dwAlgIdLen = sizeof(ALG_ID);

        if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated
            ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
            __leave;

        }
        if (CALG_RSA_KEYX == dwAlgId) {
            dwKeySpec = AT_KEYEXCHANGE;
        }

        // Determine size of buffer
        DWORD dwBufLen = 0;
        DWORD dwFlags = 0;

        if (noHashOID == JNI_TRUE) {
            dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature
        }

        if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) //deprecated
        {
            ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
            __leave;
        }

        pSignedHashBuffer = new (env) jbyte[dwBufLen];
        if (pSignedHashBuffer == NULL) {
            __leave;
        }
        if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) //deprecated
        {
            ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
            __leave;
        }

        // Create new byte array
        jbyteArray temp = env->NewByteArray(dwBufLen);
        if (temp == NULL) {
            __leave;
        }

        // Copy data from native buffer
        env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);

        jSignedHash = temp;
    }
    __finally
    {
        if (pSignedHashBuffer)
            delete [] pSignedHashBuffer;

        if (pHashBuffer)
            delete [] pHashBuffer;

        if (hHash)
            ::CryptDestroyHash(hHash); //deprecated

        if (hCryptProvAlt)
            ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
    }

    return jSignedHash;
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    signCngHash
 * Signature: (I[BIILjava/lang/String;JJ)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
  (JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,
        jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
        jlong hCryptKey)
{
    jbyteArray jSignedHash = NULL;

    jbyte* pHashBuffer = NULL;
    jbyte* pSignedHashBuffer = NULL;
    NCRYPT_KEY_HANDLE hk = NULL;

    __try
    {
        if (hCryptKey == 0) {
            hk = (NCRYPT_KEY_HANDLE)hCryptProv;
        } else {
            SS_CHECK(::NCryptTranslateHandle(
                NULL,
                &hk,
                (HCRYPTPROV)hCryptProv,
                (HCRYPTKEY)hCryptKey,
                NULL,
                0));
        }

        // Copy hash from Java to native buffer
        pHashBuffer = new (env) jbyte[jHashSize];
        if (pHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);

        VOID* param;
        DWORD dwFlags;

        switch (type) {
        case 0:
            param = NULL;
            dwFlags = 0;
            break;
        case 1:
            BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
            if (jHashAlgorithm) {
                pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
                if (pkcs1Info.pszAlgId == NULL) {
                    ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
                            "Unrecognised hash algorithm");
                    __leave;
                }
            } else {
                pkcs1Info.pszAlgId = NULL;
            }
            param = &pkcs1Info;
            dwFlags = BCRYPT_PAD_PKCS1;
            break;
        case 2:
            BCRYPT_PSS_PADDING_INFO pssInfo;
            pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
            pssInfo.cbSalt = saltLen;
            if (pssInfo.pszAlgId == NULL) {
                ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
                        "Unrecognised hash algorithm");
                __leave;
            }
            param = &pssInfo;
            dwFlags = BCRYPT_PAD_PSS;
            break;
        }

        DWORD jSignedHashSize = 0;
        SS_CHECK(::NCryptSignHash(
                hk,
                param,
                (BYTE*)pHashBuffer, jHashSize,
                NULL, 0, &jSignedHashSize,
                dwFlags
                ));

        pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
        if (pSignedHashBuffer == NULL) {
            __leave;
        }

        SS_CHECK(::NCryptSignHash(
                hk,
                param,
                (BYTE*)pHashBuffer, jHashSize,
                (BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,
                dwFlags
                ));

        // Create new byte array
        jbyteArray temp = env->NewByteArray(jSignedHashSize);
        if (temp == NULL) {
            __leave;
        }

        // Copy data from native buffer
        env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);

        jSignedHash = temp;
    }
    __finally
    {
        if (pSignedHashBuffer)
            delete [] pSignedHashBuffer;

        if (pHashBuffer)
            delete [] pHashBuffer;

        if (hCryptKey != 0 && hk != NULL)
            ::NCryptFreeObject(hk);
    }

    return jSignedHash;
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    verifySignedHash
 * Signature: ([BIL/java/lang/String;[BIJJ)Z
 */
JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash
  (JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,
        jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,
        jlong hCryptProv, jlong hCryptKey)
{
    HCRYPTHASH hHash = NULL;
    jbyte* pHashBuffer = NULL;
    jbyte* pSignedHashBuffer = NULL;
    DWORD dwSignedHashBufferLen = jSignedHashSize;
    jboolean result = JNI_FALSE;
    HCRYPTPROV hCryptProvAlt = NULL;

    __try
    {
        // Map hash algorithm
        ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);

        // Acquire a hash object handle.
        if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)
            == FALSE)
        {
            // Failover to using the PROV_RSA_AES CSP

            DWORD cbData = 256;
            BYTE pbData[256];
            pbData[0] = '\0';

            // Get name of the key container
            ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
                (BYTE *)pbData, &cbData, 0);

            // Acquire an alternative CSP handle
            if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
                PROV_RSA_AES, 0) == FALSE)
            {

                ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
                __leave;
            }

            // Acquire a hash object handle.
            if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,
                &hHash) == FALSE)
            {
                ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Copy hash and signedHash from Java to native buffer
        pHashBuffer = new (env) jbyte[jHashSize];
        if (pHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);

        pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
        if (pSignedHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
            pSignedHashBuffer);

        // Set hash value in the hash object
        if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) //deprecated
            == FALSE)
        {
            ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
            __leave;
        }

        // For RSA, the hash encryption algorithm is normally the same as the
        // public key algorithm, so AT_SIGNATURE is used.

        // Verify the signature
        if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, //deprecated
            dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)
        {
            result = JNI_TRUE;
        }
    }

    __finally
    {
        if (pSignedHashBuffer)
            delete [] pSignedHashBuffer;

        if (pHashBuffer)
            delete [] pHashBuffer;

        if (hHash)
            ::CryptDestroyHash(hHash); //deprecated

        if (hCryptProvAlt)
            ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
    }

    return result;
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    verifyCngSignedHash
 * Signature: (I[BI[BIILjava/lang/String;JJ)Z
 */
JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash
  (JNIEnv *env, jclass clazz, jint type,
        jbyteArray jHash, jint jHashSize,
        jbyteArray jSignedHash, jint jSignedHashSize,
        jint saltLen, jstring jHashAlgorithm,
        jlong hCryptProv, jlong hCryptKey)
{
    jbyte* pHashBuffer = NULL;
    jbyte* pSignedHashBuffer = NULL;
    jboolean result = JNI_FALSE;
    NCRYPT_KEY_HANDLE hk = NULL;

    __try
    {
        if (hCryptKey == 0) {
            hk = (NCRYPT_KEY_HANDLE)hCryptProv;
        } else {
            SS_CHECK(::NCryptTranslateHandle(
                NULL,
                &hk,
                (HCRYPTPROV)hCryptProv,
                (HCRYPTKEY)hCryptKey,
                NULL,
                0));
        }

        // Copy hash and signedHash from Java to native buffer
        pHashBuffer = new (env) jbyte[jHashSize];
        if (pHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);

        pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
        if (pSignedHashBuffer == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
            pSignedHashBuffer);

        VOID* param;
        DWORD dwFlags;

        switch (type) {
        case 0:
            param = NULL;
            dwFlags = 0;
            break;
        case 1:
            BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
            if (jHashAlgorithm) {
                pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
                if (pkcs1Info.pszAlgId == NULL) {
                    ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
                            "Unrecognised hash algorithm");
                    __leave;
                }
            } else {
                pkcs1Info.pszAlgId = NULL;
            }
            param = &pkcs1Info;
            dwFlags = NCRYPT_PAD_PKCS1_FLAG;
            break;
        case 2:
            BCRYPT_PSS_PADDING_INFO pssInfo;
            pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
            pssInfo.cbSalt = saltLen;
            if (pssInfo.pszAlgId == NULL) {
                ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
                        "Unrecognised hash algorithm");
                __leave;
            }
            param = &pssInfo;
            dwFlags = NCRYPT_PAD_PSS_FLAG;
            break;
        }

        if (::NCryptVerifySignature(hk, param,
                (BYTE *) pHashBuffer, jHashSize,
                (BYTE *) pSignedHashBuffer, jSignedHashSize,
                dwFlags) == ERROR_SUCCESS)
        {
            result = JNI_TRUE;
        }
    }

    __finally
    {
        if (pSignedHashBuffer)
            delete [] pSignedHashBuffer;

        if (pHashBuffer)
            delete [] pHashBuffer;

        if (hCryptKey != 0 && hk != NULL)
            ::NCryptFreeObject(hk);
    }

    return result;
}

#define DUMP_PROP(p) \
    if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
        snprintf(header, sizeof(header), "%s %ls", #p, p); \
        dump(header, buffer, len); \
    }

#define EXPORT_BLOB(p) \
    desc.cBuffers = 0; \
    if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
        snprintf(header, sizeof(header), "%s %ls (%ld)", #p, p, desc.cBuffers); \
        dump(header, buffer, len); \
        for (int i = 0; i < (int)desc.cBuffers; i++) { \
            snprintf(header, sizeof(header), "desc %ld", desc.pBuffers[i].BufferType); \
            dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \
        } \
    }

void showProperty(NCRYPT_HANDLE hKey) {
    char header[100];
    BYTE buffer[8192];
    DWORD len = 9;
    NCryptBufferDesc desc;
    DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);
    DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);
    DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);
    DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);
    DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);
    DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);
    DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);
    DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);
    DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);
    DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);
    DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);
    DUMP_PROP(NCRYPT_LENGTH_PROPERTY);
    DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);
    DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);
    DUMP_PROP(NCRYPT_NAME_PROPERTY);
    DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);
    DUMP_PROP(NCRYPT_PIN_PROPERTY);
    DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);
    DUMP_PROP(NCRYPT_READER_PROPERTY);
    DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);
    DUMP_PROP(NCRYPT_SCARD_PIN_ID);
    DUMP_PROP(NCRYPT_SCARD_PIN_INFO);
    DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);
    DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);
    DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);
    DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);
    DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);
    DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);
    DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);
    DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);
    DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);
    DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);
    DUMP_PROP(NCRYPT_VERSION_PROPERTY);
    DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);

    EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);
    EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);
    EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);
    EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);
    EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);
    EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);
    EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);
    EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);
    EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);
    EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);
    EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);
    EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);
    EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);
    EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);
    EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);
    EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);
    EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);
    EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);
    EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);
    EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);
    //EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);
    //EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
    BCryptBuffer bb;
    bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;
    bb.cbBuffer = 18;
    bb.pvBuffer = (LPWSTR)L"changeit";
    BCryptBufferDesc bbd;
    bbd.ulVersion = 0;
    bbd.cBuffers = 1;
    bbd.pBuffers = &bb;
    if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,
            (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
        snprintf(header, sizeof(header), "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
        dump(header, buffer, len);
    }
    EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);
}

/*
 * Class:     sun_security_mscapi_CKeyPairGenerator_RSA
 * Method:    generateCKeyPair
 * Signature: (Ljava/lang/String;ILjava/lang/String;)Lsun/security/mscapi/CKeyPair;
 */
JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair
  (JNIEnv *env, jclass clazz, jstring alg, jint keySize, jstring keyContainerName)
{
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTKEY hKeyPair;
    DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;
    jobject keypair = NULL;
    const char* pszKeyContainerName = NULL; // UUID

    __try
    {
        if ((pszKeyContainerName =
            env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
            __leave;
        }

        // Acquire a CSP context (create a new key container).
        // Prefer a PROV_RSA_AES CSP, when available, due to its support
        // for SHA-2-based signatures.
        if (::CryptAcquireContext( //deprecated
            &hCryptProv,
            pszKeyContainerName,
            NULL,
            PROV_RSA_AES,
            CRYPT_NEWKEYSET) == FALSE)
        {
            // Failover to using the default CSP (PROV_RSA_FULL)

            if (::CryptAcquireContext( //deprecated
                &hCryptProv,
                pszKeyContainerName,
                NULL,
                PROV_RSA_FULL,
                CRYPT_NEWKEYSET) == FALSE)
            {
                ThrowException(env, KEY_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Generate an keypair
        if(::CryptGenKey( //deprecated
           hCryptProv,
           AT_KEYEXCHANGE,
           dwFlags,
           &hKeyPair) == FALSE)
        {
            ThrowException(env, KEY_EXCEPTION, GetLastError());
            __leave;
        }

        // Get the method ID for the CKeyPair constructor
        jclass clazzCKeyPair =
            env->FindClass("sun/security/mscapi/CKeyPair");
        if (clazzCKeyPair == NULL) {
            __leave;
        }

        jmethodID mNewCKeyPair =
            env->GetMethodID(clazzCKeyPair, "<init>", "(Ljava/lang/String;JJI)V");
        if (mNewCKeyPair == NULL) {
            __leave;
        }

        // Create a new keypair
        keypair = env->NewObject(clazzCKeyPair, mNewCKeyPair,
            alg, (jlong) hCryptProv, (jlong) hKeyPair, keySize);

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (pszKeyContainerName)
            env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
    }

    return keypair;
}

/*
 * Class:     sun_security_mscapi_CKey
 * Method:    getContainerName
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getContainerName
  (JNIEnv *env, jclass jclazz, jlong hCryptProv)
{
    DWORD cbData = 256;
    BYTE pbData[256];
    pbData[0] = '\0';

    ::CryptGetProvParam( //deprecated
        (HCRYPTPROV)hCryptProv,
        PP_CONTAINER,
        (BYTE *)pbData,
        &cbData,
        0);

    return env->NewStringUTF((const char*)pbData);
}

/*
 * Class:     sun_security_mscapi_CKey
 * Method:    getKeyType
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getKeyType
  (JNIEnv *env, jclass jclazz, jlong hCryptKey)
{
    ALG_ID dwAlgId;
    DWORD dwAlgIdLen = sizeof(ALG_ID);

    if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated

        if (CALG_RSA_SIGN == dwAlgId) {
            return env->NewStringUTF("Signature");

        } else if (CALG_RSA_KEYX == dwAlgId) {
            return env->NewStringUTF("Exchange");

        } else {
            char buffer[64];
            if (snprintf(buffer, sizeof(buffer), "%lu", dwAlgId)) {
                return env->NewStringUTF(buffer);
            }
        }
    }

    return env->NewStringUTF("<Unknown>");
}

/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    storeCertificate
 * Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_storeCertificate
  (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
        jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,
        jlong hCryptKey)
{
    const char* pszCertStoreName = NULL;
    HCERTSTORE hCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    PWCHAR pszCertAliasName = NULL;
    jbyte* pbCertEncoding = NULL;
    const jchar* jCertAliasChars = NULL;
    const char* pszContainerName = NULL;
    const char* pszProviderName = NULL;
    WCHAR * pwszContainerName = NULL;
    WCHAR * pwszProviderName = NULL;

    __try
    {
        // Open a system certificate store.
        if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
            == NULL) {
            __leave;
        }
        if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Copy encoding from Java to native buffer
        pbCertEncoding = new (env) jbyte[jCertEncodingSize];
        if (pbCertEncoding == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);

        // Create a certificate context from the encoded cert
        if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
            (BYTE*) pbCertEncoding, jCertEncodingSize))) {

            ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
            __leave;
        }

        // Set the certificate's friendly name
        int size = env->GetStringLength(jCertAliasName);
        pszCertAliasName = new (env) WCHAR[size + 1];
        if (pszCertAliasName == NULL) {
            __leave;
        }

        jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
        if (jCertAliasChars == NULL) {
            __leave;
        }
        memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
        pszCertAliasName[size] = 0; // append the string terminator

        CRYPT_DATA_BLOB friendlyName = {
            sizeof(WCHAR) * (size + 1),
            (BYTE *) pszCertAliasName
        };

        env->ReleaseStringChars(jCertAliasName, jCertAliasChars);

        if (! ::CertSetCertificateContextProperty(pCertContext,
            CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {

            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Attach the certificate's private key (if supplied)
        if (hCryptProv != 0 && hCryptKey != 0) {

            CRYPT_KEY_PROV_INFO keyProviderInfo;
            DWORD dwDataLen;

            // Get the name of the key container
            if (! ::CryptGetProvParam( //deprecated
                (HCRYPTPROV) hCryptProv,
                PP_CONTAINER,
                NULL,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            pszContainerName = new (env) char[dwDataLen];
            if (pszContainerName == NULL) {
                __leave;
            }

            if (! ::CryptGetProvParam( //deprecated
                (HCRYPTPROV) hCryptProv,
                PP_CONTAINER,
                (BYTE *) pszContainerName,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            // Convert to a wide char string
            pwszContainerName = new (env) WCHAR[dwDataLen];
            if (pwszContainerName == NULL) {
                __leave;
            }

            if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {
                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            // Set the name of the key container
            keyProviderInfo.pwszContainerName = pwszContainerName;


            // Get the name of the provider
            if (! ::CryptGetProvParam( //deprecated
                (HCRYPTPROV) hCryptProv,
                PP_NAME,
                NULL,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            pszProviderName = new (env) char[dwDataLen];
            if (pszProviderName == NULL) {
                __leave;
            }

            if (! ::CryptGetProvParam( //deprecated
                (HCRYPTPROV) hCryptProv,
                PP_NAME,
                (BYTE *) pszProviderName,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            // Convert to a wide char string
            pwszProviderName = new (env) WCHAR[dwDataLen];
            if (pwszProviderName == NULL) {
                __leave;
            }

            if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {
                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            // Set the name of the provider
            keyProviderInfo.pwszProvName = pwszProviderName;

            // Get and set the type of the provider
            if (! ::CryptGetProvParam( //deprecated
                (HCRYPTPROV) hCryptProv,
                PP_PROVTYPE,
                (LPBYTE) &keyProviderInfo.dwProvType,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }

            // Set no provider flags
            keyProviderInfo.dwFlags = 0;

            // Set no provider parameters
            keyProviderInfo.cProvParam = 0;
            keyProviderInfo.rgProvParam = NULL;

            // Get the key's algorithm ID
            if (! ::CryptGetKeyParam( //deprecated
                (HCRYPTKEY) hCryptKey,
                KP_ALGID,
                (LPBYTE) &keyProviderInfo.dwKeySpec,
                &dwDataLen,
                0)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }
            // Set the key spec (using the algorithm ID).
            switch (keyProviderInfo.dwKeySpec) {
            case CALG_RSA_KEYX:
            case CALG_DH_SF:
                keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;
                break;

            case CALG_RSA_SIGN:
            case CALG_DSS_SIGN:
                keyProviderInfo.dwKeySpec = AT_SIGNATURE;
                break;

            default:
                ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);
                __leave;
            }

            if (! ::CertSetCertificateContextProperty(pCertContext,
                CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {

                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Import encoded certificate
        if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,
            CERT_STORE_ADD_REPLACE_EXISTING, NULL))
        {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (hCertStore)
            ::CertCloseStore(hCertStore, 0);

        if (pszCertStoreName)
            env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);

        if (pbCertEncoding)
            delete [] pbCertEncoding;

        if (pszCertAliasName)
            delete [] pszCertAliasName;

        if (pszContainerName)
            delete [] pszContainerName;

        if (pwszContainerName)
            delete [] pwszContainerName;

        if (pszProviderName)
            delete [] pszProviderName;

        if (pwszProviderName)
            delete [] pwszProviderName;

        if (pCertContext)
            ::CertFreeCertificateContext(pCertContext);
    }
}

/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    removeCertificate
 * Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCertificate
  (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
  jbyteArray jCertEncoding, jint jCertEncodingSize) {

    const char* pszCertStoreName = NULL;
    const wchar_t* pszCertAliasName = NULL;
    HCERTSTORE hCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    PCCERT_CONTEXT pTBDCertContext = NULL;
    jbyte* pbCertEncoding = NULL;
    DWORD cchNameString = 0;
    wchar_t* pszNameString = NULL; // certificate's friendly name
    BOOL bDeleteAttempted = FALSE;

    __try
    {
        // Open a system certificate store.
        if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
            == NULL) {
            __leave;
        }
        if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Copy encoding from Java to native buffer
        pbCertEncoding = new (env) jbyte[jCertEncodingSize];
        if (pbCertEncoding == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);

        // Create a certificate context from the encoded cert
        if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
            (BYTE*) pbCertEncoding, jCertEncodingSize))) {

            ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
            __leave;
        }

        // Find the certificate to be deleted
        if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,
            X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {

            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Check that its friendly name matches the supplied alias
        if ((cchNameString = ::CertGetNameStringW(pTBDCertContext,
                CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {

            pszNameString = new (env) wchar_t[cchNameString];
            if (pszNameString == NULL) {
                __leave;
            }

            ::CertGetNameStringW(pTBDCertContext,
                CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
                cchNameString);

            // Compare the certificate's friendly name with supplied alias name
            if ((pszCertAliasName = env->GetStringChars(jCertAliasName, NULL))
                == NULL) {
                __leave;
            }
            if (wcscmp(pszCertAliasName, pszNameString) == 0) {

                // Only delete the certificate if the alias names matches
                if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {

                    // pTBDCertContext is always freed by the
                    //  CertDeleteCertificateFromStore method
                    bDeleteAttempted = TRUE;

                    ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                    __leave;
                }
            }
        }

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (hCertStore)
            ::CertCloseStore(hCertStore, 0);

        if (pszCertStoreName)
            env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);

        if (pszCertAliasName)
            env->ReleaseStringChars(jCertAliasName, pszCertAliasName);

        if (pbCertEncoding)
            delete [] pbCertEncoding;

        if (pszNameString)
            delete [] pszNameString;

        if (pCertContext)
            ::CertFreeCertificateContext(pCertContext);

        if (bDeleteAttempted && pTBDCertContext)
            ::CertFreeCertificateContext(pTBDCertContext);
    }
}

JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCngKey
  (JNIEnv *env, jobject clazz, jlong k)
{
    SECURITY_STATUS ss;
    ss = ::NCryptDeleteKey((NCRYPT_KEY_HANDLE)k, 0);
    if (ss != ERROR_SUCCESS) {
        ThrowException(env, KEY_EXCEPTION, ss);
    }
}

/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    destroyKeyContainer
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer
  (JNIEnv *env, jobject clazz, jstring keyContainerName)
{
    HCRYPTPROV hCryptProv = NULL;
    const char* pszKeyContainerName = NULL;

    __try
    {
        if ((pszKeyContainerName =
            env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
            __leave;
        }

        // Destroying the default key container is not permitted
        // (because it may contain more one keypair).
        if (pszKeyContainerName == NULL) {
            ThrowExceptionWithMessage(env, KEYSTORE_EXCEPTION, "key container name was NULL, NTE_BAD_KEYSET_PARAM");
            __leave;
        }

        // Acquire a CSP context (to the key container).
        if (::CryptAcquireContext( //deprecated
            &hCryptProv,
            pszKeyContainerName,
            NULL,
            PROV_RSA_FULL,
            CRYPT_DELETEKEYSET) == FALSE)
        {
            ThrowExceptionWithMessageAndErrcode(env, KEYSTORE_EXCEPTION, "CryptAcquireContext failure", GetLastError());
            __leave;
        }

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (pszKeyContainerName)
            env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
    }
}

/*
 * Class:     sun_security_mscapi_CRSACipher
 * Method:    encryptDecrypt
 * Signature: ([I[BIJZ)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
  (JNIEnv *env, jclass clazz, jintArray jResultStatus, jbyteArray jData, jint jDataSize, jlong hKey,
   jboolean doEncrypt)
{
    jbyteArray result = NULL;
    jbyte* pData = NULL;
    jbyte* resultData = NULL;
    DWORD dwDataLen = jDataSize;
    DWORD dwBufLen = env->GetArrayLength(jData);
    DWORD i;
    BYTE tmp;
    BOOL success;
    DWORD ss = ERROR_SUCCESS;
    DWORD lastError = ERROR_SUCCESS;
    DWORD resultLen = 0;
    DWORD pmsLen = 48;
    jbyte pmsArr[48] = {0};

    __try
    {
        // Copy data from Java buffer to native buffer
        pData = new (env) jbyte[dwBufLen];
        if (pData == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jData, 0, dwBufLen, pData);

        if (doEncrypt == JNI_TRUE) {
            // encrypt
            if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
                &dwDataLen, dwBufLen)) {

                ThrowException(env, KEY_EXCEPTION, GetLastError());
                __leave;
            }
            dwBufLen = dwDataLen;

            // convert from little-endian
            for (i = 0; i < dwBufLen / 2; i++) {
                tmp = pData[i];
                pData[i] = pData[dwBufLen - i -1];
                pData[dwBufLen - i - 1] = tmp;
            }
            resultData = pData;
            resultLen = dwBufLen;
        } else {
            // convert to little-endian
            for (i = 0; i < dwBufLen / 2; i++) {
                tmp = pData[i];
                pData[i] = pData[dwBufLen - i -1];
                pData[dwBufLen - i - 1] = tmp;
            }

            // decrypt
            success = ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
                &dwBufLen);
            lastError = GetLastError();
            if (success) {
                ss = ERROR_SUCCESS;
                resultData = pData;
                resultLen = dwBufLen;
            } else {
                ss = lastError;
                resultData = pmsArr;
                resultLen = pmsLen;
            }
            env->SetIntArrayRegion(jResultStatus, 0, 1, (jint*) &ss);
        }

            // Create new byte array
        if ((result = env->NewByteArray(resultLen)) == NULL) {
            __leave;
        }

        // Copy data from native buffer to Java buffer
        env->SetByteArrayRegion(result, 0, resultLen, (jbyte*) resultData);
    }
    __finally
    {
        if (pData)
            delete [] pData;
    }

    return result;
}

/*
 * Class:     sun_security_mscapi_CRSACipher
 * Method:    cngEncryptDecrypt
 * Signature: ([I[BIJZ)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_cngEncryptDecrypt
  (JNIEnv *env, jclass clazz, jintArray jResultStatus, jbyteArray jData, jint jDataSize, jlong hKey,
   jboolean doEncrypt)
{
    SECURITY_STATUS ss;
    jbyteArray result = NULL;
    jbyte* pData = NULL;
    jbyte* resultData = NULL;
    DWORD dwDataLen = jDataSize;
    DWORD dwBufLen = env->GetArrayLength(jData);
    DWORD resultLen = 0;
    DWORD pmsLen = 48;
    jbyte pmsArr[48] = {0};

    __try
    {
        // Copy data from Java buffer to native buffer
        pData = new (env) jbyte[dwBufLen];
        if (pData == NULL) {
            __leave;
        }
        env->GetByteArrayRegion(jData, 0, dwBufLen, pData);

        if (doEncrypt == JNI_TRUE) {
            // encrypt
            ss = ::NCryptEncrypt((NCRYPT_KEY_HANDLE) hKey,
                    (PBYTE)pData, dwDataLen,
                    0,
                    (PBYTE)pData, dwBufLen,
                    &dwBufLen, NCRYPT_PAD_PKCS1_FLAG);
            if (ss != ERROR_SUCCESS) {
                ThrowException(env, KEY_EXCEPTION, ss);
                __leave;
            } else {
                resultLen = dwBufLen;
                resultData = pData;
            }
        } else {
            // decrypt
            ss = ::NCryptDecrypt((NCRYPT_KEY_HANDLE) hKey,
                    (PBYTE)pData, dwDataLen,
                    0,
                    (PBYTE)pData, dwBufLen,
                    &dwBufLen, NCRYPT_PAD_PKCS1_FLAG);
            env->SetIntArrayRegion(jResultStatus, 0, 1, (jint*) &ss);
            if (ss == ERROR_SUCCESS) {
                resultLen = dwBufLen;
                resultData = pData;
            } else {
                resultLen = pmsLen;
                resultData = pmsArr;
            }
       }
        // Create new byte array
        if ((result = env->NewByteArray(resultLen)) == NULL) {
            __leave;
        }

        // Copy data from native buffer to Java buffer
        env->SetByteArrayRegion(result, 0, resultLen, (jbyte*) resultData);
    }
    __finally {
        if (pData) {
            delete [] pData;
        }
    }

    return result;
}

/*
 * Class:     sun_security_mscapi_CPublicKey
 * Method:    getPublicKeyBlob
 * Signature: (JJ)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob
    (JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {

    jbyteArray blob = NULL;
    DWORD dwBlobLen;
    BYTE* pbKeyBlob = NULL;

    __try
    {

        // Determine the size of the blob
        if (hCryptKey == 0) {
            SS_CHECK(::NCryptExportKey(
                (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
                NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));
        } else {
            if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
                &dwBlobLen)) {

                ThrowException(env, KEY_EXCEPTION, GetLastError());
                __leave;
            }
        }

        pbKeyBlob = new (env) BYTE[dwBlobLen];
        if (pbKeyBlob == NULL) {
            __leave;
        }

        // Generate key blob
        if (hCryptKey == 0) {
            SS_CHECK(::NCryptExportKey(
                (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
                NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));
        } else {
            if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
                pbKeyBlob, &dwBlobLen)) {

                ThrowException(env, KEY_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Create new byte array
        if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {
            __leave;
        }

        // Copy data from native buffer to Java buffer
        env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);
    }
    __finally
    {
        if (pbKeyBlob)
            delete [] pbKeyBlob;
    }

    return blob;
}

/*
 * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
 * Method:    getExponent
 * Signature: ([B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent
    (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {

    jbyteArray exponent = NULL;
    jbyte*     exponentBytes = NULL;
    jbyte*     keyBlob = NULL;

    __try {

        jsize length = env->GetArrayLength(jKeyBlob);
        jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);

        if (length < headerLength) {
            ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
            __leave;
        }

        if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
            __leave;
        }

        PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;

        // Check BLOB type
        if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
            ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
            __leave;
        }

        RSAPUBKEY* pRsaPubKey =
            (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));

        int len = sizeof(pRsaPubKey->pubexp);
        exponentBytes = new (env) jbyte[len];
        if (exponentBytes == NULL) {
            __leave;
        }

        // convert from little-endian while copying from blob
        for (int i = 0, j = len - 1; i < len; i++, j--) {
            exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];
        }

        if ((exponent = env->NewByteArray(len)) == NULL) {
            __leave;
        }
        env->SetByteArrayRegion(exponent, 0, len, exponentBytes);
    }
    __finally
    {
        if (keyBlob)
            env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);

        if (exponentBytes)
            delete [] exponentBytes;
    }

    return exponent;
}

/*
 * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
 * Method:    getModulus
 * Signature: ([B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus
    (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {

    jbyteArray modulus = NULL;
    jbyte*     modulusBytes = NULL;
    jbyte*     keyBlob = NULL;

    __try {

        jsize length = env->GetArrayLength(jKeyBlob);
        jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);

        if (length < headerLength) {
            ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
            __leave;
        }

        if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
            __leave;
        }

        PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;

        // Check BLOB type
        if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
            ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
            __leave;
        }

        RSAPUBKEY* pRsaPubKey =
            (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));

        int len = pRsaPubKey->bitlen / 8;
        if (len < 0 || len > length - headerLength) {
            ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");
            __leave;
        }

        modulusBytes = new (env) jbyte[len];
        if (modulusBytes == NULL) {
            __leave;
        }
        BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);

        // convert from little-endian while copying from blob
        for (int i = 0, j = len - 1; i < len; i++, j--) {
            modulusBytes[i] = pbModulus[j];
        }

        if ((modulus = env->NewByteArray(len)) == NULL) {
            __leave;
        }
        env->SetByteArrayRegion(modulus, 0, len, modulusBytes);
    }
    __finally
    {
        if (keyBlob)
            env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);

        if (modulusBytes)
            delete [] modulusBytes;
    }

    return modulus;
}

/*
 * Convert an array in big-endian byte order into little-endian byte order.
 */
int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
        int destinationLength) {

    int result = -1;
    jbyte* sourceBytes = NULL;

    __try {
        int sourceLength = env->GetArrayLength(source);

        sourceBytes = env->GetByteArrayElements(source, 0);
        if (sourceBytes == NULL) {
            __leave;
        }

        int copyLen = sourceLength;
        if (sourceLength > destinationLength) {
            // source might include an extra sign byte
            if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) {
                copyLen--;
            } else {
                __leave;
            }
        }

        // Copy bytes from the end of the source array to the beginning of the
        // destination array (until the destination array is full).
        // This ensures that the sign byte from the source array will be excluded.
        for (int i = 0; i < copyLen; i++) {
            destination[i] = sourceBytes[sourceLength - 1 - i];
        }
        if (copyLen < destinationLength) {
            memset(destination + copyLen, 0, destinationLength - copyLen);
        }
        result = destinationLength;
    } __finally {
        // Clean up.
        if (sourceBytes) {
            env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);
        }
    }

    return result;
}

/*
 * The Microsoft Base Cryptographic Provider supports public-key BLOBs
 * that have the following format:
 *
 *     PUBLICKEYSTRUC publickeystruc;
 *     RSAPUBKEY rsapubkey;
 *     BYTE modulus[rsapubkey.bitlen/8];
 *
 * and private-key BLOBs that have the following format:
 *
 *     PUBLICKEYSTRUC publickeystruc;
 *     RSAPUBKEY rsapubkey;
 *     BYTE modulus[rsapubkey.bitlen/8];
 *     BYTE prime1[rsapubkey.bitlen/16];
 *     BYTE prime2[rsapubkey.bitlen/16];
 *     BYTE exponent1[rsapubkey.bitlen/16];
 *     BYTE exponent2[rsapubkey.bitlen/16];
 *     BYTE coefficient[rsapubkey.bitlen/16];
 *     BYTE privateExponent[rsapubkey.bitlen/8];
 *
 * This method generates such BLOBs from the key elements supplied.
 */
jbyteArray generateKeyBlob(
        JNIEnv *env,
        jint jKeyBitLength,
        jbyteArray jModulus,
        jbyteArray jPublicExponent,
        jbyteArray jPrivateExponent,
        jbyteArray jPrimeP,
        jbyteArray jPrimeQ,
        jbyteArray jExponentP,
        jbyteArray jExponentQ,
        jbyteArray jCrtCoefficient)
{
    jsize jKeyByteLength = jKeyBitLength / 8;
    jsize jBlobLength;
    BOOL bGeneratePrivateKeyBlob;

    // Determine whether to generate a public-key or a private-key BLOB
    if (jPrivateExponent != NULL &&
        jPrimeP != NULL &&
        jPrimeQ != NULL &&
        jExponentP != NULL &&
        jExponentQ != NULL &&
        jCrtCoefficient != NULL) {

        bGeneratePrivateKeyBlob = TRUE;
        jBlobLength = sizeof(BLOBHEADER) +
                        sizeof(RSAPUBKEY) +
                        ((jKeyBitLength / 8) * 4) +
                        (jKeyBitLength / 16);

    } else {
        bGeneratePrivateKeyBlob = FALSE;
        jBlobLength = sizeof(BLOBHEADER) +
                        sizeof(RSAPUBKEY) +
                        (jKeyBitLength / 8);
    }

    jbyte* jBlobBytes = NULL;
    jbyte* jBlobElement;
    jbyteArray jBlob = NULL;
    jsize  jElementLength;

    __try {
        jBlobBytes = new (env) jbyte[jBlobLength];
        if (jBlobBytes == NULL) {
            __leave;
        }

        BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;
        if (bGeneratePrivateKeyBlob) {
            pBlobHeader->bType = PRIVATEKEYBLOB;  // 0x07
        } else {
            pBlobHeader->bType = PUBLICKEYBLOB;   // 0x06
        }
        pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02
        pBlobHeader->reserved = 0;                // 0x0000
        pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;    // 0x0000a400

        RSAPUBKEY *pRsaPubKey =
            (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));
        if (bGeneratePrivateKeyBlob) {
            pRsaPubKey->magic = 0x32415352;       // "RSA2"
        } else {
            pRsaPubKey->magic = 0x31415352;       // "RSA1"
        }
        pRsaPubKey->bitlen = jKeyBitLength;
        pRsaPubKey->pubexp = 0; // init

        // Sanity check
        jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
        if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
            ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);
            __leave;
        }
        // The length argument must be the smaller of jPublicExponentLength
        // and sizeof(pRsaPubKey->pubkey)
        if ((jElementLength = convertToLittleEndian(env, jPublicExponent,
            (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) {
            __leave;
        }

        // Modulus n
        jBlobElement =
            (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
        if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,
            jKeyByteLength)) < 0) {
            __leave;
        }

        if (bGeneratePrivateKeyBlob) {
            // Prime p
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jPrimeP,
                jBlobElement, jKeyByteLength / 2)) < 0) {
                __leave;
            }

            // Prime q
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jPrimeQ,
                jBlobElement, jKeyByteLength / 2)) < 0) {
                __leave;
            }

            // Prime exponent p
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jExponentP,
                jBlobElement, jKeyByteLength / 2)) < 0) {
                __leave;
            }

            // Prime exponent q
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jExponentQ,
                jBlobElement, jKeyByteLength / 2)) < 0) {
                __leave;
            }

            // CRT coefficient
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient,
                jBlobElement, jKeyByteLength / 2)) < 0) {
                __leave;
            }

            // Private exponent
            jBlobElement += jElementLength;
            if ((jElementLength = convertToLittleEndian(env, jPrivateExponent,
                jBlobElement, jKeyByteLength)) < 0) {
                __leave;
            }
        }

        if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {
            __leave;
        }
        env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);

    }
    __finally
    {
        if (jBlobBytes)
            delete [] jBlobBytes;
    }

    return jBlob;
}

/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    generateRSAPrivateKeyBlob
 * Signature: (I[B[B[B[B[B[B[B[B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob
    (JNIEnv *env, jobject clazz,
        jint jKeyBitLength,
        jbyteArray jModulus,
        jbyteArray jPublicExponent,
        jbyteArray jPrivateExponent,
        jbyteArray jPrimeP,
        jbyteArray jPrimeQ,
        jbyteArray jExponentP,
        jbyteArray jExponentQ,
        jbyteArray jCrtCoefficient)
{
    return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
        jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,
        jCrtCoefficient);
}

/*
 * Class:     sun_security_mscapi_CSignature_RSA
 * Method:    generatePublicKeyBlob
 * Signature: (I[B[B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob
    (JNIEnv *env, jclass clazz,
        jint jKeyBitLength,
        jbyteArray jModulus,
        jbyteArray jPublicExponent)
{
    return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
        NULL, NULL, NULL, NULL, NULL, NULL);
}

/*
 * Class:     sun_security_mscapi_CKeyStore
 * Method:    storePrivateKey
 * Signature: (Ljava/lang/String;[BLjava/lang/String;I)Lsun/security/mscapi/CPrivateKey;
 */
JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey
    (JNIEnv *env, jobject clazz, jstring alg, jbyteArray keyBlob,
     jstring keyContainerName, jint keySize)
{
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwBlobLen;
    BYTE * pbKeyBlob = NULL;
    const char* pszKeyContainerName = NULL; // UUID
    jobject privateKey = NULL;

    __try
    {
        if ((pszKeyContainerName =
            env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
            __leave;
        }
        dwBlobLen = env->GetArrayLength(keyBlob);
        if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
            == NULL) {
            __leave;
        }

        // Acquire a CSP context (create a new key container).
        if (::CryptAcquireContext( //deprecated
            &hCryptProv,
            pszKeyContainerName,
            NULL,
            PROV_RSA_FULL,
            CRYPT_NEWKEYSET) == FALSE)
        {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Import the private key
        if (::CryptImportKey( //deprecated
            hCryptProv,
            pbKeyBlob,
            dwBlobLen,
            0,
            CRYPT_EXPORTABLE,
            &hKey) == FALSE)
        {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Get the method ID for the CPrivateKey constructor
        jclass clazzCPrivateKey =
            env->FindClass("sun/security/mscapi/CPrivateKey");
        if (clazzCPrivateKey == NULL) {
            __leave;
        }

        jmethodID mNewCPrivateKey =
            env->GetStaticMethodID(clazzCPrivateKey, "of",
            "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPrivateKey;");
        if (mNewCPrivateKey == NULL) {
            __leave;
        }

        // Create a new private key
        privateKey = env->CallStaticObjectMethod(clazzCPrivateKey, mNewCPrivateKey,
            alg, (jlong) hCryptProv, (jlong) hKey, keySize);

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (pszKeyContainerName)
            env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);

        if (pbKeyBlob)
            env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
                JNI_ABORT);
    }

    return privateKey;
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    importECPublicKey
 * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
 */
JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey
    (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
{
    NCRYPT_KEY_HANDLE       hTmpKey         = NULL;
    DWORD dwBlobLen;
    BYTE * pbKeyBlob = NULL;
    jobject publicKey = NULL;

    __try
    {
        dwBlobLen = env->GetArrayLength(keyBlob);
        if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
            == NULL) {
            __leave;
        }
        dump("NCryptImportKey", pbKeyBlob, dwBlobLen);
        NCRYPT_PROV_HANDLE hProv;
        SS_CHECK(NCryptOpenStorageProvider(
                &hProv, L"Microsoft Software Key Storage Provider", 0 ));
        SS_CHECK(NCryptImportKey(
                                                    hProv,
                                                    NULL,
                                                    BCRYPT_ECCPUBLIC_BLOB,
                                                    NULL,
                                                    &hTmpKey,
                                                    pbKeyBlob,
                                                    dwBlobLen,
                                                    0));
        NCryptFreeObject( hProv );
        // Get the method ID for the CPublicKey constructor
        jclass clazzCPublicKey =
            env->FindClass("sun/security/mscapi/CPublicKey");
        if (clazzCPublicKey == NULL) {
            __leave;
        }

        jmethodID mNewCPublicKey =
            env->GetStaticMethodID(clazzCPublicKey, "of",
            "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
        if (mNewCPublicKey == NULL) {
            __leave;
        }

        // Create a new public key
        publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
            alg, (jlong) hTmpKey, (jlong) 0, keySize);
    }
    __finally
    {
    }

    return publicKey;
}

/*
 * Class:     sun_security_mscapi_CSignature
 * Method:    importPublicKey
 * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
 */
JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importPublicKey
    (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
{
    HCRYPTPROV hCryptProv = NULL;
    HCRYPTKEY hKey = NULL;
    DWORD dwBlobLen;
    BYTE * pbKeyBlob = NULL;
    jobject publicKey = NULL;

    __try
    {
        dwBlobLen = env->GetArrayLength(keyBlob);
        if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
            == NULL) {
            __leave;
        }

        // Acquire a CSP context (create a new key container).
        // Prefer a PROV_RSA_AES CSP, when available, due to its support
        // for SHA-2-based signatures.
        if (::CryptAcquireContext( //deprecated
            &hCryptProv,
            NULL,
            NULL,
            PROV_RSA_AES,
            CRYPT_VERIFYCONTEXT) == FALSE)
        {
            // Failover to using the default CSP (PROV_RSA_FULL)

            if (::CryptAcquireContext( //deprecated
                &hCryptProv,
                NULL,
                NULL,
                PROV_RSA_FULL,
                CRYPT_VERIFYCONTEXT) == FALSE)
            {
                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                __leave;
            }
        }

        // Import the public key
        if (::CryptImportKey( //deprecated
            hCryptProv,
            pbKeyBlob,
            dwBlobLen,
            0,
            CRYPT_EXPORTABLE,
            &hKey) == FALSE)
        {
            ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
            __leave;
        }

        // Get the method ID for the CPublicKey constructor
        jclass clazzCPublicKey =
            env->FindClass("sun/security/mscapi/CPublicKey");
        if (clazzCPublicKey == NULL) {
            __leave;
        }

        jmethodID mNewCPublicKey =
            env->GetStaticMethodID(clazzCPublicKey, "of",
            "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
        if (mNewCPublicKey == NULL) {
            __leave;
        }

        // Create a new public key
        publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
            alg, (jlong) hCryptProv, (jlong) hKey, keySize);

    }
    __finally
    {
        //--------------------------------------------------------------------
        // Clean up.

        if (pbKeyBlob)
            env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
                JNI_ABORT);
    }

    return publicKey;
}

} /* extern "C" */
