0N/A/*
4111N/A * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A//=--------------------------------------------------------------------------=
0N/A// security.cpp by Stanley Man-Kit Ho
0N/A//=--------------------------------------------------------------------------=
0N/A//
0N/A
0N/A#include <jni.h>
0N/A#include <stdlib.h>
0N/A#include <windows.h>
0N/A#include <BaseTsd.h>
0N/A#include <wincrypt.h>
0N/A#include <stdio.h>
0N/A
0N/A
0N/A#define OID_EKU_ANY "2.5.29.37.0"
0N/A
0N/A#define CERTIFICATE_PARSING_EXCEPTION \
0N/A "java/security/cert/CertificateParsingException"
4111N/A#define INVALID_KEY_EXCEPTION \
4111N/A "java/security/InvalidKeyException"
0N/A#define KEY_EXCEPTION "java/security/KeyException"
0N/A#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"
0N/A#define PROVIDER_EXCEPTION "java/security/ProviderException"
0N/A#define SIGNATURE_EXCEPTION "java/security/SignatureException"
0N/A
0N/Aextern "C" {
0N/A
0N/A/*
0N/A * Throws an arbitrary Java exception.
0N/A * The exception message is a Windows system error message.
0N/A */
0N/Avoid ThrowException(JNIEnv *env, char *exceptionName, DWORD dwError)
0N/A{
0N/A char szMessage[1024];
0N/A szMessage[0] = '\0';
0N/A
0N/A FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, NULL, szMessage,
0N/A 1024, NULL);
0N/A
0N/A jclass exceptionClazz = env->FindClass(exceptionName);
0N/A env->ThrowNew(exceptionClazz, szMessage);
0N/A}
0N/A
0N/A
0N/A/*
0N/A * Maps the name of a hash algorithm to an algorithm identifier.
0N/A */
0N/AALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
0N/A
0N/A const char* pszHashAlgorithm = NULL;
0N/A ALG_ID algId = 0;
0N/A
0N/A pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL);
0N/A
0N/A if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
0N/A (strcmp("SHA1", pszHashAlgorithm) == 0) ||
0N/A (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
0N/A
0N/A algId = CALG_SHA1;
4136N/A } else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {
4136N/A algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5
0N/A } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
0N/A algId = CALG_SHA_256;
0N/A } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
0N/A algId = CALG_SHA_384;
0N/A } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
0N/A algId = CALG_SHA_512;
0N/A } else if (strcmp("MD5", pszHashAlgorithm) == 0) {
0N/A algId = CALG_MD5;
0N/A } else if (strcmp("MD2", pszHashAlgorithm) == 0) {
0N/A algId = CALG_MD2;
0N/A }
0N/A
0N/A if (pszHashAlgorithm)
0N/A env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
0N/A
0N/A return algId;
0N/A}
0N/A
0N/A
0N/A/*
0N/A * Returns a certificate chain context given a certificate context and key
0N/A * usage identifier.
0N/A */
0N/Abool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)
0N/A{
0N/A CERT_ENHKEY_USAGE EnhkeyUsage;
0N/A CERT_USAGE_MATCH CertUsage;
0N/A CERT_CHAIN_PARA ChainPara;
0N/A DWORD dwFlags = 0;
0N/A LPSTR szUsageIdentifierArray[1];
0N/A
0N/A szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;
0N/A EnhkeyUsage.cUsageIdentifier = 1;
0N/A EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;
0N/A CertUsage.dwType = USAGE_MATCH_TYPE_AND;
0N/A CertUsage.Usage = EnhkeyUsage;
0N/A ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
0N/A ChainPara.RequestedUsage=CertUsage;
0N/A
0N/A // Build a chain using CertGetCertificateChain
0N/A // and the certificate retrieved.
0N/A return (::CertGetCertificateChain(NULL, // use the default chain engine
0N/A pCertContext, // pointer to the end certificate
0N/A NULL, // use the default time
0N/A NULL, // search no additional stores
0N/A &ChainPara, // use AND logic and enhanced key usage
0N/A // as indicated in the ChainPara
0N/A // data structure
0N/A dwFlags,
0N/A NULL, // currently reserved
0N/A ppChainContext) == TRUE); // return a pointer to the chain created
0N/A}
0N/A
0N/A
0N/A/////////////////////////////////////////////////////////////////////////////
0N/A//
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_PRNG
0N/A * Method: generateSeed
0N/A * Signature: (I[B)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
0N/A (JNIEnv *env, jclass clazz, jint length, jbyteArray seed)
0N/A{
0N/A
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A BYTE* pbData = NULL;
0N/A jbyte* reseedBytes = NULL;
0N/A jbyte* seedBytes = NULL;
0N/A jbyteArray result = NULL;
0N/A
0N/A __try
0N/A {
0N/A // Acquire a CSP context.
0N/A if(::CryptAcquireContext(
0N/A &hCryptProv,
0N/A NULL,
0N/A NULL,
0N/A PROV_RSA_FULL,
0N/A CRYPT_VERIFYCONTEXT) == FALSE)
0N/A {
0N/A ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A /*
0N/A * If length is negative then use the supplied seed to re-seed the
0N/A * generator and return null.
0N/A * If length is non-zero then generate a new seed according to the
0N/A * requested length and return the new seed.
0N/A * If length is zero then overwrite the supplied seed with a new
0N/A * seed of the same length and return the seed.
0N/A */
0N/A if (length < 0) {
0N/A length = env->GetArrayLength(seed);
0N/A reseedBytes = env->GetByteArrayElements(seed, 0);
0N/A
0N/A if (::CryptGenRandom(
0N/A hCryptProv,
0N/A length,
0N/A (BYTE *) reseedBytes) == FALSE) {
0N/A
0N/A ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A result = NULL;
0N/A
0N/A } else if (length > 0) {
0N/A
0N/A pbData = new BYTE[length];
0N/A
0N/A if (::CryptGenRandom(
0N/A hCryptProv,
0N/A length,
0N/A pbData) == FALSE) {
0N/A
0N/A ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A result = env->NewByteArray(length);
0N/A env->SetByteArrayRegion(result, 0, length, (jbyte*) pbData);
0N/A
0N/A } else { // length == 0
0N/A
0N/A length = env->GetArrayLength(seed);
0N/A seedBytes = env->GetByteArrayElements(seed, 0);
0N/A
0N/A if (::CryptGenRandom(
0N/A hCryptProv,
0N/A length,
0N/A (BYTE *) seedBytes) == FALSE) {
0N/A
0N/A ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A result = seed; // seed will be updated when seedBytes gets released
0N/A }
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (reseedBytes)
0N/A env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);
0N/A
0N/A if (pbData)
0N/A delete [] pbData;
0N/A
0N/A if (seedBytes)
0N/A env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
0N/A
0N/A if (hCryptProv)
0N/A ::CryptReleaseContext(hCryptProv, 0);
0N/A }
0N/A
0N/A return result;
0N/A}
0N/A
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: loadKeysOrCertificateChains
0N/A * Signature: (Ljava/lang/String;Ljava/util/Collection;)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateChains
0N/A (JNIEnv *env, jobject obj, jstring jCertStoreName, jobject jCollections)
0N/A{
0N/A /**
0N/A * Certificate in cert store has enhanced key usage extension
0N/A * property (or EKU property) that is not part of the certificate itself. To determine
0N/A * if the certificate should be returned, both the enhanced key usage in certificate
0N/A * extension block and the extension property stored along with the certificate in
0N/A * certificate store should be examined. Otherwise, we won't be able to determine
0N/A * the proper key usage from the Java side because the information is not stored as
0N/A * part of the encoded certificate.
0N/A */
0N/A
0N/A const char* pszCertStoreName = NULL;
0N/A HCERTSTORE hCertStore = NULL;
0N/A PCCERT_CONTEXT pCertContext = NULL;
0N/A char* pszNameString = NULL; // certificate's friendly name
0N/A DWORD cchNameString = 0;
0N/A
0N/A
0N/A __try
0N/A {
0N/A // Open a system certificate store.
0N/A pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL);
0N/A if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))
0N/A == NULL) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Determine clazz and method ID to generate certificate
0N/A jclass clazzArrayList = env->FindClass("java/util/ArrayList");
0N/A
0N/A jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");
0N/A
0N/A jmethodID mGenCert = env->GetMethodID(env->GetObjectClass(obj),
0N/A "generateCertificate",
0N/A "([BLjava/util/Collection;)V");
0N/A
0N/A // Determine method ID to generate certificate chain
0N/A jmethodID mGenCertChain = env->GetMethodID(env->GetObjectClass(obj),
0N/A "generateCertificateChain",
0N/A "(Ljava/lang/String;Ljava/util/Collection;Ljava/util/Collection;)V");
0N/A
0N/A // Determine method ID to generate RSA certificate chain
0N/A jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(env->GetObjectClass(obj),
0N/A "generateRSAKeyAndCertificateChain",
0N/A "(Ljava/lang/String;JJILjava/util/Collection;Ljava/util/Collection;)V");
0N/A
0N/A // Use CertEnumCertificatesInStore to get the certificates
0N/A // from the open store. pCertContext must be reset to
0N/A // NULL to retrieve the first certificate in the store.
0N/A while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
0N/A {
0N/A // Check if private key available - client authentication certificate
0N/A // must have private key available.
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A DWORD dwKeySpec = 0;
0N/A HCRYPTKEY hUserKey = NULL;
0N/A BOOL bCallerFreeProv = FALSE;
0N/A BOOL bHasNoPrivateKey = FALSE;
0N/A DWORD dwPublicKeyLength = 0;
0N/A
0N/A if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL,
0N/A &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
0N/A {
0N/A bHasNoPrivateKey = TRUE;
0N/A
0N/A } else {
0N/A // Private key is available
0N/A
0N/A BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
0N/A
0N/A // Skip certificate if cannot find private key
0N/A if (bGetUserKey == FALSE)
0N/A {
0N/A if (bCallerFreeProv)
0N/A ::CryptReleaseContext(hCryptProv, NULL);
0N/A
0N/A continue;
0N/A }
0N/A
0N/A // Set cipher mode to ECB
0N/A DWORD dwCipherMode = CRYPT_MODE_ECB;
0N/A ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
0N/A
0N/A
0N/A // If the private key is present in smart card, we may not be able to
0N/A // determine the key length by using the private key handle. However,
0N/A // since public/private key pairs must have the same length, we could
0N/A // determine the key length of the private key by using the public key
0N/A // in the certificate.
0N/A dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0N/A &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
0N/A
0N/A}
0N/A PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
0N/A
0N/A // Build certificate chain by using system certificate store.
0N/A // Add cert chain into collection for any key usage.
0N/A //
0N/A if (GetCertificateChain(OID_EKU_ANY, pCertContext,
0N/A &pCertChainContext))
0N/A {
0N/A
0N/A for (unsigned int i=0; i < pCertChainContext->cChain; i++)
0N/A {
0N/A // Found cert chain
0N/A PCERT_SIMPLE_CHAIN rgpChain =
0N/A pCertChainContext->rgpChain[i];
0N/A
0N/A // Create ArrayList to store certs in each chain
0N/A jobject jArrayList =
0N/A env->NewObject(clazzArrayList, mNewArrayList);
0N/A
0N/A for (unsigned int j=0; j < rgpChain->cElement; j++)
0N/A {
0N/A PCERT_CHAIN_ELEMENT rgpElement =
0N/A rgpChain->rgpElement[j];
0N/A PCCERT_CONTEXT pc = rgpElement->pCertContext;
0N/A
0N/A // Retrieve the friendly name of the first certificate
0N/A // in the chain
0N/A if (j == 0) {
0N/A
0N/A // If the cert's name cannot be retrieved then
0N/A // pszNameString remains set to NULL.
0N/A // (An alias name will be generated automatically
0N/A // when storing this cert in the keystore.)
0N/A
0N/A // Get length of friendly name
0N/A if ((cchNameString = CertGetNameString(pc,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
0N/A NULL, 0)) > 1) {
0N/A
0N/A // Found friendly name
0N/A pszNameString = new char[cchNameString];
0N/A CertGetNameString(pc,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
0N/A pszNameString, cchNameString);
0N/A }
0N/A }
0N/A
0N/A BYTE* pbCertEncoded = pc->pbCertEncoded;
0N/A DWORD cbCertEncoded = pc->cbCertEncoded;
0N/A
0N/A // Allocate and populate byte array
0N/A jbyteArray byteArray = env->NewByteArray(cbCertEncoded);
0N/A env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,
0N/A (jbyte*) pbCertEncoded);
0N/A
0N/A // Generate certificate from byte array and store into
0N/A // cert collection
0N/A env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
0N/A }
0N/A if (bHasNoPrivateKey)
0N/A {
0N/A // Generate certificate chain and store into cert chain
0N/A // collection
0N/A env->CallVoidMethod(obj, mGenCertChain,
0N/A env->NewStringUTF(pszNameString),
0N/A jArrayList, jCollections);
0N/A }
0N/A else
0N/A {
0N/A // Determine key type: RSA or DSA
0N/A DWORD dwData = CALG_RSA_KEYX;
0N/A DWORD dwSize = sizeof(DWORD);
0N/A ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData,
0N/A &dwSize, NULL);
0N/A
0N/A if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
0N/A {
0N/A // Generate RSA certificate chain and store into cert
0N/A // chain collection
0N/A env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
0N/A env->NewStringUTF(pszNameString),
0N/A (jlong) hCryptProv, (jlong) hUserKey,
0N/A dwPublicKeyLength, jArrayList, jCollections);
0N/A }
0N/A}
0N/A }
0N/A
0N/A // Free cert chain
0N/A if (pCertChainContext)
0N/A ::CertFreeCertificateChain(pCertChainContext);
0N/A }
0N/A }
0N/A }
0N/A __finally
0N/A {
0N/A if (hCertStore)
0N/A ::CertCloseStore(hCertStore, 0);
0N/A
0N/A if (pszCertStoreName)
0N/A env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
0N/A
0N/A if (pszNameString)
0N/A delete [] pszNameString;
0N/A }
0N/A}
0N/A
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_Key
0N/A * Method: cleanUp
0N/A * Signature: (JJ)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_security_mscapi_Key_cleanUp
0N/A (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)
0N/A{
0N/A if (hCryptKey != NULL)
0N/A ::CryptDestroyKey((HCRYPTKEY) hCryptKey);
0N/A
0N/A if (hCryptProv != NULL)
0N/A ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL);
0N/A}
0N/A
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSASignature
0N/A * Method: signHash
4136N/A * Signature: (Z[BILjava/lang/String;JJ)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_signHash
4136N/A (JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,
4136N/A jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,
4136N/A jlong hCryptKey)
0N/A{
0N/A HCRYPTHASH hHash = NULL;
0N/A jbyte* pHashBuffer = NULL;
0N/A jbyte* pSignedHashBuffer = NULL;
0N/A jbyteArray jSignedHash = NULL;
4127N/A HCRYPTPROV hCryptProvAlt = NULL;
0N/A
0N/A __try
0N/A {
0N/A // Map hash algorithm
0N/A ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
0N/A
0N/A // Acquire a hash object handle.
0N/A if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE)
0N/A {
4127N/A // Failover to using the PROV_RSA_AES CSP
4127N/A
4127N/A DWORD cbData = 256;
4127N/A BYTE pbData[256];
4127N/A pbData[0] = '\0';
4127N/A
4127N/A // Get name of the key container
4127N/A ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER,
4127N/A (BYTE *)pbData, &cbData, 0);
4127N/A
4127N/A // Acquire an alternative CSP handle
4127N/A if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL,
4127N/A PROV_RSA_AES, 0) == FALSE)
4127N/A {
4127N/A
4127N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
4127N/A
4127N/A // Acquire a hash object handle.
4127N/A if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,
4127N/A &hHash) == FALSE)
4127N/A {
4127N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
0N/A }
0N/A
0N/A // Copy hash from Java to native buffer
0N/A pHashBuffer = new jbyte[jHashSize];
0N/A env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
0N/A
0N/A // Set hash value in the hash object
0N/A if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE)
0N/A {
0N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Determine key spec.
0N/A DWORD dwKeySpec = AT_SIGNATURE;
0N/A ALG_ID dwAlgId;
0N/A DWORD dwAlgIdLen = sizeof(ALG_ID);
0N/A
0N/A if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) {
0N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A
0N/A }
0N/A if (CALG_RSA_KEYX == dwAlgId) {
0N/A dwKeySpec = AT_KEYEXCHANGE;
0N/A }
0N/A
0N/A // Determine size of buffer
0N/A DWORD dwBufLen = 0;
4136N/A DWORD dwFlags = 0;
4136N/A
4136N/A if (noHashOID == JNI_TRUE) {
4136N/A dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature
4136N/A }
4136N/A
4136N/A if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE)
0N/A {
0N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A pSignedHashBuffer = new jbyte[dwBufLen];
4136N/A if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE)
0N/A {
0N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Create new byte array
0N/A jbyteArray temp = env->NewByteArray(dwBufLen);
0N/A
0N/A // Copy data from native buffer
0N/A env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
0N/A
0N/A jSignedHash = temp;
0N/A }
0N/A __finally
0N/A {
4127N/A if (hCryptProvAlt)
4127N/A ::CryptReleaseContext(hCryptProvAlt, 0);
4127N/A
0N/A if (pSignedHashBuffer)
0N/A delete [] pSignedHashBuffer;
0N/A
0N/A if (pHashBuffer)
0N/A delete [] pHashBuffer;
0N/A
0N/A if (hHash)
0N/A ::CryptDestroyHash(hHash);
0N/A }
0N/A
0N/A return jSignedHash;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSASignature
0N/A * Method: verifySignedHash
0N/A * Signature: ([BIL/java/lang/String;[BIJJ)Z
0N/A */
0N/AJNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_verifySignedHash
0N/A (JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,
0N/A jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,
0N/A jlong hCryptProv, jlong hCryptKey)
0N/A{
0N/A HCRYPTHASH hHash = NULL;
0N/A jbyte* pHashBuffer = NULL;
0N/A jbyte* pSignedHashBuffer = NULL;
0N/A DWORD dwSignedHashBufferLen = jSignedHashSize;
0N/A jboolean result = JNI_FALSE;
4127N/A HCRYPTPROV hCryptProvAlt = NULL;
0N/A
0N/A __try
0N/A {
0N/A // Map hash algorithm
0N/A ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
0N/A
0N/A // Acquire a hash object handle.
0N/A if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)
0N/A == FALSE)
0N/A {
4127N/A // Failover to using the PROV_RSA_AES CSP
4127N/A
4127N/A DWORD cbData = 256;
4127N/A BYTE pbData[256];
4127N/A pbData[0] = '\0';
4127N/A
4127N/A // Get name of the key container
4127N/A ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER,
4127N/A (BYTE *)pbData, &cbData, 0);
4127N/A
4127N/A // Acquire an alternative CSP handle
4127N/A if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL,
4127N/A PROV_RSA_AES, 0) == FALSE)
4127N/A {
4127N/A
4127N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
4127N/A
4127N/A // Acquire a hash object handle.
4127N/A if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,
4127N/A &hHash) == FALSE)
4127N/A {
4127N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
0N/A }
0N/A
0N/A // Copy hash and signedHash from Java to native buffer
0N/A pHashBuffer = new jbyte[jHashSize];
0N/A env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
0N/A pSignedHashBuffer = new jbyte[jSignedHashSize];
0N/A env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
0N/A pSignedHashBuffer);
0N/A
0N/A // Set hash value in the hash object
0N/A if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL)
0N/A == FALSE)
0N/A {
0N/A ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // For RSA, the hash encryption algorithm is normally the same as the
0N/A // public key algorithm, so AT_SIGNATURE is used.
0N/A
0N/A // Verify the signature
0N/A if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer,
0N/A dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)
0N/A {
0N/A result = JNI_TRUE;
0N/A }
0N/A }
0N/A
0N/A __finally
0N/A {
4127N/A if (hCryptProvAlt)
4127N/A ::CryptReleaseContext(hCryptProvAlt, 0);
4127N/A
0N/A if (pSignedHashBuffer)
0N/A delete [] pSignedHashBuffer;
0N/A
0N/A if (pHashBuffer)
0N/A delete [] pHashBuffer;
0N/A
0N/A if (hHash)
0N/A ::CryptDestroyHash(hHash);
0N/A }
0N/A
0N/A return result;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSAKeyPairGenerator
0N/A * Method: generateRSAKeyPair
0N/A * Signature: (ILjava/lang/String;)Lsun/security/mscapi/RSAKeyPair;
0N/A */
0N/AJNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSAKeyPairGenerator_generateRSAKeyPair
0N/A (JNIEnv *env, jclass clazz, jint keySize, jstring keyContainerName)
0N/A{
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A HCRYPTKEY hKeyPair;
0N/A DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;
4211N/A jobject keypair = NULL;
0N/A const char* pszKeyContainerName = NULL; // UUID
0N/A
0N/A __try
0N/A {
0N/A pszKeyContainerName = env->GetStringUTFChars(keyContainerName, NULL);
0N/A
0N/A // Acquire a CSP context (create a new key container).
4127N/A // Prefer a PROV_RSA_AES CSP, when available, due to its support
4127N/A // for SHA-2-based signatures.
0N/A if (::CryptAcquireContext(
0N/A &hCryptProv,
0N/A pszKeyContainerName,
0N/A NULL,
4127N/A PROV_RSA_AES,
0N/A CRYPT_NEWKEYSET) == FALSE)
0N/A {
4127N/A // Failover to using the default CSP (PROV_RSA_FULL)
4127N/A
4127N/A if (::CryptAcquireContext(
4127N/A &hCryptProv,
4127N/A pszKeyContainerName,
4127N/A NULL,
4127N/A PROV_RSA_FULL,
4127N/A CRYPT_NEWKEYSET) == FALSE)
4127N/A {
4127N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
0N/A }
0N/A
0N/A // Generate an RSA keypair
0N/A if(::CryptGenKey(
0N/A hCryptProv,
0N/A AT_KEYEXCHANGE,
0N/A dwFlags,
0N/A &hKeyPair) == FALSE)
0N/A {
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Get the method ID for the RSAKeyPair constructor
0N/A jclass clazzRSAKeyPair =
0N/A env->FindClass("sun/security/mscapi/RSAKeyPair");
0N/A
0N/A jmethodID mNewRSAKeyPair =
0N/A env->GetMethodID(clazzRSAKeyPair, "<init>", "(JJI)V");
0N/A
0N/A // Create a new RSA keypair
0N/A keypair = env->NewObject(clazzRSAKeyPair, mNewRSAKeyPair,
0N/A (jlong) hCryptProv, (jlong) hKeyPair, keySize);
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (pszKeyContainerName)
0N/A env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
0N/A }
0N/A
0N/A return keypair;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_Key
0N/A * Method: getContainerName
0N/A * Signature: (J)Ljava/lang/String;
0N/A */
0N/AJNIEXPORT jstring JNICALL Java_sun_security_mscapi_Key_getContainerName
0N/A (JNIEnv *env, jclass jclazz, jlong hCryptProv)
0N/A{
0N/A DWORD cbData = 256;
0N/A BYTE pbData[256];
0N/A pbData[0] = '\0';
0N/A
0N/A ::CryptGetProvParam(
0N/A (HCRYPTPROV)hCryptProv,
0N/A PP_CONTAINER,
0N/A (BYTE *)pbData,
0N/A &cbData,
0N/A 0);
0N/A
0N/A return env->NewStringUTF((const char*)pbData);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_Key
0N/A * Method: getKeyType
0N/A * Signature: (J)Ljava/lang/String;
0N/A */
0N/AJNIEXPORT jstring JNICALL Java_sun_security_mscapi_Key_getKeyType
0N/A (JNIEnv *env, jclass jclazz, jlong hCryptKey)
0N/A{
0N/A ALG_ID dwAlgId;
0N/A DWORD dwAlgIdLen = sizeof(ALG_ID);
0N/A
0N/A if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) {
0N/A
0N/A if (CALG_RSA_SIGN == dwAlgId) {
0N/A return env->NewStringUTF("Signature");
0N/A
0N/A } else if (CALG_RSA_KEYX == dwAlgId) {
0N/A return env->NewStringUTF("Exchange");
0N/A
0N/A } else {
0N/A char buffer[64];
0N/A if (sprintf(buffer, "%lu", dwAlgId)) {
0N/A return env->NewStringUTF(buffer);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return env->NewStringUTF("<Unknown>");
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: storeCertificate
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate
0N/A (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
0N/A jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,
0N/A jlong hCryptKey)
0N/A{
0N/A const char* pszCertStoreName = NULL;
0N/A HCERTSTORE hCertStore = NULL;
0N/A PCCERT_CONTEXT pCertContext = NULL;
0N/A PWCHAR pszCertAliasName = NULL;
0N/A jbyte* pbCertEncoding = NULL;
0N/A const jchar* jCertAliasChars = NULL;
0N/A const char* pszContainerName = NULL;
0N/A const char* pszProviderName = NULL;
0N/A WCHAR * pwszContainerName = NULL;
0N/A WCHAR * pwszProviderName = NULL;
0N/A
0N/A __try
0N/A {
0N/A // Open a system certificate store.
0N/A pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL);
0N/A if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Copy encoding from Java to native buffer
0N/A pbCertEncoding = new jbyte[jCertEncodingSize];
0N/A env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
0N/A
0N/A // Create a certificate context from the encoded cert
0N/A if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
0N/A (BYTE*) pbCertEncoding, jCertEncodingSize))) {
0N/A
0N/A ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Set the certificate's friendly name
0N/A int size = env->GetStringLength(jCertAliasName);
0N/A pszCertAliasName = new WCHAR[size + 1];
0N/A
0N/A jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
0N/A memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
0N/A pszCertAliasName[size] = 0; // append the string terminator
0N/A
0N/A CRYPT_DATA_BLOB friendlyName = {
0N/A sizeof(WCHAR) * (size + 1),
0N/A (BYTE *) pszCertAliasName
0N/A };
0N/A
0N/A env->ReleaseStringChars(jCertAliasName, jCertAliasChars);
0N/A
0N/A if (! ::CertSetCertificateContextProperty(pCertContext,
0N/A CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Attach the certificate's private key (if supplied)
0N/A if (hCryptProv != 0 && hCryptKey != 0) {
0N/A
0N/A CRYPT_KEY_PROV_INFO keyProviderInfo;
0N/A DWORD dwDataLen;
0N/A
0N/A // Get the name of the key container
0N/A if (! ::CryptGetProvParam(
0N/A (HCRYPTPROV) hCryptProv,
0N/A PP_CONTAINER,
0N/A NULL,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A pszContainerName = new char[dwDataLen];
0N/A
0N/A if (! ::CryptGetProvParam(
0N/A (HCRYPTPROV) hCryptProv,
0N/A PP_CONTAINER,
0N/A (BYTE *) pszContainerName,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Convert to a wide char string
0N/A pwszContainerName = new WCHAR[dwDataLen];
0N/A
0N/A if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Set the name of the key container
0N/A keyProviderInfo.pwszContainerName = pwszContainerName;
0N/A
0N/A
0N/A // Get the name of the provider
0N/A if (! ::CryptGetProvParam(
0N/A (HCRYPTPROV) hCryptProv,
0N/A PP_NAME,
0N/A NULL,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A pszProviderName = new char[dwDataLen];
0N/A
0N/A if (! ::CryptGetProvParam(
0N/A (HCRYPTPROV) hCryptProv,
0N/A PP_NAME,
0N/A (BYTE *) pszProviderName,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Convert to a wide char string
0N/A pwszProviderName = new WCHAR[dwDataLen];
0N/A
0N/A if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Set the name of the provider
0N/A keyProviderInfo.pwszProvName = pwszProviderName;
0N/A
0N/A // Get and set the type of the provider
0N/A if (! ::CryptGetProvParam(
0N/A (HCRYPTPROV) hCryptProv,
0N/A PP_PROVTYPE,
0N/A (LPBYTE) &keyProviderInfo.dwProvType,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Set no provider flags
0N/A keyProviderInfo.dwFlags = 0;
0N/A
0N/A // Set no provider parameters
0N/A keyProviderInfo.cProvParam = 0;
0N/A keyProviderInfo.rgProvParam = NULL;
0N/A
0N/A // Get the key's algorithm ID
0N/A if (! ::CryptGetKeyParam(
0N/A (HCRYPTKEY) hCryptKey,
0N/A KP_ALGID,
0N/A (LPBYTE) &keyProviderInfo.dwKeySpec,
0N/A &dwDataLen,
0N/A 0)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A // Set the key spec (using the algorithm ID).
0N/A switch (keyProviderInfo.dwKeySpec) {
0N/A case CALG_RSA_KEYX:
0N/A case CALG_DH_SF:
0N/A keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;
0N/A break;
0N/A
0N/A case CALG_RSA_SIGN:
0N/A case CALG_DSS_SIGN:
0N/A keyProviderInfo.dwKeySpec = AT_SIGNATURE;
0N/A break;
0N/A
0N/A default:
0N/A ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);
0N/A __leave;
0N/A }
0N/A
0N/A if (! ::CertSetCertificateContextProperty(pCertContext,
0N/A CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A }
0N/A
0N/A // Import encoded certificate
0N/A if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,
0N/A CERT_STORE_ADD_REPLACE_EXISTING, NULL))
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (hCertStore)
0N/A ::CertCloseStore(hCertStore, 0);
0N/A
0N/A if (pszCertStoreName)
0N/A env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
0N/A
0N/A if (pbCertEncoding)
0N/A delete [] pbCertEncoding;
0N/A
0N/A if (pszCertAliasName)
0N/A delete [] pszCertAliasName;
0N/A
0N/A if (pszContainerName)
0N/A delete [] pszContainerName;
0N/A
0N/A if (pwszContainerName)
0N/A delete [] pwszContainerName;
0N/A
0N/A if (pszProviderName)
0N/A delete [] pszProviderName;
0N/A
0N/A if (pwszProviderName)
0N/A delete [] pwszProviderName;
0N/A
0N/A if (pCertContext)
0N/A ::CertFreeCertificateContext(pCertContext);
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: removeCertificate
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate
0N/A (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
0N/A jbyteArray jCertEncoding, jint jCertEncodingSize) {
0N/A
0N/A const char* pszCertStoreName = NULL;
0N/A const char* pszCertAliasName = NULL;
0N/A HCERTSTORE hCertStore = NULL;
0N/A PCCERT_CONTEXT pCertContext = NULL;
0N/A PCCERT_CONTEXT pTBDCertContext = NULL;
0N/A jbyte* pbCertEncoding = NULL;
0N/A DWORD cchNameString = 0;
0N/A char* pszNameString = NULL; // certificate's friendly name
0N/A BOOL bDeleteAttempted = FALSE;
0N/A
0N/A __try
0N/A {
0N/A // Open a system certificate store.
0N/A pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL);
0N/A if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Copy encoding from Java to native buffer
0N/A pbCertEncoding = new jbyte[jCertEncodingSize];
0N/A env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
0N/A
0N/A // Create a certificate context from the encoded cert
0N/A if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
0N/A (BYTE*) pbCertEncoding, jCertEncodingSize))) {
0N/A
0N/A ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Find the certificate to be deleted
0N/A if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,
0N/A X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Check that its friendly name matches the supplied alias
0N/A if ((cchNameString = ::CertGetNameString(pTBDCertContext,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {
0N/A
0N/A pszNameString = new char[cchNameString];
0N/A
0N/A ::CertGetNameString(pTBDCertContext,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
0N/A cchNameString);
0N/A
0N/A // Compare the certificate's friendly name with supplied alias name
0N/A pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL);
0N/A if (strcmp(pszCertAliasName, pszNameString) == 0) {
0N/A
0N/A // Only delete the certificate if the alias names matches
0N/A if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {
0N/A
0N/A // pTBDCertContext is always freed by the
0N/A // CertDeleteCertificateFromStore method
0N/A bDeleteAttempted = TRUE;
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A }
0N/A }
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (hCertStore)
0N/A ::CertCloseStore(hCertStore, 0);
0N/A
0N/A if (pszCertStoreName)
0N/A env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
0N/A
0N/A if (pszCertAliasName)
0N/A env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);
0N/A
0N/A if (pbCertEncoding)
0N/A delete [] pbCertEncoding;
0N/A
0N/A if (pszNameString)
0N/A delete [] pszNameString;
0N/A
0N/A if (pCertContext)
0N/A ::CertFreeCertificateContext(pCertContext);
0N/A
0N/A if (bDeleteAttempted && pTBDCertContext)
0N/A ::CertFreeCertificateContext(pTBDCertContext);
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: destroyKeyContainer
0N/A * Signature: (Ljava/lang/String;)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer
0N/A (JNIEnv *env, jclass clazz, jstring keyContainerName)
0N/A{
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A const char* pszKeyContainerName = NULL;
0N/A
0N/A __try
0N/A {
0N/A pszKeyContainerName = env->GetStringUTFChars(keyContainerName, NULL);
0N/A
0N/A // Destroying the default key container is not permitted
0N/A // (because it may contain more one keypair).
0N/A if (pszKeyContainerName == NULL) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM);
0N/A __leave;
0N/A }
0N/A
0N/A // Acquire a CSP context (to the key container).
0N/A if (::CryptAcquireContext(
0N/A &hCryptProv,
0N/A pszKeyContainerName,
0N/A NULL,
0N/A PROV_RSA_FULL,
0N/A CRYPT_DELETEKEYSET) == FALSE)
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (pszKeyContainerName)
0N/A env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
0N/A }
0N/A}
0N/A
0N/A
0N/A
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSACipher
0N/A * Method: findCertificateUsingAlias
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;)J
0N/A */
0N/AJNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_findCertificateUsingAlias
0N/A (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName)
0N/A{
0N/A const char* pszCertStoreName = NULL;
0N/A const char* pszCertAliasName = NULL;
0N/A HCERTSTORE hCertStore = NULL;
0N/A PCCERT_CONTEXT pCertContext = NULL;
0N/A char* pszNameString = NULL; // certificate's friendly name
0N/A DWORD cchNameString = 0;
0N/A
0N/A __try
0N/A {
0N/A pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL);
0N/A pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL);
0N/A
0N/A // Open a system certificate store.
0N/A if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Use CertEnumCertificatesInStore to get the certificates
0N/A // from the open store. pCertContext must be reset to
0N/A // NULL to retrieve the first certificate in the store.
0N/A while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
0N/A {
0N/A if ((cchNameString = ::CertGetNameString(pCertContext,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) == 1) {
0N/A
0N/A continue; // not found
0N/A }
0N/A
0N/A pszNameString = new char[cchNameString];
0N/A
0N/A if (::CertGetNameString(pCertContext,
0N/A CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
0N/A cchNameString) == 1) {
0N/A
0N/A continue; // not found
0N/A }
0N/A
0N/A // Compare the certificate's friendly name with supplied alias name
0N/A if (strcmp(pszCertAliasName, pszNameString) == 0) {
0N/A delete [] pszNameString;
0N/A break;
0N/A
0N/A } else {
0N/A delete [] pszNameString;
0N/A }
0N/A }
0N/A }
0N/A __finally
0N/A {
0N/A if (hCertStore)
0N/A ::CertCloseStore(hCertStore, 0);
0N/A
0N/A if (pszCertStoreName)
0N/A env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
0N/A
0N/A if (pszCertAliasName)
0N/A env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);
0N/A }
0N/A
0N/A return (jlong) pCertContext;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSACipher
0N/A * Method: getKeyFromCert
0N/A * Signature: (JZ)J
0N/A */
0N/AJNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_getKeyFromCert
0N/A (JNIEnv *env, jobject obj, jlong pCertContext, jboolean usePrivateKey)
0N/A{
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A HCRYPTKEY hKey = NULL;
0N/A DWORD dwKeySpec;
0N/A
0N/A __try
0N/A {
0N/A if (usePrivateKey == JNI_TRUE) {
0N/A // Locate the key container for the certificate's private key
0N/A if (!(::CryptAcquireCertificatePrivateKey(
0N/A (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
0N/A &dwKeySpec, NULL))) {
0N/A
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Get a handle to the private key
0N/A if (!(::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))) {
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A } else { // use public key
0N/A
0N/A // Acquire a CSP context.
0N/A if(::CryptAcquireContext(
0N/A &hCryptProv,
0N/A "J2SE",
0N/A NULL,
0N/A PROV_RSA_FULL,
0N/A 0) == FALSE)
0N/A {
0N/A // If CSP context hasn't been created, create one.
0N/A //
0N/A if (::CryptAcquireContext(
0N/A &hCryptProv,
0N/A "J2SE",
0N/A NULL,
0N/A PROV_RSA_FULL,
0N/A CRYPT_NEWKEYSET) == FALSE)
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A }
0N/A
0N/A // Import the certificate's public key into the key container
0N/A if (!(::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
0N/A &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
0N/A &hKey))) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A }
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (hCryptProv)
0N/A ::CryptReleaseContext(hCryptProv, 0);
0N/A }
0N/A
0N/A return hKey; // TODO - when finished with this key, call
0N/A // CryptDestroyKey(hKey)
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: getKeyLength
0N/A * Signature: (J)I
0N/A */
0N/AJNIEXPORT jint JNICALL Java_sun_security_mscapi_KeyStore_getKeyLength
0N/A (JNIEnv *env, jobject obj, jlong hKey)
0N/A{
0N/A DWORD dwDataLen = sizeof(DWORD);
0N/A BYTE pbData[sizeof(DWORD)];
0N/A DWORD length = 0;
0N/A
0N/A __try
0N/A {
0N/A // Get key length (in bits)
0N/A //TODO - may need to use KP_BLOCKLEN instead?
0N/A if (!(::CryptGetKeyParam((HCRYPTKEY) hKey, KP_KEYLEN, (BYTE *)pbData, &dwDataLen,
0N/A 0))) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A length = (DWORD) pbData;
0N/A }
0N/A __finally
0N/A {
0N/A // no cleanup required
0N/A }
0N/A
0N/A return (jint) length;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSACipher
0N/A * Method: encryptDecrypt
0N/A * Signature: ([BIJZ)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt
0N/A (JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
0N/A jboolean doEncrypt)
0N/A{
0N/A jbyteArray result = NULL;
0N/A jbyte* pData = NULL;
0N/A DWORD dwDataLen = jDataSize;
0N/A DWORD dwBufLen = env->GetArrayLength(jData);
0N/A DWORD i;
0N/A BYTE tmp;
0N/A
0N/A __try
0N/A {
0N/A // Copy data from Java buffer to native buffer
0N/A pData = new jbyte[dwBufLen];
0N/A env->GetByteArrayRegion(jData, 0, dwBufLen, pData);
0N/A
0N/A if (doEncrypt == JNI_TRUE) {
0N/A // encrypt
0N/A if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData,
0N/A &dwDataLen, dwBufLen)) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A dwBufLen = dwDataLen;
0N/A
0N/A // convert from little-endian
0N/A for (i = 0; i < dwBufLen / 2; i++) {
0N/A tmp = pData[i];
0N/A pData[i] = pData[dwBufLen - i -1];
0N/A pData[dwBufLen - i - 1] = tmp;
0N/A }
0N/A } else {
0N/A // convert to little-endian
0N/A for (i = 0; i < dwBufLen / 2; i++) {
0N/A tmp = pData[i];
0N/A pData[i] = pData[dwBufLen - i -1];
0N/A pData[dwBufLen - i - 1] = tmp;
0N/A }
0N/A
0N/A // decrypt
0N/A if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData,
0N/A &dwBufLen)) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A }
0N/A
0N/A // Create new byte array
0N/A result = env->NewByteArray(dwBufLen);
0N/A
0N/A // Copy data from native buffer to Java buffer
0N/A env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
0N/A }
0N/A __finally
0N/A {
0N/A if (pData)
0N/A delete [] pData;
0N/A }
0N/A
0N/A return result;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSAPublicKey
0N/A * Method: getPublicKeyBlob
0N/A * Signature: (J)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyBlob
0N/A (JNIEnv *env, jclass clazz, jlong hCryptKey) {
0N/A
0N/A jbyteArray blob = NULL;
0N/A DWORD dwBlobLen;
4111N/A BYTE* pbKeyBlob = NULL;
0N/A
0N/A __try
0N/A {
0N/A
0N/A // Determine the size of the blob
0N/A if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL,
0N/A &dwBlobLen)) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A pbKeyBlob = new BYTE[dwBlobLen];
0N/A
0N/A // Generate key blob
0N/A if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0,
0N/A pbKeyBlob, &dwBlobLen)) {
0N/A
0N/A ThrowException(env, KEY_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Create new byte array
0N/A blob = env->NewByteArray(dwBlobLen);
0N/A
0N/A // Copy data from native buffer to Java buffer
0N/A env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);
0N/A }
0N/A __finally
0N/A {
0N/A if (pbKeyBlob)
0N/A delete [] pbKeyBlob;
0N/A }
0N/A
0N/A return blob;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSAPublicKey
0N/A * Method: getExponent
0N/A * Signature: ([B)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent
0N/A (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) {
0N/A
0N/A jbyteArray exponent = NULL;
0N/A jbyte* exponentBytes = NULL;
0N/A jbyte* keyBlob = NULL;
0N/A
0N/A __try {
0N/A
0N/A jsize length = env->GetArrayLength(jKeyBlob);
0N/A keyBlob = env->GetByteArrayElements(jKeyBlob, 0);
0N/A
0N/A PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
0N/A
0N/A // Check BLOB type
0N/A if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
0N/A ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
0N/A __leave;
0N/A }
0N/A
0N/A RSAPUBKEY* pRsaPubKey =
0N/A (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
0N/A int len = sizeof(pRsaPubKey->pubexp);
0N/A exponentBytes = new jbyte[len];
0N/A
0N/A // convert from little-endian while copying from blob
0N/A for (int i = 0, j = len - 1; i < len; i++, j--) {
0N/A exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];
0N/A }
0N/A
0N/A exponent = env->NewByteArray(len);
0N/A env->SetByteArrayRegion(exponent, 0, len, exponentBytes);
0N/A }
0N/A __finally
0N/A {
0N/A if (keyBlob)
0N/A env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
0N/A
0N/A if (exponentBytes)
0N/A delete [] exponentBytes;
0N/A }
0N/A
0N/A return exponent;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSAPublicKey
0N/A * Method: getModulus
0N/A * Signature: ([B)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus
0N/A (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) {
0N/A
0N/A jbyteArray modulus = NULL;
0N/A jbyte* modulusBytes = NULL;
0N/A jbyte* keyBlob = NULL;
0N/A
0N/A __try {
0N/A
0N/A jsize length = env->GetArrayLength(jKeyBlob);
0N/A keyBlob = env->GetByteArrayElements(jKeyBlob, 0);
0N/A
0N/A PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
0N/A
0N/A // Check BLOB type
0N/A if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
0N/A ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
0N/A __leave;
0N/A }
0N/A
0N/A RSAPUBKEY* pRsaPubKey =
0N/A (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
0N/A int len = pRsaPubKey->bitlen / 8;
0N/A
0N/A modulusBytes = new jbyte[len];
0N/A BYTE * pbModulus =
0N/A (BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
0N/A
0N/A // convert from little-endian while copying from blob
0N/A for (int i = 0, j = len - 1; i < len; i++, j--) {
0N/A modulusBytes[i] = pbModulus[j];
0N/A }
0N/A
0N/A modulus = env->NewByteArray(len);
0N/A env->SetByteArrayRegion(modulus, 0, len, modulusBytes);
0N/A }
0N/A __finally
0N/A {
0N/A if (keyBlob)
0N/A env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
0N/A
0N/A if (modulusBytes)
0N/A delete [] modulusBytes;
0N/A }
0N/A
0N/A return modulus;
0N/A}
0N/A
0N/A/*
0N/A * Convert an array in big-endian byte order into little-endian byte order.
0N/A */
0N/Aint convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
0N/A int destinationLength) {
0N/A
0N/A int count = 0;
0N/A int sourceLength = env->GetArrayLength(source);
0N/A
0N/A if (sourceLength < destinationLength) {
0N/A return -1;
0N/A }
0N/A
0N/A jbyte* sourceBytes = env->GetByteArrayElements(source, 0);
0N/A
0N/A // Copy bytes from the end of the source array to the beginning of the
0N/A // destination array (until the destination array is full).
0N/A // This ensures that the sign byte from the source array will be excluded.
0N/A for (int i = 0; i < destinationLength; i++) {
0N/A destination[i] = sourceBytes[sourceLength - i - 1];
0N/A count++;
0N/A }
0N/A if (sourceBytes)
0N/A env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);
0N/A
0N/A return count;
0N/A}
0N/A
0N/A/*
0N/A * The Microsoft Base Cryptographic Provider supports public-key BLOBs
0N/A * that have the following format:
0N/A *
0N/A * PUBLICKEYSTRUC publickeystruc;
0N/A * RSAPUBKEY rsapubkey;
0N/A * BYTE modulus[rsapubkey.bitlen/8];
0N/A *
0N/A * and private-key BLOBs that have the following format:
0N/A *
0N/A * PUBLICKEYSTRUC publickeystruc;
0N/A * RSAPUBKEY rsapubkey;
0N/A * BYTE modulus[rsapubkey.bitlen/8];
0N/A * BYTE prime1[rsapubkey.bitlen/16];
0N/A * BYTE prime2[rsapubkey.bitlen/16];
0N/A * BYTE exponent1[rsapubkey.bitlen/16];
0N/A * BYTE exponent2[rsapubkey.bitlen/16];
0N/A * BYTE coefficient[rsapubkey.bitlen/16];
0N/A * BYTE privateExponent[rsapubkey.bitlen/8];
0N/A *
0N/A * This method generates such BLOBs from the key elements supplied.
0N/A */
0N/AjbyteArray generateKeyBlob(
0N/A JNIEnv *env,
0N/A jint jKeyBitLength,
0N/A jbyteArray jModulus,
0N/A jbyteArray jPublicExponent,
0N/A jbyteArray jPrivateExponent,
0N/A jbyteArray jPrimeP,
0N/A jbyteArray jPrimeQ,
0N/A jbyteArray jExponentP,
0N/A jbyteArray jExponentQ,
0N/A jbyteArray jCrtCoefficient)
0N/A{
0N/A jsize jKeyByteLength = jKeyBitLength / 8;
0N/A jsize jBlobLength;
0N/A BOOL bGeneratePrivateKeyBlob;
0N/A
0N/A // Determine whether to generate a public-key or a private-key BLOB
0N/A if (jPrivateExponent != NULL &&
0N/A jPrimeP != NULL &&
0N/A jPrimeQ != NULL &&
0N/A jExponentP != NULL &&
0N/A jExponentQ != NULL &&
0N/A jCrtCoefficient != NULL) {
0N/A
0N/A bGeneratePrivateKeyBlob = TRUE;
0N/A jBlobLength = sizeof(BLOBHEADER) +
0N/A sizeof(RSAPUBKEY) +
0N/A ((jKeyBitLength / 8) * 4) +
0N/A (jKeyBitLength / 16);
0N/A
0N/A } else {
0N/A bGeneratePrivateKeyBlob = FALSE;
0N/A jBlobLength = sizeof(BLOBHEADER) +
0N/A sizeof(RSAPUBKEY) +
0N/A (jKeyBitLength / 8);
0N/A }
0N/A
0N/A jbyte* jBlobBytes = new jbyte[jBlobLength];
0N/A jbyte* jBlobElement;
0N/A jbyteArray jBlob = NULL;
0N/A jsize jElementLength;
0N/A
0N/A __try {
0N/A
0N/A BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;
0N/A if (bGeneratePrivateKeyBlob) {
0N/A pBlobHeader->bType = PRIVATEKEYBLOB; // 0x07
0N/A } else {
0N/A pBlobHeader->bType = PUBLICKEYBLOB; // 0x06
0N/A }
0N/A pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02
0N/A pBlobHeader->reserved = 0; // 0x0000
0N/A pBlobHeader->aiKeyAlg = CALG_RSA_KEYX; // 0x0000a400
0N/A
0N/A RSAPUBKEY *pRsaPubKey =
0N/A (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));
0N/A if (bGeneratePrivateKeyBlob) {
0N/A pRsaPubKey->magic = 0x32415352; // "RSA2"
0N/A } else {
0N/A pRsaPubKey->magic = 0x31415352; // "RSA1"
0N/A }
0N/A pRsaPubKey->bitlen = jKeyBitLength;
0N/A pRsaPubKey->pubexp = 0; // init
0N/A
0N/A // Sanity check
0N/A jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
0N/A if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
4111N/A ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);
0N/A __leave;
0N/A }
0N/A // The length argument must be the smaller of jPublicExponentLength
0N/A // and sizeof(pRsaPubKey->pubkey)
0N/A convertToLittleEndian(env, jPublicExponent,
0N/A (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength);
0N/A
0N/A // Modulus n
0N/A jBlobElement =
0N/A (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
0N/A jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,
0N/A jKeyByteLength);
0N/A
0N/A if (bGeneratePrivateKeyBlob) {
0N/A // Prime p
0N/A jBlobElement += jElementLength;
0N/A jElementLength = convertToLittleEndian(env, jPrimeP, jBlobElement,
0N/A jKeyByteLength / 2);
0N/A
0N/A // Prime q
0N/A jBlobElement += jElementLength;
0N/A jElementLength = convertToLittleEndian(env, jPrimeQ, jBlobElement,
0N/A jKeyByteLength / 2);
0N/A
0N/A // Prime exponent p
0N/A jBlobElement += jElementLength;
0N/A jElementLength = convertToLittleEndian(env, jExponentP,
0N/A jBlobElement, jKeyByteLength / 2);
0N/A
0N/A // Prime exponent q
0N/A jBlobElement += jElementLength;
0N/A jElementLength = convertToLittleEndian(env, jExponentQ,
0N/A jBlobElement, jKeyByteLength / 2);
0N/A
0N/A // CRT coefficient
0N/A jBlobElement += jElementLength;
0N/A jElementLength = convertToLittleEndian(env, jCrtCoefficient,
0N/A jBlobElement, jKeyByteLength / 2);
0N/A
0N/A // Private exponent
0N/A jBlobElement += jElementLength;
0N/A convertToLittleEndian(env, jPrivateExponent, jBlobElement,
0N/A jKeyByteLength);
0N/A }
0N/A
0N/A jBlob = env->NewByteArray(jBlobLength);
0N/A env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A if (jBlobBytes)
0N/A delete [] jBlobBytes;
0N/A }
0N/A
0N/A return jBlob;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: generatePrivateKeyBlob
0N/A * Signature: (I[B[B[B[B[B[B[B[B)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_KeyStore_generatePrivateKeyBlob
0N/A (JNIEnv *env, jclass clazz,
0N/A jint jKeyBitLength,
0N/A jbyteArray jModulus,
0N/A jbyteArray jPublicExponent,
0N/A jbyteArray jPrivateExponent,
0N/A jbyteArray jPrimeP,
0N/A jbyteArray jPrimeQ,
0N/A jbyteArray jExponentP,
0N/A jbyteArray jExponentQ,
0N/A jbyteArray jCrtCoefficient)
0N/A{
0N/A return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
0N/A jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,
0N/A jCrtCoefficient);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSASignature
0N/A * Method: generatePublicKeyBlob
0N/A * Signature: (I[B[B)[B
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_generatePublicKeyBlob
0N/A (JNIEnv *env, jclass clazz,
0N/A jint jKeyBitLength,
0N/A jbyteArray jModulus,
0N/A jbyteArray jPublicExponent)
0N/A{
0N/A return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
0N/A NULL, NULL, NULL, NULL, NULL, NULL);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_KeyStore
0N/A * Method: storePrivateKey
0N/A * Signature: ([BLjava/lang/String;I)Lsun/security/mscapi/RSAPrivateKey;
0N/A */
0N/AJNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey
0N/A (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jstring keyContainerName,
0N/A jint keySize)
0N/A{
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A HCRYPTKEY hKey = NULL;
0N/A DWORD dwBlobLen;
0N/A BYTE * pbKeyBlob = NULL;
0N/A const char* pszKeyContainerName = NULL; // UUID
0N/A jobject privateKey = NULL;
0N/A
0N/A __try
0N/A {
0N/A pszKeyContainerName = env->GetStringUTFChars(keyContainerName, NULL);
0N/A dwBlobLen = env->GetArrayLength(keyBlob);
0N/A pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0);
0N/A
0N/A // Acquire a CSP context (create a new key container).
0N/A if (::CryptAcquireContext(
0N/A &hCryptProv,
0N/A pszKeyContainerName,
0N/A NULL,
0N/A PROV_RSA_FULL,
0N/A CRYPT_NEWKEYSET) == FALSE)
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Import the private key
0N/A if (::CryptImportKey(
0N/A hCryptProv,
0N/A pbKeyBlob,
0N/A dwBlobLen,
0N/A 0,
0N/A CRYPT_EXPORTABLE,
0N/A &hKey) == FALSE)
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Get the method ID for the RSAPrivateKey constructor
0N/A jclass clazzRSAPrivateKey =
0N/A env->FindClass("sun/security/mscapi/RSAPrivateKey");
0N/A
0N/A jmethodID mNewRSAPrivateKey =
0N/A env->GetMethodID(clazzRSAPrivateKey, "<init>", "(JJI)V");
0N/A
0N/A // Create a new RSA private key
0N/A privateKey = env->NewObject(clazzRSAPrivateKey, mNewRSAPrivateKey,
0N/A (jlong) hCryptProv, (jlong) hKey, keySize);
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (pszKeyContainerName)
0N/A env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
0N/A
0N/A if (pbKeyBlob)
0N/A env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
0N/A JNI_ABORT);
0N/A }
0N/A
0N/A return privateKey;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_security_mscapi_RSASignature
0N/A * Method: importPublicKey
0N/A * Signature: ([BI)Lsun/security/mscapi/RSAPublicKey;
0N/A */
0N/AJNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSASignature_importPublicKey
0N/A (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jint keySize)
0N/A{
0N/A HCRYPTPROV hCryptProv = NULL;
0N/A HCRYPTKEY hKey = NULL;
0N/A DWORD dwBlobLen;
0N/A BYTE * pbKeyBlob = NULL;
0N/A jobject publicKey = NULL;
0N/A
0N/A __try
0N/A {
0N/A dwBlobLen = env->GetArrayLength(keyBlob);
0N/A pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0);
0N/A
0N/A // Acquire a CSP context (create a new key container).
4127N/A // Prefer a PROV_RSA_AES CSP, when available, due to its support
4127N/A // for SHA-2-based signatures.
0N/A if (::CryptAcquireContext(
0N/A &hCryptProv,
0N/A NULL,
0N/A NULL,
4127N/A PROV_RSA_AES,
0N/A CRYPT_VERIFYCONTEXT) == FALSE)
0N/A {
4127N/A // Failover to using the default CSP (PROV_RSA_FULL)
4127N/A
4127N/A if (::CryptAcquireContext(
4127N/A &hCryptProv,
4127N/A NULL,
4127N/A NULL,
4127N/A PROV_RSA_FULL,
4127N/A CRYPT_VERIFYCONTEXT) == FALSE)
4127N/A {
4127N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
4127N/A __leave;
4127N/A }
0N/A }
0N/A
0N/A // Import the public key
0N/A if (::CryptImportKey(
0N/A hCryptProv,
0N/A pbKeyBlob,
0N/A dwBlobLen,
0N/A 0,
0N/A CRYPT_EXPORTABLE,
0N/A &hKey) == FALSE)
0N/A {
0N/A ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
0N/A __leave;
0N/A }
0N/A
0N/A // Get the method ID for the RSAPublicKey constructor
0N/A jclass clazzRSAPublicKey =
0N/A env->FindClass("sun/security/mscapi/RSAPublicKey");
0N/A
0N/A jmethodID mNewRSAPublicKey =
0N/A env->GetMethodID(clazzRSAPublicKey, "<init>", "(JJI)V");
0N/A
0N/A // Create a new RSA public key
0N/A publicKey = env->NewObject(clazzRSAPublicKey, mNewRSAPublicKey,
0N/A (jlong) hCryptProv, (jlong) hKey, keySize);
0N/A
0N/A }
0N/A __finally
0N/A {
0N/A //--------------------------------------------------------------------
0N/A // Clean up.
0N/A
0N/A if (pbKeyBlob)
0N/A env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
0N/A JNI_ABORT);
0N/A }
0N/A
0N/A return publicKey;
0N/A}
0N/A
0N/A} /* extern "C" */