mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 21:44:09 +00:00
bcrypt: Implement 3DES cipher support.
This is used by CoD: WWII multiplayer mode to login to its servers. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b865d8ec9e
commit
6b569a451f
|
@ -113,6 +113,7 @@ struct object
|
||||||
enum alg_id
|
enum alg_id
|
||||||
{
|
{
|
||||||
/* cipher */
|
/* cipher */
|
||||||
|
ALG_ID_3DES,
|
||||||
ALG_ID_AES,
|
ALG_ID_AES,
|
||||||
|
|
||||||
/* hash */
|
/* hash */
|
||||||
|
|
|
@ -101,6 +101,7 @@ static const struct
|
||||||
}
|
}
|
||||||
builtin_algorithms[] =
|
builtin_algorithms[] =
|
||||||
{
|
{
|
||||||
|
{ BCRYPT_3DES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 522, 0, 0 },
|
||||||
{ BCRYPT_AES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 654, 0, 0 },
|
{ BCRYPT_AES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 654, 0, 0 },
|
||||||
{ BCRYPT_SHA256_ALGORITHM, BCRYPT_HASH_INTERFACE, 286, 32, 512 },
|
{ BCRYPT_SHA256_ALGORITHM, BCRYPT_HASH_INTERFACE, 286, 32, 512 },
|
||||||
{ BCRYPT_SHA384_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 48, 1024 },
|
{ BCRYPT_SHA384_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 48, 1024 },
|
||||||
|
@ -426,6 +427,7 @@ struct hash
|
||||||
struct hash_impl inner;
|
struct hash_impl inner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BLOCK_LENGTH_3DES 8
|
||||||
#define BLOCK_LENGTH_AES 16
|
#define BLOCK_LENGTH_AES 16
|
||||||
|
|
||||||
static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
|
static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
|
||||||
|
@ -467,6 +469,46 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS get_3des_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
|
||||||
|
{
|
||||||
|
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
|
||||||
|
{
|
||||||
|
*ret_size = sizeof(ULONG);
|
||||||
|
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
if (buf) *(ULONG *)buf = BLOCK_LENGTH_3DES;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
|
||||||
|
{
|
||||||
|
const WCHAR *str;
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
|
||||||
|
default: return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_size = 64;
|
||||||
|
if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
memcpy( buf, str, (lstrlenW(str) + 1) * sizeof(WCHAR) );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (!wcscmp( prop, BCRYPT_KEY_LENGTHS ))
|
||||||
|
{
|
||||||
|
BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
|
||||||
|
*ret_size = sizeof(*key_lengths);
|
||||||
|
if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
if (key_lengths)
|
||||||
|
{
|
||||||
|
key_lengths->dwMinLength = 192;
|
||||||
|
key_lengths->dwMaxLength = 192;
|
||||||
|
key_lengths->dwIncrement = 0;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
FIXME( "unsupported property %s\n", debugstr_w(prop) );
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
|
static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
|
||||||
{
|
{
|
||||||
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
|
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
|
||||||
|
@ -556,6 +598,9 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop
|
||||||
|
|
||||||
switch (alg->id)
|
switch (alg->id)
|
||||||
{
|
{
|
||||||
|
case ALG_ID_3DES:
|
||||||
|
return get_3des_property( alg->mode, prop, buf, size, ret_size );
|
||||||
|
|
||||||
case ALG_ID_AES:
|
case ALG_ID_AES:
|
||||||
return get_aes_property( alg->mode, prop, buf, size, ret_size );
|
return get_aes_property( alg->mode, prop, buf, size, ret_size );
|
||||||
|
|
||||||
|
@ -577,6 +622,23 @@ static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHA
|
||||||
{
|
{
|
||||||
switch (alg->id)
|
switch (alg->id)
|
||||||
{
|
{
|
||||||
|
case ALG_ID_3DES:
|
||||||
|
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
|
||||||
|
{
|
||||||
|
if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
|
||||||
|
{
|
||||||
|
alg->mode = MODE_ID_CBC;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop) );
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
case ALG_ID_AES:
|
case ALG_ID_AES:
|
||||||
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
|
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
|
||||||
{
|
{
|
||||||
|
@ -624,6 +686,9 @@ static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHA
|
||||||
{
|
{
|
||||||
switch (key->alg_id)
|
switch (key->alg_id)
|
||||||
{
|
{
|
||||||
|
case ALG_ID_3DES:
|
||||||
|
return get_3des_property( key->u.s.mode, prop, buf, size, ret_size );
|
||||||
|
|
||||||
case ALG_ID_AES:
|
case ALG_ID_AES:
|
||||||
if (!wcscmp( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
|
if (!wcscmp( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
|
||||||
return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
|
return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
|
||||||
|
|
|
@ -491,6 +491,7 @@ static NTSTATUS CDECL key_symmetric_init( struct key *key )
|
||||||
|
|
||||||
switch (key->alg_id)
|
switch (key->alg_id)
|
||||||
{
|
{
|
||||||
|
case ALG_ID_3DES:
|
||||||
case ALG_ID_AES:
|
case ALG_ID_AES:
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -504,6 +505,18 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
|
||||||
{
|
{
|
||||||
switch (key->alg_id)
|
switch (key->alg_id)
|
||||||
{
|
{
|
||||||
|
case ALG_ID_3DES:
|
||||||
|
WARN( "handle block size\n" );
|
||||||
|
switch (key->u.s.mode)
|
||||||
|
{
|
||||||
|
case MODE_ID_CBC:
|
||||||
|
return GNUTLS_CIPHER_3DES_CBC;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FIXME( "3DES mode %u with key length %u not supported\n", key->u.s.mode, key->u.s.secret_len );
|
||||||
|
return GNUTLS_CIPHER_UNKNOWN;
|
||||||
|
|
||||||
case ALG_ID_AES:
|
case ALG_ID_AES:
|
||||||
WARN( "handle block size\n" );
|
WARN( "handle block size\n" );
|
||||||
switch (key->u.s.mode)
|
switch (key->u.s.mode)
|
||||||
|
|
|
@ -639,6 +639,67 @@ static void test_aes(void)
|
||||||
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_3des(void)
|
||||||
|
{
|
||||||
|
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
|
||||||
|
BCRYPT_ALG_HANDLE alg;
|
||||||
|
ULONG size, len;
|
||||||
|
UCHAR mode[64];
|
||||||
|
NTSTATUS ret;
|
||||||
|
|
||||||
|
alg = NULL;
|
||||||
|
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_3DES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
ok(alg != NULL, "alg not set\n");
|
||||||
|
|
||||||
|
len = size = 0;
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
ok(len, "expected non-zero len\n");
|
||||||
|
ok(size == sizeof(len), "got %u\n", size);
|
||||||
|
|
||||||
|
len = size = 0;
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
ok(len == 8, "got %u\n", len);
|
||||||
|
ok(size == sizeof(len), "got %u\n", size);
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, 0, &size, 0);
|
||||||
|
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
|
||||||
|
ok(size == 64, "got %u\n", size);
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode) - 1, &size, 0);
|
||||||
|
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
|
||||||
|
ok(size == 64, "got %u\n", size);
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
memset(mode, 0, sizeof(mode));
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode), &size, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_CBC), "got %s\n", wine_dbgstr_w((const WCHAR *)mode));
|
||||||
|
ok(size == 64, "got %u\n", size);
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
memset(&key_lengths, 0, sizeof(key_lengths));
|
||||||
|
ret = pBCryptGetProperty(alg, BCRYPT_KEY_LENGTHS, (UCHAR*)&key_lengths, sizeof(key_lengths), &size, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
ok(size == sizeof(key_lengths), "got %u\n", size);
|
||||||
|
ok(key_lengths.dwMinLength == 192, "Expected 192, got %d\n", key_lengths.dwMinLength);
|
||||||
|
ok(key_lengths.dwMaxLength == 192, "Expected 192, got %d\n", key_lengths.dwMaxLength);
|
||||||
|
ok(key_lengths.dwIncrement == 0, "Expected 0, got %d\n", key_lengths.dwIncrement);
|
||||||
|
|
||||||
|
memcpy(mode, BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM));
|
||||||
|
ret = pBCryptSetProperty(alg, BCRYPT_CHAINING_MODE, mode, 0, 0);
|
||||||
|
ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
|
||||||
|
|
||||||
|
test_alg_name(alg, L"3DES");
|
||||||
|
|
||||||
|
ret = pBCryptCloseAlgorithmProvider(alg, 0);
|
||||||
|
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_BCryptGenerateSymmetricKey(void)
|
static void test_BCryptGenerateSymmetricKey(void)
|
||||||
{
|
{
|
||||||
static UCHAR secret[] =
|
static UCHAR secret[] =
|
||||||
|
@ -2730,6 +2791,7 @@ START_TEST(bcrypt)
|
||||||
test_BcryptHash();
|
test_BcryptHash();
|
||||||
test_BcryptDeriveKeyPBKDF2();
|
test_BcryptDeriveKeyPBKDF2();
|
||||||
test_rng();
|
test_rng();
|
||||||
|
test_3des();
|
||||||
test_aes();
|
test_aes();
|
||||||
test_BCryptGenerateSymmetricKey();
|
test_BCryptGenerateSymmetricKey();
|
||||||
test_BCryptEncrypt();
|
test_BCryptEncrypt();
|
||||||
|
|
Loading…
Reference in a new issue