From f352837868192907ef2ac6ad0d77f40700479581 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Thu, 29 Mar 2018 12:26:16 +0200 Subject: [PATCH] bcrypt: Add support for BCRYPT_OPAQUE_KEY_BLOB. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/bcrypt/bcrypt_main.c | 99 ++++++++++++++++++++++++-------------- dlls/bcrypt/tests/bcrypt.c | 27 +++++++++-- 2 files changed, 88 insertions(+), 38 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 1490089cf72..1e56062b818 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1018,6 +1018,40 @@ static ULONG get_block_size( struct algorithm *alg ) return ret; } +static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object, + ULONG object_len, UCHAR *input, ULONG input_len ) +{ + ULONG len; + + if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB )) + { + BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input; + + if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL; + if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER; + if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1) + { + FIXME( "unknown key data blob version %u\n", header->dwVersion ); + return STATUS_INVALID_PARAMETER; + } + len = header->cbKeyData; + if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER; + + return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 ); + } + else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB )) + { + if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL; + len = *(ULONG *)input; + if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER; + + return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 ); + } + + FIXME( "unsupported key type %s\n", debugstr_w(type) ); + return STATUS_NOT_IMPLEMENTED; +} + static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size ) { if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB )) @@ -1034,6 +1068,17 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U memcpy( &header[1], key->u.s.secret, key->u.s.secret_len ); return STATUS_SUCCESS; } + else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB )) + { + ULONG len, req_size = sizeof(len) + key->u.s.secret_len; + + *size = req_size; + if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL; + + *(ULONG *)output = key->u.s.secret_len; + memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len ); + return STATUS_SUCCESS; + } FIXME( "unsupported key type %s\n", debugstr_w(type) ); return STATUS_NOT_IMPLEMENTED; @@ -1829,7 +1874,8 @@ static NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *ha return STATUS_NOT_IMPLEMENTED; } -static NTSTATUS key_destroy( struct key *key ) +static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object, + ULONG object_len, UCHAR *input, ULONG input_len ) { ERR( "support for keys not available at build time\n" ); return STATUS_NOT_IMPLEMENTED; @@ -1841,6 +1887,12 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U return STATUS_NOT_IMPLEMENTED; } +static NTSTATUS key_destroy( struct key *key ) +{ + ERR( "support for keys not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; +} + static inline BOOL key_is_symmetric( struct key *key ) { ERR( "support for keys not available at build time\n" ); @@ -1880,9 +1932,9 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ return STATUS_SUCCESS; } -NTSTATUS WINAPI BCryptImportKey(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type, - BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input, - ULONG input_len, ULONG flags) +NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type, + BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input, + ULONG input_len, ULONG flags ) { struct algorithm *alg = algorithm; @@ -1894,50 +1946,27 @@ NTSTATUS WINAPI BCryptImportKey(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE d if (decrypt_key) { - FIXME("Decrypting of key not yet supported\n"); - return STATUS_NO_MEMORY; + FIXME( "decryption of key not yet supported\n" ); + return STATUS_NOT_IMPLEMENTED; } - if (!strcmpW(type, BCRYPT_KEY_DATA_BLOB)) - { - BCRYPT_KEY_DATA_BLOB_HEADER *key_header = (BCRYPT_KEY_DATA_BLOB_HEADER*)input; - - if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) - return STATUS_BUFFER_TOO_SMALL; - - if (key_header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) - return STATUS_INVALID_PARAMETER; - - if (key_header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1) - { - FIXME("Unknown key data blob version: %d\n", key_header->dwVersion); - return STATUS_INVALID_PARAMETER; - } - - if (key_header->cbKeyData + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) - return STATUS_INVALID_PARAMETER; - - return BCryptGenerateSymmetricKey(algorithm, key, object, object_len, (UCHAR*)&key_header[1], key_header->cbKeyData, 0); - } - - FIXME("Unsupported key type: %s\n", debugstr_w(type)); - return STATUS_INVALID_PARAMETER; + return key_import( algorithm, type, key, object, object_len, input, input_len ); } -NTSTATUS WINAPI BCryptExportKey(BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type, - PUCHAR output, ULONG output_len, ULONG *size, ULONG flags) +NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type, + PUCHAR output, ULONG output_len, ULONG *size, ULONG flags ) { struct key *key = export_key; TRACE("%p, %p, %s, %p, %u, %p, %u\n", key, encrypt_key, debugstr_w(type), output, output_len, size, flags); if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; - if (!output || !output_len || !size) return STATUS_INVALID_PARAMETER; + if (!output || !type || !size) return STATUS_INVALID_PARAMETER; if (encrypt_key) { - FIXME("Encryption of key not yet supported\n"); - return STATUS_NO_MEMORY; + FIXME( "encryption of key not yet supported\n" ); + return STATUS_NOT_IMPLEMENTED; } return key_export( key, type, output, output_len, size ); diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 7d59f6d4c1d..2a499711bdf 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -1393,7 +1393,7 @@ static void test_BCryptDecrypt(void) static void test_key_import_export(void) { UCHAR buffer1[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16]; - UCHAR buffer2[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16]; + UCHAR buffer2[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16], *buf; BCRYPT_KEY_DATA_BLOB_HEADER *key_data1 = (void*)buffer1; BCRYPT_ALG_HANDLE aes; BCRYPT_KEY_HANDLE key; @@ -1408,6 +1408,7 @@ static void test_key_import_export(void) key_data1->cbKeyData = 16; memset(&key_data1[1], 0x11, 16); + key = NULL; ret = pBCryptImportKey(aes, NULL, BCRYPT_KEY_DATA_BLOB, &key, NULL, 0, buffer1, sizeof(buffer1), 0); ok(ret == STATUS_SUCCESS || broken(ret == STATUS_INVALID_PARAMETER) /* vista */, "got %08x\n", ret); if (ret == STATUS_INVALID_PARAMETER) @@ -1415,11 +1416,12 @@ static void test_key_import_export(void) win_skip("broken BCryptImportKey\n"); return; } + ok(key != NULL, "key not set\n"); size = 0; - ret = pBCryptExportKey(key, NULL, BCRYPT_KEY_DATA_BLOB, buffer2, 1, &size, 0); + ret = pBCryptExportKey(key, NULL, BCRYPT_KEY_DATA_BLOB, buffer2, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(size == sizeof(buffer2), "Got %u\n", size); + ok(size == sizeof(buffer2), "got %u\n", size); size = 0; memset(buffer2, 0xff, sizeof(buffer2)); @@ -1428,6 +1430,25 @@ static void test_key_import_export(void) ok(size == sizeof(buffer2), "Got %u\n", size); ok(!memcmp(buffer1, buffer2, sizeof(buffer1)), "Expected exported key to match imported key\n"); + /* opaque blob */ + size = 0; + ret = pBCryptExportKey(key, NULL, BCRYPT_OPAQUE_KEY_BLOB, buffer2, 0, &size, 0); + ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); + ok(size > 0, "got zero\n"); + + buf = HeapAlloc(GetProcessHeap(), 0, size); + ret = pBCryptExportKey(key, NULL, BCRYPT_OPAQUE_KEY_BLOB, buf, size, &size, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + ret = pBCryptDestroyKey(key); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + key = NULL; + ret = pBCryptImportKey(aes, NULL, BCRYPT_OPAQUE_KEY_BLOB, &key, NULL, 0, buf, size, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ok(key != NULL, "key not set\n"); + HeapFree(GetProcessHeap(), 0, buf); + ret = pBCryptDestroyKey(key); ok(ret == STATUS_SUCCESS, "got %08x\n", ret);