[PATCH 2/2] dssenh:implement CPAcquireContext and CPReleaseContext.

shuai zhang wxsxsdz at gmail.com
Sat Nov 16 04:24:51 CST 2019


---
 dlls/dssenh/Makefile.in        |   5 +-
 dlls/dssenh/cryptoprovconfig.h |  85 +++++
 dlls/dssenh/dssenh.c           |  96 ++++-
 dlls/dssenh/dssenh.rgs         |  28 ++
 dlls/rsaenh/Makefile.in        |   3 +-
 dlls/rsaenh/cryptoprovconfig.h |  88 +++++
 dlls/rsaenh/cryptoprovutils.c  | 649 ++++++++++++++++++++++++++++++++
 dlls/rsaenh/cryptoprovutils.h  |  81 ++++
 dlls/rsaenh/rsaenh.c           | 656 +--------------------------------
 9 files changed, 1026 insertions(+), 665 deletions(-)
 create mode 100644 dlls/dssenh/cryptoprovconfig.h
 create mode 100644 dlls/rsaenh/cryptoprovconfig.h
 create mode 100644 dlls/rsaenh/cryptoprovutils.c
 create mode 100644 dlls/rsaenh/cryptoprovutils.h

diff --git a/dlls/dssenh/Makefile.in b/dlls/dssenh/Makefile.in
index 54295f99ba..cb34ad3ae2 100644
--- a/dlls/dssenh/Makefile.in
+++ b/dlls/dssenh/Makefile.in
@@ -1,10 +1,13 @@
 MODULE    = dssenh.dll
 IMPORTLIB = dssenh
 IMPORTS   = bcrypt crypt32 advapi32
+EXTRAINCL = -I$(top_srcdir)/dlls/

 EXTRADLLFLAGS = -mno-cygwin

 C_SRCS = \
- dssenh.c
+ dssenh.c \
+ ../rsaenh/cryptoprovutils.c \
+ ../rsaenh/handle.c

 RC_SRCS = rsrc.rc
diff --git a/dlls/dssenh/cryptoprovconfig.h b/dlls/dssenh/cryptoprovconfig.h
new file mode 100644
index 0000000000..f6e307bc96
--- /dev/null
+++ b/dlls/dssenh/cryptoprovconfig.h
@@ -0,0 +1,85 @@
+/*
+ * dlls/rsaenh/cryptoprovconfig.h
+ * Definitions of some constants used by crypto provider.
+ * It is copied to build dir then included by cryptoprovutils.h,
+ * the build dir comes first in include search paths.
+ * So a new provider implementation only needs to provide its own
+ * cryptoprovconfig.h.
+ *
+ * Copyright 2002 TransGaming Technologies (David Hammerton)
+ * Copyright 2004 Mike McCormack for CodeWeavers
+ * Copyright 2004, 2005 Michael Jung
+ * Copyright 2007 Vijay Kiran Kamuju
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_CRYPTOPROVCONFIG_H
+#define __WINE_CRYPTOPROVCONFIG_H
+#define DSSENH_MAGIC_KEY           0x73620457u
+#define DSSENH_MAX_KEY_SIZE        64
+#define DSSENH_MAX_BLOCK_SIZE      24
+#define DSSENH_MAGIC_CONTAINER     0x26384993u
+#define DSSENH_REGKEY              "Software\\Wine\\Crypto\\DSS\\%s"
+
+#define CRYPTO_PROV_MAGIC_KEY           DSSENH_MAGIC_KEY
+#define CRYPTO_PROV_MAX_KEY_SIZE        DSSENH_MAX_KEY_SIZE
+#define CRYPTO_PROV_MAX_BLOCK_SIZE      DSSENH_MAX_BLOCK_SIZE
+#define CRYPTO_PROV_MAGIC_CONTAINER     DSSENH_MAGIC_CONTAINER
+#define CRYPTO_PROV_REGKEY              DSSENH_REGKEY
+
+/******************************************************************************
+ * CRYPTKEY - key objects
+ */
+#define DSSENH_KEYSTATE_IDLE       0
+#define DSSENH_KEYSTATE_ENCRYPTING 1
+#define DSSENH_KEYSTATE_MASTERKEY  2
+typedef struct _DSSENH_SCHANNEL_INFO
+{
+    SCHANNEL_ALG saEncAlg;
+    SCHANNEL_ALG saMACAlg;
+    CRYPT_DATA_BLOB blobClientRandom;
+    CRYPT_DATA_BLOB blobServerRandom;
+} DSSENH_SCHANNEL_INFO;
+#define CRYPTO_PROV_SCHANNEL_INFO       DSSENH_SCHANNEL_INFO
+
+/******************************************************************************
+ * KEYCONTAINER - key containers
+ */
+#define DSSENH_PERSONALITY_BASE        0u
+#define DSSENH_PERSONALITY_BASE_DH     1u
+#define DSSENH_PERSONALITY_ENHANCED    2u
+#define DSSENH_PERSONALITY_SCHANNEL    3u
+
+/******************************************************************************
+ * Used by new_key_container to determine the personality via provider name.
+ * The first entry in aProvNamePersonalityPairs should be the default
personality.
+ */
+typedef struct tagPROVNAMEPERSONALITYPAIR
+{
+    LPCSTR pszProvName;
+    DWORD  dwPersonality;
+} PROVNAMEPERSONALITYPAIR;
+
+static const DWORD dwNProvNamePersonalityPairs = 0;
+static const PROVNAMEPERSONALITYPAIR aProvNamePersonalityPairs[6] =
+{
+    {"", DSSENH_PERSONALITY_ENHANCED},
+    {MS_DEF_DSS_PROV_A, DSSENH_PERSONALITY_BASE},
+    {MS_DEF_DSS_DH_PROV_A, DSSENH_PERSONALITY_BASE_DH},
+    {MS_DEF_DH_SCHANNEL_PROV_A, DSSENH_PERSONALITY_SCHANNEL}
+};
+
+#endif /* __WINE_CRYPTOPROVCONFIG_H */
diff --git a/dlls/dssenh/dssenh.c b/dlls/dssenh/dssenh.c
index 5dc5464724..a3c8af8f48 100644
--- a/dlls/dssenh/dssenh.c
+++ b/dlls/dssenh/dssenh.c
@@ -21,21 +21,39 @@

 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
 #include "wincrypt.h"
+#include "objbase.h"
+#include "rpcproxy.h"
+#include "rsaenh/handle.h"
+#include "rsaenh/cryptoprovutils.h"
 #include "wine/debug.h"

+
 WINE_DEFAULT_DEBUG_CHANNEL(dssenh);

