--- a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Thu Aug 18 17:51:40 2016 -0400
+++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Fri Aug 19 01:41:54 2016 +0300
@@ -358,38 +358,50 @@
BOOL bHasNoPrivateKey = FALSE;
DWORD dwPublicKeyLength = 0;
- if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL,
- &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
+ // First, probe it silently
+ if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL,
+ &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
+ && GetLastError() != NTE_SILENT_CONTEXT)
{
bHasNoPrivateKey = TRUE;
-
- } else {
- // Private key is available
-
- BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
-
- // Skip certificate if cannot find private key
- if (bGetUserKey == FALSE)
- {
- if (bCallerFreeProv)
- ::CryptReleaseContext(hCryptProv, NULL);
-
- continue;
+ }
+ else
+ {
+ if (bCallerFreeProv == TRUE) {
+ ::CryptReleaseContext(hCryptProv, NULL);
+ bCallerFreeProv = FALSE;
}
- // Set cipher mode to ECB
- DWORD dwCipherMode = CRYPT_MODE_ECB;
- ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
-
+ // Second, acquire the key normally (not silently)
+ if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL,
+ &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
+ {
+ bHasNoPrivateKey = TRUE;
+ }
+ else
+ {
+ // Private key is available
+ BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
- // If the private key is present in smart card, we may not be able to
- // determine the key length by using the private key handle. However,
- // since public/private key pairs must have the same length, we could
- // determine the key length of the private key by using the public key
- // in the certificate.
- dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+ // Skip certificate if cannot find private key
+ if (bGetUserKey == FALSE) {
+ if (bCallerFreeProv)
+ ::CryptReleaseContext(hCryptProv, NULL);
+ continue;
+ }
+ // Set cipher mode to ECB
+ DWORD dwCipherMode = CRYPT_MODE_ECB;
+ ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
+
+ // If the private key is present in smart card, we may not be able to
+ // determine the key length by using the private key handle. However,
+ // since public/private key pairs must have the same length, we could
+ // determine the key length of the private key by using the public key
+ // in the certificate.
+ dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+ }
}
PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
@@ -398,8 +410,7 @@
//
if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
{
-
- for (unsigned int i=0; i < pCertChainContext->cChain; i++)
+ for (DWORD i = 0; i < pCertChainContext->cChain; i++)
{
// Found cert chain
PCERT_SIMPLE_CHAIN rgpChain =
@@ -449,6 +460,7 @@
// cert collection
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
}
+
if (bHasNoPrivateKey)
{
// Generate certificate chain and store into cert chain
@@ -1367,43 +1379,57 @@
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwKeySpec;
+ BOOL bCallerFreeProv = FALSE;
+ BOOL bRes;
__try
{
if (usePrivateKey == JNI_TRUE) {
// Locate the key container for the certificate's private key
- if (!(::CryptAcquireCertificatePrivateKey(
- (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
- &dwKeySpec, NULL))) {
+
+ // First, probe it silently
+ bRes = ::CryptAcquireCertificatePrivateKey(
+ (PCCERT_CONTEXT) pCertContext, CRYPT_ACQUIRE_SILENT_FLAG,
+ NULL, &hCryptProv, &dwKeySpec, &bCallerFreeProv);
+ if (bRes == FALSE && GetLastError() != NTE_SILENT_CONTEXT)
+ {
+ ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
+ __leave;
+ }
+
+ if (bCallerFreeProv == TRUE) {
+ ::CryptReleaseContext(hCryptProv, NULL);
+ bCallerFreeProv = FALSE;
+ }
+
+ // Now, do it normally (not silently)
+ if (::CryptAcquireCertificatePrivateKey(
+ (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
+ &dwKeySpec, &bCallerFreeProv) == FALSE)
+ {
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
__leave;
}
// Get a handle to the private key
- if (!(::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))) {
+ if (::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey) == FALSE) {
ThrowException(env, KEY_EXCEPTION, GetLastError());
__leave;
}
-
- } else { // use public key
+ }
+ else // use public key
+ {
+ bCallerFreeProv = TRUE;
// Acquire a CSP context.
- if(::CryptAcquireContext(
- &hCryptProv,
- "J2SE",
- NULL,
- PROV_RSA_FULL,
- 0) == FALSE)
+ if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+ PROV_RSA_FULL, 0) == FALSE)
{
// If CSP context hasn't been created, create one.
//
- if (::CryptAcquireContext(
- &hCryptProv,
- "J2SE",
- NULL,
- PROV_RSA_FULL,
- CRYPT_NEWKEYSET) == FALSE)
+ if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+ PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE)
{
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
__leave;
@@ -1411,10 +1437,10 @@
}
// Import the certificate's public key into the key container
- if (!(::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
- &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
- &hKey))) {
-
+ if (::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
+ &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
+ &hKey) == FALSE)
+ {
ThrowException(env, KEY_EXCEPTION, GetLastError());
__leave;
}
@@ -1425,7 +1451,7 @@
//--------------------------------------------------------------------
// Clean up.
- if (hCryptProv)
+ if (bCallerFreeProv == TRUE && hCryptProv != NULL)
::CryptReleaseContext(hCryptProv, 0);
}