Implemented a substantial part of rsaenh.dll.

This commit is contained in:
Michael Jung 2004-11-04 21:15:32 +00:00 committed by Alexandre Julliard
parent 8ce698e2a4
commit 64dce8a579
16 changed files with 4955 additions and 2 deletions

14
configure vendored

File diff suppressed because one or more lines are too long

View File

@ -1174,6 +1174,11 @@ AC_CHECK_HEADERS(\
netinet/in_systm.h \
netinet/tcp.h \
netinet/tcp_fsm.h \
openssl/des.h \
openssl/md2.h \
openssl/rc2.h \
openssl/rc4.h \
openssl/rsa.h \
openssl/ssl.h \
process.h \
pthread.h \
@ -1686,6 +1691,8 @@ dlls/rpcrt4/Makefile
dlls/rpcrt4/tests/Makefile
dlls/rsabase/Makefile
dlls/rsabase/tests/Makefile
dlls/rsaenh/Makefile
dlls/rsaenh/tests/Makefile
dlls/secur32/Makefile
dlls/serialui/Makefile
dlls/setupapi/Makefile

View File

@ -110,6 +110,7 @@ BASEDIRS = \
richedit \
rpcrt4 \
rsabase \
rsaenh \
secur32 \
serialui \
setupapi \
@ -348,6 +349,7 @@ SYMLINKS_SO = \
riched32.dll.so \
rpcrt4.dll.so \
rsabase.dll.so \
rsaenh.dll.so \
secur32.dll.so \
serialui.dll.so \
setupapi.dll.so \
@ -777,6 +779,9 @@ rpcrt4.dll.so: rpcrt4/rpcrt4.dll.so
rsabase.dll.so: rsabase/rsabase.dll.so
$(RM) $@ && $(LN_S) rsabase/rsabase.dll.so $@
rsaenh.dll.so: rsaenh/rsaenh.dll.so
$(RM) $@ && $(LN_S) rsaenh/rsaenh.dll.so $@
secur32.dll.so: secur32/secur32.dll.so
$(RM) $@ && $(LN_S) secur32/secur32.dll.so $@
@ -1069,6 +1074,7 @@ IMPORT_LIBS = \
libriched32.$(IMPLIBEXT) \
librpcrt4.$(IMPLIBEXT) \
librsabase.$(IMPLIBEXT) \
librsaenh.$(IMPLIBEXT) \
libsecur32.$(IMPLIBEXT) \
libserialui.$(IMPLIBEXT) \
libsetupapi.$(IMPLIBEXT) \
@ -1571,6 +1577,11 @@ librsabase.def: rsabase/rsabase.spec.def
librsabase.a: rsabase/rsabase.spec.def
$(DLLTOOL) -k -l $@ -d rsabase/rsabase.spec.def
librsaenh.def: rsaenh/rsaenh.spec.def
$(RM) $@ && $(LN_S) rsaenh/rsaenh.spec.def $@
librsaenh.a: rsaenh/rsaenh.spec.def
$(DLLTOOL) -k -l $@ -d rsaenh/rsaenh.spec.def
libsecur32.def: secur32/secur32.spec.def
$(RM) $@ && $(LN_S) secur32/secur32.spec.def $@
libsecur32.a: secur32/secur32.spec.def
@ -1833,6 +1844,7 @@ rasapi32/rasapi32.spec.def: $(WINEBUILD)
richedit/riched32.spec.def: $(WINEBUILD)
rpcrt4/rpcrt4.spec.def: $(WINEBUILD)
rsabase/rsabase.spec.def: $(WINEBUILD)
rsaenh/rsaenh.spec.def: $(WINEBUILD)
secur32/secur32.spec.def: $(WINEBUILD)
serialui/serialui.spec.def: $(WINEBUILD)
setupapi/setupapi.spec.def: $(WINEBUILD)
@ -1981,6 +1993,7 @@ rasapi32/rasapi32.dll.so: rasapi32
richedit/riched32.dll.so: richedit
rpcrt4/rpcrt4.dll.so: rpcrt4
rsabase/rsabase.dll.so: rsabase
rsaenh/rsaenh.dll.so: rsaenh
secur32/secur32.dll.so: secur32
serialui/serialui.dll.so: serialui
setupapi/setupapi.dll.so: setupapi

3
dlls/rsaenh/.cvsignore Normal file
View File

@ -0,0 +1,3 @@
Makefile
rsaenh.dll.dbg.c
rsaenh.spec.def

18
dlls/rsaenh/Makefile.in Normal file
View File

@ -0,0 +1,18 @@
EXTRADEFS = -DCOM_NO_WINDOWS_H
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = rsaenh.dll
IMPORTS = advapi32 kernel32
C_SRCS = \
handle.c \
implossl.c \
rsaenh.c
SUBDIRS = tests
@MAKE_DLL_RULES@
### Dependencies:

454
dlls/rsaenh/handle.c Normal file
View File

@ -0,0 +1,454 @@
/*
* dlls/rsaenh/handle.c
* Support code to manage HANDLE tables.
*
* Copyright 1998 Alexandre Julliard
* Copyright 2002-2004 Mike McCormack for CodeWeavers
* Copyright 2004 Michael Jung
*
* 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);
#define HANDLE2INDEX(h) ((h)-1)
#define INDEX2HANDLE(i) ((i)+1)
/******************************************************************************
* 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 destroy_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);
}
/******************************************************************************
* destroy_handle_table
*
* Destroys the handle table.
*
* PARAMS
* lpTable [I] Pointer to the handle table, which is to be destroyed.
*
* NOTES
* Note that release_handle_table takes care of this.
*/
void destroy_handle_table(HANDLETABLE *lpTable)
{
TRACE("(lpTable=%p)\n", lpTable);
if (lpTable->paEntries)
HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
DeleteCriticalSection(&lpTable->mutex);
}
/******************************************************************************
* 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.
* dwType [I] A magic value that identifies the referenced object's type.
*
* RETURNS
* non zero, if handle is valid.
* zero, if handle is not valid.
*/
int is_valid_handle(HANDLETABLE *lpTable, unsigned int handle, DWORD dwType)
{
unsigned int index = HANDLE2INDEX(handle);
int ret = 0;
TRACE("(lpTable=%p, handle=%d)\n", lpTable, handle);
EnterCriticalSection(&lpTable->mutex);
/* We don't use zero handle values */
if (!handle) goto exit;
/* Check for index out of table bounds */
if (index >= lpTable->iEntries) goto exit;
/* Check if this handle is currently allocated */
if (!lpTable->paEntries[index].pObject) goto exit;
/* Check if this handle references an object of the correct type. */
if (lpTable->paEntries[index].pObject->dwType != dwType) goto exit;
ret = 1;
exit:
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);
destroy_handle_table(lpTable);
return (int)HeapFree(GetProcessHeap(), 0, lpTable);
}
/******************************************************************************
* grow_handle_table [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!
*/
static int grow_handle_table(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
*
* 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 = 0;
TRACE("(lpTable=%p, lpObject=%p, lpHandle=%p)\n", lpTable, lpObject, lpHandle);
EnterCriticalSection(&lpTable->mutex);
if (lpTable->iFirstFree >= lpTable->iEntries)
if (!grow_handle_table(lpTable))
{
*lpHandle = (unsigned int)INVALID_HANDLE_VALUE;
goto exit;
}
*lpHandle = INDEX2HANDLE(lpTable->iFirstFree);
lpTable->paEntries[lpTable->iFirstFree].pObject = lpObject;
lpTable->iFirstFree = lpTable->paEntries[lpTable->iFirstFree].iNextFree;
lpObject->refcount++;
ret = 1;
exit:
LeaveCriticalSection(&lpTable->mutex);
return ret;
}
/******************************************************************************
* 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
* dwType [I] Identifier for the type of the object, for which a handle is
* to be released.
*
* RETURNS
* non zero, if successfull
* zero, if not successfull (invalid handle)
*/
int release_handle(HANDLETABLE *lpTable, unsigned int handle, DWORD dwType)
{
unsigned int index = HANDLE2INDEX(handle);
OBJECTHDR *pObject;
int ret = 0;
TRACE("(lpTable=%p, hande=%d)\n", lpTable, handle);
EnterCriticalSection(&lpTable->mutex);
if (!is_valid_handle(lpTable, handle, dwType))
goto exit;
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;
ret = 1;
exit:
LeaveCriticalSection(&lpTable->mutex);
return ret;
}
/******************************************************************************
* 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)
{
unsigned int i;
TRACE("(lpTable=%p)\n", lpTable);
EnterCriticalSection(&lpTable->mutex);
for (i=0; i<lpTable->iEntries; i++)
if (lpTable->paEntries[i].pObject)
release_handle(lpTable, lpTable->paEntries[i].pObject->dwType, INDEX2HANDLE(i));
LeaveCriticalSection(&lpTable->mutex);
}
/******************************************************************************
* 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, DWORD dwType, OBJECTHDR **lplpObject)
{
int ret = 0;
TRACE("(lpTable=%p, handle=%d, lplpObject=%p)\n", lpTable, handle, lplpObject);
EnterCriticalSection(&lpTable->mutex);
if (!is_valid_handle(lpTable, handle, dwType))
{
*lplpObject = NULL;
goto exit;
}
*lplpObject = lpTable->paEntries[HANDLE2INDEX(handle)].pObject;
ret = 1;
exit:
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, DWORD dwType, unsigned int *copy)
{
OBJECTHDR *pObject;
int ret;
TRACE("(lpTable=%p, handle=%d, copy=%p)\n", lpTable, handle, copy);
EnterCriticalSection(&lpTable->mutex);
if (!lookup_handle(lpTable, handle, dwType, &pObject))
{
*copy = (unsigned int)INVALID_HANDLE_VALUE;
LeaveCriticalSection(&lpTable->mutex);
return 0;
}
ret = alloc_handle(lpTable, pObject, copy);
LeaveCriticalSection(&lpTable->mutex);
return ret;
}
/******************************************************************************
* new_object
*
* Allocates a new object of size cbSize on the current process's heap.
* Initializes the object header using the destructor and dwType params.
* Allocates a handle to the object in the handle table pointed to by lpTable.
* Returns a pointer to the created object in ppObject.
* Returns a handle to the created object.
*
* PARAMS
* lpTable [I] Pointer to the handle table, from which a handle is to be
* allocated.
* cbSize [I] Size of the object to be allocated in bytes.
* dwType [I] Object type; will be copied to the object header.
* destructor [I] Function pointer to a destructor function. Will be called
* once the object's reference count gets zero.
* ppObject [O] Pointer to a pointer variable, where a pointer to the newly
* created object will be stored. You may set this to NULL.
*
* RETURNS
* INVALID_HANDLE_VALUE, if something went wrong.
* a handle to the new object, if successfull.
*/
unsigned int new_object(HANDLETABLE *lpTable, size_t cbSize, DWORD dwType, 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->dwType = dwType;
pObject->refcount = 0;
pObject->destructor = destructor;
if (!alloc_handle(lpTable, pObject, &hObject))
HeapFree(GetProcessHeap(), 0, pObject);
else
if (ppObject)
*ppObject = pObject;
return hObject;
}

