Rob, as far as I can tell from looking at your patch, our work is pretty much non overlapping.
I worked on the following aspects: - Implementation of "real handles", instead of "address-handles". - Separating OpenSSL dependend code from CSP code. I consider this beneficial, since there seem to be some license issues with OpenSSL (at least for the ReactOS project - there was a short discussion on this on the wine-devel list). If the OpenSSL code is cleanly separated, it will be easier to support GNUTLS or something later. - Basically, my code doesn't do any crypto stuff at all until now (Besides some first lines of code for MD5 hashing). I tried to get the MSDN CryptoAPI examples to compile and run, which only acquire contexts, hash data, derive keys, query CSP params and so on, but which never verify the results. So my code is mainly skin (but elephant skin), no guts. I've attached the current version of my patch. Do you have a certain application, which you want to get running? Would it be ok for you if we proceed as follows: I will wait until you submit your patch (It would be nice if you could add some unit-tests that test for behaviour you depend on). After this you give me a week or two to incorporate my work. Is there any area in rsabase, which you definitely will not implement in the near future and which I could work on until you submit your patch? Greetings, Michael
Index: dlls/rsabase/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/rsabase/Makefile.in,v retrieving revision 1.2 diff -u -r1.2 Makefile.in --- dlls/rsabase/Makefile.in 1 Mar 2004 21:20:33 -0000 1.2 +++ dlls/rsabase/Makefile.in 25 Jul 2004 08:25:50 -0000 @@ -7,7 +7,11 @@ IMPORTS = advapi32 kernel32 C_SRCS = \ - main.c + main.c \ + handle.c \ + implossl.c + +SUBDIRS = tests @MAKE_DLL_RULES@ Index: dlls/rsabase/main.c =================================================================== RCS file: /home/wine/wine/dlls/rsabase/main.c,v retrieving revision 1.7 diff -u -r1.7 main.c --- dlls/rsabase/main.c 25 Jun 2004 01:17:37 -0000 1.7 +++ dlls/rsabase/main.c 25 Jul 2004 08:25:52 -0000 @@ -21,27 +21,24 @@ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - #include "config.h" #include "wine/port.h" #include <stdarg.h> +#include <stdio.h> #include "windef.h" #include "winbase.h" #include "winreg.h" #include "wincrypt.h" +#include "lmcons.h" +#include "handle.h" +#include "rsabase.h" #ifdef HAVE_OPENSSL_SSL_H -#define DSA __ssl_DSA /* avoid conflict with commctrl.h */ -#undef FAR -# include <openssl/rand.h> -#undef FAR -#define FAR do_not_use_this_in_wine -#undef DSA +#include "implossl.h" #endif #include "wine/library.h" @@ -51,84 +48,316 @@ #define RSABASE_MAGIC 0x52534100 -#ifdef HAVE_OPENSSL_SSL_H - -#ifndef SONAME_LIBCRYPTO -#define SONAME_LIBCRYPTO "libcrypto.so" -#endif - -static void *libcrypto; - -#define MAKE_FUNCPTR(f) static typeof(f) * p##f - -/* OpenSSL funtions that we use */ -MAKE_FUNCPTR(RAND_bytes); - -static BOOL load_libcrypto( void ) +#define RSASTRONG_NUM_ALGS 14 +PROV_ENUMALGS_EX aProvEnumAlgsEx[RSASTRONG_NUM_ALGS] = { + {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"}, + {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"}, + {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"}, + {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"}, + {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"}, + {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, + {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 27,"MD2 Message Digest 2 (MD2)"}, + {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 27,"MD4 Message Digest 4 (MD4)"}, + {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 27,"MD5 Message Digest 5 (MD5)"}, + {CALG_SSL3_SHAMD5,288,288, 288,0, 12,"SSL3 SHAMD5", 12,"SSL3 SHAMD5"}, + {CALG_MAC, 0, 0, 0,0, 4,"MAC", 27,"Message Authentication Code"}, + {CALG_RSA_SIGN, 1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN", 14,"RSA Signature"}, + {CALG_RSA_KEYX, 1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX", 18,"RSA Key Exchange"}, + {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 23,"HMAC Hugo's MAC (HMAC)"} +}; + +unsigned int iEnumAlgs; +HANDLETABLE handle_table; + +int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + init_handle_table(&handle_table); + break; + + case DLL_PROCESS_DETACH: + destruct_handle_table(&handle_table); + break; + } + return 1; +} + +int is_algid_supported(ALG_ID algid) +{ + int i; + for (i=0; i<RSASTRONG_NUM_ALGS; i++) + if (aProvEnumAlgsEx[i].aiAlgid == algid) + return 1; + return 0; +} + +unsigned int new_object(size_t cbSize, DESTRUCTOR destructor, OBJECTHDR **ppObject) +{ + OBJECTHDR *pObject; + unsigned int hObject; + + if (ppObject) + *ppObject = NULL; + + pObject = (OBJECTHDR*)HeapAlloc(GetProcessHeap(), 0, cbSize); + if (!pObject) + return (unsigned int)INVALID_HANDLE_VALUE; + + pObject->refcount = 0; + pObject->destructor = destructor; + + if (!alloc_handle(&handle_table, pObject, &hObject)) + HeapFree(GetProcessHeap(), 0, pObject); + else + if (ppObject) + *ppObject = pObject; + + return hObject; +} + +void crypt_hash_destructor(OBJECTHDR *pCryptHash) +{ + if (((CRYPTHASH*)pCryptHash)->pContext) + HeapFree(GetProcessHeap(), 0, ((CRYPTHASH*)pCryptHash)->pContext); + HeapFree(GetProcessHeap(), 0, pCryptHash); +} + +HCRYPTHASH new_crypt_hash(ALG_ID aiAlgid, HCRYPTKEY hKey) +{ + HCRYPTHASH hCryptHash; + CRYPTHASH *pCryptHash; + + hCryptHash = (HCRYPTHASH)new_object(sizeof(CRYPTHASH), crypt_hash_destructor, (OBJECTHDR**)&pCryptHash); + if (hCryptHash != (HCRYPTHASH)INVALID_HANDLE_VALUE) + { + pCryptHash->aiAlgid = aiAlgid; + pCryptHash->hKey = hKey; + pCryptHash->fFinished = FALSE; + switch (aiAlgid) + { + case CALG_MD5: + pCryptHash->pContext = (PVOID)HeapAlloc(GetProcessHeap(), 0, sizeof(IMPL(md5_context))); + IMPL(md5_init)((IMPL(md5_context)*)pCryptHash->pContext); + break; + + default: + FIXME("ALG_ID %08x not implemented!\n", aiAlgid); + pCryptHash->pContext = NULL; + } + } + + return hCryptHash; +} + +void crypt_key_destructor(OBJECTHDR *pCryptKey) +{ + HeapFree(GetProcessHeap(), 0, pCryptKey); +} + +HCRYPTKEY new_crypt_key(ALG_ID aiAlgid, DWORD dwKeyLen, BYTE *pbKey) +{ + HCRYPTKEY hCryptKey; + CRYPTKEY *pCryptKey; + + hCryptKey = (HCRYPTKEY)new_object(sizeof(CRYPTKEY), crypt_key_destructor, (OBJECTHDR**)&pCryptKey); + if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE) + { + pCryptKey->aiAlgid = aiAlgid; + pCryptKey->dwKeyLen = dwKeyLen; + if (pbKey) + memcpy(pCryptKey->abKey, pbKey, dwKeyLen >> 3); + } + + return hCryptKey; +} + +HCRYPTKEY duplicate_key(HCRYPTKEY other) +{ + CRYPTKEY *pCryptKey; + + if (!lookup_handle(&handle_table, other, (OBJECTHDR**)&pCryptKey)) + return (HCRYPTKEY)INVALID_HANDLE_VALUE; + + return new_crypt_key(pCryptKey->aiAlgid, pCryptKey->dwKeyLen, pCryptKey->abKey); +} + +void key_container_destructor(OBJECTHDR *pKeyContainer) +{ + CHAR szRSABase[MAX_PATH]; + HKEY hKey; + DWORD dummy = 0xefbeadde; + + strcpy(szRSABase, "Software\\Wine\\rsabase\\"); + strcat(szRSABase, ((KEYCONTAINER*)pKeyContainer)->szName); + + if (RegCreateKeyExA(HKEY_CURRENT_USER, szRSABase, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) + { + if (((KEYCONTAINER*)pKeyContainer)->hKeyExchangeKeyPair) + RegSetValueExA(hKey, "KeyExchangeKeyPair", 0, REG_BINARY, (const BYTE *)&dummy, sizeof(dummy)); + + if (((KEYCONTAINER*)pKeyContainer)->hSignatureKeyPair) + RegSetValueExA(hKey, "SignatureKeyPair", 0, REG_BINARY, (const BYTE *)&dummy, sizeof(dummy)); + + RegCloseKey(hKey); + } + + release_handle(&handle_table, (unsigned int)((KEYCONTAINER*)pKeyContainer)->hSignatureKeyPair); + release_handle(&handle_table, (unsigned int)((KEYCONTAINER*)pKeyContainer)->hKeyExchangeKeyPair); + HeapFree( GetProcessHeap(), 0, pKeyContainer ); +} + +HCRYPTPROV new_key_container(PCHAR pszContainerName) +{ + KEYCONTAINER *pKeyContainer; + HCRYPTPROV hKeyContainer; + + hKeyContainer = (HCRYPTPROV)new_object(sizeof(KEYCONTAINER), key_container_destructor, (OBJECTHDR**)&pKeyContainer); + if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE) + { + strncpy(pKeyContainer->szName, pszContainerName, MAX_PATH); + pKeyContainer->szName[MAX_PATH-1] = '\0'; + pKeyContainer->dwMode = 0; + pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE; + pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE; + } + + return hKeyContainer; +} + +HCRYPTPROV read_key_container(PCHAR pszContainerName) +{ + CHAR szRSABase[MAX_PATH]; + HKEY hKey; + DWORD dwValueType; + KEYCONTAINER *pKeyContainer; + HCRYPTPROV hKeyContainer; + + strcpy(szRSABase, "Software\\Wine\\rsabase\\"); + strcat(szRSABase, pszContainerName); + + if (RegOpenKeyExA(HKEY_CURRENT_USER, szRSABase, 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + SetLastError(NTE_BAD_KEYSET); + return (HCRYPTPROV)INVALID_HANDLE_VALUE; + } + + hKeyContainer = new_key_container(pszContainerName); + if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE) + { + if (!lookup_handle(&handle_table, hKeyContainer, (OBJECTHDR**)&pKeyContainer)) + return (HCRYPTPROV)INVALID_HANDLE_VALUE; + + if (RegQueryValueExA(hKey, "KeyExchangeKeyPair", 0, &dwValueType, NULL, NULL) == ERROR_SUCCESS) + pKeyContainer->hKeyExchangeKeyPair = new_crypt_key(CALG_RSA_KEYX, 0, NULL); + + if (RegQueryValueExA(hKey, "SignatureKeyPair", 0, &dwValueType, NULL, NULL) == ERROR_SUCCESS) + pKeyContainer->hSignatureKeyPair = new_crypt_key(CALG_RSA_SIGN, 0, NULL); + } + + return hKeyContainer; +} + +/****************************************************************************** + * get_key_container_name [Internal] + * + * Derives the name of the key container based on the string pszContainer. + * If pszContainer is NULL or points to an empty string, the name of the current + * user is returned via pszKeyContainerName. Otherwise pszContainer is copied to + * pszKeyContainerName. If the container name does not fit into cbMax bytes, 0 is + * returned. + */ +DWORD get_key_container_name(LPSTR pszKeyContainerName, LPSTR pszContainer, DWORD cbMax) { - libcrypto = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0); - if (!libcrypto) - { - MESSAGE("Couldn't load %s, RSA encryption not available.\n", SONAME_LIBCRYPTO); - MESSAGE("Install the openssl package if you're have problems.\n"); - return FALSE; - } - - #define GETFUNC(x) \ - p##x = wine_dlsym(libcrypto, #x, NULL, 0); \ - if (!p##x) \ - { \ - ERR("failed to load symbol %s\n", #x); \ - return FALSE; \ - } - - GETFUNC(RAND_bytes); - - return TRUE; + if (pszContainer ? strlen(pszContainer) : 0) + { + if (strlen(pszContainer) < cbMax) + { + strcpy(pszKeyContainerName, pszContainer); + return 1; + } + else + { + pszKeyContainerName[0] = '\0'; + return 0; + } + } + else + { + return GetUserNameA(pszKeyContainerName, &cbMax); + } } -#endif - -typedef struct _RSA_CryptProv -{ - DWORD dwMagic; -} RSA_CryptProv; - BOOL WINAPI RSA_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer, DWORD dwFlags, PVTableProvStruc pVTable) { - BOOL ret = FALSE; + CHAR szKeyContainerName[MAX_PATH]; TRACE("%p %s %08lx %p\n", phProv, debugstr_a(pszContainer), dwFlags, pVTable); -#ifdef HAVE_OPENSSL_SSL_H - - if( !load_libcrypto() ) - return FALSE; - else - { - RSA_CryptProv *cp = HeapAlloc( GetProcessHeap(), 0, sizeof (RSA_CryptProv) ); - if( !cp ) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - cp->dwMagic = RSABASE_MAGIC; - - *phProv = (HCRYPTPROV) cp; - ret = TRUE; - } -#endif - - return ret; + if (!IMPL(load_lib)()) + { + /* MSDN: Failed to load or initalize provider DLL */ + SetLastError(NTE_PROVIDER_DLL_FAIL); + return FALSE; + } + + if (!get_key_container_name(szKeyContainerName, pszContainer, MAX_PATH)) + { + SetLastError(NTE_BAD_KEYSET_PARAM); + return FALSE; + } + + switch (dwFlags) + { + case 0: + *phProv = read_key_container(szKeyContainerName); + break; + + case CRYPT_NEWKEYSET: + *phProv = read_key_container(szKeyContainerName); + if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) + { + release_handle(&handle_table, (unsigned int)*phProv); + SetLastError(NTE_EXISTS); + return FALSE; + } + *phProv = new_key_container(szKeyContainerName); + break; + + default: + *phProv = (unsigned int)INVALID_HANDLE_VALUE; + SetLastError(NTE_BAD_FLAGS); + return FALSE; + } + + return *phProv != (unsigned int)INVALID_HANDLE_VALUE; } BOOL WINAPI RSA_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) { - FIXME("%08lx %d %08lx %08lx %p\n", hProv, Algid, hKey, dwFlags, phHash); - return FALSE; + if (!is_valid_handle(&handle_table, hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (!is_algid_supported(Algid)) + { + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + if (dwFlags) + { + SetLastError(NTE_BAD_FLAGS); + return FALSE; + } + + *phHash = new_crypt_hash(Algid, hKey); + return TRUE; } BOOL WINAPI RSA_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) @@ -137,22 +366,207 @@ return FALSE; } -BOOL WINAPI RSA_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey) +BOOL WINAPI RSA_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) { - FIXME("(stub)\n"); - return FALSE; + CRYPTHASH *pCryptHash; + DWORD dwDataLen; + + if (!is_valid_handle(&handle_table, (unsigned int)hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (dwFlags) + { + SetLastError(NTE_BAD_FLAGS); + return FALSE; + } + + if (!lookup_handle(&handle_table, (unsigned int)hHash, (OBJECTHDR**)&pCryptHash)) + { + SetLastError(NTE_BAD_HASH); + return FALSE; + } + + if (!pdwDataLen) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + dwDataLen = *pdwDataLen; + *pdwDataLen = 0; + + switch (dwParam) + { + case HP_ALGID: + *pdwDataLen = sizeof(ALG_ID); + if (pbData) + { + if (dwDataLen < *pdwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + *(ALG_ID*)pbData = pCryptHash->aiAlgid; + } + return TRUE; + + case HP_HASHSIZE: + *pdwDataLen = sizeof(DWORD); + if (pbData) + { + if (dwDataLen < *pdwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + + switch (pCryptHash->aiAlgid) + { + case CALG_MD5: + *(DWORD*)pbData = 16; + break; + + default: + FIXME("Unsupported Algid: %08x\n", pCryptHash->aiAlgid); + SetLastError(NTE_FAIL); + return FALSE; + } + } + return TRUE; + + case HP_HASHVALUE: + switch (pCryptHash->aiAlgid) + { + case CALG_MD5: + *pdwDataLen = 16; + break; + + default: + FIXME("Unsupported Algid: %08x\n", pCryptHash->aiAlgid); + SetLastError(NTE_FAIL); + return FALSE; + } + + if (pbData) + { + if (dwDataLen < *pdwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + + switch (pCryptHash->aiAlgid) + { + case CALG_MD5: + IMPL(md5_get_digest)((IMPL(md5_context)*)pCryptHash->pContext, (unsigned char*)pbData); + break; + + default: + FIXME("Unsupported Algid: %08x\n", pCryptHash->aiAlgid); + SetLastError(NTE_FAIL); + return FALSE; + } + + pCryptHash->fFinished = TRUE; + } + return TRUE; + + default: + SetLastError(NTE_BAD_TYPE); + return FALSE; + } +} + +BOOL WINAPI RSA_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey) +{ + DWORD cLen = 0; + BYTE *pbHashValue; + + if (!is_valid_handle(&handle_table, (unsigned int)hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (!is_valid_handle(&handle_table, (unsigned int)hBaseData)) + { + SetLastError(NTE_BAD_HASH); + return FALSE; + } + + if (!phKey) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!RSA_CPGetHashParam(hProv, hBaseData, HP_HASHVALUE, NULL, &cLen, 0)) + return FALSE; + + pbHashValue = (BYTE*)HeapAlloc(GetProcessHeap(), 0, cLen); + if (!pbHashValue) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + if (!RSA_CPGetHashParam(hProv, hBaseData, HP_HASHVALUE, pbHashValue, &cLen, 0)) + { + HeapFree(GetProcessHeap(), 0, pbHashValue); + return FALSE; + } + + switch (Algid) + { + case CALG_RC2: + *phKey = new_crypt_key(Algid, 128, pbHashValue); + break; + + default: + HeapFree(GetProcessHeap(), 0, pbHashValue); + FIXME("Unimplemented Algid: %08x\n", Algid); + SetLastError(NTE_FAIL); + return FALSE; + } + + return TRUE; } BOOL WINAPI RSA_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash) { - FIXME("(stub)\n"); - return FALSE; + if (!is_valid_handle(&handle_table, hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (!release_handle(&handle_table, hHash)) + { + SetLastError(NTE_BAD_KEY); + return FALSE; + } + + return TRUE; } BOOL WINAPI RSA_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey) { - FIXME("(stub)\n"); - return FALSE; + if (!is_valid_handle(&handle_table, hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (!release_handle(&handle_table, hKey)) + { + SetLastError(NTE_BAD_KEY); + return FALSE; + } + + return TRUE; } BOOL WINAPI RSA_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved, DWORD dwFlags, HCRYPTHASH *phHash) @@ -163,8 +577,20 @@ BOOL WINAPI RSA_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey) { - FIXME("(stub)\n"); - return FALSE; + if (!is_valid_handle(&handle_table, hUID)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + *phKey = duplicate_key(hKey); + if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) + { + SetLastError(NTE_BAD_KEY); + return FALSE; + } + + return TRUE; } BOOL WINAPI RSA_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen) @@ -181,35 +607,56 @@ BOOL WINAPI RSA_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey) { - FIXME("(stub)\n"); - return FALSE; + KEYCONTAINER *pKeyContainer; + + if (!lookup_handle(&handle_table, (unsigned int)hProv, (OBJECTHDR**)&pKeyContainer)) + { + /* MSDN: hProv not containing valid context handle */ + SetLastError(NTE_BAD_UID); + return FALSE; + } + + switch (Algid) + { + case AT_SIGNATURE: + RSA_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair); + *phKey = pKeyContainer->hSignatureKeyPair = new_crypt_key(CALG_RSA_SIGN, 0, NULL); + break; + + case AT_KEYEXCHANGE: + RSA_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair); + *phKey = pKeyContainer->hKeyExchangeKeyPair = new_crypt_key(CALG_RSA_KEYX, 0, NULL); + break; + + case CALG_RC2: + case CALG_RC4: + case CALG_DES: + *phKey = new_crypt_key(Algid, 0, NULL); + break; + + default: + /* MSDN: Algorithm not supported specified by Algid */ + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return *phKey != (unsigned int)INVALID_HANDLE_VALUE; } BOOL WINAPI RSA_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) { - BOOL ret = FALSE; - RSA_CryptProv *cp = (RSA_CryptProv*) hProv; + KEYCONTAINER *pKeyContainer; TRACE("%08lx %ld %p\n", hProv, dwLen, pbBuffer); - if( cp && ( cp->dwMagic != RSABASE_MAGIC ) ) - return FALSE; - -#ifdef HAVE_OPENSSL_SSL_H - - if( !pRAND_bytes) - return FALSE; - ret = pRAND_bytes( pbBuffer, dwLen ); - -#endif - - return ret; -} + if (!lookup_handle(&handle_table, (unsigned int)hProv, (OBJECTHDR**)&pKeyContainer)) + { + /* MSDN: hProv not containing valid context handle */ + SetLastError(NTE_BAD_UID); + return FALSE; + } -BOOL WINAPI RSA_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) -{ - FIXME("(stub)\n"); - return FALSE; + return IMPL(random_bytes)(pbBuffer, dwLen); } BOOL WINAPI RSA_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) @@ -220,20 +667,165 @@ BOOL WINAPI RSA_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) { - FIXME("(stub)\n"); + KEYCONTAINER *pKeyContainer; + DWORD dwDataLen = *pdwDataLen; + static const char szProviderName[] = "Microsoft Strong Cryptographic Provider"; + + if (!lookup_handle(&handle_table, (unsigned int)hProv, (OBJECTHDR**)&pKeyContainer)) + { + /* MSDN: hProv not containing valid context handle */ + SetLastError(NTE_BAD_UID); + return FALSE; + } + + switch (dwParam) + { + case PP_CONTAINER: + *pdwDataLen = strlen(pKeyContainer->szName)+1; + if (pbData) + { + if (*pdwDataLen > dwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + strcpy(pbData, pKeyContainer->szName); + } + return TRUE; + + case PP_NAME: + *pdwDataLen = strlen(szProviderName)+1; + if (pbData) + { + if (*pdwDataLen > dwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + strcpy(pbData, szProviderName); + } + return TRUE; + + case PP_ENUMALGS: + if ((iEnumAlgs >= RSASTRONG_NUM_ALGS-1) && ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST)) + { + SetLastError(ERROR_NO_MORE_ITEMS); + return FALSE; + } + *pdwDataLen = sizeof(PROV_ENUMALGS); + if (pbData) + { + if (*pdwDataLen > dwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + iEnumAlgs = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 0 : iEnumAlgs+1; + ((PROV_ENUMALGS*)pbData)->aiAlgid = aProvEnumAlgsEx[iEnumAlgs].aiAlgid; + ((PROV_ENUMALGS*)pbData)->dwBitLen = aProvEnumAlgsEx[iEnumAlgs].dwDefaultLen; + ((PROV_ENUMALGS*)pbData)->dwNameLen = aProvEnumAlgsEx[iEnumAlgs].dwNameLen; + memcpy(((PROV_ENUMALGS*)pbData)->szName, aProvEnumAlgsEx[iEnumAlgs].szName, 20*sizeof(CHAR)); + } + return TRUE; + + case PP_ENUMALGS_EX: + if ((iEnumAlgs >= RSASTRONG_NUM_ALGS-1) && ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST)) + { + SetLastError(ERROR_NO_MORE_ITEMS); + return FALSE; + } + *pdwDataLen = sizeof(PROV_ENUMALGS_EX); + if (pbData) + { + if (*pdwDataLen > dwDataLen) + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + iEnumAlgs = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 0 : iEnumAlgs+1; + memcpy(pbData, &aProvEnumAlgsEx[iEnumAlgs], sizeof(PROV_ENUMALGS_EX)); + } + return TRUE; + + default: + /* MSDN: Unknown parameter number in dwParam */ + SetLastError(NTE_BAD_TYPE); + return FALSE; + } return FALSE; } BOOL WINAPI RSA_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey) { - FIXME("(stub)\n"); - return FALSE; + KEYCONTAINER *pKeyContainer; + + if (!lookup_handle(&handle_table, (unsigned int)hProv, (OBJECTHDR**)&pKeyContainer)) + { + /* MSDN: hProv not containing valid context handle */ + SetLastError(NTE_BAD_UID); + return FALSE; + } + + switch (dwKeySpec) + { + case AT_KEYEXCHANGE: + copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, (unsigned int*)phUserKey); + break; + + case AT_SIGNATURE: + copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, (unsigned int*)phUserKey); + break; + + default: + *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE; + } + + if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) + { + /* MSDN: dwKeySpec parameter specifies non existent key */ + SetLastError(NTE_NO_KEY); + return FALSE; + } + + return TRUE; } BOOL WINAPI RSA_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) { - FIXME("(stub)\n"); - return FALSE; + CRYPTHASH *pCryptHash; + + if (!is_valid_handle(&handle_table, (unsigned int)hProv)) + { + SetLastError(NTE_BAD_UID); + return FALSE; + } + + if (dwFlags) + { + SetLastError(NTE_BAD_FLAGS); + return FALSE; + } + + if (!lookup_handle(&handle_table, (unsigned int)hProv, (OBJECTHDR**)&pCryptHash)) + { + SetLastError(NTE_BAD_HASH); + return FALSE; + } + + if (pCryptHash->fFinished) + { + SetLastError(NTE_BAD_HASH_STATE); + return FALSE; + } + + switch (pCryptHash->aiAlgid) + { + case CALG_MD5: + IMPL(md5_update)((IMPL(md5_context)*)pCryptHash->pContext, (const void *)pbData, (unsigned int)dwDataLen); + break; + } + + return TRUE; } BOOL WINAPI RSA_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags) @@ -250,14 +842,14 @@ BOOL WINAPI RSA_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) { - RSA_CryptProv *cp = (RSA_CryptProv*) hProv; - TRACE("%08lx %08lx\n", hProv, dwFlags); - if( cp && ( cp->dwMagic != RSABASE_MAGIC ) ) - return FALSE; - - HeapFree( GetProcessHeap(), 0, cp ); + if (!release_handle(&handle_table, (unsigned int)hProv)) + { + /* MSDN: hProv not containing valid context handle */ + SetLastError(NTE_BAD_UID); + return FALSE; + } return TRUE; } @@ -340,8 +932,14 @@ 'M','i','c','r','o','s','o','f','t',' ','B','a','s','e',' ','C', 'r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r', 'o','v','i','d','e','r',' ','v','1','.','0',0 }; + static const WCHAR szTypeName[] = { 'T','y','p','e','N','a','m','e',0 }; + static const WCHAR szRSATypeName[] = { + 'R','S','A',' ','F','u','l','l',' ', + '(','S','i','g','n','a','t','u','r','e',' ','a','n','d',' ', + 'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 }; RegSetValueExW(key, szName, 0, REG_SZ, (LPBYTE)szRSAName, sizeof(szRSAName)); + RegSetValueExW(key, szTypeName, 0, REG_SZ, (LPBYTE)szRSATypeName, sizeof(szRSATypeName)); } RegCloseKey(key); } --- /dev/null 2004-06-05 20:01:53.000000000 +0200 +++ dlls/rsabase/handle.c 2004-07-24 10:05:32.000000000 +0200 @@ -0,0 +1,445 @@ +/* + * dlls/rsabase/handle.c + * Support code to manage HANDLE tables. + * + * Copyright 2004 Michael Jung + * + * based on code by Mike McCormack (dlls/msi/handle.c) + * and Alexandre Julliard (server/handle.c) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "handle.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(handle); + +/* NT handles are multiples of four and non zero */ +#define HANDLE2INDEX(h) (((h)>>2)-1) +#define INDEX2HANDLE(i) (((i)+1)<<2) + +/****************************************************************************** + * init_handle_table + * + * Initializes the HANDLETABLE structure pointed to by lpTable + * + * PARAMS + * lpTable [I] Pointer to the HANDLETABLE structure, which is to be initalized. + * + * NOTES + * Note that alloc_handle_table calls init_handle_table on it's own, which + * means that you only have to call init_handle_table, if you use a global + * variable of type HANDLETABLE for your handle table. However, in this + * case you have to call destruct_handle_table when you don't need the table + * any more. + */ +void init_handle_table(HANDLETABLE *lpTable) +{ + TRACE("(lpTable=%p)\n", lpTable); + + lpTable->paEntries = NULL; + lpTable->iEntries = 0; + lpTable->iFirstFree = 0; + InitializeCriticalSection(&lpTable->mutex); +} + +/****************************************************************************** + * destruct_handle_table + * + * Destructs the handle table. + * + * PARAMS + * lpTable [I] Pointer to the handle table, which is to be destructed. + * + * NOTES + * Note that release_handle_table takes care of this. + */ +void destruct_handle_table(HANDLETABLE *lpTable) +{ + TRACE("(lpTable=%p)\n", lpTable); + + if (lpTable->paEntries) + HeapFree(GetProcessHeap(), 0, lpTable->paEntries); + DeleteCriticalSection(&lpTable->mutex); +} + +/****************************************************************************** + * is_valid_handle_impl [Internal] + */ +int is_valid_handle_impl(HANDLETABLE *lpTable, unsigned int handle) +{ + unsigned int index = HANDLE2INDEX(handle); + + /* NT does not use zero handle values */ + if (!handle) + return 0; + /* NT handles are multiples of four */ + if (handle & 0x3) + return 0; + /* Check for index out of table bounds */ + if (index >= lpTable->iEntries) + return 0; + /* Check if this handle is currently allocated */ + if (!lpTable->paEntries[index].pObject) + return 0; + return 1; +} + +/****************************************************************************** + * is_valid_handle + * + * Tests if handle is valid given the specified handle table + * + * PARAMS + * lpTable [I] Pointer to the handle table, with respect to which the handle's + * validness is tested. + * handle [I] The handle tested for validness. + * + * RETURNS + * non zero, if handle is valid. + * zero, if handle is not valid. + */ +int is_valid_handle(HANDLETABLE *lpTable, unsigned int handle) +{ + int ret; + + TRACE("(lpTable=%p, handle=%d)\n", lpTable, handle); + + EnterCriticalSection(&lpTable->mutex); + ret = is_valid_handle_impl(lpTable, handle); + LeaveCriticalSection(&lpTable->mutex); + + return ret; +} + +/****************************************************************************** + * alloc_handle_table + * + * Allocates a new handle table + * + * PARAMS + * lplpTable [O] Pointer to the variable, to which the pointer to the newly + * allocated handle table is written. + * RETURNS + * non zero, if successfull + * zero, if not successfull (out of process heap memory) + * + * NOTES + * If all you need is a single handle table, you may as well declare a global + * variable of type HANDLETABLE and call init_handle_table on your own. + */ +int alloc_handle_table(HANDLETABLE **lplpTable) +{ + TRACE("(lplpTable=%p)\n", lplpTable); + + *lplpTable = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETABLE)); + if (*lplpTable) + { + init_handle_table(*lplpTable); + return 1; + } + else + return 0; +} + +/****************************************************************************** + * release_handle_table + * + * Releases a handle table and frees the resources occupied by it. + * + * PARAMS + * lpTable [I] Pointer to the handle table, which is to be released. + * + * RETURNS + * non zero, if successfull + * zero, if not successfull + * + * NOTES + * All valid handles still in the table are released also. + */ +int release_handle_table(HANDLETABLE *lpTable) +{ + TRACE("(lpTable=%p)\n", lpTable); + + release_all_handles(lpTable); + destruct_handle_table(lpTable); + return (int)HeapFree(GetProcessHeap(), 0, lpTable); +} + +/****************************************************************************** + * grow_handle_table_impl [Internal] + * + * Grows the number of entries in the given table by TABLE_SIZE_INCREMENT + * + * PARAMS + * lpTable [I] Pointer to the table, which is to be grown + * + * RETURNS + * non zero, if successfull + * zero, if not successfull (out of memory on process heap) + * + * NOTES + * This is a support function for alloc_handle. Do not call! + */ +int grow_handle_table_impl(HANDLETABLE *lpTable) +{ + HANDLETABLEENTRY *newEntries; + unsigned int i, newIEntries; + + newIEntries = lpTable->iEntries + TABLE_SIZE_INCREMENT; + + newEntries = (HANDLETABLEENTRY*)HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETABLEENTRY)*newIEntries); + if (!newEntries) + return 0; + + if (lpTable->paEntries) + { + memcpy(newEntries, lpTable->paEntries, sizeof(HANDLETABLEENTRY)*lpTable->iEntries); + HeapFree(GetProcessHeap(), 0, lpTable->paEntries); + } + + for (i=lpTable->iEntries; i<newIEntries; i++) + { + newEntries[i].pObject = NULL; + newEntries[i].iNextFree = i+1; + } + + lpTable->paEntries = newEntries; + lpTable->iEntries = newIEntries; + + return 1; +} + +/****************************************************************************** + * alloc_handle_impl [Internal] + */ +int alloc_handle_impl(HANDLETABLE *lpTable, OBJECTHDR *lpObject, unsigned int *lpHandle) +{ + if (lpTable->iFirstFree >= lpTable->iEntries) + if (!grow_handle_table_impl(lpTable)) + { + *lpHandle = (unsigned int)INVALID_HANDLE_VALUE; + return 0; + } + + *lpHandle = INDEX2HANDLE(lpTable->iFirstFree); + + lpTable->paEntries[lpTable->iFirstFree].pObject = lpObject; + lpTable->iFirstFree = lpTable->paEntries[lpTable->iFirstFree].iNextFree; + lpObject->refcount++; + + return 1; +} + +/****************************************************************************** + * alloc_handle + * + * Allocates a new handle to the specified object in a given handle table. + * + * PARAMS + * lpTable [I] Pointer to the handle table, from which the new handle is + * allocated. + * lpObject [I] Pointer to the object, for which a handle shall be allocated. + * lpHandle [O] Pointer to a handle variable, into which the handle value will + * be stored. If not successfull, this will be + * INVALID_HANDLE_VALUE + * RETURNS + * non zero, if successfull + * zero, if not successfull (no free handle) + */ +int alloc_handle(HANDLETABLE *lpTable, OBJECTHDR *lpObject, unsigned int *lpHandle) +{ + int ret; + + TRACE("(lpTable=%p, lpObject=%p, lpHandle=%p)\n", lpTable, lpObject, lpHandle); + + EnterCriticalSection(&lpTable->mutex); + ret = alloc_handle_impl(lpTable, lpObject, lpHandle); + LeaveCriticalSection(&lpTable->mutex); + + return ret; +} + +/****************************************************************************** + * release_handle_impl [Internal] + */ +int release_handle_impl(HANDLETABLE *lpTable, unsigned int handle) +{ + unsigned int index; + OBJECTHDR *pObject; + + if (!is_valid_handle_impl(lpTable, handle)) + return 0; + + index = HANDLE2INDEX(handle); + + pObject = lpTable->paEntries[index].pObject; + pObject->refcount--; + if (pObject->refcount == 0) + if (pObject->destructor) + pObject->destructor(pObject); + + lpTable->paEntries[index].pObject = NULL; + lpTable->paEntries[index].iNextFree = lpTable->iFirstFree; + lpTable->iFirstFree = index; + + return 1; +} + +/****************************************************************************** + * release_handle + * + * Releases resources occupied by the specified handle in the given table. + * The reference count of the handled object is decremented. If it becomes + * zero and if the 'destructor' function pointer member is non NULL, the + * destructor function will be called. Note that release_handle does not + * release resources other than the handle itself. If this is wanted, do it + * in the destructor function. + * + * PARAMS + * lpTable [I] Pointer to the handle table, from which a handle is to be + * released. + * handle [I] The handle, which is to be released + * + * RETURNS + * non zero, if successfull + * zero, if not successfull (invalid handle) + */ +int release_handle(HANDLETABLE *lpTable, unsigned int handle) +{ + int ret; + + TRACE("(lpTable=%p, hande=%d)\n", lpTable, handle); + + EnterCriticalSection(&lpTable->mutex); + ret = release_handle_impl(lpTable, handle); + LeaveCriticalSection(&lpTable->mutex); + + return ret; +} + +/****************************************************************************** + * release_all_handles_impl [Internal] + */ +void release_all_handles_impl(HANDLETABLE *lpTable) +{ + unsigned int i; + + for (i=0; i<lpTable->iEntries; i++) + if (lpTable->paEntries[i].pObject) + release_handle_impl(lpTable, INDEX2HANDLE(i)); +} + +/****************************************************************************** + * release_all_handles + * + * Releases all valid handles in the given handle table and shrinks the table + * to zero size. + * + * PARAMS + * lpTable [I] The table of which all valid handles shall be released. + */ +void release_all_handles(HANDLETABLE *lpTable) +{ + TRACE("(lpTable=%p)\n", lpTable); + + EnterCriticalSection(&lpTable->mutex); + release_all_handles_impl(lpTable); + LeaveCriticalSection(&lpTable->mutex); +} + +/****************************************************************************** + * lookup_handle_impl [Internal] + */ +int lookup_handle_impl(HANDLETABLE *lpTable, unsigned int handle, OBJECTHDR **lplpObject) +{ + if (!is_valid_handle_impl(lpTable, handle)) + { + *lplpObject = NULL; + return 0; + } + + *lplpObject = lpTable->paEntries[HANDLE2INDEX(handle)].pObject; + return 1; +} + +/****************************************************************************** + * lookup_handle + * + * Returns the object identified by the handle in the given handle table + * + * PARAMS + * lpTable [I] Pointer to the handle table, in which the handle is looked up. + * handle [I] The handle, which is to be looked up + * lplpObject [O] Pointer to the variable, into which the pointer to the + * object looked up is copied. + * RETURNS + * non zero, if successfull + * zero, if not successfull (invalid handle) + */ +int lookup_handle(HANDLETABLE *lpTable, unsigned int handle, OBJECTHDR **lplpObject) +{ + int ret; + + TRACE("(lpTable=%p, handle=%d, lplpObject=%p)\n", lpTable, handle, lplpObject); + + EnterCriticalSection(&lpTable->mutex); + ret = lookup_handle_impl(lpTable, handle, lplpObject); + LeaveCriticalSection(&lpTable->mutex); + + return ret; +} + +/****************************************************************************** + * copy_handle + * + * Copies a handle. Increments reference count in the object referenced by the + * handle + * + * PARAMS + * lpTable [I] Pointer to the handle table, which holds the handle to be copied. + * handle [I] The handle to be copied. + * copy [O] Pointer to a handle variable, where the copied handle is put. + * + * RETURNS + * non zero, if successfull + * zero, if not successfull (invalid handle or out of memory) + */ +int copy_handle(HANDLETABLE *lpTable, unsigned int handle, unsigned int *copy) +{ + OBJECTHDR *pObject; + int ret; + + TRACE("(lpTable=%p, handle=%d, copy=%p)\n", lpTable, handle, copy); + + EnterCriticalSection(&lpTable->mutex); + if (!lookup_handle_impl(lpTable, handle, &pObject)) + { + *copy = (unsigned int)INVALID_HANDLE_VALUE; + LeaveCriticalSection(&lpTable->mutex); + return 0; + } + + ret = alloc_handle_impl(lpTable, pObject, copy); + LeaveCriticalSection(&lpTable->mutex); + return ret; +} --- /dev/null 2004-06-05 20:01:53.000000000 +0200 +++ dlls/rsabase/handle.h 2004-07-24 10:05:32.000000000 +0200 @@ -0,0 +1,72 @@ +/* + * dlls/rsabse/handle.h + * Support code to manage HANDLE tables. + * + * Copyright 2004 Michael Jung + * + * based on code by Mike McCormack (dlls/msi/handle.c) + * and Alexandre Julliard (server/handle.c) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_HANDLE_H +#define __WINE_HANDLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TABLE_SIZE_INCREMENT 32 + +struct tagOBJECTHDR; +typedef struct tagOBJECTHDR OBJECTHDR; +typedef void (*DESTRUCTOR)(OBJECTHDR *object); +struct tagOBJECTHDR +{ + UINT refcount; + DESTRUCTOR destructor; +}; + +typedef struct tagHANDLETABLEENTRY +{ + OBJECTHDR *pObject; + unsigned int iNextFree; +} HANDLETABLEENTRY; + +typedef struct tagHANDLETABLE +{ + unsigned int iEntries; + unsigned int iFirstFree; + HANDLETABLEENTRY *paEntries; + CRITICAL_SECTION mutex; +} HANDLETABLE; + +int alloc_handle_table (HANDLETABLE **lplpTable); +void init_handle_table (HANDLETABLE *lpTable); +void release_all_handles (HANDLETABLE *lpTable); +int release_handle_table (HANDLETABLE *lpTable); +void destruct_handle_table(HANDLETABLE *lpTable); +int alloc_handle (HANDLETABLE *lpTable, OBJECTHDR *lpObject, unsigned int *lpHandle); +int release_handle (HANDLETABLE *lpTable, unsigned int handle); +int copy_handle (HANDLETABLE *lpTable, unsigned int handle, unsigned int *copy); +int lookup_handle (HANDLETABLE *lpTable, unsigned int handle, OBJECTHDR **lplpObject); +int is_valid_handle (HANDLETABLE *lpTable, unsigned int handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_HANDLE_H */ --- /dev/null 2004-06-05 20:01:53.000000000 +0200 +++ dlls/rsabase/implossl.c 2004-07-24 10:09:08.000000000 +0200 @@ -0,0 +1,82 @@ +#include "config.h" +#ifdef HAVE_OPENSSL_SSL_H + +#include "wine/port.h" +#include "wine/library.h" +#include "wine/debug.h" + +#include <openssl/rand.h> + +#include "implossl.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +#ifndef SONAME_LIBCRYPTO +#define SONAME_LIBCRYPTO "libcrypto.so" +#endif + +static void *libcrypto; + +#define MAKE_FUNCPTR(f) static typeof(f) * p##f + +/* OpenSSL funtions that we use */ +MAKE_FUNCPTR(RAND_bytes); +MAKE_FUNCPTR(MD5_Init); +MAKE_FUNCPTR(MD5_Update); +MAKE_FUNCPTR(MD5_Final); + +int IMPLOSSL_load_lib( void ) +{ + libcrypto = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0); + if (!libcrypto) + { + MESSAGE("Couldn't load %s, RSA encryption not available.\n", SONAME_LIBCRYPTO); + MESSAGE("Install the openssl package if you're have problems.\n"); + return 0; + } + + #define GETFUNC(x) \ + p##x = wine_dlsym(libcrypto, #x, NULL, 0); \ + if (!p##x) \ + { \ + ERR("failed to load symbol %s\n", #x); \ + return FALSE; \ + } + + GETFUNC(RAND_bytes); + GETFUNC(MD5_Init); + GETFUNC(MD5_Update); + GETFUNC(MD5_Final); + + return 1; +} + +int IMPLOSSL_random_bytes(unsigned char *pbBuffer, unsigned int cbLen) +{ + if (!pRAND_bytes) + return 0; + return pRAND_bytes(pbBuffer, cbLen); +} + +int IMPLOSSL_md5_init(IMPLOSSL_md5_context *ctx) +{ + if (!pMD5_Init) + return 0; + return pMD5_Init(ctx); +} + +int IMPLOSSL_md5_update(IMPLOSSL_md5_context *ctx, const void *pbData, unsigned int cbLen) +{ + if (!pMD5_Update) + return 0; + return pMD5_Update(ctx, pbData, cbLen); +} + +int IMPLOSSL_md5_get_digest(IMPLOSSL_md5_context *ctx, unsigned char *pbBuffer) +{ + if (!pMD5_Final) + return 0; + return pMD5_Final(pbBuffer, ctx); +} + +#endif /* HAVE_OPENSSL_SSL_H */ --- /dev/null 2004-06-05 20:01:53.000000000 +0200 +++ dlls/rsabase/implossl.h 2004-07-24 22:16:06.000000000 +0200 @@ -0,0 +1,16 @@ +#ifndef __WINE_IMPLOSSL_H +#define __WINE_IMPLOSSL_H + +#include <openssl/md5.h> + +#define IMPL(f) IMPLOSSL_##f + +typedef MD5_CTX IMPLOSSL_md5_context; + +int IMPLOSSL_load_lib(void); +int IMPLOSSL_random_bytes(unsigned char *pbBuffer, unsigned int cbLen); +int IMPLOSSL_md5_init(IMPLOSSL_md5_context *ctx); +int IMPLOSSL_md5_update(IMPLOSSL_md5_context *ctx, const void *pbData, unsigned int cbLen); +int IMPLOSSL_md5_get_digest(IMPLOSSL_md5_context *ctx, unsigned char *pbBuffer); + +#endif /* __WINE_IMPLOSSL_H */ --- /dev/null 2004-06-05 20:01:53.000000000 +0200 +++ dlls/rsabase/rsabase.h 2004-07-24 22:53:25.000000000 +0200 @@ -0,0 +1,48 @@ +#ifndef __WINE_RSABASE_H +#define __WINE_RSABASE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct tagCRYPTHASH +{ + OBJECTHDR header; + ALG_ID aiAlgid; + HCRYPTKEY hKey; + PVOID pContext; + BOOL fFinished; +} CRYPTHASH; + +typedef struct tagCRYPTKEY +{ + OBJECTHDR header; + ALG_ID aiAlgid; + DWORD dwKeyLen; + BYTE abKey[16]; +} CRYPTKEY; + +#define MODE_EPHEMERAL 0x00000001u +#define MODE_SILENT 0x00000002u +#define MODE_MACHINE_KEYSET 0x00000004u + +typedef struct tagKEYCONTAINER +{ + OBJECTHDR header; + DWORD dwMode; + CHAR szName[MAX_PATH]; + HCRYPTKEY hKeyExchangeKeyPair; + HCRYPTKEY hSignatureKeyPair; +} KEYCONTAINER; + +HCRYPTHASH new_crypt_hash(ALG_ID aiAlgid, HCRYPTKEY hKey); +HCRYPTKEY new_crypt_key(ALG_ID aiAlgid, DWORD dwKeyLen, BYTE *pbKey); +HCRYPTKEY duplicate_key(HCRYPTKEY other); +HCRYPTPROV new_key_container(PCHAR pszContainerName); +HCRYPTPROV read_key_container(PCHAR pszContainerName); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_RSABASE_H */