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 ...@@ -132,6 +132,7 @@ enum alg_id
/* secret agreement */ /* secret agreement */
ALG_ID_ECDH_P256, ALG_ID_ECDH_P256,
ALG_ID_ECDH_P384,
/* signature */ /* signature */
ALG_ID_RSA_SIGN, ALG_ID_RSA_SIGN,
......
...@@ -115,6 +115,7 @@ builtin_algorithms[] = ...@@ -115,6 +115,7 @@ builtin_algorithms[] =
{ BCRYPT_MD2_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 128 }, { BCRYPT_MD2_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 128 },
{ BCRYPT_RSA_ALGORITHM, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE, 0, 0, 0 }, { BCRYPT_RSA_ALGORITHM, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE, 0, 0, 0 },
{ BCRYPT_ECDH_P256_ALGORITHM, BCRYPT_SECRET_AGREEMENT_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_RSA_SIGN_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
{ BCRYPT_ECDSA_P256_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 }, { 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 ...@@ -1356,6 +1357,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
break; break;
case ALG_ID_ECDH_P384:
key_size = 48;
magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
break;
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
key_size = 32; key_size = 32;
magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
...@@ -1402,6 +1408,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP ...@@ -1402,6 +1408,12 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
key_size = 32; key_size = 32;
magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
break; break;
case ALG_ID_ECDH_P384:
key_size = 48;
magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC;
break;
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
key_size = 32; key_size = 32;
magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC;
...@@ -1799,6 +1811,7 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN ...@@ -1799,6 +1811,7 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN
switch (key_blob->Magic) switch (key_blob->Magic)
{ {
case BCRYPT_ECDH_PUBLIC_P256_MAGIC: case BCRYPT_ECDH_PUBLIC_P256_MAGIC:
case BCRYPT_ECDH_PUBLIC_P384_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P384_MAGIC: case BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
type = BCRYPT_ECCPUBLIC_BLOB; type = BCRYPT_ECCPUBLIC_BLOB;
......
...@@ -718,10 +718,22 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U ...@@ -718,10 +718,22 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U
magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
size = 32; size = 32;
break; break;
case ALG_ID_ECDH_P384:
magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
size = 48;
break;
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
size = 32; size = 32;
break; break;
case ALG_ID_ECDSA_P384:
magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
size = 48;
break;
default: default:
FIXME( "algorithm %u not supported\n", key->alg_id ); FIXME( "algorithm %u not supported\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
...@@ -740,7 +752,7 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U ...@@ -740,7 +752,7 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U
return STATUS_INTERNAL_ERROR; 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 ); FIXME( "curve %u not supported\n", curve );
free( x.data ); free( y.data ); free( x.data ); free( y.data );
...@@ -923,6 +935,12 @@ static NTSTATUS key_asymmetric_generate( void *args ) ...@@ -923,6 +935,12 @@ static NTSTATUS key_asymmetric_generate( void *args )
bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 ); bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
break; 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: default:
FIXME( "algorithm %u not supported\n", key->alg_id ); FIXME( "algorithm %u not supported\n", key->alg_id );
return STATUS_NOT_SUPPORTED; return STATUS_NOT_SUPPORTED;
...@@ -975,11 +993,22 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r ...@@ -975,11 +993,22 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r
magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
size = 32; size = 32;
break; break;
case ALG_ID_ECDH_P384:
magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC;
size = 48;
break;
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC;
size = 32; size = 32;
break; break;
case ALG_ID_ECDSA_P384:
magic = BCRYPT_ECDSA_PRIVATE_P384_MAGIC;
size = 48;
break;
default: default:
FIXME( "algorithm %u does not yet support exporting ecc blob\n", key->alg_id ); FIXME( "algorithm %u does not yet support exporting ecc blob\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
...@@ -1036,6 +1065,11 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) ...@@ -1036,6 +1065,11 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
curve = GNUTLS_ECC_CURVE_SECP256R1; curve = GNUTLS_ECC_CURVE_SECP256R1;
break; break;
case ALG_ID_ECDH_P384:
case ALG_ID_ECDSA_P384:
curve = GNUTLS_ECC_CURVE_SECP384R1;
break;
default: default:
FIXME( "algorithm %u not yet supported\n", key->alg_id ); FIXME( "algorithm %u not yet supported\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
...@@ -1290,8 +1324,12 @@ static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len ) ...@@ -1290,8 +1324,12 @@ static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len )
switch (key->alg_id) switch (key->alg_id)
{ {
case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P256:
case ALG_ID_ECDSA_P256: curve = GNUTLS_ECC_CURVE_SECP256R1; break; case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break; curve = GNUTLS_ECC_CURVE_SECP256R1; break;
case ALG_ID_ECDH_P384:
case ALG_ID_ECDSA_P384:
curve = GNUTLS_ECC_CURVE_SECP384R1; break;
default: default:
FIXME( "algorithm %u not yet supported\n", key->alg_id ); FIXME( "algorithm %u not yet supported\n", key->alg_id );
...@@ -1448,6 +1486,7 @@ static NTSTATUS key_asymmetric_export( void *args ) ...@@ -1448,6 +1486,7 @@ static NTSTATUS key_asymmetric_export( void *args )
switch (key->alg_id) switch (key->alg_id)
{ {
case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P256:
case ALG_ID_ECDH_P384:
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P384:
if (flags & KEY_EXPORT_FLAG_PUBLIC) if (flags & KEY_EXPORT_FLAG_PUBLIC)
...@@ -1486,6 +1525,7 @@ static NTSTATUS key_asymmetric_import( void *args ) ...@@ -1486,6 +1525,7 @@ static NTSTATUS key_asymmetric_import( void *args )
switch (key->alg_id) switch (key->alg_id)
{ {
case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P256:
case ALG_ID_ECDH_P384:
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P384:
if (flags & KEY_IMPORT_FLAG_PUBLIC) if (flags & KEY_IMPORT_FLAG_PUBLIC)
...@@ -1880,6 +1920,7 @@ static NTSTATUS key_asymmetric_duplicate( void *args ) ...@@ -1880,6 +1920,7 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
break; break;
} }
case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P256:
case ALG_ID_ECDH_P384:
case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P384:
{ {
......
...@@ -2728,11 +2728,7 @@ static void test_ECDH(void) ...@@ -2728,11 +2728,7 @@ static void test_ECDH(void)
status = BCryptSecretAgreement(privkey, pubkey, &secret, 0); status = BCryptSecretAgreement(privkey, pubkey, &secret, 0);
ok(status == STATUS_SUCCESS, "got %#lx\n", status); 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 */ /* verify result on windows 10 */
status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, NULL, NULL, 0, &size, 0); status = BCryptDeriveKey(secret, BCRYPT_KDF_RAW_SECRET, NULL, NULL, 0, &size, 0);
...@@ -2744,11 +2740,7 @@ static void test_ECDH(void) ...@@ -2744,11 +2740,7 @@ static void test_ECDH(void)
} }
todo_wine ok(status == STATUS_SUCCESS, "got %#lx\n", status); 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); ok(size == 32, "size of secret key incorrect, got %lu, expected 32\n", size);
buf = HeapAlloc(GetProcessHeap(), 0, size); buf = HeapAlloc(GetProcessHeap(), 0, size);
...@@ -2757,15 +2749,10 @@ static void test_ECDH(void) ...@@ -2757,15 +2749,10 @@ static void test_ECDH(void)
ok(!(memcmp(ecdh_secret, buf, size)), "wrong data\n"); ok(!(memcmp(ecdh_secret, buf, size)), "wrong data\n");
HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, buf);
raw_secret_end: raw_secret_end:
status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0);
todo_wine ok (status == STATUS_SUCCESS, "got %#lx\n", status); 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); ok (size == 20, "got %lu\n", size);
buf = HeapAlloc(GetProcessHeap(), 0, size); buf = HeapAlloc(GetProcessHeap(), 0, size);
...@@ -2791,12 +2778,45 @@ static void test_ECDH(void) ...@@ -2791,12 +2778,45 @@ static void test_ECDH(void)
status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, NULL, 0, &size, 0);
ok (status == STATUS_NOT_SUPPORTED, "got %#lx\n", status); ok (status == STATUS_NOT_SUPPORTED, "got %#lx\n", status);
derive_end: derive_end:
BCryptDestroySecret(secret); BCryptDestroySecret(secret);
BCryptDestroyKey(pubkey); BCryptDestroyKey(pubkey);
BCryptDestroyKey(privkey); BCryptDestroyKey(privkey);
BCryptCloseAlgorithmProvider(alg, 0); 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) static void test_BCryptEnumContextFunctions(void)
......
...@@ -84,6 +84,7 @@ typedef LONG NTSTATUS; ...@@ -84,6 +84,7 @@ typedef LONG NTSTATUS;
#define BCRYPT_DES_ALGORITHM L"DES" #define BCRYPT_DES_ALGORITHM L"DES"
#define BCRYPT_DSA_ALGORITHM L"DSA" #define BCRYPT_DSA_ALGORITHM L"DSA"
#define BCRYPT_ECDH_P256_ALGORITHM L"ECDH_P256" #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_P256_ALGORITHM L"ECDSA_P256"
#define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384" #define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384"
#define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521" #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