Path: blob/master/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp
41149 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 "jni_util.h"32#include <stdlib.h>33#include <string.h>34#include <windows.h>35#include <BaseTsd.h>36#include <wincrypt.h>37#include <stdio.h>38#include <memory>39#include "sun_security_mscapi_CKey.h"40#include "sun_security_mscapi_CKeyStore.h"41#include "sun_security_mscapi_PRNG.h"42#include "sun_security_mscapi_CRSACipher.h"43#include "sun_security_mscapi_CKeyPairGenerator_RSA.h"44#include "sun_security_mscapi_CPublicKey.h"45#include "sun_security_mscapi_CPublicKey_CRSAPublicKey.h"46#include "sun_security_mscapi_CSignature.h"47#include "sun_security_mscapi_CSignature_RSA.h"4849#define OID_EKU_ANY "2.5.29.37.0"5051#define CERTIFICATE_PARSING_EXCEPTION \52"java/security/cert/CertificateParsingException"53#define INVALID_KEY_EXCEPTION \54"java/security/InvalidKeyException"55#define KEY_EXCEPTION "java/security/KeyException"56#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"57#define PROVIDER_EXCEPTION "java/security/ProviderException"58#define SIGNATURE_EXCEPTION "java/security/SignatureException"59#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"6061#define SS_CHECK(Status) \62if (Status != ERROR_SUCCESS) { \63ThrowException(env, SIGNATURE_EXCEPTION, Status); \64__leave; \65}6667#define PP(fmt, ...) \68if (trace) { \69fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \70fprintf(stdout, fmt, ##__VA_ARGS__); \71fprintf(stdout, "\n"); \72fflush(stdout); \73}7475extern "C" {7677char* trace = getenv("CAPI_TRACE");7879/*80* Declare library specific JNI_Onload entry if static build81*/82DEF_STATIC_JNI_OnLoad8384void showProperty(NCRYPT_HANDLE hKey);8586void dump(LPSTR title, PBYTE data, DWORD len)87{88if (trace) {89printf("==== %s ====\n", title);90for (DWORD i = 0; i < len; i+=16) {91printf("%04x: ", i);92for (int j = 0; j < 16; j++) {93if (j == 8) {94printf(" ");95}96if (i + j < len) {97printf("%02X ", *(data + i + j) & 0xff);98} else {99printf(" ");100}101}102for (int j = 0; j < 16; j++) {103if (i + j < len) {104int k = *(data + i + j) & 0xff;105if (k < 32 || k > 127) printf(".");106else printf("%c", (char)k);107}108}109printf("\n");110}111fflush(stdout);112}113}114115/*116* Throws an arbitrary Java exception with the given message.117*/118void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,119const char *szMessage)120{121jclass exceptionClazz = env->FindClass(exceptionName);122if (exceptionClazz != NULL) {123env->ThrowNew(exceptionClazz, szMessage);124}125}126127/*128* Throws an arbitrary Java exception.129* The exception message is a Windows system error message.130*/131void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)132{133char szMessage[1024];134szMessage[0] = '\0';135136DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,137NULL, szMessage, sizeof(szMessage), NULL);138if (res == 0) {139strcpy(szMessage, "Unknown error");140}141142ThrowExceptionWithMessage(env, exceptionName, szMessage);143}144145/*146* Overloaded 'operator new[]' variant, which will raise Java's147* OutOfMemoryError in the case of a failure.148*/149void* operator new[](std::size_t size, JNIEnv *env)150{151void* buf = ::operator new[](size, std::nothrow);152if (buf == NULL) {153ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,154"Native memory allocation failed");155}156return buf;157}158159/*160* Maps the name of a hash algorithm to an algorithm identifier.161*/162ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {163164const char* pszHashAlgorithm = NULL;165ALG_ID algId = 0;166167if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))168== NULL) {169return algId;170}171172if ((strcmp("SHA", pszHashAlgorithm) == 0) ||173(strcmp("SHA1", pszHashAlgorithm) == 0) ||174(strcmp("SHA-1", pszHashAlgorithm) == 0)) {175176algId = CALG_SHA1;177} else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {178algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5179} else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {180algId = CALG_SHA_256;181} else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {182algId = CALG_SHA_384;183} else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {184algId = CALG_SHA_512;185} else if (strcmp("MD5", pszHashAlgorithm) == 0) {186algId = CALG_MD5;187} else if (strcmp("MD2", pszHashAlgorithm) == 0) {188algId = CALG_MD2;189}190191if (pszHashAlgorithm)192env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);193194return algId;195}196197/*198* Maps the name of a hash algorithm to a CNG Algorithm Identifier.199*/200LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {201202const char* pszHashAlgorithm = NULL;203LPCWSTR id = NULL;204205if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))206== NULL) {207return id;208}209210if ((strcmp("SHA", pszHashAlgorithm) == 0) ||211(strcmp("SHA1", pszHashAlgorithm) == 0) ||212(strcmp("SHA-1", pszHashAlgorithm) == 0)) {213214id = BCRYPT_SHA1_ALGORITHM;215} else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {216id = BCRYPT_SHA256_ALGORITHM;217} else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {218id = BCRYPT_SHA384_ALGORITHM;219} else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {220id = BCRYPT_SHA512_ALGORITHM;221}222223if (pszHashAlgorithm)224env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);225226return id;227}228229/*230* Returns a certificate chain context given a certificate context and key231* usage identifier.232*/233bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)234{235CERT_ENHKEY_USAGE EnhkeyUsage;236CERT_USAGE_MATCH CertUsage;237CERT_CHAIN_PARA ChainPara;238DWORD dwFlags = 0;239LPSTR szUsageIdentifierArray[1];240241szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;242EnhkeyUsage.cUsageIdentifier = 1;243EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;244CertUsage.dwType = USAGE_MATCH_TYPE_AND;245CertUsage.Usage = EnhkeyUsage;246ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);247ChainPara.RequestedUsage=CertUsage;248249// Build a chain using CertGetCertificateChain250// and the certificate retrieved.251return (::CertGetCertificateChain(NULL, // use the default chain engine252pCertContext, // pointer to the end certificate253NULL, // use the default time254NULL, // search no additional stores255&ChainPara, // use AND logic and enhanced key usage256// as indicated in the ChainPara257// data structure258dwFlags,259NULL, // currently reserved260ppChainContext) == TRUE); // return a pointer to the chain created261}262263264/////////////////////////////////////////////////////////////////////////////265//266267/*268* Class: sun_security_mscapi_PRNG269* Method: getContext270* Signature: ()J271*/272JNIEXPORT jlong JNICALL Java_sun_security_mscapi_PRNG_getContext273(JNIEnv *env, jclass clazz) {274HCRYPTPROV hCryptProv = NULL;275if(::CryptAcquireContext( //deprecated276&hCryptProv,277NULL,278NULL,279PROV_RSA_FULL,280CRYPT_VERIFYCONTEXT) == FALSE)281{282ThrowException(env, PROVIDER_EXCEPTION, GetLastError());283}284return hCryptProv;285}286287288/*289* Class: sun_security_mscapi_PRNG290* Method: releaseContext291* Signature: (J)V292*/293JNIEXPORT void JNICALL Java_sun_security_mscapi_PRNG_releaseContext294(JNIEnv *env, jclass clazz, jlong ctxt) {295if (ctxt) {296::CryptReleaseContext((HCRYPTPROV)ctxt, 0); //deprecated297}298}299300301/*302* Class: sun_security_mscapi_PRNG303* Method: generateSeed304* Signature: (JI[B)[B305*/306JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed307(JNIEnv *env, jclass clazz, jlong ctxt, jint length, jbyteArray seed)308{309310HCRYPTPROV hCryptProv = (HCRYPTPROV)ctxt;311jbyte* reseedBytes = NULL;312jbyte* seedBytes = NULL;313jbyteArray result = NULL;314315__try316{317/*318* If length is negative then use the supplied seed to re-seed the319* generator and return null.320* If length is non-zero then generate a new seed according to the321* requested length and return the new seed.322* If length is zero then overwrite the supplied seed with a new323* seed of the same length and return the seed.324*/325if (length < 0) {326length = env->GetArrayLength(seed);327if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {328__leave;329}330331if (::CryptGenRandom( //deprecated332hCryptProv,333length,334(BYTE *) reseedBytes) == FALSE) {335336ThrowException(env, PROVIDER_EXCEPTION, GetLastError());337__leave;338}339340result = NULL;341342} else {343344if (length > 0) {345seed = env->NewByteArray(length);346if (seed == NULL) {347__leave;348}349} else {350length = env->GetArrayLength(seed);351}352353if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {354__leave;355}356357if (::CryptGenRandom( //deprecated358hCryptProv,359length,360(BYTE *) seedBytes) == FALSE) {361362ThrowException(env, PROVIDER_EXCEPTION, GetLastError());363__leave;364}365366result = seed; // seed will be updated when seedBytes gets released367}368}369__finally370{371//--------------------------------------------------------------------372// Clean up.373374if (reseedBytes)375env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);376377if (seedBytes)378env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig379}380381return result;382}383384385/*386* Class: sun_security_mscapi_CKeyStore387* Method: loadKeysOrCertificateChains388* Signature: (Ljava/lang/String;)V389*/390JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains391(JNIEnv *env, jobject obj, jstring jCertStoreName)392{393/**394* Certificate in cert store has enhanced key usage extension395* property (or EKU property) that is not part of the certificate itself. To determine396* if the certificate should be returned, both the enhanced key usage in certificate397* extension block and the extension property stored along with the certificate in398* certificate store should be examined. Otherwise, we won't be able to determine399* the proper key usage from the Java side because the information is not stored as400* part of the encoded certificate.401*/402403const char* pszCertStoreName = NULL;404HCERTSTORE hCertStore = NULL;405PCCERT_CONTEXT pCertContext = NULL;406char* pszNameString = NULL; // certificate's friendly name407DWORD cchNameString = 0;408409410__try411{412// Open a system certificate store.413if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))414== NULL) {415__leave;416}417if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))418== NULL) {419420ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());421__leave;422}423424// Determine clazz and method ID to generate certificate425jclass clazzArrayList = env->FindClass("java/util/ArrayList");426if (clazzArrayList == NULL) {427__leave;428}429430jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");431if (mNewArrayList == NULL) {432__leave;433}434435jclass clazzOfThis = env->GetObjectClass(obj);436if (clazzOfThis == NULL) {437__leave;438}439440jmethodID mGenCert = env->GetMethodID(clazzOfThis,441"generateCertificate",442"([BLjava/util/Collection;)V");443if (mGenCert == NULL) {444__leave;445}446447// Determine method ID to generate certificate chain448jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,449"generateCertificateChain",450"(Ljava/lang/String;Ljava/util/Collection;)V");451if (mGenCertChain == NULL) {452__leave;453}454455// Determine method ID to generate RSA certificate chain456jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,457"generateKeyAndCertificateChain",458"(ZLjava/lang/String;JJILjava/util/Collection;)V");459if (mGenKeyAndCertChain == NULL) {460__leave;461}462463// Use CertEnumCertificatesInStore to get the certificates464// from the open store. pCertContext must be reset to465// NULL to retrieve the first certificate in the store.466while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))467{468PP("--------------------------");469// Check if private key available - client authentication certificate470// must have private key available.471HCRYPTPROV hCryptProv = NULL;472DWORD dwKeySpec = 0;473HCRYPTKEY hUserKey = NULL;474BOOL bCallerFreeProv = FALSE;475BOOL bHasNoPrivateKey = FALSE;476DWORD dwPublicKeyLength = 0;477478// First, probe it silently479if (::CryptAcquireCertificatePrivateKey(pCertContext,480CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,481&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE482&& GetLastError() != NTE_SILENT_CONTEXT)483{484PP("bHasNoPrivateKey = TRUE!");485bHasNoPrivateKey = TRUE;486}487else488{489if (bCallerFreeProv == TRUE) {490::CryptReleaseContext(hCryptProv, NULL); // deprecated491bCallerFreeProv = FALSE;492}493494// Second, acquire the key normally (not silently)495if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,496&hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)497{498PP("bHasNoPrivateKey = TRUE!!");499bHasNoPrivateKey = TRUE;500}501else502{503if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {504PP("CNG %I64d", (__int64)hCryptProv);505} else {506// Private key is available507BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated508509// Skip certificate if cannot find private key510if (bGetUserKey == FALSE) {511if (bCallerFreeProv)512::CryptReleaseContext(hCryptProv, NULL); // deprecated513continue;514}515516// Set cipher mode to ECB517DWORD dwCipherMode = CRYPT_MODE_ECB;518::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated519PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);520}521// If the private key is present in smart card, we may not be able to522// determine the key length by using the private key handle. However,523// since public/private key pairs must have the same length, we could524// determine the key length of the private key by using the public key525// in the certificate.526dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,527&(pCertContext->pCertInfo->SubjectPublicKeyInfo));528}529}530PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;531532// Build certificate chain by using system certificate store.533// Add cert chain into collection for any key usage.534//535if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))536{537for (DWORD i = 0; i < pCertChainContext->cChain; i++)538{539// Found cert chain540PCERT_SIMPLE_CHAIN rgpChain =541pCertChainContext->rgpChain[i];542543// Create ArrayList to store certs in each chain544jobject jArrayList =545env->NewObject(clazzArrayList, mNewArrayList);546if (jArrayList == NULL) {547__leave;548}549550// Cleanup the previous allocated name551if (pszNameString) {552delete [] pszNameString;553pszNameString = NULL;554}555556for (unsigned int j=0; j < rgpChain->cElement; j++)557{558PCERT_CHAIN_ELEMENT rgpElement =559rgpChain->rgpElement[j];560PCCERT_CONTEXT pc = rgpElement->pCertContext;561562// Retrieve the friendly name of the first certificate563// in the chain564if (j == 0) {565566// If the cert's name cannot be retrieved then567// pszNameString remains set to NULL.568// (An alias name will be generated automatically569// when storing this cert in the keystore.)570571// Get length of friendly name572if ((cchNameString = CertGetNameString(pc,573CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,574NULL, 0)) > 1) {575576// Found friendly name577pszNameString = new (env) char[cchNameString];578if (pszNameString == NULL) {579__leave;580}581582CertGetNameString(pc,583CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,584pszNameString, cchNameString);585}586}587588BYTE* pbCertEncoded = pc->pbCertEncoded;589DWORD cbCertEncoded = pc->cbCertEncoded;590591// Allocate and populate byte array592jbyteArray byteArray = env->NewByteArray(cbCertEncoded);593if (byteArray == NULL) {594__leave;595}596env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,597(jbyte*) pbCertEncoded);598599// Generate certificate from byte array and store into600// cert collection601env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);602}603604// Usually pszNameString should be non-NULL. It's either605// the friendly name or an element from the subject name606// or SAN.607if (pszNameString)608{609PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);610if (bHasNoPrivateKey)611{612// Generate certificate chain and store into cert chain613// collection614jstring name = env->NewStringUTF(pszNameString);615if (name == NULL) {616__leave;617}618env->CallVoidMethod(obj, mGenCertChain,619name,620jArrayList);621}622else623{624if (hUserKey) {625// Only accept RSA for CAPI626DWORD dwData = CALG_RSA_KEYX;627DWORD dwSize = sizeof(DWORD);628::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated629&dwSize, NULL);630if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)631{632// Generate RSA certificate chain and store into cert633// chain collection634jstring name = env->NewStringUTF(pszNameString);635if (name == NULL) {636__leave;637}638env->CallVoidMethod(obj, mGenKeyAndCertChain,6391,640name,641(jlong) hCryptProv, (jlong) hUserKey,642dwPublicKeyLength, jArrayList);643}644} else {645// Only accept EC for CNG646BYTE buffer[32];647DWORD len = 0;648if (::NCryptGetProperty(649hCryptProv, NCRYPT_ALGORITHM_PROPERTY,650(PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {651jstring name = env->NewStringUTF(pszNameString);652if (name == NULL) {653__leave;654}655if (buffer[0] == 'E' && buffer[2] == 'C'656&& (dwPublicKeyLength == 256657|| dwPublicKeyLength == 384658|| dwPublicKeyLength == 521)) {659env->CallVoidMethod(obj, mGenKeyAndCertChain,6600,661name,662(jlong) hCryptProv, (jlong) 0,663dwPublicKeyLength, jArrayList);664} else if (buffer[0] == 'R' && buffer[2] == 'S'665&& buffer[4] == 'A') {666env->CallVoidMethod(obj, mGenKeyAndCertChain,6671,668name,669(jlong) hCryptProv, (jlong) 0,670dwPublicKeyLength, jArrayList);671} else {672dump("Unknown NCRYPT_ALGORITHM_PROPERTY", buffer, len);673}674}675}676}677}678}679680// Free cert chain681if (pCertChainContext)682::CertFreeCertificateChain(pCertChainContext);683} else {684PP("GetCertificateChain failed %d", GetLastError());685}686}687}688__finally689{690if (hCertStore)691::CertCloseStore(hCertStore, 0);692693if (pszCertStoreName)694env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);695696if (pszNameString)697delete [] pszNameString;698}699}700701702/*703* Class: sun_security_mscapi_CKey704* Method: cleanUp705* Signature: (JJ)V706*/707JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp708(JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)709{710if (hCryptKey == NULL && hCryptProv != NULL) {711NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);712} else {713if (hCryptKey != NULL)714::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated715716if (hCryptProv != NULL)717::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated718}719}720721/*722* Class: sun_security_mscapi_CSignature723* Method: signHash724* Signature: (Z[BILjava/lang/String;JJ)[B725*/726JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash727(JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,728jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,729jlong hCryptKey)730{731HCRYPTHASH hHash = NULL;732jbyte* pHashBuffer = NULL;733jbyte* pSignedHashBuffer = NULL;734jbyteArray jSignedHash = NULL;735HCRYPTPROV hCryptProvAlt = NULL;736737__try738{739// Map hash algorithm740ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);741742// Acquire a hash object handle.743if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) //deprecated744{745// Failover to using the PROV_RSA_AES CSP746747DWORD cbData = 256;748BYTE pbData[256];749pbData[0] = '\0';750751// Get name of the key container752::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated753(BYTE *)pbData, &cbData, 0);754755// Acquire an alternative CSP handle756if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated757PROV_RSA_AES, 0) == FALSE)758{759760ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());761__leave;762}763764// Acquire a hash object handle.765if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, //deprecated766&hHash) == FALSE)767{768ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());769__leave;770}771}772773// Copy hash from Java to native buffer774pHashBuffer = new (env) jbyte[jHashSize];775if (pHashBuffer == NULL) {776__leave;777}778env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);779780// Set hash value in the hash object781if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) //deprecated782{783ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());784__leave;785}786787// Determine key spec.788DWORD dwKeySpec = AT_SIGNATURE;789ALG_ID dwAlgId;790DWORD dwAlgIdLen = sizeof(ALG_ID);791792if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated793ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());794__leave;795796}797if (CALG_RSA_KEYX == dwAlgId) {798dwKeySpec = AT_KEYEXCHANGE;799}800801// Determine size of buffer802DWORD dwBufLen = 0;803DWORD dwFlags = 0;804805if (noHashOID == JNI_TRUE) {806dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature807}808809if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) //deprecated810{811ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());812__leave;813}814815pSignedHashBuffer = new (env) jbyte[dwBufLen];816if (pSignedHashBuffer == NULL) {817__leave;818}819if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) //deprecated820{821ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());822__leave;823}824825// Create new byte array826jbyteArray temp = env->NewByteArray(dwBufLen);827if (temp == NULL) {828__leave;829}830831// Copy data from native buffer832env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);833834jSignedHash = temp;835}836__finally837{838if (pSignedHashBuffer)839delete [] pSignedHashBuffer;840841if (pHashBuffer)842delete [] pHashBuffer;843844if (hHash)845::CryptDestroyHash(hHash); //deprecated846847if (hCryptProvAlt)848::CryptReleaseContext(hCryptProvAlt, 0); // deprecated849}850851return jSignedHash;852}853854/*855* Class: sun_security_mscapi_CSignature856* Method: signCngHash857* Signature: (I[BIILjava/lang/String;JJ)[B858*/859JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash860(JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,861jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,862jlong hCryptKey)863{864jbyteArray jSignedHash = NULL;865866jbyte* pHashBuffer = NULL;867jbyte* pSignedHashBuffer = NULL;868NCRYPT_KEY_HANDLE hk = NULL;869870__try871{872if (hCryptKey == 0) {873hk = (NCRYPT_KEY_HANDLE)hCryptProv;874} else {875SS_CHECK(::NCryptTranslateHandle(876NULL,877&hk,878(HCRYPTPROV)hCryptProv,879(HCRYPTKEY)hCryptKey,880NULL,8810));882}883884// Copy hash from Java to native buffer885pHashBuffer = new (env) jbyte[jHashSize];886if (pHashBuffer == NULL) {887__leave;888}889env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);890891VOID* param;892DWORD dwFlags;893894switch (type) {895case 0:896param = NULL;897dwFlags = 0;898break;899case 1:900BCRYPT_PKCS1_PADDING_INFO pkcs1Info;901if (jHashAlgorithm) {902pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);903if (pkcs1Info.pszAlgId == NULL) {904ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,905"Unrecognised hash algorithm");906__leave;907}908} else {909pkcs1Info.pszAlgId = NULL;910}911param = &pkcs1Info;912dwFlags = BCRYPT_PAD_PKCS1;913break;914case 2:915BCRYPT_PSS_PADDING_INFO pssInfo;916pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);917pssInfo.cbSalt = saltLen;918if (pssInfo.pszAlgId == NULL) {919ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,920"Unrecognised hash algorithm");921__leave;922}923param = &pssInfo;924dwFlags = BCRYPT_PAD_PSS;925break;926}927928DWORD jSignedHashSize = 0;929SS_CHECK(::NCryptSignHash(930hk,931param,932(BYTE*)pHashBuffer, jHashSize,933NULL, 0, &jSignedHashSize,934dwFlags935));936937pSignedHashBuffer = new (env) jbyte[jSignedHashSize];938if (pSignedHashBuffer == NULL) {939__leave;940}941942SS_CHECK(::NCryptSignHash(943hk,944param,945(BYTE*)pHashBuffer, jHashSize,946(BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,947dwFlags948));949950// Create new byte array951jbyteArray temp = env->NewByteArray(jSignedHashSize);952if (temp == NULL) {953__leave;954}955956// Copy data from native buffer957env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);958959jSignedHash = temp;960}961__finally962{963if (pSignedHashBuffer)964delete [] pSignedHashBuffer;965966if (pHashBuffer)967delete [] pHashBuffer;968969if (hCryptKey != 0 && hk != NULL)970::NCryptFreeObject(hk);971}972973return jSignedHash;974}975976/*977* Class: sun_security_mscapi_CSignature978* Method: verifySignedHash979* Signature: ([BIL/java/lang/String;[BIJJ)Z980*/981JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash982(JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,983jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,984jlong hCryptProv, jlong hCryptKey)985{986HCRYPTHASH hHash = NULL;987jbyte* pHashBuffer = NULL;988jbyte* pSignedHashBuffer = NULL;989DWORD dwSignedHashBufferLen = jSignedHashSize;990jboolean result = JNI_FALSE;991HCRYPTPROV hCryptProvAlt = NULL;992993__try994{995// Map hash algorithm996ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);997998// Acquire a hash object handle.999if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)1000== FALSE)1001{1002// Failover to using the PROV_RSA_AES CSP10031004DWORD cbData = 256;1005BYTE pbData[256];1006pbData[0] = '\0';10071008// Get name of the key container1009::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated1010(BYTE *)pbData, &cbData, 0);10111012// Acquire an alternative CSP handle1013if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated1014PROV_RSA_AES, 0) == FALSE)1015{10161017ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());1018__leave;1019}10201021// Acquire a hash object handle.1022if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,1023&hHash) == FALSE)1024{1025ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());1026__leave;1027}1028}10291030// Copy hash and signedHash from Java to native buffer1031pHashBuffer = new (env) jbyte[jHashSize];1032if (pHashBuffer == NULL) {1033__leave;1034}1035env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);10361037pSignedHashBuffer = new (env) jbyte[jSignedHashSize];1038if (pSignedHashBuffer == NULL) {1039__leave;1040}1041env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,1042pSignedHashBuffer);10431044// Set hash value in the hash object1045if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) //deprecated1046== FALSE)1047{1048ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());1049__leave;1050}10511052// For RSA, the hash encryption algorithm is normally the same as the1053// public key algorithm, so AT_SIGNATURE is used.10541055// Verify the signature1056if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, //deprecated1057dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)1058{1059result = JNI_TRUE;1060}1061}10621063__finally1064{1065if (pSignedHashBuffer)1066delete [] pSignedHashBuffer;10671068if (pHashBuffer)1069delete [] pHashBuffer;10701071if (hHash)1072::CryptDestroyHash(hHash); //deprecated10731074if (hCryptProvAlt)1075::CryptReleaseContext(hCryptProvAlt, 0); // deprecated1076}10771078return result;1079}10801081/*1082* Class: sun_security_mscapi_CSignature1083* Method: verifyCngSignedHash1084* Signature: (I[BI[BIILjava/lang/String;JJ)Z1085*/1086JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash1087(JNIEnv *env, jclass clazz, jint type,1088jbyteArray jHash, jint jHashSize,1089jbyteArray jSignedHash, jint jSignedHashSize,1090jint saltLen, jstring jHashAlgorithm,1091jlong hCryptProv, jlong hCryptKey)1092{1093jbyte* pHashBuffer = NULL;1094jbyte* pSignedHashBuffer = NULL;1095jboolean result = JNI_FALSE;1096NCRYPT_KEY_HANDLE hk = NULL;10971098__try1099{1100if (hCryptKey == 0) {1101hk = (NCRYPT_KEY_HANDLE)hCryptProv;1102} else {1103SS_CHECK(::NCryptTranslateHandle(1104NULL,1105&hk,1106(HCRYPTPROV)hCryptProv,1107(HCRYPTKEY)hCryptKey,1108NULL,11090));1110}11111112// Copy hash and signedHash from Java to native buffer1113pHashBuffer = new (env) jbyte[jHashSize];1114if (pHashBuffer == NULL) {1115__leave;1116}1117env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);11181119pSignedHashBuffer = new (env) jbyte[jSignedHashSize];1120if (pSignedHashBuffer == NULL) {1121__leave;1122}1123env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,1124pSignedHashBuffer);11251126VOID* param;1127DWORD dwFlags;11281129switch (type) {1130case 0:1131param = NULL;1132dwFlags = 0;1133break;1134case 1:1135BCRYPT_PKCS1_PADDING_INFO pkcs1Info;1136if (jHashAlgorithm) {1137pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);1138if (pkcs1Info.pszAlgId == NULL) {1139ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,1140"Unrecognised hash algorithm");1141__leave;1142}1143} else {1144pkcs1Info.pszAlgId = NULL;1145}1146param = &pkcs1Info;1147dwFlags = NCRYPT_PAD_PKCS1_FLAG;1148break;1149case 2:1150BCRYPT_PSS_PADDING_INFO pssInfo;1151pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);1152pssInfo.cbSalt = saltLen;1153if (pssInfo.pszAlgId == NULL) {1154ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,1155"Unrecognised hash algorithm");1156__leave;1157}1158param = &pssInfo;1159dwFlags = NCRYPT_PAD_PSS_FLAG;1160break;1161}11621163if (::NCryptVerifySignature(hk, param,1164(BYTE *) pHashBuffer, jHashSize,1165(BYTE *) pSignedHashBuffer, jSignedHashSize,1166dwFlags) == ERROR_SUCCESS)1167{1168result = JNI_TRUE;1169}1170}11711172__finally1173{1174if (pSignedHashBuffer)1175delete [] pSignedHashBuffer;11761177if (pHashBuffer)1178delete [] pHashBuffer;11791180if (hCryptKey != 0 && hk != NULL)1181::NCryptFreeObject(hk);1182}11831184return result;1185}11861187#define DUMP_PROP(p) \1188if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \1189sprintf(header, "%s %ls", #p, p); \1190dump(header, buffer, len); \1191}11921193#define EXPORT_BLOB(p) \1194desc.cBuffers = 0; \1195if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \1196sprintf(header, "%s %ls (%ld)", #p, p, desc.cBuffers); \1197dump(header, buffer, len); \1198for (int i = 0; i < (int)desc.cBuffers; i++) { \1199sprintf(header, "desc %ld", desc.pBuffers[i].BufferType); \1200dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \1201} \1202}12031204void showProperty(NCRYPT_HANDLE hKey) {1205char header[100];1206BYTE buffer[8192];1207DWORD len = 9;1208NCryptBufferDesc desc;1209DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);1210DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);1211DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);1212DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);1213DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);1214DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);1215DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);1216DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);1217DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);1218DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);1219DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);1220DUMP_PROP(NCRYPT_LENGTH_PROPERTY);1221DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);1222DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);1223DUMP_PROP(NCRYPT_NAME_PROPERTY);1224DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);1225DUMP_PROP(NCRYPT_PIN_PROPERTY);1226DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);1227DUMP_PROP(NCRYPT_READER_PROPERTY);1228DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);1229DUMP_PROP(NCRYPT_SCARD_PIN_ID);1230DUMP_PROP(NCRYPT_SCARD_PIN_INFO);1231DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);1232DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);1233DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);1234DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);1235DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);1236DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);1237DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);1238DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);1239DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);1240DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);1241DUMP_PROP(NCRYPT_VERSION_PROPERTY);1242DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);12431244EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);1245EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);1246EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);1247EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);1248EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);1249EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);1250EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);1251EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);1252EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);1253EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);1254EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);1255EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);1256EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);1257EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);1258EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);1259EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);1260EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);1261EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);1262EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);1263EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);1264//EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);1265//EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);1266BCryptBuffer bb;1267bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;1268bb.cbBuffer = 18;1269bb.pvBuffer = L"changeit";1270BCryptBufferDesc bbd;1271bbd.ulVersion = 0;1272bbd.cBuffers = 1;1273bbd.pBuffers = &bb;1274if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,1275(PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {1276sprintf(header, "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);1277dump(header, buffer, len);1278}1279EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);1280}12811282/*1283* Class: sun_security_mscapi_CKeyPairGenerator_RSA1284* Method: generateCKeyPair1285* Signature: (Ljava/lang/String;ILjava/lang/String;)Lsun/security/mscapi/CKeyPair;1286*/1287JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair1288(JNIEnv *env, jclass clazz, jstring alg, jint keySize, jstring keyContainerName)1289{1290HCRYPTPROV hCryptProv = NULL;1291HCRYPTKEY hKeyPair;1292DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;1293jobject keypair = NULL;1294const char* pszKeyContainerName = NULL; // UUID12951296__try1297{1298if ((pszKeyContainerName =1299env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {1300__leave;1301}13021303// Acquire a CSP context (create a new key container).1304// Prefer a PROV_RSA_AES CSP, when available, due to its support1305// for SHA-2-based signatures.1306if (::CryptAcquireContext( //deprecated1307&hCryptProv,1308pszKeyContainerName,1309NULL,1310PROV_RSA_AES,1311CRYPT_NEWKEYSET) == FALSE)1312{1313// Failover to using the default CSP (PROV_RSA_FULL)13141315if (::CryptAcquireContext( //deprecated1316&hCryptProv,1317pszKeyContainerName,1318NULL,1319PROV_RSA_FULL,1320CRYPT_NEWKEYSET) == FALSE)1321{1322ThrowException(env, KEY_EXCEPTION, GetLastError());1323__leave;1324}1325}13261327// Generate an keypair1328if(::CryptGenKey( //deprecated1329hCryptProv,1330AT_KEYEXCHANGE,1331dwFlags,1332&hKeyPair) == FALSE)1333{1334ThrowException(env, KEY_EXCEPTION, GetLastError());1335__leave;1336}13371338// Get the method ID for the CKeyPair constructor1339jclass clazzCKeyPair =1340env->FindClass("sun/security/mscapi/CKeyPair");1341if (clazzCKeyPair == NULL) {1342__leave;1343}13441345jmethodID mNewCKeyPair =1346env->GetMethodID(clazzCKeyPair, "<init>", "(Ljava/lang/String;JJI)V");1347if (mNewCKeyPair == NULL) {1348__leave;1349}13501351// Create a new keypair1352keypair = env->NewObject(clazzCKeyPair, mNewCKeyPair,1353alg, (jlong) hCryptProv, (jlong) hKeyPair, keySize);13541355}1356__finally1357{1358//--------------------------------------------------------------------1359// Clean up.13601361if (pszKeyContainerName)1362env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);1363}13641365return keypair;1366}13671368/*1369* Class: sun_security_mscapi_CKey1370* Method: getContainerName1371* Signature: (J)Ljava/lang/String;1372*/1373JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getContainerName1374(JNIEnv *env, jclass jclazz, jlong hCryptProv)1375{1376DWORD cbData = 256;1377BYTE pbData[256];1378pbData[0] = '\0';13791380::CryptGetProvParam( //deprecated1381(HCRYPTPROV)hCryptProv,1382PP_CONTAINER,1383(BYTE *)pbData,1384&cbData,13850);13861387return env->NewStringUTF((const char*)pbData);1388}13891390/*1391* Class: sun_security_mscapi_CKey1392* Method: getKeyType1393* Signature: (J)Ljava/lang/String;1394*/1395JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getKeyType1396(JNIEnv *env, jclass jclazz, jlong hCryptKey)1397{1398ALG_ID dwAlgId;1399DWORD dwAlgIdLen = sizeof(ALG_ID);14001401if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated14021403if (CALG_RSA_SIGN == dwAlgId) {1404return env->NewStringUTF("Signature");14051406} else if (CALG_RSA_KEYX == dwAlgId) {1407return env->NewStringUTF("Exchange");14081409} else {1410char buffer[64];1411if (sprintf(buffer, "%lu", dwAlgId)) {1412return env->NewStringUTF(buffer);1413}1414}1415}14161417return env->NewStringUTF("<Unknown>");1418}14191420/*1421* Class: sun_security_mscapi_CKeyStore1422* Method: storeCertificate1423* Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V1424*/1425JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_storeCertificate1426(JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,1427jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,1428jlong hCryptKey)1429{1430const char* pszCertStoreName = NULL;1431HCERTSTORE hCertStore = NULL;1432PCCERT_CONTEXT pCertContext = NULL;1433PWCHAR pszCertAliasName = NULL;1434jbyte* pbCertEncoding = NULL;1435const jchar* jCertAliasChars = NULL;1436const char* pszContainerName = NULL;1437const char* pszProviderName = NULL;1438WCHAR * pwszContainerName = NULL;1439WCHAR * pwszProviderName = NULL;14401441__try1442{1443// Open a system certificate store.1444if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))1445== NULL) {1446__leave;1447}1448if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {1449ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1450__leave;1451}14521453// Copy encoding from Java to native buffer1454pbCertEncoding = new (env) jbyte[jCertEncodingSize];1455if (pbCertEncoding == NULL) {1456__leave;1457}1458env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);14591460// Create a certificate context from the encoded cert1461if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,1462(BYTE*) pbCertEncoding, jCertEncodingSize))) {14631464ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());1465__leave;1466}14671468// Set the certificate's friendly name1469int size = env->GetStringLength(jCertAliasName);1470pszCertAliasName = new (env) WCHAR[size + 1];1471if (pszCertAliasName == NULL) {1472__leave;1473}14741475jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);1476if (jCertAliasChars == NULL) {1477__leave;1478}1479memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));1480pszCertAliasName[size] = 0; // append the string terminator14811482CRYPT_DATA_BLOB friendlyName = {1483sizeof(WCHAR) * (size + 1),1484(BYTE *) pszCertAliasName1485};14861487env->ReleaseStringChars(jCertAliasName, jCertAliasChars);14881489if (! ::CertSetCertificateContextProperty(pCertContext,1490CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {14911492ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1493__leave;1494}14951496// Attach the certificate's private key (if supplied)1497if (hCryptProv != 0 && hCryptKey != 0) {14981499CRYPT_KEY_PROV_INFO keyProviderInfo;1500DWORD dwDataLen;15011502// Get the name of the key container1503if (! ::CryptGetProvParam( //deprecated1504(HCRYPTPROV) hCryptProv,1505PP_CONTAINER,1506NULL,1507&dwDataLen,15080)) {15091510ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1511__leave;1512}15131514pszContainerName = new (env) char[dwDataLen];1515if (pszContainerName == NULL) {1516__leave;1517}15181519if (! ::CryptGetProvParam( //deprecated1520(HCRYPTPROV) hCryptProv,1521PP_CONTAINER,1522(BYTE *) pszContainerName,1523&dwDataLen,15240)) {15251526ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1527__leave;1528}15291530// Convert to a wide char string1531pwszContainerName = new (env) WCHAR[dwDataLen];1532if (pwszContainerName == NULL) {1533__leave;1534}15351536if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {1537ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1538__leave;1539}15401541// Set the name of the key container1542keyProviderInfo.pwszContainerName = pwszContainerName;154315441545// Get the name of the provider1546if (! ::CryptGetProvParam( //deprecated1547(HCRYPTPROV) hCryptProv,1548PP_NAME,1549NULL,1550&dwDataLen,15510)) {15521553ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1554__leave;1555}15561557pszProviderName = new (env) char[dwDataLen];1558if (pszProviderName == NULL) {1559__leave;1560}15611562if (! ::CryptGetProvParam( //deprecated1563(HCRYPTPROV) hCryptProv,1564PP_NAME,1565(BYTE *) pszProviderName,1566&dwDataLen,15670)) {15681569ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1570__leave;1571}15721573// Convert to a wide char string1574pwszProviderName = new (env) WCHAR[dwDataLen];1575if (pwszProviderName == NULL) {1576__leave;1577}15781579if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {1580ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1581__leave;1582}15831584// Set the name of the provider1585keyProviderInfo.pwszProvName = pwszProviderName;15861587// Get and set the type of the provider1588if (! ::CryptGetProvParam( //deprecated1589(HCRYPTPROV) hCryptProv,1590PP_PROVTYPE,1591(LPBYTE) &keyProviderInfo.dwProvType,1592&dwDataLen,15930)) {15941595ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1596__leave;1597}15981599// Set no provider flags1600keyProviderInfo.dwFlags = 0;16011602// Set no provider parameters1603keyProviderInfo.cProvParam = 0;1604keyProviderInfo.rgProvParam = NULL;16051606// Get the key's algorithm ID1607if (! ::CryptGetKeyParam( //deprecated1608(HCRYPTKEY) hCryptKey,1609KP_ALGID,1610(LPBYTE) &keyProviderInfo.dwKeySpec,1611&dwDataLen,16120)) {16131614ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1615__leave;1616}1617// Set the key spec (using the algorithm ID).1618switch (keyProviderInfo.dwKeySpec) {1619case CALG_RSA_KEYX:1620case CALG_DH_SF:1621keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;1622break;16231624case CALG_RSA_SIGN:1625case CALG_DSS_SIGN:1626keyProviderInfo.dwKeySpec = AT_SIGNATURE;1627break;16281629default:1630ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);1631__leave;1632}16331634if (! ::CertSetCertificateContextProperty(pCertContext,1635CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {16361637ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1638__leave;1639}1640}16411642// Import encoded certificate1643if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,1644CERT_STORE_ADD_REPLACE_EXISTING, NULL))1645{1646ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1647__leave;1648}16491650}1651__finally1652{1653//--------------------------------------------------------------------1654// Clean up.16551656if (hCertStore)1657::CertCloseStore(hCertStore, 0);16581659if (pszCertStoreName)1660env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);16611662if (pbCertEncoding)1663delete [] pbCertEncoding;16641665if (pszCertAliasName)1666delete [] pszCertAliasName;16671668if (pszContainerName)1669delete [] pszContainerName;16701671if (pwszContainerName)1672delete [] pwszContainerName;16731674if (pszProviderName)1675delete [] pszProviderName;16761677if (pwszProviderName)1678delete [] pwszProviderName;16791680if (pCertContext)1681::CertFreeCertificateContext(pCertContext);1682}1683}16841685/*1686* Class: sun_security_mscapi_CKeyStore1687* Method: removeCertificate1688* Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V1689*/1690JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCertificate1691(JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,1692jbyteArray jCertEncoding, jint jCertEncodingSize) {16931694const char* pszCertStoreName = NULL;1695const char* pszCertAliasName = NULL;1696HCERTSTORE hCertStore = NULL;1697PCCERT_CONTEXT pCertContext = NULL;1698PCCERT_CONTEXT pTBDCertContext = NULL;1699jbyte* pbCertEncoding = NULL;1700DWORD cchNameString = 0;1701char* pszNameString = NULL; // certificate's friendly name1702BOOL bDeleteAttempted = FALSE;17031704__try1705{1706// Open a system certificate store.1707if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))1708== NULL) {1709__leave;1710}1711if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {1712ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1713__leave;1714}17151716// Copy encoding from Java to native buffer1717pbCertEncoding = new (env) jbyte[jCertEncodingSize];1718if (pbCertEncoding == NULL) {1719__leave;1720}1721env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);17221723// Create a certificate context from the encoded cert1724if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,1725(BYTE*) pbCertEncoding, jCertEncodingSize))) {17261727ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());1728__leave;1729}17301731// Find the certificate to be deleted1732if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,1733X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {17341735ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1736__leave;1737}17381739// Check that its friendly name matches the supplied alias1740if ((cchNameString = ::CertGetNameString(pTBDCertContext,1741CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {17421743pszNameString = new (env) char[cchNameString];1744if (pszNameString == NULL) {1745__leave;1746}17471748::CertGetNameString(pTBDCertContext,1749CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,1750cchNameString);17511752// Compare the certificate's friendly name with supplied alias name1753if ((pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL))1754== NULL) {1755__leave;1756}1757if (strcmp(pszCertAliasName, pszNameString) == 0) {17581759// Only delete the certificate if the alias names matches1760if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {17611762// pTBDCertContext is always freed by the1763// CertDeleteCertificateFromStore method1764bDeleteAttempted = TRUE;17651766ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1767__leave;1768}1769}1770}17711772}1773__finally1774{1775//--------------------------------------------------------------------1776// Clean up.17771778if (hCertStore)1779::CertCloseStore(hCertStore, 0);17801781if (pszCertStoreName)1782env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);17831784if (pszCertAliasName)1785env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);17861787if (pbCertEncoding)1788delete [] pbCertEncoding;17891790if (pszNameString)1791delete [] pszNameString;17921793if (pCertContext)1794::CertFreeCertificateContext(pCertContext);17951796if (bDeleteAttempted && pTBDCertContext)1797::CertFreeCertificateContext(pTBDCertContext);1798}1799}18001801/*1802* Class: sun_security_mscapi_CKeyStore1803* Method: destroyKeyContainer1804* Signature: (Ljava/lang/String;)V1805*/1806JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer1807(JNIEnv *env, jobject clazz, jstring keyContainerName)1808{1809HCRYPTPROV hCryptProv = NULL;1810const char* pszKeyContainerName = NULL;18111812__try1813{1814if ((pszKeyContainerName =1815env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {1816__leave;1817}18181819// Destroying the default key container is not permitted1820// (because it may contain more one keypair).1821if (pszKeyContainerName == NULL) {18221823ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM);1824__leave;1825}18261827// Acquire a CSP context (to the key container).1828if (::CryptAcquireContext( //deprecated1829&hCryptProv,1830pszKeyContainerName,1831NULL,1832PROV_RSA_FULL,1833CRYPT_DELETEKEYSET) == FALSE)1834{1835ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());1836__leave;1837}18381839}1840__finally1841{1842//--------------------------------------------------------------------1843// Clean up.18441845if (pszKeyContainerName)1846env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);1847}1848}18491850/*1851* Class: sun_security_mscapi_CRSACipher1852* Method: encryptDecrypt1853* Signature: ([BIJZ)[B1854*/1855JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt1856(JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,1857jboolean doEncrypt)1858{1859jbyteArray result = NULL;1860jbyte* pData = NULL;1861DWORD dwDataLen = jDataSize;1862DWORD dwBufLen = env->GetArrayLength(jData);1863DWORD i;1864BYTE tmp;18651866__try1867{1868// Copy data from Java buffer to native buffer1869pData = new (env) jbyte[dwBufLen];1870if (pData == NULL) {1871__leave;1872}1873env->GetByteArrayRegion(jData, 0, dwBufLen, pData);18741875if (doEncrypt == JNI_TRUE) {1876// encrypt1877if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated1878&dwDataLen, dwBufLen)) {18791880ThrowException(env, KEY_EXCEPTION, GetLastError());1881__leave;1882}1883dwBufLen = dwDataLen;18841885// convert from little-endian1886for (i = 0; i < dwBufLen / 2; i++) {1887tmp = pData[i];1888pData[i] = pData[dwBufLen - i -1];1889pData[dwBufLen - i - 1] = tmp;1890}1891} else {1892// convert to little-endian1893for (i = 0; i < dwBufLen / 2; i++) {1894tmp = pData[i];1895pData[i] = pData[dwBufLen - i -1];1896pData[dwBufLen - i - 1] = tmp;1897}18981899// decrypt1900if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated1901&dwBufLen)) {19021903ThrowException(env, KEY_EXCEPTION, GetLastError());1904__leave;1905}1906}19071908// Create new byte array1909if ((result = env->NewByteArray(dwBufLen)) == NULL) {1910__leave;1911}19121913// Copy data from native buffer to Java buffer1914env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);1915}1916__finally1917{1918if (pData)1919delete [] pData;1920}19211922return result;1923}19241925/*1926* Class: sun_security_mscapi_CPublicKey1927* Method: getPublicKeyBlob1928* Signature: (JJ)[B1929*/1930JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob1931(JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {19321933jbyteArray blob = NULL;1934DWORD dwBlobLen;1935BYTE* pbKeyBlob = NULL;19361937__try1938{19391940// Determine the size of the blob1941if (hCryptKey == 0) {1942SS_CHECK(::NCryptExportKey(1943(NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,1944NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));1945} else {1946if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated1947&dwBlobLen)) {19481949ThrowException(env, KEY_EXCEPTION, GetLastError());1950__leave;1951}1952}19531954pbKeyBlob = new (env) BYTE[dwBlobLen];1955if (pbKeyBlob == NULL) {1956__leave;1957}19581959// Generate key blob1960if (hCryptKey == 0) {1961SS_CHECK(::NCryptExportKey(1962(NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,1963NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));1964} else {1965if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated1966pbKeyBlob, &dwBlobLen)) {19671968ThrowException(env, KEY_EXCEPTION, GetLastError());1969__leave;1970}1971}19721973// Create new byte array1974if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {1975__leave;1976}19771978// Copy data from native buffer to Java buffer1979env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);1980}1981__finally1982{1983if (pbKeyBlob)1984delete [] pbKeyBlob;1985}19861987return blob;1988}19891990/*1991* Class: sun_security_mscapi_CPublicKey_CRSAPublicKey1992* Method: getExponent1993* Signature: ([B)[B1994*/1995JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent1996(JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {19971998jbyteArray exponent = NULL;1999jbyte* exponentBytes = NULL;2000jbyte* keyBlob = NULL;20012002__try {20032004jsize length = env->GetArrayLength(jKeyBlob);2005jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);20062007if (length < headerLength) {2008ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");2009__leave;2010}20112012if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {2013__leave;2014}20152016PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;20172018// Check BLOB type2019if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {2020ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);2021__leave;2022}20232024RSAPUBKEY* pRsaPubKey =2025(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));20262027int len = sizeof(pRsaPubKey->pubexp);2028exponentBytes = new (env) jbyte[len];2029if (exponentBytes == NULL) {2030__leave;2031}20322033// convert from little-endian while copying from blob2034for (int i = 0, j = len - 1; i < len; i++, j--) {2035exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];2036}20372038if ((exponent = env->NewByteArray(len)) == NULL) {2039__leave;2040}2041env->SetByteArrayRegion(exponent, 0, len, exponentBytes);2042}2043__finally2044{2045if (keyBlob)2046env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);20472048if (exponentBytes)2049delete [] exponentBytes;2050}20512052return exponent;2053}20542055/*2056* Class: sun_security_mscapi_CPublicKey_CRSAPublicKey2057* Method: getModulus2058* Signature: ([B)[B2059*/2060JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus2061(JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {20622063jbyteArray modulus = NULL;2064jbyte* modulusBytes = NULL;2065jbyte* keyBlob = NULL;20662067__try {20682069jsize length = env->GetArrayLength(jKeyBlob);2070jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);20712072if (length < headerLength) {2073ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");2074__leave;2075}20762077if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {2078__leave;2079}20802081PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;20822083// Check BLOB type2084if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {2085ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);2086__leave;2087}20882089RSAPUBKEY* pRsaPubKey =2090(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));20912092int len = pRsaPubKey->bitlen / 8;2093if (len < 0 || len > length - headerLength) {2094ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");2095__leave;2096}20972098modulusBytes = new (env) jbyte[len];2099if (modulusBytes == NULL) {2100__leave;2101}2102BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);21032104// convert from little-endian while copying from blob2105for (int i = 0, j = len - 1; i < len; i++, j--) {2106modulusBytes[i] = pbModulus[j];2107}21082109if ((modulus = env->NewByteArray(len)) == NULL) {2110__leave;2111}2112env->SetByteArrayRegion(modulus, 0, len, modulusBytes);2113}2114__finally2115{2116if (keyBlob)2117env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);21182119if (modulusBytes)2120delete [] modulusBytes;2121}21222123return modulus;2124}21252126/*2127* Convert an array in big-endian byte order into little-endian byte order.2128*/2129int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,2130int destinationLength) {21312132int result = -1;2133jbyte* sourceBytes = NULL;21342135__try {2136int sourceLength = env->GetArrayLength(source);21372138sourceBytes = env->GetByteArrayElements(source, 0);2139if (sourceBytes == NULL) {2140__leave;2141}21422143int copyLen = sourceLength;2144if (sourceLength > destinationLength) {2145// source might include an extra sign byte2146if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) {2147copyLen--;2148} else {2149__leave;2150}2151}21522153// Copy bytes from the end of the source array to the beginning of the2154// destination array (until the destination array is full).2155// This ensures that the sign byte from the source array will be excluded.2156for (int i = 0; i < copyLen; i++) {2157destination[i] = sourceBytes[sourceLength - 1 - i];2158}2159if (copyLen < destinationLength) {2160memset(destination + copyLen, 0, destinationLength - copyLen);2161}2162result = destinationLength;2163} __finally {2164// Clean up.2165if (sourceBytes) {2166env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);2167}2168}21692170return result;2171}21722173/*2174* The Microsoft Base Cryptographic Provider supports public-key BLOBs2175* that have the following format:2176*2177* PUBLICKEYSTRUC publickeystruc;2178* RSAPUBKEY rsapubkey;2179* BYTE modulus[rsapubkey.bitlen/8];2180*2181* and private-key BLOBs that have the following format:2182*2183* PUBLICKEYSTRUC publickeystruc;2184* RSAPUBKEY rsapubkey;2185* BYTE modulus[rsapubkey.bitlen/8];2186* BYTE prime1[rsapubkey.bitlen/16];2187* BYTE prime2[rsapubkey.bitlen/16];2188* BYTE exponent1[rsapubkey.bitlen/16];2189* BYTE exponent2[rsapubkey.bitlen/16];2190* BYTE coefficient[rsapubkey.bitlen/16];2191* BYTE privateExponent[rsapubkey.bitlen/8];2192*2193* This method generates such BLOBs from the key elements supplied.2194*/2195jbyteArray generateKeyBlob(2196JNIEnv *env,2197jint jKeyBitLength,2198jbyteArray jModulus,2199jbyteArray jPublicExponent,2200jbyteArray jPrivateExponent,2201jbyteArray jPrimeP,2202jbyteArray jPrimeQ,2203jbyteArray jExponentP,2204jbyteArray jExponentQ,2205jbyteArray jCrtCoefficient)2206{2207jsize jKeyByteLength = jKeyBitLength / 8;2208jsize jBlobLength;2209BOOL bGeneratePrivateKeyBlob;22102211// Determine whether to generate a public-key or a private-key BLOB2212if (jPrivateExponent != NULL &&2213jPrimeP != NULL &&2214jPrimeQ != NULL &&2215jExponentP != NULL &&2216jExponentQ != NULL &&2217jCrtCoefficient != NULL) {22182219bGeneratePrivateKeyBlob = TRUE;2220jBlobLength = sizeof(BLOBHEADER) +2221sizeof(RSAPUBKEY) +2222((jKeyBitLength / 8) * 4) +2223(jKeyBitLength / 16);22242225} else {2226bGeneratePrivateKeyBlob = FALSE;2227jBlobLength = sizeof(BLOBHEADER) +2228sizeof(RSAPUBKEY) +2229(jKeyBitLength / 8);2230}22312232jbyte* jBlobBytes = NULL;2233jbyte* jBlobElement;2234jbyteArray jBlob = NULL;2235jsize jElementLength;22362237__try {2238jBlobBytes = new (env) jbyte[jBlobLength];2239if (jBlobBytes == NULL) {2240__leave;2241}22422243BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;2244if (bGeneratePrivateKeyBlob) {2245pBlobHeader->bType = PRIVATEKEYBLOB; // 0x072246} else {2247pBlobHeader->bType = PUBLICKEYBLOB; // 0x062248}2249pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x022250pBlobHeader->reserved = 0; // 0x00002251pBlobHeader->aiKeyAlg = CALG_RSA_KEYX; // 0x0000a40022522253RSAPUBKEY *pRsaPubKey =2254(RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));2255if (bGeneratePrivateKeyBlob) {2256pRsaPubKey->magic = 0x32415352; // "RSA2"2257} else {2258pRsaPubKey->magic = 0x31415352; // "RSA1"2259}2260pRsaPubKey->bitlen = jKeyBitLength;2261pRsaPubKey->pubexp = 0; // init22622263// Sanity check2264jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);2265if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {2266ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);2267__leave;2268}2269// The length argument must be the smaller of jPublicExponentLength2270// and sizeof(pRsaPubKey->pubkey)2271if ((jElementLength = convertToLittleEndian(env, jPublicExponent,2272(jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) {2273__leave;2274}22752276// Modulus n2277jBlobElement =2278(jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));2279if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,2280jKeyByteLength)) < 0) {2281__leave;2282}22832284if (bGeneratePrivateKeyBlob) {2285// Prime p2286jBlobElement += jElementLength;2287if ((jElementLength = convertToLittleEndian(env, jPrimeP,2288jBlobElement, jKeyByteLength / 2)) < 0) {2289__leave;2290}22912292// Prime q2293jBlobElement += jElementLength;2294if ((jElementLength = convertToLittleEndian(env, jPrimeQ,2295jBlobElement, jKeyByteLength / 2)) < 0) {2296__leave;2297}22982299// Prime exponent p2300jBlobElement += jElementLength;2301if ((jElementLength = convertToLittleEndian(env, jExponentP,2302jBlobElement, jKeyByteLength / 2)) < 0) {2303__leave;2304}23052306// Prime exponent q2307jBlobElement += jElementLength;2308if ((jElementLength = convertToLittleEndian(env, jExponentQ,2309jBlobElement, jKeyByteLength / 2)) < 0) {2310__leave;2311}23122313// CRT coefficient2314jBlobElement += jElementLength;2315if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient,2316jBlobElement, jKeyByteLength / 2)) < 0) {2317__leave;2318}23192320// Private exponent2321jBlobElement += jElementLength;2322if ((jElementLength = convertToLittleEndian(env, jPrivateExponent,2323jBlobElement, jKeyByteLength)) < 0) {2324__leave;2325}2326}23272328if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {2329__leave;2330}2331env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);23322333}2334__finally2335{2336if (jBlobBytes)2337delete [] jBlobBytes;2338}23392340return jBlob;2341}23422343/*2344* Class: sun_security_mscapi_CKeyStore2345* Method: generateRSAPrivateKeyBlob2346* Signature: (I[B[B[B[B[B[B[B[B)[B2347*/2348JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob2349(JNIEnv *env, jobject clazz,2350jint jKeyBitLength,2351jbyteArray jModulus,2352jbyteArray jPublicExponent,2353jbyteArray jPrivateExponent,2354jbyteArray jPrimeP,2355jbyteArray jPrimeQ,2356jbyteArray jExponentP,2357jbyteArray jExponentQ,2358jbyteArray jCrtCoefficient)2359{2360return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,2361jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,2362jCrtCoefficient);2363}23642365/*2366* Class: sun_security_mscapi_CSignature_RSA2367* Method: generatePublicKeyBlob2368* Signature: (I[B[B)[B2369*/2370JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob2371(JNIEnv *env, jclass clazz,2372jint jKeyBitLength,2373jbyteArray jModulus,2374jbyteArray jPublicExponent)2375{2376return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,2377NULL, NULL, NULL, NULL, NULL, NULL);2378}23792380/*2381* Class: sun_security_mscapi_CKeyStore2382* Method: storePrivateKey2383* Signature: (Ljava/lang/String;[BLjava/lang/String;I)Lsun/security/mscapi/CPrivateKey;2384*/2385JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey2386(JNIEnv *env, jobject clazz, jstring alg, jbyteArray keyBlob,2387jstring keyContainerName, jint keySize)2388{2389HCRYPTPROV hCryptProv = NULL;2390HCRYPTKEY hKey = NULL;2391DWORD dwBlobLen;2392BYTE * pbKeyBlob = NULL;2393const char* pszKeyContainerName = NULL; // UUID2394jobject privateKey = NULL;23952396__try2397{2398if ((pszKeyContainerName =2399env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {2400__leave;2401}2402dwBlobLen = env->GetArrayLength(keyBlob);2403if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2404== NULL) {2405__leave;2406}24072408// Acquire a CSP context (create a new key container).2409if (::CryptAcquireContext( //deprecated2410&hCryptProv,2411pszKeyContainerName,2412NULL,2413PROV_RSA_FULL,2414CRYPT_NEWKEYSET) == FALSE)2415{2416ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2417__leave;2418}24192420// Import the private key2421if (::CryptImportKey( //deprecated2422hCryptProv,2423pbKeyBlob,2424dwBlobLen,24250,2426CRYPT_EXPORTABLE,2427&hKey) == FALSE)2428{2429ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2430__leave;2431}24322433// Get the method ID for the CPrivateKey constructor2434jclass clazzCPrivateKey =2435env->FindClass("sun/security/mscapi/CPrivateKey");2436if (clazzCPrivateKey == NULL) {2437__leave;2438}24392440jmethodID mNewCPrivateKey =2441env->GetStaticMethodID(clazzCPrivateKey, "of",2442"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPrivateKey;");2443if (mNewCPrivateKey == NULL) {2444__leave;2445}24462447// Create a new private key2448privateKey = env->CallStaticObjectMethod(clazzCPrivateKey, mNewCPrivateKey,2449alg, (jlong) hCryptProv, (jlong) hKey, keySize);24502451}2452__finally2453{2454//--------------------------------------------------------------------2455// Clean up.24562457if (pszKeyContainerName)2458env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);24592460if (pbKeyBlob)2461env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,2462JNI_ABORT);2463}24642465return privateKey;2466}24672468/*2469* Class: sun_security_mscapi_CSignature2470* Method: importECPublicKey2471* Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;2472*/2473JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey2474(JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)2475{2476BCRYPT_ALG_HANDLE hSignAlg = NULL;2477NCRYPT_KEY_HANDLE hTmpKey = NULL;2478DWORD dwBlobLen;2479BYTE * pbKeyBlob = NULL;2480jobject publicKey = NULL;24812482__try2483{2484dwBlobLen = env->GetArrayLength(keyBlob);2485if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2486== NULL) {2487__leave;2488}2489dump("NCryptImportKey", pbKeyBlob, dwBlobLen);2490NCRYPT_PROV_HANDLE hProv;2491SS_CHECK(NCryptOpenStorageProvider(2492&hProv, L"Microsoft Software Key Storage Provider", 0 ));2493SS_CHECK(NCryptImportKey(2494hProv,2495NULL,2496BCRYPT_ECCPUBLIC_BLOB,2497NULL,2498&hTmpKey,2499pbKeyBlob,2500dwBlobLen,25010));2502NCryptFreeObject( hProv );2503// Get the method ID for the CPublicKey constructor2504jclass clazzCPublicKey =2505env->FindClass("sun/security/mscapi/CPublicKey");2506if (clazzCPublicKey == NULL) {2507__leave;2508}25092510jmethodID mNewCPublicKey =2511env->GetStaticMethodID(clazzCPublicKey, "of",2512"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");2513if (mNewCPublicKey == NULL) {2514__leave;2515}25162517// Create a new public key2518publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,2519alg, (jlong) hTmpKey, (jlong) 0, keySize);2520}2521__finally2522{2523}25242525return publicKey;2526}25272528/*2529* Class: sun_security_mscapi_CSignature2530* Method: importPublicKey2531* Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;2532*/2533JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importPublicKey2534(JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)2535{2536HCRYPTPROV hCryptProv = NULL;2537HCRYPTKEY hKey = NULL;2538DWORD dwBlobLen;2539BYTE * pbKeyBlob = NULL;2540jobject publicKey = NULL;25412542__try2543{2544dwBlobLen = env->GetArrayLength(keyBlob);2545if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))2546== NULL) {2547__leave;2548}25492550// Acquire a CSP context (create a new key container).2551// Prefer a PROV_RSA_AES CSP, when available, due to its support2552// for SHA-2-based signatures.2553if (::CryptAcquireContext( //deprecated2554&hCryptProv,2555NULL,2556NULL,2557PROV_RSA_AES,2558CRYPT_VERIFYCONTEXT) == FALSE)2559{2560// Failover to using the default CSP (PROV_RSA_FULL)25612562if (::CryptAcquireContext( //deprecated2563&hCryptProv,2564NULL,2565NULL,2566PROV_RSA_FULL,2567CRYPT_VERIFYCONTEXT) == FALSE)2568{2569ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2570__leave;2571}2572}25732574// Import the public key2575if (::CryptImportKey( //deprecated2576hCryptProv,2577pbKeyBlob,2578dwBlobLen,25790,2580CRYPT_EXPORTABLE,2581&hKey) == FALSE)2582{2583ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());2584__leave;2585}25862587// Get the method ID for the CPublicKey constructor2588jclass clazzCPublicKey =2589env->FindClass("sun/security/mscapi/CPublicKey");2590if (clazzCPublicKey == NULL) {2591__leave;2592}25932594jmethodID mNewCPublicKey =2595env->GetStaticMethodID(clazzCPublicKey, "of",2596"(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");2597if (mNewCPublicKey == NULL) {2598__leave;2599}26002601// Create a new public key2602publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,2603alg, (jlong) hCryptProv, (jlong) hKey, keySize);26042605}2606__finally2607{2608//--------------------------------------------------------------------2609// Clean up.26102611if (pbKeyBlob)2612env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,2613JNI_ABORT);2614}26152616return publicKey;2617}26182619} /* extern "C" */262026212622