crypt32: correct the implementation of CertCreateSelfSignCertificate

Mounir IDRASSI mounir.idrassi at idrix.fr
Wed May 9 21:01:03 CDT 2007


Hi,
This patch corrects the implementation of the function
CertCreateSelfSignCertificate to be more close to MSDN documentation.
Two internal functions (CertContext_SetKeyProvInfo and
CRYPT_CreateSignedCert) have been modified to accommodate this change.
Another new test have been also added to demonstrate the new
capabilities implemented in CertCreateSelfSignCertificate. This test
have been validated under Windows.

Mounir IDRASSI
IDRIX - Cryptography and IT Security Experts
http://www.idrix.fr

-------------- next part --------------
>From 14dcc5e7f893665154186af6c7ff5361155925bb Mon Sep 17 00:00:00 2001
From: Mounir IDRASSI <mounir.idrassi at idrix.fr>
Date: Thu, 10 May 2007 03:53:04 +0200
Subject: crypt32: correct the implementation of CertCreateSelfSignCertificate

---
 dlls/crypt32/cert.c       |   88 ++++++++++++++++++++++++++++++++++++--------
 dlls/crypt32/tests/cert.c |   49 +++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 16 deletions(-)

diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index d20a49f..6c59061 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)
         {
@@ -2193,7 +2249,7 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
             CRYPT_DER_BLOB blob = { 0, NULL };
             BYTE serial[16];
             CRYPT_DATA_BLOB serialBlob = { sizeof(serial), serial };
-
+	    
             CryptGenRandom(hProv, sizeof(serial), serial);
             CRYPT_MakeCertInfo(&info, &serialBlob, pSubjectIssuerBlob,
              pSignatureAlgorithm, pStartTime, pEndTime, pubKey, pExtensions);
@@ -2201,9 +2257,9 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
              &info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&blob.pbData,
              &blob.cbData);
             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,
-- 
1.4.4.2



More information about the wine-patches mailing list