75
dlls/rsaenh/handle.h Normal file
View File

@ -0,0 +1,75 @@
/*
* dlls/rsaenh/handle.h
* Support code to manage HANDLE tables.
*
* Copyright 1998 Alexandre Julliard
* Copyright 2002-2004 Mike McCormack for CodeWeavers
* Copyright 2004 Michael Jung
*
* 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
{
DWORD dwType;
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 destroy_handle_table(HANDLETABLE *lpTable);
int alloc_handle (HANDLETABLE *lpTable, OBJECTHDR *lpObject, unsigned int *lpHandle);
int release_handle (HANDLETABLE *lpTable, unsigned int handle, DWORD dwType);
int copy_handle (HANDLETABLE *lpTable, unsigned int handle, DWORD dwType, unsigned int *copy);
int lookup_handle (HANDLETABLE *lpTable, unsigned int handle, DWORD dwType, OBJECTHDR **lplpObject);
int is_valid_handle (HANDLETABLE *lpTable, unsigned int handle, DWORD dwType);
unsigned int new_object (HANDLETABLE *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
OBJECTHDR **ppObject);
#ifdef __cplusplus
}
#endif
#endif /* __WINE_HANDLE_H */

683
dlls/rsaenh/implossl.c Normal file
View File

@ -0,0 +1,683 @@
/*
* dlls/rsaenh/implossl.c
* Encapsulating the OpenSSL dependend parts of RSAENH
*
* Copyright (c) 2004 Michael Jung
*
* based on code by Mike McCormack and David Hammerton
*
* 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 "config.h"
#include "wine/port.h"
#include "wine/library.h"
#include "wine/debug.h"
#include "windef.h"
#include "wincrypt.h"
#include "implossl.h"
#include <stdio.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 */
#ifdef HAVE_OPENSSL_MD2_H
MAKE_FUNCPTR(MD2_Init);
MAKE_FUNCPTR(MD2_Update);
MAKE_FUNCPTR(MD2_Final);
#endif
#ifdef HAVE_OPENSSL_RC2_H
MAKE_FUNCPTR(RC2_set_key);
MAKE_FUNCPTR(RC2_ecb_encrypt);
#endif
#ifdef HAVE_OPENSSL_RC4_H
MAKE_FUNCPTR(RC4_set_key);
MAKE_FUNCPTR(RC4);
#endif
#ifdef HAVE_OPENSSL_DES_H
MAKE_FUNCPTR(DES_set_odd_parity);
MAKE_FUNCPTR(DES_set_key_unchecked);
MAKE_FUNCPTR(DES_ecb_encrypt);
MAKE_FUNCPTR(DES_ecb3_encrypt);
#endif
#ifdef HAVE_OPENSSL_RSA_H
MAKE_FUNCPTR(RSA_generate_key);
MAKE_FUNCPTR(RSA_free);
MAKE_FUNCPTR(RSA_size);
MAKE_FUNCPTR(RSA_check_key);
MAKE_FUNCPTR(RSA_public_encrypt);
MAKE_FUNCPTR(RSA_private_encrypt);
MAKE_FUNCPTR(RSAPrivateKey_dup);
MAKE_FUNCPTR(BN_bn2bin);
MAKE_FUNCPTR(BN_bin2bn);
MAKE_FUNCPTR(BN_get_word);
MAKE_FUNCPTR(BN_set_word);
MAKE_FUNCPTR(BN_num_bits);
#endif
/* Function prototypes copied from dlls/advapi32/crypt_md4.c */
VOID WINAPI MD4Init( MD4_CTX *ctx );
VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len );
VOID WINAPI MD4Final( MD4_CTX *ctx );
/* Function prototypes copied from dlls/advapi32/crypt_md5.c */
VOID WINAPI MD5Init( MD5_CTX *ctx );
VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len );
VOID WINAPI MD5Final( MD5_CTX *ctx );
/* Function prototypes copied from dlls/advapi32/crypt_sha.c */
VOID WINAPI A_SHAInit(PSHA_CTX Context);
VOID WINAPI A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize);
VOID WINAPI A_SHAFinal(PSHA_CTX Context, PULONG Result);
BOOL load_lib( void )
{
/* FIXME: Is this portable? */
#if defined HAVE_OPENSSL_MD2_H || defined HAVE_OPENSSL_RC2_H || defined HAVE_OPENSSL_RC4_H || \
defined HAVE_OPENSSL_DES_H || defined HAVE_OPENSSL_RSA_H
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");
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
#define GETFUNC(x) p##x = wine_dlsym(libcrypto, #x, NULL, 0);
#ifdef HAVE_OPENSSL_MD2_H
GETFUNC(MD2_Init);
GETFUNC(MD2_Update);
GETFUNC(MD2_Final);
#endif
#ifdef HAVE_OPENSSL_RC2_H
GETFUNC(RC2_set_key);
GETFUNC(RC2_ecb_encrypt);
#endif
#ifdef HAVE_OPENSSL_RC4_H
GETFUNC(RC4_set_key);
GETFUNC(RC4);
#endif
#ifdef HAVE_OPENSSL_DES_H
GETFUNC(DES_set_odd_parity);
GETFUNC(DES_set_key_unchecked);
GETFUNC(DES_ecb_encrypt);
GETFUNC(DES_ecb3_encrypt);
#endif
#ifdef HAVE_OPENSSL_RSA_H
GETFUNC(RSA_generate_key);
GETFUNC(RSA_free);
GETFUNC(RSA_size);
GETFUNC(RSA_check_key);
GETFUNC(RSA_public_encrypt);
GETFUNC(RSA_private_encrypt);
GETFUNC(RSAPrivateKey_dup);
GETFUNC(BN_bn2bin);
GETFUNC(BN_bin2bn);
GETFUNC(BN_get_word);
GETFUNC(BN_set_word);
GETFUNC(BN_num_bits);
#endif
#endif /* ifdef have any openssl header */
return TRUE;
}
BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_MD2_H
case CALG_MD2:
if (!pMD2_Init)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pMD2_Init(&pHashContext->md2);
break;
#endif
case CALG_MD4:
MD4Init(&pHashContext->md4);
break;
case CALG_MD5:
MD5Init(&pHashContext->md5);
break;
case CALG_SHA:
A_SHAInit(&pHashContext->sha);
break;
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData,
DWORD dwDataLen)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_MD2_H
case CALG_MD2:
if (!pMD2_Update)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pMD2_Update(&pHashContext->md2, pbData, dwDataLen);
break;
#endif
case CALG_MD4:
MD4Update(&pHashContext->md4, pbData, dwDataLen);
break;
case CALG_MD5:
MD5Update(&pHashContext->md5, pbData, dwDataLen);
break;
case CALG_SHA:
A_SHAUpdate(&pHashContext->sha, (PCHAR)pbData, dwDataLen);
break;
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_MD2_H
case CALG_MD2:
if (!pMD2_Final)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pMD2_Final(pbHashValue, &pHashContext->md2);
break;
#endif
case CALG_MD4:
MD4Final(&pHashContext->md4);
memcpy(pbHashValue, pHashContext->md4.digest, 16);
break;
case CALG_MD5:
MD5Final(&pHashContext->md5);
memcpy(pbHashValue, pHashContext->md5.digest, 16);
break;
case CALG_SHA:
A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue);
break;
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext,
HASH_CONTEXT *pDestHashContext)
{
memcpy(pDestHashContext, pSrcHashContext, sizeof(HASH_CONTEXT));
return TRUE;
}
BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_RSA_H
case CALG_RSA_KEYX:
case CALG_RSA_SIGN:
if (!pRSA_generate_key)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pKeyContext->rsa = pRSA_generate_key((int)dwKeyLen*8, 65537, NULL, NULL);
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_RSA_H
case CALG_RSA_KEYX:
case CALG_RSA_SIGN:
if (!pRSA_free)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
if (pKeyContext->rsa) pRSA_free(pKeyContext->rsa);
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen,
BYTE *abKeyValue)
{
switch (aiAlgid)
{
#ifdef HAVE_OPENSSL_RC4_H
case CALG_RC4:
if (!pRC4_set_key)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pRC4_set_key(&pKeyContext->rc4, dwKeyLen + dwSaltLen, abKeyValue);
break;
#endif
#ifdef HAVE_OPENSSL_RC2_H
case CALG_RC2:
if (!pRC2_set_key)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pRC2_set_key(&pKeyContext->rc2, dwKeyLen + dwSaltLen, abKeyValue, dwKeyLen * 8);
break;
#endif
#ifdef HAVE_OPENSSL_DES_H
case CALG_3DES:
if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[2]);
pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[2], &pKeyContext->des[2]);
case CALG_3DES_112:
if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[1]);
pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[1], &pKeyContext->des[1]);
case CALG_DES:
if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_set_odd_parity((DES_cblock*)abKeyValue);
pDES_set_key_unchecked((DES_cblock*)abKeyValue, &pKeyContext->des[0]);
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext,
KEY_CONTEXT *pDestKeyContext)
{
switch (aiAlgid)
{
case CALG_RC4:
case CALG_RC2:
case CALG_3DES:
case CALG_3DES_112:
case CALG_DES:
memcpy(pDestKeyContext, pSrcKeyContext, sizeof(KEY_CONTEXT));
break;
#ifdef HAVE_OPENSSL_RSA_H
case CALG_RSA_KEYX:
case CALG_RSA_SIGN:
if (!pRSAPrivateKey_dup)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDestKeyContext->rsa = pRSAPrivateKey_dup(pSrcKeyContext->rsa);
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
#ifdef HAVE_OPENSSL_RSA_H
static inline void reverse_bytes(BYTE *pbData, DWORD dwLen) {
BYTE swap;
DWORD i;
for (i=0; i<dwLen/2; i++) {
swap = pbData[i];
pbData[i] = pbData[dwLen-i-1];
pbData[dwLen-i-1] = swap;
}
}
#endif
BOOL encrypt_block_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, CONST BYTE *in, BYTE *out,
DWORD enc)
{
#ifdef HAVE_OPENSSL_RSA_H
int cLen;
#endif
switch (aiAlgid) {
#ifdef HAVE_OPENSSL_RC2_H
case CALG_RC2:
if (!pRC2_ecb_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pRC2_ecb_encrypt(in, out, &pKeyContext->rc2, enc ? RC2_ENCRYPT : RC2_DECRYPT);
break;
#endif
#ifdef HAVE_OPENSSL_DES_H
case CALG_DES:
if (!pDES_ecb_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_ecb_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &pKeyContext->des[0],
enc ? DES_ENCRYPT : DES_DECRYPT);
break;
case CALG_3DES_112:
if (!pDES_ecb3_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out,
&pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[0],
enc ? DES_ENCRYPT : DES_DECRYPT);
break;
case CALG_3DES:
if (!pDES_ecb3_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out,
&pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[2],
enc ? DES_ENCRYPT : DES_DECRYPT);
break;
#endif
#ifdef HAVE_OPENSSL_RSA_H
case CALG_RSA_KEYX:
if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
cLen = pBN_num_bits(pKeyContext->rsa->n)/8;
if (enc) {
pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
reverse_bytes((BYTE*)in, cLen);
} else {
reverse_bytes((BYTE*)in, cLen);
pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
}
break;
case CALG_RSA_SIGN:
if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
cLen = pBN_num_bits(pKeyContext->rsa->n)/8;
if (enc) {
pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
reverse_bytes((BYTE*)in, cLen);
} else {
reverse_bytes((BYTE*)in, cLen);
pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
}
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *stream, DWORD dwLen)
{
switch (aiAlgid) {
#ifdef HAVE_OPENSSL_RC4_H
case CALG_RC4:
if (!pRC4)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pRC4(&pKeyContext->rc4, (unsigned long)dwLen, stream, stream);
break;
#endif
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
return TRUE;
}
BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen)
{
FILE *dev_random;
/* FIXME: /dev/urandom does not provide random numbers of a sufficient
* quality for cryptographic applications. /dev/random is much better,
* but it blocks if the kernel has not yet collected enough entropy for
* the request, which will suspend the calling thread for an indefinite
* amount of time. */
dev_random = fopen("/dev/urandom", "r");
if (dev_random)
{
if (fread(pbBuffer, (size_t)dwLen, 1, dev_random) == 1)
{
fclose(dev_random);
return TRUE;
}
fclose(dev_random);
}
SetLastError(NTE_FAIL);
return FALSE;
}
BOOL export_public_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,DWORD *pdwPubExp)
{
#ifdef HAVE_OPENSSL_RSA_H
if (!pBN_bn2bin || !pBN_get_word)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pBN_bn2bin(pKeyContext->rsa->n, pbDest);
reverse_bytes(pbDest, dwKeyLen);
*pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e);
return TRUE;
#else
SetLastError(NTE_FAIL);
return FALSE;
#endif
}
BOOL import_public_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD dwPubExp)
{
#ifdef HAVE_OPENSSL_RSA_H
BYTE *pbTemp;
if (!pBN_bin2bn || !pBN_set_word)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pbTemp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwKeyLen);
if (!pbTemp) return FALSE;
memcpy(pbTemp, pbSrc, dwKeyLen);
reverse_bytes(pbTemp, dwKeyLen);
pBN_bin2bn(pbTemp, dwKeyLen, pKeyContext->rsa->n);
HeapFree(GetProcessHeap(), 0, pbTemp);
pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp);
return TRUE;
#else
SetLastError(NTE_FAIL);
return FALSE;
#endif
}
BOOL export_private_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD *pdwPubExp)
{
#ifdef HAVE_OPENSSL_RSA_H
if (!pBN_bn2bin || !pBN_get_word)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pBN_bn2bin(pKeyContext->rsa->n, pbDest);
reverse_bytes(pbDest, dwKeyLen);
pbDest += dwKeyLen;
pBN_bn2bin(pKeyContext->rsa->p, pbDest);
reverse_bytes(pbDest, (dwKeyLen+1)>>1);
pbDest += (dwKeyLen+1)>>1;
pBN_bn2bin(pKeyContext->rsa->q, pbDest);
reverse_bytes(pbDest, (dwKeyLen+1)>>1);
pbDest += (dwKeyLen+1)>>1;
pBN_bn2bin(pKeyContext->rsa->dmp1, pbDest);
reverse_bytes(pbDest, (dwKeyLen+1)>>1);
pbDest += (dwKeyLen+1)>>1;
pBN_bn2bin(pKeyContext->rsa->dmq1, pbDest);
reverse_bytes(pbDest, (dwKeyLen+1)>>1);
pbDest += (dwKeyLen+1)>>1;
pBN_bn2bin(pKeyContext->rsa->iqmp, pbDest);
reverse_bytes(pbDest, (dwKeyLen+1)>>1);
pbDest += (dwKeyLen+1)>>1;
pBN_bn2bin(pKeyContext->rsa->d, pbDest);
reverse_bytes(pbDest, dwKeyLen);
*pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e);
return TRUE;
#else
SetLastError(NTE_FAIL);
return FALSE;
#endif
}
BOOL import_private_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD dwPubExp)
{
#ifdef HAVE_OPENSSL_RSA_H
BYTE *pbTemp, *pbBigNum;
if (!pBN_bin2bn || !pBN_set_word)
{
SetLastError(NTE_PROVIDER_DLL_FAIL);
return FALSE;
}
pbTemp = HeapAlloc(GetProcessHeap(), 0, 2*dwKeyLen+5*((dwKeyLen+1)>>1));
if (!pbTemp) return FALSE;
memcpy(pbTemp, pbSrc, 2*dwKeyLen+5*((dwKeyLen+1)>>1));
pbBigNum = pbTemp;
reverse_bytes(pbBigNum, dwKeyLen);
pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->n);
pbBigNum += dwKeyLen;
reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->p);
pbBigNum += (dwKeyLen+1)>>1;
reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->q);
pbBigNum += (dwKeyLen+1)>>1;
reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmp1);
pbBigNum += (dwKeyLen+1)>>1;
reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmq1);
pbBigNum += (dwKeyLen+1)>>1;
reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->iqmp);
pbBigNum += (dwKeyLen+1)>>1;
reverse_bytes(pbBigNum, dwKeyLen);
pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->d);
pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp);
HeapFree(GetProcessHeap(), 0, pbTemp);
return TRUE;
#else
SetLastError(NTE_FAIL);
return FALSE;
#endif
}

