Commit 8bd3e4cc authored by Patrick Armstrong's avatar Patrick Armstrong Committed by Alexandre Julliard

bcrypt: Implement MD5 algorithm and add tests.

parent 9bfacd24
......@@ -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}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment