bcrypt: Implement MD5 algorithm and add tests.
Signed-off-by: Patrick Armstrong <pat@oldpatricka.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9bfacd24d2
commit
8bd3e4cc2e
|
@ -174,6 +174,7 @@ struct object
|
|||
|
||||
enum alg_id
|
||||
{
|
||||
ALG_ID_MD5,
|
||||
ALG_ID_SHA1,
|
||||
ALG_ID_SHA256,
|
||||
ALG_ID_SHA384,
|
||||
|
@ -184,6 +185,7 @@ static const struct {
|
|||
ULONG hash_length;
|
||||
const WCHAR *alg_name;
|
||||
} alg_props[] = {
|
||||
/* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM },
|
||||
/* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM },
|
||||
/* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
|
||||
/* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
|
||||
|
@ -211,6 +213,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
|
|||
}
|
||||
|
||||
if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
|
||||
else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
|
||||
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;
|
||||
|
@ -262,6 +265,7 @@ struct hash
|
|||
enum alg_id alg_id;
|
||||
union
|
||||
{
|
||||
CC_MD5_CTX md5_ctx;
|
||||
CC_SHA1_CTX sha1_ctx;
|
||||
CC_SHA256_CTX sha256_ctx;
|
||||
CC_SHA512_CTX sha512_ctx;
|
||||
|
@ -272,6 +276,9 @@ static NTSTATUS hash_init( struct hash *hash )
|
|||
{
|
||||
switch (hash->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;
|
||||
|
@ -299,6 +306,10 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
|
|||
{
|
||||
switch (hash->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;
|
||||
|
@ -326,6 +337,10 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
|
|||
{
|
||||
switch (hash->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;
|
||||
|
@ -364,6 +379,9 @@ static NTSTATUS hash_init( struct hash *hash )
|
|||
|
||||
switch (hash->alg_id)
|
||||
{
|
||||
case ALG_ID_MD5:
|
||||
alg = GNUTLS_DIG_MD5;
|
||||
break;
|
||||
case ALG_ID_SHA1:
|
||||
alg = GNUTLS_DIG_SHA1;
|
||||
break;
|
||||
|
@ -426,6 +444,7 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
|
|||
}
|
||||
#endif
|
||||
|
||||
#define OBJECT_LENGTH_MD5 274
|
||||
#define OBJECT_LENGTH_SHA1 278
|
||||
#define OBJECT_LENGTH_SHA256 286
|
||||
#define OBJECT_LENGTH_SHA384 382
|
||||
|
@ -467,6 +486,14 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf,
|
|||
|
||||
switch (id)
|
||||
{
|
||||
case ALG_ID_MD5:
|
||||
if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
|
||||
{
|
||||
value = OBJECT_LENGTH_MD5;
|
||||
break;
|
||||
}
|
||||
FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
case ALG_ID_SHA1:
|
||||
if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
|
||||
{
|
||||
|
|
|
@ -404,6 +404,79 @@ static void test_sha512(void)
|
|||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
}
|
||||
|
||||
static void test_md5(void)
|
||||
{
|
||||
static const char expected[] =
|
||||
"e2a3e68d23ce348b8f68b3079de3d4c9";
|
||||
BCRYPT_ALG_HANDLE alg;
|
||||
BCRYPT_HASH_HANDLE hash;
|
||||
UCHAR buf[512], md5[16];
|
||||
ULONG size, len;
|
||||
char str[65];
|
||||
NTSTATUS ret;
|
||||
|
||||
alg = NULL;
|
||||
ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
ok(alg != NULL, "alg not set\n");
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
|
||||
ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
|
||||
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
|
||||
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
ok(size == sizeof(len), "got %u\n", size);
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
|
||||
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
|
||||
ok(len == 0xdeadbeef, "got %u\n", len);
|
||||
ok(size == sizeof(len), "got %u\n", size);
|
||||
|
||||
len = size = 0xdeadbeef;
|
||||
ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
ok(len != 0xdeadbeef, "len not set\n");
|
||||
ok(size == sizeof(len), "got %u\n", size);
|
||||
|
||||
test_hash_length(alg, 16);
|
||||
test_alg_name(alg, "MD5");
|
||||
|
||||
hash = NULL;
|
||||
len = sizeof(buf);
|
||||
ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
ok(hash != NULL, "hash not set\n");
|
||||
|
||||
ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
|
||||
test_hash_length(hash, 16);
|
||||
test_alg_name(hash, "MD5");
|
||||
|
||||
memset(md5, 0, sizeof(md5));
|
||||
ret = BCryptFinishHash(hash, md5, sizeof(md5), 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
format_hash( md5, sizeof(md5), str );
|
||||
ok(!strcmp(str, expected), "got %s\n", str);
|
||||
|
||||
ret = BCryptDestroyHash(hash);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
|
||||
ret = BCryptCloseAlgorithmProvider(alg, 0);
|
||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||
}
|
||||
|
||||
START_TEST(bcrypt)
|
||||
{
|
||||
test_BCryptGenRandom();
|
||||
|
@ -412,4 +485,5 @@ START_TEST(bcrypt)
|
|||
test_sha256();
|
||||
test_sha384();
|
||||
test_sha512();
|
||||
test_md5();
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef LONG NTSTATUS;
|
|||
#define MS_PLATFORM_CRYPTO_PROVIDER (const WCHAR [])\
|
||||
{'M','i','c','r','o','s','o','f','t',' ','P','l','a','t','f','o','r','m',' ','C','r','y','p','t','o',' ','P','r','o','v','i','d','e','r',0}
|
||||
|
||||
#define BCRYPT_MD5_ALGORITHM (const WCHAR []){'M','D','5',0}
|
||||
#define BCRYPT_SHA1_ALGORITHM (const WCHAR []){'S','H','A','1',0}
|
||||
#define BCRYPT_SHA256_ALGORITHM (const WCHAR []){'S','H','A','2','5','6',0}
|
||||
#define BCRYPT_SHA384_ALGORITHM (const WCHAR []){'S','H','A','3','8','4',0}
|
||||
|
|
Loading…
Reference in New Issue