129
dlls/rsaenh/implossl.h Normal file
View File

@ -0,0 +1,129 @@
/*
* dlls/rsaenh/implossl.h
* Encapsulating the OpenSSL dependend parts of RSABASE
*
* Copyright (c) 2004 Michael Jung
*
* based on code by Mike McCormack and David Hammerton
*
* 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_IMPLOSSL_H
#define __WINE_IMPLOSSL_H
#ifdef HAVE_OPENSSL_MD2_H
#include <openssl/md2.h>
#endif
#ifdef HAVE_OPENSSL_RC2_H
#include <openssl/rc2.h>
#endif
#ifdef HAVE_OPENSSL_RC4_H
#include <openssl/rc4.h>
#endif
#ifdef HAVE_OPENSSL_DES_H
#include <openssl/des.h>
#endif
#ifdef HAVE_OPENSSL_RSA_H
#include <openssl/rsa.h>
#endif
/* Next typedef copied from dlls/advapi32/crypt_md4.c */
typedef struct tagMD4_CTX {
unsigned int buf[4];
unsigned int i[2];
unsigned char in[64];
unsigned char digest[16];
} MD4_CTX;
/* Next typedef copied from dlls/advapi32/crypt_md5.c */
typedef struct tagMD5_CTX
{
unsigned int i[2];
unsigned int buf[4];
unsigned char in[64];
unsigned char digest[16];
} MD5_CTX;
/* Next typedef copied form dlls/advapi32/crypt_sha.c */
typedef struct tagSHA_CTX
{
ULONG Unknown[6];
ULONG State[5];
ULONG Count[2];
UCHAR Buffer[64];
} SHA_CTX, *PSHA_CTX;
typedef union tagHASH_CONTEXT {
#ifdef HAVE_OPENSSL_MD2_H
MD2_CTX md2;
#endif
MD4_CTX md4;
MD5_CTX md5;
SHA_CTX sha;
} HASH_CONTEXT;
typedef union tagKEY_CONTEXT {
#ifdef HAVE_OPENSSL_RC2_H
RC2_KEY rc2;
#endif
#ifdef HAVE_OPENSSL_RC4_H
RC4_KEY rc4;
#endif
#ifdef HAVE_OPENSSL_DES_H
DES_key_schedule des[3];
#endif
#ifdef HAVE_OPENSSL_RSA_H
RSA *rsa;
#endif
DWORD dwDummy;
} KEY_CONTEXT;
BOOL load_lib(void);
BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext);
BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData,
DWORD dwDataLen);
BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue);
BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext,
HASH_CONTEXT *pDestHashContext);
BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen);
BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext);
BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen,
BYTE *abKeyValue);
BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext,
KEY_CONTEXT *pDestKeyContext);
BOOL encrypt_block_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, CONST BYTE *pbIn, BYTE *pbOut,
DWORD enc);
BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *pbInOut, DWORD dwLen);
BOOL export_public_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD *pdwPubExp);
BOOL import_public_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD dwPubExp);
BOOL export_private_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD *pdwPubExp);
BOOL import_private_key_impl(CONST BYTE* pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
DWORD dwPubExp);
BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen);
#endif /* __WINE_IMPLOSSL_H */