-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+static HINSTANCE instance;
+
+/******************************************************************************
+ * CSP's handle table (used by all acquired key containers)
+ */
+struct handle_table handle_table;
+
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID reserved)
 {
-    TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+    TRACE("(0x%p, %d, %p)\n", hInstance, fdwReason, reserved);

     switch (fdwReason)
     {
-        case DLL_WINE_PREATTACH:
-            return FALSE;    /* prefer native version */
         case DLL_PROCESS_ATTACH:
-            DisableThreadLibraryCalls(hinstDLL);
+            instance = hInstance;
+            DisableThreadLibraryCalls(hInstance);
+            init_handle_table(&handle_table);
+            break;
+
+        case DLL_PROCESS_DETACH:
+            if (reserved) break;
+            destroy_handle_table(&handle_table);
             break;
     }
     return TRUE;
@@ -46,8 +64,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD
fdwReason, LPVOID lpvReserved)
  */
 HRESULT WINAPI DllRegisterServer(void)
 {
-    FIXME("Not implemented.\n");
-    return E_UNEXPECTED;
+    return __wine_register_resources( instance );
 }

 /*****************************************************
@@ -55,8 +72,63 @@ HRESULT WINAPI DllRegisterServer(void)
  */
 HRESULT WINAPI DllUnregisterServer(void)
 {
-    FIXME("Not implemented.\n");
-    return E_UNEXPECTED;
+    return __wine_unregister_resources( instance );
+}
+
+/******************************************************************************
+ * crypt_export_key [Internal]
+ *
+ * Export a key into a binary large object (BLOB).  Called by CPExportKey and
+ * by store_key_pair.
+ *
+ * PARAMS
+ *  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
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
+                             DWORD dwBlobType, DWORD dwFlags, BOOL force,
+                             BYTE *pbData, DWORD *pdwDataLen)
+{
+    FIXME("stub\n");
+    return FALSE;
+}
+
+/******************************************************************************
+ * import_key [Internal]
+ *
+ * Import a BLOB'ed key into a key container, optionally storing the key's
+ * value to the registry.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the key is to be imported.
+ *  pbData    [I] Pointer to a buffer which holds the BLOB.
+ *  dwDataLen [I] Length of data in buffer at pbData.
+ *  hPubKey   [I] Key used to decrypt sensitive BLOB data.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  fStoreKey [I] If TRUE, the imported key is stored to the registry.
+ *  phKey     [O] Handle to the imported key.
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+BOOL import_key(HCRYPTPROV hProv, const BYTE *pbData, DWORD
dwDataLen, HCRYPTKEY hPubKey,
+                       DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
+{
+    FIXME("stub\n");
+    return FALSE;
 }

 /******************************************************************************
@@ -87,8 +159,7 @@ HRESULT WINAPI DllUnregisterServer(void)
 BOOL WINAPI DSSENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
                    DWORD dwFlags, PVTableProvStruc pVTable)
 {
-    FIXME("stub\n");
-    return FALSE;
+    return CRYPTO_PROV_CPAcquireContext(phProv, pszContainer,
dwFlags, pVTable);
 }

 /******************************************************************************
@@ -573,8 +644,7 @@ BOOL WINAPI DSSENH_CPImportKey(HCRYPTPROV hProv,
const BYTE *pbData, DWORD dwDat
  */
 BOOL WINAPI DSSENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
 {
-    FIXME("stub\n");
-    return FALSE;
+    return CRYPTO_PROV_CPReleaseContext(hProv, dwFlags);
 }

 /******************************************************************************
diff --git a/dlls/dssenh/dssenh.rgs b/dlls/dssenh/dssenh.rgs
index 19899cb516..e16d8e0bc7 100644
--- a/dlls/dssenh/dssenh.rgs
+++ b/dlls/dssenh/dssenh.rgs
@@ -16,6 +16,24 @@ HKLM
                             val 'Signature' = b deadbeef
                             val 'Type' = d 13
                         }
+                        ForceRemove 'Microsoft Base DSS and
Diffie-Hellman Cryptographic Provider'
+                        {
+                            val 'Image Path' = s '%MODULE%'
+                            val 'Signature' = b deadbeef
+                            val 'Type' = d 13
+                        }
+                        ForceRemove 'Microsoft Base DSS Cryptographic Provider'
+                        {
+                            val 'Image Path' = s '%MODULE%'
+                            val 'Signature' = b deadbeef
+                            val 'Type' = d 3
+                        }
+                        ForceRemove 'Microsoft DH SChannel
Cryptographic Provider'
+                        {
+                            val 'Image Path' = s '%MODULE%'
+                            val 'Signature' = b deadbeef
+                            val 'Type' = d 18
+                        }
                     }
                     NoRemove 'Provider Types'
                     {
@@ -24,6 +42,16 @@ HKLM
                             val 'Name' = s 'Microsoft Enhanced DSS
and Diffie-Hellman Cryptographic Provider'
                             val 'TypeName' = s 'DSS Signature with
Diffe-zhellman Key Exchange'
                         }
+                        ForceRemove 'Type 003'
+                        {
+                            val 'Name' = s 'Microsoft Base DSS
Cryptographic Provider'
+                            val 'TypeName' = s 'DSS Signature'
+                        }
+                        ForceRemove 'Type 018'
+                        {
+                            val 'Name' = s 'Microsoft DH SChannel
Cryptographic Provider'
+                            val 'TypeName' = s 'Diffie-Hellman SChannel'
+                        }
                     }
                 }
             }
diff --git a/dlls/rsaenh/Makefile.in b/dlls/rsaenh/Makefile.in
index 80680d6622..dd8574fcaf 100644
--- a/dlls/rsaenh/Makefile.in
+++ b/dlls/rsaenh/Makefile.in
@@ -13,6 +13,7 @@ C_SRCS = \
  rc2.c \
  rc4.c \
  rsa.c \
- rsaenh.c
+ rsaenh.c \
+ cryptoprovutils.c

 RC_SRCS = rsrc.rc
diff --git a/dlls/rsaenh/cryptoprovconfig.h b/dlls/rsaenh/cryptoprovconfig.h
new file mode 100644
index 0000000000..667bb475ac
--- /dev/null
+++ b/dlls/rsaenh/cryptoprovconfig.h
@@ -0,0 +1,88 @@
+/*
+ * dlls/rsaenh/cryptoprovconfig.h
+ * Definitions of some constants used by crypto provider.
+ * It is copied to build dir then included by cryptoprovutils.h,
+ * the build dir comes first in include search paths.
+ * So a new provider implementation only needs to provide its own
+ * cryptoprovconfig.h.
+ *
+ * Copyright 2002 TransGaming Technologies (David Hammerton)
+ * Copyright 2004 Mike McCormack for CodeWeavers
+ * Copyright 2004, 2005 Michael Jung
+ * Copyright 2007 Vijay Kiran Kamuju
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_CRYPTOPROVCONFIG_H
+#define __WINE_CRYPTOPROVCONFIG_H
+#define RSAENH_MAGIC_KEY           0x73620457u
+#define RSAENH_MAX_KEY_SIZE        64
+#define RSAENH_MAX_BLOCK_SIZE      24
+#define RSAENH_MAGIC_CONTAINER     0x26384993u
+#define RSAENH_REGKEY              "Software\\Wine\\Crypto\\RSA\\%s"
+
+#define CRYPTO_PROV_MAGIC_KEY           RSAENH_MAGIC_KEY
+#define CRYPTO_PROV_MAX_KEY_SIZE        RSAENH_MAX_KEY_SIZE
+#define CRYPTO_PROV_MAX_BLOCK_SIZE      RSAENH_MAX_BLOCK_SIZE
+#define CRYPTO_PROV_MAGIC_CONTAINER     RSAENH_MAGIC_CONTAINER
+#define CRYPTO_PROV_REGKEY              RSAENH_REGKEY
+
+/******************************************************************************
+ * CRYPTKEY - key objects
+ */
+#define RSAENH_KEYSTATE_IDLE       0
+#define RSAENH_KEYSTATE_ENCRYPTING 1
+#define RSAENH_KEYSTATE_MASTERKEY  2
+typedef struct _RSAENH_SCHANNEL_INFO
+{
+    SCHANNEL_ALG saEncAlg;
+    SCHANNEL_ALG saMACAlg;
+    CRYPT_DATA_BLOB blobClientRandom;
+    CRYPT_DATA_BLOB blobServerRandom;
+} RSAENH_SCHANNEL_INFO;
+#define CRYPTO_PROV_SCHANNEL_INFO       RSAENH_SCHANNEL_INFO
+
+/******************************************************************************
+ * KEYCONTAINER - key containers
+ */
+#define RSAENH_PERSONALITY_BASE        0u
+#define RSAENH_PERSONALITY_STRONG      1u
+#define RSAENH_PERSONALITY_ENHANCED    2u
+#define RSAENH_PERSONALITY_SCHANNEL    3u
+#define RSAENH_PERSONALITY_AES         4u
+
+/******************************************************************************
+ * Used by new_key_container to determine the personality via provider name.
+ * The first entry in aProvNamePersonalityPairs should be the default
personality.
+ */
+typedef struct tagPROVNAMEPERSONALITYPAIR
+{
+    LPCSTR pszProvName;
+    DWORD  dwPersonality;
+} PROVNAMEPERSONALITYPAIR;
+
+static const DWORD dwNProvNamePersonalityPairs = 6;
+static const PROVNAMEPERSONALITYPAIR aProvNamePersonalityPairs[6] =
+{
+    {"", RSAENH_PERSONALITY_STRONG},
+    {MS_DEF_PROV_A, RSAENH_PERSONALITY_BASE},
+    {MS_ENHANCED_PROV_A, RSAENH_PERSONALITY_ENHANCED},
+    {MS_DEF_RSA_SCHANNEL_PROV_A, RSAENH_PERSONALITY_SCHANNEL},
+    {MS_ENH_RSA_AES_PROV_A, RSAENH_PERSONALITY_AES},
+    {MS_ENH_RSA_AES_PROV_XP_A, RSAENH_PERSONALITY_AES}
+};
+
+#endif /* __WINE_CRYPTOPROVCONFIG_H */
diff --git a/dlls/rsaenh/cryptoprovutils.c b/dlls/rsaenh/cryptoprovutils.c
new file mode 100644
index 0000000000..c37c4e7925
--- /dev/null
+++ b/dlls/rsaenh/cryptoprovutils.c
@@ -0,0 +1,649 @@
+/*
+ * dlls/rsaenh/cryptoprovutils.c
+ * Utility functions to implement crypto privider.
+ *
+ * Copyright 2002 TransGaming Technologies (David Hammerton)
+ * Copyright 2004 Mike McCormack for CodeWeavers
+ * Copyright 2004, 2005 Michael Jung
+ * Copyright 2007 Vijay Kiran Kamuju
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wincrypt.h"
+#include "handle.h"
+#include "cryptoprovutils.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+extern struct handle_table handle_table;
+
+/******************************************************************************
+ * create_container_key [Internal]
+ *
+ * Creates the registry key for a key container's persistent storage.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container
+ *  sam           [I] Desired registry access
+ *  phKey         [O] Returned key
+ */
+BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey)
+{
+    CHAR szBase[sizeof(CRYPTO_PROV_REGKEY) + MAX_PATH];
+    HKEY hRootKey;
+
+    sprintf(szBase, CRYPTO_PROV_REGKEY, pKeyContainer->szName);
+
+    if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
+        hRootKey = HKEY_LOCAL_MACHINE;
+    else
+        hRootKey = HKEY_CURRENT_USER;
+
+    /* @@ Wine registry key: HKLM\Software\Wine\Crypto\[CRYPTO_PROV] */
+    /* @@ Wine registry key: HKCU\Software\Wine\Crypto\[CRYPTO_PROV] */
+    return RegCreateKeyExA(hRootKey, szBase, 0, NULL,
+                           REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
+                           == ERROR_SUCCESS;
+}
+
+/******************************************************************************
+ * open_container_key [Internal]
+ *
+ * Opens a key container's persistent storage for reading.
+ *
+ * PARAMS
+ *  pszContainerName [I] Name of the container to be opened.  May be the empty
+ *                       string if the parent key of all containers is to be
+ *                       opened.
+ *  dwFlags          [I] Flags indicating which keyset to be opened.
+ *  phKey            [O] Returned key
+ */
+BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags,
REGSAM access, HKEY *phKey)
+{
+    CHAR szRegBase[sizeof(CRYPTO_PROV_REGKEY) + MAX_PATH];
+    HKEY hRootKey;
+
+    sprintf(szRegBase, CRYPTO_PROV_REGKEY, pszContainerName);
+
+    if (dwFlags & CRYPT_MACHINE_KEYSET)
+        hRootKey = HKEY_LOCAL_MACHINE;
+    else
+        hRootKey = HKEY_CURRENT_USER;
+
+    /* @@ Wine registry key: HKLM\Software\Wine\Crypto\[CRYPTO_PROV] */
+    /* @@ Wine registry key: HKCU\Software\Wine\Crypto\[CRYPTO_PROV] */
+    return RegOpenKeyExA(hRootKey, szRegBase, 0, access, phKey) ==
+                         ERROR_SUCCESS;
+}
+
+/******************************************************************************
+ * delete_container_key [Internal]
+ *
+ * Deletes a key container's persistent storage.
+ *
+ * PARAMS
+ *  pszContainerName [I] Name of the container to be opened.
+ *  dwFlags          [I] Flags indicating which keyset to be opened.
+ */
+static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
+{
+    CHAR szRegKey[sizeof(CRYPTO_PROV_REGKEY) + MAX_PATH];
+    HKEY hRootKey;
+
+    sprintf(szRegKey, CRYPTO_PROV_REGKEY, pszContainerName);
+
+    if (dwFlags & CRYPT_MACHINE_KEYSET)
+        hRootKey = HKEY_LOCAL_MACHINE;
+    else
+        hRootKey = HKEY_CURRENT_USER;
+    if (!RegDeleteKeyA(hRootKey, szRegKey)) {
+        SetLastError(ERROR_SUCCESS);
+        return TRUE;
+    } else {
+        SetLastError(NTE_BAD_KEYSET);
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+ * new_key_container [Internal]
+ *
+ * Create a new key container. The personality of the CSP is determined via
+ * the pVTable->pszProvName string.
+ *
+ * PARAMS
+ *  pszContainerName [I] Name of the key container.
+ *  pVTable          [I] Callback functions and context info provided by the OS
+ *
+ * RETURNS
+ *  Success: Handle to the new key container.
+ *  Failure: INVALID_HANDLE_VALUE
+ */
+HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags,
const VTableProvStruc *pVTable)
+{
+    KEYCONTAINER *pKeyContainer;
+    HCRYPTPROV hKeyContainer;
+    DWORD i;
+
+    hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER),
+                CRYPTO_PROV_MAGIC_CONTAINER, destroy_key_container,
+        (OBJECTHDR**)&pKeyContainer);
+    if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
+    {
+        lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
+        pKeyContainer->dwFlags = dwFlags;
+        pKeyContainer->dwEnumAlgsCtr = 0;
+        pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
+        pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
+        if (pVTable && pVTable->pszProvName) {
+            lstrcpynA(pKeyContainer->szProvName,
pVTable->pszProvName, MAX_PATH);
+            pKeyContainer->dwPersonality
+                = aProvNamePersonalityPairs[0].dwPersonality;
+            for (i = 1; i < dwNProvNamePersonalityPairs; i++) {
+                if (!strcmp(pVTable->pszProvName,
+                            aProvNamePersonalityPairs[i].pszProvName)) {
+                    pKeyContainer->dwPersonality
+                        = aProvNamePersonalityPairs[i].dwPersonality;
+     break;
+                }
+            }
+        }
+
+        /* The new key container has to be inserted into the CSP immediately
+         * after creation to be available for CPGetProvParam's
PP_ENUMCONTAINERS. */
+        if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
+            HKEY hKey;
+
+            if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
+                RegCloseKey(hKey);
+        }
+    }
+
+    return hKeyContainer;
+}
+
+/******************************************************************************
+ * destroy_key_container [Internal]
+ *
+ * Destructor for key containers.
+ *
+ * PARAMS
+ *  pObjectHdr [I] Pointer to the key container to be destroyed.
+ */
+void destroy_key_container(OBJECTHDR *pObjectHdr)
+{
+    KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
+
+    if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
+    {
+        store_key_container_keys(pKeyContainer);
+        store_key_container_permissions(pKeyContainer);
+        release_key_container_keys(pKeyContainer);
+    }
+    else
+        release_key_container_keys(pKeyContainer);
+    HeapFree( GetProcessHeap(), 0, pKeyContainer );
+}
+
+/******************************************************************************
+ * store_key_container_keys [Internal]
+ *
+ * Stores key container's keys in a persistent location.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container whose keys are to be saved
+ */
+void store_key_container_keys(KEYCONTAINER *pKeyContainer)
+{
+    HKEY hKey;
+    DWORD dwFlags;
+
+    /* On WinXP, persistent keys are stored in a file located at:
+     * $AppData$\\Microsoft\\Crypto\\[CRYPTO_PROV]\\$SID$\\some_hex_string
+     */
+
+    if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
+        dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
+    else
+        dwFlags = 0;
+
+    if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
+    {
+        store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
+                       AT_KEYEXCHANGE, dwFlags);
+        store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
+                       AT_SIGNATURE, dwFlags);
+        RegCloseKey(hKey);
+    }
+}
+
+/******************************************************************************
+ * store_key_pair [Internal]
+ *
+ * Stores a key pair to the registry
+ *
+ * PARAMS
+ *  hCryptKey     [I] Handle to the key to be stored
+ *  hKey          [I] Registry key where the key pair is to be stored
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *  dwFlags       [I] Flags for protecting the key
+ */
+void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec,
DWORD dwFlags)
+{
+    LPCSTR szValueName;
+    DATA_BLOB blobIn, blobOut;
+    CRYPTKEY *pKey;
+    DWORD dwLen;
+    BYTE *pbKey;
+
+    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
+        return;
+    if (lookup_handle(&handle_table, hCryptKey, CRYPTO_PROV_MAGIC_KEY,
+                      (OBJECTHDR**)&pKey))
+    {
+        if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
+        {
+            pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
+            if (pbKey)
+            {
+                if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
+                    &dwLen))
+                {
+                    blobIn.pbData = pbKey;
+                    blobIn.cbData = dwLen;
+
+                    if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
+                        dwFlags, &blobOut))
+                    {
+                        RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
+                                       blobOut.pbData, blobOut.cbData);
+                        LocalFree(blobOut.pbData);
+                    }
+                }
+                HeapFree(GetProcessHeap(), 0, pbKey);
+            }
+        }
+    }
+}
+
+/******************************************************************************
+ * store_key_container_permissions [Internal]
+ *
+ * Stores key container's key permissions in a persistent location.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container whose key permissions are to
+ *                    be saved
+ */
+void store_key_container_permissions(KEYCONTAINER *pKeyContainer)
+{
+    HKEY hKey;
+
+    if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
+    {
+        store_key_permissions(pKeyContainer->hKeyExchangeKeyPair, hKey,
+                       AT_KEYEXCHANGE);
+        store_key_permissions(pKeyContainer->hSignatureKeyPair, hKey,
+                       AT_SIGNATURE);
+        RegCloseKey(hKey);
+    }
+}
+
+/******************************************************************************
+ * store_key_permissions [Internal]
+ *
+ * Stores a key's permissions to the registry
+ *
+ * PARAMS
+ *  hCryptKey     [I] Handle to the key whose permissions are to be stored
+ *  hKey          [I] Registry key where the key permissions are to be stored
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ */
+void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+    CRYPTKEY *pKey;
+
+    if (!(szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
+        return;
+    if (lookup_handle(&handle_table, hCryptKey, CRYPTO_PROV_MAGIC_KEY,
+                      (OBJECTHDR**)&pKey))
+        RegSetValueExA(hKey, szValueName, 0, REG_DWORD,
+                       (BYTE *)&pKey->dwPermissions,
+                       sizeof(pKey->dwPermissions));
+}
+
+/******************************************************************************
+ * release_key_container_keys [Internal]
+ *
+ * Releases key container's keys.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container whose keys are to
be released.
+ */
+void release_key_container_keys(KEYCONTAINER *pKeyContainer)
+{
+    release_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair,
+                   CRYPTO_PROV_MAGIC_KEY);
+    release_handle(&handle_table, pKeyContainer->hSignatureKeyPair,
+                   CRYPTO_PROV_MAGIC_KEY);
+}
+
+/******************************************************************************
+ * map_key_spec_to_key_pair_name [Internal]
+ *
+ * Returns the name of the registry value associated with a key spec.
+ *
+ * PARAMS
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *
+ * RETURNS
+ *  Success: Name of registry value.
+ *  Failure: NULL
+ */
+LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+
+    switch (dwKeySpec)
+    {
+    case AT_KEYEXCHANGE:
+        szValueName = "KeyExchangeKeyPair";
+        break;
+    case AT_SIGNATURE:
+        szValueName = "SignatureKeyPair";
+        break;
+    default:
+        WARN("invalid key spec %d\n", dwKeySpec);
+        szValueName = NULL;
+    }
+    return szValueName;
+}
+
+/******************************************************************************
+ * map_key_spec_to_permissions_name [Internal]
+ *
+ * Returns the name of the registry value associated with the permissions for
+ * a key spec.
+ *
+ * PARAMS
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *
+ * RETURNS
+ *  Success: Name of registry value.
+ *  Failure: NULL
+ */
+LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+
+    switch (dwKeySpec)
+    {
+    case AT_KEYEXCHANGE:
+        szValueName = "KeyExchangePermissions";
+        break;
+    case AT_SIGNATURE:
+        szValueName = "SignaturePermissions";
+        break;
+    default:
+        WARN("invalid key spec %d\n", dwKeySpec);
+        szValueName = NULL;
+    }
+    return szValueName;
+}
+
+/******************************************************************************
+ * read_key_value [Internal]
+ *
+ * Reads a key pair value from the registry
+ *
+ * PARAMS
+ *  hKeyContainer [I] Crypt provider to use to import the key
+ *  hKey          [I] Registry key from which to read the key pair
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *  dwFlags       [I] Flags for unprotecting the key
+ *  phCryptKey    [O] Returned key
+ */
+static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, DWORD
dwKeySpec, DWORD dwFlags, HCRYPTKEY *phCryptKey)
+{
+    LPCSTR szValueName;
+    DWORD dwValueType, dwLen;
+    BYTE *pbKey;
+    DATA_BLOB blobIn, blobOut;
+    BOOL ret = FALSE;
+
+    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
+        return FALSE;
+    if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
+        ERROR_SUCCESS)
+    {
+        pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
+        if (pbKey)
+        {
+            if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType,
pbKey, &dwLen) ==
+                ERROR_SUCCESS)
+            {
+                blobIn.pbData = pbKey;
+                blobIn.cbData = dwLen;
+
+                if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
+                    dwFlags, &blobOut))
+                {
+                    ret = import_key(hKeyContainer, blobOut.pbData,
blobOut.cbData, 0, 0,
+                                     FALSE, phCryptKey);
+                    LocalFree(blobOut.pbData);
+                }
+            }
+            HeapFree(GetProcessHeap(), 0, pbKey);
+        }
+    }
+    if (ret)
+    {
+        CRYPTKEY *pKey;
+
+        if (lookup_handle(&handle_table, *phCryptKey, CRYPTO_PROV_MAGIC_KEY,
+                          (OBJECTHDR**)&pKey))
+        {
+            if ((szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
+            {
+                dwLen = sizeof(pKey->dwPermissions);
+                RegQueryValueExA(hKey, szValueName, 0, NULL,
+                                 (BYTE *)&pKey->dwPermissions, &dwLen);
+            }
+        }
+    }
+    return ret;
+}
+
+/******************************************************************************
+ * read_key_container [Internal]
+ *
+ * Tries to read the persistent state of the key container (mainly
the signature
+ * and key exchange private keys) given by pszContainerName.
+ *
+ * PARAMS
+ *  pszContainerName [I] Name of the key container to read from the registry
+ *  pVTable          [I] Pointer to context data provided by the
operating system
+ *
+ * RETURNS
+ *  Success: Handle to the key container read from the registry
+ *  Failure: INVALID_HANDLE_VALUE
+ */
+static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD
dwFlags, const VTableProvStruc *pVTable)
+{
+    HKEY hKey;
+    KEYCONTAINER *pKeyContainer;
+    HCRYPTPROV hKeyContainer;
+    HCRYPTKEY hCryptKey;
+
+    if (!open_container_key(pszContainerName, dwFlags, KEY_READ, &hKey))
+    {
+        SetLastError(NTE_BAD_KEYSET);
+        return (HCRYPTPROV)INVALID_HANDLE_VALUE;
+    }
+
+    hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
+    if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
+    {
+        DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
+            CRYPTPROTECT_LOCAL_MACHINE : 0;
+
+        if (!lookup_handle(&handle_table, hKeyContainer,
CRYPTO_PROV_MAGIC_CONTAINER,
+                           (OBJECTHDR**)&pKeyContainer))
+            return (HCRYPTPROV)INVALID_HANDLE_VALUE;
+
+        /* read_key_value calls import_key, which calls import_private_key,
+         * which implicitly installs the key value into the appropriate key
+         * container key.  Thus the ref count is incremented twice, once for
+         * the output key value, and once for the implicit install, and needs
+         * to be decremented to balance the two.
+         */
+        if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE,
+            dwProtectFlags, &hCryptKey))
+            release_handle(&handle_table, hCryptKey, CRYPTO_PROV_MAGIC_KEY);
+        if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE,
+            dwProtectFlags, &hCryptKey))
+            release_handle(&handle_table, hCryptKey, CRYPTO_PROV_MAGIC_KEY);
+    }
+
+    return hKeyContainer;
+}
+
+/******************************************************************************
+ * CPAcquireContext (CRYPTO_PROV_PFX.@)
+ *
+ * Acquire a handle to the key container specified by pszContainer
+ *
+ * PARAMS
+ *  phProv       [O] Pointer to the location the acquired handle will
be written to.
+ *  pszContainer [I] Name of the desired key container. See Notes
+ *  dwFlags      [I] Flags. See Notes.
+ *  pVTable      [I] Pointer to a PVTableProvStruct containing callbacks.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  If pszContainer is NULL or points to a zero length string the user's login
+ *  name will be used as the key container name.
+ *
+ *  If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will
be created.
+ *  If a keyset with the given name already exists, the function fails and sets
+ *  last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
+ *  key container does not exist, function fails and sets last error to
+ *  NTE_BAD_KEYSET.
+ */
+BOOL CRYPTO_PROV_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
+                                  DWORD dwFlags, PVTableProvStruc pVTable)
+{
+    CHAR szKeyContainerName[MAX_PATH];
+
+    TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
+          debugstr_a(pszContainer), dwFlags, pVTable);
+
+    if (pszContainer && *pszContainer)
+    {
+        lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
+    }
+    else
+    {
+        DWORD dwLen = sizeof(szKeyContainerName);
+        if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
+    }
+
+    switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
+    {
+        case 0:
+            *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
+            break;
+
+        case CRYPT_DELETEKEYSET:
+            return delete_container_key(szKeyContainerName, dwFlags);
+
+        case CRYPT_NEWKEYSET:
+            *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
+            if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
+            {
+                release_handle(&handle_table, *phProv,
CRYPTO_PROV_MAGIC_CONTAINER);
+                TRACE("Can't create new keyset, already exists\n");
+                SetLastError(NTE_EXISTS);
+                return FALSE;
+            }
+            *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
+            break;
+
+        case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
+        case CRYPT_VERIFYCONTEXT:
+            if (pszContainer && *pszContainer) {
+                TRACE("pszContainer should be empty\n");
+                SetLastError(NTE_BAD_FLAGS);
+                return FALSE;
+            }
+            *phProv = new_key_container("", dwFlags, pVTable);
+            break;
+
+        default:
+            *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
+            SetLastError(NTE_BAD_FLAGS);
+            return FALSE;
+    }
+
+    if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
+        SetLastError(ERROR_SUCCESS);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+ * CPReleaseContext (CRYPTO_PROV.@)
+ *
+ * Release a key container.
+ *
+ * PARAMS
+ *  hProv   [I] Key container to be released.
+ *  dwFlags [I] Currently none defined.
+ *
+ * RETURNS
+ *  Success: TRUE
+ *  Failure: FALSE
+ */
+BOOL CRYPTO_PROV_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
+{
+    TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
+
+    if (!release_handle(&handle_table, hProv, CRYPTO_PROV_MAGIC_CONTAINER))
+    {
+        /* MSDN: hProv not containing valid context handle */
+        SetLastError(NTE_BAD_UID);
+        return FALSE;
+    }
+
+    if (dwFlags) {
+        SetLastError(NTE_BAD_FLAGS);
+        return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/dlls/rsaenh/cryptoprovutils.h b/dlls/rsaenh/cryptoprovutils.h
new file mode 100644
index 0000000000..c4997bb35e
--- /dev/null
+++ b/dlls/rsaenh/cryptoprovutils.h
@@ -0,0 +1,81 @@
+/*
+ * dlls/rsaenh/cryptoprovutils.h
+ * Header of utility functions to implement crypto privider.
+ *
+ * Copyright 2002 TransGaming Technologies (David Hammerton)
+ * Copyright 2004 Mike McCormack for CodeWeavers
+ * Copyright 2004, 2005 Michael Jung
+ * Copyright 2007 Vijay Kiran Kamuju
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_CRYPTOPROVUTILS_H
+#define __WINE_CRYPTOPROVUTILS_H
+#include <cryptoprovconfig.h>
+#include "implglue.h"
+typedef struct tagKEYCONTAINER
+{
+    OBJECTHDR    header;
+    DWORD        dwFlags;
+    DWORD        dwPersonality;
+    DWORD        dwEnumAlgsCtr;
+    DWORD        dwEnumContainersCtr;
+    char         szName[MAX_PATH];
+    char         szProvName[MAX_PATH];
+    HCRYPTKEY    hKeyExchangeKeyPair;
+    HCRYPTKEY    hSignatureKeyPair;
+} KEYCONTAINER;
+
+typedef struct tagCRYPTKEY
+{
+    OBJECTHDR   header;
+    ALG_ID      aiAlgid;
+    HCRYPTPROV  hProv;
+    DWORD       dwMode;
+    DWORD       dwModeBits;
+    DWORD       dwPermissions;
+    DWORD       dwKeyLen;
+    DWORD       dwEffectiveKeyLen;
+    DWORD       dwSaltLen;
+    DWORD       dwBlockLen;
+    DWORD       dwState;
+    KEY_CONTEXT context;
+    BYTE        abKeyValue[CRYPTO_PROV_MAX_KEY_SIZE];
+    BYTE        abInitVector[CRYPTO_PROV_MAX_BLOCK_SIZE];
+    BYTE        abChainVector[CRYPTO_PROV_MAX_BLOCK_SIZE];
+    CRYPTO_PROV_SCHANNEL_INFO siSChannelInfo;
+    CRYPT_DATA_BLOB blobHmacKey;
+} CRYPTKEY;
+
+HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags,
const VTableProvStruc *pVTable);
+BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam,
HKEY *phKey);
+void destroy_key_container(OBJECTHDR *pObjectHdr);
+void store_key_container_keys(KEYCONTAINER *pKeyContainer);
+void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec,
DWORD dwFlags);
+void store_key_container_permissions(KEYCONTAINER *pKeyContainer);
+void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec);
+void release_key_container_keys(KEYCONTAINER *pKeyContainer);
+LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec);
+BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
+                      DWORD dwBlobType, DWORD dwFlags, BOOL force,
+       BYTE *pbData, DWORD *pdwDataLen);
+LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec);
+BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags,
REGSAM access, HKEY *phKey);
+BOOL CRYPTO_PROV_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
+                                  DWORD dwFlags, PVTableProvStruc pVTable);
+BOOL import_key(HCRYPTPROV hProv, const BYTE *pbData, DWORD
dwDataLen, HCRYPTKEY hPubKey,
+                       DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey);
+#endif /* __WINE_CRYPTOPROVUTILS_H */
diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index 9119d4be2d..6a746d7b07 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -34,6 +34,7 @@
 #include "objbase.h"
 #include "rpcproxy.h"
 #include "aclapi.h"
+#include "cryptoprovutils.h"
 #include "wine/debug.h"

 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@@ -66,67 +67,6 @@ typedef struct tagCRYPTHASH
     RSAENH_TLS1PRF_PARAMS tpPRFParams;
 } CRYPTHASH;

-/******************************************************************************
- * CRYPTKEY - key objects
- */
-#define RSAENH_MAGIC_KEY           0x73620457u
-#define RSAENH_MAX_KEY_SIZE        64
-#define RSAENH_MAX_BLOCK_SIZE      24
-#define RSAENH_KEYSTATE_IDLE       0
-#define RSAENH_KEYSTATE_ENCRYPTING 1
-#define RSAENH_KEYSTATE_MASTERKEY  2
-typedef struct _RSAENH_SCHANNEL_INFO
-{
-    SCHANNEL_ALG saEncAlg;
-    SCHANNEL_ALG saMACAlg;
-    CRYPT_DATA_BLOB blobClientRandom;
-    CRYPT_DATA_BLOB blobServerRandom;
-} RSAENH_SCHANNEL_INFO;
-
-typedef struct tagCRYPTKEY
-{
-    OBJECTHDR   header;
-    ALG_ID      aiAlgid;
-    HCRYPTPROV  hProv;
-    DWORD       dwMode;
-    DWORD       dwModeBits;
-    DWORD       dwPermissions;
-    DWORD       dwKeyLen;
-    DWORD       dwEffectiveKeyLen;
-    DWORD       dwSaltLen;
-    DWORD       dwBlockLen;
-    DWORD       dwState;
-    KEY_CONTEXT context;
-    BYTE        abKeyValue[RSAENH_MAX_KEY_SIZE];
-    BYTE        abInitVector[RSAENH_MAX_BLOCK_SIZE];
-    BYTE        abChainVector[RSAENH_MAX_BLOCK_SIZE];
-    RSAENH_SCHANNEL_INFO siSChannelInfo;
-    CRYPT_DATA_BLOB blobHmacKey;
-} CRYPTKEY;
-
-/******************************************************************************
- * KEYCONTAINER - key containers
- */
-#define RSAENH_PERSONALITY_BASE        0u
-#define RSAENH_PERSONALITY_STRONG      1u
-#define RSAENH_PERSONALITY_ENHANCED    2u
-#define RSAENH_PERSONALITY_SCHANNEL    3u
-#define RSAENH_PERSONALITY_AES         4u
-
-#define RSAENH_MAGIC_CONTAINER         0x26384993u
-typedef struct tagKEYCONTAINER
-{
-    OBJECTHDR    header;
-    DWORD        dwFlags;
-    DWORD        dwPersonality;
-    DWORD        dwEnumAlgsCtr;
-    DWORD        dwEnumContainersCtr;
-    CHAR         szName[MAX_PATH];
-    CHAR         szProvName[MAX_PATH];
-    HCRYPTKEY    hKeyExchangeKeyPair;
-    HCRYPTKEY    hSignatureKeyPair;
-} KEYCONTAINER;
-
 /******************************************************************************
  * Some magic constants
  */
@@ -149,7 +89,6 @@ typedef struct tagKEYCONTAINER
 #define RSAENH_SSL3_VERSION_MINOR         0
 #define RSAENH_TLS1_VERSION_MAJOR         3
 #define RSAENH_TLS1_VERSION_MINOR         1
-#define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"

 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
 /******************************************************************************
@@ -316,26 +255,6 @@ RSAENH_CPDestroyHash(
     HCRYPTHASH hHash
 );

-static BOOL crypt_export_key(
-    CRYPTKEY *pCryptKey,
-    HCRYPTKEY hPubKey,
-    DWORD dwBlobType,
-    DWORD dwFlags,
-    BOOL force,
-    BYTE *pbData,
-    DWORD *pdwDataLen
-);
-
-static BOOL import_key(
-    HCRYPTPROV hProv,
-    const BYTE *pbData,
-    DWORD dwDataLen,
-    HCRYPTKEY hPubKey,
-    DWORD dwFlags,
-    BOOL fStoreKey,
-    HCRYPTKEY *phKey
-);
-
 BOOL WINAPI
 RSAENH_CPHashData(
     HCRYPTPROV hProv,
@@ -348,7 +267,7 @@ RSAENH_CPHashData(
 /******************************************************************************
  * CSP's handle table (used by all acquired key containers)
  */
-static struct handle_table handle_table;
+struct handle_table handle_table;

 /******************************************************************************
  * DllMain (RSAENH.@)
@@ -933,498 +852,6 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv,
ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
     return hCryptKey;
 }

-/******************************************************************************
- * map_key_spec_to_key_pair_name [Internal]
- *
- * Returns the name of the registry value associated with a key spec.
- *
- * PARAMS
- *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
- *
- * RETURNS
- *  Success: Name of registry value.
- *  Failure: NULL
- */
-static LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec)
-{
-    LPCSTR szValueName;
-
-    switch (dwKeySpec)
-    {
-    case AT_KEYEXCHANGE:
-        szValueName = "KeyExchangeKeyPair";
-        break;
-    case AT_SIGNATURE:
-        szValueName = "SignatureKeyPair";
-        break;
-    default:
-        WARN("invalid key spec %d\n", dwKeySpec);
-        szValueName = NULL;
-    }
-    return szValueName;
-}
-
-/******************************************************************************
- * store_key_pair [Internal]
- *
- * Stores a key pair to the registry
- *
- * PARAMS
- *  hCryptKey     [I] Handle to the key to be stored
- *  hKey          [I] Registry key where the key pair is to be stored
- *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
- *  dwFlags       [I] Flags for protecting the key
- */
-static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD
dwKeySpec, DWORD dwFlags)
-{
-    LPCSTR szValueName;
-    DATA_BLOB blobIn, blobOut;
-    CRYPTKEY *pKey;
-    DWORD dwLen;
-    BYTE *pbKey;
-
-    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
-        return;
-    if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
-                      (OBJECTHDR**)&pKey))
-    {
-        if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
-        {
-            pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
-            if (pbKey)
-            {
-                if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
-                    &dwLen))
-                {
-                    blobIn.pbData = pbKey;
-                    blobIn.cbData = dwLen;
-
-                    if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
-                        dwFlags, &blobOut))
-                    {
-                        RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
-                                       blobOut.pbData, blobOut.cbData);
-                        LocalFree(blobOut.pbData);
-                    }
-                }
-                HeapFree(GetProcessHeap(), 0, pbKey);
-            }
-        }
-    }
-}
-
-/******************************************************************************
- * map_key_spec_to_permissions_name [Internal]
- *
- * Returns the name of the registry value associated with the permissions for
- * a key spec.
- *
- * PARAMS
- *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
- *
- * RETURNS
- *  Success: Name of registry value.
- *  Failure: NULL
- */
-static LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec)
-{
-    LPCSTR szValueName;
-
-    switch (dwKeySpec)
-    {
-    case AT_KEYEXCHANGE:
-        szValueName = "KeyExchangePermissions";
-        break;
-    case AT_SIGNATURE:
-        szValueName = "SignaturePermissions";
-        break;
-    default:
-        WARN("invalid key spec %d\n", dwKeySpec);
-        szValueName = NULL;
-    }
-    return szValueName;
-}
-
-/******************************************************************************
- * store_key_permissions [Internal]
- *
- * Stores a key's permissions to the registry
- *
- * PARAMS
- *  hCryptKey     [I] Handle to the key whose permissions are to be stored
- *  hKey          [I] Registry key where the key permissions are to be stored
- *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
- */
-static void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey,
DWORD dwKeySpec)
-{
-    LPCSTR szValueName;
-    CRYPTKEY *pKey;
-
-    if (!(szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
-        return;
-    if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
-                      (OBJECTHDR**)&pKey))
-        RegSetValueExA(hKey, szValueName, 0, REG_DWORD,
-                       (BYTE *)&pKey->dwPermissions,
-                       sizeof(pKey->dwPermissions));
-}
-
-/******************************************************************************
- * create_container_key [Internal]
- *
- * Creates the registry key for a key container's persistent storage.
- *
- * PARAMS
- *  pKeyContainer [I] Pointer to the key container
- *  sam           [I] Desired registry access
- *  phKey         [O] Returned key
- */
-static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM
sam, HKEY *phKey)
-{
-    CHAR szRSABase[sizeof(RSAENH_REGKEY) + MAX_PATH];
-    HKEY hRootKey;
-
-    sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
-
-    if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
-        hRootKey = HKEY_LOCAL_MACHINE;
-    else
-        hRootKey = HKEY_CURRENT_USER;
-
-    /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
-    /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
-    return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL,
-                           REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
-                           == ERROR_SUCCESS;
-}
-
-/******************************************************************************
- * open_container_key [Internal]
- *
- * Opens a key container's persistent storage for reading.
- *
- * PARAMS
- *  pszContainerName [I] Name of the container to be opened.  May be the empty
- *                       string if the parent key of all containers is to be
- *                       opened.
- *  dwFlags          [I] Flags indicating which keyset to be opened.
- *  phKey            [O] Returned key
- */
-static BOOL open_container_key(LPCSTR pszContainerName, DWORD
dwFlags, REGSAM access, HKEY *phKey)
-{
-    CHAR szRSABase[sizeof(RSAENH_REGKEY) + MAX_PATH];
-    HKEY hRootKey;
-
-    sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
-
-    if (dwFlags & CRYPT_MACHINE_KEYSET)
-        hRootKey = HKEY_LOCAL_MACHINE;
-    else
-        hRootKey = HKEY_CURRENT_USER;
-
-    /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
-    /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
-    return RegOpenKeyExA(hRootKey, szRSABase, 0, access, phKey) ==
-                         ERROR_SUCCESS;
-}
-
-/******************************************************************************
- * delete_container_key [Internal]
- *
- * Deletes a key container's persistent storage.
- *
- * PARAMS
- *  pszContainerName [I] Name of the container to be opened.
- *  dwFlags          [I] Flags indicating which keyset to be opened.
- */
-static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
-{
-    CHAR szRegKey[sizeof(RSAENH_REGKEY) + MAX_PATH];
-    HKEY hRootKey;
-
-    sprintf(szRegKey, RSAENH_REGKEY, pszContainerName);
-
-    if (dwFlags & CRYPT_MACHINE_KEYSET)
-        hRootKey = HKEY_LOCAL_MACHINE;
-    else
-        hRootKey = HKEY_CURRENT_USER;
-    if (!RegDeleteKeyA(hRootKey, szRegKey)) {
-        SetLastError(ERROR_SUCCESS);
-        return TRUE;
-    } else {
-        SetLastError(NTE_BAD_KEYSET);
-        return FALSE;
-    }
-}
-
-/******************************************************************************
- * store_key_container_keys [Internal]
- *
- * Stores key container's keys in a persistent location.
- *
- * PARAMS
- *  pKeyContainer [I] Pointer to the key container whose keys are to be saved
- */
-static void store_key_container_keys(KEYCONTAINER *pKeyContainer)
-{
-    HKEY hKey;
-    DWORD dwFlags;
-
-    /* On WinXP, persistent keys are stored in a file located at:
-     * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
-     */
-
-    if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
-        dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
-    else
-        dwFlags = 0;
-
-    if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
-    {
-        store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
-                       AT_KEYEXCHANGE, dwFlags);
-        store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
-                       AT_SIGNATURE, dwFlags);
-        RegCloseKey(hKey);
-    }
-}
-
-/******************************************************************************
- * store_key_container_permissions [Internal]
- *
- * Stores key container's key permissions in a persistent location.
- *
- * PARAMS
- *  pKeyContainer [I] Pointer to the key container whose key permissions are to
- *                    be saved
- */
-static void store_key_container_permissions(KEYCONTAINER *pKeyContainer)
-{
-    HKEY hKey;
-
-    if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
-    {
-        store_key_permissions(pKeyContainer->hKeyExchangeKeyPair, hKey,
-                       AT_KEYEXCHANGE);
-        store_key_permissions(pKeyContainer->hSignatureKeyPair, hKey,
-                       AT_SIGNATURE);
-        RegCloseKey(hKey);
-    }
-}
-
-/******************************************************************************
- * release_key_container_keys [Internal]
- *
- * Releases key container's keys.
- *
- * PARAMS
- *  pKeyContainer [I] Pointer to the key container whose keys are to
be released.
- */
-static void release_key_container_keys(KEYCONTAINER *pKeyContainer)
-{
-    release_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair,
-                   RSAENH_MAGIC_KEY);
-    release_handle(&handle_table, pKeyContainer->hSignatureKeyPair,
-                   RSAENH_MAGIC_KEY);
-}
-
-/******************************************************************************
- * destroy_key_container [Internal]
- *
- * Destructor for key containers.
- *
- * PARAMS
- *  pObjectHdr [I] Pointer to the key container to be destroyed.
- */
-static void destroy_key_container(OBJECTHDR *pObjectHdr)
-{
-    KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
-
-    if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
-    {
-        store_key_container_keys(pKeyContainer);
-        store_key_container_permissions(pKeyContainer);
-        release_key_container_keys(pKeyContainer);
-    }
-    else
-        release_key_container_keys(pKeyContainer);
-    HeapFree( GetProcessHeap(), 0, pKeyContainer );
-}
-
-/******************************************************************************
- * new_key_container [Internal]
- *
- * Create a new key container. The personality (RSA Base, Strong or
Enhanced CP)
- * of the CSP is determined via the pVTable->pszProvName string.
- *
- * PARAMS
- *  pszContainerName [I] Name of the key container.
- *  pVTable          [I] Callback functions and context info provided by the OS
- *
- * RETURNS
- *  Success: Handle to the new key container.
- *  Failure: INVALID_HANDLE_VALUE
- */
-static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD
dwFlags, const VTableProvStruc *pVTable)
-{
-    KEYCONTAINER *pKeyContainer;
-    HCRYPTPROV hKeyContainer;
-
-    hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER),
RSAENH_MAGIC_CONTAINER,
-                               destroy_key_container,
(OBJECTHDR**)&pKeyContainer);
-    if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
-    {
-        lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
-        pKeyContainer->dwFlags = dwFlags;
-        pKeyContainer->dwEnumAlgsCtr = 0;
-        pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
-        pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
-        if (pVTable && pVTable->pszProvName) {
-            lstrcpynA(pKeyContainer->szProvName,
pVTable->pszProvName, MAX_PATH);
-            if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
-                pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
-            } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
-                pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
-            } else if (!strcmp(pVTable->pszProvName,
MS_DEF_RSA_SCHANNEL_PROV_A)) {
-                pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
-            } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A) ||
-                       !strcmp(pVTable->pszProvName,
MS_ENH_RSA_AES_PROV_XP_A)) {
-                pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES;
-            } else {
-                pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
-            }
-        }
-
-        /* The new key container has to be inserted into the CSP immediately
-         * after creation to be available for CPGetProvParam's
PP_ENUMCONTAINERS. */
-        if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
-            HKEY hKey;
-
-            if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
-                RegCloseKey(hKey);
-        }
-    }
-
-    return hKeyContainer;
-}
-
-/******************************************************************************
- * read_key_value [Internal]
- *
- * Reads a key pair value from the registry
- *
- * PARAMS
- *  hKeyContainer [I] Crypt provider to use to import the key
- *  hKey          [I] Registry key from which to read the key pair
- *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
- *  dwFlags       [I] Flags for unprotecting the key
- *  phCryptKey    [O] Returned key
- */
-static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, DWORD
dwKeySpec, DWORD dwFlags, HCRYPTKEY *phCryptKey)
-{
-    LPCSTR szValueName;
-    DWORD dwValueType, dwLen;
-    BYTE *pbKey;
-    DATA_BLOB blobIn, blobOut;
-    BOOL ret = FALSE;
-
-    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
-        return FALSE;
-    if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
-        ERROR_SUCCESS)
-    {
-        pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
-        if (pbKey)
-        {
-            if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType,
pbKey, &dwLen) ==
-                ERROR_SUCCESS)
-            {
-                blobIn.pbData = pbKey;
-                blobIn.cbData = dwLen;
-
-                if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
-                    dwFlags, &blobOut))
-                {
-                    ret = import_key(hKeyContainer, blobOut.pbData,
blobOut.cbData, 0, 0,
-                                     FALSE, phCryptKey);
-                    LocalFree(blobOut.pbData);
-                }
-            }
-            HeapFree(GetProcessHeap(), 0, pbKey);
-        }
-    }
-    if (ret)
-    {
-        CRYPTKEY *pKey;
-
-        if (lookup_handle(&handle_table, *phCryptKey, RSAENH_MAGIC_KEY,
-                          (OBJECTHDR**)&pKey))
-        {
-            if ((szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
-            {
-                dwLen = sizeof(pKey->dwPermissions);
-                RegQueryValueExA(hKey, szValueName, 0, NULL,
-                                 (BYTE *)&pKey->dwPermissions, &dwLen);
-            }
-        }
-    }
-    return ret;
-}
-
-/******************************************************************************
- * read_key_container [Internal]
- *
- * Tries to read the persistent state of the key container (mainly
the signature
- * and key exchange private keys) given by pszContainerName.
- *
- * PARAMS
- *  pszContainerName [I] Name of the key container to read from the registry
- *  pVTable          [I] Pointer to context data provided by the
operating system
- *
- * RETURNS
- *  Success: Handle to the key container read from the registry
- *  Failure: INVALID_HANDLE_VALUE
- */
-static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD
dwFlags, const VTableProvStruc *pVTable)
-{
-    HKEY hKey;
-    KEYCONTAINER *pKeyContainer;
-    HCRYPTPROV hKeyContainer;
-    HCRYPTKEY hCryptKey;
-
-    if (!open_container_key(pszContainerName, dwFlags, KEY_READ, &hKey))
-    {
-        SetLastError(NTE_BAD_KEYSET);
-        return (HCRYPTPROV)INVALID_HANDLE_VALUE;
-    }
-
-    hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
-    if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
-    {
-        DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
-            CRYPTPROTECT_LOCAL_MACHINE : 0;
-
-        if (!lookup_handle(&handle_table, hKeyContainer,
RSAENH_MAGIC_CONTAINER,
-                           (OBJECTHDR**)&pKeyContainer))
-            return (HCRYPTPROV)INVALID_HANDLE_VALUE;
-
-        /* read_key_value calls import_key, which calls import_private_key,
-         * which implicitly installs the key value into the appropriate key
-         * container key.  Thus the ref count is incremented twice, once for
-         * the output key value, and once for the implicit install, and needs
-         * to be decremented to balance the two.
-         */
-        if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE,
-            dwProtectFlags, &hCryptKey))
-            release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
-        if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE,
-            dwProtectFlags, &hCryptKey))
-            release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
-    }
-
-    return hKeyContainer;
-}
-
 /******************************************************************************
  * build_hash_signature [Internal]
  *
@@ -2073,64 +1500,7 @@ static BOOL unpad_data(HCRYPTPROV hProv, const
BYTE *abData, DWORD dwDataLen, BY
 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
                    DWORD dwFlags, PVTableProvStruc pVTable)
 {
-    CHAR szKeyContainerName[MAX_PATH];
-
-    TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
-          debugstr_a(pszContainer), dwFlags, pVTable);
-
-    if (pszContainer && *pszContainer)
-    {
-        lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
-    }
-    else
-    {
-        DWORD dwLen = sizeof(szKeyContainerName);
-        if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
-    }
-
-    switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
-    {
-        case 0:
-            *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
-            break;
-
-        case CRYPT_DELETEKEYSET:
-            return delete_container_key(szKeyContainerName, dwFlags);
-
-        case CRYPT_NEWKEYSET:
-            *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
-            if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
-            {
-                release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER);
-                TRACE("Can't create new keyset, already exists\n");
-                SetLastError(NTE_EXISTS);
-                return FALSE;
-            }
-            *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
-            break;
-
-        case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
-        case CRYPT_VERIFYCONTEXT:
-            if (pszContainer && *pszContainer) {
-                TRACE("pszContainer should be empty\n");
-                SetLastError(NTE_BAD_FLAGS);
-                return FALSE;
-            }
-            *phProv = new_key_container("", dwFlags, pVTable);
-            break;
-
-        default:
-            *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
-            SetLastError(NTE_BAD_FLAGS);
-            return FALSE;
-    }
-
-    if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
-        SetLastError(ERROR_SUCCESS);
-        return TRUE;
-    } else {
-        return FALSE;
-    }
+    return CRYPTO_PROV_CPAcquireContext(phProv, pszContainer,
dwFlags, pVTable);
 }

 /******************************************************************************
@@ -2906,7 +2276,7 @@ static BOOL crypt_export_plaintext_key(CRYPTKEY
*pCryptKey, BYTE *pbData,
  *  Success: TRUE.
  *  Failure: FALSE.
  */
