diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index a40f9d1a4b7..593e78416e2 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -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 diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 2b9ae0b766f..0c68a4f3e6c 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -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; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 6865e87ca8c..c3f8f3d78af 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -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;