2658
dlls/rsaenh/rsaenh.c Normal file

File diff suppressed because it is too large Load Diff

27
dlls/rsaenh/rsaenh.spec Normal file
View File

@ -0,0 +1,27 @@
@ stdcall CPAcquireContext(ptr str long ptr) RSAENH_CPAcquireContext
@ stdcall CPCreateHash(long long ptr long ptr) RSAENH_CPCreateHash
@ stdcall CPDecrypt(long long long long long ptr ptr) RSAENH_CPDecrypt
@ stdcall CPDeriveKey(long long long long ptr) RSAENH_CPDeriveKey
@ stdcall CPDestroyHash(long long) RSAENH_CPDestroyHash
@ stdcall CPDestroyKey(long long) RSAENH_CPDestroyKey
@ stdcall CPDuplicateHash(long long ptr long ptr) RSAENH_CPDuplicateHash
@ stdcall CPDuplicateKey(long long ptr long ptr) RSAENH_CPDuplicateKey
@ stdcall CPEncrypt(long long long long long ptr ptr long) RSAENH_CPEncrypt
@ stdcall CPExportKey(long long long long long ptr ptr) RSAENH_CPExportKey
@ stdcall CPGenKey(long long long ptr) RSAENH_CPGenKey
@ stdcall CPGenRandom(long long ptr) RSAENH_CPGenRandom
@ stdcall CPGetHashParam(long long long ptr ptr long) RSAENH_CPGetHashParam
@ stdcall CPGetKeyParam(long long long ptr ptr long) RSAENH_CPGetKeyParam
@ stdcall CPGetProvParam(long long ptr ptr long) RSAENH_CPGetProvParam
@ stdcall CPGetUserKey(long long ptr) RSAENH_CPGetUserKey
@ stdcall CPHashData(long long ptr long long) RSAENH_CPHashData
@ stdcall CPHashSessionKey(long long long long) RSAENH_CPHashSessionKey
@ stdcall CPImportKey(long ptr long long long ptr) RSAENH_CPImportKey
@ stdcall CPReleaseContext(long long) RSAENH_CPReleaseContext
@ stdcall CPSetHashParam(long long long ptr long) RSAENH_CPSetHashParam
@ stdcall CPSetKeyParam(long long long ptr long) RSAENH_CPSetKeyParam
@ stdcall CPSetProvParam(long long ptr long) RSAENH_CPSetProvParam
@ stdcall CPSignHash(long long long wstr long ptr ptr) RSAENH_CPSignHash
@ stdcall CPVerifySignature(long long ptr long long wstr long) RSAENH_CPVerifySignature
@ stdcall -private DllRegisterServer() RSAENH_DllRegisterServer
@ stdcall -private DllUnregisterServer() RSAENH_DllUnregisterServer

