diff --git a/Libraries/LibCrypto/Certificate/Certificate.cpp b/Libraries/LibCrypto/Certificate/Certificate.cpp index 6750fae23a106..ef9f432ecf816 100644 --- a/Libraries/LibCrypto/Certificate/Certificate.cpp +++ b/Libraries/LibCrypto/Certificate/Certificate.cpp @@ -14,11 +14,6 @@ #include #include -namespace { -// Used by ASN1 macros -static String s_error_string; -} - namespace Crypto::Certificate { static ErrorOr parse_certificate_version(Crypto::ASN1::Decoder& decoder, Vector current_scope) diff --git a/Libraries/LibCrypto/Curves/SECPxxxr1.h b/Libraries/LibCrypto/Curves/SECPxxxr1.h index 13d9c08f81d57..24d99b5a8bf34 100644 --- a/Libraries/LibCrypto/Curves/SECPxxxr1.h +++ b/Libraries/LibCrypto/Curves/SECPxxxr1.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Michiel Visser + * Copyright (c) 2024, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -36,6 +37,16 @@ struct SECPxxxr1CurveParameters { struct SECPxxxr1Point { UnsignedBigInteger x; UnsignedBigInteger y; + size_t size; + + static ErrorOr scalar_to_bytes(UnsignedBigInteger const& a, size_t size) + { + auto a_bytes = TRY(ByteBuffer::create_uninitialized(a.byte_length())); + auto a_size = a.export_data(a_bytes.span()); + VERIFY(a_size >= size); + + return a_bytes.slice(a_size - size, size); + } static ErrorOr from_uncompressed(ReadonlyBytes data) { @@ -46,16 +57,30 @@ struct SECPxxxr1Point { return SECPxxxr1Point { UnsignedBigInteger::import_data(data.slice(1, half_size)), UnsignedBigInteger::import_data(data.slice(1 + half_size, half_size)), + half_size, }; } + ErrorOr x_bytes() const + { + return scalar_to_bytes(x, size); + } + + ErrorOr y_bytes() const + { + return scalar_to_bytes(y, size); + } + ErrorOr to_uncompressed() const { - auto bytes = TRY(ByteBuffer::create_uninitialized(1 + x.byte_length() + y.byte_length())); + auto x = TRY(x_bytes()); + auto y = TRY(y_bytes()); + + auto bytes = TRY(ByteBuffer::create_uninitialized(1 + (size * 2))); bytes[0] = 0x04; // uncompressed - auto x_size = x.export_data(bytes.span().slice(1)); - auto y_size = y.export_data(bytes.span().slice(1 + x_size)); - return bytes.slice(0, 1 + x_size + y_size); + memcpy(bytes.data() + 1, x.data(), size); + memcpy(bytes.data() + 1 + size, y.data(), size); + return bytes; } }; @@ -218,7 +243,11 @@ class SECPxxxr1 : public EllipticCurve { { VERIFY(scalar.byte_length() >= KEY_BYTE_SIZE); - return compute_coordinate_point(scalar, SECPxxxr1Point { UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1, KEY_BYTE_SIZE), UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1 + KEY_BYTE_SIZE, KEY_BYTE_SIZE) }); + return compute_coordinate_point(scalar, SECPxxxr1Point { + UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1, KEY_BYTE_SIZE), + UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1 + KEY_BYTE_SIZE, KEY_BYTE_SIZE), + KEY_BYTE_SIZE, + }); } ErrorOr compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override @@ -248,8 +277,9 @@ class SECPxxxr1 : public EllipticCurve { auto result_point = TRY(compute_coordinate_internal(scalar_int, JacobianPoint { point_x_int, point_y_int, 1u })); return SECPxxxr1Point { - .x = storage_type_to_unsigned_big_integer(result_point.x), - .y = storage_type_to_unsigned_big_integer(result_point.y), + storage_type_to_unsigned_big_integer(result_point.x), + storage_type_to_unsigned_big_integer(result_point.y), + KEY_BYTE_SIZE, }; } diff --git a/Libraries/LibCrypto/PK/EC.cpp b/Libraries/LibCrypto/PK/EC.cpp index 3aed0f32871d7..11d720f73b787 100644 --- a/Libraries/LibCrypto/PK/EC.cpp +++ b/Libraries/LibCrypto/PK/EC.cpp @@ -9,11 +9,6 @@ #include #include -namespace { -// Used by ASN1 macros -static String s_error_string; -} - namespace Crypto::PK { template<> @@ -23,9 +18,8 @@ ErrorOr ECPrivateKey::export_as_der() const TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr { TRY(encoder.write(1u)); // version - auto d_bytes = TRY(ByteBuffer::create_uninitialized(m_d.byte_length())); - auto d_size = m_d.export_data(d_bytes.span()); - TRY(encoder.write(d_bytes.span().slice(0, d_size))); + auto d = TRY(d_bytes()); + TRY(encoder.write(d)); if (m_parameters.has_value()) { TRY(encoder.write_constructed(ASN1::Class::Context, static_cast(0), [&]() -> ErrorOr { @@ -65,6 +59,7 @@ static ErrorOr> read_ec_public_key(ReadonlyBytes bytes, Vector { UnsignedBigInteger::import_data(bytes.slice(1, half_size)), UnsignedBigInteger::import_data(bytes.slice(1 + half_size, half_size)), + half_size, }; } else { ERROR_WITH_SCOPE("Unsupported public key format"); @@ -125,7 +120,7 @@ ErrorOr EC::parse_ec_key(ReadonlyBytes der, bool is_private, Ve keypair.public_key = maybe_public_key.release_value(); public_key = keypair.public_key; - if (keypair.public_key.x().byte_length() != private_key.byte_length() || keypair.public_key.y().byte_length() != private_key.byte_length()) { + if (keypair.public_key.scalar_size() != private_key_bytes.length()) { ERROR_WITH_SCOPE("Invalid public key length"); } @@ -133,7 +128,7 @@ ErrorOr EC::parse_ec_key(ReadonlyBytes der, bool is_private, Ve } } - keypair.private_key = ECPrivateKey { private_key, parameters, public_key }; + keypair.private_key = ECPrivateKey { private_key, private_key_bytes.length(), parameters, public_key }; EXIT_SCOPE(); return keypair; diff --git a/Libraries/LibCrypto/PK/EC.h b/Libraries/LibCrypto/PK/EC.h index 9f1195f260e5f..5ed61147d98c9 100644 --- a/Libraries/LibCrypto/PK/EC.h +++ b/Libraries/LibCrypto/PK/EC.h @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Crypto::PK { @@ -16,41 +17,62 @@ namespace Crypto::PK { template class ECPublicKey { public: - ECPublicKey(Integer x, Integer y) + ECPublicKey(Integer x, Integer y, size_t scalar_size) : m_x(move(x)) , m_y(move(y)) + , m_scalar_size(scalar_size) + { + } + + ECPublicKey(Curves::SECPxxxr1Point point) + : m_x(move(point.x)) + , m_y(move(point.y)) + , m_scalar_size(point.size) { } ECPublicKey() : m_x(0) , m_y(0) + , m_scalar_size(0) + { + } + + size_t scalar_size() const { return m_scalar_size; } + + ErrorOr x_bytes() const + { + return Curves::SECPxxxr1Point::scalar_to_bytes(m_x, m_scalar_size); + } + + ErrorOr y_bytes() const { + return Curves::SECPxxxr1Point::scalar_to_bytes(m_y, m_scalar_size); } - Integer const& x() const { return m_x; } - Integer const& y() const { return m_y; } + Curves::SECPxxxr1Point to_secpxxxr1_point() const + { + return Curves::SECPxxxr1Point { m_x, m_y, m_scalar_size }; + } ErrorOr to_uncompressed() const { - auto bytes = TRY(ByteBuffer::create_uninitialized(1 + m_x.byte_length() + m_y.byte_length())); - bytes[0] = 0x04; // uncompressed - auto x_size = m_x.export_data(bytes.span().slice(1)); - auto y_size = m_y.export_data(bytes.span().slice(1 + x_size)); - return bytes.slice(0, 1 + x_size + y_size); + return to_secpxxxr1_point().to_uncompressed(); } private: Integer m_x; Integer m_y; + size_t m_scalar_size; }; // https://www.rfc-editor.org/rfc/rfc5915#section-3 template class ECPrivateKey { public: - ECPrivateKey(Integer d, Optional> parameters, Optional> public_key) + ECPrivateKey(Integer d, size_t scalar_size, Optional> parameters, Optional> public_key) : m_d(move(d)) + , m_scalar_size(scalar_size) , m_parameters(parameters) , m_public_key(public_key) { @@ -59,6 +81,11 @@ class ECPrivateKey { ECPrivateKey() = default; Integer const& d() const { return m_d; } + ErrorOr d_bytes() const + { + return Curves::SECPxxxr1Point::scalar_to_bytes(m_d, m_scalar_size); + } + Optional const&> parameters() const { return m_parameters; } Optional const&> public_key() const { return m_public_key; } @@ -66,6 +93,8 @@ class ECPrivateKey { private: Integer m_d; + size_t m_scalar_size; + Optional> m_parameters; Optional> m_public_key; }; diff --git a/Libraries/LibCrypto/PK/RSA.cpp b/Libraries/LibCrypto/PK/RSA.cpp index 58a13ed010b77..ebba1ebca7065 100644 --- a/Libraries/LibCrypto/PK/RSA.cpp +++ b/Libraries/LibCrypto/PK/RSA.cpp @@ -13,11 +13,6 @@ #include #include -namespace { -// Used by ASN1 macros -static String s_error_string; -} - namespace Crypto::PK { ErrorOr RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, Vector current_scope) diff --git a/Libraries/LibTLS/HandshakeServer.cpp b/Libraries/LibTLS/HandshakeServer.cpp index c1c72f303521b..a84806c24ef7a 100644 --- a/Libraries/LibTLS/HandshakeServer.cpp +++ b/Libraries/LibTLS/HandshakeServer.cpp @@ -458,8 +458,7 @@ ssize_t TLSv12::verify_ecdsa_server_key_exchange(ReadonlyBytes server_key_info_b dbgln("verify_ecdsa_server_key_exchange failed: Attempting to verify signature without certificates"); return (i8)Error::NotSafe; } - auto server_public_key = m_context.certificates.first().public_key.ec; - auto server_point = Crypto::Curves::SECPxxxr1Point { server_public_key.x(), server_public_key.y() }; + auto server_point = m_context.certificates.first().public_key.ec.to_secpxxxr1_point(); auto message_result = ByteBuffer::create_uninitialized(64 + server_key_info_buffer.size()); if (message_result.is_error()) { diff --git a/Libraries/LibTLS/TLSv12.cpp b/Libraries/LibTLS/TLSv12.cpp index 77da37e30058a..34682150ef67e 100644 --- a/Libraries/LibTLS/TLSv12.cpp +++ b/Libraries/LibTLS/TLSv12.cpp @@ -371,8 +371,7 @@ bool Context::verify_certificate_pair(Certificate const& subject, Certificate co return false; } - auto public_key = issuer.public_key.ec; - auto public_point = Crypto::Curves::SECPxxxr1Point { public_key.x(), public_key.y() }; + auto public_point = issuer.public_key.ec.to_secpxxxr1_point(); auto maybe_signature = Crypto::Curves::SECPxxxr1Signature::from_asn(subject.signature_value, {}); if (maybe_signature.is_error()) { diff --git a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index bc7b946479b33..1bf43e9f4441d 100644 --- a/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -2304,7 +2304,7 @@ WebIDL::ExceptionOr, GC::Ref>> ECDSA:: return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string); auto public_key_data = maybe_public_key_data.release_value(); - auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data.x, public_key_data.y }; + auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data }; // 7. Let algorithm be a new EcKeyAlgorithm object. auto algorithm = EcKeyAlgorithm::create(m_realm); @@ -2331,7 +2331,7 @@ WebIDL::ExceptionOr, GC::Ref>> ECDSA:: public_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Verify } })); // 15. Let privateKey be a new CryptoKey representing the private key of the generated key pair. - auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, {}, ec_public_key }; + auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, public_key_data.size, {}, ec_public_key }; auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key }); // 16. Set the [[type]] internal slot of privateKey to "private" @@ -2512,7 +2512,7 @@ WebIDL::ExceptionOr ECDSA::verify(AlgorithmParams const& params, GC:: auto maybe_result = curve.visit( [](Empty const&) -> ErrorOr { return Error::from_string_literal("Failed to create valid crypto instance"); }, - [&](auto instance) { return instance.verify_point(M, ::Crypto::Curves::SECPxxxr1Point { Q.x(), Q.y() }, ::Crypto::Curves::SECPxxxr1Signature { r, s }); }); + [&](auto instance) { return instance.verify_point(M, Q.to_secpxxxr1_point(), ::Crypto::Curves::SECPxxxr1Signature { r, s }); }); if (maybe_result.is_error()) { auto error_message = MUST(String::from_utf8(maybe_result.error().string_literal())); @@ -2839,6 +2839,7 @@ WebIDL::ExceptionOr> ECDSA::import_key(AlgorithmParams const& auto public_key = ::Crypto::PK::ECPublicKey<> { ::Crypto::UnsignedBigInteger::import_data(x_bytes), ::Crypto::UnsignedBigInteger::import_data(y_bytes), + coord_size, }; // If the d field is present: @@ -2856,6 +2857,7 @@ WebIDL::ExceptionOr> ECDSA::import_key(AlgorithmParams const& // by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA]. auto private_key = ::Crypto::PK::ECPrivateKey<> { ::Crypto::UnsignedBigInteger::import_data(d_bytes), + coord_size, {}, public_key, }; @@ -3130,46 +3132,39 @@ WebIDL::ExceptionOr> ECDSA::export_key(Bindings::KeyFormat f auto maybe_error = handle.visit( [&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr { // 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA]. - auto x_bytes = TRY(ByteBuffer::create_uninitialized(public_key.x().byte_length())); - auto x_size = public_key.x().export_data(x_bytes); - jwk.x = TRY(encode_base64url(x_bytes.span().slice(0, x_size), AK::OmitPadding::Yes)); + auto x_bytes = TRY(public_key.x_bytes()); + jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes)); // 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA]. - auto y_bytes = TRY(ByteBuffer::create_uninitialized(public_key.y().byte_length())); - auto y_size = public_key.y().export_data(y_bytes); - jwk.y = TRY(encode_base64url(y_bytes.span().slice(0, y_size), AK::OmitPadding::Yes)); + auto y_bytes = TRY(public_key.y_bytes()); + jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes)); return {}; }, [&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr { - size_t coord_size; Variant curve; - if (algorithm.named_curve() == "P-256"sv) { + if (algorithm.named_curve() == "P-256"sv) curve = ::Crypto::Curves::SECP256r1 {}; - coord_size = 32; - } else if (algorithm.named_curve() == "P-384"sv) { + else if (algorithm.named_curve() == "P-384"sv) curve = ::Crypto::Curves::SECP384r1 {}; - coord_size = 48; - } else if (algorithm.named_curve() == "P-521"sv) { + else if (algorithm.named_curve() == "P-521"sv) curve = ::Crypto::Curves::SECP521r1 {}; - coord_size = 66; - } else { + else VERIFY_NOT_REACHED(); - } auto maybe_public_key = curve.visit( [](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); }, [&](auto instance) { return instance.generate_public_key_point(private_key.d()); }); auto public_key = TRY(maybe_public_key); - auto public_key_bytes = TRY(public_key.to_uncompressed()); - VERIFY(public_key_bytes[0] == 0x04); + auto x_bytes = TRY(public_key.x_bytes()); + auto y_bytes = TRY(public_key.y_bytes()); // 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA]. - jwk.x = TRY(encode_base64url(public_key_bytes.span().slice(1, coord_size), AK::OmitPadding::Yes)); + jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes)); // 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA]. - jwk.y = TRY(encode_base64url(public_key_bytes.span().slice(1 + coord_size, coord_size), AK::OmitPadding::Yes)); + jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes)); return {}; }, @@ -3185,9 +3180,8 @@ WebIDL::ExceptionOr> ECDSA::export_key(Bindings::KeyFormat f auto maybe_error = handle.visit( [&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr { // Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA]. - auto d_bytes = TRY(ByteBuffer::create_uninitialized(private_key.d().byte_length())); - auto d_size = private_key.d().export_data(d_bytes); - jwk.d = TRY(encode_base64url(d_bytes.span().slice(0, d_size), AK::OmitPadding::Yes)); + auto d_bytes = TRY(private_key.d_bytes()); + jwk.d = TRY(encode_base64url(d_bytes, AK::OmitPadding::Yes)); return {}; }, @@ -3320,7 +3314,7 @@ WebIDL::ExceptionOr, GC::Ref>> ECDH::g return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string); auto public_key_data = maybe_public_key_data.release_value(); - auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data.x, public_key_data.y }; + auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data }; // 4. Let algorithm be a new EcKeyAlgorithm object. auto algorithm = EcKeyAlgorithm::create(m_realm); @@ -3347,7 +3341,7 @@ WebIDL::ExceptionOr, GC::Ref>> ECDH::g public_key->set_usages({}); // 12. Let privateKey be a new CryptoKey representing the private key of the generated key pair. - auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, {}, ec_public_key }; + auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, public_key_data.size, {}, ec_public_key }; auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key }); // 13. Set the [[type]] internal slot of privateKey to "private" @@ -3424,7 +3418,7 @@ WebIDL::ExceptionOr> ECDH::derive_bits(AlgorithmParams auto maybe_secret = curve.visit( [](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); }, - [&private_key_data, &public_key_data](auto instance) { return instance.compute_coordinate_point(private_key_data.d(), ::Crypto::Curves::SECPxxxr1Point { public_key_data.x(), public_key_data.y() }); }); + [&private_key_data, &public_key_data](auto instance) { return instance.compute_coordinate_point(private_key_data.d(), public_key_data.to_secpxxxr1_point()); }); if (maybe_secret.is_error()) { auto message = TRY_OR_THROW_OOM(realm.vm(), String::formatted("Failed to compute secret: {}", maybe_secret.error())); @@ -3741,6 +3735,7 @@ WebIDL::ExceptionOr> ECDH::import_key(AlgorithmParams const& auto public_key = ::Crypto::PK::ECPublicKey<> { ::Crypto::UnsignedBigInteger::import_data(x_bytes), ::Crypto::UnsignedBigInteger::import_data(y_bytes), + coord_size, }; // If the d field is present: @@ -3758,6 +3753,7 @@ WebIDL::ExceptionOr> ECDH::import_key(AlgorithmParams const& // by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA]. auto private_key = ::Crypto::PK::ECPrivateKey<> { ::Crypto::UnsignedBigInteger::import_data(d_bytes), + coord_size, {}, public_key, }; @@ -4023,46 +4019,39 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo auto maybe_error = handle.visit( [&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr { // 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA]. - auto x_bytes = TRY(ByteBuffer::create_uninitialized(public_key.x().byte_length())); - auto x_size = public_key.x().export_data(x_bytes); - jwk.x = TRY(encode_base64url(x_bytes.span().slice(0, x_size), AK::OmitPadding::Yes)); + auto x_bytes = TRY(public_key.x_bytes()); + jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes)); // 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA]. - auto y_bytes = TRY(ByteBuffer::create_uninitialized(public_key.y().byte_length())); - auto y_size = public_key.y().export_data(y_bytes); - jwk.y = TRY(encode_base64url(y_bytes.span().slice(0, y_size), AK::OmitPadding::Yes)); + auto y_bytes = TRY(public_key.y_bytes()); + jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes)); return {}; }, [&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr { - size_t coord_size; Variant curve; - if (algorithm.named_curve() == "P-256"sv) { + if (algorithm.named_curve() == "P-256"sv) curve = ::Crypto::Curves::SECP256r1 {}; - coord_size = 32; - } else if (algorithm.named_curve() == "P-384"sv) { + else if (algorithm.named_curve() == "P-384"sv) curve = ::Crypto::Curves::SECP384r1 {}; - coord_size = 48; - } else if (algorithm.named_curve() == "P-521"sv) { + else if (algorithm.named_curve() == "P-521"sv) curve = ::Crypto::Curves::SECP521r1 {}; - coord_size = 66; - } else { + else VERIFY_NOT_REACHED(); - } auto maybe_public_key = curve.visit( [](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); }, [&](auto instance) { return instance.generate_public_key_point(private_key.d()); }); auto public_key = TRY(maybe_public_key); - auto public_key_bytes = TRY(public_key.to_uncompressed()); - VERIFY(public_key_bytes[0] == 0x04); + auto x_bytes = TRY(public_key.x_bytes()); + auto y_bytes = TRY(public_key.y_bytes()); // 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA]. - jwk.x = TRY(encode_base64url(public_key_bytes.span().slice(1, coord_size), AK::OmitPadding::Yes)); + jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes)); // 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA]. - jwk.y = TRY(encode_base64url(public_key_bytes.span().slice(1 + coord_size, coord_size), AK::OmitPadding::Yes)); + jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes)); return {}; }, @@ -4078,9 +4067,8 @@ WebIDL::ExceptionOr> ECDH::export_key(Bindings::KeyFormat fo auto maybe_error = handle.visit( [&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr { // Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA]. - auto d_bytes = TRY(ByteBuffer::create_uninitialized(private_key.d().byte_length())); - auto d_size = private_key.d().export_data(d_bytes); - jwk.d = TRY(encode_base64url(d_bytes.span().slice(0, d_size), AK::OmitPadding::Yes)); + auto d_bytes = TRY(private_key.d_bytes()); + jwk.d = TRY(encode_base64url(d_bytes, AK::OmitPadding::Yes)); return {}; }, diff --git a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt index 48fc5558e41c7..25c0669ddf8b3 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/WebCryptoAPI/import_export/ec_importKey.https.any.txt @@ -2,8 +2,8 @@ Harness status: OK Found 246 tests -174 Pass -24 Fail +192 Pass +6 Fail 48 Optional Feature Unsupported Pass Good parameters: P-256 bits (spki, buffer(91), {name: ECDSA, namedCurve: P-256}, true, [verify]) Optional Feature Unsupported Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify]) @@ -89,23 +89,23 @@ Pass Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-3 Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign]) Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign, sign]) Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, []) -Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify]) +Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify]) Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify]) -Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify]) +Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify]) Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify]) -Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, []) Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, []) Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) +Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) -Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) +Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, []) Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign]) Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign]) @@ -211,16 +211,16 @@ Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: E Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, []) -Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, []) Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, []) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, alg), {name: ECDH, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, []) +Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, []) Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, []) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) -Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits]) +Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits]) Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, []) Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey]) Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey])