From: Hans Leidekker hans@codeweavers.com
--- dlls/bcrypt/bcrypt_internal.h | 1 + dlls/bcrypt/bcrypt_main.c | 13 ++++++++ dlls/bcrypt/gnutls.c | 47 ++++++++++++++++++++++++++-- dlls/bcrypt/tests/bcrypt.c | 58 +++++++++++++++++++++++------------ include/bcrypt.h | 1 + 5 files changed, 98 insertions(+), 22 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 76924804cfa..a418642382b 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -132,6 +132,7 @@ enum alg_id
/* secret agreement */ ALG_ID_ECDH_P256, + ALG_ID_ECDH_P384,
/* signature */ ALG_ID_RSA_SIGN, diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 5a3fefd2b51..fc39197e067 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -115,6 +115,7 @@ builtin_algorithms[] = { BCRYPT_MD2_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 128 }, { BCRYPT_RSA_ALGORITHM, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE, 0, 0, 0 }, { BCRYPT_ECDH_P256_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 }, + { BCRYPT_ECDH_P384_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 }, { BCRYPT_RSA_SIGN_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 }, { BCRYPT_ECDSA_P256_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 }, { BCRYPT_ECDSA_P384_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 }, @@ -1356,6 +1357,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; break;
+ case ALG_ID_ECDH_P384: + key_size = 48; + magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC; + break; + case ALG_ID_ECDSA_P256: key_size = 32; magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; @@ -1402,6 +1408,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP key_size = 32; magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; break; + + case ALG_ID_ECDH_P384: + key_size = 48; + magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC; + break; + case ALG_ID_ECDSA_P256: key_size = 32; magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; @@ -1799,6 +1811,7 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN switch (key_blob->Magic) { case BCRYPT_ECDH_PUBLIC_P256_MAGIC: + case BCRYPT_ECDH_PUBLIC_P384_MAGIC: case BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case BCRYPT_ECDSA_PUBLIC_P384_MAGIC: type = BCRYPT_ECCPUBLIC_BLOB; diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 64a7a195527..f06f39559dc 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -718,10 +718,22 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; size = 32; break; + + case ALG_ID_ECDH_P384: + magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC; + size = 48; + break; + case ALG_ID_ECDSA_P256: magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; size = 32; break; + + case ALG_ID_ECDSA_P384: + magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; + size = 48; + break; + default: FIXME( "algorithm %u not supported\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -740,7 +752,7 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U return STATUS_INTERNAL_ERROR; }
- if (curve != GNUTLS_ECC_CURVE_SECP256R1) + if (curve != GNUTLS_ECC_CURVE_SECP256R1 && curve != GNUTLS_ECC_CURVE_SECP384R1) { FIXME( "curve %u not supported\n", curve ); free( x.data ); free( y.data ); @@ -923,6 +935,12 @@ static NTSTATUS key_asymmetric_generate( void *args ) bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 ); break;
+ case ALG_ID_ECDH_P384: + case ALG_ID_ECDSA_P384: + pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */ + bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP384R1 ); + break; + default: FIXME( "algorithm %u not supported\n", key->alg_id ); return STATUS_NOT_SUPPORTED; @@ -975,11 +993,22 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; size = 32; break; + + case ALG_ID_ECDH_P384: + magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC; + size = 48; + break; + case ALG_ID_ECDSA_P256: magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; size = 32; break;
+ case ALG_ID_ECDSA_P384: + magic = BCRYPT_ECDSA_PRIVATE_P384_MAGIC; + size = 48; + break; + default: FIXME( "algorithm %u does not yet support exporting ecc blob\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -1036,6 +1065,11 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) curve = GNUTLS_ECC_CURVE_SECP256R1; break;
+ case ALG_ID_ECDH_P384: + case ALG_ID_ECDSA_P384: + curve = GNUTLS_ECC_CURVE_SECP384R1; + break; + default: FIXME( "algorithm %u not yet supported\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -1290,8 +1324,12 @@ static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len ) switch (key->alg_id) { case ALG_ID_ECDH_P256: - case ALG_ID_ECDSA_P256: curve = GNUTLS_ECC_CURVE_SECP256R1; break; - case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break; + case ALG_ID_ECDSA_P256: + curve = GNUTLS_ECC_CURVE_SECP256R1; break; + + case ALG_ID_ECDH_P384: + case ALG_ID_ECDSA_P384: + curve = GNUTLS_ECC_CURVE_SECP384R1; break;
default: FIXME( "algorithm %u not yet supported\n", key->alg_id ); @@ -1448,6 +1486,7 @@ static NTSTATUS key_asymmetric_export( void *args ) switch (key->alg_id) { case ALG_ID_ECDH_P256: + case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: if (flags & KEY_EXPORT_FLAG_PUBLIC) @@ -1486,6 +1525,7 @@ static NTSTATUS key_asymmetric_import( void *args ) switch (key->alg_id) { case ALG_ID_ECDH_P256: + case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: if (flags & KEY_IMPORT_FLAG_PUBLIC) @@ -1880,6 +1920,7 @@ static NTSTATUS key_asymmetric_duplicate( void *args ) break; } case ALG_ID_ECDH_P256: + case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: { diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index a72849fb4e9..a438d7626ad 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -2728,11 +2728,7 @@ static void test_ECDH(void)
status = BCryptSecretAgreement(privkey, pubkey, &secret, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - - if (status != STATUS_SUCCESS) - { - goto derive_end; - } + if (status != STATUS_SUCCESS) goto derive_end;
/* verify result on windows 10 */ status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, NULL, NULL, 0, &size, 0); @@ -2744,11 +2740,7 @@ static void test_ECDH(void) }
todo_wine ok(status == STATUS_SUCCESS, "got %#lx\n", status); - - if (status != STATUS_SUCCESS) - { - goto raw_secret_end; - } + if (status != STATUS_SUCCESS) goto raw_secret_end;
ok(size == 32, "size of secret key incorrect, got %lu, expected 32\n", size); buf = HeapAlloc(GetProcessHeap(), 0, size); @@ -2757,15 +2749,10 @@ static void test_ECDH(void) ok(!(memcmp(ecdh_secret, buf, size)), "wrong data\n"); HeapFree(GetProcessHeap(), 0, buf);
- raw_secret_end: - +raw_secret_end: status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); todo_wine ok (status == STATUS_SUCCESS, "got %#lx\n", status); - - if (status != STATUS_SUCCESS) - { - goto derive_end; - } + if (status != STATUS_SUCCESS) goto derive_end;
ok (size == 20, "got %lu\n", size); buf = HeapAlloc(GetProcessHeap(), 0, size); @@ -2791,12 +2778,45 @@ static void test_ECDH(void) status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); ok (status == STATUS_NOT_SUPPORTED, "got %#lx\n", status);
- derive_end: - +derive_end: BCryptDestroySecret(secret); BCryptDestroyKey(pubkey); BCryptDestroyKey(privkey); BCryptCloseAlgorithmProvider(alg, 0); + + status = BCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDH_P384_ALGORITHM, NULL, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + + key = NULL; + status = BCryptGenerateKeyPair(alg, &key, 384, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(key != NULL, "key not set\n"); + + status = BCryptFinalizeKeyPair(key, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + + size = 0; + status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(size, "size not set\n"); + + buf = HeapAlloc(GetProcessHeap(), 0, size); + status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, buf, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ecckey = (BCRYPT_ECCKEY_BLOB *)buf; + ok(ecckey->dwMagic == BCRYPT_ECDH_PUBLIC_P384_MAGIC, "got %#lx\n", ecckey->dwMagic); + ok(ecckey->cbKey == 48, "got %lu\n", ecckey->cbKey); + ok(size == sizeof(*ecckey) + ecckey->cbKey * 2, "got %lu\n", size); + + status = BCryptImportKeyPair(alg, NULL, BCRYPT_PUBLIC_KEY_BLOB, &pubkey, buf, size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + BCryptDestroyKey(pubkey); + + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &pubkey, buf, size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + HeapFree(GetProcessHeap(), 0, buf); + BCryptDestroyKey(pubkey); + BCryptCloseAlgorithmProvider(alg, 0); }
static void test_BCryptEnumContextFunctions(void) diff --git a/include/bcrypt.h b/include/bcrypt.h index fd660c1843c..ba44c01bbc9 100644 --- a/include/bcrypt.h +++ b/include/bcrypt.h @@ -84,6 +84,7 @@ typedef LONG NTSTATUS; #define BCRYPT_DES_ALGORITHM L"DES" #define BCRYPT_DSA_ALGORITHM L"DSA" #define BCRYPT_ECDH_P256_ALGORITHM L"ECDH_P256" +#define BCRYPT_ECDH_P384_ALGORITHM L"ECDH_P384" #define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256" #define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384" #define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521"