--- 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); }
/******************************************************************************
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=60288
Your paranoid android.
=== debian10 (build log) ===
error: corrupt patch at line 121 Task: Patch failed to apply
=== debian10 (build log) ===
error: corrupt patch at line 121 Task: Patch failed to apply