Juan Lang : rsaenh: Honor a key's permissions when exporting a private key.

Alexandre Julliard julliard at winehq.org
Thu Jan 29 09:14:59 CST 2009


Module: wine
Branch: master
Commit: e8ea6700ca4f33765d1dedf5f27777791264b59a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e8ea6700ca4f33765d1dedf5f27777791264b59a

Author: Juan Lang <juan.lang at gmail.com>
Date:   Wed Jan 28 21:18:32 2009 -0800

rsaenh: Honor a key's permissions when exporting a private key.

---

 dlls/rsaenh/rsaenh.c       |  103 +++++++++++++++++++++++++++++--------------
 dlls/rsaenh/tests/rsaenh.c |    2 -
 2 files changed, 69 insertions(+), 36 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index cccbcf3..059dad2 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -311,13 +311,12 @@ RSAENH_CPDestroyHash(
     HCRYPTHASH hHash
 );
 
-BOOL WINAPI 
-RSAENH_CPExportKey(
-    HCRYPTPROV hProv, 
-    HCRYPTKEY hKey, 
+static BOOL crypt_export_key(
+    CRYPTKEY *pCryptKey,
     HCRYPTKEY hPubKey, 
     DWORD dwBlobType, 
     DWORD dwFlags, 
+    BOOL force,
     BYTE *pbData, 
     DWORD *pdwDataLen
 );
@@ -911,14 +910,13 @@ static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, D
     if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
                       (OBJECTHDR**)&pKey))
     {
-        if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
-            &dwLen))
+        if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
         {
             pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
             if (pbKey)
             {
-                if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
-                                       PRIVATEKEYBLOB, 0, pbKey, &dwLen))
+                if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
+                    &dwLen))
                 {
                     blobIn.pbData = pbKey;
                     blobIn.cbData = dwLen;
@@ -2282,8 +2280,8 @@ static BOOL crypt_export_public_key(CRYPTKEY *pCryptKey, BYTE *pbData,
     return TRUE;
 }
 
-static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
-    DWORD *pdwDataLen)
+static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BOOL force,
+    BYTE *pbData, DWORD *pdwDataLen)
 {
     BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
     RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
@@ -2293,6 +2291,11 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
         SetLastError(NTE_BAD_KEY);
         return FALSE;
     }
+    if (!force && !(pCryptKey->dwPermissions & CRYPT_EXPORT))
+    {
+        SetLastError(NTE_BAD_KEY_STATE);
+        return FALSE;
+    }
 
     dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
                 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
@@ -2319,16 +2322,19 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
 }
 
 /******************************************************************************
- * CPExportKey (RSAENH.@)
+ * crypt_export_key [Internal]
  *
- * Export a key into a binary large object (BLOB).
+ * Export a key into a binary large object (BLOB).  Called by CPExportKey and
+ * by store_key_pair.
  *
  * PARAMS
- *  hProv      [I]   Key container from which a key is to be exported.
- *  hKey       [I]   Key to be exported.
+ *  pCryptKey  [I]   Key to be exported.
  *  hPubKey    [I]   Key used to encrypt sensitive BLOB data.
  *  dwBlobType [I]   SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
  *  dwFlags    [I]   Currently none defined.
+ *  force      [I]   If TRUE, the key is written no matter what the key's
+ *                   permissions are.  Otherwise the key's permissions are
+ *                   checked before exporting.
  *  pbData     [O]   Pointer to a buffer where the BLOB will be written to.
  *  pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
  *
@@ -2336,26 +2342,12 @@ static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BYTE *pbData,
  *  Success: TRUE.
  *  Failure: FALSE.
  */
-BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, 
-                               DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
+static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
+                             DWORD dwBlobType, DWORD dwFlags, BOOL force,
+                             BYTE *pbData, DWORD *pdwDataLen)
 {
-    CRYPTKEY *pCryptKey, *pPubKey;
+    CRYPTKEY *pPubKey;
     
-    TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
-          "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
-    
-    if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
-    {
-        SetLastError(NTE_BAD_UID);
-        return FALSE;
-    }
-
-    if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
-    {
-        SetLastError(NTE_BAD_KEY);
-        return FALSE;
-    }
-
     if (dwFlags & CRYPT_SSL2_FALLBACK) {
         if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
             SetLastError(NTE_BAD_KEY);
@@ -2370,7 +2362,8 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
                 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
                 return FALSE;
             }
-            return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData, pdwDataLen);
+            return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData,
+                                       pdwDataLen);
             
         case PUBLICKEYBLOB:
             if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
@@ -2381,7 +2374,7 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
             return crypt_export_public_key(pCryptKey, pbData, pdwDataLen);
 
         case PRIVATEKEYBLOB:
-            return crypt_export_private_key(pCryptKey, pbData, pdwDataLen);
+            return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen);
             
         default:
             SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
@@ -2390,6 +2383,48 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
 }
 
 /******************************************************************************
+ * CPExportKey (RSAENH.@)
+ *
+ * Export a key into a binary large object (BLOB).
+ *
+ * PARAMS
+ *  hProv      [I]   Key container from which a key is to be exported.
+ *  hKey       [I]   Key to be exported.
+ *  hPubKey    [I]   Key used to encrypt sensitive BLOB data.
+ *  dwBlobType [I]   SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
+ *  dwFlags    [I]   Currently none defined.
+ *  pbData     [O]   Pointer to a buffer where the BLOB will be written to.
+ *  pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
+                               DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
+{
+    CRYPTKEY *pCryptKey;
+
+    TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
+          "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
+
+    if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
+    {
+        SetLastError(NTE_BAD_UID);
+        return FALSE;
+    }
+
+    if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
+    {
+        SetLastError(NTE_BAD_KEY);
+        return FALSE;
+    }
+
+    return crypt_export_key(pCryptKey, hPubKey, dwBlobType, dwFlags, FALSE,
+        pbData, pdwDataLen);
+}
+
+/******************************************************************************
  * CPImportKey (RSAENH.@)
  *
  * Import a BLOB'ed key into a key container.
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index e13bc1c..57ca35f 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -1574,7 +1574,6 @@ static void test_rsa_encrypt(void)
     /* but its private key may not be. */
     SetLastError(0xdeadbeef);
     result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
-    todo_wine
     ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
         "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
     /* Setting the permissions of the key exchange key isn't allowed, either. */
@@ -1606,7 +1605,6 @@ static void test_rsa_encrypt(void)
     /* but its private key may not be. */
     SetLastError(0xdeadbeef);
     result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
-    todo_wine
     ok(!result && GetLastError() == NTE_BAD_KEY_STATE,
         "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
     /* Setting the permissions of the signature key isn't allowed, either. */




More information about the wine-cvs mailing list