From 1740d793d8556680245a1b34a54b7054b101266c Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 20 Dec 2016 22:36:51 +0100 Subject: [PATCH] Added patchset with various BCrypt improvements. --- .../0001-bcrypt-Add-AES-provider.patch | 573 +++++++++++++++ ...-Directly-implement-hmac-computation.patch | 469 ++++++++++++ ...nal-fallback-implementation-for-hash.patch | 673 ++++++++++++++++++ ...fallback-implementation-as-default-a.patch | 216 ++++++ ...bcrypt-Implement-BCryptDuplicateHash.patch | 56 ++ patches/bcrypt-Improvements/definition | 2 + patches/patchinstall.sh | 29 + 7 files changed, 2018 insertions(+) create mode 100644 patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch create mode 100644 patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch create mode 100644 patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch create mode 100644 patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch create mode 100644 patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch create mode 100644 patches/bcrypt-Improvements/definition diff --git a/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch b/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch new file mode 100644 index 00000000..8a55efac --- /dev/null +++ b/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch @@ -0,0 +1,573 @@ +From b6efa0b8bb1bba73863ca985c13d46a5eaec4198 Mon Sep 17 00:00:00 2001 +From: Hans Leidekker +Date: Mon, 19 Dec 2016 19:38:52 +0100 +Subject: bcrypt: Add AES provider. + +--- + dlls/bcrypt/bcrypt.spec | 10 +- + dlls/bcrypt/bcrypt_main.c | 347 ++++++++++++++++++++++++++++++++++++++++++++- + dlls/bcrypt/tests/bcrypt.c | 18 +-- + include/bcrypt.h | 3 + + 4 files changed, 352 insertions(+), 26 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec +index e299fe0..962953e 100644 +--- a/dlls/bcrypt/bcrypt.spec ++++ b/dlls/bcrypt/bcrypt.spec +@@ -5,15 +5,15 @@ + @ stub BCryptConfigureContextFunction + @ stub BCryptCreateContext + @ stdcall BCryptCreateHash(ptr ptr ptr long ptr long long) +-@ stub BCryptDecrypt ++@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long) + @ stub BCryptDeleteContext + @ stub BCryptDeriveKey + @ stdcall BCryptDestroyHash(ptr) +-@ stub BCryptDestroyKey ++@ stdcall BCryptDestroyKey(ptr) + @ stub BCryptDestroySecret + @ stub BCryptDuplicateHash + @ stub BCryptDuplicateKey +-@ stub BCryptEncrypt ++@ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) + @ stdcall BCryptEnumAlgorithms(long ptr ptr long) + @ stub BCryptEnumContextFunctionProviders + @ stub BCryptEnumContextFunctions +@@ -26,7 +26,7 @@ + @ stub BCryptFreeBuffer + @ stdcall BCryptGenRandom(ptr ptr long long) + @ stub BCryptGenerateKeyPair +-@ stub BCryptGenerateSymmetricKey ++@ stdcall BCryptGenerateSymmetricKey(ptr ptr ptr long ptr long long) + @ stdcall BCryptGetFipsAlgorithmMode(ptr) + @ stdcall BCryptGetProperty(ptr wstr ptr long ptr long) + @ stdcall BCryptHash(ptr ptr long ptr long ptr long) +@@ -46,7 +46,7 @@ + @ stub BCryptSecretAgreement + @ stub BCryptSetAuditingInterface + @ stub BCryptSetContextFunctionProperty +-@ stub BCryptSetProperty ++@ stdcall BCryptSetProperty(ptr wstr ptr long long) + @ stub BCryptSignHash + @ stub BCryptUnregisterConfigChangeNotify + @ stub BCryptUnregisterProvider +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 6023c94..937bdf7 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -49,6 +49,10 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); + + static void *libgnutls_handle; + #define MAKE_FUNCPTR(f) static typeof(f) * p##f ++MAKE_FUNCPTR(gnutls_cipher_init); ++MAKE_FUNCPTR(gnutls_cipher_deinit); ++MAKE_FUNCPTR(gnutls_cipher_encrypt2); ++MAKE_FUNCPTR(gnutls_cipher_decrypt2); + MAKE_FUNCPTR(gnutls_global_deinit); + MAKE_FUNCPTR(gnutls_global_init); + MAKE_FUNCPTR(gnutls_global_set_log_function); +@@ -84,6 +88,10 @@ static BOOL gnutls_initialize(void) + goto fail; \ + } + ++ LOAD_FUNCPTR(gnutls_cipher_init) ++ LOAD_FUNCPTR(gnutls_cipher_deinit) ++ LOAD_FUNCPTR(gnutls_cipher_encrypt2) ++ LOAD_FUNCPTR(gnutls_cipher_decrypt2) + LOAD_FUNCPTR(gnutls_global_deinit) + LOAD_FUNCPTR(gnutls_global_init) + LOAD_FUNCPTR(gnutls_global_set_log_function) +@@ -138,6 +146,7 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount, + + #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0') + #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H') ++#define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0') + struct object + { + ULONG magic; +@@ -145,6 +154,7 @@ struct object + + enum alg_id + { ++ ALG_ID_AES, + ALG_ID_MD5, + ALG_ID_RNG, + ALG_ID_SHA1, +@@ -157,6 +167,7 @@ static const struct { + ULONG hash_length; + const WCHAR *alg_name; + } alg_props[] = { ++ /* ALG_ID_AES */ { 0, BCRYPT_AES_ALGORITHM }, + /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM }, + /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM }, + /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM }, +@@ -215,11 +226,10 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c + + NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags ) + { ++ const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG; + struct algorithm *alg; + enum alg_id alg_id; + +- const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG; +- + TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags ); + + if (!handle || !id) return STATUS_INVALID_PARAMETER; +@@ -229,9 +239,10 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR + return STATUS_NOT_IMPLEMENTED; + } + +- if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1; ++ if (!strcmpW( id, BCRYPT_AES_ALGORITHM )) alg_id = ALG_ID_AES; + else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5; + else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG; ++ else if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1; + else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; + else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; + else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512; +@@ -430,7 +441,6 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) + static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) + { + CCHmacFinal( &hash->u.hmac_ctx, output ); +- + return STATUS_SUCCESS; + } + #elif defined(HAVE_GNUTLS_HASH) +@@ -586,12 +596,19 @@ static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) + } + #endif + ++#ifdef _WIN64 ++#define OBJECT_LENGTH_AES 654 ++#else ++#define OBJECT_LENGTH_AES 618 ++#endif + #define OBJECT_LENGTH_MD5 274 + #define OBJECT_LENGTH_SHA1 278 + #define OBJECT_LENGTH_SHA256 286 + #define OBJECT_LENGTH_SHA384 382 + #define OBJECT_LENGTH_SHA512 382 + ++#define BLOCK_LENGTH_AES 16 ++ + static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) + { + if (!strcmpW( prop, BCRYPT_HASH_LENGTH )) +@@ -628,6 +645,34 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, + + switch (id) + { ++ case ALG_ID_AES: ++ if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH )) ++ { ++ value = BLOCK_LENGTH_AES; ++ break; ++ } ++ if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) ++ { ++ value = OBJECT_LENGTH_AES; ++ break; ++ } ++ if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) ++ { ++ if (size >= sizeof(BCRYPT_CHAIN_MODE_CBC)) ++ { ++ memcpy(buf, BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC)); ++ *ret_size = sizeof(BCRYPT_CHAIN_MODE_CBC) * sizeof(WCHAR); ++ return STATUS_SUCCESS; ++ } ++ else ++ { ++ *ret_size = sizeof(BCRYPT_CHAIN_MODE_CBC) * sizeof(WCHAR); ++ return STATUS_BUFFER_TOO_SMALL; ++ } ++ } ++ FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); ++ return STATUS_NOT_IMPLEMENTED; ++ + case ALG_ID_MD5: + if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) + { +@@ -731,6 +776,13 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu + } + } + ++NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ++ ULONG size, ULONG flags ) ++{ ++ FIXME( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, + UCHAR *secret, ULONG secretlen, ULONG flags ) + { +@@ -854,6 +906,293 @@ NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG se + return BCryptDestroyHash( handle ); + } + ++#if defined(HAVE_GNUTLS_HASH) ++struct key ++{ ++ struct object hdr; ++ enum alg_id alg_id; ++ ULONG block_size; ++ gnutls_cipher_hd_t handle; ++ UCHAR *secret; ++ ULONG secret_len; ++}; ++ ++static ULONG get_block_size( enum alg_id alg ) ++{ ++ ULONG ret = 0, size = sizeof(ret); ++ get_alg_property( alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&ret, sizeof(ret), &size ); ++ return ret; ++} ++ ++static NTSTATUS key_init( struct key *key, enum alg_id id, UCHAR *secret, ULONG secret_len ) ++{ ++ if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; ++ ++ switch (id) ++ { ++ case ALG_ID_AES: ++ break; ++ ++ default: ++ FIXME( "algorithm %u not supported\n", id ); ++ return STATUS_NOT_SUPPORTED; ++ } ++ ++ if (!(key->block_size = get_block_size( id ))) return STATUS_INVALID_PARAMETER; ++ ++ key->alg_id = id; ++ key->handle = 0; /* initialized on first use */ ++ key->secret = secret; ++ key->secret_len = secret_len; ++ ++ return STATUS_SUCCESS; ++} ++ ++static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) ++{ ++ switch (key->alg_id) ++ { ++ case ALG_ID_AES: ++ FIXME( "handle block size and chaining mode\n" ); ++ return GNUTLS_CIPHER_AES_128_CBC; ++ ++ default: ++ FIXME( "algorithm %u not supported\n", key->alg_id ); ++ return GNUTLS_CIPHER_UNKNOWN; ++ } ++} ++ ++static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) ++{ ++ gnutls_cipher_algorithm_t cipher; ++ gnutls_datum_t secret, vector; ++ int ret; ++ ++ if (key->handle) ++ { ++ pgnutls_cipher_deinit( key->handle ); ++ key->handle = NULL; ++ } ++ ++ if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) ++ return STATUS_NOT_SUPPORTED; ++ ++ secret.data = key->secret; ++ secret.size = key->secret_len; ++ if (iv) ++ { ++ vector.data = iv; ++ vector.size = iv_len; ++ } ++ ++ if ((ret = pgnutls_cipher_init( &key->handle, cipher, &secret, iv ? &vector : NULL ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ++ ULONG output_len ) ++{ ++ int ret; ++ ++ if ((ret = pgnutls_cipher_encrypt2( key->handle, input, input_len, output, output_len ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ++ ULONG output_len ) ++{ ++ int ret; ++ ++ if ((ret = pgnutls_cipher_decrypt2( key->handle, input, input_len, output, output_len ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++static NTSTATUS key_destroy( struct key *key ) ++{ ++ if (key->handle) pgnutls_cipher_deinit( key->handle ); ++ HeapFree( GetProcessHeap(), 0, key->secret ); ++ HeapFree( GetProcessHeap(), 0, key ); ++ return STATUS_SUCCESS; ++} ++#else ++struct key ++{ ++ struct object hdr; ++ ULONG block_size; ++}; ++ ++static NTSTATUS key_init( struct key *key, enum alg_id id, const UCHAR *secret, ULONG secret_len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ ++static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ ++static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ++ ULONG output_len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ ++static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ++ ULONG output_len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ ++static NTSTATUS key_destroy( struct key *key ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++#endif ++ ++NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ++ UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len, ++ ULONG flags ) ++{ ++ struct algorithm *alg = algorithm; ++ struct key *key; ++ NTSTATUS status; ++ ++ TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", alg, handle, object, object_len, secret, secret_len, flags ); ++ ++ if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; ++ if (object) FIXME( "ignoring object buffer\n" ); ++ ++ if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) return STATUS_NO_MEMORY; ++ key->hdr.magic = MAGIC_KEY; ++ ++ if ((status = key_init( key, alg->id, secret, secret_len ))) ++ { ++ HeapFree( GetProcessHeap(), 0, key ); ++ return status; ++ } ++ ++ *handle = key; ++ return STATUS_SUCCESS; ++} ++ ++NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle ) ++{ ++ struct key *key = handle; ++ ++ TRACE( "%p\n", handle ); ++ ++ if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; ++ return key_destroy( key ); ++} ++ ++NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, ++ void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output, ++ ULONG output_len, ULONG *ret_len, ULONG flags ) ++{ ++ struct key *key = handle; ++ ULONG bytes_left = input_len; ++ UCHAR *buf, *src, *dst; ++ NTSTATUS status; ++ ++ TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, ++ padding, iv, iv_len, output, output_len, ret_len, flags ); ++ ++ if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; ++ if (padding) ++ { ++ FIXME( "padding info not implemented\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ if (flags & ~BCRYPT_BLOCK_PADDING) ++ { ++ FIXME( "flags %08x not implemented\n", flags ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ ++ if ((status = key_set_params( key, iv, iv_len ))) return status; ++ ++ *ret_len = input_len; ++ if (input_len & (key->block_size - 1)) ++ { ++ if (!(flags & BCRYPT_BLOCK_PADDING)) return STATUS_INVALID_BUFFER_SIZE; ++ *ret_len = (input_len + key->block_size - 1) & ~(key->block_size - 1); ++ } ++ if (!output) return STATUS_SUCCESS; ++ if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; ++ ++ src = input; ++ dst = output; ++ while (bytes_left >= key->block_size) ++ { ++ if ((status = key_encrypt( key, src, key->block_size, dst, key->block_size ))) return status; ++ bytes_left -= key->block_size; ++ src += key->block_size; ++ dst += key->block_size; ++ } ++ if (bytes_left) ++ { ++ if (!(buf = HeapAlloc( GetProcessHeap(), 0, key->block_size ))) return STATUS_NO_MEMORY; ++ memcpy( buf, src, bytes_left ); ++ memset( buf + bytes_left, key->block_size - bytes_left, key->block_size - bytes_left ); ++ status = key_encrypt( key, buf, key->block_size, dst, key->block_size ); ++ HeapFree( GetProcessHeap(), 0, buf ); ++ } ++ ++ return status; ++} ++ ++NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, ++ void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output, ++ ULONG output_len, ULONG *ret_len, ULONG flags ) ++{ ++ struct key *key = handle; ++ NTSTATUS status; ++ ++ FIXME( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, ++ padding, iv, iv_len, output, output_len, ret_len, flags ); ++ ++ if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; ++ if (padding) ++ { ++ FIXME( "padding info not implemented\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ if (flags & ~BCRYPT_BLOCK_PADDING) ++ { ++ FIXME( "flags %08x not supported\n", flags ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ ++ if ((status = key_set_params( key, iv, iv_len ))) return status; ++ ++ *ret_len = input_len; ++ if (input_len & (key->block_size - 1)) return STATUS_INVALID_BUFFER_SIZE; ++ if (!output) return STATUS_SUCCESS; ++ if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; ++ ++ return key_decrypt( key, input, input_len, output, output_len ); ++} ++ + BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) + { + switch (reason) +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 3e41335..2668153 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -780,7 +780,7 @@ static void test_aes(void) + ULONG size, len; + UCHAR mode[64]; + NTSTATUS ret; +-todo_wine { ++ + alg = NULL; + ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +@@ -828,7 +828,6 @@ todo_wine { + ret = pBCryptCloseAlgorithmProvider(alg, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + } +-} + + static void test_BCryptGenerateSymmetricKey(void) + { +@@ -847,11 +846,6 @@ static void test_BCryptGenerateSymmetricKey(void) + NTSTATUS ret; + + ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); +- if (ret != STATUS_SUCCESS) /* remove whole IF when Wine is fixed */ +- { +- todo_wine ok(0, "AES provider not available\n"); +- return; +- } + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + len = size = 0xdeadbeef; +@@ -936,11 +930,6 @@ static void test_BCryptEncrypt(void) + NTSTATUS ret; + + ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); +- if (ret != STATUS_SUCCESS) /* remove whole IF when Wine is fixed */ +- { +- todo_wine ok(0, "AES provider not available\n"); +- return; +- } + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + len = 0xdeadbeef; +@@ -1027,11 +1016,6 @@ static void test_BCryptDecrypt(void) + NTSTATUS ret; + + ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); +- if (ret != STATUS_SUCCESS) /* remove whole IF when Wine is fixed */ +- { +- todo_wine ok(0, "AES provider not available\n"); +- return; +- } + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + len = 0xdeadbeef; +diff --git a/include/bcrypt.h b/include/bcrypt.h +index 05d0691..6af85e3 100644 +--- a/include/bcrypt.h ++++ b/include/bcrypt.h +@@ -74,6 +74,9 @@ typedef LONG NTSTATUS; + #define BCRYPT_CHAIN_MODE_NA (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','N','/','A',0} + #define BCRYPT_CHAIN_MODE_CBC (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','C','B','C',0} + #define BCRYPT_CHAIN_MODE_ECB (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','E','C','B',0} ++#define BCRYPT_CHAIN_MODE_CFB (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','C','F','B',0} ++#define BCRYPT_CHAIN_MODE_CCM (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','C','C','M',0} ++#define BCRYPT_CHAIN_MODE_GCM (const WCHAR []){'C','h','a','i','n','i','n','g','M','o','d','e','G','C','M',0} + + typedef struct _BCRYPT_ALGORITHM_IDENTIFIER + { +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch b/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch new file mode 100644 index 00000000..4adf1ea4 --- /dev/null +++ b/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch @@ -0,0 +1,469 @@ +From f527689b793100c79654ac5d6c1376d128ca3175 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 19 Dec 2016 23:58:52 +0100 +Subject: bcrypt: Directly implement hmac computation. + +--- + dlls/bcrypt/bcrypt_main.c | 277 +++++++++++++++++----------------------------- + 1 file changed, 104 insertions(+), 173 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 937bdf7..af2314a 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -60,9 +60,6 @@ MAKE_FUNCPTR(gnutls_global_set_log_level); + MAKE_FUNCPTR(gnutls_hash); + MAKE_FUNCPTR(gnutls_hash_deinit); + MAKE_FUNCPTR(gnutls_hash_init); +-MAKE_FUNCPTR(gnutls_hmac); +-MAKE_FUNCPTR(gnutls_hmac_deinit); +-MAKE_FUNCPTR(gnutls_hmac_init); + MAKE_FUNCPTR(gnutls_perror); + #undef MAKE_FUNCPTR + +@@ -99,9 +96,6 @@ static BOOL gnutls_initialize(void) + LOAD_FUNCPTR(gnutls_hash); + LOAD_FUNCPTR(gnutls_hash_deinit); + LOAD_FUNCPTR(gnutls_hash_init); +- LOAD_FUNCPTR(gnutls_hmac); +- LOAD_FUNCPTR(gnutls_hmac_deinit); +- LOAD_FUNCPTR(gnutls_hmac_init); + LOAD_FUNCPTR(gnutls_perror) + #undef LOAD_FUNCPTR + +@@ -163,6 +157,8 @@ enum alg_id + ALG_ID_SHA512 + }; + ++#define MAX_HASH_OUTPUT_BYTES 64 ++ + static const struct { + ULONG hash_length; + const WCHAR *alg_name; +@@ -183,6 +179,19 @@ struct algorithm + BOOL hmac; + }; + ++#define MAX_HASH_BLOCK_BITS 1024 ++ ++int alg_block_bits[] = ++{ ++ /* ALG_ID_AES */ 0, ++ /* ALG_ID_MD5 */ 512, ++ /* ALG_ID_RNG */ 0, ++ /* ALG_ID_SHA1 */ 512, ++ /* ALG_ID_SHA256 */ 512, ++ /* ALG_ID_SHA384 */ 1024, ++ /* ALG_ID_SHA512 */ 1024 ++}; ++ + NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) + { + const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; +@@ -289,24 +298,20 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) + } + + #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H +-struct hash ++struct hash_impl + { +- struct object hdr; +- enum alg_id alg_id; +- BOOL hmac; + union + { + CC_MD5_CTX md5_ctx; + CC_SHA1_CTX sha1_ctx; + CC_SHA256_CTX sha256_ctx; + CC_SHA512_CTX sha512_ctx; +- CCHmacContext hmac_ctx; + } u; + }; + +-static NTSTATUS hash_init( struct hash *hash ) ++static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) + { +- switch (hash->alg_id) ++ switch (alg_id) + { + case ALG_ID_MD5: + CC_MD5_Init( &hash->u.md5_ctx ); +@@ -329,50 +334,16 @@ static NTSTATUS hash_init( struct hash *hash ) + break; + + default: +- ERR( "unhandled id %u\n", hash->alg_id ); ++ ERR( "unhandled id %u\n", alg_id ); + return STATUS_NOT_IMPLEMENTED; + } + return STATUS_SUCCESS; + } + +-static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) ++static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *input, ULONG size ) + { +- CCHmacAlgorithm cc_algorithm; +- switch (hash->alg_id) +- { +- case ALG_ID_MD5: +- cc_algorithm = kCCHmacAlgMD5; +- break; +- +- case ALG_ID_SHA1: +- cc_algorithm = kCCHmacAlgSHA1; +- break; +- +- case ALG_ID_SHA256: +- cc_algorithm = kCCHmacAlgSHA256; +- break; +- +- case ALG_ID_SHA384: +- cc_algorithm = kCCHmacAlgSHA384; +- break; +- +- case ALG_ID_SHA512: +- cc_algorithm = kCCHmacAlgSHA512; +- break; +- +- default: +- ERR( "unhandled id %u\n", hash->alg_id ); +- return STATUS_NOT_IMPLEMENTED; +- } +- +- CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size ); +- return STATUS_SUCCESS; +-} +- +- +-static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) +-{ +- switch (hash->alg_id) ++ switch (alg_id) + { + case ALG_ID_MD5: + CC_MD5_Update( &hash->u.md5_ctx, input, size ); +@@ -395,21 +366,16 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) + break; + + default: +- ERR( "unhandled id %u\n", hash->alg_id ); ++ ERR( "unhandled id %u\n", alg_id ); + return STATUS_NOT_IMPLEMENTED; + } + return STATUS_SUCCESS; + } + +-static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) +-{ +- CCHmacUpdate( &hash->u.hmac_ctx, input, size ); +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) ++static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *output, ULONG size ) + { +- switch (hash->alg_id) ++ switch (alg_id) + { + case ALG_ID_MD5: + CC_MD5_Final( output, &hash->u.md5_ctx ); +@@ -432,37 +398,25 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) + break; + + default: +- ERR( "unhandled id %u\n", hash->alg_id ); ++ ERR( "unhandled id %u\n", alg_id ); + break; + } + return STATUS_SUCCESS; + } + +-static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) +-{ +- CCHmacFinal( &hash->u.hmac_ctx, output ); +- return STATUS_SUCCESS; +-} + #elif defined(HAVE_GNUTLS_HASH) +-struct hash ++struct hash_impl + { +- struct object hdr; +- enum alg_id alg_id; +- BOOL hmac; +- union +- { +- gnutls_hash_hd_t hash_handle; +- gnutls_hmac_hd_t hmac_handle; +- } u; ++ gnutls_hash_hd_t hash_handle; + }; + +-static NTSTATUS hash_init( struct hash *hash ) ++static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) + { + gnutls_digest_algorithm_t alg; + + if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; + +- switch (hash->alg_id) ++ switch (alg_id) + { + case ALG_ID_MD5: + alg = GNUTLS_DIG_MD5; +@@ -484,117 +438,63 @@ static NTSTATUS hash_init( struct hash *hash ) + break; + + default: +- ERR( "unhandled id %u\n", hash->alg_id ); +- return STATUS_NOT_IMPLEMENTED; +- } +- +- if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR; +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) +-{ +- gnutls_mac_algorithm_t alg; +- +- if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; +- +- switch (hash->alg_id) +- { +- case ALG_ID_MD5: +- alg = GNUTLS_MAC_MD5; +- break; +- case ALG_ID_SHA1: +- alg = GNUTLS_MAC_SHA1; +- break; +- +- case ALG_ID_SHA256: +- alg = GNUTLS_MAC_SHA256; +- break; +- +- case ALG_ID_SHA384: +- alg = GNUTLS_MAC_SHA384; +- break; +- +- case ALG_ID_SHA512: +- alg = GNUTLS_MAC_SHA512; +- break; +- +- default: +- ERR( "unhandled id %u\n", hash->alg_id ); ++ ERR( "unhandled id %u\n", alg_id ); + return STATUS_NOT_IMPLEMENTED; + } + +- if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR; +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) +-{ +- if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR; ++ if (pgnutls_hash_init( &hash->hash_handle, alg )) return STATUS_INTERNAL_ERROR; + return STATUS_SUCCESS; + } + +-static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) ++static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *input, ULONG size ) + { +- if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR; ++ if (pgnutls_hash( hash->hash_handle, input, size )) return STATUS_INTERNAL_ERROR; + return STATUS_SUCCESS; + } + +-static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) ++static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *output, ULONG size ) + { +- pgnutls_hash_deinit( hash->u.hash_handle, output ); ++ pgnutls_hash_deinit( hash->hash_handle, output ); + return STATUS_SUCCESS; + } + +-static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) +-{ +- pgnutls_hmac_deinit( hash->u.hmac_handle, output ); +- return STATUS_SUCCESS; +-} + #else +-struct hash ++struct hash_impl + { +- struct object hdr; +- BOOL hmac; +- enum alg_id alg_id; +-}; + +-static NTSTATUS hash_init( struct hash *hash ) +-{ +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; +-} +- +-static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) +-{ +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; +-} ++}; + +-static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) ++static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) + { + ERR( "support for hashes not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; + } + +-static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) ++static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *input, ULONG size ) + { + ERR( "support for hashes not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; + } + +-static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) ++static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, ++ UCHAR *output, ULONG size ) + { + ERR( "support for hashes not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; + } ++#endif + +-static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) ++struct hash + { +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; +-} +-#endif ++ struct object hdr; ++ enum alg_id alg_id; ++ BOOL hmac; ++ struct hash_impl outer; ++ struct hash_impl inner; ++}; + + #ifdef _WIN64 + #define OBJECT_LENGTH_AES 654 +@@ -787,8 +687,11 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL + UCHAR *secret, ULONG secretlen, ULONG flags ) + { + struct algorithm *alg = algorithm; ++ UCHAR buffer[MAX_HASH_BLOCK_BITS / 8]; + struct hash *hash; ++ int block_bytes; + NTSTATUS status; ++ int i; + + TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen, + secret, secretlen, flags ); +@@ -806,17 +709,45 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL + hash->alg_id = alg->id; + hash->hmac = alg->hmac; + +- if (hash->hmac) ++ status = hash_init( &hash->inner, hash->alg_id ); ++ if (status || !hash->hmac) goto end; ++ status = hash_init( &hash->outer, hash->alg_id ); ++ if (status) goto end; ++ ++ /* reduce key size if too big */ ++ block_bytes = alg_block_bits[hash->alg_id] / 8; ++ if (secretlen > block_bytes) + { +- status = hmac_init( hash, secret, secretlen ); ++ struct hash_impl temp; ++ status = hash_init( &temp, hash->alg_id ); ++ if (status) goto end; ++ status = hash_update( &temp, hash->alg_id, secret, secretlen ); ++ if (status) goto end; ++ memset( buffer, 0, block_bytes ); ++ status = hash_finish( &temp, hash->alg_id, buffer, alg_props[hash->alg_id].hash_length ); ++ if (status) goto end; + } + else + { +- status = hash_init( hash ); ++ memset( buffer, 0, block_bytes ); ++ memcpy( buffer, secret, secretlen ); + } + ++ /* initialize outer hash */ ++ for (i = 0; i < block_bytes; i++) ++ buffer[i] ^= 0x5c; ++ status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ); ++ if (status) goto end; ++ ++ /* initialize inner hash */ ++ for (i = 0; i < block_bytes; i++) ++ buffer[i] ^= (0x5c ^ 0x36); ++ status = hash_update( &hash->inner, hash->alg_id, buffer, block_bytes ); ++ ++end: + if (status != STATUS_SUCCESS) + { ++ /* FIXME: call hash_finish to release resources */ + HeapFree( GetProcessHeap(), 0, hash ); + return status; + } +@@ -845,33 +776,33 @@ NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG s + if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; + if (!input) return STATUS_SUCCESS; + +- if (hash->hmac) +- { +- return hmac_update( hash, input, size ); +- } +- else +- { +- return hash_update( hash, input, size ); +- } ++ return hash_update( &hash->inner, hash->alg_id, input, size ); + } + + NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags ) + { ++ UCHAR buffer[MAX_HASH_OUTPUT_BYTES]; + struct hash *hash = handle; ++ NTSTATUS status; ++ int hash_size; + + TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags ); + + if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; + if (!output) return STATUS_INVALID_PARAMETER; + +- if (hash->hmac) +- { +- return hmac_finish( hash, output, size ); +- } +- else +- { +- return hash_finish( hash, output, size ); +- } ++ if (!hash->hmac) ++ return hash_finish( &hash->inner, hash->alg_id, output, size ); ++ ++ hash_size = alg_props[hash->alg_id].hash_length; ++ ++ status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_size); ++ if (status) return status; ++ ++ status = hash_update( &hash->outer, hash->alg_id, buffer, hash_size); ++ if (status) return status; ++ ++ return hash_finish( &hash->outer, hash->alg_id, output, size); + } + + NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen, +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch b/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch new file mode 100644 index 00000000..1f517b01 --- /dev/null +++ b/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch @@ -0,0 +1,673 @@ +From ecff30df4deadc0df006a880a5528343a4ab788f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 20 Dec 2016 02:36:57 +0100 +Subject: bcrypt: Add internal fallback implementation for hash calculations. + +--- + dlls/bcrypt/Makefile.in | 5 +- + dlls/bcrypt/bcrypt_internal.h | 79 +++++++++++++++++ + dlls/bcrypt/bcrypt_main.c | 101 ++++++++++++++++++++-- + dlls/bcrypt/sha256.c | 169 +++++++++++++++++++++++++++++++++++++ + dlls/bcrypt/sha384.c | 41 +++++++++ + dlls/bcrypt/sha512.c | 191 ++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 578 insertions(+), 8 deletions(-) + create mode 100644 dlls/bcrypt/bcrypt_internal.h + create mode 100644 dlls/bcrypt/sha256.c + create mode 100644 dlls/bcrypt/sha384.c + create mode 100644 dlls/bcrypt/sha512.c + +diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in +index ef9d7ea..38753bd 100644 +--- a/dlls/bcrypt/Makefile.in ++++ b/dlls/bcrypt/Makefile.in +@@ -4,6 +4,9 @@ IMPORTLIB = bcrypt + EXTRAINCL = $(GNUTLS_CFLAGS) + + C_SRCS = \ +- bcrypt_main.c ++ bcrypt_main.c \ ++ sha256.c \ ++ sha512.c \ ++ sha384.c + + RC_SRCS = version.rc +diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h +new file mode 100644 +index 0000000..8a8f6d1 +--- /dev/null ++++ b/dlls/bcrypt/bcrypt_internal.h +@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2016 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ * ++ */ ++ ++#ifndef __BCRYPT_INTERNAL_H ++#define __BCRYPT_INTERNAL_H ++ ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++ ++typedef struct ++{ ++ ULONG64 len; ++ DWORD h[8]; ++ UCHAR buf[64]; ++} SHA256_CTX; ++ ++void sha256_init(SHA256_CTX *ctx); ++void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len); ++void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer); ++ ++typedef struct ++{ ++ ULONG64 len; ++ ULONG64 h[8]; ++ UCHAR buf[128]; ++} SHA512_CTX; ++ ++void sha512_init(SHA512_CTX *ctx); ++void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len); ++void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer); ++ ++void sha384_init(SHA512_CTX *ctx); ++#define sha384_update sha512_update ++void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer); ++ ++/* Definitions from advapi32 */ ++typedef struct ++{ ++ unsigned int i[2]; ++ unsigned int buf[4]; ++ unsigned char in[64]; ++ unsigned char digest[16]; ++} MD5_CTX; ++ ++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); ++ ++typedef struct ++{ ++ ULONG Unknown[6]; ++ ULONG State[5]; ++ ULONG Count[2]; ++ UCHAR Buffer[64]; ++} SHA_CTX; ++ ++VOID WINAPI A_SHAInit(SHA_CTX *ctx); ++VOID WINAPI A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size); ++VOID WINAPI A_SHAFinal(SHA_CTX *ctx, PULONG result); ++ ++#endif /* __BCRYPT_INTERNAL_H */ +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index af2314a..9441cf0 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -36,6 +36,8 @@ + #include "ntsecapi.h" + #include "bcrypt.h" + ++#include "bcrypt_internal.h" ++ + #include "wine/debug.h" + #include "wine/library.h" + #include "wine/unicode.h" +@@ -463,27 +465,112 @@ static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, + #else + struct hash_impl + { +- ++ union ++ { ++ MD5_CTX md5; ++ SHA_CTX sha1; ++ SHA256_CTX sha256; ++ SHA512_CTX sha512; ++ } u; + }; + + static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) + { +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; ++ switch (alg_id) ++ { ++ case ALG_ID_MD5: ++ MD5Init(&hash->u.md5); ++ break; ++ ++ case ALG_ID_SHA1: ++ A_SHAInit(&hash->u.sha1); ++ break; ++ ++ case ALG_ID_SHA256: ++ sha256_init(&hash->u.sha256); ++ break; ++ ++ case ALG_ID_SHA384: ++ sha384_init(&hash->u.sha512); ++ break; ++ ++ case ALG_ID_SHA512: ++ sha512_init(&hash->u.sha512); ++ break; ++ ++ default: ++ ERR( "unhandled id %u\n", alg_id ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ ++ return STATUS_SUCCESS; + } + + static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, + UCHAR *input, ULONG size ) + { +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; ++ switch (alg_id) ++ { ++ case ALG_ID_MD5: ++ MD5Update(&hash->u.md5, input, size); ++ break; ++ ++ case ALG_ID_SHA1: ++ A_SHAUpdate(&hash->u.sha1, input, size); ++ break; ++ ++ case ALG_ID_SHA256: ++ sha256_update(&hash->u.sha256, input, size); ++ break; ++ ++ case ALG_ID_SHA384: ++ sha384_update(&hash->u.sha512, input, size); ++ break; ++ ++ case ALG_ID_SHA512: ++ sha512_update(&hash->u.sha512, input, size); ++ break; ++ ++ default: ++ ERR( "unhandled id %u\n", alg_id ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ ++ return STATUS_SUCCESS; + } + + static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, + UCHAR *output, ULONG size ) + { +- ERR( "support for hashes not available at build time\n" ); +- return STATUS_NOT_IMPLEMENTED; ++ switch (alg_id) ++ { ++ case ALG_ID_MD5: ++ MD5Final(&hash->u.md5); ++ memcpy(output, hash->u.md5.digest, 16); ++ break; ++ ++ case ALG_ID_SHA1: ++ A_SHAFinal(&hash->u.sha1, (ULONG*)output); ++ break; ++ ++ case ALG_ID_SHA256: ++ sha256_finalize(&hash->u.sha256, output); ++ break; ++ ++ case ALG_ID_SHA384: ++ sha384_finalize(&hash->u.sha512, output); ++ break; ++ ++ case ALG_ID_SHA512: ++ sha512_finalize(&hash->u.sha512, output); ++ break; ++ ++ default: ++ ERR( "unhandled id %u\n", alg_id ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ ++ return STATUS_SUCCESS; + } + #endif + +diff --git a/dlls/bcrypt/sha256.c b/dlls/bcrypt/sha256.c +new file mode 100644 +index 0000000..48c4a48 +--- /dev/null ++++ b/dlls/bcrypt/sha256.c +@@ -0,0 +1,169 @@ ++/* ++ * Copyright 2016 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ * ++ */ ++ ++/* Based on public domain implementation from ++ https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha256.c */ ++ ++#include "bcrypt_internal.h" ++ ++static DWORD ror(DWORD n, int k) { return (n >> k) | (n << (32-k)); } ++#define Ch(x,y,z) (z ^ (x & (y ^ z))) ++#define Maj(x,y,z) ((x & y) | (z & (x | y))) ++#define S0(x) (ror(x,2) ^ ror(x,13) ^ ror(x,22)) ++#define S1(x) (ror(x,6) ^ ror(x,11) ^ ror(x,25)) ++#define R0(x) (ror(x,7) ^ ror(x,18) ^ (x>>3)) ++#define R1(x) (ror(x,17) ^ ror(x,19) ^ (x>>10)) ++ ++static const DWORD K[64] = ++{ ++ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, ++ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, ++ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, ++ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, ++ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, ++ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, ++ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, ++ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ++}; ++ ++static void processblock(SHA256_CTX *ctx, const UCHAR *buffer) ++{ ++ DWORD W[64], t1, t2, a, b, c, d, e, f, g, h; ++ int i; ++ ++ for (i = 0; i < 16; i++) ++ { ++ W[i] = (DWORD)buffer[4*i]<<24; ++ W[i] |= (DWORD)buffer[4*i+1]<<16; ++ W[i] |= (DWORD)buffer[4*i+2]<<8; ++ W[i] |= buffer[4*i+3]; ++ } ++ ++ for (; i < 64; i++) ++ W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; ++ ++ a = ctx->h[0]; ++ b = ctx->h[1]; ++ c = ctx->h[2]; ++ d = ctx->h[3]; ++ e = ctx->h[4]; ++ f = ctx->h[5]; ++ g = ctx->h[6]; ++ h = ctx->h[7]; ++ ++ for (i = 0; i < 64; i++) ++ { ++ t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; ++ t2 = S0(a) + Maj(a,b,c); ++ h = g; ++ g = f; ++ f = e; ++ e = d + t1; ++ d = c; ++ c = b; ++ b = a; ++ a = t1 + t2; ++ } ++ ++ ctx->h[0] += a; ++ ctx->h[1] += b; ++ ctx->h[2] += c; ++ ctx->h[3] += d; ++ ctx->h[4] += e; ++ ctx->h[5] += f; ++ ctx->h[6] += g; ++ ctx->h[7] += h; ++} ++ ++static void pad(SHA256_CTX *ctx) ++{ ++ ULONG64 r = ctx->len % 64; ++ ++ ctx->buf[r++] = 0x80; ++ ++ if (r > 56) ++ { ++ memset(ctx->buf + r, 0, 64 - r); ++ r = 0; ++ processblock(ctx, ctx->buf); ++ } ++ ++ memset(ctx->buf + r, 0, 56 - r); ++ ctx->len *= 8; ++ ctx->buf[56] = ctx->len >> 56; ++ ctx->buf[57] = ctx->len >> 48; ++ ctx->buf[58] = ctx->len >> 40; ++ ctx->buf[59] = ctx->len >> 32; ++ ctx->buf[60] = ctx->len >> 24; ++ ctx->buf[61] = ctx->len >> 16; ++ ctx->buf[62] = ctx->len >> 8; ++ ctx->buf[63] = ctx->len; ++ ++ processblock(ctx, ctx->buf); ++} ++ ++void sha256_init(SHA256_CTX *ctx) ++{ ++ ctx->len = 0; ++ ctx->h[0] = 0x6a09e667; ++ ctx->h[1] = 0xbb67ae85; ++ ctx->h[2] = 0x3c6ef372; ++ ctx->h[3] = 0xa54ff53a; ++ ctx->h[4] = 0x510e527f; ++ ctx->h[5] = 0x9b05688c; ++ ctx->h[6] = 0x1f83d9ab; ++ ctx->h[7] = 0x5be0cd19; ++} ++ ++void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len) ++{ ++ const UCHAR *p = buffer; ++ ULONG64 r = ctx->len % 64; ++ ++ ctx->len += len; ++ if (r) ++ { ++ if (len < 64 - r) ++ { ++ memcpy(ctx->buf + r, p, len); ++ return; ++ } ++ memcpy(ctx->buf + r, p, 64 - r); ++ len -= 64 - r; ++ p += 64 - r; ++ processblock(ctx, ctx->buf); ++ } ++ for (; len >= 64; len -= 64, p += 64) ++ processblock(ctx, p); ++ memcpy(ctx->buf, p, len); ++} ++ ++void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer) ++{ ++ int i; ++ ++ pad(ctx); ++ for (i = 0; i < 8; i++) ++ { ++ buffer[4*i] = ctx->h[i] >> 24; ++ buffer[4*i+1] = ctx->h[i] >> 16; ++ buffer[4*i+2] = ctx->h[i] >> 8; ++ buffer[4*i+3] = ctx->h[i]; ++ } ++} +diff --git a/dlls/bcrypt/sha384.c b/dlls/bcrypt/sha384.c +new file mode 100644 +index 0000000..81e7e08 +--- /dev/null ++++ b/dlls/bcrypt/sha384.c +@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2016 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ * ++ */ ++ ++#include "bcrypt_internal.h" ++ ++void sha384_init(SHA512_CTX *ctx) ++{ ++ ctx->len = 0; ++ ctx->h[0] = 0xcbbb9d5dc1059ed8ULL; ++ ctx->h[1] = 0x629a292a367cd507ULL; ++ ctx->h[2] = 0x9159015a3070dd17ULL; ++ ctx->h[3] = 0x152fecd8f70e5939ULL; ++ ctx->h[4] = 0x67332667ffc00b31ULL; ++ ctx->h[5] = 0x8eb44a8768581511ULL; ++ ctx->h[6] = 0xdb0c2e0d64f98fa7ULL; ++ ctx->h[7] = 0x47b5481dbefa4fa4ULL; ++} ++ ++void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer) ++{ ++ UCHAR buffer512[64]; ++ ++ sha512_finalize(ctx, buffer512); ++ memcpy(buffer, buffer512, 48); ++} +diff --git a/dlls/bcrypt/sha512.c b/dlls/bcrypt/sha512.c +new file mode 100644 +index 0000000..fdd7867 +--- /dev/null ++++ b/dlls/bcrypt/sha512.c +@@ -0,0 +1,191 @@ ++/* ++ * Copyright 2016 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ * ++ */ ++ ++/* Based on public domain implementation from ++ https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha512.c */ ++ ++#include "bcrypt_internal.h" ++ ++static ULONG64 ror(ULONG64 n, int k) { return (n >> k) | (n << (64-k)); } ++#define Ch(x,y,z) (z ^ (x & (y ^ z))) ++#define Maj(x,y,z) ((x & y) | (z & (x | y))) ++#define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39)) ++#define S1(x) (ror(x,14) ^ ror(x,18) ^ ror(x,41)) ++#define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7)) ++#define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6)) ++ ++static const ULONG64 K[80] = ++{ ++ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, ++ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, ++ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, ++ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, ++ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, ++ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, ++ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, ++ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, ++ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, ++ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, ++ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, ++ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, ++ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, ++ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, ++ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, ++ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, ++ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, ++ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, ++ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, ++ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL ++}; ++ ++static void processblock(SHA512_CTX *ctx, const UCHAR *buffer) ++{ ++ ULONG64 W[80], t1, t2, a, b, c, d, e, f, g, h; ++ int i; ++ ++ for (i = 0; i < 16; i++) ++ { ++ W[i] = (ULONG64)buffer[8*i]<<56; ++ W[i] |= (ULONG64)buffer[8*i+1]<<48; ++ W[i] |= (ULONG64)buffer[8*i+2]<<40; ++ W[i] |= (ULONG64)buffer[8*i+3]<<32; ++ W[i] |= (ULONG64)buffer[8*i+4]<<24; ++ W[i] |= (ULONG64)buffer[8*i+5]<<16; ++ W[i] |= (ULONG64)buffer[8*i+6]<<8; ++ W[i] |= buffer[8*i+7]; ++ } ++ ++ for (; i < 80; i++) ++ W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; ++ ++ a = ctx->h[0]; ++ b = ctx->h[1]; ++ c = ctx->h[2]; ++ d = ctx->h[3]; ++ e = ctx->h[4]; ++ f = ctx->h[5]; ++ g = ctx->h[6]; ++ h = ctx->h[7]; ++ ++ for (i = 0; i < 80; i++) ++ { ++ t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; ++ t2 = S0(a) + Maj(a,b,c); ++ h = g; ++ g = f; ++ f = e; ++ e = d + t1; ++ d = c; ++ c = b; ++ b = a; ++ a = t1 + t2; ++ } ++ ++ ctx->h[0] += a; ++ ctx->h[1] += b; ++ ctx->h[2] += c; ++ ctx->h[3] += d; ++ ctx->h[4] += e; ++ ctx->h[5] += f; ++ ctx->h[6] += g; ++ ctx->h[7] += h; ++} ++ ++static void pad(SHA512_CTX *ctx) ++{ ++ ULONG64 r = ctx->len % 128; ++ ++ ctx->buf[r++] = 0x80; ++ if (r > 112) ++ { ++ memset(ctx->buf + r, 0, 128 - r); ++ r = 0; ++ processblock(ctx, ctx->buf); ++ } ++ ++ memset(ctx->buf + r, 0, 120 - r); ++ ctx->len *= 8; ++ ctx->buf[120] = ctx->len >> 56; ++ ctx->buf[121] = ctx->len >> 48; ++ ctx->buf[122] = ctx->len >> 40; ++ ctx->buf[123] = ctx->len >> 32; ++ ctx->buf[124] = ctx->len >> 24; ++ ctx->buf[125] = ctx->len >> 16; ++ ctx->buf[126] = ctx->len >> 8; ++ ctx->buf[127] = ctx->len; ++ ++ processblock(ctx, ctx->buf); ++} ++ ++void sha512_init(SHA512_CTX *ctx) ++{ ++ ctx->len = 0; ++ ctx->h[0] = 0x6a09e667f3bcc908ULL; ++ ctx->h[1] = 0xbb67ae8584caa73bULL; ++ ctx->h[2] = 0x3c6ef372fe94f82bULL; ++ ctx->h[3] = 0xa54ff53a5f1d36f1ULL; ++ ctx->h[4] = 0x510e527fade682d1ULL; ++ ctx->h[5] = 0x9b05688c2b3e6c1fULL; ++ ctx->h[6] = 0x1f83d9abfb41bd6bULL; ++ ctx->h[7] = 0x5be0cd19137e2179ULL; ++} ++ ++void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len) ++{ ++ const UCHAR *p = buffer; ++ unsigned r = ctx->len % 128; ++ ++ ctx->len += len; ++ if (r) ++ { ++ if (len < 128 - r) ++ { ++ memcpy(ctx->buf + r, p, len); ++ return; ++ } ++ memcpy(ctx->buf + r, p, 128 - r); ++ len -= 128 - r; ++ p += 128 - r; ++ processblock(ctx, ctx->buf); ++ } ++ ++ for (; len >= 128; len -= 128, p += 128) ++ processblock(ctx, p); ++ ++ memcpy(ctx->buf, p, len); ++} ++ ++void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer) ++{ ++ int i; ++ ++ pad(ctx); ++ ++ for (i = 0; i < 8; i++) ++ { ++ buffer[8*i] = ctx->h[i] >> 56; ++ buffer[8*i+1] = ctx->h[i] >> 48; ++ buffer[8*i+2] = ctx->h[i] >> 40; ++ buffer[8*i+3] = ctx->h[i] >> 32; ++ buffer[8*i+4] = ctx->h[i] >> 24; ++ buffer[8*i+5] = ctx->h[i] >> 16; ++ buffer[8*i+6] = ctx->h[i] >> 8; ++ buffer[8*i+7] = ctx->h[i]; ++ } ++} +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch b/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch new file mode 100644 index 00000000..f39b8d98 --- /dev/null +++ b/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch @@ -0,0 +1,216 @@ +From ae04ece5f64a29a67e187d5aa32c6b8d3e399d61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 20 Dec 2016 02:39:26 +0100 +Subject: bcrypt: Use hash fallback implementation as default and remove gnutls + / commoncrypto hash implemetation. + +--- + dlls/bcrypt/bcrypt_main.c | 171 ---------------------------------------------- + 1 file changed, 171 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 9441cf0..3e2b22d 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -59,9 +59,6 @@ MAKE_FUNCPTR(gnutls_global_deinit); + MAKE_FUNCPTR(gnutls_global_init); + MAKE_FUNCPTR(gnutls_global_set_log_function); + MAKE_FUNCPTR(gnutls_global_set_log_level); +-MAKE_FUNCPTR(gnutls_hash); +-MAKE_FUNCPTR(gnutls_hash_deinit); +-MAKE_FUNCPTR(gnutls_hash_init); + MAKE_FUNCPTR(gnutls_perror); + #undef MAKE_FUNCPTR + +@@ -95,9 +92,6 @@ static BOOL gnutls_initialize(void) + LOAD_FUNCPTR(gnutls_global_init) + LOAD_FUNCPTR(gnutls_global_set_log_function) + LOAD_FUNCPTR(gnutls_global_set_log_level) +- LOAD_FUNCPTR(gnutls_hash); +- LOAD_FUNCPTR(gnutls_hash_deinit); +- LOAD_FUNCPTR(gnutls_hash_init); + LOAD_FUNCPTR(gnutls_perror) + #undef LOAD_FUNCPTR + +@@ -299,170 +293,6 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) + return STATUS_SUCCESS; + } + +-#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H +-struct hash_impl +-{ +- union +- { +- CC_MD5_CTX md5_ctx; +- CC_SHA1_CTX sha1_ctx; +- CC_SHA256_CTX sha256_ctx; +- CC_SHA512_CTX sha512_ctx; +- } u; +-}; +- +-static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) +-{ +- switch (alg_id) +- { +- case ALG_ID_MD5: +- CC_MD5_Init( &hash->u.md5_ctx ); +- break; +- +- case ALG_ID_SHA1: +- CC_SHA1_Init( &hash->u.sha1_ctx ); +- break; +- +- case ALG_ID_SHA256: +- CC_SHA256_Init( &hash->u.sha256_ctx ); +- break; +- +- case ALG_ID_SHA384: +- CC_SHA384_Init( &hash->u.sha512_ctx ); +- break; +- +- case ALG_ID_SHA512: +- CC_SHA512_Init( &hash->u.sha512_ctx ); +- break; +- +- default: +- ERR( "unhandled id %u\n", alg_id ); +- return STATUS_NOT_IMPLEMENTED; +- } +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, +- UCHAR *input, ULONG size ) +-{ +- switch (alg_id) +- { +- case ALG_ID_MD5: +- CC_MD5_Update( &hash->u.md5_ctx, input, size ); +- break; +- +- case ALG_ID_SHA1: +- CC_SHA1_Update( &hash->u.sha1_ctx, input, size ); +- break; +- +- case ALG_ID_SHA256: +- CC_SHA256_Update( &hash->u.sha256_ctx, input, size ); +- break; +- +- case ALG_ID_SHA384: +- CC_SHA384_Update( &hash->u.sha512_ctx, input, size ); +- break; +- +- case ALG_ID_SHA512: +- CC_SHA512_Update( &hash->u.sha512_ctx, input, size ); +- break; +- +- default: +- ERR( "unhandled id %u\n", alg_id ); +- return STATUS_NOT_IMPLEMENTED; +- } +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, +- UCHAR *output, ULONG size ) +-{ +- switch (alg_id) +- { +- case ALG_ID_MD5: +- CC_MD5_Final( output, &hash->u.md5_ctx ); +- break; +- +- case ALG_ID_SHA1: +- CC_SHA1_Final( output, &hash->u.sha1_ctx ); +- break; +- +- case ALG_ID_SHA256: +- CC_SHA256_Final( output, &hash->u.sha256_ctx ); +- break; +- +- case ALG_ID_SHA384: +- CC_SHA384_Final( output, &hash->u.sha512_ctx ); +- break; +- +- case ALG_ID_SHA512: +- CC_SHA512_Final( output, &hash->u.sha512_ctx ); +- break; +- +- default: +- ERR( "unhandled id %u\n", alg_id ); +- break; +- } +- return STATUS_SUCCESS; +-} +- +-#elif defined(HAVE_GNUTLS_HASH) +-struct hash_impl +-{ +- gnutls_hash_hd_t hash_handle; +-}; +- +-static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) +-{ +- gnutls_digest_algorithm_t alg; +- +- if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; +- +- switch (alg_id) +- { +- case ALG_ID_MD5: +- alg = GNUTLS_DIG_MD5; +- break; +- case ALG_ID_SHA1: +- alg = GNUTLS_DIG_SHA1; +- break; +- +- case ALG_ID_SHA256: +- alg = GNUTLS_DIG_SHA256; +- break; +- +- case ALG_ID_SHA384: +- alg = GNUTLS_DIG_SHA384; +- break; +- +- case ALG_ID_SHA512: +- alg = GNUTLS_DIG_SHA512; +- break; +- +- default: +- ERR( "unhandled id %u\n", alg_id ); +- return STATUS_NOT_IMPLEMENTED; +- } +- +- if (pgnutls_hash_init( &hash->hash_handle, alg )) return STATUS_INTERNAL_ERROR; +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, +- UCHAR *input, ULONG size ) +-{ +- if (pgnutls_hash( hash->hash_handle, input, size )) return STATUS_INTERNAL_ERROR; +- return STATUS_SUCCESS; +-} +- +-static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, +- UCHAR *output, ULONG size ) +-{ +- pgnutls_hash_deinit( hash->hash_handle, output ); +- return STATUS_SUCCESS; +-} +- +-#else + struct hash_impl + { + union +@@ -572,7 +402,6 @@ static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, + + return STATUS_SUCCESS; + } +-#endif + + struct hash + { +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch b/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch new file mode 100644 index 00000000..18b61d0b --- /dev/null +++ b/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch @@ -0,0 +1,56 @@ +From 9331e2a78e8ec0ba29ed1041a9f851ffd39cc249 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 20 Dec 2016 03:59:19 +0100 +Subject: bcrypt: Implement BCryptDuplicateHash. + +FIXME: Should we check for NULL pointers? +--- + dlls/bcrypt/bcrypt.spec | 2 +- + dlls/bcrypt/bcrypt_main.c | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec +index 962953e..9ecd21d 100644 +--- a/dlls/bcrypt/bcrypt.spec ++++ b/dlls/bcrypt/bcrypt.spec +@@ -11,7 +11,7 @@ + @ stdcall BCryptDestroyHash(ptr) + @ stdcall BCryptDestroyKey(ptr) + @ stub BCryptDestroySecret +-@ stub BCryptDuplicateHash ++@ stdcall BCryptDuplicateHash(ptr ptr ptr long long) + @ stub BCryptDuplicateKey + @ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) + @ stdcall BCryptEnumAlgorithms(long ptr ptr long) +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 3e2b22d..944a9ea 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -672,6 +672,24 @@ end: + return STATUS_SUCCESS; + } + ++NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy, ++ UCHAR *object, ULONG object_count, ULONG flags ) ++{ ++ struct hash *hash_orig = handle; ++ struct hash *hash_copy; ++ ++ TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, object_count, flags ); ++ ++ if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; ++ if (!(hash_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash_copy) ))) ++ return STATUS_NO_MEMORY; ++ ++ memcpy( hash_copy, hash_orig, sizeof(*hash_orig) ); ++ ++ *handle_copy = hash_copy; ++ return STATUS_SUCCESS; ++} ++ + NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle ) + { + struct hash *hash = handle; +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/definition b/patches/bcrypt-Improvements/definition new file mode 100644 index 00000000..45120ff7 --- /dev/null +++ b/patches/bcrypt-Improvements/definition @@ -0,0 +1,2 @@ +Fixes: [41951] Implement bcrypt.BCryptDuplicateHash +Fixes: [40418] Implement BCrypt AES provider diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index dafa0fc9..7b28f9ff 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -95,6 +95,7 @@ patch_enable_all () enable_avifil32_AVIFile_Proxies="$1" enable_avifil32_IGetFrame_fnSetFormat="$1" enable_avifile_dll16_AVIStreamGetFrame="$1" + enable_bcrypt_Improvements="$1" enable_browseui_Progress_Dialog="$1" enable_cabinet_iFolder="$1" enable_combase_RoApi="$1" @@ -463,6 +464,9 @@ patch_enable () avifile.dll16-AVIStreamGetFrame) enable_avifile_dll16_AVIStreamGetFrame="$2" ;; + bcrypt-Improvements) + enable_bcrypt_Improvements="$2" + ;; browseui-Progress_Dialog) enable_browseui_Progress_Dialog="$2" ;; @@ -2802,6 +2806,31 @@ if test "$enable_avifile_dll16_AVIStreamGetFrame" -eq 1; then ) >> "$patchlist" fi +# Patchset bcrypt-Improvements +# | +# | This patchset fixes the following Wine bugs: +# | * [#41951] Implement bcrypt.BCryptDuplicateHash +# | * [#40418] Implement BCrypt AES provider +# | +# | Modified files: +# | * dlls/bcrypt/Makefile.in, dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_internal.h, dlls/bcrypt/bcrypt_main.c, +# | dlls/bcrypt/sha256.c, dlls/bcrypt/sha384.c, dlls/bcrypt/sha512.c, dlls/bcrypt/tests/bcrypt.c, include/bcrypt.h +# | +if test "$enable_bcrypt_Improvements" -eq 1; then + patch_apply bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch + patch_apply bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch + patch_apply bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch + patch_apply bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch + patch_apply bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch + ( + echo '+ { "Hans Leidekker", "bcrypt: Add AES provider.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Directly implement hmac computation.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Add internal fallback implementation for hash calculations.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Use hash fallback implementation as default and remove gnutls / commoncrypto hash implemetation.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptDuplicateHash.", 1 },'; + ) >> "$patchlist" +fi + # Patchset browseui-Progress_Dialog # | # | Modified files: