rsaenh: fix bugs in RSAENH_CPAcquireContext and RSAENH_CPGetProvParam

Mounir IDRASSI mounir.idrassi at idrix.fr
Sun May 6 17:02:09 CDT 2007


Hi,
The attached patch corrects the following bugs in MS Enhanced CSP
implementation in wine and adds tests that illustrate them.
    - In RSAENH_CPAcquireContext : when specifying CRYPT_DELETEKEYSET,
the function always deletes the container for the local user, while it
should check the CRYPT_MACHINE_KEYSET flag to see if it should be
deleted on the local machine or for the local user.
    - In RSAENH_CPGetProvParam: The following mandatory parameters were
not supported : PP_UNIQUE_CONTAINER, PP_PROVTYPE, PP_KEYSPEC,
PP_KEYSET_TYPE, PP_KEYSTORAGE.

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

-------------- next part --------------
>From 33a9a1f1573299c9b83c2d699dd4ac31f097a682 Mon Sep 17 00:00:00 2001
From: Mounir IDRASSI <mounir.idrassi at idrix.fr>
Date: Sun, 6 May 2007 21:36:08 +0200
Subject: rsaenh: fix bugs in RSAENH_CPAcquireContext and RSAENH_CPGetProvParam

---
 dlls/rsaenh/rsaenh.c       |   32 ++++++++++++++++++++++-
 dlls/rsaenh/tests/rsaenh.c |   61 ++++++++++++++++++++++++++++++++++++++++---
 include/wincrypt.h         |    5 +++
 3 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index 2ace2d5..488b90c 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -1473,7 +1473,13 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
                 SetLastError(NTE_BAD_KEYSET_PARAM);
                 return FALSE;
             } else {
-                if (!RegDeleteKeyA(HKEY_CURRENT_USER, szRegKey)) {
+		HKEY hRootKey;
+                if (dwFlags & CRYPT_MACHINE_KEYSET)
+                    hRootKey = HKEY_LOCAL_MACHINE;
+                else
+                    hRootKey = HKEY_CURRENT_USER;
+	
+                if (!RegDeleteKeyA(hRootKey, szRegKey)) {
                     SetLastError(ERROR_SUCCESS);
                     return TRUE;
                 } else {
@@ -2899,6 +2905,7 @@ BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
     switch (dwParam) 
     {
         case PP_CONTAINER:
+        case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */		
             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName, 
                               strlen(pKeyContainer->szName)+1);
 
@@ -2906,6 +2913,29 @@ BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName, 
                               strlen(pKeyContainer->szProvName)+1);
 
+        case PP_PROVTYPE:
+	    dwTemp = PROV_RSA_FULL;
+            return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
+
+        case PP_KEYSPEC:
+            dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE;
+            return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
+
+        case PP_KEYSET_TYPE:
+	    dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET;
+	    return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
+
+        case PP_KEYSTORAGE:
+            dwTemp = GetVersion();
+            /* for Windows NT, 95,98, Me, return CRYPT_PSTORE | CRYPT_UI_PROMPT | CRYPT_SEC_DESCR
+	     * for the others, return CRYPT_SEC_DESCR
+	     */
+	    if(dwTemp < 0x80000000 && ((dwTemp & 0x000000FF)  != 0x00000004))
+               dwTemp = CRYPT_SEC_DESCR;
+            else
+               dwTemp = CRYPT_PSTORE | CRYPT_UI_PROMPT | CRYPT_SEC_DESCR;
+	    return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
+
         case PP_SIG_KEYSIZE_INC:
         case PP_KEYX_KEYSIZE_INC:
             dwTemp = 8;
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index fe27f4b..dd7013b 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -1480,7 +1480,8 @@ static void test_null_provider(void)
     HCRYPTPROV prov;
     HCRYPTKEY key;
     BOOL result;
-    DWORD keySpec, dataLen;
+    DWORD keySpec, dataLen,dwParam;
+    char szName[MAX_PATH];
 
     result = CryptAcquireContext(NULL, szContainer, NULL, 0, 0);
     ok(!result && GetLastError() == NTE_BAD_PROV_TYPE,
@@ -1513,10 +1514,23 @@ static void test_null_provider(void)
      CRYPT_VERIFYCONTEXT);
     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
     if (!result) return;
+    /* Test provider parameters getter */
+    dataLen = sizeof(dwParam);
+    result = CryptGetProvParam(prov, PP_PROVTYPE, (LPBYTE)&dwParam, &dataLen, 0);
+    ok(result && dataLen == sizeof(dwParam) && dwParam == PROV_RSA_FULL,
+	"Expected PROV_RSA_FULL, got 0x%08X\n",dwParam);
+    dataLen = sizeof(dwParam);
+    result = CryptGetProvParam(prov, PP_KEYSET_TYPE, (LPBYTE)&dwParam, &dataLen, 0);
+    ok(result && dataLen == sizeof(dwParam) && dwParam == 0,
+	"Expected 0, got 0x%08X\n",dwParam);
+    dataLen = sizeof(dwParam);
+    result = CryptGetProvParam(prov, PP_KEYSTORAGE, (LPBYTE)&dwParam, &dataLen, 0);
+    ok(result && dataLen == sizeof(dwParam) && (dwParam & CRYPT_SEC_DESCR),
+	"Expected CRYPT_SEC_DESCR to be set, got 0x%08X\n",dwParam);    
+    
     dataLen = sizeof(keySpec);
     result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
-    if (result)
-        ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
+    ok(result && keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
          "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
     /* Even though PP_KEYSPEC says both AT_KEYEXCHANGE and AT_SIGNATURE are
      * supported, you can't get the keys from this container.
@@ -1558,9 +1572,21 @@ static void test_null_provider(void)
     if (!result) return;
     dataLen = sizeof(keySpec);
     result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
-    if (result)
-        ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
+    ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
          "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
+    /* PP_CONTAINER parameter */
+    dataLen = sizeof(szName);
+    result = CryptGetProvParam(prov, PP_CONTAINER, (LPBYTE)szName, &dataLen, 0);    
+    ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
+	"failed getting PP_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
+	(result)? "TRUE":"FALSE",GetLastError(),dataLen);
+    /* PP_UNIQUE_CONTAINER parameter */
+    dataLen = sizeof(szName);    
+    result = CryptGetProvParam(prov, PP_UNIQUE_CONTAINER, (LPBYTE)szName, &dataLen, 0);    
+    ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
+	"failed getting PP_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
+	(result)? "TRUE":"FALSE",GetLastError(),dataLen);
+    
     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
     ok(!result && GetLastError() == NTE_NO_KEY,
      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
@@ -1603,6 +1629,31 @@ static void test_null_provider(void)
 
     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
      CRYPT_DELETEKEYSET);
+    
+    /* test the machine key set */
+    CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
+     CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);   
+    result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
+     CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET);
+    ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
+    /* check PP_KEYSET_TYPE parameter */
+    dataLen = sizeof(dwParam);
+    result = CryptGetProvParam(prov, PP_KEYSET_TYPE, (LPBYTE)&dwParam, &dataLen, 0);
+    ok(result && dataLen == sizeof(dwParam) && dwParam == CRYPT_MACHINE_KEYSET,
+	"Expected CRYPT_MACHINE_KEYSET, got 0x%08X\n",dwParam);
+    CryptReleaseContext(prov, 0);
+    result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
+     CRYPT_MACHINE_KEYSET);
+    ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
+    CryptReleaseContext(prov,0);
+    result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
+       CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET); 
+    ok(result, "CryptAcquireContext with CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET failed: %08x\n", 
+		GetLastError());
+    result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
+     CRYPT_MACHINE_KEYSET);
+    ok(!result && GetLastError() == NTE_BAD_KEYSET ,
+	"Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
 }
 
 START_TEST(rsaenh)
diff --git a/include/wincrypt.h b/include/wincrypt.h
index 2219bd5..2aaa89b 100644
--- a/include/wincrypt.h
+++ b/include/wincrypt.h
@@ -1613,6 +1613,11 @@ static const WCHAR MS_SCARD_PROV_W[] =           { 'M','i','c','r','o','s','o','
 #define PP_KEYSPEC              39
 #define PP_ENUMEX_SIGNING_PROT  40
 
+/* Values returned by CryptGetProvParam of PP_KEYSTORAGE */
+#define CRYPT_SEC_DESCR		0x00000001
+#define CRYPT_PSTORE			0x00000002
+#define CRYPT_UI_PROMPT		0x00000004
+
 /* Crypt{Get/Set}KeyParam */
 #define KP_IV                   1
 #define KP_SALT                 2
-- 
1.4.4.2



More information about the wine-patches mailing list