A while ago I started hacking out an implementation of CryptoAPI. It sat idle for a while and a few days ago I decided to start doing a bit more hacking again.
The basics of ADVAPI32's CryptoAPI part is that it does nothing except provide an interface for applications to call into CSPs without actually loading the CSPs themselves.
At the moment the TESTCSP.EXE with its accompanying CSP.DLL is starting to work. These are from Microsoft's CSPDK and include source code. I have not tried compiling the source with Winelib, that is a later project.
At the moment this code keeps track of which CSPs are loaded and which CSP an HCRYPTPROV handle uses. This allows testcsp to load up csp.dll and do a few things, but not everything.
What bothers me though is that it does not get Intenret Explorer to load up the RSA CSP. The LoadLibrary fails because the DllMain function in the CSP returns FALSE. I speculate this has something to do with the fact that a real CSP needs to have its image verified before it will load. Or maybe it is something different entirely.
Anyway, still left to be done are to keep track of Key and Hash handles (trivially easy) and maybe some other stuff.
As far as putting this into the tree goes, I don't think it would harm anything, although I noticed that the GenRandom function had a useless implementation in it. It now has what I believe to be the correct implementation, but if loading the CSP fails that CryptGenRadom isn't going to work. Did somebodies appication actually depend on this behavior or was it implemented just to have something there?
In any case, this still needs to be cleaned up a bit, but I am hoping to get some input on why I cannot load a real CSP as this is all completely useless (well, not completely, but for my purposes) if a real CSP cannot be loaded.
-Dave
David Elliott dfe@tgwbd.org writes:
What bothers me though is that it does not get Intenret Explorer to load up the RSA CSP. The LoadLibrary fails because the DllMain function in the CSP returns FALSE. I speculate this has something to do with the fact that a real CSP needs to have its image verified before it will load. Or maybe it is something different entirely.
Is this rsabase.dll? If so this is because of a problem with LOAD_LIBRARY_AS_DATAFILE; I have a patch for this somewhere.
On 2001.12.19 20:08 Alexandre Julliard wrote:
David Elliott dfe@tgwbd.org writes:
What bothers me though is that it does not get Intenret Explorer to load up the RSA CSP. The LoadLibrary fails because the DllMain function in the CSP returns FALSE. I speculate this has something to do with the fact that a real CSP needs to have its image verified before it will load. Or maybe it is something different entirely.
Is this rsabase.dll? If so this is because of a problem with LOAD_LIBRARY_AS_DATAFILE; I have a patch for this somewhere.
-- Alexandre Julliard julliard@winehq.com
Actually, rsaenh.dll. I am running IE 5.5 and accessing https://internetbanking.suntrust.com/. Not that this site doesn't work with Galeon anyway, but it seemed like a fairly simple way to test the crypto functionality.
Running wine --debugmsg +crypt IEXPLORE.EXE I get:
[...] trace:crypt:CryptAcquireContextA (phProv=0x7741b7d4, szContainer=(null), szProvider=Microsoft Enhanced Cryptographic Provider v1.0, dwProvType=1, dwFlags=f0000000) trace:crypt:CryptAcquireContextA Provider is Microsoft Enhanced Cryptographic Provider v1.0 trace:crypt:CryptAcquireContextA DLL is rsaenh.dll trace:crypt:CryptAcquireContextA Signature is 136 bytes long trace:crypt:CryptAcquireContextA Type is 1 trace:crypt:CRYPTOAPI_LoadCSP ImagePath=rsaenh.dll trace:crypt:CRYPTOAPI_LoadCSP pCspInfo->ImagePath=rsaenh.dll err:crypt:CRYPTOAPI_LoadCSP Could not LoadLibrary 1114 err:crypt:CryptAcquireContextA Could not load CSP trace:crypt:CryptAcquireContextA (phProv=0x7741b7d4, szContainer=(null), szProvider=Microsoft Enhanced Cryptographic Provider v1.0, dwProvType=1, dwFlags=f0000000) trace:crypt:CryptAcquireContextA Provider is Microsoft Enhanced Cryptographic Provider v1.0 trace:crypt:CryptAcquireContextA DLL is rsaenh.dll trace:crypt:CryptAcquireContextA Signature is 136 bytes long trace:crypt:CryptAcquireContextA Type is 1 trace:crypt:CRYPTOAPI_LoadCSP ImagePath=rsaenh.dll trace:crypt:CRYPTOAPI_LoadCSP pCspInfo->ImagePath=rsaenh.dll err:crypt:CRYPTOAPI_LoadCSP Could not LoadLibrary 1114 err:crypt:CryptAcquireContextA Could not load CSP [...]
I just tried running with +crypt,+relay and I get a crash before the main window comes up (with the non-drawn splash screen above everything) in INT21_FindFirstFCB on line 788 which is else pFCB = (FINDFILE_FCB *)fcb;
For some reason I cannot use the enter key in the console and trying to paste an enter from another window doesn't work either. So using the debugger does not work, hitting Ctrl-C in the console does work though. Is this a problem other people are having? I would have thought someone would have reported it by now if that was the case.
Anyway, if you think the patch you have might help me get RSAENH.DLL loaded and a bit further then I could probably have https sites working in IE shortly.
In any case I think if I just look over this code a little bit and make sure there are no absolutely glaring errors there should be no reason not to put it in the tree, even if it can't actually load a real CSP for some other reason.
-Dave
On Wednesday, December 19, 2001 10:12 pm, you wrote:
On 2001.12.19 20:08 Alexandre Julliard wrote:
David Elliott dfe@tgwbd.org writes:
What bothers me though is that it does not get Intenret Explorer to load up the RSA CSP. The LoadLibrary fails because the DllMain function in the CSP returns FALSE. I speculate this has something to do with the fact that a real CSP needs to have its image verified before it will load. Or maybe it is something different entirely.
Is this rsabase.dll? If so this is because of a problem with LOAD_LIBRARY_AS_DATAFILE; I have a patch for this somewhere.
-- Alexandre Julliard julliard@winehq.com
Actually, rsaenh.dll. I am running IE 5.5 and accessing https://internetbanking.suntrust.com/. Not that this site doesn't work with Galeon anyway, but it seemed like a fairly simple way to test the crypto functionality.
Running wine --debugmsg +crypt IEXPLORE.EXE I get:
[...] trace:crypt:CryptAcquireContextA (phProv=0x7741b7d4, szContainer=(null), szProvider=Microsoft Enhanced Cryptographic Provider v1.0, dwProvType=1, dwFlags=f0000000) trace:crypt:CryptAcquireContextA Provider is Microsoft Enhanced Cryptographic Provider v1.0 trace:crypt:CryptAcquireContextA DLL is rsaenh.dll trace:crypt:CryptAcquireContextA Signature is 136 bytes long trace:crypt:CryptAcquireContextA Type is 1 trace:crypt:CRYPTOAPI_LoadCSP ImagePath=rsaenh.dll trace:crypt:CRYPTOAPI_LoadCSP pCspInfo->ImagePath=rsaenh.dll err:crypt:CRYPTOAPI_LoadCSP Could not LoadLibrary 1114 err:crypt:CryptAcquireContextA Could not load CSP trace:crypt:CryptAcquireContextA (phProv=0x7741b7d4, szContainer=(null), szProvider=Microsoft Enhanced Cryptographic Provider v1.0, dwProvType=1, dwFlags=f0000000) trace:crypt:CryptAcquireContextA Provider is Microsoft Enhanced Cryptographic Provider v1.0 trace:crypt:CryptAcquireContextA DLL is rsaenh.dll trace:crypt:CryptAcquireContextA Signature is 136 bytes long trace:crypt:CryptAcquireContextA Type is 1 trace:crypt:CRYPTOAPI_LoadCSP ImagePath=rsaenh.dll trace:crypt:CRYPTOAPI_LoadCSP pCspInfo->ImagePath=rsaenh.dll err:crypt:CRYPTOAPI_LoadCSP Could not LoadLibrary 1114 err:crypt:CryptAcquireContextA Could not load CSP [...]
I just tried running with +crypt,+relay and I get a crash before the main window comes up (with the non-drawn splash screen above everything) in INT21_FindFirstFCB on line 788 which is else pFCB = (FINDFILE_FCB *)fcb;
For some reason I cannot use the enter key in the console and trying to paste an enter from another window doesn't work either. So using the debugger does not work, hitting Ctrl-C in the console does work though. Is this a problem other people are having? I would have thought someone would have reported it by now if that was the case.
Anyway, if you think the patch you have might help me get RSAENH.DLL loaded and a bit further then I could probably have https sites working in IE shortly.
In any case I think if I just look over this code a little bit and make sure there are no absolutely glaring errors there should be no reason not to put it in the tree, even if it can't actually load a real CSP for some other reason.
-Dave
Actually I too, have been hacking away at the CryptoAPI (advapi32.dll) and was going to submit a full patch for it at the end of the week. My patch, however, has almost a completely different approach to the problem! Attached is my version (not quite complete or clean).
These are the main differences and issues I see between our patches:
1) I can successfully acquire/release a context (tested with MSDN sample code). I have not experienced any problems with <loading> a CSP. 2) Currently the ms CSPs can perform but all launch pstores.exe - the protected stores service. This is fine except that it eventually crashes with an unhandled exception c0000005 and then becomes unwilling to start again. 3) Dependancy functions of pstores and M$ providers not implemented: (advapi:RevertToSelf, ntdll:NtOpenProcessToken, advapi:SetThreadToken, mpr:WNetGetCachedPassword, etc.) 4) I do not create any list of providers. This should not be required as the registry is supposed to contain the list of available providers. Once a handle is acquired then we can gain access to the provider by this handle. Note: Key and hash objects need to link to the provider handle, when they are created. 5) I have not yet considered thread or process safing/locking. Nor have I done any reference counting. 6) Seting and getting Key/Hash/Prov Params doesn't consider flags not used by the CSP and have meaning in advapi32.dll. 7) I currently do not allow a CSP to drop any of the stardard functions. This only affects a few functions, however, as MSDN states these functions are *required* for the CSP to have. If they are not implemented they must set the last error as ERROR_CALL_NOT_IMPLEMENTED. 8) You seem to make not use
Anyway I think the correct thing to do right now is to co-ordinate our work to make a single patch and implementation.
I am currently testing this code against windows 98.
- Travis
David Elliott dfe@tgwbd.org writes:
Anyway, if you think the patch you have might help me get RSAENH.DLL loaded and a bit further then I could probably have https sites working in IE shortly.
If rasenh.dll has the same problem as rsabase.dll, I think this should help:
Index: loader/module.c =================================================================== RCS file: /opt/cvs-commit/wine/loader/module.c,v retrieving revision 1.144 diff -u -r1.144 module.c --- loader/module.c 2001/12/20 00:19:42 1.144 +++ loader/module.c 2001/12/20 16:08:04 @@ -1284,7 +1284,18 @@ NULL, OPEN_EXISTING, 0, 0 ); if (hFile != INVALID_HANDLE_VALUE) { - hmod = PE_LoadImage( hFile, filename, flags ); + DWORD type; + MODULE_GetBinaryType( hFile, filename, &type ); + if (type == SCS_32BIT_BINARY) + { + HANDLE mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, + 0, 0, NULL ); + if (mapping) + { + hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); + CloseHandle( mapping ); + } + } CloseHandle( hFile ); } if (hmod) return (HMODULE)((ULONG_PTR)hmod + 1); Index: loader/pe_resource.c =================================================================== RCS file: /opt/cvs-commit/wine/loader/pe_resource.c,v retrieving revision 1.34 diff -u -r1.34 pe_resource.c --- loader/pe_resource.c 2001/10/14 16:18:53 1.34 +++ loader/pe_resource.c 2001/12/20 16:08:05 @@ -48,6 +48,39 @@
/********************************************************************** + * is_data_file_module + * + * Check if a module handle is for a LOAD_LIBRARY_AS_DATAFILE module. + */ +inline static int is_data_file_module( HMODULE hmod ) +{ + return (ULONG_PTR)hmod & 1; +} + + +/********************************************************************** + * get_data_file_ptr + * + * Get a pointer to a given offset in a file mapped as data file. + */ +static const void *get_data_file_ptr( const void *base, DWORD offset ) +{ + const IMAGE_NT_HEADERS *nt = PE_HEADER(base); + const IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + + nt->FileHeader.SizeOfOptionalHeader); + int i; + + /* find the section containing the virtual address */ + for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) + { + if ((sec->VirtualAddress <= offset) && (sec->VirtualAddress + sec->SizeOfRawData > offset)) + return (char *)base + sec->PointerToRawData + (offset - sec->VirtualAddress); + } + return NULL; +} + + +/********************************************************************** * get_resdir * * Get the resource directory of a PE module @@ -62,7 +95,10 @@ { dir = &PE_HEADER(base)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; if (dir->Size && dir->VirtualAddress) - ret = (IMAGE_RESOURCE_DIRECTORY *)((char *)base + dir->VirtualAddress); + { + if (is_data_file_module(hmod)) ret = get_data_file_ptr( base, dir->VirtualAddress ); + else ret = (IMAGE_RESOURCE_DIRECTORY *)((char *)base + dir->VirtualAddress); + } } return ret; } @@ -272,9 +308,17 @@ */ HGLOBAL PE_LoadResource( HMODULE hmod, HRSRC hRsrc ) { + DWORD offset; const void *base = get_module_base( hmod ); - if (!hRsrc) return 0; - return (HANDLE)((char *)base + ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData); + + if (!hRsrc || !base) return 0; + + offset = ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData; + + if (is_data_file_module(hmod)) + return (HANDLE)get_data_file_ptr( base, offset ); + else + return (HANDLE)((char *)base + offset); }