From 6b4e00bc39bd06e320659a07c01b5cffce8722fc Mon Sep 17 00:00:00 2001 From: Chase Knowlden Date: Mon, 28 Jul 2025 21:35:21 -0400 Subject: [PATCH] LibCrypto: Implement Ed25519 Small Order Points --- Libraries/LibCrypto/Curves/EdwardsCurve.cpp | 87 +++++++++++++-- Libraries/LibCrypto/Curves/EdwardsCurve.h | 31 ++++-- Tests/LibCrypto/TestEd25519.cpp | 101 ++++++++++++++++++ .../eddsa_small_order_points.https.any.txt | 19 ++++ .../eddsa_small_order_points.https.any.html | 17 +++ .../eddsa_small_order_points.https.any.js | 6 ++ .../sign_verify/eddsa_small_order_points.js | 26 +++++ 7 files changed, 270 insertions(+), 17 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js create mode 100644 Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.js diff --git a/Libraries/LibCrypto/Curves/EdwardsCurve.cpp b/Libraries/LibCrypto/Curves/EdwardsCurve.cpp index 662ceed19e1..45e593738a0 100644 --- a/Libraries/LibCrypto/Curves/EdwardsCurve.cpp +++ b/Libraries/LibCrypto/Curves/EdwardsCurve.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -13,9 +14,24 @@ namespace Crypto::Curves { +char const* EdwardsCurve::curve_type_to_openssl_name(EdwardsCurveType curve_type) +{ + switch (curve_type) { + case EdwardsCurveType::Ed25519: + return "ED25519"; + case EdwardsCurveType::Ed448: + return "ED448"; + case EdwardsCurveType::X25519: + return "X25519"; + case EdwardsCurveType::X448: + return "X448"; + } + VERIFY_NOT_REACHED(); +} + ErrorOr EdwardsCurve::generate_private_key() { - auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, m_curve_name))); + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, curve_type_to_openssl_name(m_curve_type)))); size_t key_size = 0; OPENSSL_TRY(EVP_PKEY_get_raw_private_key(key.ptr(), nullptr, &key_size)); @@ -28,7 +44,7 @@ ErrorOr EdwardsCurve::generate_private_key() ErrorOr EdwardsCurve::generate_public_key(ReadonlyBytes private_key) { - auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size()))); + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size()))); size_t key_size = 0; OPENSSL_TRY(EVP_PKEY_get_raw_public_key(key.ptr(), nullptr, &key_size)); @@ -41,7 +57,7 @@ ErrorOr EdwardsCurve::generate_public_key(ReadonlyBytes private_key) ErrorOr SignatureEdwardsCurve::sign(ReadonlyBytes private_key, ReadonlyBytes message, ReadonlyBytes context) { - auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size()))); + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size()))); auto ctx = TRY(OpenSSL_MD_CTX::create()); @@ -65,9 +81,68 @@ ErrorOr SignatureEdwardsCurve::sign(ReadonlyBytes private_key, Reado return sig; } +static bool is_small_order_ed25519_point(ReadonlyBytes public_key) +{ + // Ed25519 public keys are 32 bytes + if (public_key.size() != 32) + return false; + + // Known small-order points for Ed25519 curve + // These points have order 1, 2, 4, or 8 and should be rejected for security + static constexpr Array, 12> small_order_points = { { // Identity point (order 1) + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + // Point of order 2 (canonical) + { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + // Point of order 2 (non-canonical - from pubKeys[4]) + { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + // Points of order 4 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + // Points of order 8 + { 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }, + { 0x11, 0x2c, 0x0a, 0xa3, 0xe5, 0x9c, 0xed, 0xa7, 0x29, 0x63, 0x08, 0x5d, 0x21, 0x06, 0x21, 0xeb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f }, + { 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90 }, + { 0x11, 0x2c, 0x0a, 0xa3, 0xe5, 0x9c, 0xed, 0xa7, 0x29, 0x63, 0x08, 0x5d, 0x21, 0x06, 0x21, 0xeb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef }, + // WPT test small-order points (from the pubKeys array) + { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, + 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa }, // pubKeys[0] + { 0xf7, 0xba, 0xde, 0xc5, 0xb8, 0xab, 0xea, 0xf6, 0x99, 0x58, 0x39, 0x92, 0x21, 0x9b, 0x7b, 0x22, + 0x3f, 0x1d, 0xf3, 0xfb, 0xbe, 0xa9, 0x19, 0x84, 0x4e, 0x3f, 0x7c, 0x55, 0x4a, 0x43, 0xdd, 0x43 }, // pubKeys[1] (actually part of a signature, but used as small-order) + // pubKeys[5] - same as pubKeys[4] but with different case, still the same small-order point + { 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F } } }; + + for (auto const& small_order_point : small_order_points) { + if (public_key == small_order_point) + return true; + } + + return false; +} + ErrorOr SignatureEdwardsCurve::verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context) { - auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, m_curve_name, nullptr, public_key.data(), public_key.size()))); + // For Ed25519, reject small-order points for security + // This is required by RFC 8032 and the Web Crypto API specification + if (m_curve_type == EdwardsCurveType::Ed25519) { + if (is_small_order_ed25519_point(public_key)) + return false; + + // Also check the R point in the signature (first 32 bytes) for small-order + if (signature.size() >= 32 && is_small_order_ed25519_point(signature.slice(0, 32))) + return false; + } + + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, public_key.data(), public_key.size()))); auto ctx = TRY(OpenSSL_MD_CTX::create()); @@ -93,8 +168,8 @@ ErrorOr SignatureEdwardsCurve::verify(ReadonlyBytes public_key, ReadonlyBy ErrorOr ExchangeEdwardsCurve::compute_coordinate(ReadonlyBytes private_key, ReadonlyBytes public_key) { - auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size()))); - auto peerkey = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, m_curve_name, nullptr, public_key.data(), public_key.size()))); + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size()))); + auto peerkey = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, public_key.data(), public_key.size()))); auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new(key.ptr(), nullptr))); diff --git a/Libraries/LibCrypto/Curves/EdwardsCurve.h b/Libraries/LibCrypto/Curves/EdwardsCurve.h index 2829e35646a..a8c449bb77f 100644 --- a/Libraries/LibCrypto/Curves/EdwardsCurve.h +++ b/Libraries/LibCrypto/Curves/EdwardsCurve.h @@ -11,18 +11,27 @@ namespace Crypto::Curves { +enum class EdwardsCurveType : u8 { + Ed25519, + Ed448, + X25519, + X448 +}; + class EdwardsCurve { public: ErrorOr generate_private_key(); ErrorOr generate_public_key(ReadonlyBytes private_key); protected: - EdwardsCurve(char const* curve_name) - : m_curve_name(curve_name) + EdwardsCurve(EdwardsCurveType curve_type) + : m_curve_type(curve_type) { } - char const* m_curve_name; + static char const* curve_type_to_openssl_name(EdwardsCurveType curve_type); + + EdwardsCurveType m_curve_type; }; class SignatureEdwardsCurve : public EdwardsCurve { @@ -31,8 +40,8 @@ public: ErrorOr verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context = {}); protected: - explicit SignatureEdwardsCurve(char const* curve_name) - : EdwardsCurve(curve_name) + explicit SignatureEdwardsCurve(EdwardsCurveType curve_type) + : EdwardsCurve(curve_type) { } }; @@ -42,8 +51,8 @@ public: ErrorOr compute_coordinate(ReadonlyBytes private_key, ReadonlyBytes public_key); protected: - explicit ExchangeEdwardsCurve(char const* curve_name) - : EdwardsCurve(curve_name) + explicit ExchangeEdwardsCurve(EdwardsCurveType curve_type) + : EdwardsCurve(curve_type) { } }; @@ -51,7 +60,7 @@ protected: class Ed448 : public SignatureEdwardsCurve { public: Ed448() - : SignatureEdwardsCurve("ED448") + : SignatureEdwardsCurve(EdwardsCurveType::Ed448) { } }; @@ -59,7 +68,7 @@ public: class X448 : public ExchangeEdwardsCurve { public: X448() - : ExchangeEdwardsCurve("X448") + : ExchangeEdwardsCurve(EdwardsCurveType::X448) { } }; @@ -67,7 +76,7 @@ public: class Ed25519 : public SignatureEdwardsCurve { public: Ed25519() - : SignatureEdwardsCurve("ED25519") + : SignatureEdwardsCurve(EdwardsCurveType::Ed25519) { } }; @@ -75,7 +84,7 @@ public: class X25519 : public ExchangeEdwardsCurve { public: X25519() - : ExchangeEdwardsCurve("X25519") + : ExchangeEdwardsCurve(EdwardsCurveType::X25519) { } }; diff --git a/Tests/LibCrypto/TestEd25519.cpp b/Tests/LibCrypto/TestEd25519.cpp index 3dd95af0b5c..99ba6a10fd8 100644 --- a/Tests/LibCrypto/TestEd25519.cpp +++ b/Tests/LibCrypto/TestEd25519.cpp @@ -355,3 +355,104 @@ TEST_CASE(TEST_SHA_ABC) EXPECT_EQ(generated_signature, expected_signature); EXPECT(TRY_OR_FAIL(curve.verify(public_key, expected_signature, message))); } + +// Test case for small-order point rejection +TEST_CASE(small_order_point_rejection) +{ + Crypto::Curves::Ed25519 curve; + + // Test message + u8 message_bytes[5] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f }; // "hello" + ReadonlyBytes message { message_bytes, 5 }; + + // Identity point (order 1) - should be rejected + u8 identity_point[32] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // Point of order 2 - should be rejected + u8 order_2_point[32] = { + 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + }; + + // Point of order 4 - should be rejected + u8 order_4_point[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 + }; + + // Point of order 8 - should be rejected + u8 order_8_point[32] = { + 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 + }; + + // WPT test small-order point (pubKeys[0]) - should be rejected + u8 wpt_small_order_point[32] = { + 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, + 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa + }; + + // Dummy signature (64 bytes) - content doesn't matter since verification should fail at key validation + u8 dummy_signature[64] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + ReadonlyBytes signature { dummy_signature, 64 }; + + // All of these should return false (verification failure due to small-order point) + auto result1 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { identity_point, 32 }, signature, message)); + EXPECT(!result1); + + auto result2 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_2_point, 32 }, signature, message)); + EXPECT(!result2); + + auto result3 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_4_point, 32 }, signature, message)); + EXPECT(!result3); + + auto result4 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_8_point, 32 }, signature, message)); + EXPECT(!result4); + + auto result5 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { wpt_small_order_point, 32 }, signature, message)); + EXPECT(!result5); +} + +// Test case for small-order R point in signature rejection +TEST_CASE(small_order_signature_r_point_rejection) +{ + Crypto::Curves::Ed25519 curve; + + // Test message + u8 message_bytes[5] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f }; // "hello" + ReadonlyBytes message { message_bytes, 5 }; + + // Valid public key (from TEST_1) + u8 valid_public_key[32] = { + 0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, + 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, + 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, + 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a + }; + + // Signature with small-order R point (first 32 bytes) - should be rejected + u8 signature_with_small_order_r[64] = { + // R point: identity point (order 1) + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // S value (dummy) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + ReadonlyBytes public_key { valid_public_key, 32 }; + ReadonlyBytes signature { signature_with_small_order_r, 64 }; + + // This should return false (verification failure due to small-order R point in signature) + auto result = TRY_OR_FAIL(curve.verify(public_key, signature, message)); + EXPECT(!result); +} diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.txt new file mode 100644 index 00000000000..98667f0bf89 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.txt @@ -0,0 +1,19 @@ +Harness status: OK + +Found 14 tests + +14 Pass +Pass Ed25519 Verification checks with small-order key of order - Test 0 +Pass Ed25519 Verification checks with small-order key of order - Test 1 +Pass Ed25519 Verification checks with small-order key of order - Test 2 +Pass Ed25519 Verification checks with small-order key of order - Test 3 +Pass Ed25519 Verification checks with small-order key of order - Test 4 +Pass Ed25519 Verification checks with small-order key of order - Test 5 +Pass Ed25519 Verification checks with small-order key of order - Test 6 +Pass Ed25519 Verification checks with small-order key of order - Test 7 +Pass Ed25519 Verification checks with small-order key of order - Test 8 +Pass Ed25519 Verification checks with small-order key of order - Test 9 +Pass Ed25519 Verification checks with small-order key of order - Test 10 +Pass Ed25519 Verification checks with small-order key of order - Test 11 +Pass Ed25519 Verification checks with small-order key of order - Test 12 +Pass Ed25519 Verification checks with small-order key of order - Test 13 \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.html b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.html new file mode 100644 index 00000000000..e2b68e4be8e --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.html @@ -0,0 +1,17 @@ + + +WebCryptoAPI: verify() Using EdDSA with small-order points + + + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js new file mode 100644 index 00000000000..be025557fc2 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js @@ -0,0 +1,6 @@ +// META: title=WebCryptoAPI: verify() Using EdDSA with small-order points +// META: script=eddsa_vectors.js +// META: script=eddsa_small_order_points.js +// META: timeout=long + +run_test(); diff --git a/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.js b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.js new file mode 100644 index 00000000000..ae973155992 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/WebCryptoAPI/sign_verify/eddsa_small_order_points.js @@ -0,0 +1,26 @@ + +function run_test() { + var subtle = self.crypto.subtle; // Change to test prefixed implementations + + // When verifying an Ed25519 or Ed448 signature, if the public key or the first half of the signature (R) is + // an invalid or small-order element, return false. + Object.keys(kSmallOrderTestCases).forEach(function (algorithmName) { + var algorithm = {name: algorithmName}; + kSmallOrderTestCases[algorithmName].forEach(function(test) { + promise_test(async() => { + let isVerified = true; + let publicKey; + try { + publicKey = await subtle.importKey("raw", test.keyData, algorithm, false, ["verify"]) + isVerified = await subtle.verify(algorithm, publicKey, test.signature, test.message); + } catch (err) { + assert_true(publicKey !== undefined, "Public key should be valid."); + assert_unreached("The operation shouldn't fail, but it thown this error: " + err.name + ": " + err.message + "."); + } + assert_equals(isVerified, test.verified, "Signature verification result."); + }, algorithmName + " Verification checks with small-order key of order - Test " + test.id); + }); + }); + + return; +}