From 01455ea26bd3a2cecfdf6d3b130a92e3631b306d Mon Sep 17 00:00:00 2001 From: devgianlu Date: Sun, 17 Nov 2024 18:14:13 +0100 Subject: [PATCH] LibWeb: Implement ECDH.generateKey --- Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp | 100 ++++ Libraries/LibWeb/Crypto/CryptoAlgorithms.h | 16 + Libraries/LibWeb/Crypto/SubtleCrypto.cpp | 2 +- .../generateKey/failures_ECDH.https.any.txt | 487 ++++++++++++++++++ .../generateKey/successes_ECDH.https.any.txt | 82 +++ .../WebCryptoAPI/generateKey/failures.js | 228 ++++++++ .../generateKey/failures_ECDH.https.any.html | 17 + .../generateKey/failures_ECDH.https.any.js | 5 + .../WebCryptoAPI/generateKey/successes.js | 115 +++++ .../generateKey/successes_ECDH.https.any.html | 18 + .../generateKey/successes_ECDH.https.any.js | 6 + .../wpt-import/WebCryptoAPI/util/helpers.js | 299 +++++++++++ .../input/wpt-import/common/subset-tests.js | 60 +++ 13 files changed, 1434 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/util/helpers.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/common/subset-tests.js diff --git a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 12bc64d4991..4cf0848b08e 100644 --- a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -2526,6 +2526,106 @@ WebIDL::ExceptionOr ECDSA::verify(AlgorithmParams const& params, GC:: return JS::Value(result); } +// https://w3c.github.io/webcrypto/#ecdh-operations +WebIDL::ExceptionOr, GC::Ref>> ECDH::generate_key(AlgorithmParams const& params, bool extractable, Vector const& key_usages) +{ + // 1. If usages contains an entry which is not "deriveKey" or "deriveBits" then throw a SyntaxError. + for (auto const& usage : key_usages) { + if (usage != Bindings::KeyUsage::Derivekey && usage != Bindings::KeyUsage::Derivebits) { + return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage)))); + } + } + + auto const& normalized_algorithm = static_cast(params); + + // 2. If the namedCurve member of normalizedAlgorithm is "P-256", "P-384" or "P-521": + // Generate an Elliptic Curve key pair, as defined in [RFC6090] + // with domain parameters for the curve identified by the namedCurve member of normalizedAlgorithm. + Variant curve; + if (normalized_algorithm.named_curve.is_one_of("P-256"sv, "P-384"sv, "P-521"sv)) { + if (normalized_algorithm.named_curve.equals_ignoring_ascii_case("P-256"sv)) + curve = ::Crypto::Curves::SECP256r1 {}; + + if (normalized_algorithm.named_curve.equals_ignoring_ascii_case("P-384"sv)) + curve = ::Crypto::Curves::SECP384r1 {}; + + // FIXME: Support P-521 + if (normalized_algorithm.named_curve.equals_ignoring_ascii_case("P-521"sv)) + return WebIDL::NotSupportedError::create(m_realm, "'P-521' is not supported yet"_string); + } else { + // If the namedCurve member of normalizedAlgorithm is a value specified in an applicable specification + // that specifies the use of that value with ECDH: + // Perform the ECDH generation steps specified in that specification, + // passing in normalizedAlgorithm and resulting in an elliptic curve key pair. + + // Otherwise: throw a NotSupportedError + return WebIDL::NotSupportedError::create(m_realm, "Only 'P-256', 'P-384' and 'P-521' is supported"_string); + } + + // 3. If performing the operation results in an error, then throw a OperationError. + auto maybe_private_key_data = curve.visit( + [](Empty const&) -> ErrorOr { return Error::from_string_literal("noop error"); }, + [](auto instance) { return instance.generate_private_key(); }); + + if (maybe_private_key_data.is_error()) + return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string); + + auto private_key_data = maybe_private_key_data.release_value(); + + auto maybe_public_key_data = curve.visit( + [](Empty const&) -> ErrorOr { return Error::from_string_literal("noop error"); }, + [&](auto instance) { return instance.generate_public_key(private_key_data); }); + + if (maybe_public_key_data.is_error()) + return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string); + + auto public_key_data = maybe_public_key_data.release_value(); + + // 4. Let algorithm be a new EcKeyAlgorithm object. + auto algorithm = EcKeyAlgorithm::create(m_realm); + + // 5. Set the name attribute of algorithm to "ECDH". + algorithm->set_name("ECDH"_string); + + // 6. Set the namedCurve attribute of algorithm to equal the namedCurve member of normalizedAlgorithm. + algorithm->set_named_curve(normalized_algorithm.named_curve); + + // 7. Let publicKey be a new CryptoKey representing the public key of the generated key pair. + auto public_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { public_key_data }); + + // 8. Set the [[type]] internal slot of publicKey to "public" + public_key->set_type(Bindings::KeyType::Public); + + // 9. Set the [[algorithm]] internal slot of publicKey to algorithm. + public_key->set_algorithm(algorithm); + + // 10. Set the [[extractable]] internal slot of publicKey to true. + public_key->set_extractable(true); + + // 11. Set the [[usages]] internal slot of publicKey to be the empty list. + public_key->set_usages({}); + + // 12. Let privateKey be a new CryptoKey representing the private key of the generated key pair. + auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { private_key_data }); + + // 13. Set the [[type]] internal slot of privateKey to "private" + private_key->set_type(Bindings::KeyType::Private); + + // 14. Set the [[algorithm]] internal slot of privateKey to algorithm. + private_key->set_algorithm(algorithm); + + // 15. Set the [[extractable]] internal slot of privateKey to extractable. + private_key->set_extractable(extractable); + + // 16. Set the [[usages]] internal slot of privateKey to be the usage intersection of usages and [ "deriveKey", "deriveBits" ]. + private_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Derivekey, Bindings::KeyUsage::Derivebits } })); + + // 17. Let result be a new CryptoKeyPair dictionary. + // 18. Set the publicKey attribute of result to be publicKey. + // 19. Set the privateKey attribute of result to be privateKey. + // 20. Return the result of converting result to an ECMAScript Object, as defined by [WebIDL]. + return Variant, GC::Ref> { CryptoKeyPair::create(m_realm, public_key, private_key) }; +} // https://wicg.github.io/webcrypto-secure-curves/#ed25519-operations WebIDL::ExceptionOr, GC::Ref>> ED25519::generate_key([[maybe_unused]] AlgorithmParams const& params, bool extractable, Vector const& key_usages) { diff --git a/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index a7d43508562..8a9a9111c23 100644 --- a/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -493,6 +493,22 @@ private: } }; +class ECDH : public AlgorithmMethods { +public: + virtual WebIDL::ExceptionOr, GC::Ref>> generate_key(AlgorithmParams const&, bool, Vector const&) override; + // TODO: virtual WebIDL::ExceptionOr> derive_bits(AlgorithmParams const&, GC::Ref, Optional) override; + // TODO: virtual WebIDL::ExceptionOr> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector const&) override; + // TODO: virtual WebIDL::ExceptionOr> export_key(Bindings::KeyFormat, GC::Ref) override; + + static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new ECDH(realm)); } + +private: + explicit ECDH(JS::Realm& realm) + : AlgorithmMethods(realm) + { + } +}; + class ED25519 : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr> sign(AlgorithmParams const&, GC::Ref, ByteBuffer const&) override; diff --git a/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index 7f1e1a67760..6c23f2c2272 100644 --- a/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -801,10 +801,10 @@ SupportedAlgorithmsMap supported_algorithms() // FIXME: define_an_algorithm("exportKey"_string, "ECDSA"_string); // https://w3c.github.io/webcrypto/#ecdh-registration - // FIXME: define_an_algorithm("generateKey"_string, "ECDH"_string); // FIXME: define_an_algorithm("deriveBits"_string, "ECDH"_string); // FIXME: define_an_algorithm("importKey"_string, "ECDH"_string); // FIXME: define_an_algorithm("exportKey"_string, "ECDH"_string); + define_an_algorithm("generateKey"_string, "ECDH"_string); // https://w3c.github.io/webcrypto/#aes-ctr-registration define_an_algorithm("encrypt"_string, "AES-CTR"_string); 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 new file mode 100644 index 00000000000..92287251425 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.txt @@ -0,0 +1,487 @@ +Summary + +Harness status: OK + +Rerun + +Found 476 tests + +410 Pass +66 Fail +Details +Result Test Name MessagePass Bad algorithm: generateKey(AES, false, [decrypt]) +Pass Bad algorithm: generateKey(AES, true, [decrypt]) +Pass Bad algorithm: generateKey(AES, RED, [decrypt]) +Pass Bad algorithm: generateKey(AES, 7, [decrypt]) +Pass Bad algorithm: generateKey(AES, false, [sign, decrypt]) +Pass Bad algorithm: generateKey(AES, true, [sign, decrypt]) +Pass Bad algorithm: generateKey(AES, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey(AES, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey(AES, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey(AES, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey(AES, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey(AES, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey(AES, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey(AES, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey(AES, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey(AES, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey(AES, false, [sign]) +Pass Bad algorithm: generateKey(AES, true, [sign]) +Pass Bad algorithm: generateKey(AES, RED, [sign]) +Pass Bad algorithm: generateKey(AES, 7, [sign]) +Pass Bad algorithm: generateKey(AES, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey(AES, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey(AES, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey(AES, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey(AES, false, [deriveBits]) +Pass Bad algorithm: generateKey(AES, true, [deriveBits]) +Pass Bad algorithm: generateKey(AES, RED, [deriveBits]) +Pass Bad algorithm: generateKey(AES, 7, [deriveBits]) +Pass Bad algorithm: generateKey(AES, false, []) +Pass Bad algorithm: generateKey(AES, true, []) +Pass Bad algorithm: generateKey(AES, RED, []) +Pass Bad algorithm: generateKey(AES, 7, []) +Pass Bad algorithm: generateKey(AES, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey(AES, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey(AES, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey(AES, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, false, [decrypt]) +Pass Bad algorithm: generateKey({name: AES}, true, [decrypt]) +Pass Bad algorithm: generateKey({name: AES}, RED, [decrypt]) +Pass Bad algorithm: generateKey({name: AES}, 7, [decrypt]) +Pass Bad algorithm: generateKey({name: AES}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: AES}, false, [sign]) +Pass Bad algorithm: generateKey({name: AES}, true, [sign]) +Pass Bad algorithm: generateKey({name: AES}, RED, [sign]) +Pass Bad algorithm: generateKey({name: AES}, 7, [sign]) +Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, false, []) +Pass Bad algorithm: generateKey({name: AES}, true, []) +Pass Bad algorithm: generateKey({name: AES}, RED, []) +Pass Bad algorithm: generateKey({name: AES}, 7, []) +Pass Bad algorithm: generateKey({name: AES}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: AES}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, []) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, []) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, []) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, []) +Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, []) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, sign, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, decrypt]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [sign]) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [sign]) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [sign]) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [sign]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, sign]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, sign]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, sign]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, sign]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, []) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, []) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, []) +Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, []) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, []) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, []) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, []) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, []) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, []) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, []) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, []) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, []) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, sign, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, decrypt]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, sign]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, []) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, []) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, []) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, []) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Empty algorithm: generateKey({}, false, [decrypt]) +Fail Empty algorithm: generateKey({}, true, [decrypt]) +Fail Empty algorithm: generateKey({}, RED, [decrypt]) +Fail Empty algorithm: generateKey({}, 7, [decrypt]) +Fail Empty algorithm: generateKey({}, false, [sign, decrypt]) +Fail Empty algorithm: generateKey({}, true, [sign, decrypt]) +Fail Empty algorithm: generateKey({}, RED, [sign, decrypt]) +Fail Empty algorithm: generateKey({}, 7, [sign, decrypt]) +Fail Empty algorithm: generateKey({}, false, [deriveBits, sign, decrypt]) +Fail Empty algorithm: generateKey({}, true, [deriveBits, sign, decrypt]) +Fail Empty algorithm: generateKey({}, RED, [deriveBits, sign, decrypt]) +Fail Empty algorithm: generateKey({}, 7, [deriveBits, sign, decrypt]) +Fail Empty algorithm: generateKey({}, false, [deriveBits, decrypt]) +Fail Empty algorithm: generateKey({}, true, [deriveBits, decrypt]) +Fail Empty algorithm: generateKey({}, RED, [deriveBits, decrypt]) +Fail Empty algorithm: generateKey({}, 7, [deriveBits, decrypt]) +Fail Empty algorithm: generateKey({}, false, [sign]) +Fail Empty algorithm: generateKey({}, true, [sign]) +Fail Empty algorithm: generateKey({}, RED, [sign]) +Fail Empty algorithm: generateKey({}, 7, [sign]) +Fail Empty algorithm: generateKey({}, false, [deriveBits, sign]) +Fail Empty algorithm: generateKey({}, true, [deriveBits, sign]) +Fail Empty algorithm: generateKey({}, RED, [deriveBits, sign]) +Fail Empty algorithm: generateKey({}, 7, [deriveBits, sign]) +Fail Empty algorithm: generateKey({}, false, [deriveBits]) +Fail Empty algorithm: generateKey({}, true, [deriveBits]) +Fail Empty algorithm: generateKey({}, RED, [deriveBits]) +Fail Empty algorithm: generateKey({}, 7, [deriveBits]) +Fail Empty algorithm: generateKey({}, false, []) +Fail Empty algorithm: generateKey({}, true, []) +Fail Empty algorithm: generateKey({}, RED, []) +Fail Empty algorithm: generateKey({}, 7, []) +Fail Empty algorithm: generateKey({}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Empty algorithm: generateKey({}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Empty algorithm: generateKey({}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Fail Empty algorithm: generateKey({}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveBits, unwrapKey]) +Pass Bad usages: generateKey({name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, false, [deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, true, [deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, false, [deriveBits, deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, true, [deriveBits, deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, false, [deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, true, [deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, false, []) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, true, []) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: P-512}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, false, [deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, true, [deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, false, [deriveBits, deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, true, [deriveBits, deriveKey]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, false, [deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, true, [deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, false, []) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, true, []) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Bad algorithm property: generateKey({name: ECDH, namedCurve: Curve25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +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 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 new file mode 100644 index 00000000000..3966eca8b9e --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.txt @@ -0,0 +1,82 @@ +Summary + +Harness status: OK + +Rerun + +Found 72 tests + +72 Fail +Details +Result Test Name MessageFail Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, true, [deriveBits]) +Fail Success: generateKey({name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail 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]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, true, [deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, true, [deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, true, [deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, true, [deriveBits]) +Fail Success: generateKey({name: ecdh, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail 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]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, true, [deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, true, [deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-256}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, true, [deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveBits, deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, true, [deriveBits, deriveKey]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, true, [deriveBits]) +Fail Success: generateKey({name: Ecdh, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits]) +Fail 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 diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures.js new file mode 100644 index 00000000000..deaac636a99 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures.js @@ -0,0 +1,228 @@ +function run_test(algorithmNames) { + var subtle = crypto.subtle; // Change to test prefixed implementations + + setup({explicit_timeout: true}); + +// These tests check that generateKey throws an error, and that +// the error is of the right type, for a wide set of incorrect parameters. +// +// Error testing occurs by setting the parameter that should trigger the +// error to an invalid value, then combining that with all valid +// parameters that should be checked earlier by generateKey, and all +// valid and invalid parameters that should be checked later by +// generateKey. +// +// There are a lot of combinations of possible parameters for both +// success and failure modes, resulting in a very large number of tests +// performed. + + +// Setup: define the correct behaviors that should be sought, and create +// helper functions that generate all possible test parameters for +// different situations. + + var allTestVectors = [ // Parameters that should work for generateKey + {name: "AES-CTR", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-CBC", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-GCM", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-KW", resultType: CryptoKey, usages: ["wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "HMAC", resultType: CryptoKey, usages: ["sign", "verify"], mandatoryUsages: []}, + {name: "RSASSA-PKCS1-v1_5", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "RSA-PSS", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "RSA-OAEP", resultType: "CryptoKeyPair", usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: ["decrypt", "unwrapKey"]}, + {name: "ECDSA", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "ECDH", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + {name: "Ed25519", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "Ed448", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "X25519", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + {name: "X448", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + ]; + + var testVectors = []; + if (algorithmNames && !Array.isArray(algorithmNames)) { + algorithmNames = [algorithmNames]; + }; + allTestVectors.forEach(function(vector) { + if (!algorithmNames || algorithmNames.includes(vector.name)) { + testVectors.push(vector); + } + }); + + + function parameterString(algorithm, extractable, usages) { + if (typeof algorithm !== "object" && typeof algorithm !== "string") { + alert(algorithm); + } + + var result = "(" + + objectToString(algorithm) + ", " + + objectToString(extractable) + ", " + + objectToString(usages) + + ")"; + + return result; + } + + // Test that a given combination of parameters results in an error, + // AND that it is the correct kind of error. + // + // Expected error is either a number, tested against the error code, + // or a string, tested against the error name. + function testError(algorithm, extractable, usages, expectedError, testTag) { + promise_test(function(test) { + return crypto.subtle.generateKey(algorithm, extractable, usages) + .then(function(result) { + assert_unreached("Operation succeeded, but should not have"); + }, function(err) { + if (typeof expectedError === "number") { + assert_equals(err.code, expectedError, testTag + " not supported"); + } else { + assert_equals(err.name, expectedError, testTag + " not supported"); + } + }); + }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); + } + + + // Given an algorithm name, create several invalid parameters. + function badAlgorithmPropertySpecifiersFor(algorithmName) { + var results = []; + + if (algorithmName.toUpperCase().substring(0, 3) === "AES") { + // Specifier properties are name and length + [64, 127, 129, 255, 257, 512].forEach(function(length) { + results.push({name: algorithmName, length: length}); + }); + } else if (algorithmName.toUpperCase().substring(0, 3) === "RSA") { + [new Uint8Array([1]), new Uint8Array([1,0,0])].forEach(function(publicExponent) { + results.push({name: algorithmName, hash: "SHA-256", modulusLength: 1024, publicExponent: publicExponent}); + }); + } else if (algorithmName.toUpperCase().substring(0, 2) === "EC") { + ["P-512", "Curve25519"].forEach(function(curveName) { + results.push({name: algorithmName, namedCurve: curveName}); + }); + } + + return results; + } + + + // Don't create an exhaustive list of all invalid usages, + // because there would usually be nearly 2**8 of them, + // way too many to test. Instead, create every singleton + // of an illegal usage, and "poison" every valid usage + // with an illegal one. + function invalidUsages(validUsages, mandatoryUsages) { + var results = []; + + var illegalUsages = []; + ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey", "deriveKey", "deriveBits"].forEach(function(usage) { + if (!validUsages.includes(usage)) { + illegalUsages.push(usage); + } + }); + + var goodUsageCombinations = allValidUsages(validUsages, false, mandatoryUsages); + + illegalUsages.forEach(function(illegalUsage) { + results.push([illegalUsage]); + goodUsageCombinations.forEach(function(usageCombination) { + results.push(usageCombination.concat([illegalUsage])); + }); + }); + + return results; + } + + +// Now test for properly handling errors +// - Unsupported algorithm +// - Bad usages for algorithm +// - Bad key lengths + + // Algorithm normalization should fail with "Not supported" + var badAlgorithmNames = [ + "AES", + {name: "AES"}, + {name: "AES", length: 128}, + {name: "AES-CMAC", length: 128}, // Removed after CR + {name: "AES-CFB", length: 128}, // Removed after CR + {name: "HMAC", hash: "MD5"}, + {name: "RSA", hash: "SHA-256", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, + {name: "RSA-PSS", hash: "SHA", modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}, + {name: "EC", namedCurve: "P521"} + ]; + + + // Algorithm normalization failures should be found first + // - all other parameters can be good or bad, should fail + // due to NotSupportedError. + badAlgorithmNames.forEach(function(algorithm) { + allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used + .forEach(function(usages) { + [false, true, "RED", 7].forEach(function(extractable){ + testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm"); + }); + }); + }); + + // Empty algorithm should fail with TypeError + allValidUsages(["decrypt", "sign", "deriveBits"], true, []) // Small search space, shouldn't matter because should fail before used + .forEach(function(usages) { + [false, true, "RED", 7].forEach(function(extractable){ + testError({}, extractable, usages, "TypeError", "Empty algorithm"); + }); + }); + + + // Algorithms normalize okay, but usages bad (though not empty). + // It shouldn't matter what other extractable is. Should fail + // due to SyntaxError + testVectors.forEach(function(vector) { + var name = vector.name; + + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { + invalidUsages(vector.usages, vector.mandatoryUsages).forEach(function(usages) { + [true].forEach(function(extractable) { + testError(algorithm, extractable, usages, "SyntaxError", "Bad usages"); + }); + }); + }); + }); + + + // Other algorithm properties should be checked next, so try good + // algorithm names and usages, but bad algorithm properties next. + // - Special case: normally bad usage [] isn't checked until after properties, + // so it's included in this test case. It should NOT cause an error. + testVectors.forEach(function(vector) { + var name = vector.name; + badAlgorithmPropertySpecifiersFor(name).forEach(function(algorithm) { + allValidUsages(vector.usages, true, vector.mandatoryUsages) + .forEach(function(usages) { + [false, true].forEach(function(extractable) { + if (name.substring(0,2) === "EC") { + testError(algorithm, extractable, usages, "NotSupportedError", "Bad algorithm property"); + } else { + testError(algorithm, extractable, usages, "OperationError", "Bad algorithm property"); + } + }); + }); + }); + }); + + + // The last thing that should be checked is empty usages (disallowed for secret and private keys). + testVectors.forEach(function(vector) { + var name = vector.name; + + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { + var usages = []; + [false, true].forEach(function(extractable) { + testError(algorithm, extractable, usages, "SyntaxError", "Empty usages"); + }); + }); + }); + + +} diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.html b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.html new file mode 100644 index 00000000000..46faf0f2100 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.html @@ -0,0 +1,17 @@ + + +WebCryptoAPI: generateKey() for Failures + + + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.js new file mode 100644 index 00000000000..e522254d743 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/failures_ECDH.https.any.js @@ -0,0 +1,5 @@ +// META: title=WebCryptoAPI: generateKey() for Failures +// META: timeout=long +// META: script=../util/helpers.js +// META: script=failures.js +run_test(["ECDH"]); diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes.js new file mode 100644 index 00000000000..a9a168e1adb --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes.js @@ -0,0 +1,115 @@ + +function run_test(algorithmNames, slowTest) { + var subtle = crypto.subtle; // Change to test prefixed implementations + + setup({explicit_timeout: true}); + +// These tests check that generateKey successfully creates keys +// when provided any of a wide set of correct parameters +// and that they can be exported afterwards. +// +// There are a lot of combinations of possible parameters, +// resulting in a very large number of tests +// performed. + + +// Setup: define the correct behaviors that should be sought, and create +// helper functions that generate all possible test parameters for +// different situations. + + var allTestVectors = [ // Parameters that should work for generateKey + {name: "AES-CTR", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-CBC", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-GCM", resultType: CryptoKey, usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "AES-KW", resultType: CryptoKey, usages: ["wrapKey", "unwrapKey"], mandatoryUsages: []}, + {name: "HMAC", resultType: CryptoKey, usages: ["sign", "verify"], mandatoryUsages: []}, + {name: "RSASSA-PKCS1-v1_5", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "RSA-PSS", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "RSA-OAEP", resultType: "CryptoKeyPair", usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], mandatoryUsages: ["decrypt", "unwrapKey"]}, + {name: "ECDSA", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "ECDH", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + {name: "Ed25519", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "Ed448", resultType: "CryptoKeyPair", usages: ["sign", "verify"], mandatoryUsages: ["sign"]}, + {name: "X25519", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + {name: "X448", resultType: "CryptoKeyPair", usages: ["deriveKey", "deriveBits"], mandatoryUsages: ["deriveKey", "deriveBits"]}, + ]; + + var testVectors = []; + if (algorithmNames && !Array.isArray(algorithmNames)) { + algorithmNames = [algorithmNames]; + }; + allTestVectors.forEach(function(vector) { + if (!algorithmNames || algorithmNames.includes(vector.name)) { + testVectors.push(vector); + } + }); + + function parameterString(algorithm, extractable, usages) { + var result = "(" + + objectToString(algorithm) + ", " + + objectToString(extractable) + ", " + + objectToString(usages) + + ")"; + + return result; + } + + // Test that a given combination of parameters is successful + function testSuccess(algorithm, extractable, usages, resultType, testTag) { + // algorithm, extractable, and usages are the generateKey parameters + // resultType is the expected result, either the CryptoKey object or "CryptoKeyPair" + // testTag is a string to prepend to the test name. + + promise_test(function(test) { + return subtle.generateKey(algorithm, extractable, usages) + .then(function(result) { + if (resultType === "CryptoKeyPair") { + assert_goodCryptoKey(result.privateKey, algorithm, extractable, usages, "private"); + assert_goodCryptoKey(result.publicKey, algorithm, true, usages, "public"); + } else { + assert_goodCryptoKey(result, algorithm, extractable, usages, "secret"); + } + return result; + }, function(err) { + assert_unreached("generateKey threw an unexpected error: " + err.toString()); + }) + .then(async function (result) { + if (resultType === "CryptoKeyPair") { + await Promise.all([ + subtle.exportKey('jwk', result.publicKey), + subtle.exportKey('spki', result.publicKey), + result.publicKey.algorithm.name.startsWith('RSA') ? undefined : subtle.exportKey('raw', result.publicKey), + ...(extractable ? [ + subtle.exportKey('jwk', result.privateKey), + subtle.exportKey('pkcs8', result.privateKey), + ] : []) + ]); + } else { + if (extractable) { + await Promise.all([ + subtle.exportKey('raw', result), + subtle.exportKey('jwk', result), + ]); + } + } + }, function(err) { + assert_unreached("exportKey threw an unexpected error: " + err.toString()); + }) + }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); + } + + // Test all valid sets of parameters for successful + // key generation. + testVectors.forEach(function(vector) { + allNameVariants(vector.name, slowTest).forEach(function(name) { + allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { + allValidUsages(vector.usages, false, vector.mandatoryUsages).forEach(function(usages) { + [false, true].forEach(function(extractable) { + subsetTest(testSuccess, algorithm, extractable, usages, vector.resultType, "Success"); + }); + }); + }); + }); + }); + +} diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.html b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.html new file mode 100644 index 00000000000..02b1fb5441f --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.html @@ -0,0 +1,18 @@ + + +WebCryptoAPI: generateKey() Successful Calls + + + + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.js new file mode 100644 index 00000000000..e9dee526149 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/generateKey/successes_ECDH.https.any.js @@ -0,0 +1,6 @@ +// META: title=WebCryptoAPI: generateKey() Successful Calls +// META: timeout=long +// META: script=../util/helpers.js +// META: script=/common/subset-tests.js +// META: script=successes.js +run_test(["ECDH"]); diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/util/helpers.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/util/helpers.js new file mode 100644 index 00000000000..c60371dc6ad --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/util/helpers.js @@ -0,0 +1,299 @@ +// +// helpers.js +// +// Helper functions used by several WebCryptoAPI tests +// + +var registeredAlgorithmNames = [ + "RSASSA-PKCS1-v1_5", + "RSA-PSS", + "RSA-OAEP", + "ECDSA", + "ECDH", + "AES-CTR", + "AES-CBC", + "AES-GCM", + "AES-KW", + "HMAC", + "SHA-1", + "SHA-256", + "SHA-384", + "SHA-512", + "HKDF", + "PBKDF2", + "Ed25519", + "Ed448", + "X25519", + "X448" +]; + + +// Treats an array as a set, and generates an array of all non-empty +// subsets (which are themselves arrays). +// +// The order of members of the "subsets" is not guaranteed. +function allNonemptySubsetsOf(arr) { + var results = []; + var firstElement; + var remainingElements; + + for(var i=0; i 0) { + allNonemptySubsetsOf(remainingElements).forEach(function(combination) { + combination.push(firstElement); + results.push(combination); + }); + } + } + + return results; +} + + +// Create a string representation of keyGeneration parameters for +// test names and labels. +function objectToString(obj) { + var keyValuePairs = []; + + if (Array.isArray(obj)) { + return "[" + obj.map(function(elem){return objectToString(elem);}).join(", ") + "]"; + } else if (typeof obj === "object") { + Object.keys(obj).sort().forEach(function(keyName) { + keyValuePairs.push(keyName + ": " + objectToString(obj[keyName])); + }); + return "{" + keyValuePairs.join(", ") + "}"; + } else if (typeof obj === "undefined") { + return "undefined"; + } else { + return obj.toString(); + } + + var keyValuePairs = []; + + Object.keys(obj).sort().forEach(function(keyName) { + var value = obj[keyName]; + if (typeof value === "object") { + value = objectToString(value); + } else if (typeof value === "array") { + value = "[" + value.map(function(elem){return objectToString(elem);}).join(", ") + "]"; + } else { + value = value.toString(); + } + + keyValuePairs.push(keyName + ": " + value); + }); + + return "{" + keyValuePairs.join(", ") + "}"; +} + +// Is key a CryptoKey object with correct algorithm, extractable, and usages? +// Is it a secret, private, or public kind of key? +function assert_goodCryptoKey(key, algorithm, extractable, usages, kind) { + var correctUsages = []; + + var registeredAlgorithmName; + registeredAlgorithmNames.forEach(function(name) { + if (name.toUpperCase() === algorithm.name.toUpperCase()) { + registeredAlgorithmName = name; + } + }); + + assert_equals(key.constructor, CryptoKey, "Is a CryptoKey"); + assert_equals(key.type, kind, "Is a " + kind + " key"); + assert_equals(key.extractable, extractable, "Extractability is correct"); + + assert_equals(key.algorithm.name, registeredAlgorithmName, "Correct algorithm name"); + if (key.algorithm.name.toUpperCase() === "HMAC" && algorithm.length === undefined) { + switch (key.algorithm.hash.name.toUpperCase()) { + case 'SHA-1': + case 'SHA-256': + assert_equals(key.algorithm.length, 512, "Correct length"); + break; + case 'SHA-384': + case 'SHA-512': + assert_equals(key.algorithm.length, 1024, "Correct length"); + break; + default: + assert_unreached("Unrecognized hash"); + } + } else { + assert_equals(key.algorithm.length, algorithm.length, "Correct length"); + } + if (["HMAC", "RSASSA-PKCS1-v1_5", "RSA-PSS"].includes(registeredAlgorithmName)) { + assert_equals(key.algorithm.hash.name.toUpperCase(), algorithm.hash.toUpperCase(), "Correct hash function"); + } + + if (/^(?:Ed|X)(?:25519|448)$/.test(key.algorithm.name)) { + assert_false('namedCurve' in key.algorithm, "Does not have a namedCurve property"); + } + + // usages is expected to be provided for a key pair, but we are checking + // only a single key. The publicKey and privateKey portions of a key pair + // recognize only some of the usages appropriate for a key pair. + if (key.type === "public") { + ["encrypt", "verify", "wrapKey"].forEach(function(usage) { + if (usages.includes(usage)) { + correctUsages.push(usage); + } + }); + } else if (key.type === "private") { + ["decrypt", "sign", "unwrapKey", "deriveKey", "deriveBits"].forEach(function(usage) { + if (usages.includes(usage)) { + correctUsages.push(usage); + } + }); + } else { + correctUsages = usages; + } + + assert_equals((typeof key.usages), "object", key.type + " key.usages is an object"); + assert_not_equals(key.usages, null, key.type + " key.usages isn't null"); + + // The usages parameter could have repeats, but the usages + // property of the result should not. + var usageCount = 0; + key.usages.forEach(function(usage) { + usageCount += 1; + assert_in_array(usage, correctUsages, "Has " + usage + " usage"); + }); + assert_equals(key.usages.length, usageCount, "usages property is correct"); + assert_equals(key[Symbol.toStringTag], 'CryptoKey', "has the expected Symbol.toStringTag"); +} + + +// The algorithm parameter is an object with a name and other +// properties. Given the name, generate all valid parameters. +function allAlgorithmSpecifiersFor(algorithmName) { + var results = []; + + // RSA key generation is slow. Test a minimal set of parameters + var hashes = ["SHA-1", "SHA-256"]; + + // EC key generation is a lot faster. Check all curves in the spec + var curves = ["P-256", "P-384", "P-521"]; + + if (algorithmName.toUpperCase().substring(0, 3) === "AES") { + // Specifier properties are name and length + [128, 192, 256].forEach(function(length) { + results.push({name: algorithmName, length: length}); + }); + } else if (algorithmName.toUpperCase() === "HMAC") { + [ + {hash: "SHA-1", length: 160}, + {hash: "SHA-256", length: 256}, + {hash: "SHA-384", length: 384}, + {hash: "SHA-512", length: 512}, + {hash: "SHA-1"}, + {hash: "SHA-256"}, + {hash: "SHA-384"}, + {hash: "SHA-512"}, + ].forEach(function(hashAlgorithm) { + results.push({name: algorithmName, ...hashAlgorithm}); + }); + } else if (algorithmName.toUpperCase().substring(0, 3) === "RSA") { + hashes.forEach(function(hashName) { + results.push({name: algorithmName, hash: hashName, modulusLength: 2048, publicExponent: new Uint8Array([1,0,1])}); + }); + } else if (algorithmName.toUpperCase().substring(0, 2) === "EC") { + curves.forEach(function(curveName) { + results.push({name: algorithmName, namedCurve: curveName}); + }); + } else if (algorithmName.toUpperCase().substring(0, 1) === "X" || algorithmName.toUpperCase().substring(0, 2) === "ED") { + results.push({ name: algorithmName }); + } + + return results; +} + + +// Create every possible valid usages parameter, given legal +// usages. Note that an empty usages parameter is not always valid. +// +// There is an optional parameter - mandatoryUsages. If provided, +// it should be an array containing those usages of which one must be +// included. +function allValidUsages(validUsages, emptyIsValid, mandatoryUsages) { + if (typeof mandatoryUsages === "undefined") { + mandatoryUsages = []; + } + + var okaySubsets = []; + allNonemptySubsetsOf(validUsages).forEach(function(subset) { + if (mandatoryUsages.length === 0) { + okaySubsets.push(subset); + } else { + for (var i=0; i for copy/paste into tests. + // Sample usage: + // test.html?split=1000 + match = /(?:^\?|&)split=(\d+)(?:&|$)/.exec(location.search); + if (match) { + var testsPerVariant = parseInt(match[1], 10); + add_completion_callback(tests => { + var total = tests.length; + var template = ''; + var metas = []; + for (var i = 1; i < total - testsPerVariant; i = i + testsPerVariant) { + metas.push(template.replace("%s", i).replace("%s", i + testsPerVariant - 1)); + } + metas.push(template.replace("%s", i).replace("%s", "last")); + var pre = document.createElement('pre'); + pre.textContent = metas.join('\n'); + document.body.insertBefore(pre, document.body.firstChild); + document.getSelection().selectAllChildren(pre); + }); + } + } + /** + * Check if `currentSubTest` is in the subset specified in the URL. + * @param {number} currentSubTest + * @returns {boolean} + */ + function shouldRunSubTest(currentSubTest) { + return currentSubTest >= subTestStart && currentSubTest <= subTestEnd; + } + var currentSubTest = 0; + /** + * Only test a subset of tests with, e.g., `?1-10` in the URL. + * Can be used together with `` + * Sample usage: + * for (const test of tests) { + * subsetTest(async_test, test.fn, test.name); + * } + */ + function subsetTest(testFunc, ...args) { + currentSubTest++; + if (shouldRunSubTest(currentSubTest)) { + return testFunc(...args); + } + return null; + } + self.shouldRunSubTest = shouldRunSubTest; + self.subsetTest = subsetTest; +})();