LibCrypto+LibTLS: Add SECP256r1 support to LibTLS

Add the required methods to SECP256r1 to conform to the EllipticCurve
virtual base class. Using this updated version of SECP256r1, support in
LibTLS is implemented.
This commit is contained in:
Michiel Visser 2022-03-18 10:39:34 +01:00 committed by Ali Mohammad Pur
parent c1b041e761
commit 66d99c83d9
5 changed files with 35 additions and 6 deletions

View file

@ -195,13 +195,15 @@ TEST_CASE(test_secp256r1)
ReadonlyBytes bob_private_key { bob_private_key_data, 32 };
ReadonlyBytes bob_public_key { bob_public_key_data, 65 };
auto generated_alice_public = MUST(Crypto::Curves::SECP256r1::generate_public_key(alice_private_key));
Crypto::Curves::SECP256r1 curve;
auto generated_alice_public = MUST(curve.generate_public_key(alice_private_key));
EXPECT_EQ(alice_public_key, generated_alice_public);
auto generated_bob_public = MUST(Crypto::Curves::SECP256r1::generate_public_key(bob_private_key));
auto generated_bob_public = MUST(curve.generate_public_key(bob_private_key));
EXPECT_EQ(bob_public_key, generated_bob_public);
auto generated_public = MUST(Crypto::Curves::SECP256r1::generate_public_key({ private_key_data, 32 }));
auto generated_public = MUST(curve.generate_public_key({ private_key_data, 32 }));
ReadonlyBytes expected_public_key { expected_public_key_data, 65 };
EXPECT_EQ(expected_public_key, generated_public);
}

View file

@ -6,6 +6,7 @@
#include <AK/ByteReader.h>
#include <AK/Endian.h>
#include <AK/Random.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/UFixedBigInt.h>
@ -346,6 +347,13 @@ bool SECP256r1::is_point_on_curve(JacobianPoint const& point)
return temp.is_zero_constant_time();
}
ErrorOr<ByteBuffer> SECP256r1::generate_private_key()
{
auto buffer = TRY(ByteBuffer::create_uninitialized(32));
fill_with_random(buffer.data(), buffer.size());
return buffer;
}
ErrorOr<ByteBuffer> SECP256r1::generate_public_key(ReadonlyBytes a)
{
// clang-format off
@ -426,4 +434,14 @@ ErrorOr<ByteBuffer> SECP256r1::compute_coordinate(ReadonlyBytes scalar_bytes, Re
return buf;
}
ErrorOr<ByteBuffer> SECP256r1::derive_premaster_key(ReadonlyBytes shared_point)
{
VERIFY(shared_point.size() == 65);
VERIFY(shared_point[0] == 0x04);
ByteBuffer premaster_key = TRY(ByteBuffer::create_uninitialized(32));
premaster_key.overwrite(0, shared_point.data() + 1, 32);
return premaster_key;
}
}

View file

@ -8,6 +8,7 @@
#include <AK/ByteBuffer.h>
#include <AK/UFixedBigInt.h>
#include <LibCrypto/Curves/EllipticCurve.h>
namespace Crypto::Curves {
@ -17,10 +18,13 @@ struct JacobianPoint {
u256 z { 0u };
};
class SECP256r1 {
class SECP256r1 : public EllipticCurve {
public:
static ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes a);
static ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes);
size_t key_size() override { return 1 + 2 * 32; }
ErrorOr<ByteBuffer> generate_private_key() override;
ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes a) override;
ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override;
ErrorOr<ByteBuffer> derive_premaster_key(ReadonlyBytes shared_point) override;
private:
static u256 modular_reduce(u256 const& value);

View file

@ -12,6 +12,7 @@
#include <LibCore/Timer.h>
#include <LibCrypto/ASN1/DER.h>
#include <LibCrypto/Curves/EllipticCurve.h>
#include <LibCrypto/Curves/SECP256r1.h>
#include <LibCrypto/Curves/X25519.h>
#include <LibCrypto/Curves/X448.h>
#include <LibCrypto/PK/Code/EMSA_PKCS1_V1_5.h>
@ -311,6 +312,9 @@ ssize_t TLSv12::handle_ecdhe_rsa_server_key_exchange(ReadonlyBytes buffer)
case NamedCurve::x448:
m_context.server_key_exchange_curve = make<Crypto::Curves::X448>();
break;
case NamedCurve::secp256r1:
m_context.server_key_exchange_curve = make<Crypto::Curves::SECP256r1>();
break;
default:
return (i8)Error::NotUnderstood;
}

View file

@ -245,6 +245,7 @@ struct Options {
{ HashAlgorithm::SHA1, SignatureAlgorithm::RSA });
OPTION_WITH_DEFAULTS(Vector<NamedCurve>, elliptic_curves,
NamedCurve::x25519,
NamedCurve::secp256r1,
NamedCurve::x448)
OPTION_WITH_DEFAULTS(Vector<ECPointFormat>, supported_ec_point_formats, ECPointFormat::Uncompressed)