View File

@ -0,0 +1,3 @@
Makefile
rsaenh.ok
testlist.c

View File

@ -0,0 +1,13 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
TESTDLL = rsaenh.dll
IMPORTS = advapi32 kernel32
CTESTS = \
rsaenh.c
@MAKE_TEST_RULES@
### Dependencies:

843
dlls/rsaenh/tests/rsaenh.c Normal file
View File

@ -0,0 +1,843 @@
/*
* Unit tests for rsaenh functions
*
* Copyright (c) 2004 Michael Jung
*
* 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 <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wincrypt.h"
static HCRYPTPROV hProv;
static const char szContainer[] = "winetest";
static const unsigned char pbData[] = "Wine rocks totally!";
static const char szProvider[] = MS_ENHANCED_PROV_A;
/*
static void trace_hex(BYTE *pbData, DWORD dwLen) {
char szTemp[256];
DWORD i, j;
for (i = 0; i < dwLen-7; i+=8) {
sprintf(szTemp, "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
pbData[i], pbData[i+1], pbData[i+2], pbData[i+3], pbData[i+4], pbData[i+5],
pbData[i+6], pbData[i+7]);
trace(szTemp);
}
for (j=0; i<dwLen; j++,i++) {
sprintf(szTemp+6*j, "0x%02x, \n", pbData[i]);
}
trace(szTemp);
}
*/
static int init_environment(void)
{
HCRYPTKEY hKey;
BOOL result;
hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
if (!CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, 0))
{
ok(GetLastError()==NTE_BAD_KEYSET, "%08lx\n", GetLastError());
if (GetLastError()!=NTE_BAD_KEYSET) return 0;
result = CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL,
CRYPT_NEWKEYSET);
ok(result, "%08lx\n", GetLastError());
if (!result) return 0;
result = CryptGenKey(hProv, AT_KEYEXCHANGE, 0, &hKey);
ok(result, "%08lx\n", GetLastError());
if (result) CryptDestroyKey(hKey);
result = CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey);
ok(result, "%08lx\n", GetLastError());
if (result) CryptDestroyKey(hKey);
}
return 1;
}
static void clean_up_environment(void)
{
CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
}
static void test_prov()
{
BOOL result;
DWORD dwLen, dwInc;
dwLen = (DWORD)sizeof(DWORD);
result = CryptGetProvParam(hProv, PP_SIG_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
ok(result && dwInc==8, "%08lx, %ld\n", GetLastError(), dwInc);
dwLen = (DWORD)sizeof(DWORD);
result = CryptGetProvParam(hProv, PP_KEYX_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
ok(result && dwInc==8, "%08lx, %ld\n", GetLastError(), dwInc);
}
static void test_gen_random()
{
BOOL result;
BYTE rnd1[16], rnd2[16];
memset(rnd1, 0, sizeof(rnd1));
memset(rnd2, 0, sizeof(rnd2));
result = CryptGenRandom(hProv, sizeof(rnd1), rnd1);
if (!result && GetLastError() == NTE_FAIL) {
/* rsaenh compiled without OpenSSL */
return;
}
ok(result, "%08lx\n", GetLastError());
result = CryptGenRandom(hProv, sizeof(rnd2), rnd2);
ok(result, "%08lx\n", GetLastError());
ok(memcmp(rnd1, rnd2, sizeof(rnd1)), "CryptGenRandom generates non random data\n");
}
static BOOL derive_key(ALG_ID aiAlgid, HCRYPTKEY *phKey, DWORD len)
{
HCRYPTHASH hHash;
BOOL result;
unsigned char pbData[2000];
int i;
*phKey = (HCRYPTKEY)NULL;
for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError()==NTE_BAD_ALGID, "%08lx", GetLastError());
return FALSE;
}
ok(result, "%08lx\n", GetLastError());
if (!result) return FALSE;
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
if (!result) return FALSE;
result = CryptDeriveKey(hProv, aiAlgid, hHash, (len << 16) | CRYPT_EXPORTABLE, phKey);
ok(result, "%08lx\n", GetLastError());
if (!result) return FALSE;
len = 2000;
result = CryptGetHashParam(hHash, HP_HASHVAL, pbData, &len, 0);
ok(result, "%08lx\n", GetLastError());
CryptDestroyHash(hHash);
return TRUE;
}
static void test_hashes(void)
{
static const unsigned char md2hash[16] = {
0x12, 0xcb, 0x1b, 0x08, 0xc8, 0x48, 0xa4, 0xa9,
0xaa, 0xf3, 0xf1, 0x9f, 0xfc, 0x29, 0x28, 0x68 };
static const unsigned char md4hash[16] = {
0x8e, 0x2a, 0x58, 0xbf, 0xf2, 0xf5, 0x26, 0x23,
0x79, 0xd2, 0x92, 0x36, 0x1b, 0x23, 0xe3, 0x81 };
static const unsigned char md5hash[16] = {
0x15, 0x76, 0xa9, 0x4d, 0x6c, 0xb3, 0x34, 0xdd,
0x12, 0x6c, 0xb1, 0xc2, 0x7f, 0x19, 0xe0, 0xf2 };
static const unsigned char sha1hash[20] = {
0xf1, 0x0c, 0xcf, 0xde, 0x60, 0xc1, 0x7d, 0xb2, 0x6e, 0x7d,
0x85, 0xd3, 0x56, 0x65, 0xc7, 0x66, 0x1d, 0xbb, 0xeb, 0x2c };
unsigned char pbData[2048];
BOOL result;
HCRYPTHASH hHash, hHashClone;
BYTE pbHashValue[36];
DWORD hashlen, len;
int i;
for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;
/* MD2 Hashing */
result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError() == NTE_BAD_ALGID, "%08lx\n", GetLastError());
} else {
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
len = sizeof(DWORD);
result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
ok(result && (hashlen == 16), "%08lx, hashlen: %ld\n", GetLastError(), hashlen);
len = 16;
result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbHashValue, md2hash, 16), "Wrong MD2 hash!\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
}
/* MD4 Hashing */
result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
len = sizeof(DWORD);
result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
ok(result && (hashlen == 16), "%08lx, hashlen: %ld\n", GetLastError(), hashlen);
len = 16;
result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbHashValue, md4hash, 16), "Wrong MD4 hash!\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
/* MD5 Hashing */
result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
len = sizeof(DWORD);
result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
ok(result && (hashlen == 16), "%08lx, hashlen: %ld\n", GetLastError(), hashlen);
len = 16;
result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbHashValue, md5hash, 16), "Wrong MD5 hash!\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
/* SHA1 Hashing */
result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, (BYTE*)pbData, 5, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptDuplicateHash(hHash, 0, 0, &hHashClone);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHashClone, (BYTE*)pbData+5, sizeof(pbData)-5, 0);
ok(result, "%08lx\n", GetLastError());
len = sizeof(DWORD);
result = CryptGetHashParam(hHashClone, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
ok(result && (hashlen == 20), "%08lx, hashlen: %ld\n", GetLastError(), hashlen);
len = 20;
result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbHashValue, sha1hash, 20), "Wrong SHA1 hash!\n");
result = CryptDestroyHash(hHashClone);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
}
static void test_block_cipher_modes()
{
static const BYTE plain[23] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
static const BYTE ecb[24] = {
0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0xf2, 0xb2, 0x5d, 0x5f,
0x08, 0xff, 0x49, 0xa4, 0x45, 0x3a, 0x68, 0x14, 0xca, 0x18, 0xe5, 0xf4 };
static const BYTE cbc[24] = {
0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0x10, 0xf5, 0xda, 0x61,
0x4e, 0x3d, 0xab, 0xc0, 0x97, 0x85, 0x01, 0x12, 0x97, 0xa4, 0xf7, 0xd3 };
static const BYTE cfb[24] = {
0x29, 0xb5, 0x67, 0x85, 0x0b, 0x1b, 0xec, 0x07, 0x67, 0x2d, 0xa1, 0xa4,
0x1a, 0x47, 0x24, 0x6a, 0x54, 0xe1, 0xe0, 0x92, 0xf9, 0x0e, 0xf6, 0xeb };
HCRYPTKEY hKey;
BOOL result;
BYTE abData[24];
DWORD dwMode, dwLen;
result = derive_key(CALG_RC2, &hKey, 40);
if (!result) return;
memcpy(abData, plain, sizeof(abData));
dwMode = CRYPT_MODE_ECB;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
SetLastError(ERROR_SUCCESS);
dwLen = 23;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData, &dwLen, 24);
ok(result && dwLen == 24 && !memcmp(ecb, abData, sizeof(ecb)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData, &dwLen);
ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwMode = CRYPT_MODE_CBC;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = 23;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData, &dwLen, 24);
ok(result && dwLen == 24 && !memcmp(cbc, abData, sizeof(cbc)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData, &dwLen);
ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwMode = CRYPT_MODE_CFB;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = 16;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, FALSE, 0, abData, &dwLen, 24);
ok(result && dwLen == 16, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwLen = 7;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData+16, &dwLen, 8);
ok(result && dwLen == 8 && !memcmp(cfb, abData, sizeof(cfb)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwLen = 8;
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, FALSE, 0, abData, &dwLen);
ok(result && dwLen == 8, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwLen = 16;
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData+8, &dwLen);
ok(result && dwLen == 15 && !memcmp(plain, abData, sizeof(plain)),
"%08lx, dwLen: %ld\n", GetLastError(), dwLen);
dwMode = CRYPT_MODE_OFB;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = 23;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abData, &dwLen, 24);
ok(!result && GetLastError() == NTE_BAD_ALGID, "%08lx\n", GetLastError());
}
static void test_3des112()
{
HCRYPTKEY hKey;
BOOL result;
DWORD dwLen;
unsigned char pbData[16];
int i;
result = derive_key(CALG_3DES_112, &hKey, 0);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError() == NTE_BAD_ALGID, "%08lx\n", GetLastError());
return;
}
for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
dwLen = 13;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen, 16);
ok(result, "%08lx\n", GetLastError());
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
static void test_des()
{
HCRYPTKEY hKey;
BOOL result;
DWORD dwLen, dwMode;
unsigned char pbData[16];
int i;
result = derive_key(CALG_DES, &hKey, 56);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError()==NTE_BAD_ALGID, "%08lx\n", GetLastError());
return;
}
dwMode = CRYPT_MODE_ECB;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
dwLen = 13;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen, 16);
ok(result, "%08lx\n", GetLastError());
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
static void test_3des()
{
HCRYPTKEY hKey;
BOOL result;
DWORD dwLen;
unsigned char pbData[16];
static const BYTE des3[16] = {
0x7b, 0xba, 0xdd, 0xa2, 0x39, 0xd3, 0x7b, 0xb3,
0xc7, 0x51, 0x81, 0x41, 0x53, 0xe8, 0xcf, 0xeb };
int i;
result = derive_key(CALG_3DES, &hKey, 0);
if (!result) return;
for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
dwLen = 13;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen, 16);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbData, des3, sizeof(des3)), "3DES encryption failed!\n");
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwLen);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
static void test_rc2()
{
static const BYTE rc2encrypted[16] = {
0x02, 0x34, 0x7d, 0xf6, 0x1d, 0xc5, 0x9b, 0x8b,
0x2e, 0x0d, 0x63, 0x80, 0x72, 0xc1, 0xc2, 0xb1 };
HCRYPTHASH hHash;
HCRYPTKEY hKey;
BOOL result;
DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits;
BYTE *pbTemp;
unsigned char pbData[2000], pbHashValue[16];
int i;
for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
/* MD2 Hashing */
result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
if (!result) {
ok(GetLastError()==NTE_BAD_ALGID, "%08lx\n", GetLastError());
} else {
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
dwLen = 16;
result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptDeriveKey(hProv, CALG_RC2, hHash, 56 << 16, &hKey);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
dwMode = CRYPT_MODE_CBC;
result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_MODE_BITS, (BYTE*)&dwModeBits, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwModeBits, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
HeapFree(GetProcessHeap(), 0, pbTemp);
result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
HeapFree(GetProcessHeap(), 0, pbTemp);
dwLen = sizeof(DWORD);
CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
dwDataLen = 13;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen, 24);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbData, rc2encrypted, 8), "RC2 encryption failed!\n");
result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
HeapFree(GetProcessHeap(), 0, pbTemp);
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
}
static void test_rc4()
{
static const BYTE rc4[16] = {
0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0,
0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };
BOOL result;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD dwDataLen = 5, dwKeyLen, dwLen = sizeof(DWORD), dwMode;
unsigned char pbData[2000], *pbTemp;
unsigned char pszBuffer[256];
int i;
for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
/* MD2 Hashing */
result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError() == NTE_BAD_ALGID, "%08lx\n", GetLastError());
} else {
result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
ok(result, "%08lx\n", GetLastError());
dwLen = 16;
result = CryptGetHashParam(hHash, HP_HASHVAL, pszBuffer, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptDeriveKey(hProv, CALG_RC4, hHash, 56 << 16, &hKey);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(DWORD);
result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
HeapFree(GetProcessHeap(), 0, pbTemp);
result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
HeapFree(GetProcessHeap(), 0, pbTemp);
dwLen = sizeof(DWORD);
CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
dwDataLen = 16;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen, 24);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(pbData, rc4, dwDataLen), "RC4 encryption failed!\n");
result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
}
static void test_hmac() {
HCRYPTKEY hKey;
HCRYPTHASH hHash;
BOOL result;
HMAC_INFO hmacInfo = { CALG_MD2, NULL, 0, NULL, 0 };
DWORD dwLen;
BYTE abData[256];
static const BYTE hmac[16] = {
0xfd, 0x16, 0xb5, 0xb6, 0x13, 0x1c, 0x2b, 0xd6,
0x0a, 0xc7, 0xae, 0x92, 0x76, 0xa3, 0x05, 0x71 };
int i;
for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
if (!derive_key(CALG_RC2, &hKey, 56)) return;
result = CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
if (!result) return;
result = CryptSetHashParam(hHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, (BYTE*)abData, sizeof(abData), 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(abData)/sizeof(BYTE);
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
ok(result, "%08lx\n", GetLastError());
ok(!memcmp(abData, hmac, sizeof(hmac)), "HMAC failed!\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
/* Provoke errors */
result = CryptCreateHash(hProv, CALG_HMAC, 0, 0, &hHash);
ok(!result && GetLastError() == NTE_BAD_KEY, "%08lx\n", GetLastError());
}
static void test_mac() {
HCRYPTKEY hKey;
HCRYPTHASH hHash;
BOOL result;
DWORD dwLen;
BYTE abData[256], abEnc[264];
static const BYTE mac[8] = { 0x0d, 0x3e, 0x15, 0x6b, 0x85, 0x63, 0x5c, 0x11 };
int i;
for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abEnc[i] = (BYTE)i;
if (!derive_key(CALG_RC2, &hKey, 56)) return;
dwLen = 256;
result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, abEnc, &dwLen, 264);
ok (result && dwLen == 264, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
if (!result) return;
result = CryptHashData(hHash, (BYTE*)abData, sizeof(abData), 0);
ok(result, "%08lx\n", GetLastError());
dwLen = sizeof(abData)/sizeof(BYTE);
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
ok(result && dwLen == 8, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
ok(!memcmp(abData, mac, sizeof(mac)), "MAC failed!\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
/* Provoke errors */
if (!derive_key(CALG_RC4, &hKey, 56)) return;
result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
ok(!result && GetLastError() == NTE_BAD_KEY, "%08lx\n", GetLastError());
result = CryptDestroyKey(hKey);
ok(result, "%08lx\n", GetLastError());
}
static void test_import_private()
{
DWORD dwLen;
HCRYPTKEY hKeyExchangeKey, hSessionKey;
BOOL result;
BYTE abPlainPrivateKey[596] = {
0x07, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0x9b, 0x64, 0xef, 0xce,
0x31, 0x7c, 0xad, 0x56, 0xe2, 0x1e, 0x9b, 0x96,
0xb3, 0xf0, 0x29, 0x88, 0x6e, 0xa8, 0xc2, 0x11,
0x33, 0xd6, 0xcc, 0x8c, 0x69, 0xb2, 0x1a, 0xfd,
0xfc, 0x23, 0x21, 0x30, 0x4d, 0x29, 0x45, 0xb6,
0x3a, 0x67, 0x11, 0x80, 0x1a, 0x91, 0xf2, 0x9f,
0x01, 0xac, 0xc0, 0x11, 0x50, 0x5f, 0xcd, 0xb9,
0xad, 0x76, 0x9f, 0x6e, 0x91, 0x55, 0x71, 0xda,
0x97, 0x96, 0x96, 0x22, 0x75, 0xb4, 0x83, 0x44,
0x89, 0x9e, 0xf8, 0x44, 0x40, 0x7c, 0xd6, 0xcd,
0x9d, 0x88, 0xd6, 0x88, 0xbc, 0x56, 0xb7, 0x64,
0xe9, 0x2c, 0x24, 0x2f, 0x0d, 0x78, 0x55, 0x1c,
0xb2, 0x67, 0xb1, 0x5e, 0xbc, 0x0c, 0xcf, 0x1c,
0xe9, 0xd3, 0x9e, 0xa2, 0x15, 0x24, 0x73, 0xd6,
0xdb, 0x6f, 0x83, 0xb2, 0xf8, 0xbc, 0xe7, 0x47,
0x3b, 0x01, 0xef, 0x49, 0x08, 0x98, 0xd6, 0xa3,
0xf9, 0x25, 0x57, 0xe9, 0x39, 0x3c, 0x53, 0x30,
0x1b, 0xf2, 0xc9, 0x62, 0x31, 0x43, 0x5d, 0x84,
0x24, 0x30, 0x21, 0x9a, 0xad, 0xdb, 0x62, 0x91,
0xc8, 0x07, 0xd9, 0x2f, 0xd6, 0xb5, 0x37, 0x6f,
0xfe, 0x7a, 0x12, 0xbc, 0xd9, 0xd2, 0x2b, 0xbf,
0xd7, 0xb1, 0xfa, 0x7d, 0xc0, 0x48, 0xdd, 0x74,
0xdd, 0x55, 0x04, 0xa1, 0x8b, 0xc1, 0x0a, 0xc4,
0xa5, 0x57, 0x62, 0xee, 0x08, 0x8b, 0xf9, 0x19,
0x6c, 0x52, 0x06, 0xf8, 0x73, 0x0f, 0x24, 0xc9,
0x71, 0x9f, 0xc5, 0x45, 0x17, 0x3e, 0xae, 0x06,
0x81, 0xa2, 0x96, 0x40, 0x06, 0xbf, 0xeb, 0x9e,
0x80, 0x2b, 0x27, 0x20, 0x8f, 0x38, 0xcf, 0xeb,
0xff, 0x3b, 0x38, 0x41, 0x35, 0x69, 0x66, 0x13,
0x1d, 0x3c, 0x01, 0x3b, 0xf6, 0x37, 0xca, 0x9c,
0x61, 0x74, 0x98, 0xcf, 0xc9, 0x6e, 0xe8, 0x90,
0xc7, 0xb7, 0x33, 0xc0, 0x07, 0x3c, 0xf8, 0xc8,
0xf6, 0xf2, 0xd7, 0xf0, 0x21, 0x62, 0x58, 0x8a,
0x55, 0xbf, 0xa1, 0x2d, 0x3d, 0xa6, 0x69, 0xc5,
0x02, 0x19, 0x31, 0xf0, 0x94, 0x0f, 0x45, 0x5c,
0x95, 0x1b, 0x53, 0xbc, 0xf5, 0xb0, 0x1a, 0x8f,
0xbf, 0x40, 0xe0, 0xc7, 0x73, 0xe7, 0x72, 0x6e,
0xeb, 0xb1, 0x0f, 0x38, 0xc5, 0xf8, 0xee, 0x04,
0xed, 0x34, 0x1a, 0x10, 0xf9, 0x53, 0x34, 0xf3,
0x3e, 0xe6, 0x5c, 0xd1, 0x47, 0x65, 0xcd, 0xbd,
0xf1, 0x06, 0xcb, 0xb4, 0xb1, 0x26, 0x39, 0x9f,
0x71, 0xfe, 0x3d, 0xf8, 0x62, 0xab, 0x22, 0x8b,
0x0e, 0xdc, 0xb9, 0xe8, 0x74, 0x06, 0xfc, 0x8c,
0x25, 0xa1, 0xa9, 0xcf, 0x07, 0xf9, 0xac, 0x21,
0x01, 0x7b, 0x1c, 0xdc, 0x94, 0xbd, 0x47, 0xe1,
0xa0, 0x86, 0x59, 0x35, 0x6a, 0x6f, 0xb9, 0x70,
0x26, 0x7c, 0x3c, 0xfd, 0xbd, 0x81, 0x39, 0x36,
0x42, 0xc2, 0xbd, 0xbe, 0x84, 0x27, 0x9a, 0x69,
0x81, 0xda, 0x99, 0x27, 0xc2, 0x4f, 0x62, 0x33,
0xf4, 0x79, 0x30, 0xc5, 0x63, 0x54, 0x71, 0xf1,
0x47, 0x22, 0x25, 0x9b, 0x6c, 0x00, 0x2f, 0x1c,
0xf4, 0x1f, 0x85, 0xbc, 0xf6, 0x67, 0x6a, 0xe3,
0xf6, 0x55, 0x8a, 0xef, 0xd0, 0x0b, 0xd3, 0xa2,
0xc5, 0x51, 0x70, 0x15, 0x0a, 0xf0, 0x98, 0x4c,
0xb7, 0x19, 0x62, 0x0e, 0x2d, 0x2a, 0x4a, 0x7d,
0x7a, 0x0a, 0xc4, 0x17, 0xe3, 0x5d, 0x20, 0x52,
0xa9, 0x98, 0xc3, 0xaa, 0x11, 0xf6, 0xbf, 0x4c,
0x94, 0x99, 0x81, 0x89, 0xf0, 0x7f, 0x66, 0xaa,
0xc8, 0x88, 0xd7, 0x31, 0x84, 0x71, 0xb6, 0x64,
0x09, 0x76, 0x0b, 0x7f, 0x1a, 0x1f, 0x2e, 0xfe,
0xcd, 0x59, 0x2a, 0x54, 0x11, 0x84, 0xd4, 0x6a,
0x61, 0xdf, 0xaa, 0x76, 0x66, 0x9d, 0x82, 0x11,
0x56, 0x3d, 0xd2, 0x52, 0xe6, 0x42, 0x5a, 0x77,
0x92, 0x98, 0x34, 0xf3, 0x56, 0x6c, 0x96, 0x10,
0x40, 0x59, 0x16, 0xcb, 0x77, 0x61, 0xe3, 0xbf,
0x4b, 0xd4, 0x39, 0xfb, 0xb1, 0x4e, 0xc1, 0x74,
0xec, 0x7a, 0xea, 0x3d, 0x68, 0xbb, 0x0b, 0xe6,
0xc6, 0x06, 0xbf, 0xdd, 0x7f, 0x94, 0x42, 0xc0,
0x0f, 0xe4, 0x92, 0x33, 0x6c, 0x6e, 0x1b, 0xba,
0x73, 0xf9, 0x79, 0x84, 0xdf, 0x45, 0x00, 0xe4,
0x94, 0x88, 0x9d, 0x08, 0x89, 0xcf, 0xf2, 0xa4,
0xc5, 0x47, 0x45, 0x85, 0x86, 0xa5, 0xcc, 0xa8,
0xf2, 0x5d, 0x58, 0x07
};
BYTE abSessionKey[148] = {
0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
0x04, 0x8c, 0x49, 0x92
};
BYTE abEncryptedMessage[12] = {
0x40, 0x64, 0x28, 0xe8, 0x8a, 0xe7, 0xa4, 0xd4,
0x1c, 0xfd, 0xde, 0x71
};
dwLen = (DWORD)sizeof(abPlainPrivateKey);
result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
if (!result) {
/* rsaenh compiled without OpenSSL */
ok(GetLastError() == NTE_FAIL, "%08lx\n", GetLastError());
return;
}
dwLen = (DWORD)sizeof(abSessionKey);
result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
ok(result, "%08lx\n", GetLastError());
if (!result) return;
dwLen = (DWORD)sizeof(abEncryptedMessage);
result = CryptDecrypt(hSessionKey, 0, TRUE, 0, abEncryptedMessage, &dwLen);
ok(result && dwLen == 12 && !strcmp(abEncryptedMessage, "Wine rocks!"),
"%08lx, len: %ld\n", GetLastError(), dwLen);
if (!derive_key(CALG_RC4, &hSessionKey, 56)) return;
dwLen = (DWORD)sizeof(abSessionKey);
result = CryptExportKey(hSessionKey, hKeyExchangeKey, SIMPLEBLOB, 0, abSessionKey, &dwLen);
ok(result, "%08lx\n", GetLastError());
if (!result) return;
dwLen = (DWORD)sizeof(abSessionKey);
result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
ok(result, "%08lx\n", GetLastError());
if (!result) return;
}
START_TEST(rsaenh)
{
if (!init_environment())
return;
test_prov();
test_gen_random();
test_hashes();
test_rc4();
test_rc2();
test_des();
test_3des112();
test_3des();
test_hmac();
test_mac();
test_block_cipher_modes();
test_import_private();
clean_up_environment();
}

View File

@ -431,6 +431,21 @@
/* Define if OpenGL is present on the system */
#undef HAVE_OPENGL
/* Define to 1 if you have the <openssl/des.h> header file. */
#undef HAVE_OPENSSL_DES_H
/* Define to 1 if you have the <openssl/md2.h> header file. */
#undef HAVE_OPENSSL_MD2_H
/* Define to 1 if you have the <openssl/rc2.h> header file. */
#undef HAVE_OPENSSL_RC2_H
/* Define to 1 if you have the <openssl/rc4.h> header file. */
#undef HAVE_OPENSSL_RC4_H
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#undef HAVE_OPENSSL_RSA_H
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#undef HAVE_OPENSSL_SSL_H

View File

@ -2005,7 +2005,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
11,,ole32.dll,1
11,,oleaut32.dll,1
11,,quartz.dll,1
11,,rsabase.dll,1
11,,rsaenh.dll,1
11,,shdocvw.dll,1
11,,shell32.dll,1
11,,urlmon.dll,1