From 204bdb8755d65511c7b85eecfeb1eca27d4b3027 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 10 May 2007 04:01:03 +0200 Subject: [PATCH] crypt32: Correct the implementation of CertCreateSelfSignCertificate. --- dlls/crypt32/cert.c | 84 ++++++++++++++++++++++++++++++++------- dlls/crypt32/tests/cert.c | 49 +++++++++++++++++++++++ 2 files changed, 119 insertions(+), 14 deletions(-) diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index d20a49f8f5c..884c2da66fa 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 (!hProv) + if(!pSubjectIssuerBlob) { - hProv = CRYPT_CreateKeyProv(); - releaseContext = TRUE; + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; } - CryptExportPublicKeyInfo(hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, + if (!hProv) + { + 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, 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 345c9f5a92d..cdc6cfb94a3 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,