-static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
+BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
                              DWORD dwBlobType, DWORD dwFlags, BOOL force,
                              BYTE *pbData, DWORD *pdwDataLen)
 {
@@ -3351,7 +2721,7 @@ static BOOL import_plaintext_key(HCRYPTPROV
hProv, const BYTE *pbData, DWORD dwD
  *  Success: TRUE.
  *  Failure: FALSE.
  */
-static BOOL import_key(HCRYPTPROV hProv, const BYTE *pbData, DWORD
dwDataLen, HCRYPTKEY hPubKey,
+BOOL import_key(HCRYPTPROV hProv, const BYTE *pbData, DWORD
dwDataLen, HCRYPTKEY hPubKey,
                        DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
 {
     KEYCONTAINER *pKeyContainer;
@@ -4549,21 +3919,7 @@ BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV
hProv, HCRYPTHASH hHash, HCRYPTKE
  */
 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
 {
-    TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
-
-    if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
-    {
-        /* MSDN: hProv not containing valid context handle */
-        SetLastError(NTE_BAD_UID);
-        return FALSE;
-    }
-
-    if (dwFlags) {
-        SetLastError(NTE_BAD_FLAGS);
-        return FALSE;
-    }
-
-    return TRUE;
+    return CRYPTO_PROV_CPReleaseContext(hProv, dwFlags);
 }

 /******************************************************************************
-- 
2.21.0



More information about the wine-devel mailing list