Mounir IDRASSI : crypt32:
Correct the implementation of CertCreateSelfSignCertificate.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu May 10 07:49:58 CDT 2007
Module: wine
Branch: master
Commit: 204bdb8755d65511c7b85eecfeb1eca27d4b3027
URL: http://source.winehq.org/git/wine.git/?a=commit;h=204bdb8755d65511c7b85eecfeb1eca27d4b3027
Author: Mounir IDRASSI <mounir.idrassi at idrix.fr>
Date: Thu May 10 04:01:03 2007 +0200
crypt32: Correct the implementation of CertCreateSelfSignCertificate.
---
dlls/crypt32/cert.c | 82 +++++++++++++++++++++++++++++++++++++-------
dlls/crypt32/tests/cert.c | 49 +++++++++++++++++++++++++++
2 files changed, 118 insertions(+), 13 deletions(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index d20a49f..884c2da 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -1970,10 +1970,10 @@ static void CertContext_SetKeyProvInfo(PCCERT_CONTEXT context,
}
}
size = sizeof(info.dwKeySpec);
- ret = CryptGetProvParam(hProv, PP_KEYSPEC, (LPBYTE)&info.dwKeySpec,
- &size, 0);
- if (!ret)
- info.dwKeySpec = AT_SIGNATURE;
+ /* in case no CRYPT_KEY_PROV_INFO given,
+ * we always use AT_SIGNATURE key spec
+ */
+ info.dwKeySpec = AT_SIGNATURE;
size = sizeof(info.dwProvType);
ret = CryptGetProvParam(hProv, PP_PROVTYPE, (LPBYTE)&info.dwProvType,
&size, 0);
@@ -1996,19 +1996,19 @@ static void CertContext_SetKeyProvInfo(PCCERT_CONTEXT context,
* in blob, using the crypto provider hProv and the signature algorithm sigAlgo.
*/
static PCCERT_CONTEXT CRYPT_CreateSignedCert(const CRYPT_DER_BLOB *blob,
- HCRYPTPROV hProv, PCRYPT_ALGORITHM_IDENTIFIER sigAlgo)
+ HCRYPTPROV hProv, DWORD dwKeySpec, PCRYPT_ALGORITHM_IDENTIFIER sigAlgo)
{
PCCERT_CONTEXT context = NULL;
BOOL ret;
DWORD sigSize = 0;
- ret = CryptSignCertificate(hProv, AT_SIGNATURE, X509_ASN_ENCODING,
+ ret = CryptSignCertificate(hProv, dwKeySpec, X509_ASN_ENCODING,
blob->pbData, blob->cbData, sigAlgo, NULL, NULL, &sigSize);
if (ret)
{
LPBYTE sig = CryptMemAlloc(sigSize);
- ret = CryptSignCertificate(hProv, AT_SIGNATURE, X509_ASN_ENCODING,
+ ret = CryptSignCertificate(hProv, dwKeySpec, X509_ASN_ENCODING,
blob->pbData, blob->cbData, sigAlgo, NULL, sig, &sigSize);
if (ret)
{
@@ -2168,24 +2168,80 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
PCCERT_CONTEXT context = NULL;
BOOL ret, releaseContext = FALSE;
PCERT_PUBLIC_KEY_INFO pubKey = NULL;
- DWORD pubKeySize = 0;
+ DWORD pubKeySize = 0,dwKeySpec = AT_SIGNATURE;
TRACE("(%08lx, %p, %08x, %p, %p, %p, %p, %p)\n", hProv,
pSubjectIssuerBlob, dwFlags, pKeyProvInfo, pSignatureAlgorithm, pStartTime,
pExtensions, pExtensions);
+ if(!pSubjectIssuerBlob)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
if (!hProv)
{
- hProv = CRYPT_CreateKeyProv();
- releaseContext = TRUE;
+ if (!pKeyProvInfo)
+ {
+ hProv = CRYPT_CreateKeyProv();
+ releaseContext = TRUE;
+ }
+ else if (pKeyProvInfo->dwFlags & CERT_SET_KEY_PROV_HANDLE_PROP_ID)
+ {
+ SetLastError(NTE_BAD_FLAGS);
+ return NULL;
+ }
+ else
+ {
+ HCRYPTKEY hKey = 0;
+ /* acquire the context using the given information*/
+ ret = CryptAcquireContextW(&hProv,pKeyProvInfo->pwszContainerName,
+ pKeyProvInfo->pwszProvName,pKeyProvInfo->dwProvType,
+ pKeyProvInfo->dwFlags);
+ if (!ret)
+ {
+ if(GetLastError() != NTE_BAD_KEYSET)
+ return NULL;
+ /* create the key set */
+ ret = CryptAcquireContextW(&hProv,pKeyProvInfo->pwszContainerName,
+ pKeyProvInfo->pwszProvName,pKeyProvInfo->dwProvType,
+ pKeyProvInfo->dwFlags|CRYPT_NEWKEYSET);
+ if (!ret)
+ return NULL;
+ }
+ dwKeySpec = pKeyProvInfo->dwKeySpec;
+ /* check if the key is here */
+ ret = CryptGetUserKey(hProv,dwKeySpec,&hKey);
+ if(!ret)
+ {
+ if (NTE_NO_KEY == GetLastError())
+ { /* generate the key */
+ ret = CryptGenKey(hProv,dwKeySpec,0,&hKey);
+ }
+ if (!ret)
+ {
+ CryptReleaseContext(hProv,0);
+ SetLastError(NTE_BAD_KEYSET);
+ return NULL;
+ }
+ }
+ CryptDestroyKey(hKey);
+ releaseContext = TRUE;
+ }
+ }
+ else if (pKeyProvInfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
}
- CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
+ CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING, NULL,
&pubKeySize);
pubKey = CryptMemAlloc(pubKeySize);
if (pubKey)
{
- ret = CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING,
+ ret = CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING,
pubKey, &pubKeySize);
if (ret)
{
@@ -2203,7 +2259,7 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
if (ret)
{
if (!(dwFlags & CERT_CREATE_SELFSIGN_NO_SIGN))
- context = CRYPT_CreateSignedCert(&blob, hProv,
+ context = CRYPT_CreateSignedCert(&blob, hProv,dwKeySpec,
&info.SignatureAlgorithm);
else
context = CertCreateCertificateContext(X509_ASN_ENCODING,
diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c
index 345c9f5..cdc6cfb 100644
--- a/dlls/crypt32/tests/cert.c
+++ b/dlls/crypt32/tests/cert.c
@@ -1157,6 +1157,7 @@ static void testCreateSelfSignCert(void)
HCRYPTPROV csp;
BOOL ret;
HCRYPTKEY key;
+ CRYPT_KEY_PROV_INFO info;
/* This crashes:
context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
@@ -1228,6 +1229,54 @@ static void testCreateSelfSignCert(void)
CryptReleaseContext(csp, 0);
ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
CRYPT_DELETEKEYSET);
+
+ /* do the same test with AT_KEYEXCHANGE and key info*/
+ memset(&info,0,sizeof(info));
+ info.dwProvType = PROV_RSA_FULL;
+ info.dwKeySpec = AT_KEYEXCHANGE;
+ info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
+ info.pwszContainerName = cspNameW;
+ context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
+ NULL, NULL);
+ ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
+ GetLastError());
+ if (context)
+ {
+ DWORD size = 0;
+ PCRYPT_KEY_PROV_INFO info;
+
+ /* The context must have a key provider info property */
+ ret = CertGetCertificateContextProperty(context,
+ CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
+ ok(ret && size, "Expected non-zero key provider info\n");
+ if (size)
+ {
+ info = HeapAlloc(GetProcessHeap(), 0, size);
+ if (info)
+ {
+ ret = CertGetCertificateContextProperty(context,
+ CERT_KEY_PROV_INFO_PROP_ID, info, &size);
+ ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
+ GetLastError());
+ if (ret)
+ {
+ /* Sanity-check the key provider */
+ ok(!lstrcmpW(info->pwszContainerName, cspNameW),
+ "Unexpected key container\n");
+ ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
+ "Unexpected provider\n");
+ ok(info->dwKeySpec == AT_KEYEXCHANGE,
+ "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
+ }
+ HeapFree(GetProcessHeap(), 0, info);
+ }
+ }
+
+ CertFreeCertificateContext(context);
+ }
+
+ CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
+ CRYPT_DELETEKEYSET);
}
static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
More information about the wine-cvs
mailing list