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:
parent
03e9ef38a7
commit
dc97df72ff
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue