[PATCH 0/4] MR11635: bcrypt: Fix a couple of issues.
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/bcrypt/tests/bcrypt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 8cb6319ff39..b80fbc520f1 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -459,6 +459,11 @@ static void test_BcryptHash(void) format_hash( md5, sizeof(md5), str ); ok(!strcmp(str, expected), "got %s\n", str); + /* With a secret but without BCRYPT_ALG_HANDLE_HMAC_FLAG */ + ret = pBCryptHash(alg, (UCHAR *)"key", sizeof("key"), (UCHAR *)"test", sizeof("test"), md5, sizeof(md5)); + todo_wine + ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); + ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11635
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/bcrypt/tests/bcrypt.c | 124 ++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index b80fbc520f1..2a051ddeeac 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -3347,10 +3347,13 @@ struct ecdh_test BYTE *ecdh_secret; ULONG ecdh_secret_len; BYTE *hashed_secret; + BYTE *hashed_secret_prepended; DWORD public_magic; DWORD private_magic; }; +static const UCHAR hash_prepend[][2] = {{0xca, 0xfe}, {0xf0, 0x0d}}; + static void test_ECDH_alg(const struct ecdh_test *t) { BCryptBuffer hash_param_buffers[] = @@ -3361,6 +3364,24 @@ static void test_ECDH_alg(const struct ecdh_test *t) (void *)BCRYPT_SHA1_ALGORITHM, } }; + BCryptBuffer hash_param_buffers_prepended[] = + { + { + sizeof(BCRYPT_SHA1_ALGORITHM), + KDF_HASH_ALGORITHM, + (void *)BCRYPT_SHA1_ALGORITHM, + }, + { + sizeof(hash_prepend[0]), + KDF_SECRET_PREPEND, + (void *)hash_prepend[0], + }, + { + sizeof(hash_prepend[1]), + KDF_SECRET_PREPEND, + (void *)hash_prepend[1], + } + }; BCryptBufferDesc hash_params = { @@ -3368,6 +3389,12 @@ static void test_ECDH_alg(const struct ecdh_test *t) ARRAY_SIZE(hash_param_buffers), hash_param_buffers, }; + BCryptBufferDesc hash_params_prepended = + { + BCRYPTBUFFER_VERSION, + ARRAY_SIZE(hash_param_buffers_prepended), + hash_param_buffers_prepended, + }; BYTE *buf; BCRYPT_ECCKEY_BLOB *ecckey; BCRYPT_ALG_HANDLE alg; @@ -3466,6 +3493,17 @@ static void test_ECDH_alg(const struct ecdh_test *t) ok(!(memcmp(t->ecdh_secret, buf, size)), "wrong data\n"); free(buf); + /* Raw secret with a BCryptBufferDesc, which is ignored */ + status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, &hash_params_prepended, NULL, 0, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + + ok(size == (t->bitlen + 7) / 8, "size of secret key incorrect, got %lu, expected 32\n", size); + buf = malloc(size); + status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, &hash_params_prepended, buf, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(!(memcmp(t->ecdh_secret, buf, size)), "wrong data\n"); + free(buf); + raw_secret_end: status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); ok (status == STATUS_SUCCESS, "got %#lx\n", status); @@ -3478,6 +3516,17 @@ raw_secret_end: ok(!(memcmp(t->hashed_secret, buf, size)), "wrong data\n"); free(buf); + status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params_prepended, NULL, 0, &size, 0); + ok (status == STATUS_SUCCESS, "got %#lx\n", status); + + ok (size == 20, "got %lu\n", size); + buf = malloc(size); + status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params_prepended, buf, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + todo_wine + ok(!(memcmp(t->hashed_secret_prepended, buf, size)), "wrong data\n"); + free(buf); + /* ulVersion is not verified */ hash_params.ulVersion = 0xdeadbeef; status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); @@ -3532,6 +3581,11 @@ static void test_ECDH(void) 0x1b, 0xe7, 0xbf, 0x0f, 0x65, 0x1e, 0xd0, 0x07, 0xf9, 0xf4, 0x77, 0x48, 0x48, 0x39, 0xd0, 0xf8, 0xf3, 0xce, 0xfc, 0x89 }; + static BYTE hashed256_secret_prepended[] = + { + 0x10, 0x99, 0x5f, 0x01, 0xef, 0xa8, 0x18, 0x82, 0xd2, 0x62, 0x37, 0xab, 0xe0, 0x7c, 0x62, 0xc7, + 0x50, 0x7f, 0xa6, 0xa0, + }; static BYTE ecc384privkey[] = { @@ -3567,6 +3621,11 @@ static void test_ECDH(void) 0x78, 0xf8, 0x07, 0xab, 0x00, 0x35, 0xaa, 0x8c, 0x22, 0xd0, 0xe7, 0x06, 0xfc, 0x0b, 0x74, 0x41, 0xed, 0xdc, 0x16, 0x6c, }; + static BYTE hashed384_secret_prepended[] = + { + 0x3d, 0xe0, 0x30, 0xd9, 0xe2, 0xdc, 0x61, 0xad, 0x26, 0x21, 0xad, 0xa3, 0x3e, 0xaf, 0xd5, 0x8e, + 0xb6, 0xbc, 0x5a, 0x51, + }; static BYTE ecc521privkey[] = { @@ -3611,22 +3670,27 @@ static void test_ECDH(void) 0x72, 0x39, 0x73, 0x5f, 0xc9, 0x26, 0x1f, 0x8e, 0xe3, 0x30, 0x11, 0xe1, 0x4f, 0xc4, 0x65, 0xc0, 0xde, 0xf9, 0xe6, 0x6a, }; + static BYTE hashed521_secret_prepended[] = + { + 0x2e, 0x6f, 0x51, 0xc9, 0x15, 0xfb, 0x9f, 0xd0, 0xad, 0x92, 0x43, 0xdb, 0xc8, 0x6b, 0xd9, 0xe6, + 0x1a, 0x5f, 0x52, 0xa6, + }; static const struct ecdh_test tests[] = { { BCRYPT_ECDH_P256_ALGORITHM, 256, ecc256privkey, sizeof(ecc256privkey), ecdh256_pubkey, sizeof(ecdh256_pubkey), - ecdh256_secret, sizeof(ecdh256_secret), hashed256_secret, + ecdh256_secret, sizeof(ecdh256_secret), hashed256_secret, hashed256_secret_prepended, BCRYPT_ECDH_PUBLIC_P256_MAGIC, BCRYPT_ECDH_PRIVATE_P256_MAGIC, }, { BCRYPT_ECDH_P384_ALGORITHM, 384, ecc384privkey, sizeof(ecc384privkey), ecdh384_pubkey, sizeof(ecdh384_pubkey), - ecdh384_secret, sizeof(ecdh384_secret), hashed384_secret, + ecdh384_secret, sizeof(ecdh384_secret), hashed384_secret, hashed384_secret_prepended, BCRYPT_ECDH_PUBLIC_P384_MAGIC, BCRYPT_ECDH_PRIVATE_P384_MAGIC, }, { BCRYPT_ECDH_P521_ALGORITHM, 521, ecc521privkey, sizeof(ecc521privkey), ecdh521_pubkey, sizeof(ecdh521_pubkey), - ecdh521_secret, sizeof(ecdh521_secret), hashed521_secret, + ecdh521_secret, sizeof(ecdh521_secret), hashed521_secret, hashed521_secret_prepended, BCRYPT_ECDH_PUBLIC_P521_MAGIC, BCRYPT_ECDH_PRIVATE_P521_MAGIC, }, }; @@ -3803,6 +3867,12 @@ static BYTE dh_hashed_secret[] = 0xb5, 0x0a, 0xfe, 0x8f, }; +static BYTE dh_hashed_secret_prepended[] = +{ + 0x03, 0x9d, 0x31, 0x52, 0x32, 0xca, 0xfc, 0x12, 0x23, 0x2e, 0x63, 0x0b, 0x7a, 0x1c, 0xaf, 0xee, + 0x17, 0xf0, 0x7b, 0xc6, +}; + BCryptBuffer dh_hash_param_buffers[] = { { @@ -3811,6 +3881,24 @@ BCryptBuffer dh_hash_param_buffers[] = (void *)BCRYPT_SHA1_ALGORITHM, } }; +BCryptBuffer dh_hash_param_buffers_prepended[] = +{ + { + sizeof(BCRYPT_SHA1_ALGORITHM), + KDF_HASH_ALGORITHM, + (void *)BCRYPT_SHA1_ALGORITHM, + }, + { + sizeof(hash_prepend[0]), + KDF_SECRET_PREPEND, + (void *)hash_prepend[0], + }, + { + sizeof(hash_prepend[1]), + KDF_SECRET_PREPEND, + (void *)hash_prepend[1], + } +}; BCryptBufferDesc dh_hash_params = { @@ -3818,6 +3906,12 @@ BCryptBufferDesc dh_hash_params = ARRAY_SIZE(dh_hash_param_buffers), dh_hash_param_buffers, }; +BCryptBufferDesc dh_hash_params_prepended = +{ + BCRYPTBUFFER_VERSION, + ARRAY_SIZE(dh_hash_param_buffers_prepended), + dh_hash_param_buffers_prepended, +}; static void test_DH(void) { @@ -3945,6 +4039,18 @@ static void test_DH(void) ok(!memcmp(dh_secret, buf, size), "wrong data\n"); free(buf); + /* Raw secret with a BCryptBufferDesc, which is ignored */ + size = 0; + status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, &dh_hash_params_prepended, NULL, 0, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(size == 64, "got %lu\n", size); + + buf = calloc(1, size); + status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, &dh_hash_params_prepended, buf, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(!memcmp(dh_secret, buf, size), "wrong data\n"); + free(buf); + size = 0; status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, NULL, NULL, 0, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); @@ -3964,6 +4070,18 @@ static void test_DH(void) ok(!memcmp(dh_hashed_secret, buf, size), "wrong data\n"); ok(size == 20, "got %lu\n", size); + size = 0; + status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &dh_hash_params_prepended, NULL, 0, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(size == 20, "got %lu\n", size); + + buf = calloc(1, size); + status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &dh_hash_params_prepended, buf, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + todo_wine + ok(!memcmp(dh_hashed_secret_prepended, buf, size), "wrong data\n"); + ok(size == 20, "got %lu\n", size); + memset(buf, 0, 20); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &dh_hash_params, buf, 10, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11635
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/bcrypt/bcrypt_main.c | 2 ++ dlls/bcrypt/tests/bcrypt.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 22ee309ab9c..db7eec4dace 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1385,6 +1385,8 @@ static NTSTATUS create_hash( const struct algorithm *alg, UCHAR *secret, ULONG s struct hash *hash; const SYMCRYPT_HASH *desc = get_hash_from_alg( alg->id ); + if (secret && !(alg->flags & BCRYPT_ALG_HANDLE_HMAC_FLAG)) return STATUS_INVALID_PARAMETER; + if (!desc) return STATUS_NOT_IMPLEMENTED; if (!(hash = calloc( 1, sizeof(*hash) ))) return STATUS_NO_MEMORY; hash->hdr.magic = MAGIC_HASH; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 2a051ddeeac..6c43445b575 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -461,7 +461,6 @@ static void test_BcryptHash(void) /* With a secret but without BCRYPT_ALG_HANDLE_HMAC_FLAG */ ret = pBCryptHash(alg, (UCHAR *)"key", sizeof("key"), (UCHAR *)"test", sizeof("test"), md5, sizeof(md5)); - todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11635
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/bcrypt/bcrypt_main.c | 27 ++++++++++++++++++++++++++- dlls/bcrypt/tests/bcrypt.c | 2 -- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index db7eec4dace..30dddadee57 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -4168,6 +4168,7 @@ static const struct algorithm *get_hash_from_desc( const BCryptBufferDesc *desc return NULL; } } + else if (desc->pBuffers[i].BufferType == KDF_SECRET_PREPEND) continue; else FIXME( "buffer type %lu not supported\n", desc->pBuffers[i].BufferType ); } return alg; @@ -4176,6 +4177,9 @@ static const struct algorithm *get_hash_from_desc( const BCryptBufferDesc *desc static NTSTATUS derive_key_hash( const struct secret *secret, const BCryptBufferDesc *desc, UCHAR *output, ULONG output_len, ULONG *ret_len ) { + ULONG derived_key_len = secret->derived_key_len, secret_len = 0; + ULONG i, buffer_count = desc ? desc->cBuffers : 0; + UCHAR *derived_key = secret->derived_key; const struct algorithm *alg; ULONG len; UCHAR hash[MAX_HASH_OUTPUT_BYTES]; @@ -4190,7 +4194,28 @@ static NTSTATUS derive_key_hash( const struct secret *secret, const BCryptBuffer return STATUS_SUCCESS; } - if ((status = hash_single( alg, NULL, 0, secret->derived_key, secret->derived_key_len, hash ))) return status; + for (i = 0; i < buffer_count; i++) + if (desc->pBuffers[i].BufferType == KDF_SECRET_PREPEND) secret_len += desc->pBuffers[i].cbBuffer; + + if (secret_len) + { + if (!(derived_key = malloc( secret_len + derived_key_len ))) return STATUS_NO_MEMORY; + + derived_key_len = 0; + for (i = 0; i < buffer_count; i++) + { + if (desc->pBuffers[i].BufferType != KDF_SECRET_PREPEND) continue; + memcpy( derived_key + derived_key_len, desc->pBuffers[i].pvBuffer, desc->pBuffers[i].cbBuffer ); + derived_key_len += desc->pBuffers[i].cbBuffer; + } + + memcpy( derived_key + derived_key_len, secret->derived_key, secret->derived_key_len ); + derived_key_len += secret->derived_key_len; + } + + status = hash_single( alg, NULL, 0, derived_key, derived_key_len, hash ); + if (derived_key != secret->derived_key) free( derived_key ); + if (status) return status; len = min( len, output_len ); memcpy( output, hash, len ); diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 6c43445b575..fb7760a4d35 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -3522,7 +3522,6 @@ raw_secret_end: buf = malloc(size); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params_prepended, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - todo_wine ok(!(memcmp(t->hashed_secret_prepended, buf, size)), "wrong data\n"); free(buf); @@ -4077,7 +4076,6 @@ static void test_DH(void) buf = calloc(1, size); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &dh_hash_params_prepended, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - todo_wine ok(!memcmp(dh_hashed_secret_prepended, buf, size), "wrong data\n"); ok(size == 20, "got %lu\n", size); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11635
participants (2)
-
Conor McCarthy -
Conor McCarthy (@cmccarthy)