The Crew Motorsport depends on that.
ECDSA_P521 is not exactly needed in this case (only ECDH_P521) but that has a lot of common parts and probably makes sense to add at once.
WRT RSA encryption change, the game calls BCryptEncrypt(... BCRYPT_PAD_OAEP) with NULL padding info and output buffer and length, maybe trying to determine the output size this way. The failure here is fatal for that process (while then it is going to use BCRYPT_PAD_PKCS1 with the actual output buffer). Turns out on Windows that works, makes some sense because the size of RSA encrypted output depends on RSA key size only (I added a test with 0 input and no padding just in case). While for decrypt that is different as it is not possible to determine decrypted length without knowing padding algorithm.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/bcrypt_internal.h | 5 +++++ dlls/bcrypt/bcrypt_main.c | 8 ++++---- dlls/bcrypt/gnutls.c | 26 +++++++++++++------------- 3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 866232343c6..2a0f121dd0d 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -277,4 +277,9 @@ enum key_funcs unix_funcs_count, };
+static inline ULONG len_from_bitlen( ULONG bitlen ) +{ + return bitlen / 8; +} + #endif /* __BCRYPT_INTERNAL_H */ diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index dc1244aae03..afb9472f83c 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -809,7 +809,7 @@ static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *val
if (key->u.a.flags & KEY_FLAG_FINALIZED) return STATUS_INVALID_HANDLE; if (key->alg_id != ALG_ID_DH || size < sizeof(*hdr) || hdr->cbLength != size || - hdr->dwMagic != BCRYPT_DH_PARAMETERS_MAGIC || hdr->cbKeyLength != key->u.a.bitlen / 8) + hdr->dwMagic != BCRYPT_DH_PARAMETERS_MAGIC || hdr->cbKeyLength != len_from_bitlen( key->u.a.bitlen )) return STATUS_INVALID_PARAMETER;
params.key = key; @@ -1921,7 +1921,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP pubkey = (DSSPUBKEY *)(hdr + 1); if (pubkey->magic != MAGIC_DSS2) return STATUS_NOT_SUPPORTED;
- if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED)) + if (input_len < sizeof(*hdr) + sizeof(*pubkey) + len_from_bitlen( pubkey->bitlen ) * 2 + 40 + sizeof(DSSSEED)) return STATUS_INVALID_PARAMETER;
if ((status = key_asymmetric_create( alg->id, pubkey->bitlen, &key ))) return status; @@ -1954,7 +1954,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP pubkey = (DSSPUBKEY *)(hdr + 1); if (pubkey->magic != MAGIC_DSS1) return STATUS_NOT_SUPPORTED;
- size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); + size = sizeof(*hdr) + sizeof(*pubkey) + len_from_bitlen( pubkey->bitlen ) * 3 + 20 + sizeof(DSSSEED); if (input_len < size) return STATUS_INVALID_PARAMETER;
if ((status = key_asymmetric_create( alg->id, pubkey->bitlen, &key ))) return status; @@ -2628,7 +2628,7 @@ static NTSTATUS derive_key_hash( struct secret *secret, BCryptBufferDesc *desc, ULONG *ret_len ) { struct key_asymmetric_derive_key_params params; - ULONG hash_len, derived_key_len = secret->privkey->u.a.bitlen / 8; + ULONG hash_len, derived_key_len = len_from_bitlen( secret->privkey->u.a.bitlen ); UCHAR hash_buf[MAX_HASH_OUTPUT_BYTES]; struct algorithm *alg = NULL; UCHAR *derived_key; diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 582b868a36e..a8b559fef8a 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -780,7 +780,7 @@ static NTSTATUS key_export_rsa_public( struct key *key, UCHAR *buf, ULONG len, U { BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf; gnutls_datum_t m, e; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); UCHAR *dst; int ret;
@@ -887,7 +887,7 @@ static NTSTATUS key_export_dsa_public( struct key *key, UCHAR *buf, ULONG len, U { BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)buf; gnutls_datum_t p, q, g, y; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); NTSTATUS status = STATUS_SUCCESS; UCHAR *dst; int ret; @@ -956,7 +956,7 @@ static NTSTATUS key_export_dsa_capi_public( struct key *key, UCHAR *buf, ULONG l BLOBHEADER *hdr = (BLOBHEADER *)buf; DSSPUBKEY *dsskey; gnutls_datum_t p, q, g, y; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); NTSTATUS status = STATUS_SUCCESS; UCHAR *dst; int ret; @@ -1288,7 +1288,7 @@ static NTSTATUS key_export_rsa( struct key *key, ULONG flags, UCHAR *buf, ULONG { BCRYPT_RSAKEY_BLOB *rsa_blob; gnutls_datum_t m, e, d, p, q, u, e1, e2; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); BOOL full = (flags & KEY_EXPORT_FLAG_RSA_FULL); UCHAR *dst; int ret; @@ -1385,7 +1385,7 @@ static NTSTATUS key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULO BLOBHEADER *hdr; DSSPUBKEY *pubkey; gnutls_datum_t p, q, g, y, x; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); UCHAR *dst; int ret;
@@ -1458,7 +1458,7 @@ static NTSTATUS key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len ) }
pubkey = (DSSPUBKEY *)(hdr + 1); - if ((size = pubkey->bitlen / 8) > sizeof(p_data)) + if ((size = len_from_bitlen( pubkey->bitlen )) > sizeof(p_data)) { FIXME( "size %u not supported\n", size ); pgnutls_privkey_deinit( handle ); @@ -1630,7 +1630,7 @@ static NTSTATUS key_import_dsa_capi_public( struct key *key, UCHAR *buf, ULONG l
hdr = (BLOBHEADER *)buf; pubkey = (DSSPUBKEY *)(hdr + 1); - size = pubkey->bitlen / 8; + size = len_from_bitlen( pubkey->bitlen ); data = (unsigned char *)(pubkey + 1);
p.data = p_data; @@ -1667,7 +1667,7 @@ static NTSTATUS key_import_dsa_capi_public( struct key *key, UCHAR *buf, ULONG l static NTSTATUS key_export_dh_public( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len ) { BCRYPT_DH_KEY_BLOB *dh_blob = (BCRYPT_DH_KEY_BLOB *)buf; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); gnutls_dh_params_t params; gnutls_datum_t p, g, y; UCHAR *dst; @@ -1715,7 +1715,7 @@ static NTSTATUS key_export_dh( struct key *key, UCHAR *buf, ULONG len, ULONG *re BCRYPT_DH_KEY_BLOB *dh_blob = (BCRYPT_DH_KEY_BLOB *)buf; gnutls_datum_t p, g, y, x; gnutls_dh_params_t params; - ULONG size = key->u.a.bitlen / 8; + ULONG size = len_from_bitlen( key->u.a.bitlen ); UCHAR *dst; int ret;
@@ -1764,7 +1764,7 @@ static NTSTATUS key_export_dh( struct key *key, UCHAR *buf, ULONG len, ULONG *re static NTSTATUS key_export_dh_params( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len ) { BCRYPT_DH_PARAMETER_HEADER *hdr = (BCRYPT_DH_PARAMETER_HEADER *)buf; - unsigned int size = sizeof(*hdr) + key->u.a.bitlen / 8 * 2; + unsigned int size = sizeof(*hdr) + len_from_bitlen( key->u.a.bitlen ) * 2; gnutls_datum_t p, g; NTSTATUS status = STATUS_SUCCESS; UCHAR *dst; @@ -1784,7 +1784,7 @@ static NTSTATUS key_export_dh_params( struct key *key, UCHAR *buf, ULONG len, UL { hdr->cbLength = size; hdr->dwMagic = BCRYPT_DH_PARAMETERS_MAGIC; - hdr->cbKeyLength = key->u.a.bitlen / 8; + hdr->cbKeyLength = len_from_bitlen( key->u.a.bitlen );
dst = (UCHAR *)(hdr + 1); dst += export_gnutls_datum( dst, hdr->cbKeyLength, &p, 1 ); @@ -2428,7 +2428,7 @@ static NTSTATUS key_asymmetric_sign( void *args )
if (!params->output) { - *params->ret_len = key->u.a.bitlen / 8; + *params->ret_len = len_from_bitlen( key->u.a.bitlen ); return STATUS_SUCCESS; } if (!key_data(key)->a.privkey) return STATUS_INVALID_PARAMETER; @@ -2783,7 +2783,7 @@ static NTSTATUS key_asymmetric_derive_key( void *args ) return STATUS_INTERNAL_ERROR; }
- *params->ret_len = EXPORT_SIZE( s, params->privkey->u.a.bitlen / 8, 1 ); + *params->ret_len = EXPORT_SIZE( s, len_from_bitlen( params->privkey->u.a.bitlen ), 1 ); if (params->output) { if (params->output_len < *params->ret_len) status = STATUS_BUFFER_TOO_SMALL;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/bcrypt_main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index afb9472f83c..36b28b11bcd 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1736,29 +1736,29 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP if (!wcscmp( type, BCRYPT_ECCPUBLIC_BLOB )) { BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; - DWORD key_size, magic; + DWORD bitlen, magic;
if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
switch (alg->id) { case ALG_ID_ECDH_P256: - key_size = 32; + bitlen = 256; magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; break;
case ALG_ID_ECDH_P384: - key_size = 48; + bitlen = 384; magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC; break;
case ALG_ID_ECDSA_P256: - key_size = 32; + bitlen = 256; magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; break;
case ALG_ID_ECDSA_P384: - key_size = 48; + bitlen = 384; magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; break;
@@ -1768,10 +1768,10 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP }
if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; - if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2) + if (ecc_blob->cbKey != len_from_bitlen( bitlen ) || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2) return STATUS_INVALID_PARAMETER;
- if ((status = key_asymmetric_create( alg->id, key_size * 8, &key ))) return status; + if ((status = key_asymmetric_create( alg->id, bitlen, &key ))) return status; params.key = key; params.flags = KEY_IMPORT_FLAG_PUBLIC; params.buf = input; @@ -1785,24 +1785,24 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB )) { BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; - DWORD key_size, magic; + DWORD bitlen, magic;
if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
switch (alg->id) { case ALG_ID_ECDH_P256: - key_size = 32; + bitlen = 256; magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; break;
case ALG_ID_ECDH_P384: - key_size = 48; + bitlen = 384; magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC; break;
case ALG_ID_ECDSA_P256: - key_size = 32; + bitlen = 256; magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; break;
@@ -1812,10 +1812,10 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP }
if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; - if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3) + if (ecc_blob->cbKey != len_from_bitlen( bitlen ) || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3) return STATUS_INVALID_PARAMETER;
- if ((status = key_asymmetric_create( alg->id, key_size * 8, &key ))) return status; + if ((status = key_asymmetric_create( alg->id, bitlen, &key ))) return status; params.key = key; params.flags = 0; params.buf = input;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/bcrypt_main.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 36b28b11bcd..38089ba074c 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1806,6 +1806,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; break;
+ case ALG_ID_ECDSA_P384: + bitlen = 384; + magic = BCRYPT_ECDSA_PRIVATE_P384_MAGIC; + break; + default: FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); return STATUS_NOT_SUPPORTED;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/bcrypt_internal.h | 3 +- dlls/bcrypt/bcrypt_main.c | 14 +++- dlls/bcrypt/gnutls.c | 36 +++++++++- dlls/bcrypt/tests/bcrypt.c | 122 +++++++++++++++++++++++++++++++++- 4 files changed, 169 insertions(+), 6 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 2a0f121dd0d..02d55868690 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -69,6 +69,7 @@ enum alg_id ALG_ID_RSA_SIGN, ALG_ID_ECDSA_P256, ALG_ID_ECDSA_P384, + ALG_ID_ECDSA_P521, ALG_ID_DSA,
/* rng */ @@ -279,7 +280,7 @@ enum key_funcs
static inline ULONG len_from_bitlen( ULONG bitlen ) { - return bitlen / 8; + return (bitlen + 7) / 8; }
#endif /* __BCRYPT_INTERNAL_H */ diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 38089ba074c..310deddcdb6 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -121,6 +121,7 @@ builtin_algorithms[] = { 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 }, + { BCRYPT_ECDSA_P521_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 }, { BCRYPT_DSA_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 }, { BCRYPT_RNG_ALGORITHM, BCRYPT_RNG_INTERFACE, 0, 0, 0 }, { BCRYPT_PBKDF2_ALGORITHM, BCRYPT_KEY_DERIVATION_INTERFACE, 618, 0, 0 }, @@ -251,7 +252,7 @@ static const struct algorithm pseudo_algorithms[] = {{ MAGIC_ALG }, ALG_ID_DSA }, {{ MAGIC_ALG }, ALG_ID_ECDSA_P256 }, {{ MAGIC_ALG }, ALG_ID_ECDSA_P384 }, - {{ 0 }}, /* ECDSA_P512 */ + {{ MAGIC_ALG }, ALG_ID_ECDSA_P521 }, {{ MAGIC_ALG }, ALG_ID_RSA_SIGN }, };
@@ -1762,6 +1763,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; break;
+ case ALG_ID_ECDSA_P521: + bitlen = 521; + magic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC; + break; + default: FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); return STATUS_NOT_SUPPORTED; @@ -1811,6 +1817,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDSA_PRIVATE_P384_MAGIC; break;
+ case ALG_ID_ECDSA_P521: + bitlen = 521; + magic = BCRYPT_ECDSA_PRIVATE_P521_MAGIC; + break; + default: FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); return STATUS_NOT_SUPPORTED; @@ -2188,6 +2199,7 @@ static const WCHAR *resolve_blob_type( const WCHAR *type, UCHAR *input, ULONG in case BCRYPT_ECDH_PUBLIC_P384_MAGIC: case BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case BCRYPT_ECDSA_PUBLIC_P384_MAGIC: + case BCRYPT_ECDSA_PUBLIC_P521_MAGIC: return BCRYPT_ECCPUBLIC_BLOB;
case BCRYPT_RSAPUBLIC_MAGIC: diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index a8b559fef8a..1fbc3ce3062 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -845,6 +845,11 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U size = 48; break;
+ case ALG_ID_ECDSA_P521: + magic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC; + size = 66; + break; + default: FIXME( "algorithm %u not supported\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -861,7 +866,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 && curve != GNUTLS_ECC_CURVE_SECP384R1) + if (curve != GNUTLS_ECC_CURVE_SECP256R1 && curve != GNUTLS_ECC_CURVE_SECP384R1 && curve != GNUTLS_ECC_CURVE_SECP521R1) { FIXME( "curve %u not supported\n", curve ); free( x.data ); free( y.data ); @@ -1131,6 +1136,11 @@ static NTSTATUS key_asymmetric_generate( void *args ) bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP384R1 ); break;
+ case ALG_ID_ECDSA_P521: + pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */ + bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP521R1 ); + break; + default: FIXME( "algorithm %u not supported\n", key->alg_id ); return STATUS_NOT_SUPPORTED; @@ -1196,6 +1206,11 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r size = 48; break;
+ case ALG_ID_ECDSA_P521: + magic = BCRYPT_ECDSA_PRIVATE_P521_MAGIC; + size = 66; + break; + default: FIXME( "algorithm %u does not yet support exporting ecc blob\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -1209,7 +1224,7 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r return STATUS_INTERNAL_ERROR; }
- if (curve != GNUTLS_ECC_CURVE_SECP256R1 && curve != GNUTLS_ECC_CURVE_SECP384R1) + if (curve != GNUTLS_ECC_CURVE_SECP256R1 && curve != GNUTLS_ECC_CURVE_SECP384R1 && curve != GNUTLS_ECC_CURVE_SECP521R1) { FIXME( "curve %u not supported\n", curve ); free( x.data ); free( y.data ); free( d.data ); @@ -1253,6 +1268,10 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) curve = GNUTLS_ECC_CURVE_SECP384R1; break;
+ case ALG_ID_ECDSA_P521: + curve = GNUTLS_ECC_CURVE_SECP521R1; + break; + default: FIXME( "algorithm %u not yet supported\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -1518,6 +1537,9 @@ static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len ) case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break;
+ case ALG_ID_ECDSA_P521: + curve = GNUTLS_ECC_CURVE_SECP521R1; break; + default: FIXME( "algorithm %u not yet supported\n", key->alg_id ); return STATUS_NOT_IMPLEMENTED; @@ -1809,6 +1831,7 @@ static NTSTATUS key_asymmetric_export( void *args ) case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: if (flags & KEY_EXPORT_FLAG_PUBLIC) return key_export_ecc_public( key, params->buf, params->len, params->ret_len ); return key_export_ecc( key, params->buf, params->len, params->ret_len ); @@ -1995,6 +2018,7 @@ static NTSTATUS key_asymmetric_import( void *args ) case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: if (flags & KEY_IMPORT_FLAG_PUBLIC) return key_import_ecc_public( key, params->buf, params->len ); ret = key_import_ecc( key, params->buf, params->len ); @@ -2093,6 +2117,7 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO { case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: case ALG_ID_DSA: return prepare_gnutls_signature_dsa( key, signature, signature_len, gnutls_signature );
@@ -2159,6 +2184,7 @@ static NTSTATUS key_asymmetric_verify( void *args ) { case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: { if (flags) FIXME( "flags %#x not supported\n", flags );
@@ -2253,6 +2279,7 @@ static unsigned int get_signature_length( enum alg_id id ) { case ALG_ID_ECDSA_P256: return 64; case ALG_ID_ECDSA_P384: return 96; + case ALG_ID_ECDSA_P521: return 132; case ALG_ID_DSA: return 40; default: FIXME( "unhandled algorithm %u\n", id ); @@ -2275,6 +2302,7 @@ static NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signat } case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: case ALG_ID_DSA: { int err; @@ -2341,7 +2369,7 @@ static NTSTATUS key_asymmetric_sign( void *args ) NTSTATUS status; int ret;
- if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384) + if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384 || key->alg_id == ALG_ID_ECDSA_P521) { /* With ECDSA, we find the digest algorithm from the hash length, and verify it */ switch (params->input_len) @@ -2499,6 +2527,7 @@ static NTSTATUS dup_privkey( struct key *key_orig, struct key *key_copy ) case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: { gnutls_ecc_curve_t curve; gnutls_datum_t x, y, k; @@ -2578,6 +2607,7 @@ static NTSTATUS dup_pubkey( struct key *key_orig, struct key *key_copy ) case ALG_ID_ECDH_P384: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: + case ALG_ID_ECDSA_P521: { gnutls_ecc_curve_t curve; gnutls_datum_t x, y; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 2ca0eb3ab91..a834d729447 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -2195,6 +2195,27 @@ static BYTE eccPrivkey[] = 0xb9, 0xcd, 0xbe, 0xd4, 0x75, 0x5d, 0x05, 0xe5, 0x83, 0x0c, 0xd3, 0x37, 0x34, 0x15, 0xe3, 0x2c, 0xe5, 0x85, 0x15, 0xa9, 0xee, 0xba, 0x94, 0x03, 0x03, 0x0b, 0x86, 0xea, 0x85, 0x40, 0xbd, 0x35, }; +static BYTE ecc521Privkey[] = +{ + /* X */ + 0x00, 0x5f, 0xea, 0x1e, 0x01, 0xae, 0x69, 0xc3, 0x88, 0x1c, 0xbf, 0x7f, 0x86, 0x1a, 0x48, 0x20, + 0xd3, 0xba, 0xac, 0x9f, 0x1c, 0xc9, 0x99, 0xfa, 0x7d, 0x39, 0xf6, 0xe0, 0xd6, 0x92, 0x97, 0xee, + 0xf6, 0xca, 0x65, 0x40, 0x24, 0xa6, 0xf7, 0x97, 0x17, 0x8c, 0xe1, 0x81, 0x6c, 0x10, 0x92, 0xcd, + 0x41, 0xbc, 0x1c, 0xde, 0x37, 0x4a, 0x21, 0xb9, 0xbc, 0x46, 0x40, 0xa9, 0x91, 0xd9, 0x61, 0x84, + 0x15, 0x33, + /* Y */ + 0x00, 0x31, 0xde, 0xe9, 0x64, 0x9d, 0xb8, 0x43, 0x3a, 0x93, 0x5d, 0xc8, 0x82, 0xec, 0xe4, 0x7f, + 0x83, 0x8d, 0x2c, 0xc7, 0xe8, 0x24, 0x38, 0x5a, 0x81, 0x3d, 0xe6, 0x8d, 0xd4, 0xb1, 0xa0, 0x37, + 0x89, 0xae, 0x1f, 0x81, 0x23, 0x22, 0x8f, 0xd1, 0xe0, 0xc4, 0x6a, 0x99, 0xcc, 0xc8, 0xe4, 0xa0, + 0x65, 0x42, 0x9e, 0xbd, 0xaf, 0x07, 0x79, 0xe8, 0x88, 0xc2, 0xfe, 0xc0, 0x2d, 0x88, 0xd5, 0x3a, + 0xbd, 0xb1, + /* d */ + 0x00, 0x8b, 0xc5, 0xd5, 0x06, 0x3a, 0x1d, 0xd2, 0xf8, 0x26, 0x8e, 0xa2, 0xd3, 0x69, 0x5a, 0xf9, + 0xb6, 0x42, 0x8b, 0x1a, 0x9c, 0x34, 0x04, 0xa6, 0x1d, 0xfc, 0x67, 0xe5, 0x23, 0x71, 0x8e, 0xad, + 0x61, 0x45, 0x4f, 0x00, 0x3e, 0x8f, 0x61, 0xa3, 0xfb, 0xb6, 0x7a, 0x98, 0xf8, 0x27, 0x2c, 0x1b, + 0xa8, 0xda, 0xb7, 0x78, 0xe9, 0xf5, 0x9d, 0xff, 0x6a, 0x07, 0xb0, 0xe2, 0xae, 0x64, 0x15, 0x03, + 0xb3, 0x8a, +}; static BYTE eccPubkey[] = { /* X */ @@ -2218,10 +2239,22 @@ static BYTE certSignature[] = 0xe3, 0x94, 0x15, 0x3b, 0x6c, 0x71, 0x6e, 0x44, 0x22, 0xcb, 0xa0, 0x88, 0xcd, 0x0a, 0x5a, 0x50, 0x29, 0x7c, 0x5c, 0xd6, 0x6c, 0xd2, 0xe0, 0x7f, 0xcd, 0x02, 0x92, 0x21, 0x4c, 0x2c, 0x92, 0xee, }; +static BYTE cert521Signature[] = +{ + 0x01, 0x6b, 0xd6, 0xca, 0xac, 0x28, 0xa8, 0xa9, 0x83, 0x9d, 0xca, 0x13, 0x08, 0xd6, 0xf2, 0x9c, + 0x94, 0x6b, 0x28, 0x6b, 0x93, 0x58, 0x3c, 0x65, 0x54, 0xb4, 0xa6, 0xb8, 0x0d, 0x55, 0xed, 0x4e, + 0xc9, 0x98, 0x26, 0x96, 0x1a, 0xbb, 0x9f, 0x9e, 0x5c, 0xb1, 0x1e, 0x8b, 0x04, 0x82, 0xe6, 0x32, + 0x15, 0x92, 0xcb, 0xfe, 0xe7, 0x53, 0xfc, 0x17, 0xe0, 0xc9, 0x44, 0xf5, 0x1d, 0x37, 0x33, 0x02, + 0xbb, 0x75, 0x01, 0x65, 0x84, 0xab, 0x89, 0xb3, 0x69, 0x56, 0xf4, 0x18, 0xb0, 0xdd, 0xfd, 0x69, + 0xe6, 0x52, 0x1e, 0x75, 0x4f, 0x98, 0xa8, 0x49, 0x88, 0x84, 0x15, 0x58, 0x23, 0x9f, 0x89, 0x06, + 0x73, 0x6b, 0x8c, 0xf9, 0x9a, 0x85, 0x1d, 0xd2, 0xf4, 0x06, 0x65, 0xa5, 0x88, 0x12, 0xa3, 0x4e, + 0xcd, 0x99, 0x06, 0x1b, 0xf8, 0x17, 0xe0, 0xeb, 0xb8, 0x7f, 0x6b, 0x89, 0x47, 0xd2, 0x5d, 0x30, + 0xf4, 0xf6, 0x5f, 0x83, +};
static void test_ECDSA(void) { - BYTE buffer[sizeof(BCRYPT_ECCKEY_BLOB) + sizeof(eccPrivkey)]; + BYTE buffer[sizeof(BCRYPT_ECCKEY_BLOB) + sizeof(ecc521Privkey)]; BCRYPT_ECCKEY_BLOB *ecckey = (void *)buffer; BCRYPT_ALG_HANDLE alg; BCRYPT_KEY_HANDLE key; @@ -2321,6 +2354,67 @@ static void test_ECDSA(void)
BCryptDestroyKey(key); BCryptCloseAlgorithmProvider(alg, 0); + + /* P521 */ + status = BCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDSA_P521_ALGORITHM, NULL, 0); + ok(!status, "got %#lx\n", status); + + ecckey->dwMagic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC; + ecckey->cbKey = 66; + size = sizeof(BCRYPT_ECCKEY_BLOB) + ecckey->cbKey * 2; + memcpy(ecckey + 1, ecc521Privkey, ecckey->cbKey * 2); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &key, buffer, size, 0); + ok(!status, "BCryptImportKeyPair failed: %#lx\n", status); + + keylen = 0; + status = BCryptGetProperty(key, BCRYPT_KEY_STRENGTH, (UCHAR *)&keylen, sizeof(keylen), &size, 0); + ok(!status, "got %#lx\n", status); + ok(size == sizeof(keylen), "got %lu\n", size); + ok(keylen == 521, "got %lu\n", keylen); + + memset(buffer, 0xcc, sizeof(buffer)); + status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, buffer, sizeof(buffer), &size, 0); + ok(!status, "Got unexpected status %#lx\n", status); + ok(ecckey->dwMagic == BCRYPT_ECDSA_PUBLIC_P521_MAGIC, "Got unexpected magic %#lx.\n", ecckey->dwMagic); + ok(ecckey->cbKey == 66, "got %lu\n", ecckey->cbKey); + ok(!memcmp(ecckey + 1, ecc521Privkey, ecckey->cbKey * 2), "Got unexpected key data.\n"); + + memcpy(buffer, cert521Signature, sizeof(cert521Signature)); + status = BCryptVerifySignature(key, NULL, certHash, sizeof(certHash), buffer, sizeof(cert521Signature), 0); + ok(!status, "BCryptVerifySignature failed: %#lx\n", status); + + ++buffer[5]; + status = BCryptVerifySignature(key, NULL, certHash, sizeof(certHash), buffer, sizeof(cert521Signature), 0); + ok(status == STATUS_INVALID_SIGNATURE, "BCryptVerifySignature failed: %#lx\n", status); + + BCryptDestroyKey(key); + + ecckey->dwMagic = BCRYPT_ECDSA_PRIVATE_P521_MAGIC; + ecckey->cbKey = 66; + memcpy(ecckey + 1, ecc521Privkey, sizeof(ecc521Privkey)); + size = sizeof(*ecckey) + sizeof(ecc521Privkey); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPRIVATE_BLOB, &key, buffer, size, 0); + ok(!status, "BCryptImportKeyPair failed: %#lx\n", status); + + memset( buffer, 0xcc, sizeof(buffer) ); + status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, buffer, sizeof(buffer), &size, 0); + ok(!status, "Got unexpected status %#lx\n", status); + ok(ecckey->dwMagic == BCRYPT_ECDSA_PUBLIC_P521_MAGIC, "got %#lx\n", ecckey->dwMagic); + ok(ecckey->cbKey == 66, "got %lu\n", ecckey->cbKey); + ok(!memcmp(ecckey + 1, ecc521Privkey, ecckey->cbKey * 2), "Got unexpected key data.\n"); + + size = sizeof(BCRYPT_ECCKEY_BLOB) + sizeof(ecc521Privkey); + memset( buffer, 0xcc, sizeof(buffer) ); + status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, buffer, size, &size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ecckey = (BCRYPT_ECCKEY_BLOB *)buffer; + ok(ecckey->dwMagic == BCRYPT_ECDSA_PRIVATE_P521_MAGIC, "got %#lx\n", ecckey->dwMagic); + ok(ecckey->cbKey == 66, "got %lu\n", ecckey->cbKey); + ok(size == sizeof(*ecckey) + ecckey->cbKey * 3, "got %lu\n", size); + ok(!memcmp(ecckey + 1, ecc521Privkey, ecckey->cbKey * 3), "Got unexpected key data.\n"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(alg, 0); }
static UCHAR rsaPublicBlob[] = @@ -3593,6 +3687,32 @@ static void test_BCryptSignHash(void)
ret = BCryptCloseAlgorithmProvider(alg, 0); ok(!ret, "got %#lx\n", ret); + + /* ECDSA P521 */ + ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDSA_P521_ALGORITHM, NULL, 0); + ok(!ret, "got %#lx\n", ret); + + ret = BCryptGenerateKeyPair(alg, &key, 256, 0); + todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); + ret = BCryptGenerateKeyPair(alg, &key, 522, 0); + todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); + + ret = BCryptGenerateKeyPair(alg, &key, 521, 0); + ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); + ret = BCryptFinalizeKeyPair(key, 0); + ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); + len = 0; + ret = BCryptSignHash(key, NULL, hash, sizeof(hash), sig, sizeof(sig), &len, 0); + ok (!ret, "got %#lx\n", ret); + ok (len == 132, "got %lu\n", len); + + ret = BCryptVerifySignature(key, NULL, hash, sizeof(hash), sig, len, 0); + ok(!ret, "got %#lx\n", ret); + + ret = BCryptDestroyKey(key); + ok(!ret, "got %#lx\n", ret); + ret = BCryptCloseAlgorithmProvider(alg, 0); + ok(!ret, "got %#lx\n", ret); }
static void test_BCryptEnumAlgorithms(void)
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/tests/bcrypt.c | 307 +++++++++++++++++++++---------------- 1 file changed, 179 insertions(+), 128 deletions(-)
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index a834d729447..cdff79d5562 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -3103,57 +3103,38 @@ static void test_RSA_SIGN(void) ok(!ret, "BCryptCloseAlgorithmProvider failed: %#lx\n", ret); }
-static BYTE eccprivkey[] = +struct ecdh_test { - 0x45, 0x43, 0x4b, 0x32, 0x20, 0x00, 0x00, 0x00, - 0xfb, 0xbd, 0x3d, 0x20, 0x1b, 0x6d, 0x66, 0xb3, 0x7c, 0x9f, 0x89, 0xf3, 0xe4, 0x41, 0x16, 0xa5, - 0x68, 0x52, 0x77, 0xac, 0xab, 0x55, 0xb2, 0x6c, 0xb0, 0x23, 0x55, 0xcb, 0x96, 0x14, 0xfd, 0x0b, - 0x1c, 0xef, 0xdf, 0x07, 0x6d, 0x31, 0xaf, 0x39, 0xce, 0x8c, 0x8f, 0x9d, 0x75, 0xd0, 0x7b, 0xea, - 0x81, 0xdc, 0x40, 0x21, 0x1f, 0x58, 0x22, 0x5f, 0x72, 0x55, 0xfc, 0x58, 0x8a, 0xeb, 0x88, 0x5d, - 0x02, 0x09, 0x90, 0xd2, 0xe3, 0x36, 0xac, 0xfe, 0x83, 0x13, 0x6c, 0x88, 0x1a, 0xab, 0x9b, 0xdd, - 0xaa, 0x8a, 0xee, 0x69, 0x9a, 0x6a, 0x62, 0x86, 0x6a, 0x13, 0x69, 0x88, 0xb7, 0xd5, 0xa3, 0xcd -}; - -static BYTE ecdh_pubkey[] = -{ - 0x45, 0x43, 0x4b, 0x31, 0x20, 0x00, 0x00, 0x00, - 0x07, 0x61, 0x9d, 0x49, 0x63, 0x6b, 0x96, 0x94, 0xd1, 0x8f, 0xd1, 0x48, 0xcc, 0xcf, 0x72, 0x4d, - 0xff, 0x43, 0xf4, 0x97, 0x0f, 0xa3, 0x8a, 0x72, 0xe9, 0xe0, 0xba, 0x87, 0x6d, 0xc3, 0x62, 0x15, - 0xae, 0x65, 0xdd, 0x31, 0x51, 0xfc, 0x3b, 0xc9, 0x59, 0xa1, 0x0a, 0x92, 0x17, 0x2b, 0x64, 0x55, - 0x03, 0x3e, 0x62, 0x1d, 0xac, 0x3e, 0x37, 0x40, 0x6a, 0x4c, 0xb6, 0x21, 0x3f, 0x73, 0x5c, 0xf5 -}; - -/* little endian */ -static BYTE ecdh_secret[] = -{ - 0x48, 0xb0, 0x11, 0xdb, 0x69, 0x4e, 0xb4, 0xf4, 0xf5, 0x3e, 0xe1, 0x9b, 0xca, 0x00, 0x04, 0xc8, - 0x9b, 0x69, 0xaf, 0xd1, 0xaf, 0x1f, 0xc2, 0xd7, 0x83, 0x0a, 0xb7, 0xf8, 0x4f, 0x24, 0x32, 0x8e, -}; - -BCryptBuffer hash_param_buffers[] = -{ -{ - sizeof(BCRYPT_SHA1_ALGORITHM), - KDF_HASH_ALGORITHM, - (void *)BCRYPT_SHA1_ALGORITHM, -} -}; - -BCryptBufferDesc hash_params = -{ - BCRYPTBUFFER_VERSION, - ARRAY_SIZE(hash_param_buffers), - hash_param_buffers, + const WCHAR *alg; + ULONG bitlen; + BYTE *eccprivkey; + ULONG eccprivkey_len; + BYTE *ecdh_pubkey; + ULONG ecdh_pubkey_len; + BYTE *ecdh_secret; + ULONG ecdh_secret_len; + BYTE *hashed_secret; + DWORD public_magic; + DWORD private_magic; };
-static BYTE hashed_secret[] = +static void test_ECDH_alg(const struct ecdh_test *t) { - 0x1b, 0xe7, 0xbf, 0x0f, 0x65, 0x1e, 0xd0, 0x07, 0xf9, 0xf4, 0x77, 0x48, 0x48, 0x39, 0xd0, 0xf8, - 0xf3, 0xce, 0xfc, 0x89 -}; + BCryptBuffer hash_param_buffers[] = + { + { + sizeof(BCRYPT_SHA1_ALGORITHM), + KDF_HASH_ALGORITHM, + (void *)BCRYPT_SHA1_ALGORITHM, + } + };
-static void test_ECDH(void) -{ + BCryptBufferDesc hash_params = + { + BCRYPTBUFFER_VERSION, + ARRAY_SIZE(hash_param_buffers), + hash_param_buffers, + }; BYTE *buf; BCRYPT_ECCKEY_BLOB *ecckey; BCRYPT_ALG_HANDLE alg; @@ -3162,11 +3143,11 @@ static void test_ECDH(void) NTSTATUS status; ULONG size;
- status = BCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDH_P256_ALGORITHM, NULL, 0); + status = BCryptOpenAlgorithmProvider(&alg, t->alg, NULL, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status);
key = NULL; - status = BCryptGenerateKeyPair(alg, &key, 256, 0); + status = BCryptGenerateKeyPair(alg, &key, t->bitlen, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); ok(key != NULL, "key not set\n");
@@ -3182,8 +3163,8 @@ static void test_ECDH(void) 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_P256_MAGIC, "got %#lx\n", ecckey->dwMagic); - ok(ecckey->cbKey == 32, "got %lu\n", ecckey->cbKey); + ok(ecckey->dwMagic == t->public_magic, "got %#lx\n", ecckey->dwMagic); + ok(ecckey->cbKey == (t->bitlen + 7) / 8, "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); @@ -3203,8 +3184,8 @@ static void test_ECDH(void) status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); ecckey = (BCRYPT_ECCKEY_BLOB *)buf; - ok(ecckey->dwMagic == BCRYPT_ECDH_PRIVATE_P256_MAGIC, "got %#lx\n", ecckey->dwMagic); - ok(ecckey->cbKey == 32, "got %lu\n", ecckey->cbKey); + ok(ecckey->dwMagic == t->private_magic, "got %#lx\n", ecckey->dwMagic); + ok(ecckey->cbKey == (t->bitlen + 7) / 8, "got %lu\n", ecckey->cbKey); ok(size == sizeof(*ecckey) + ecckey->cbKey * 3, "got %lu\n", size);
status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPRIVATE_BLOB, &privkey, buf, size, 0); @@ -3214,7 +3195,7 @@ static void test_ECDH(void) BCryptDestroyKey(privkey); BCryptDestroyKey(key);
- status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPRIVATE_BLOB, &privkey, eccprivkey, sizeof(eccprivkey), 0); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPRIVATE_BLOB, &privkey, t->eccprivkey, t->eccprivkey_len, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status);
size = 0; @@ -3225,11 +3206,11 @@ static void test_ECDH(void) buf = malloc(size); status = BCryptExportKey(privkey, NULL, BCRYPT_ECCPRIVATE_BLOB, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - ok(size == sizeof(eccprivkey), "got %lu\n", size); - ok(!memcmp(buf, eccprivkey, size), "wrong data\n"); + ok(size == t->eccprivkey_len, "got %lu\n", size); + ok(!memcmp(buf, t->eccprivkey, size), "wrong data\n"); free(buf);
- status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &pubkey, ecdh_pubkey, sizeof(ecdh_pubkey), 0); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &pubkey, t->ecdh_pubkey, t->ecdh_pubkey_len, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status);
status = BCryptSecretAgreement(privkey, pubkey, &secret, 0); @@ -3245,11 +3226,11 @@ static void test_ECDH(void) todo_wine ok(status == STATUS_SUCCESS, "got %#lx\n", status); if (status != STATUS_SUCCESS) goto raw_secret_end;
- ok(size == 32, "size of secret key incorrect, got %lu, expected 32\n", size); + 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, NULL, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - ok(!(memcmp(ecdh_secret, buf, size)), "wrong data\n"); + ok(!(memcmp(t->ecdh_secret, buf, size)), "wrong data\n"); free(buf);
raw_secret_end: @@ -3261,7 +3242,7 @@ raw_secret_end: buf = malloc(size); status = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, &hash_params, buf, size, &size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); - ok(!(memcmp(hashed_secret, buf, size)), "wrong data\n"); + ok(!(memcmp(t->hashed_secret, buf, size)), "wrong data\n"); free(buf);
/* ulVersion is not verified */ @@ -3286,40 +3267,95 @@ derive_end: 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"); +static void test_ECDH(void) +{ + static BYTE ecc256privkey[] = + { + 0x45, 0x43, 0x4b, 0x32, 0x20, 0x00, 0x00, 0x00, + 0xfb, 0xbd, 0x3d, 0x20, 0x1b, 0x6d, 0x66, 0xb3, 0x7c, 0x9f, 0x89, 0xf3, 0xe4, 0x41, 0x16, 0xa5, + 0x68, 0x52, 0x77, 0xac, 0xab, 0x55, 0xb2, 0x6c, 0xb0, 0x23, 0x55, 0xcb, 0x96, 0x14, 0xfd, 0x0b, + 0x1c, 0xef, 0xdf, 0x07, 0x6d, 0x31, 0xaf, 0x39, 0xce, 0x8c, 0x8f, 0x9d, 0x75, 0xd0, 0x7b, 0xea, + 0x81, 0xdc, 0x40, 0x21, 0x1f, 0x58, 0x22, 0x5f, 0x72, 0x55, 0xfc, 0x58, 0x8a, 0xeb, 0x88, 0x5d, + 0x02, 0x09, 0x90, 0xd2, 0xe3, 0x36, 0xac, 0xfe, 0x83, 0x13, 0x6c, 0x88, 0x1a, 0xab, 0x9b, 0xdd, + 0xaa, 0x8a, 0xee, 0x69, 0x9a, 0x6a, 0x62, 0x86, 0x6a, 0x13, 0x69, 0x88, 0xb7, 0xd5, 0xa3, 0xcd + }; + static BYTE ecdh256_pubkey[] = + { + 0x45, 0x43, 0x4b, 0x31, 0x20, 0x00, 0x00, 0x00, + 0x07, 0x61, 0x9d, 0x49, 0x63, 0x6b, 0x96, 0x94, 0xd1, 0x8f, 0xd1, 0x48, 0xcc, 0xcf, 0x72, 0x4d, + 0xff, 0x43, 0xf4, 0x97, 0x0f, 0xa3, 0x8a, 0x72, 0xe9, 0xe0, 0xba, 0x87, 0x6d, 0xc3, 0x62, 0x15, + 0xae, 0x65, 0xdd, 0x31, 0x51, 0xfc, 0x3b, 0xc9, 0x59, 0xa1, 0x0a, 0x92, 0x17, 0x2b, 0x64, 0x55, + 0x03, 0x3e, 0x62, 0x1d, 0xac, 0x3e, 0x37, 0x40, 0x6a, 0x4c, 0xb6, 0x21, 0x3f, 0x73, 0x5c, 0xf5 + }; + static BYTE ecdh256_secret[] = + { + 0x48, 0xb0, 0x11, 0xdb, 0x69, 0x4e, 0xb4, 0xf4, 0xf5, 0x3e, 0xe1, 0x9b, 0xca, 0x00, 0x04, 0xc8, + 0x9b, 0x69, 0xaf, 0xd1, 0xaf, 0x1f, 0xc2, 0xd7, 0x83, 0x0a, 0xb7, 0xf8, 0x4f, 0x24, 0x32, 0x8e, + }; + static BYTE hashed256_secret[] = + { + 0x1b, 0xe7, 0xbf, 0x0f, 0x65, 0x1e, 0xd0, 0x07, 0xf9, 0xf4, 0x77, 0x48, 0x48, 0x39, 0xd0, 0xf8, + 0xf3, 0xce, 0xfc, 0x89 + };
- buf = malloc(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); + static BYTE ecc384privkey[] = + { + 0x45, 0x43, 0x4b, 0x34, 0x30, 0x00, 0x00, 0x00, + 0xc9, 0xcb, 0x38, 0x54, 0xa1, 0xe2, 0xb6, 0x60, 0x13, 0xd9, 0x45, 0x0d, 0x76, 0x90, 0xf9, 0x49, + 0x75, 0x81, 0x76, 0xac, 0x43, 0x96, 0xc1, 0x04, 0x04, 0xda, 0x76, 0x72, 0xb1, 0x19, 0x38, 0xbd, + 0xaf, 0x96, 0x0c, 0x4e, 0xc3, 0x29, 0x67, 0x91, 0x6c, 0xac, 0xcc, 0x33, 0x51, 0x1f, 0x82, 0xd5, + 0x17, 0xbf, 0xa2, 0x94, 0xd7, 0x15, 0x4f, 0x83, 0xe7, 0xa3, 0xb8, 0x6d, 0xd0, 0x7f, 0xbc, 0x8a, + 0x30, 0x09, 0x9e, 0x13, 0xaa, 0x2e, 0xf6, 0xde, 0x1c, 0x02, 0x4a, 0x65, 0xf6, 0x72, 0xb3, 0xf0, + 0x4f, 0x7f, 0x1a, 0xce, 0x4e, 0x94, 0xc5, 0x98, 0x89, 0x74, 0xad, 0x51, 0x8f, 0x2b, 0x25, 0x17, + 0xdc, 0x4a, 0x54, 0x8a, 0x42, 0xda, 0x30, 0x1a, 0xe3, 0x6d, 0x77, 0x4d, 0x3b, 0x33, 0x9a, 0xe3, + 0x37, 0xd4, 0x06, 0x5b, 0xb3, 0x3f, 0x73, 0xb9, 0x7e, 0x0b, 0x37, 0x02, 0x8b, 0xed, 0x08, 0x10, + 0x03, 0xf8, 0x69, 0xe3, 0x2a, 0x4f, 0xbb, 0x20, 0x6c, 0x5d, 0x24, 0x09, 0x0d, 0xd9, 0x86, 0x32, + }; + static BYTE ecdh384_pubkey[] = + { + 0x45, 0x43, 0x4b, 0x33, 0x30, 0x00, 0x00, 0x00, + 0xd6, 0xc3, 0xef, 0x4a, 0xbb, 0x4c, 0xa2, 0x27, 0xa1, 0x96, 0x03, 0x3b, 0x0a, 0x83, 0x01, 0xff, + 0xeb, 0x9a, 0xf1, 0x06, 0xee, 0x83, 0xce, 0x7c, 0xaa, 0x6b, 0x7c, 0x43, 0x1c, 0x8b, 0x30, 0x82, + 0x99, 0x8f, 0xc4, 0x86, 0x0d, 0x19, 0x16, 0xb6, 0xab, 0xd1, 0x9f, 0xeb, 0xf9, 0x31, 0xda, 0xcd, + 0xb9, 0xf8, 0xea, 0x87, 0xa1, 0x36, 0xaf, 0x10, 0x98, 0x8f, 0x9b, 0xcc, 0x6c, 0xe3, 0x24, 0xb4, + 0x82, 0x37, 0xde, 0x1e, 0x04, 0x53, 0x03, 0xc0, 0x2a, 0x41, 0xe9, 0x50, 0x07, 0x87, 0xb2, 0x60, + 0xe6, 0x32, 0x53, 0x4c, 0x8e, 0xa7, 0x80, 0x0f, 0xad, 0x25, 0x3b, 0x01, 0xa4, 0xd6, 0xe3, 0x54, + }; + static BYTE ecdh384_secret[] = + { + 0x08, 0x8c, 0xd1, 0xfa, 0x57, 0xb6, 0xf9, 0x79, 0x9e, 0x0c, 0x71, 0xc3, 0xcb, 0xa5, 0xb1, 0xfd, + 0xde, 0xbc, 0x6d, 0x7c, 0x8a, 0x5b, 0x26, 0xe8, 0x18, 0x80, 0x61, 0x45, 0x6a, 0x38, 0xf9, 0x13, + 0x2a, 0x8f, 0x4b, 0xfe, 0x75, 0x02, 0x62, 0xe9, 0xb3, 0x6e, 0xc5, 0x52, 0xc9, 0x82, 0x38, 0x53, + }; + static BYTE hashed384_secret[] = + { + 0x78, 0xf8, 0x07, 0xab, 0x00, 0x35, 0xaa, 0x8c, 0x22, 0xd0, 0xe7, 0x06, 0xfc, 0x0b, 0x74, 0x41, + 0xed, 0xdc, 0x16, 0x6c, + };
- status = BCryptImportKeyPair(alg, NULL, BCRYPT_PUBLIC_KEY_BLOB, &pubkey, buf, size, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); - BCryptDestroyKey(pubkey); + 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, + 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, + BCRYPT_ECDH_PUBLIC_P384_MAGIC, BCRYPT_ECDH_PRIVATE_P384_MAGIC, + }, + }; + unsigned int i;
- status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &pubkey, buf, size, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); - free(buf); - BCryptDestroyKey(pubkey); - BCryptCloseAlgorithmProvider(alg, 0); + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context("%s", debugstr_w(tests[i].alg)); + test_ECDH_alg(&tests[i]); + winetest_pop_context(); + } }
static BYTE dh_pubkey[] = @@ -4144,6 +4180,16 @@ static void test_SecretAgreement(void) { 0x3213db5b, 0x8cc8250b, 0xc829eaab, 0x00933709, 0x68160aa9, 0xfb9f1e20, 0xf92368e6, 0x2b8e18eb, }; + static const struct + { + const WCHAR *alg; + ULONG bitlen; + } + ecdh_algorithms[] = + { + { BCRYPT_ECDH_P256_ALGORITHM, 256 }, + { BCRYPT_ECDH_P384_ALGORITHM, 384 }, + }; static const ULONG length = 1024; BCRYPT_DH_PARAMETER_HEADER *dh_header; BCRYPT_DH_KEY_BLOB *dh_key_blob; @@ -4154,62 +4200,67 @@ static void test_SecretAgreement(void) NTSTATUS status; ULONG size, i;
- status = BCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDH_P256_ALGORITHM, NULL, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + for (i = 0; i < ARRAY_SIZE(ecdh_algorithms); ++i) + { + winetest_push_context("%s", debugstr_w(ecdh_algorithms[i].alg)); + status = BCryptOpenAlgorithmProvider(&alg, ecdh_algorithms[i].alg, NULL, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- key = NULL; - status = BCryptGenerateKeyPair(alg, &key, 256, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); - ok(key != NULL, "key not set\n"); + key = NULL; + status = BCryptGenerateKeyPair(alg, &key, ecdh_algorithms[i].bitlen, 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); + status = BCryptFinalizeKeyPair(key, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- status = BCryptSecretAgreement(NULL, key, &secret, 0); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptSecretAgreement(NULL, key, &secret, 0); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptSecretAgreement(key, NULL, &secret, 0); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptSecretAgreement(key, NULL, &secret, 0); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptSecretAgreement(key, key, NULL, 0); - ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + status = BCryptSecretAgreement(key, key, NULL, 0); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status);
- status = BCryptSecretAgreement(key, key, &secret, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = BCryptSecretAgreement(key, key, &secret, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- status = BCryptDeriveKey(NULL, L"HASH", NULL, NULL, 0, &size, 0); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptDeriveKey(NULL, L"HASH", NULL, NULL, 0, &size, 0); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptDeriveKey(key, L"HASH", NULL, NULL, 0, &size, 0); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptDeriveKey(key, L"HASH", NULL, NULL, 0, &size, 0); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptDeriveKey(secret, NULL, NULL, NULL, 0, &size, 0); - ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + status = BCryptDeriveKey(secret, NULL, NULL, NULL, 0, &size, 0); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status);
- status = BCryptDeriveKey(secret, L"HASH", NULL, NULL, 0, &size, 0); - todo_wine - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = BCryptDeriveKey(secret, L"HASH", NULL, NULL, 0, &size, 0); + todo_wine + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- status = BCryptDestroyHash(secret); - ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + status = BCryptDestroyHash(secret); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status);
- status = BCryptDestroyKey(secret); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptDestroyKey(secret); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptDestroySecret(NULL); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptDestroySecret(NULL); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptDestroySecret(alg); - ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status); + status = BCryptDestroySecret(alg); + ok(status == STATUS_INVALID_HANDLE, "got %#lx\n", status);
- status = BCryptDestroySecret(secret); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = BCryptDestroySecret(secret); + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- status = BCryptDestroyKey(key); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = BCryptDestroyKey(key); + ok(status == STATUS_SUCCESS, "got %#lx\n", status);
- status = BCryptCloseAlgorithmProvider(alg, 0); - ok(status == STATUS_SUCCESS, "got %#lx\n", status); + status = BCryptCloseAlgorithmProvider(alg, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + winetest_pop_context(); + }
/* DH */ status = BCryptOpenAlgorithmProvider(&alg, BCRYPT_DH_ALGORITHM, NULL, 0);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/bcrypt_internal.h | 1 + dlls/bcrypt/bcrypt_main.c | 14 +++++++++- dlls/bcrypt/gnutls.c | 17 ++++++++++++ dlls/bcrypt/tests/bcrypt.c | 50 +++++++++++++++++++++++++++++++++++ include/bcrypt.h | 1 + 5 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h index 02d55868690..92dc6813cfc 100644 --- a/dlls/bcrypt/bcrypt_internal.h +++ b/dlls/bcrypt/bcrypt_internal.h @@ -64,6 +64,7 @@ enum alg_id ALG_ID_DH, ALG_ID_ECDH_P256, ALG_ID_ECDH_P384, + ALG_ID_ECDH_P521,
/* signature */ ALG_ID_RSA_SIGN, diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 310deddcdb6..c3045a330a0 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -118,6 +118,7 @@ builtin_algorithms[] = { BCRYPT_DH_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_ECDH_P521_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 }, @@ -248,7 +249,7 @@ static const struct algorithm pseudo_algorithms[] = {{ 0 }}, /* ECDH */ {{ MAGIC_ALG }, ALG_ID_ECDH_P256 }, {{ MAGIC_ALG }, ALG_ID_ECDH_P384 }, - {{ 0 }}, /* ECDH_P512 */ + {{ MAGIC_ALG }, ALG_ID_ECDH_P521 }, {{ MAGIC_ALG }, ALG_ID_DSA }, {{ MAGIC_ALG }, ALG_ID_ECDSA_P256 }, {{ MAGIC_ALG }, ALG_ID_ECDSA_P384 }, @@ -1753,6 +1754,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC; break;
+ case ALG_ID_ECDH_P521: + bitlen = 521; + magic = BCRYPT_ECDH_PUBLIC_P521_MAGIC; + break; + case ALG_ID_ECDSA_P256: bitlen = 256; magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; @@ -1807,6 +1813,11 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC; break;
+ case ALG_ID_ECDH_P521: + bitlen = 521; + magic = BCRYPT_ECDH_PRIVATE_P521_MAGIC; + break; + case ALG_ID_ECDSA_P256: bitlen = 256; magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; @@ -2197,6 +2208,7 @@ static const WCHAR *resolve_blob_type( const WCHAR *type, UCHAR *input, ULONG in { case BCRYPT_ECDH_PUBLIC_P256_MAGIC: case BCRYPT_ECDH_PUBLIC_P384_MAGIC: + case BCRYPT_ECDH_PUBLIC_P521_MAGIC: case BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case BCRYPT_ECDSA_PUBLIC_P384_MAGIC: case BCRYPT_ECDSA_PUBLIC_P521_MAGIC: diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index 1fbc3ce3062..c8c901f3460 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -835,6 +835,11 @@ static NTSTATUS key_export_ecc_public( struct key *key, UCHAR *buf, ULONG len, U size = 48; break;
+ case ALG_ID_ECDH_P521: + magic = BCRYPT_ECDH_PUBLIC_P521_MAGIC; + size = 66; + break; + case ALG_ID_ECDSA_P256: magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; size = 32; @@ -1136,6 +1141,7 @@ static NTSTATUS key_asymmetric_generate( void *args ) bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP384R1 ); break;
+ case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P521: pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */ bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP521R1 ); @@ -1196,6 +1202,11 @@ static NTSTATUS key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *r size = 48; break;
+ case ALG_ID_ECDH_P521: + magic = BCRYPT_ECDH_PRIVATE_P521_MAGIC; + size = 66; + break; + case ALG_ID_ECDSA_P256: magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; size = 32; @@ -1268,6 +1279,7 @@ static NTSTATUS key_import_ecc( struct key *key, UCHAR *buf, ULONG len ) curve = GNUTLS_ECC_CURVE_SECP384R1; break;
+ case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P521: curve = GNUTLS_ECC_CURVE_SECP521R1; break; @@ -1537,6 +1549,7 @@ static NTSTATUS key_import_ecc_public( struct key *key, UCHAR *buf, ULONG len ) case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break;
+ case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P521: curve = GNUTLS_ECC_CURVE_SECP521R1; break;
@@ -1829,6 +1842,7 @@ static NTSTATUS key_asymmetric_export( void *args ) { case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P384: + case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P521: @@ -2016,6 +2030,7 @@ static NTSTATUS key_asymmetric_import( void *args ) { case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P384: + case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P521: @@ -2525,6 +2540,7 @@ static NTSTATUS dup_privkey( struct key *key_orig, struct key *key_copy ) } case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P384: + case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P521: @@ -2605,6 +2621,7 @@ static NTSTATUS dup_pubkey( struct key *key_orig, struct key *key_copy ) } case ALG_ID_ECDH_P256: case ALG_ID_ECDH_P384: + case ALG_ID_ECDH_P521: case ALG_ID_ECDSA_P256: case ALG_ID_ECDSA_P384: case ALG_ID_ECDSA_P521: diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index cdff79d5562..3ff33a1c177 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -3335,6 +3335,50 @@ static void test_ECDH(void) 0xed, 0xdc, 0x16, 0x6c, };
+ static BYTE ecc521privkey[] = + { + 0x45, 0x43, 0x4b, 0x36, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x96, 0xb0, 0x4e, 0x35, 0x6f, 0xbe, 0x00, 0xb6, 0xc3, 0x83, 0x53, 0x92, 0x18, 0xda, 0x86, + 0x9e, 0x4b, 0x0f, 0xb2, 0x0b, 0xc3, 0x9f, 0xd8, 0x9c, 0x18, 0x8a, 0x93, 0x5c, 0x91, 0xb2, 0x4f, + 0x56, 0x7d, 0x0e, 0xf7, 0xf4, 0xdf, 0x91, 0xc6, 0x74, 0x00, 0xc7, 0xb8, 0x59, 0xeb, 0x55, 0xc0, + 0xb5, 0x26, 0x7f, 0x6d, 0x49, 0x53, 0x02, 0x3b, 0x3c, 0xa0, 0x57, 0x1e, 0x1c, 0x7c, 0x5b, 0x08, + 0x23, 0x68, 0x01, 0x47, 0x4d, 0x47, 0xcf, 0x05, 0xfe, 0x18, 0x26, 0x81, 0x9d, 0xb4, 0x34, 0xfa, + 0x50, 0x7e, 0x03, 0x29, 0xa3, 0x6e, 0x90, 0x9c, 0x27, 0x69, 0x66, 0x2c, 0x70, 0x7b, 0xf9, 0xe7, + 0xef, 0xac, 0x27, 0xbf, 0x15, 0x86, 0xf6, 0xff, 0x2d, 0x99, 0x41, 0x9e, 0x36, 0x1f, 0xe9, 0x3a, + 0x99, 0x74, 0x54, 0xf3, 0xc3, 0x08, 0xb1, 0x00, 0x28, 0x84, 0x82, 0x84, 0xe3, 0xf4, 0x32, 0xfd, + 0x48, 0x67, 0xae, 0x08, 0x01, 0xe2, 0x08, 0x1d, 0xeb, 0x27, 0xc2, 0x98, 0x45, 0x8b, 0x33, 0x20, + 0x3b, 0x21, 0x5c, 0x7f, 0x56, 0xbd, 0xa5, 0x99, 0x58, 0xea, 0x19, 0xf8, 0xbc, 0xf1, 0x9e, 0x39, + 0x00, 0xb9, 0x2c, 0x2a, 0xb6, 0x19, 0x3a, 0xaf, 0xea, 0x4b, 0xa6, 0x22, 0xb4, 0x35, 0x09, 0x86, + 0x2e, 0x67, 0xe0, 0xfe, 0x81, 0x0e, 0x6a, 0x68, 0x6a, 0xb3, 0x32, 0x3b, 0xf8, 0x89, 0x45, 0x72, + 0x69, 0xf1, 0xe1, 0x84, 0xd7, 0xed, + }; + static BYTE ecdh521_pubkey[] = + { + 0x45, 0x43, 0x4b, 0x35, 0x42, 0x00, 0x00, 0x00, + 0x00, 0xfd, 0x72, 0xca, 0x31, 0x08, 0x76, 0xd9, 0x08, 0xb7, 0x26, 0x4a, 0x04, 0xbc, 0x73, 0x1a, + 0x04, 0xbb, 0x77, 0xf4, 0xe2, 0xfc, 0x3a, 0x88, 0x0a, 0xa8, 0x72, 0x8f, 0xfc, 0xe9, 0xe3, 0x5f, + 0x73, 0x05, 0xf1, 0x7f, 0x31, 0xee, 0x15, 0x91, 0x36, 0xe9, 0xeb, 0xed, 0xbe, 0x0e, 0x78, 0xa1, + 0x28, 0x4e, 0xc5, 0xcb, 0xba, 0xd8, 0x0c, 0x96, 0x75, 0x44, 0x71, 0x71, 0x00, 0x41, 0x43, 0xdf, + 0x27, 0x91, 0x00, 0x81, 0xcc, 0x56, 0x8d, 0x8e, 0x32, 0xae, 0x78, 0xfb, 0x3e, 0x84, 0x7b, 0x3b, + 0xf8, 0x8e, 0x7b, 0x27, 0x73, 0xa4, 0x11, 0x61, 0x24, 0x40, 0x9b, 0xbe, 0xd3, 0xc3, 0x0e, 0xbb, + 0x26, 0xae, 0x55, 0x58, 0xd1, 0xec, 0x14, 0xd3, 0x13, 0xf2, 0x6b, 0x2b, 0xc3, 0xf9, 0xa4, 0x50, + 0x9e, 0xce, 0xfe, 0x18, 0xa0, 0x8b, 0x10, 0x80, 0x68, 0x72, 0x2e, 0x5c, 0xa0, 0xb3, 0x01, 0x6b, + 0x43, 0x26, 0xad, 0x58, + }; + static BYTE ecdh521_secret[] = + { + 0x2d, 0xab, 0x9f, 0x38, 0x14, 0x5d, 0x49, 0x65, 0x06, 0x22, 0x04, 0xf9, 0xb3, 0x25, 0xca, 0xf9, + 0xe6, 0xdc, 0xc6, 0xe8, 0xf9, 0x0b, 0xbf, 0x3c, 0x9d, 0xf0, 0x08, 0x95, 0x92, 0xdd, 0x92, 0x8a, + 0x95, 0x85, 0xe8, 0x1c, 0x6d, 0x41, 0xb9, 0xe4, 0x7b, 0x7a, 0xa5, 0x68, 0x30, 0x48, 0x8e, 0xc0, + 0xbc, 0x2b, 0xc6, 0xe9, 0x75, 0x9c, 0xed, 0xc3, 0xf5, 0x3a, 0xa3, 0xd7, 0x41, 0xec, 0x28, 0x82, + 0xef, 0x01, + }; + static BYTE hashed521_secret[] = + { + 0x72, 0x39, 0x73, 0x5f, 0xc9, 0x26, 0x1f, 0x8e, 0xe3, 0x30, 0x11, 0xe1, 0x4f, 0xc4, 0x65, 0xc0, + 0xde, 0xf9, 0xe6, 0x6a, + }; + static const struct ecdh_test tests[] = { { @@ -3347,6 +3391,11 @@ static void test_ECDH(void) ecdh384_secret, sizeof(ecdh384_secret), hashed384_secret, 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, + BCRYPT_ECDH_PUBLIC_P521_MAGIC, BCRYPT_ECDH_PRIVATE_P521_MAGIC, + }, }; unsigned int i;
@@ -4189,6 +4238,7 @@ static void test_SecretAgreement(void) { { BCRYPT_ECDH_P256_ALGORITHM, 256 }, { BCRYPT_ECDH_P384_ALGORITHM, 384 }, + { BCRYPT_ECDH_P521_ALGORITHM, 521 }, }; static const ULONG length = 1024; BCRYPT_DH_PARAMETER_HEADER *dh_header; diff --git a/include/bcrypt.h b/include/bcrypt.h index b7d6c161467..bb6ed5c1625 100644 --- a/include/bcrypt.h +++ b/include/bcrypt.h @@ -91,6 +91,7 @@ typedef LONG NTSTATUS; #define BCRYPT_DSA_ALGORITHM L"DSA" #define BCRYPT_ECDH_P256_ALGORITHM L"ECDH_P256" #define BCRYPT_ECDH_P384_ALGORITHM L"ECDH_P384" +#define BCRYPT_ECDH_P521_ALGORITHM L"ECDH_P521" #define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256" #define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384" #define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521"
From: Paul Gofman pgofman@codeweavers.com
--- dlls/bcrypt/gnutls.c | 7 +++++++ dlls/bcrypt/tests/bcrypt.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c index c8c901f3460..78f30dc7c83 100644 --- a/dlls/bcrypt/gnutls.c +++ b/dlls/bcrypt/gnutls.c @@ -2777,6 +2777,13 @@ static NTSTATUS key_asymmetric_encrypt( void *args )
if (!key_data(params->key)->a.pubkey) return STATUS_INVALID_HANDLE;
+ if (params->key->alg_id == ALG_ID_RSA + && (!params->output || len_from_bitlen( params->key->u.a.bitlen ) > params->output_len)) + { + *params->ret_len = len_from_bitlen( params->key->u.a.bitlen ); + return !params->output ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL; + } + if (params->key->alg_id == ALG_ID_RSA && params->flags & BCRYPT_PAD_OAEP) { BCRYPT_OAEP_PADDING_INFO *pad = params->padding; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 3ff33a1c177..9a0fdf1f6b9 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -2614,6 +2614,12 @@ static void test_rsa_encrypt(void) /* No padding */ todo_wine { memset(input_no_padding, 0, sizeof(input_no_padding)); + + encrypted_size = 0; + ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_NONE); + ok(ret == STATUS_SUCCESS, "got %lx\n", ret); + ok(encrypted_size == 64, "got size of %ld\n", encrypted_size); + strcpy((char *)input_no_padding, "Hello World"); encrypted_size = 0; ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_NONE); @@ -2709,26 +2715,45 @@ static void test_rsa_encrypt(void) ret = BCryptFinalizeKeyPair(key, 0); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
- todo_wine { encrypted_size = 0; ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_OAEP); ok(ret == STATUS_SUCCESS, "got %lx\n", ret); ok(encrypted_size == 80, "got size of %ld\n", encrypted_size);
+ encrypted_size = 0; + ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_OAEP); + ok(ret == STATUS_SUCCESS, "got %lx\n", ret); + ok(encrypted_size == 80, "got size of %ld\n", encrypted_size); + encrypted_a = realloc(encrypted_a, encrypted_size); memset(encrypted_a, 0, encrypted_size); encrypted_b = realloc(encrypted_b, encrypted_size); memset(encrypted_b, 0, encrypted_size);
- ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, encrypted_a, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP); + ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, NULL, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP); ok(ret == STATUS_SUCCESS, "got %lx\n", ret); ok(encrypted_size == 80, "got size of %ld\n", encrypted_size);
+ encrypted_size = 0; + ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, encrypted_a, 0, &encrypted_size, BCRYPT_PAD_OAEP); + ok(ret == STATUS_BUFFER_TOO_SMALL, "got %lx\n", ret); + ok(encrypted_size == 80, "got size of %ld\n", encrypted_size); + + ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, encrypted_a, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP); + todo_wine ok(ret == STATUS_SUCCESS, "got %lx\n", ret); + ok(encrypted_size == 80, "got size of %ld\n", encrypted_size); + ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, encrypted_b, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP); - ok(ret == STATUS_SUCCESS, "got %lx\n", ret); + todo_wine ok(ret == STATUS_SUCCESS, "got %lx\n", ret); ok(encrypted_size == 80, "got size of %ld\n", encrypted_size); - ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n"); + todo_wine ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n"); + + decrypted_size = 0; + memset(decrypted, 0, sizeof(decrypted)); + ret = BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_OAEP); + ok(ret == STATUS_INVALID_PARAMETER, "got %lx\n", ret);
+ todo_wine { decrypted_size = 0; memset(decrypted, 0, sizeof(decrypted)); ret = BCryptDecrypt(key, encrypted_a, encrypted_size, &oaep_pad, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_OAEP);