Commit 204bdb87 authored by Mounir IDRASSI's avatar Mounir IDRASSI Committed by Alexandre Julliard

crypt32: Correct the implementation of CertCreateSelfSignCertificate.

parent d7596086
......@@ -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,
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment