diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 9e0d06e9cc7..542bd0756a0 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1521,9 +1521,10 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len, ULONG flags ) { + BCRYPT_KEY_LENGTHS_STRUCT key_lengths; struct algorithm *alg = algorithm; + ULONG block_size, size; struct key *key; - ULONG block_size; TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm, handle, object, object_len, secret, secret_len, flags ); @@ -1538,6 +1539,25 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ if (!(block_size = get_block_size( alg ))) return STATUS_INVALID_PARAMETER; + if (!get_alg_property( alg, BCRYPT_KEY_LENGTHS, (UCHAR*)&key_lengths, sizeof(key_lengths), &size )) + { + if (secret_len > (size = key_lengths.dwMaxLength / 8)) + { + WARN( "secret_len %u exceeds key max length %u, setting to maximum.\n", secret_len, size ); + secret_len = size; + } + else if (secret_len < (size = key_lengths.dwMinLength / 8)) + { + WARN( "secret_len %u is less than minimum key length %u.\n", secret_len, size ); + return STATUS_INVALID_PARAMETER; + } + else if (key_lengths.dwIncrement && (secret_len * 8 - key_lengths.dwMinLength) % key_lengths.dwIncrement) + { + WARN( "secret_len %u is not a valid key length.\n", secret_len ); + return STATUS_INVALID_PARAMETER; + } + } + if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY; InitializeCriticalSection( &key->u.s.cs ); key->hdr.magic = MAGIC_KEY; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index fb5ac03b039..4dd0f4195aa 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -731,6 +731,17 @@ static void test_BCryptGenerateSymmetricKey(void) key = NULL; buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + + key = (BCRYPT_KEY_HANDLE)0xdeadbeef; + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, 1, 0); + ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); + ok(key == (HANDLE)0xdeadbeef, "got unexpected key %p.\n", key); + + key = (BCRYPT_KEY_HANDLE)0xdeadbeef; + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret) + 1, 0); + ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); + ok(key == (HANDLE)0xdeadbeef, "got unexpected key %p.\n", key); + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(key != NULL, "key not set\n"); @@ -1101,8 +1112,16 @@ static void test_BCryptEncrypt(void) /* 256 bit key */ buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ret = pBCryptDestroyKey(key); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + /* Key generations succeeds if the key size exceeds maximum and uses maximum key length + * from secret. */ + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256) + 1, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); size = 0; memcpy(ivbuf, iv, sizeof(iv));