Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/security/mscapi/security.cpp
32288 views
/*1* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425//=--------------------------------------------------------------------------=26// security.cpp by Stanley Man-Kit Ho27//=--------------------------------------------------------------------------=28//2930#include <jni.h>31#include <stdlib.h>32#include <string.h>33#include <windows.h>34#include <BaseTsd.h>35#include <wincrypt.h>36#include <stdio.h>37#include <memory>38#include "sun_security_mscapi_CKey.h"39#include "sun_security_mscapi_CKeyStore.h"40#include "sun_security_mscapi_CRSACipher.h"41#include "sun_security_mscapi_CKeyPairGenerator_RSA.h"42#include "sun_security_mscapi_CPublicKey.h"43#include "sun_security_mscapi_CPublicKey_CRSAPublicKey.h"44#include "sun_security_mscapi_CSignature.h"45#include "sun_security_mscapi_CSignature_RSA.h"464748#define OID_EKU_ANY "2.5.29.37.0"4950#define CERTIFICATE_PARSING_EXCEPTION \51"java/security/cert/CertificateParsingException"52#define INVALID_KEY_EXCEPTION \53"java/security/InvalidKeyException"54#define KEY_EXCEPTION "java/security/KeyException"55#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"56#define PROVIDER_EXCEPTION "java/security/ProviderException"57#define SIGNATURE_EXCEPTION "java/security/SignatureException"58#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"5960#define SS_CHECK(Status) \61if (Status != ERROR_SUCCESS) { \62ThrowException(env, SIGNATURE_EXCEPTION, Status); \63__leave; \64}6566#define PP(fmt, ...) \67if (trace) { \68fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \69fprintf(stdout, fmt, ##__VA_ARGS__); \70fprintf(stdout, "\n"); \71fflush(stdout); \72}7374extern "C" {7576char* trace = getenv("CAPI_TRACE");7778void showProperty(NCRYPT_HANDLE hKey);7980void dump(LPSTR title, PBYTE data, DWORD len)81{82if (trace) {83printf("==== %s ====\n", title);84for (DWORD i = 0; i < len; i+=16) {85printf("%04x: ", i);86for (int j = 0; j < 16; j++) {87if (j == 8) {88printf(" ");89}90if (i + j < len) {91printf("%02X ", *(data + i + j) & 0xff);92} else {93printf(" ");94}95}96for (int j = 0; j < 16; j++) {97if (i + j < len) {98int k = *(data + i + j) & 0xff;99if (k < 32 || k > 127) printf(".");100else printf("%c", (char)k);101}102}103printf("\n");104}105fflush(stdout);106}107}108109/*110* Throws an arbitrary Java exception with the given message.111*/112void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,113const char *szMessage)114{115jclass exceptionClazz = env->FindClass(exceptionName);116if (exceptionClazz != NULL) {117env->ThrowNew(exceptionClazz, szMessage);118}119}120121/*122* Throws an arbitrary Java exception.123* The exception message is a Windows system error message.124*/125void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)126{127char szMessage[1024];128szMessage[0] = '\0';129130DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,131NULL, szMessage, sizeof(szMessage), NULL);132if (res == 0) {133strcpy(szMessage, "Unknown error");134}135136ThrowExceptionWithMessage(env, exceptionName, szMessage);137}138139/*140* Overloaded 'operator new[]' variant, which will raise Java's141* OutOfMemoryError in the case of a failure.142*/143void* operator new[](std::size_t size, JNIEnv *env)144{145void* buf = ::operator new[](size, std::nothrow);146if (buf == NULL) {147ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,148"Native memory allocation failed");149}150return buf;151}152153/*154* Maps the name of a hash algorithm to an algorithm identifier.155*/156ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {157158const char* pszHashAlgorithm = NULL;159ALG_ID algId = 0;160161if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))162== NULL) {163return algId;164}165166if ((strcmp("SHA", pszHashAlgorithm) == 0) ||167(strcmp("SHA1", pszHashAlgorithm) == 0) ||168(strcmp("SHA-1", pszHashAlgorithm) == 0)) {169170algId = CALG_SHA1;171} else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {172algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5173} else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {174algId = CALG_SHA_256;175} else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {176algId = CALG_SHA_384;177} else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {178algId = CALG_SHA_512;179} else if (strcmp("MD5", pszHashAlgorithm) == 0) {180algId = CALG_MD5;181} else if (strcmp("MD2", pszHashAlgorithm) == 0) {182algId = CALG_MD2;183}184185if (pszHashAlgorithm)186env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);187188return algId;189}190191/*192* Maps the name of a hash algorithm to a CNG Algorithm Identifier.193*/194LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {195196const char* pszHashAlgorithm = NULL;197LPCWSTR id = NULL;198199if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))200== NULL) {201return id;202}203204if ((strcmp("SHA", pszHashAlgorithm) == 0) ||205(strcmp("SHA1", pszHashAlgorithm) == 0) ||206(strcmp("SHA-1", pszHashAlgorithm) == 0)) {207208id = BCRYPT_SHA1_ALGORITHM;209} else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {210id = BCRYPT_SHA256_ALGORITHM;211} else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {212id = BCRYPT_SHA384_ALGORITHM;213} else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {214id = BCRYPT_SHA512_ALGORITHM;215}216217if (pszHashAlgorithm)218env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);219220return id;221}222223/*224* Returns a certificate chain context given a certificate context and key225* usage identifier.226*/227bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)228{229CERT_ENHKEY_USAGE EnhkeyUsage;230CERT_USAGE_MATCH CertUsage;231CERT_CHAIN_PARA ChainPara;232DWORD dwFlags = 0;233LPSTR szUsageIdentifierArray[1];234235szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;236EnhkeyUsage.cUsageIdentifier = 1;237EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;238CertUsage.dwType = USAGE_MATCH_TYPE_AND;239CertUsage.Usage = EnhkeyUsage;240ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);241ChainPara.RequestedUsage=CertUsage;242243// Build a chain using CertGetCertificateChain244// and the certificate retrieved.245return (::CertGetCertificateChain(NULL, // use the default chain engine246pCertContext, // pointer to the end certificate247NULL, // use the default time248NULL, // search no additional stores249&ChainPara, // use AND logic and enhanced key usage250// as indicated in the ChainPara251// data structure252dwFlags,253NULL, // currently reserved254ppChainContext) == TRUE); // return a pointer to the chain created255}256257258/////////////////////////////////////////////////////////////////////////////259//260261/*262* Class: sun_security_mscapi_PRNG263* Method: generateSeed264* Signature: (I[B)[B265*/266JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed267(JNIEnv *env, jclass clazz, jint length, jbyteArray seed)268{269270HCRYPTPROV hCryptProv = NULL;271jbyte* reseedBytes = NULL;272jbyte* seedBytes = NULL;273jbyteArray result = NULL;274275__try276{277// Acquire a CSP context.278if(::CryptAcquireContext( //deprecated279&hCryptProv,280NULL,281NULL,282PROV_RSA_FULL,283CRYPT_VERIFYCONTEXT) == FALSE)284{285ThrowException(env, PROVIDER_EXCEPTION, GetLastError());286__leave;287}288289/*290* If length is negative and a seed is supplied, use it to re-seed the291* generator. Return null whether a seed is supplied or not.292* If length is non-zero then generate a new seed according to the293* requested length and return the new seed.294* If length is zero then overwrite the supplied seed with a new295* seed of the same length and return the seed.296*/297if (length < 0) {298if (seed == NULL) {299__leave;300}301length = env->GetArrayLength(seed);302if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {303__leave;304}305306if (::CryptGenRandom( //deprecated307hCryptProv,308length,309(BYTE *) reseedBytes) == FALSE) {310311ThrowException(env, PROVIDER_EXCEPTION, GetLastError());312__leave;313}314315result = NULL;316317} else {318319if (length > 0) {320seed = env->NewByteArray(length);321if (seed == NULL) {322__leave;323}324} else {325length = env->GetArrayLength(seed);326}327328if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {329__leave;330}331332if (::CryptGenRandom( //deprecated333hCryptProv,334length,335(BYTE *) seedBytes) == FALSE) {336337ThrowException(env, PROVIDER_EXCEPTION, GetLastError());338__leave;339}340341result = seed; // seed will be updated when seedBytes gets released342}343}344__finally345{346//--------------------------------------------------------------------347// Clean up.348349if (reseedBytes)350env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);351352if (seedBytes)353env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig354355if (hCryptProv)356::CryptReleaseContext(hCryptProv, 0); //deprecated357}358359return result;360}361362363/*364* Class: sun_security_mscapi_CKeyStore365* Method: loadKeysOrCertificateChains366* Signature: (Ljava/lang/String;)V367*/368JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains369(JNIEnv *env, jobject obj, jstring jCertStoreName)370{371/**372* Certificate in cert store has enhanced key usage extension373* property (or EKU property) that is not part of the certificate itself. To determine374* if the certificate should be returned, both the enhanced key usage in certificate375* extension block and the extension property stored along with the certificate in376* certificate store should be examined. Otherwise, we won't be able to determine377* the proper key usage from the Java side because the information is not stored as378* part of the encoded certificate.379*/380381const char* pszCertStoreName = NULL;382HCERTSTORE hCertStore = NULL;383PCCERT_CONTEXT pCertContext = NULL;384char* pszNameString = NULL; // certificate's friendly name385DWORD cchNameString = 0;386387388__try389{390// Open a system certificate store.391if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))392== NULL) {393__leave;394}395if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))396== NULL) {397398ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());399__leave;400}401402// Determine clazz and method ID to generate certificate403jclass clazzArrayList = env->FindClass("java/util/ArrayList");404if (clazzArrayList == NULL) {405__leave;406}407408jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");409if (mNewArrayList == NULL) {410__leave;411}412413jclass clazzOfThis = env->GetObjectClass(obj);414if (clazzOfThis == NULL) {415__leave;416}417418jmethodID mGenCert = env->GetMethodID(clazzOfThis,419"generateCertificate",420"([BLjava/util/Collection;)V");421if (mGenCert == NULL) {422__leave;423}424425// Determine method ID to generate certificate chain426jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,427"generateCertificateChain",428"(Ljava/lang/String;Ljava/util/Collection;)V");429if (mGenCertChain == NULL) {430__leave;431}432433// Determine method ID to generate RSA certificate chain434jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,435"generateKeyAndCertificateChain",436"(ZLjava/lang/String;JJILjava/util/Collection;)V");437if (mGenKeyAndCertChain == NULL) {438__leave;439}440441// Use CertEnumCertificatesInStore to get the certificates442// from the open store. pCertContext must be reset to443// NULL to retrieve the first certificate in the store.444while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))445{446PP("--------------------------");447// Check if private key available - client authentication certificate448// must have private key available.449HCRYPTPROV hCryptProv = NULL;450DWORD dwKeySpec = 0;451HCRYPTKEY hUserKey = NULL;452BOOL bCallerFreeProv = FALSE;453BOOL bHasNoPrivateKey = FALSE;454DWORD dwPublicKeyLength = 0;455456// First, probe it silently457if (::CryptAcquireCertificatePrivateKey(pCertContext,458CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,459&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE460&& GetLastError() != NTE_SILENT_CONTEXT)461{462PP("bHasNoPrivateKey = TRUE!");463bHasNoPrivateKey = TRUE;464}465else466{467if (bCallerFreeProv == TRUE) {468::CryptReleaseContext(hCryptProv, NULL); // deprecated469bCallerFreeProv = FALSE;470}471472// Second, acquire the key normally (not silently)473if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,474&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)475{476PP("bHasNoPrivateKey = TRUE!!");477bHasNoPrivateKey = TRUE;478}479else480{481if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {482PP("CNG %I64d", (__int64)hCryptProv);483} else {484// Private key is available485BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated486487// Skip certificate if cannot find private key488if (bGetUserKey == FALSE) {489if (bCallerFreeProv)490::CryptReleaseContext(hCryptProv, NULL); // deprecated491continue;492}493494// Set cipher mode to ECB495DWORD dwCipherMode = CRYPT_MODE_ECB;496::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated497PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);498}499// If the private key is present in smart card, we may not be able to500// determine the key length by using the private key handle. However,501// since public/private key pairs must have the same length, we could502// determine the key length of the private key by using the public key503// in the certificate.504dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,505&(pCertContext->pCertInfo->SubjectPublicKeyInfo));506}507}508PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;509510// Build certificate chain by using system certificate store.511// Add cert chain into collection for any key usage.512//513if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))514{515for (DWORD i = 0; i < pCertChainContext->cChain; i++)516{517// Found cert chain518PCERT_SIMPLE_CHAIN rgpChain =519pCertChainContext->rgpChain[i];520521// Create ArrayList to store certs in each chain522jobject jArrayList =523env->NewObject(clazzArrayList, mNewArrayList);524if (jArrayList == NULL) {525__leave;526}527528// Cleanup the previous allocated name529if (pszNameString) {530delete [] pszNameString;531pszNameString = NULL;532}533534for (unsigned int j=0; j < rgpChain->cElement; j++)535{536PCERT_CHAIN_ELEMENT rgpElement =537rgpChain->rgpElement[j];538PCCERT_CONTEXT pc = rgpElement->pCertContext;539540// Retrieve the friendly name of the first certificate541// in the chain542if (j == 0) {543544// If the cert's name cannot be retrieved then545// pszNameString remains set to NULL.546// (An alias name will be generated automatically547// when storing this cert in the keystore.)548549// Get length of friendly name550if ((cchNameString = CertGetNameString(pc,551CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,552NULL, 0)) > 1) {553554// Found friendly name555pszNameString = new (env) char[cchNameString];556if (pszNameString == NULL) {557__leave;558}559560CertGetNameString(pc,561CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,562pszNameString, cchNameString);563}564}565566BYTE* pbCertEncoded = pc->pbCertEncoded;567DWORD cbCertEncoded = pc->cbCertEncoded;568569// Allocate and populate byte array570jbyteArray byteArray = env->NewByteArray(cbCertEncoded);571if (byteArray == NULL) {572__leave;573}574env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,575(jbyte*) pbCertEncoded);576577// Generate certificate from byte array and store into578// cert collection579env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);580}581582// Usually pszNameString should be non-NULL. It's either583// the friendly name or an element from the subject name584// or SAN.585if (pszNameString)586{587PP("%s: %s", pszNameString,588pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);589if (bHasNoPrivateKey)590{591// Generate certificate chain and store into cert chain592// collection593jstring name = env->NewStringUTF(pszNameString);594if (name == NULL) {595__leave;596}597env->CallVoidMethod(obj, mGenCertChain,598name,599jArrayList);600}601else602{603if (hUserKey) {604// Only accept RSA for CAPI605DWORD dwData = CALG_RSA_KEYX;606DWORD dwSize = sizeof(DWORD);607::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated608&dwSize, NULL);609if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)610{611// Generate RSA certificate chain and store into cert612// chain collection613jstring name = env->NewStringUTF(pszNameString);614if (name == NULL) {615__leave;616}617env->CallVoidMethod(obj, mGenKeyAndCertChain,6181,619name,620(jlong) hCryptProv, (jlong) hUserKey,621dwPublicKeyLength, jArrayList);622}623} else {624// Only accept EC for CNG625BYTE buffer[32];626DWORD len = 0;627if (::NCryptGetProperty(628hCryptProv, NCRYPT_ALGORITHM_PROPERTY,629(PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {630jstring name = env->NewStringUTF(pszNameString);631if (name == NULL) {632__leave;633}634if (buffer[0] == 'E' && buffer[2] == 'C'635&& (dwPublicKeyLength == 256636|| dwPublicKeyLength == 384637|| dwPublicKeyLength == 521)) {638env->CallVoidMethod(obj, mGenKeyAndCertChain,6390,640name,641(jlong) hCryptProv, (jlong) 0,642dwPublicKeyLength, jArrayList);643} else if (buffer[0] == 'R' && buffer[2] == 'S'644&& buffer[4] == 'A') {645env->CallVoidMethod(obj, mGenKeyAndCertChain,6461,647name,648(jlong) hCryptProv, (jlong) 0,649dwPublicKeyLength, jArrayList);650} else {651dump("Unknown NCRYPT_ALGORITHM_PROPERTY", buffer, len);652}653}654}655}656}657}658659// Free cert chain660if (pCertChainContext)661::CertFreeCertificateChain(pCertChainContext);662} else {663PP("GetCertificateChain failed %d", GetLastError());664}665}666}667__finally668{669if (hCertStore)670::CertCloseStore(hCertStore, 0);671672if (pszCertStoreName)673env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);674675if (pszNameString)676delete [] pszNameString;677}678}679680681/*682* Class: sun_security_mscapi_CKey683* Method: cleanUp684* Signature: (JJ)V685*/686JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp687(JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)688{689if (hCryptKey == NULL && hCryptProv != NULL) {690NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);691} else {692if (hCryptKey != NULL)693::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated694695if (hCryptProv != NULL)696::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated697}698}699700/*701* Class: sun_security_mscapi_CSignature702* Method: signHash703* Signature: (Z[BILjava/lang/String;JJ)[B704*/705JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash706(JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,707jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,708jlong hCryptKey)709{710HCRYPTHASH hHash = NULL;711jbyte* pHashBuffer = NULL;712jbyte* pSignedHashBuffer = NULL;713jbyteArray jSignedHash = NULL;714HCRYPTPROV hCryptProvAlt = NULL;715716__try717{718// Map hash algorithm719ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);720721// Acquire a hash object handle.722if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) //deprecated723{724// Failover to using the PROV_RSA_AES CSP725726DWORD cbData = 256;727BYTE pbData[256];728pbData[0] = '\0';729730// Get name of the key container731::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated732(BYTE *)pbData, &cbData, 0);733734// Acquire an alternative CSP handle735if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated736PROV_RSA_AES, 0) == FALSE)737{738739ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());740__leave;741}742743// Acquire a hash object handle.744if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, //deprecated745&hHash) == FALSE)746{747ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());748__leave;749}750}751752// Copy hash from Java to native buffer753pHashBuffer = new (env) jbyte[jHashSize];754if (pHashBuffer == NULL) {755__leave;756}757env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);758759// Set hash value in the hash object760if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) //deprecated761{762ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());763__leave;764}765766// Determine key spec.767DWORD dwKeySpec = AT_SIGNATURE;768ALG_ID dwAlgId;769DWORD dwAlgIdLen = sizeof(ALG_ID);770771if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated772ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());773__leave;774775}776if (CALG_RSA_KEYX == dwAlgId) {777dwKeySpec = AT_KEYEXCHANGE;778}779780// Determine size of buffer781DWORD dwBufLen = 0;782DWORD dwFlags = 0;783784if (noHashOID == JNI_TRUE) {785dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature786}787788if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) //deprecated789{790ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());791__leave;792}793794pSignedHashBuffer = new (env) jbyte[dwBufLen];795if (pSignedHashBuffer == NULL) {796__leave;797}798if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) //deprecated799{800ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());801__leave;802}803804// Create new byte array805jbyteArray temp = env->NewByteArray(dwBufLen);806if (temp == NULL) {807__leave;808}809810// Copy data from native buffer811env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);812813jSignedHash = temp;814}815__finally816{817if (pSignedHashBuffer)818delete [] pSignedHashBuffer;819820if (pHashBuffer)821delete [] pHashBuffer;822823if (hHash)824::CryptDestroyHash(hHash); //deprecated825826if (hCryptProvAlt)827::CryptReleaseContext(hCryptProvAlt, 0); // deprecated828}829830return jSignedHash;831}832833/*834* Class: sun_security_mscapi_CSignature835* Method: signCngHash836* Signature: (I[BIILjava/lang/String;JJ)[B837*/838JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash839(JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,840jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,841jlong hCryptKey)842{843jbyteArray jSignedHash = NULL;844845jbyte* pHashBuffer = NULL;846jbyte* pSignedHashBuffer = NULL;847NCRYPT_KEY_HANDLE hk = NULL;848849__try850{851if (hCryptKey == 0) {852hk = (NCRYPT_KEY_HANDLE)hCryptProv;853} else {854SS_CHECK(::NCryptTranslateHandle(855NULL,856&hk,857(HCRYPTPROV)hCryptProv,858(HCRYPTKEY)hCryptKey,859NULL,8600));861}862863// Copy hash from Java to native buffer864pHashBuffer = new (env) jbyte[jHashSize];865if (pHashBuffer == NULL) {866__leave;867}868env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);869870VOID* param;871DWORD dwFlags;872873switch (type) {874case 0:875param = NULL;876dwFlags = 0;877break;878case 1:879BCRYPT_PKCS1_PADDING_INFO pkcs1Info;880if (jHashAlgorithm) {881pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);882if (pkcs1Info.pszAlgId == NULL) {883ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,884"Unrecognised hash algorithm");885__leave;886}887} else {888pkcs1Info.pszAlgId = NULL;889}890param = &pkcs1Info;891dwFlags = BCRYPT_PAD_PKCS1;892break;893case 2:894BCRYPT_PSS_PADDING_INFO pssInfo;895pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);896pssInfo.cbSalt = saltLen;897if (pssInfo.pszAlgId == NULL) {898ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,899"Unrecognised hash algorithm");900__leave;901}902param = &pssInfo;903dwFlags = BCRYPT_PAD_PSS;904break;905}906907DWORD jSignedHashSize = 0;908SS_CHECK(::NCryptSignHash(909hk,910param,911(BYTE*)pHashBuffer, jHashSize,912NULL, 0, &jSignedHashSize,913dwFlags914));915916pSignedHashBuffer = new (env) jbyte[jSignedHashSize];917if (pSignedHashBuffer == NULL) {918__leave;919}920921SS_CHECK(::NCryptSignHash(922hk,923param,924(BYTE*)pHashBuffer, jHashSize,925(BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,926dwFlags927));928929// Create new byte array930jbyteArray temp = env->NewByteArray(jSignedHashSize);931if (temp == NULL) {932__leave;933}934935// Copy data from native buffer936env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);937938jSignedHash = temp;939}940__finally941{942if (pSignedHashBuffer)943delete [] pSignedHashBuffer;944945if (pHashBuffer)946delete [] pHashBuffer;947948if (hCryptKey != 0 && hk != NULL)949::NCryptFreeObject(hk);950}951952return jSignedHash;953}954955/*956* Class: sun_security_mscapi_CSignature957* Method: verifySignedHash958* Signature: ([BIL/java/lang/String;[BIJJ)Z959*/960JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash961(JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,962jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,963jlong hCryptProv, jlong hCryptKey)964{965HCRYPTHASH hHash = NULL;966jbyte* pHashBuffer = NULL;967jbyte* pSignedHashBuffer = NULL;968DWORD dwSignedHashBufferLen = jSignedHashSize;969jboolean result = JNI_FALSE;970HCRYPTPROV hCryptProvAlt = NULL;971972__try973{974// Map hash algorithm975ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);976977// Acquire a hash object handle.978if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)979== FALSE)980{981// Failover to using the PROV_RSA_AES CSP982983DWORD cbData = 256;984BYTE pbData[256];985pbData[0] = '\0';986987// Get name of the key container988::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated989(BYTE *)pbData, &cbData, 0);990991// Acquire an alternative CSP handle992if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated993PROV_RSA_AES, 0) == FALSE)994{995996ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());997__leave;998}9991000// Acquire a hash object handle.1001if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,1002&hHash) == FALSE)1003{1004ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());1005__leave;1006}1007}10081009// Copy hash and signedHash from Java to native buffer1010pHashBuffer = new (env) jbyte[jHashSize];1011if (pHashBuffer == NULL) {1012__leave;1013}1014env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);10151016pSignedHashBuffer = new (env) jbyte[jSignedHashSize];1017if (pSignedHashBuffer == NULL) {1018__leave;1019}1020env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,1021pSignedHashBuffer);10221023// Set hash value in the hash object1024if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) //deprecated1025== FALSE)1026{1027ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());1028__leave;1029}10301031// For RSA, the hash encryption algorithm is normally the same as the1032// public key algorithm, so AT_SIGNATURE is used.10331034// Verify the signature1035if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, //deprecated1036dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)1037{1038result = JNI_TRUE;1039}1040}10411042__finally1043{1044if (pSignedHashBuffer)1045delete [] pSignedHashBuffer;10461047if (pHashBuffer)1048delete [] pHashBuffer;10491050if (hHash)1051::CryptDestroyHash(hHash); //deprecated10521053if (hCryptProvAlt)1054::CryptReleaseContext(hCryptProvAlt, 0); // deprecated1055}10561057return result;1058}10591060/*1061* Class: sun_security_mscapi_CSignature1062* Method: verifyCngSignedHash1063* Signature: (I[BI[BIILjava/lang/String;JJ)Z1064*/1065JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash1066(JNIEnv *env, jclass clazz, jint type,1067jbyteArray jHash, jint jHashSize,1068jbyteArray jSignedHash, jint jSignedHashSize,1069jint saltLen, jstring jHashAlgorithm,1070jlong hCryptProv, jlong hCryptKey)1071{1072jbyte* pHashBuffer = NULL;1073jbyte* pSignedHashBuffer = NULL;1074jboolean result = JNI_FALSE;1075NCRYPT_KEY_HANDLE hk = NULL;10761077__try1078{1079if (hCryptKey == 0) {1080hk = (NCRYPT_KEY_HANDLE)hCryptProv;1081} else {1082SS_CHECK(::NCryptTranslateHandle(1083NULL,1084&hk,1085(HCRYPTPROV)hCryptProv,1086(HCRYPTKEY)hCryptKey,1087NULL,10880));1089}10901091// Copy hash and signedHash from Java to native buffer1092pHashBuffer = new (env) jbyte[jHashSize];1093if (pHashBuffer == NULL) {1094__leave;1095}1096env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);10971098pSignedHashBuffer = new (env) jbyte[jSignedHashSize];1099if (pSignedHashBuffer == NULL) {1100__leave;1101}1102env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,1103pSignedHashBuffer);11041105VOID* param;1106DWORD dwFlags;11071108switch (type) {1109case 0:1110param = NULL;1111dwFlags = 0;1112break;1113case 1:1114BCRYPT_PKCS1_PADDING_INFO pkcs1Info;1115if (jHashAlgorithm) {1116pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);1117if (pkcs1Info.pszAlgId == NULL) {1118ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,1119"Unrecognised hash algorithm");1120__leave;1121}1122} else {1123pkcs1Info.pszAlgId = NULL;1124}1125param = &pkcs1Info;1126dwFlags = NCRYPT_PAD_PKCS1_FLAG;1127break;1128case 2:1129BCRYPT_PSS_PADDING_INFO pssInfo;1130pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);1131pssInfo.cbSalt = saltLen;1132if (pssInfo.pszAlgId == NULL) {1133ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,1134"Unrecognised hash algorithm");1135__leave;1136}1137param = &pssInfo;1138dwFlags = NCRYPT_PAD_PSS_FLAG;1139break;1140}11411142if (::NCryptVerifySignature(hk, param,1143(BYTE *) pHashBuffer, jHashSize,1144(BYTE *) pSignedHashBuffer, jSignedHashSize,1145dwFlags) == ERROR_SUCCESS)1146{1147result = JNI_TRUE;1148}1149}11501151__finally1152{1153if (pSignedHashBuffer)1154delete [] pSignedHashBuffer;11551156if (pHashBuffer)1157delete [] pHashBuffer;11581159if (hCryptKey != 0 && hk != NULL)1160::NCryptFreeObject(hk);1161}11621163return result;1164}11651166#define DUMP_PROP(p) \1167if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \1168sprintf(header, "%s %ls", #p, p); \1169dump(header, buffer, len); \1170}11711172#define EXPORT_BLOB(p) \1173desc.cBuffers = 0; \1174if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \1175sprintf(header, "%s %ls (%ld)", #p, p, desc.cBuffers); \1176dump(header, buffer, len); \1177for (int i = 0; i < (int)desc.cBuffers; i++) { \1178sprintf(header, "desc %ld", desc.pBuffers[i].BufferType); \1179dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \1180} \1181}11821183void showProperty(NCRYPT_HANDLE hKey) {1184char header[100];1185BYTE buffer[8192];1186DWORD len = 9;1187NCryptBufferDesc desc;1188DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);1189DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);1190DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);1191DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);1192DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);1193DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);1194DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);1195DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);1196DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);1197DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);1198DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);1199DUMP_PROP(NCRYPT_LENGTH_PROPERTY);1200DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);1201DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);1202DUMP_PROP(NCRYPT_NAME_PROPERTY);1203DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);1204DUMP_PROP(NCRYPT_PIN_PROPERTY);1205DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);1206DUMP_PROP(NCRYPT_READER_PROPERTY);1207DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);1208DUMP_PROP(NCRYPT_SCARD_PIN_ID);1209DUMP_PROP(NCRYPT_SCARD_PIN_INFO);1210DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);1211DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);1212DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);1213DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);1214DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);1215DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);1216DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);1217DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);1218DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);1219DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);1220DUMP_PROP(NCRYPT_VERSION_PROPERTY);1221DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);12221223EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);1224EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);1225EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);1226EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);1227EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);1228EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);1229EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);1230EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);1231EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);1232EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);1233EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);1234EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);1235EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);1236EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);1237EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);1238EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);1239EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);1240// Support starts from Windows 8 and Windows Server 20121241//EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);1242EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);1243EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);1244//EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);1245//EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);1246BCryptBuffer bb;1247bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;1248bb.cbBuffer = 18;1249bb.pvBuffer = L"changeit";1250BCryptBufferDesc bbd;1251bbd.ulVersion = 0;1252bbd.cBuffers = 1;1253bbd.pBuffers = &bb;1254if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,1255(PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {1256sprintf(header, "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);1257dump(header, buffer, len);1258}1259// Support starts from Windows 8 and Windows Server 20121260//EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);1261}12621263/*1264* Class: sun_security_mscapi_CKeyPairGenerator_RSA1265* Method: generateCKeyPair1266* Signature: (Ljava/lang/String;ILjava/lang/String;)Lsun/security/mscapi/CKeyPair;1267*/1268JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair1269(JNIEnv *env, jclass clazz, jstring alg, jint keySize, jstring keyContainerName)1270{1271HCRYPTPROV hCryptProv = NULL;1272HCRYPTKEY hKeyPair;1273DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;1274jobject keypair = NULL;1275const char* pszKeyContainerName = NULL; // UUID12761277__try1278{1279if ((pszKeyContainerName =1280env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {1281__leave;1282}12831284// Acquire a CSP context (create a new key container).1285// Prefer a PROV_RSA_AES CSP, when available, due to its support1286// for SHA-2-based signatures.1287if (::CryptAcquireContext( //deprecated1288&hCryptProv,1289pszKeyContainerName,1290NULL,1291PROV_RSA_AES,1292CRYPT_NEWKEYSET) == FALSE)1293{1294// Failover to using the default CSP (PROV_RSA_FULL)12951296if (::CryptAcquireContext( //deprecated1297&hCryptProv,1298pszKeyContainerName,1299NULL,1300PROV_RSA_FULL,1301CRYPT_NEWKEYSET) == FALSE)1302{1303ThrowException(env, KEY_EXCEPTION, GetLastError());1304__leave;1305}1306}13071308// Generate an keypair1309if(::CryptGenKey( //deprecated1310hCryptProv,1311AT_KEYEXCHANGE,1312dwFlags,1313&hKeyPair) == FALSE)1314{1315ThrowException(env, KEY_EXCEPTION, GetLastError());1316__leave;1317}13181319// Get the method ID for the CKeyPair constructor1320jclass clazzCKeyPair =1321env->FindClass("sun/security/mscapi/CKeyPair");1322if (clazzCKeyPair == NULL) {1323__leave;1324}13251326jmethodID mNewCKeyPair =1327env->GetMethodID(clazzCKeyPair, "<init>", "(Ljava/lang/String;JJI)V");1328if (mNewCKeyPair == NULL) {1329__leave;1330}13311332// Create a new keypair1333keypair = env->NewObject(clazzCKeyPair, mNewCKeyPair,1334alg, (jlong) hCryptProv, (jlong) hKeyPair, keySize);13351336}1337__finally1338{1339//--------------------------------------------------------------------1340// Clean up.13411342if (pszKeyContainerName)1343env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);1344}13451346return keypair;1347}13481349/*1350* Class: sun_security_mscapi_CKey1351* Method: getContainerName1352* Signature: (J)Ljava/lang/String;1353*/1354JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getContainerName1355(JNIEnv *env, jclass jclazz, jlong hCryptProv)1356{1357DWORD cbData = 256;1358BYTE pbData[256];1359pbData[0] = '\0';13601361::CryptGetProvParam( //deprecated1362(HCRYPTPROV)hCryptProv,1363PP_CONTAINER,1364(BYTE *)pbData,1365&cbData,13660);13671368return env->NewStringUTF((const char*)pbData);1369}13701371/*1372* Class: sun_security_mscapi_CKey1373* Method: getKeyType1374* Signature: (J)Ljava/lang/String;1375*/1376JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getKeyType1377(JNIEnv *env, jclass jclazz, jlong hCryptKey)1378{1379ALG_ID dwAlgId;1380DWORD dwAlgIdLen = sizeof(ALG_ID);13811382if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated13831384if (CALG_RSA_SIGN == dwAlgId) {1385return env->NewStringUTF("Signature");13861387} else if (CALG_RSA_KEYX == dwAlgId) {1388return env->NewStringUTF("Exchange");13891390} else {1391char buffer[64];1392if (sprintf(buffer, "%lu", dwAlgId)) {1393return env->NewStringUTF(buffer);1394}1395}1396}13971398return env->NewStringUTF("<Unknown>");1399}14001401/*1402* Class: sun_security_mscapi_CKeyStore1403* Method: storeCertificate1404* Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V1405*/1406JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_storeCertificate1407(JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,1408jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,1409jlong hCryptKey)1410{1411const char* pszCertStoreName = NULL;1412HCERTSTORE hCertStore = NULL;1413PCCERT_CONTEXT pCertContext = NULL;1414PWCHAR pszCertAliasName = NULL;1415jbyte* pbCertEncoding = NULL;1416const jchar* jCertAliasChars = NULL;1417const char* pszContainerName = NULL;1418const char* pszProviderName = NULL;1419WCHAR * pwszContainerName = NULL;1420WCHAR * pwszProviderName = NULL;14211422__try1423{1424// Open a system certificate store.1425if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))1426== NULL) {1427__leave;1428}1429if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {1430ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1431__leave;1432}14331434// Copy encoding from Java to native buffer1435pbCertEncoding = new (env) jbyte[jCertEncodingSize];1436if (pbCertEncoding == NULL) {1437__leave;1438}1439env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);14401441// Create a certificate context from the encoded cert1442if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,1443(BYTE*) pbCertEncoding, jCertEncodingSize))) {14441445ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());1446__leave;1447}14481449// Set the certificate's friendly name1450int size = env->GetStringLength(jCertAliasName);1451pszCertAliasName = new (env) WCHAR[size + 1];1452if (pszCertAliasName == NULL) {1453__leave;1454}14551456jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);1457if (jCertAliasChars == NULL) {1458__leave;1459}1460memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));1461pszCertAliasName[size] = 0; // append the string terminator14621463CRYPT_DATA_BLOB friendlyName = {1464sizeof(WCHAR) * (size + 1),1465(BYTE *) pszCertAliasName1466};14671468env->ReleaseStringChars(jCertAliasName, jCertAliasChars);14691470if (! ::CertSetCertificateContextProperty(pCertContext,1471CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {14721473ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1474__leave;1475}14761477// Attach the certificate's private key (if supplied)1478if (hCryptProv != 0 && hCryptKey != 0) {14791480CRYPT_KEY_PROV_INFO keyProviderInfo;1481DWORD dwDataLen;14821483// Get the name of the key container1484if (! ::CryptGetProvParam( //deprecated1485(HCRYPTPROV) hCryptProv,1486PP_CONTAINER,1487NULL,1488&dwDataLen,14890)) {14901491ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1492__leave;1493}14941495pszContainerName = new (env) char[dwDataLen];1496if (pszContainerName == NULL) {1497__leave;1498}14991500if (! ::CryptGetProvParam( //deprecated1501(HCRYPTPROV) hCryptProv,1502PP_CONTAINER,1503(BYTE *) pszContainerName,1504&dwDataLen,15050)) {15061507ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1508__leave;1509}15101511// Convert to a wide char string1512pwszContainerName = new (env) WCHAR[dwDataLen];1513if (pwszContainerName == NULL) {1514__leave;1515}15161517if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {1518ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1519__leave;1520}15211522// Set the name of the key container1523keyProviderInfo.pwszContainerName = pwszContainerName;152415251526// Get the name of the provider1527if (! ::CryptGetProvParam( //deprecated1528(HCRYPTPROV) hCryptProv,1529PP_NAME,1530NULL,1531&dwDataLen,15320)) {15331534ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1535__leave;1536}15371538pszProviderName = new (env) char[dwDataLen];1539if (pszProviderName == NULL) {1540__leave;1541}15421543if (! ::CryptGetProvParam( //deprecated1544(HCRYPTPROV) hCryptProv,1545PP_NAME,1546(BYTE *) pszProviderName,1547&dwDataLen,15480)) {15491550ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1551__leave;1552}15531554// Convert to a wide char string1555pwszProviderName = new (env) WCHAR[dwDataLen];1556if (pwszProviderName == NULL) {1557__leave;1558}15591560if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {1561ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1562__leave;1563}15641565// Set the name of the provider1566keyProviderInfo.pwszProvName = pwszProviderName;15671568// Get and set the type of the provider1569if (! ::CryptGetProvParam( //deprecated1570(HCRYPTPROV) hCryptProv,1571PP_PROVTYPE,1572(LPBYTE) &keyProviderInfo.dwProvType,1573&dwDataLen,15740)) {15751576ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1577__leave;1578}15791580// Set no provider flags1581keyProviderInfo.dwFlags = 0;15821583// Set no provider parameters1584keyProviderInfo.cProvParam = 0;1585keyProviderInfo.rgProvParam = NULL;15861587// Get the key's algorithm ID1588if (! ::CryptGetKeyParam( //deprecated1589(HCRYPTKEY) hCryptKey,1590KP_ALGID,1591(LPBYTE) &keyProviderInfo.dwKeySpec,1592&dwDataLen,15930)) {15941595ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1596__leave;1597}1598// Set the key spec (using the algorithm ID).1599switch (keyProviderInfo.dwKeySpec) {1600case CALG_RSA_KEYX:1601case CALG_DH_SF:1602keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;1603break;16041605case CALG_RSA_SIGN:1606case CALG_DSS_SIGN:1607keyProviderInfo.dwKeySpec = AT_SIGNATURE;1608break;16091610default:1611ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);1612__leave;1613}16141615if (! ::CertSetCertificateContextProperty(pCertContext,1616CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {16171618ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1619__leave;1620}1621}16221623// Import encoded certificate1624if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,1625CERT_STORE_ADD_REPLACE_EXISTING, NULL))1626{1627ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1628__leave;1629}16301631}1632__finally1633{1634//--------------------------------------------------------------------1635// Clean up.16361637if (hCertStore)1638::CertCloseStore(hCertStore, 0);16391640if (pszCertStoreName)1641env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);16421643if (pbCertEncoding)1644delete [] pbCertEncoding;16451646if (pszCertAliasName)1647delete [] pszCertAliasName;16481649if (pszContainerName)1650delete [] pszContainerName;16511652if (pwszContainerName)1653delete [] pwszContainerName;16541655if (pszProviderName)1656delete [] pszProviderName;16571658if (pwszProviderName)1659delete [] pwszProviderName;16601661if (pCertContext)1662::CertFreeCertificateContext(pCertContext);1663}1664}16651666/*1667* Class: sun_security_mscapi_CKeyStore1668* Method: removeCertificate1669* Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V1670*/1671JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCertificate1672(JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,1673jbyteArray jCertEncoding, jint jCertEncodingSize) {16741675const char* pszCertStoreName = NULL;1676const char* pszCertAliasName = NULL;1677HCERTSTORE hCertStore = NULL;1678PCCERT_CONTEXT pCertContext = NULL;1679PCCERT_CONTEXT pTBDCertContext = NULL;1680jbyte* pbCertEncoding = NULL;1681DWORD cchNameString = 0;1682char* pszNameString = NULL; // certificate's friendly name1683BOOL bDeleteAttempted = FALSE;16841685__try1686{1687// Open a system certificate store.1688if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))1689== NULL) {1690__leave;1691}1692if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {1693ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1694__leave;1695}16961697// Copy encoding from Java to native buffer1698pbCertEncoding = new (env) jbyte[jCertEncodingSize];1699if (pbCertEncoding == NULL) {1700__leave;1701}1702env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);17031704// Create a certificate context from the encoded cert1705if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,1706(BYTE*) pbCertEncoding, jCertEncodingSize))) {17071708ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());1709__leave;1710}17111712// Find the certificate to be deleted1713if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,1714X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {17151716ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1717__leave;1718}17191720// Check that its friendly name matches the supplied alias1721if ((cchNameString = ::CertGetNameString(pTBDCertContext,1722CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {17231724pszNameString = new (env) char[cchNameString];1725if (pszNameString == NULL) {1726__leave;1727}17281729::CertGetNameString(pTBDCertContext,1730CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,1731cchNameString);17321733// Compare the certificate's friendly name with supplied alias name1734if ((pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL))1735== NULL) {1736__leave;1737}1738if (strcmp(pszCertAliasName, pszNameString) == 0) {17391740// Only delete the certificate if the alias names matches1741if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {17421743// pTBDCertContext is always freed by the1744// CertDeleteCertificateFromStore method1745bDeleteAttempted = TRUE;17461747ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1748__leave;1749}1750}1751}17521753}1754__finally1755{1756//--------------------------------------------------------------------1757// Clean up.17581759if (hCertStore)1760::CertCloseStore(hCertStore, 0);17611762if (pszCertStoreName)1763env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);17641765if (pszCertAliasName)1766env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);17671768if (pbCertEncoding)1769delete [] pbCertEncoding;17701771if (pszNameString)1772delete [] pszNameString;17731774if (pCertContext)1775::CertFreeCertificateContext(pCertContext);17761777if (bDeleteAttempted && pTBDCertContext)1778::CertFreeCertificateContext(pTBDCertContext);1779}1780}17811782/*1783* Class: sun_security_mscapi_CKeyStore1784* Method: destroyKeyContainer1785* Signature: (Ljava/lang/String;)V1786*/1787JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer1788(JNIEnv *env, jobject clazz, jstring keyContainerName)1789{1790HCRYPTPROV hCryptProv = NULL;1791const char* pszKeyContainerName = NULL;17921793__try1794{1795if ((pszKeyContainerName =1796env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {1797__leave;1798}17991800// Destroying the default key container is not permitted1801// (because it may contain more one keypair).1802if (pszKeyContainerName == NULL) {18031804ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM);1805__leave;1806}18071808// Acquire a CSP context (to the key container).1809if (::CryptAcquireContext( //deprecated1810&hCryptProv,1811pszKeyContainerName,1812NULL,1813PROV_RSA_FULL,1814CRYPT_DELETEKEYSET) == FALSE)1815{1816ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1817__leave;1818}18191820}1821__finally1822{1823//--------------------------------------------------------------------1824// Clean up.18251826if (pszKeyContainerName)1827env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);1828}1829}18301831/*1832* Class: sun_security_mscapi_CRSACipher1833* Method: encryptDecrypt1834* Signature: ([BIJZ)[B1835*/1836JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt1837(JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,1838jboolean doEncrypt)1839{1840jbyteArray result = NULL;1841jbyte* pData = NULL;1842DWORD dwDataLen = jDataSize;1843DWORD dwBufLen = env->GetArrayLength(jData);1844DWORD i;1845BYTE tmp;18461847__try1848{1849// Copy data from Java buffer to native buffer1850pData = new (env) jbyte[dwBufLen];1851if (pData == NULL) {1852__leave;1853}1854env->GetByteArrayRegion(jData, 0, dwBufLen, pData);18551856if (doEncrypt == JNI_TRUE) {1857// encrypt1858if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated1859&dwDataLen, dwBufLen)) {18601861ThrowException(env, KEY_EXCEPTION, GetLastError());1862__leave;1863}1864dwBufLen = dwDataLen;18651866// convert from little-endian1867for (i = 0; i < dwBufLen / 2; i++) {1868tmp = pData[i];1869pData[i] = pData[dwBufLen - i -1];1870pData[dwBufLen - i - 1] = tmp;1871}1872} else {1873// convert to little-endian1874for (i = 0; i < dwBufLen / 2; i++) {1875tmp = pData[i];1876pData[i] = pData[dwBufLen - i -1];1877pData[dwBufLen - i - 1] = tmp;1878}18791880// decrypt1881if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated1882&dwBufLen)) {18831884ThrowException(env, KEY_EXCEPTION, GetLastError());1885__leave;1886}1887}18881889// Create new byte array1890if ((result = env->NewByteArray(dwBufLen)) == NULL) {1891__leave;1892}18931894// Copy data from native buffer to Java buffer1895env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);1896}1897__finally1898{1899if (pData)1900delete [] pData;1901}19021903return result;1904}19051906/*1907* Class: sun_security_mscapi_CPublicKey1908* Method: getPublicKeyBlob1909* Signature: (JJ)[B1910*/1911JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob1912(JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {19131914jbyteArray blob = NULL;1915DWORD dwBlobLen;1916BYTE* pbKeyBlob = NULL;19171918__try1919{19201921// Determine the size of the blob1922if (hCryptKey == 0) {1923SS_CHECK(::NCryptExportKey(1924(NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,1925NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));1926} else {1927if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated1928&dwBlobLen)) {19291930ThrowException(env, KEY_EXCEPTION, GetLastError());1931__leave;1932}1933}19341935pbKeyBlob = new (env) BYTE[dwBlobLen];1936if (pbKeyBlob == NULL) {1937__leave;1938}19391940// Generate key blob1941if (hCryptKey == 0) {1942SS_CHECK(::NCryptExportKey(1943(NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,1944NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));1945} else {1946if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated1947pbKeyBlob, &dwBlobLen)) {19481949ThrowException(env, KEY_EXCEPTION, GetLastError());1950__leave;1951}1952}19531954// Create new byte array1955if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {1956__leave;1957}19581959// Copy data from native buffer to Java buffer1960env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);1961}1962__finally1963{1964if (pbKeyBlob)1965delete [] pbKeyBlob;1966}19671968return blob;1969}19701971/*1972* Class: sun_security_mscapi_CPublicKey_CRSAPublicKey1973* Method: getExponent1974* Signature: ([B)[B1975*/1976JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent1977(JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {19781979jbyteArray exponent = NULL;1980jbyte* exponentBytes = NULL;1981jbyte* keyBlob = NULL;19821983__try {19841985jsize length = env->GetArrayLength(jKeyBlob);1986jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);19871988if (length < headerLength) {1989ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");1990__leave;1991}19921993if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {1994__leave;1995}19961997PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;19981999// Check BLOB type2000if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {2001ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);2002__leave;2003}20042005RSAPUBKEY* pRsaPubKey =2006(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));20072008int len = sizeof(pRsaPubKey->pubexp);2009exponentBytes = new (env) jbyte[len];2010if (exponentBytes == NULL) {2011__leave;2012}20132014// convert from little-endian while copying from blob2015for (int i = 0, j = len - 1; i < len; i++, j--) {2016exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];2017}20182019if ((exponent = env->NewByteArray(len)) == NULL) {2020__leave;2021}2022env->SetByteArrayRegion(exponent, 0, len, exponentBytes);2023}2024__finally2025{2026if (keyBlob)2027env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);20282029if (exponentBytes)2030delete [] exponentBytes;2031}20322033return exponent;2034}20352036/*2037* Class: sun_security_mscapi_CPublicKey_CRSAPublicKey2038* Method: getModulus2039* Signature: ([B)[B2040*/2041JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus2042(JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {20432044jbyteArray modulus = NULL;2045jbyte* modulusBytes = NULL;2046jbyte* keyBlob = NULL;20472048__try {20492050jsize length = env->GetArrayLength(jKeyBlob);2051jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);20522053if (length < headerLength) {2054ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");2055__leave;2056}20572058if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {2059__leave;2060}20612062PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;20632064// Check BLOB type2065if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {2066ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);2067__leave;2068}20692070RSAPUBKEY* pRsaPubKey =2071(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));20722073int len = pRsaPubKey->bitlen / 8;2074if (len < 0 || len > length - headerLength) {2075ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");2076__leave;2077}20782079modulusBytes = new (env) jbyte[len];2080if (modulusBytes == NULL) {2081__leave;2082}2083BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);20842085// convert from little-endian while copying from blob2086for (int i = 0, j = len - 1; i < len; i++, j--) {2087modulusBytes[i] = pbModulus[j];2088}20892090if ((modulus = env->NewByteArray(len)) == NULL) {2091__leave;2092}2093env->SetByteArrayRegion(modulus, 0, len, modulusBytes);2094}2095__finally2096{2097if (keyBlob)2098env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);20992100if (modulusBytes)2101delete [] modulusBytes;2102}21032104return modulus;2105}21062107/*2108* Convert an array in big-endian byte order into little-endian byte order.2109*/2110int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,2111int destinationLength) {21122113int result = -1;2114jbyte* sourceBytes = NULL;21152116__try {2117int sourceLength = env->GetArrayLength(source);21182119sourceBytes = env->GetByteArrayElements(source, 0);2120if (sourceBytes == NULL) {2121__leave;2122}21232124int copyLen = sourceLength;2125if (sourceLength > destinationLength) {2126// source might include an extra sign byte2127if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) {2128copyLen--;2129} else {2130__leave;2131}2132}21332134// Copy bytes from the end of the source array to the beginning of the2135// destination array (until the destination array is full).2136// This ensures that the sign byte from the source array will be excluded.2137for (int i = 0; i < copyLen; i++) {2138destination[i] = sourceBytes[sourceLength - 1 - i];2139}2140if (copyLen < destinationLength) {2141memset(destination + copyLen, 0, destinationLength - copyLen);2142}2143result = destinationLength;2144} __finally {2145// Clean up.2146if (sourceBytes) {2147env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);2148}2149}21502151return result;2152}21532154/*2155* The Microsoft Base Cryptographic Provider supports public-key BLOBs2156* that have the following format:2157*2158* PUBLICKEYSTRUC publickeystruc;2159* RSAPUBKEY rsapubkey;2160* BYTE modulus[rsapubkey.bitlen/8];2161*2162* and private-key BLOBs that have the following format:2163*2164* PUBLICKEYSTRUC publickeystruc;2165* RSAPUBKEY rsapubkey;2166* BYTE modulus[rsapubkey.bitlen/8];2167* BYTE prime1[rsapubkey.bitlen/16];2168* BYTE prime2[rsapubkey.bitlen/16];2169* BYTE exponent1[rsapubkey.bitlen/16];2170* BYTE exponent2[rsapubkey.bitlen/16];2171* BYTE coefficient[rsapubkey.bitlen/16];2172* BYTE privateExponent[rsapubkey.bitlen/8];2173*2174* This method generates such BLOBs from the key elements supplied.2175*/2176jbyteArray generateKeyBlob(2177JNIEnv *env,2178jint jKeyBitLength,2179jbyteArray jModulus,2180jbyteArray jPublicExponent,2181jbyteArray jPrivateExponent,2182jbyteArray jPrimeP,2183jbyteArray jPrimeQ,2184jbyteArray jExponentP,2185jbyteArray jExponentQ,2186jbyteArray jCrtCoefficient)2187{2188jsize jKeyByteLength = jKeyBitLength / 8;2189jsize jBlobLength;2190BOOL bGeneratePrivateKeyBlob;21912192// Determine whether to generate a public-key or a private-key BLOB2193if (jPrivateExponent != NULL &&2194jPrimeP != NULL &&2195jPrimeQ != NULL &&2196jExponentP != NULL &&2197jExponentQ != NULL &&2198jCrtCoefficient != NULL) {21992200bGeneratePrivateKeyBlob = TRUE;2201jBlobLength = sizeof(BLOBHEADER) +2202sizeof(RSAPUBKEY) +2203((jKeyBitLength / 8) * 4) +2204(jKeyBitLength / 16);22052206} else {2207bGeneratePrivateKeyBlob = FALSE;2208jBlobLength = sizeof(BLOBHEADER) +2209sizeof(RSAPUBKEY) +2210(jKeyBitLength / 8);2211}22122213jbyte* jBlobBytes = NULL;2214jbyte* jBlobElement;2215jbyteArray jBlob = NULL;2216jsize jElementLength;22172218__try {2219jBlobBytes = new (env) jbyte[jBlobLength];2220if (jBlobBytes == NULL) {2221__leave;2222}22232224BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;2225if (bGeneratePrivateKeyBlob) {2226pBlobHeader->bType = PRIVATEKEYBLOB; // 0x072227} else {2228pBlobHeader->bType = PUBLICKEYBLOB; // 0x062229}2230pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x022231pBlobHeader->reserved = 0; // 0x00002232pBlobHeader->aiKeyAlg = CALG_RSA_KEYX; // 0x0000a40022332234RSAPUBKEY *pRsaPubKey =2235(RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));2236if (bGeneratePrivateKeyBlob) {2237pRsaPubKey->magic = 0x32415352; // "RSA2"2238} else {2239pRsaPubKey->magic = 0x31415352; // "RSA1"2240}2241pRsaPubKey->bitlen = jKeyBitLength;2242pRsaPubKey->pubexp = 0; // init22432244// Sanity check2245jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);2246if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {2247ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);2248__leave;2249}2250// The length argument must be the smaller of jPublicExponentLength2251// and sizeof(pRsaPubKey->pubkey)2252if ((jElementLength = convertToLittleEndian(env, jPublicExponent,2253(jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) {2254__leave;2255}22562257// Modulus n2258jBlobElement =2259(jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));2260if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,2261jKeyByteLength)) < 0) {2262__leave;2263}22642265if (bGeneratePrivateKeyBlob) {2266// Prime p2267jBlobElement += jElementLength;2268if ((jElementLength = convertToLittleEndian(env, jPrimeP,2269jBlobElement, jKeyByteLength / 2)) < 0) {2270__leave;2271}22722273// Prime q2274jBlobElement += jElementLength;2275if ((jElementLength = convertToLittleEndian(env, jPrimeQ,2276jBlobElement, jKeyByteLength / 2)) < 0) {2277__leave;2278}22792280// Prime exponent p2281jBlobElement += jElementLength;2282if ((jElementLength = convertToLittleEndian(env, jExponentP,2283jBlobElement, jKeyByteLength / 2)) < 0) {2284__leave;2285}22862287// Prime exponent q2288jBlobElement += jElementLength;2289if ((jElementLength = convertToLittleEndian(env, jExponentQ,2290jBlobElement, jKeyByteLength / 2)) < 0) {2291__leave;2292}22932294// CRT coefficient2295jBlobElement += jElementLength;2296if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient,2297jBlobElement, jKeyByteLength / 2)) < 0) {2298__leave;2299}23002301// Private exponent2302jBlobElement += jElementLength;2303if ((jElementLength = convertToLittleEndian(env, jPrivateExponent,2304jBlobElement, jKeyByteLength)) < 0) {2305__leave;2306}2307}23082309if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {2310__leave;2311}2312env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);23132314}2315__finally2316{2317if (jBlobBytes)2318delete [] jBlobBytes;2319}23202321return jBlob;2322}23232324/*2325* Class: sun_security_mscapi_CKeyStore2326* Method: generateRSAPrivateKeyBlob2327* Signature: (I[B[B[B[B[B[B[B[B)[B2328*/2329JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob2330(JNIEnv *env, jobject clazz,2331jint jKeyBitLength,2332jbyteArray jModulus,2333jbyteArray jPublicExponent,2334jbyteArray jPrivateExponent,2335jbyteArray jPrimeP,2336jbyteArray jPrimeQ,2337jbyteArray jExponentP,2338jbyteArray jExponentQ,2339jbyteArray jCrtCoefficient)2340{2341return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,2342jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,2343jCrtCoefficient);2344}23452346/*2347* Class: sun_security_mscapi_CSignature_RSA2348* Method: generatePublicKeyBlob2349* Signature: (I[B[B)[B2350*/2351JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob2352(JNIEnv *env, jclass clazz,2353jint jKeyBitLength,2354jbyteArray jModulus,2355jbyteArray jPublicExponent)2356{2357return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,2358NULL, NULL, NULL, NULL, NULL, NULL);2359}23602361/*2362* Class: sun_security_mscapi_CKeyStore2363* Method: storePrivateKey2364* Signature: (Ljava/lang/String;[BLjava/lang/String;I)Lsun/security/mscapi/CPrivateKey;2365*/2366JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey2367(JNIEnv *env, jobject clazz, jstring alg, jbyteArray keyBlob,2368jstring keyContainerName, jint keySize)2369{2370HCRYPTPROV hCryptProv = NULL;2371HCRYPTKEY hKey = NULL;2372DWORD dwBlobLen;2373BYTE * pbKeyBlob = NULL;2374const char* pszKeyContainerName = NULL; // UUID2375jobject privateKey = NULL;23762377__try2378{2379if ((pszKeyContainerName =2380env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {2381__leave;2382}2383dwBlobLen = env->GetArrayLength(keyBlob);2384if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2385== NULL) {2386__leave;2387}23882389// Acquire a CSP context (create a new key container).2390if (::CryptAcquireContext( //deprecated2391&hCryptProv,2392pszKeyContainerName,2393NULL,2394PROV_RSA_FULL,2395CRYPT_NEWKEYSET) == FALSE)2396{2397ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2398__leave;2399}24002401// Import the private key2402if (::CryptImportKey( //deprecated2403hCryptProv,2404pbKeyBlob,2405dwBlobLen,24060,2407CRYPT_EXPORTABLE,2408&hKey) == FALSE)2409{2410ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2411__leave;2412}24132414// Get the method ID for the CPrivateKey constructor2415jclass clazzCPrivateKey =2416env->FindClass("sun/security/mscapi/CPrivateKey");2417if (clazzCPrivateKey == NULL) {2418__leave;2419}24202421jmethodID mNewCPrivateKey =2422env->GetStaticMethodID(clazzCPrivateKey, "of",2423"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPrivateKey;");2424if (mNewCPrivateKey == NULL) {2425__leave;2426}24272428// Create a new private key2429privateKey = env->CallStaticObjectMethod(clazzCPrivateKey, mNewCPrivateKey,2430alg, (jlong) hCryptProv, (jlong) hKey, keySize);24312432}2433__finally2434{2435//--------------------------------------------------------------------2436// Clean up.24372438if (pszKeyContainerName)2439env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);24402441if (pbKeyBlob)2442env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,2443JNI_ABORT);2444}24452446return privateKey;2447}24482449/*2450* Class: sun_security_mscapi_CSignature2451* Method: importECPublicKey2452* Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;2453*/2454JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey2455(JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)2456{2457BCRYPT_ALG_HANDLE hSignAlg = NULL;2458NCRYPT_KEY_HANDLE hTmpKey = NULL;2459DWORD dwBlobLen;2460BYTE * pbKeyBlob = NULL;2461jobject publicKey = NULL;24622463__try2464{2465dwBlobLen = env->GetArrayLength(keyBlob);2466if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2467== NULL) {2468__leave;2469}2470dump("NCryptImportKey", pbKeyBlob, dwBlobLen);2471NCRYPT_PROV_HANDLE hProv;2472SS_CHECK(NCryptOpenStorageProvider(2473&hProv, L"Microsoft Software Key Storage Provider", 0 ));2474SS_CHECK(NCryptImportKey(2475hProv,2476NULL,2477BCRYPT_ECCPUBLIC_BLOB,2478NULL,2479&hTmpKey,2480pbKeyBlob,2481dwBlobLen,24820));2483NCryptFreeObject( hProv );2484// Get the method ID for the CPublicKey constructor2485jclass clazzCPublicKey =2486env->FindClass("sun/security/mscapi/CPublicKey");2487if (clazzCPublicKey == NULL) {2488__leave;2489}24902491jmethodID mNewCPublicKey =2492env->GetStaticMethodID(clazzCPublicKey, "of",2493"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");2494if (mNewCPublicKey == NULL) {2495__leave;2496}24972498// Create a new public key2499publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,2500alg, (jlong) hTmpKey, (jlong) 0, keySize);2501}2502__finally2503{2504}25052506return publicKey;2507}25082509/*2510* Class: sun_security_mscapi_CSignature2511* Method: importPublicKey2512* Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;2513*/2514JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importPublicKey2515(JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)2516{2517HCRYPTPROV hCryptProv = NULL;2518HCRYPTKEY hKey = NULL;2519DWORD dwBlobLen;2520BYTE * pbKeyBlob = NULL;2521jobject publicKey = NULL;25222523__try2524{2525dwBlobLen = env->GetArrayLength(keyBlob);2526if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2527== NULL) {2528__leave;2529}25302531// Acquire a CSP context (create a new key container).2532// Prefer a PROV_RSA_AES CSP, when available, due to its support2533// for SHA-2-based signatures.2534if (::CryptAcquireContext( //deprecated2535&hCryptProv,2536NULL,2537NULL,2538PROV_RSA_AES,2539CRYPT_VERIFYCONTEXT) == FALSE)2540{2541// Failover to using the default CSP (PROV_RSA_FULL)25422543if (::CryptAcquireContext( //deprecated2544&hCryptProv,2545NULL,2546NULL,2547PROV_RSA_FULL,2548CRYPT_VERIFYCONTEXT) == FALSE)2549{2550ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2551__leave;2552}2553}25542555// Import the public key2556if (::CryptImportKey( //deprecated2557hCryptProv,2558pbKeyBlob,2559dwBlobLen,25600,2561CRYPT_EXPORTABLE,2562&hKey) == FALSE)2563{2564ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2565__leave;2566}25672568// Get the method ID for the CPublicKey constructor2569jclass clazzCPublicKey =2570env->FindClass("sun/security/mscapi/CPublicKey");2571if (clazzCPublicKey == NULL) {2572__leave;2573}25742575jmethodID mNewCPublicKey =2576env->GetStaticMethodID(clazzCPublicKey, "of",2577"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");2578if (mNewCPublicKey == NULL) {2579__leave;2580}25812582// Create a new public key2583publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,2584alg, (jlong) hCryptProv, (jlong) hKey, keySize);25852586}2587__finally2588{2589//--------------------------------------------------------------------2590// Clean up.25912592if (pbKeyBlob)2593env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,2594JNI_ABORT);2595}25962597return publicKey;2598}25992600} /* extern "C" */260126022603