bcrypt: Support retrieving properties from key handles.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2018-12-04 08:59:20 +01:00 committed by Alexandre Julliard
parent 03e9ef38a7
commit dc97df72ff
3 changed files with 117 additions and 54 deletions

View File

@ -198,9 +198,19 @@ struct key
} u;
};
#else
struct key_symmetric
{
enum mode_id mode;
};
struct key
{
struct object hdr;
enum alg_id alg_id;
union
{
struct key_symmetric s;
} u;
};
#endif

View File

@ -413,6 +413,63 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
{
*ret_size = sizeof(ULONG);
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
if (buf) *(ULONG *)buf = BLOCK_LENGTH_AES;
return STATUS_SUCCESS;
}
if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
{
const WCHAR *str;
switch (mode)
{
case MODE_ID_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
case MODE_ID_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
default: return STATUS_NOT_IMPLEMENTED;
}
*ret_size = 64;
if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
memcpy( buf, str, (strlenW(str) + 1) * sizeof(WCHAR) );
return STATUS_SUCCESS;
}
if (!strcmpW( 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 = 128;
key_lengths->dwMaxLength = 256;
key_lengths->dwIncrement = 64;
}
return STATUS_SUCCESS;
}
if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
{
BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
if (mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED;
*ret_size = sizeof(*tag_length);
if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
if (tag_length)
{
tag_length->dwMinLength = 12;
tag_length->dwMaxLength = 16;
tag_length->dwIncrement = 1;
}
return STATUS_SUCCESS;
}
FIXME( "unsupported property %s\n", debugstr_w(prop) );
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
NTSTATUS status;
@ -424,59 +481,7 @@ NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR
switch (alg->id)
{
case ALG_ID_AES:
if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
{
*ret_size = sizeof(ULONG);
if (size < sizeof(ULONG))
return STATUS_BUFFER_TOO_SMALL;
if (buf)
*(ULONG *)buf = BLOCK_LENGTH_AES;
return STATUS_SUCCESS;
}
if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
{
const WCHAR *mode;
switch (alg->mode)
{
case MODE_ID_ECB: mode = BCRYPT_CHAIN_MODE_ECB; break;
case MODE_ID_CBC: mode = BCRYPT_CHAIN_MODE_CBC; break;
case MODE_ID_GCM: mode = BCRYPT_CHAIN_MODE_GCM; break;
default: return STATUS_NOT_IMPLEMENTED;
}
*ret_size = 64;
if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) );
return STATUS_SUCCESS;
}
if (!strcmpW( 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 = 128;
key_lengths->dwMaxLength = 256;
key_lengths->dwIncrement = 64;
}
return STATUS_SUCCESS;
}
if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
{
BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
if (alg->mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED;
*ret_size = sizeof(*tag_length);
if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
if (tag_length)
{
tag_length->dwMinLength = 12;
tag_length->dwMaxLength = 16;
tag_length->dwIncrement = 1;
}
return STATUS_SUCCESS;
}
break;
return get_aes_property( alg->mode, prop, buf, size, ret_size );
default:
break;
@ -533,6 +538,20 @@ static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, U
return status;
}
static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
switch (key->alg_id)
{
case ALG_ID_AES:
if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
default:
FIXME( "unsupported algorithm %u\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED;
}
}
NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
{
struct object *object = handle;
@ -549,6 +568,11 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu
const struct algorithm *alg = (const struct algorithm *)object;
return get_alg_property( alg, prop, buffer, count, res );
}
case MAGIC_KEY:
{
const struct key *key = (const struct key *)object;
return get_key_property( key, prop, buffer, count, res );
}
case MAGIC_HASH:
{
const struct hash *hash = (const struct hash *)object;

View File

@ -507,7 +507,8 @@ static void test_BCryptGenerateSymmetricKey(void)
{0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79};
BCRYPT_ALG_HANDLE aes;
BCRYPT_KEY_HANDLE key, key2;
UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16];
UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16], mode[64];
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
ULONG size, len, i;
NTSTATUS ret;
@ -608,6 +609,27 @@ static void test_BCryptGenerateSymmetricKey(void)
ok(size == 16, "got %u\n", size);
ok(!memcmp(plaintext, data, sizeof(data)), "wrong data\n");
memset(mode, 0, sizeof(mode));
ret = pBCryptGetProperty(key, 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), "wrong mode\n");
len = 0;
size = 0;
ret = pBCryptGetProperty(key, BCRYPT_BLOCK_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(len == 16, "got %u\n", len);
ok(size == sizeof(len), "got %u\n", size);
size = 0;
memset(&key_lengths, 0, sizeof(key_lengths));
ret = pBCryptGetProperty(aes, 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 == 128, "Expected 128, got %d\n", key_lengths.dwMinLength);
ok(key_lengths.dwMaxLength == 256, "Expected 256, got %d\n", key_lengths.dwMaxLength);
ok(key_lengths.dwIncrement == 64, "Expected 64, got %d\n", key_lengths.dwIncrement);
ret = pBCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
HeapFree(GetProcessHeap(), 0, buf);
@ -855,6 +877,9 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(key != NULL, "key not set\n");
ret = pBCryptGetProperty(key, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_length, sizeof(tag_length), &size, 0);
ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
memset(&auth_info, 0, sizeof(auth_info));
auth_info.cbSize = sizeof(auth_info);
auth_info.dwInfoVersion = 1;
@ -1108,6 +1133,7 @@ static void test_BCryptDecrypt(void)
{0x17,0x9d,0xc0,0x7a,0xf0,0xcf,0xaa,0xd5,0x1c,0x11,0xc4,0x4b,0xd6,0xa3,0x3e,0x77};
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info;
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
BCRYPT_AUTH_TAG_LENGTHS_STRUCT tag_lengths;
BCRYPT_ALG_HANDLE aes;
BCRYPT_KEY_HANDLE key;
UCHAR *buf, plaintext[48], ivbuf[16];
@ -1242,6 +1268,9 @@ static void test_BCryptDecrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(key != NULL, "key not set\n");
ret = pBCryptGetProperty(key, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_lengths, sizeof(tag_lengths), &size, 0);
ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
memset(&auth_info, 0, sizeof(auth_info));
auth_info.cbSize = sizeof(auth_info);
auth_info.dwInfoVersion = 1;