diff --git a/Libraries/LibCrypto/Certificate/Certificate.cpp b/Libraries/LibCrypto/Certificate/Certificate.cpp index e43302f61d..939f5f5286 100644 --- a/Libraries/LibCrypto/Certificate/Certificate.cpp +++ b/Libraries/LibCrypto/Certificate/Certificate.cpp @@ -109,15 +109,17 @@ ErrorOr> parse_ec_parameters(Crypto::ASN1::Decoder& decoder, Vector< // } PUSH_SCOPE("ECParameters"sv); READ_OBJECT(ObjectIdentifier, Vector, named_curve); - // Note: namedCurve sometimes has 5 nodes, but we need 7 for the comparison below to work. - while (named_curve.size() < 7) { - named_curve.append(0); - } POP_SCOPE(); + constexpr static Array, 3> known_curve_identifiers { + secp256r1_oid, + secp384r1_oid, + secp521r1_oid + }; + bool is_known_curve = false; for (auto const& curves : known_curve_identifiers) { - if (curves.span() == named_curve.span()) { + if (curves == named_curve.span()) { is_known_curve = true; break; } @@ -139,15 +141,26 @@ static ErrorOr parse_algorithm_identifier(Crypto::ASN1::Dec ENTER_TYPED_SCOPE(Sequence, "AlgorithmIdentifier"sv); PUSH_SCOPE("algorithm"sv); READ_OBJECT(ObjectIdentifier, Vector, algorithm); - // Note: ecPublicKey only has 6 nodes, but we need 7 for the comparison below to work. - while (algorithm.size() < 7) { - algorithm.append(0); - } POP_SCOPE(); + constexpr static Array, 12> known_algorithm_identifiers { + rsa_encryption_oid, + rsa_md5_encryption_oid, + rsa_sha1_encryption_oid, + rsa_sha256_encryption_oid, + rsa_sha384_encryption_oid, + rsa_sha512_encryption_oid, + ecdsa_with_sha256_encryption_oid, + ecdsa_with_sha384_encryption_oid, + ec_public_key_encryption_oid, + x25519_oid, + ed25519_oid, + x448_oid, + }; + bool is_known_algorithm = false; for (auto const& inner : known_algorithm_identifiers) { - if (inner.span() == algorithm.span()) { + if (inner == algorithm.span()) { is_known_algorithm = true; break; } @@ -166,7 +179,7 @@ static ErrorOr parse_algorithm_identifier(Crypto::ASN1::Dec // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } // sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 } - Array, 8> rsa_null_algorithms = { + constexpr static Array, 8> rsa_null_algorithms = { rsa_encryption_oid, rsa_md5_encryption_oid, rsa_sha1_encryption_oid, @@ -178,7 +191,7 @@ static ErrorOr parse_algorithm_identifier(Crypto::ASN1::Dec bool is_rsa_null_algorithm = false; for (auto const& inner : rsa_null_algorithms) { - if (inner.span() == algorithm.span()) { + if (inner == algorithm.span()) { is_rsa_null_algorithm = true; break; } @@ -202,7 +215,7 @@ static ErrorOr parse_algorithm_identifier(Crypto::ASN1::Dec // https://datatracker.ietf.org/doc/html/rfc8410#section-9 // For all of the OIDs, the parameters MUST be absent. - Array, 8> no_parameter_algorithms = { + constexpr static Array, 8> no_parameter_algorithms = { ecdsa_with_sha224_encryption_oid, ecdsa_with_sha256_encryption_oid, ecdsa_with_sha384_encryption_oid, @@ -215,7 +228,7 @@ static ErrorOr parse_algorithm_identifier(Crypto::ASN1::Dec bool is_no_parameter_algorithm = false; for (auto const& inner : no_parameter_algorithms) { - if (inner.span() == algorithm.span()) { + if (inner == algorithm.span()) { is_no_parameter_algorithm = true; } } @@ -381,7 +394,7 @@ ErrorOr parse_subject_public_key_info(Crypto::ASN1::Decoder& d // https://datatracker.ietf.org/doc/html/rfc8410#section-9 // For all of the OIDs, the parameters MUST be absent. - Array, 5> no_parameter_algorithms = { + constexpr static Array, 5> no_parameter_algorithms = { ec_public_key_encryption_oid, x25519_oid, x448_oid, @@ -390,7 +403,7 @@ ErrorOr parse_subject_public_key_info(Crypto::ASN1::Decoder& d }; for (auto const& inner : no_parameter_algorithms) { - if (public_key.algorithm.identifier.span() == inner.span()) { + if (public_key.algorithm.identifier.span() == inner) { // Note: Raw key is already stored, so we can just exit out at this point. EXIT_SCOPE(); return public_key; @@ -451,7 +464,7 @@ ErrorOr parse_private_key_info(Crypto::ASN1::Decoder& decoder, Vecto // https://datatracker.ietf.org/doc/html/rfc8410#section-9 // For all of the OIDs, the parameters MUST be absent. - Array, 5> no_parameter_algorithms = { + constexpr static Array, 5> no_parameter_algorithms = { ec_public_key_encryption_oid, x25519_oid, x448_oid, @@ -460,7 +473,7 @@ ErrorOr parse_private_key_info(Crypto::ASN1::Decoder& decoder, Vecto }; for (auto const& inner : no_parameter_algorithms) { - if (private_key.algorithm.identifier.span() == inner.span()) { + if (private_key.algorithm.identifier.span() == inner) { // Note: Raw key is already stored, so we can just exit out at this point. EXIT_SCOPE(); return private_key; diff --git a/Libraries/LibCrypto/Certificate/Certificate.h b/Libraries/LibCrypto/Certificate/Certificate.h index 7a07f567ea..f3448a7206 100644 --- a/Libraries/LibCrypto/Certificate/Certificate.h +++ b/Libraries/LibCrypto/Certificate/Certificate.h @@ -31,40 +31,20 @@ constexpr static Array ecdsa_with_sha256_encryption_oid { 1, 2, 840, 10045, 4, 3, 2 }, ecdsa_with_sha384_encryption_oid { 1, 2, 840, 10045, 4, 3, 3 }, ecdsa_with_sha512_encryption_oid { 1, 2, 840, 10045, 4, 3, 4 }, - ec_public_key_encryption_oid { 1, 2, 840, 10045, 2, 1 }, + secp256r1_oid { 1, 2, 840, 10045, 3, 1, 7 }; + +constexpr static Array + ec_public_key_encryption_oid { 1, 2, 840, 10045, 2, 1 }; + +constexpr static Array + secp384r1_oid { 1, 3, 132, 0, 34 }, + secp521r1_oid { 1, 3, 132, 0, 35 }; + +constexpr static Array x25519_oid { 1, 3, 101, 110 }, x448_oid { 1, 3, 101, 111 }, ed25519_oid { 1, 3, 101, 112 }, ed448_oid { 1, 3, 101, 113 }, - secp256r1_oid { 1, 2, 840, 10045, 3, 1, 7 }, - secp384r1_oid { 1, 3, 132, 0, 34 }, - secp521r1_oid { 1, 3, 132, 0, 35 }; - -constexpr static Array, 12> known_algorithm_identifiers { - rsa_encryption_oid, - rsa_md5_encryption_oid, - rsa_sha1_encryption_oid, - rsa_sha256_encryption_oid, - rsa_sha384_encryption_oid, - rsa_sha512_encryption_oid, - ecdsa_with_sha256_encryption_oid, - ecdsa_with_sha384_encryption_oid, - ec_public_key_encryption_oid, - x25519_oid, - ed25519_oid, - x448_oid, -}; - -constexpr static Array - curve_ansip384r1 { 1, 3, 132, 0, 34 }, - curve_prime256 { 1, 2, 840, 10045, 3, 1, 7 }; - -constexpr static Array, 9> known_curve_identifiers { - curve_ansip384r1, - curve_prime256 -}; - -constexpr static Array key_usage_oid { 2, 5, 29, 15 }, subject_alternative_name_oid { 2, 5, 29, 17 }, issuer_alternative_name_oid { 2, 5, 29, 18 }, diff --git a/Libraries/LibTLS/TLSv12.cpp b/Libraries/LibTLS/TLSv12.cpp index 584d88ad3e..2f7ff534d7 100644 --- a/Libraries/LibTLS/TLSv12.cpp +++ b/Libraries/LibTLS/TLSv12.cpp @@ -597,9 +597,9 @@ ErrorOr> DefaultRootCACertificates::parse_pem_root_certifica ErrorOr oid_to_curve(Vector curve) { - if (curve == Crypto::Certificate::curve_ansip384r1) + if (curve == Crypto::Certificate::secp384r1_oid) return SupportedGroup::SECP384R1; - if (curve == Crypto::Certificate::curve_prime256) + if (curve == Crypto::Certificate::secp256r1_oid) return SupportedGroup::SECP256R1; return AK::Error::from_string_literal("Unknown curve oid"); diff --git a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 04c136d357..1a8e604dfe 100644 --- a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -3144,7 +3144,7 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo [&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr { auto public_key_bytes = TRY(public_key.to_uncompressed()); - Array ec_params; + Span ec_params; if (algorithm.named_curve() == "P-256"sv) ec_params = ::Crypto::Certificate::secp256r1_oid; else if (algorithm.named_curve() == "P-384"sv) @@ -3154,17 +3154,7 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo else VERIFY_NOT_REACHED(); - // NOTE: we store OIDs as 7 bytes, but they might be shorter - size_t trailing_zeros = 0; - for (size_t i = ec_params.size() - 1; i > 0; --i) { - if (ec_params[i] == 0) - ++trailing_zeros; - else - break; - } - - auto ec_public_key_oid = ::Crypto::Certificate::ec_public_key_encryption_oid.span().trim(6); - return TRY(::Crypto::PK::wrap_in_subject_public_key_info(public_key_bytes, ec_public_key_oid, ec_params.span().trim(ec_params.size() - trailing_zeros))); + return TRY(::Crypto::PK::wrap_in_subject_public_key_info(public_key_bytes, ::Crypto::Certificate::ec_public_key_encryption_oid, ec_params)); }, [](auto) -> ErrorOr { VERIFY_NOT_REACHED(); @@ -3221,7 +3211,7 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo // NOTE: everything above happens in wrap_in_private_key_info auto maybe_data = handle.visit( [&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr { - Array ec_params; + Span ec_params; if (algorithm.named_curve() == "P-256"sv) ec_params = ::Crypto::Certificate::secp256r1_oid; else if (algorithm.named_curve() == "P-384"sv) @@ -3231,17 +3221,7 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo else VERIFY_NOT_REACHED(); - // NOTE: we store OIDs as 7 bytes, but they might be shorter - size_t trailing_zeros = 0; - for (size_t i = ec_params.size() - 1; i > 0; --i) { - if (ec_params[i] == 0) - ++trailing_zeros; - else - break; - } - - auto ec_public_key_oid = ::Crypto::Certificate::ec_public_key_encryption_oid.span().trim(6); - return TRY(::Crypto::PK::wrap_in_private_key_info(private_key, ec_public_key_oid, ec_params.span().trim(ec_params.size() - trailing_zeros))); + return TRY(::Crypto::PK::wrap_in_private_key_info(private_key, ::Crypto::Certificate::ec_public_key_encryption_oid, ec_params)); }, [](auto) -> ErrorOr { VERIFY_NOT_REACHED(); 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 72240fba0e..6bf0c70965 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 @@ -6,8 +6,8 @@ Rerun Found 40 tests -25 Pass -15 Fail +30 Pass +10 Fail Details Result Test Name MessagePass setup - define tests Fail P-521 good parameters @@ -16,12 +16,12 @@ Fail P-521 short result 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 -Fail P-521 mismatched curves +Pass P-521 mismatched curves Fail P-521 public property of algorithm is not an ECDSA public key Cannot access property "publicKey" on null object "ecdsaKeyPairs[namedCurve]" -Fail P-521 no deriveBits usage for base key -Fail P-521 base key is not a private key -Fail P-521 public property value is a private key -Fail P-521 public property value is a secret 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 +Pass P-521 public property value is a secret key Fail P-521 asking for too many bits Pass P-256 good parameters Pass P-256 mixed case parameters 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 9042790175..06559b2b73 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 @@ -6,20 +6,20 @@ Rerun Found 31 tests -23 Pass -8 Fail +28 Pass +3 Fail Details Result Test Name MessagePass 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 -Fail P-521 mismatched curves +Pass P-521 mismatched curves Fail P-521 public property of algorithm is not an ECDSA public key Cannot access property "publicKey" on null object "ecdsaKeyPairs[namedCurve]" -Fail P-521 no deriveKey usage for base key -Fail P-521 base key is not a private key -Fail P-521 public property value is a private key -Fail P-521 public property value is a secret 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 +Pass P-521 public property value is a secret key Pass P-256 good parameters Pass P-256 mixed case parameters Pass P-256 missing public curve 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 7ee3287fb2..de3b41d059 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 @@ -6,8 +6,8 @@ Rerun Found 246 tests -90 Pass -144 Fail +97 Pass +137 Fail 12 Optional Feature Unsupported Details Result Test Name MessageFail Good parameters: P-256 bits (spki, buffer(91), {name: ECDSA, namedCurve: P-256}, true, [verify]) @@ -217,7 +217,7 @@ Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, n Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, []) Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, []) -Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, []) Compressed point format not supported: DataError: Error parsing subjectPublicKeyInfo: [ "SubjectPublicKeyInfo"sv, "AlgorithmIdentifier"sv ]: Unknown named curve [ 1, 3, 132, 0, 35, 0, 0 ] +Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, []) Compressed point format not supported: DataError: Unsupported key format Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, []) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, alg), {name: ECDH, namedCurve: P-521}, true, []) Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, []) @@ -226,7 +226,7 @@ Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, []) +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 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]) @@ -236,17 +236,17 @@ Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: E Fail 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, []) -Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, false, []) -Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, false, []) Compressed point format not supported: DataError: Error parsing subjectPublicKeyInfo: [ "SubjectPublicKeyInfo"sv, "AlgorithmIdentifier"sv ]: Unknown named curve [ 1, 3, 132, 0, 35, 0, 0 ] +Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, false, []) +Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, false, []) Compressed point format not supported: DataError: Unsupported key format Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, false, []) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, alg), {name: ECDH, namedCurve: P-521}, false, []) Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, false, []) Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, false, []) Compressed point format not supported: DataError: Invalid key size -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits]) -Fail Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, []) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveBits]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, [deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, false, []) Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveKey]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, false, [deriveKey]) Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, false, [deriveBits, deriveKey]) diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey_failures_ECDH.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey_failures_ECDH.https.any.txt index 42c18bffaf..a3782079c2 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey_failures_ECDH.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey_failures_ECDH.https.any.txt @@ -6,8 +6,7 @@ Rerun Found 608 tests -606 Pass -2 Fail +608 Pass Details Result Test Name MessagePass Bad usages: importKey(spki, {name: ECDH, namedCurve: P-256}, true, [encrypt]) Pass Bad usages: importKey(spki, {name: ECDH, namedCurve: P-256}, false, [encrypt]) @@ -473,8 +472,8 @@ Pass Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-384}, true, []) Pass Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-384}, false, []) Pass Empty usages: importKey(jwk(private), {name: ECDH, namedCurve: P-384}, true, []) Pass Empty usages: importKey(jwk(private), {name: ECDH, namedCurve: P-384}, false, []) -Fail Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-521}, true, []) -Fail Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-521}, false, []) +Pass Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-521}, true, []) +Pass Empty usages: importKey(pkcs8, {name: ECDH, namedCurve: P-521}, false, []) Pass Empty usages: importKey(jwk(private), {name: ECDH, namedCurve: P-521}, true, []) Pass Empty usages: importKey(jwk(private), {name: ECDH, namedCurve: P-521}, false, []) Pass Bad key length: importKey(spki, {name: ECDH, namedCurve: P-256}, true, [])