From bce28936381efc43de764628a3e4452cd0b6d3e0 Mon Sep 17 00:00:00 2001 From: devgianlu Date: Thu, 5 Dec 2024 14:28:05 +0100 Subject: [PATCH] LibCrypto: Add utility functions to `SECPxxxr1` This allows to move ASN1 logic from inside the `SECPxxxr1` curve itself to the data structures. It makes more sense to have dedicated and explicit methods to handle transformation between formats. --- Libraries/LibCrypto/Curves/SECPxxxr1.h | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Libraries/LibCrypto/Curves/SECPxxxr1.h b/Libraries/LibCrypto/Curves/SECPxxxr1.h index 4d089a468ba..2344a666b80 100644 --- a/Libraries/LibCrypto/Curves/SECPxxxr1.h +++ b/Libraries/LibCrypto/Curves/SECPxxxr1.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -17,6 +18,11 @@ #include #include +namespace { +// Used by ASN1 macros +static String s_error_string; +} + namespace Crypto::Curves { struct SECPxxxr1CurveParameters { @@ -31,6 +37,18 @@ struct SECPxxxr1Point { UnsignedBigInteger x; UnsignedBigInteger y; + static ErrorOr from_uncompressed(ReadonlyBytes data) + { + if (data.size() < 1 || data[0] != 0x04) + return Error::from_string_literal("Invalid length or not an uncompressed SECPxxxr1 point"); + + auto half_size = (data.size() - 1) / 2; + return SECPxxxr1Point { + UnsignedBigInteger::import_data(data.slice(1, half_size)), + UnsignedBigInteger::import_data(data.slice(1 + half_size, half_size)), + }; + } + ErrorOr to_uncompressed() const { auto bytes = TRY(ByteBuffer::create_uninitialized(1 + x.byte_length() + y.byte_length())); @@ -44,6 +62,27 @@ struct SECPxxxr1Point { struct SECPxxxr1Signature { UnsignedBigInteger r; UnsignedBigInteger s; + + static ErrorOr from_asn(ReadonlyBytes signature, Vector current_scope) + { + ASN1::Decoder decoder(signature); + ENTER_TYPED_SCOPE(Sequence, "SECPxxxr1Signature"); + READ_OBJECT(Integer, UnsignedBigInteger, r_big_int); + READ_OBJECT(Integer, UnsignedBigInteger, s_big_int); + return SECPxxxr1Signature { r_big_int, s_big_int }; + } + + ErrorOr to_asn() + { + ASN1::Encoder encoder; + TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr { + TRY(encoder.write(r)); + TRY(encoder.write(s)); + return {}; + })); + + return encoder.finish(); + } }; template