Commit 5253c8d7 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

bcrypt: Support ECDH_P384 key import/export.

parent 8eb7843d
......@@ -132,6 +132,7 @@ enum alg_id
/* secret agreement */
ALG_ID_ECDH_P256,
ALG_ID_ECDH_P384,
/* signature */
ALG_ID_RSA_SIGN,
......
......@@ -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;
......
......@@ -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:
{
......
......@@ -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)
......
......@@ -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"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment