diff --git a/Libraries/LibCrypto/Curves/SECPxxxr1.h b/Libraries/LibCrypto/Curves/SECPxxxr1.h index c109deaf85a..593a8a8e14c 100644 --- a/Libraries/LibCrypto/Curves/SECPxxxr1.h +++ b/Libraries/LibCrypto/Curves/SECPxxxr1.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, Michiel Visser - * Copyright (c) 2024, Altomani Gianluca + * Copyright (c) 2024-2025, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,14 +11,17 @@ #include #include #include -#include #include #include #include #include #include #include -#include +#include + +#include +#include +#include namespace { // Used by ASN1 macros @@ -28,6 +31,7 @@ static String s_error_string; namespace Crypto::Curves { struct SECPxxxr1CurveParameters { + char const* name; StringView prime; StringView a; StringView b; @@ -230,31 +234,54 @@ public: ErrorOr generate_private_key() override { + auto key = TRY(generate_private_key_scalar()); + auto buffer = TRY(ByteBuffer::create_uninitialized(KEY_BYTE_SIZE)); - fill_with_secure_random(buffer); - return buffer; + auto buffer_bytes = buffer.bytes(); + auto size = key.export_data(buffer_bytes); + return buffer.slice(0, size); } ErrorOr generate_private_key_scalar() { - auto buffer = TRY(generate_private_key()); - return UnsignedBigInteger::import_data(buffer.data(), buffer.size()); + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, "EC", CURVE_PARAMETERS.name))); + + auto priv_bn = TRY(OpenSSL_BN::create()); + auto* priv_bn_ptr = priv_bn.ptr(); + OPENSSL_TRY(EVP_PKEY_get_bn_param(key.ptr(), OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn_ptr)); + + return TRY(openssl_bignum_to_unsigned_big_integer(priv_bn)); } ErrorOr generate_public_key(ReadonlyBytes a) override { - return compute_coordinate(a, GENERATOR_POINT); + auto a_int = UnsignedBigInteger::import_data(a); + auto point = TRY(generate_public_key_point(a_int)); + return point.to_uncompressed(); } ErrorOr generate_public_key_point(UnsignedBigInteger scalar) { - VERIFY(scalar.byte_length() >= KEY_BYTE_SIZE); + auto* group = EC_GROUP_new_by_curve_name(EC_curve_nist2nid(CURVE_PARAMETERS.name)); + ScopeGuard const free_group = [&] { EC_GROUP_free(group); }; - return compute_coordinate_point(scalar, SECPxxxr1Point { - UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1, KEY_BYTE_SIZE), - UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1 + KEY_BYTE_SIZE, KEY_BYTE_SIZE), - KEY_BYTE_SIZE, - }); + auto scalar_int = TRY(unsigned_big_integer_to_openssl_bignum(scalar)); + + auto* r = EC_POINT_new(group); + ScopeGuard const free_r = [&] { EC_POINT_free(r); }; + + OPENSSL_TRY(EC_POINT_mul(group, r, scalar_int.ptr(), nullptr, nullptr, nullptr)); + + auto x = TRY(OpenSSL_BN::create()); + auto y = TRY(OpenSSL_BN::create()); + + OPENSSL_TRY(EC_POINT_get_affine_coordinates(group, r, x.ptr(), y.ptr(), nullptr)); + + return SECPxxxr1Point { + TRY(openssl_bignum_to_unsigned_big_integer(x)), + TRY(openssl_bignum_to_unsigned_big_integer(y)), + KEY_BYTE_SIZE, + }; } ErrorOr compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override @@ -872,6 +899,7 @@ private: // SECP256r1 curve static constexpr SECPxxxr1CurveParameters SECP256r1_CURVE_PARAMETERS { + .name = "P-256", .prime = "FFFFFFFF_00000001_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF"sv, .a = "FFFFFFFF_00000001_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFC"sv, .b = "5AC635D8_AA3A93E7_B3EBBD55_769886BC_651D06B0_CC53B0F6_3BCE3C3E_27D2604B"sv, @@ -882,6 +910,7 @@ using SECP256r1 = SECPxxxr1<256, SECP256r1_CURVE_PARAMETERS>; // SECP384r1 curve static constexpr SECPxxxr1CurveParameters SECP384r1_CURVE_PARAMETERS { + .name = "P-384", .prime = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFFFF_00000000_00000000_FFFFFFFF"sv, .a = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFFFF_00000000_00000000_FFFFFFFC"sv, .b = "B3312FA7_E23EE7E4_988E056B_E3F82D19_181D9C6E_FE814112_0314088F_5013875A_C656398D_8A2ED19D_2A85C8ED_D3EC2AEF"sv, @@ -892,6 +921,7 @@ using SECP384r1 = SECPxxxr1<384, SECP384r1_CURVE_PARAMETERS>; // SECP521r1 curve static constexpr SECPxxxr1CurveParameters SECP521r1_CURVE_PARAMETERS { + .name = "P-521", .prime = "01FF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF"sv, .a = "01FF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFC"sv, .b = "0051_953EB961_8E1C9A1F_929A21A0_B68540EE_A2DA725B_99B315F3_B8B48991_8EF109E1_56193951_EC7E937B_1652C0BD_3BB1BF07_3573DF88_3D2C34F1_EF451FD4_6B503F00"sv, diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_bits.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_bits.https.any.txt index 53aee5e7a5b..f692baf5159 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_bits.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_bits.https.any.txt @@ -2,8 +2,8 @@ Harness status: OK Found 40 tests -35 Pass -5 Fail +36 Pass +4 Fail Pass setup - define tests Fail P-521 good parameters Fail P-521 mixed case parameters @@ -12,7 +12,7 @@ Fail P-521 non-multiple of 8 bits Pass P-521 missing public curve Pass P-521 public property of algorithm is not a CryptoKey Pass P-521 mismatched curves -Fail P-521 public property of algorithm is not an ECDSA public key +Pass P-521 public property of algorithm is not an ECDSA public key Pass P-521 no deriveBits usage for base key Pass P-521 base key is not a private key Pass P-521 public property value is a private key diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_keys.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_keys.https.any.txt index a56378b1a7d..340876a8a79 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_keys.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/derive_bits_keys/ecdh_keys.https.any.txt @@ -2,15 +2,15 @@ Harness status: OK Found 31 tests -28 Pass -3 Fail +29 Pass +2 Fail Pass setup - define tests Fail P-521 good parameters Fail P-521 mixed case parameters Pass P-521 missing public curve Pass P-521 public property of algorithm is not a CryptoKey Pass P-521 mismatched curves -Fail P-521 public property of algorithm is not an ECDSA public key +Pass P-521 public property of algorithm is not an ECDSA public key Pass P-521 no deriveKey usage for base key Pass P-521 base key is not a private key Pass P-521 public property value is a private key diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt index eae1caced6b..be1443a5cfa 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt @@ -2,8 +2,7 @@ Harness status: OK Found 476 tests -474 Pass -2 Fail +476 Pass Pass Bad algorithm: generateKey(AES, false, [decrypt]) Pass Bad algorithm: generateKey(AES, true, [decrypt]) Pass Bad algorithm: generateKey(AES, RED, [decrypt]) @@ -478,5 +477,5 @@ Pass Empty usages: generateKey({name: ECDH, namedCurve: P-256}, false, []) Pass Empty usages: generateKey({name: ECDH, namedCurve: P-256}, true, []) Pass Empty usages: generateKey({name: ECDH, namedCurve: P-384}, false, []) Pass Empty usages: generateKey({name: ECDH, namedCurve: P-384}, true, []) -Fail Empty usages: generateKey({name: ECDH, namedCurve: P-521}, false, []) -Fail Empty usages: generateKey({name: ECDH, namedCurve: P-521}, true, []) \ No newline at end of file +Pass Empty usages: generateKey({name: ECDH, namedCurve: P-521}, false, []) +Pass Empty usages: generateKey({name: ECDH, namedCurve: P-521}, true, []) \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt index ea1d0d16914..f95f24f85d7 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt @@ -2,8 +2,7 @@ Harness status: OK Found 72 tests -48 Pass -24 Fail +72 Pass Pass Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveKey]) Pass Success: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey]) Pass Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveBits, deriveKey]) @@ -20,14 +19,14 @@ Pass Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveBits]) Pass Success: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits]) Pass Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) Pass Success: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveKey]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveBits]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveKey]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveBits]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Success: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) Pass Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveKey]) Pass Success: generateKey({name: ecdh, namedCurve: P-256}, true, [deriveKey]) Pass Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveBits, deriveKey]) @@ -44,14 +43,14 @@ Pass Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveBits]) Pass Success: generateKey({name: ecdh, namedCurve: P-384}, true, [deriveBits]) Pass Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) Pass Success: generateKey({name: ecdh, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveKey]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveKey]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveBits, deriveKey]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveBits, deriveKey]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveBits]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveBits]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveKey]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveKey]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveBits, deriveKey]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveBits, deriveKey]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveBits]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveBits]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Success: generateKey({name: ecdh, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) Pass Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveKey]) Pass Success: generateKey({name: Ecdh, namedCurve: P-256}, true, [deriveKey]) Pass Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveBits, deriveKey]) @@ -68,11 +67,11 @@ Pass Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveBits]) Pass Success: generateKey({name: Ecdh, namedCurve: P-384}, true, [deriveBits]) Pass Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) Pass Success: generateKey({name: Ecdh, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveKey]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveKey]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveBits, deriveKey]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveBits, deriveKey]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveBits]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveBits]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) \ No newline at end of file +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveKey]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveKey]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveBits, deriveKey]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveBits, deriveKey]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveBits]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveBits]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Success: generateKey({name: Ecdh, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt index 25c0669ddf8..896af1a7922 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt @@ -2,8 +2,7 @@ Harness status: OK Found 246 tests -192 Pass -6 Fail +198 Pass 48 Optional Feature Unsupported Pass Good parameters: P-256 bits (spki, buffer(91), {name: ECDSA, namedCurve: P-256}, true, [verify]) Optional Feature Unsupported Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify]) @@ -107,8 +106,8 @@ Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compre Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign]) Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) Pass Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, []) Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, false, [verify]) Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, false, [verify]) @@ -222,13 +221,13 @@ Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass Empty Usages: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, []) Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, false, [])