mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:37:35 +00:00
LibTLS: Add support for curve x448
This commit is contained in:
parent
0df7ad7493
commit
125a43e203
3 changed files with 78 additions and 16 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include <LibCrypto/ASN1/DER.h>
|
#include <LibCrypto/ASN1/DER.h>
|
||||||
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
||||||
#include <LibCrypto/Curves/X25519.h>
|
#include <LibCrypto/Curves/X25519.h>
|
||||||
|
#include <LibCrypto/Curves/X448.h>
|
||||||
#include <LibCrypto/NumberTheory/ModularFunctions.h>
|
#include <LibCrypto/NumberTheory/ModularFunctions.h>
|
||||||
#include <LibCrypto/PK/Code/EMSA_PSS.h>
|
#include <LibCrypto/PK/Code/EMSA_PSS.h>
|
||||||
#include <LibTLS/TLSv12.h>
|
#include <LibTLS/TLSv12.h>
|
||||||
|
@ -294,19 +295,68 @@ void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder)
|
||||||
builder.append(dh_Yc_bytes);
|
builder.append(dh_Yc_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> TLSv12::named_curve_multiply(NamedCurve curve, ReadonlyBytes a, ReadonlyBytes b)
|
||||||
|
{
|
||||||
|
switch (curve) {
|
||||||
|
case NamedCurve::x25519:
|
||||||
|
return Crypto::Curves::X25519::compute_coordinate(a, b);
|
||||||
|
case NamedCurve::x448:
|
||||||
|
return Crypto::Curves::X448::compute_coordinate(a, b);
|
||||||
|
default:
|
||||||
|
dbgln("No known handler for multiplying curve {}", static_cast<u16>(curve));
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> TLSv12::named_curve_generator_point(NamedCurve curve)
|
||||||
|
{
|
||||||
|
auto key_size = named_curve_key_size(curve) / 8;
|
||||||
|
|
||||||
|
auto generator_point_data_result = ByteBuffer::create_zeroed(key_size);
|
||||||
|
if (generator_point_data_result.is_error()) {
|
||||||
|
dbgln("Failed to generate curve multiplication point: not enough memory");
|
||||||
|
return AK::Error::from_string_literal("Failed to generate curve multiplication point: not enough memory");
|
||||||
|
}
|
||||||
|
auto generator_point_data = generator_point_data_result.release_value();
|
||||||
|
|
||||||
|
switch (curve) {
|
||||||
|
case NamedCurve::x25519:
|
||||||
|
ByteReader::store(generator_point_data.offset_pointer(0), 9);
|
||||||
|
break;
|
||||||
|
case NamedCurve::x448:
|
||||||
|
ByteReader::store(generator_point_data.offset_pointer(0), 5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbgln("No known handler for generator point of curve {}", static_cast<u16>(curve));
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
return generator_point_data;
|
||||||
|
}
|
||||||
|
|
||||||
void TLSv12::build_ecdhe_rsa_pre_master_secret(PacketBuilder& builder)
|
void TLSv12::build_ecdhe_rsa_pre_master_secret(PacketBuilder& builder)
|
||||||
{
|
{
|
||||||
size_t const key_size = named_curve_key_size(NamedCurve::x25519) / 8;
|
size_t const key_size = named_curve_key_size(m_context.server_curve_choice) / 8;
|
||||||
u8 generator_point[key_size] { 9 };
|
auto generator_point_result = named_curve_generator_point(m_context.server_curve_choice);
|
||||||
ReadonlyBytes generator_point_bytes { generator_point, key_size };
|
if (generator_point_result.is_error()) {
|
||||||
|
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto generator_point = generator_point_result.release_value();
|
||||||
|
ReadonlyBytes generator_point_bytes = generator_point;
|
||||||
|
|
||||||
// Create a random private key
|
// Create a random private key
|
||||||
u8 private_key[key_size];
|
auto private_key_result = ByteBuffer::create_uninitialized(key_size);
|
||||||
fill_with_random(private_key, key_size);
|
if (private_key_result.is_error()) {
|
||||||
ReadonlyBytes private_key_bytes { private_key, key_size };
|
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto private_key = private_key_result.release_value();
|
||||||
|
fill_with_random(private_key.data(), key_size);
|
||||||
|
ReadonlyBytes private_key_bytes = private_key;
|
||||||
|
|
||||||
// Calculate the public key by multiplying the private key with 9
|
// Calculate the public key by multiplying the private key with the generator point
|
||||||
auto public_key_result = Crypto::Curves::X25519::compute_coordinate(private_key_bytes, generator_point_bytes);
|
auto public_key_result = named_curve_multiply(m_context.server_curve_choice, private_key_bytes, generator_point_bytes);
|
||||||
if (public_key_result.is_error()) {
|
if (public_key_result.is_error()) {
|
||||||
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||||
return;
|
return;
|
||||||
|
@ -315,7 +365,7 @@ void TLSv12::build_ecdhe_rsa_pre_master_secret(PacketBuilder& builder)
|
||||||
|
|
||||||
// Calculate the pre master secret by multiplying the client private key and the server public key
|
// Calculate the pre master secret by multiplying the client private key and the server public key
|
||||||
ReadonlyBytes server_public_key_bytes = m_context.server_diffie_hellman_params.p;
|
ReadonlyBytes server_public_key_bytes = m_context.server_diffie_hellman_params.p;
|
||||||
auto pre_master_secret_result = Crypto::Curves::X25519::compute_coordinate(private_key_bytes, server_public_key_bytes);
|
auto pre_master_secret_result = named_curve_multiply(m_context.server_curve_choice, private_key_bytes, server_public_key_bytes);
|
||||||
if (pre_master_secret_result.is_error()) {
|
if (pre_master_secret_result.is_error()) {
|
||||||
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -290,21 +290,26 @@ ssize_t TLSv12::handle_dhe_rsa_server_key_exchange(ReadonlyBytes buffer)
|
||||||
|
|
||||||
ssize_t TLSv12::handle_ecdhe_rsa_server_key_exchange(ReadonlyBytes buffer)
|
ssize_t TLSv12::handle_ecdhe_rsa_server_key_exchange(ReadonlyBytes buffer)
|
||||||
{
|
{
|
||||||
auto x25519_key_size_bytes = named_curve_key_size(NamedCurve::x25519) / 8;
|
size_t size_required_for_curve_name = 6;
|
||||||
if (buffer.size() < x25519_key_size_bytes + 7)
|
if (buffer.size() < size_required_for_curve_name)
|
||||||
return (i8)Error::NeedMoreData;
|
return (i8)Error::NeedMoreData;
|
||||||
|
|
||||||
auto curve_type = buffer[3];
|
auto curve_type = buffer[3];
|
||||||
if (curve_type != (u8)ECCurveType::NamedCurve)
|
if (curve_type != (u8)ECCurveType::NamedCurve)
|
||||||
return (i8)Error::NotUnderstood;
|
return (i8)Error::NotUnderstood;
|
||||||
|
|
||||||
auto curve = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(4)));
|
auto curve = static_cast<NamedCurve>(AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(4))));
|
||||||
if (curve != (u16)NamedCurve::x25519)
|
if (!m_context.options.elliptic_curves.contains_slow(curve))
|
||||||
return (i8)Error::NotUnderstood;
|
return (i8)Error::NotUnderstood;
|
||||||
|
|
||||||
|
m_context.server_curve_choice = curve;
|
||||||
|
auto curve_key_size_bytes = named_curve_key_size(curve) / 8;
|
||||||
|
if (buffer.size() < curve_key_size_bytes + 1)
|
||||||
|
return (i8)Error::NeedMoreData;
|
||||||
|
|
||||||
auto server_public_key_length = buffer[6];
|
auto server_public_key_length = buffer[6];
|
||||||
if (server_public_key_length != x25519_key_size_bytes)
|
if (server_public_key_length != curve_key_size_bytes)
|
||||||
return (i8)Error::NotUnderstood;
|
return (i8)Error::FeatureNotSupported;
|
||||||
|
|
||||||
auto server_public_key = buffer.slice(7, server_public_key_length);
|
auto server_public_key = buffer.slice(7, server_public_key_length);
|
||||||
auto server_public_key_copy_result = ByteBuffer::copy(server_public_key);
|
auto server_public_key_copy_result = ByteBuffer::copy(server_public_key);
|
||||||
|
|
|
@ -242,7 +242,9 @@ struct Options {
|
||||||
{ HashAlgorithm::SHA384, SignatureAlgorithm::RSA },
|
{ HashAlgorithm::SHA384, SignatureAlgorithm::RSA },
|
||||||
{ HashAlgorithm::SHA256, SignatureAlgorithm::RSA },
|
{ HashAlgorithm::SHA256, SignatureAlgorithm::RSA },
|
||||||
{ HashAlgorithm::SHA1, SignatureAlgorithm::RSA });
|
{ HashAlgorithm::SHA1, SignatureAlgorithm::RSA });
|
||||||
OPTION_WITH_DEFAULTS(Vector<NamedCurve>, elliptic_curves, NamedCurve::x25519)
|
OPTION_WITH_DEFAULTS(Vector<NamedCurve>, elliptic_curves,
|
||||||
|
NamedCurve::x25519,
|
||||||
|
NamedCurve::x448)
|
||||||
OPTION_WITH_DEFAULTS(Vector<ECPointFormat>, supported_ec_point_formats, ECPointFormat::Uncompressed)
|
OPTION_WITH_DEFAULTS(Vector<ECPointFormat>, supported_ec_point_formats, ECPointFormat::Uncompressed)
|
||||||
|
|
||||||
OPTION_WITH_DEFAULTS(bool, use_sni, true)
|
OPTION_WITH_DEFAULTS(bool, use_sni, true)
|
||||||
|
@ -331,6 +333,8 @@ struct Context {
|
||||||
ByteBuffer g;
|
ByteBuffer g;
|
||||||
ByteBuffer Ys;
|
ByteBuffer Ys;
|
||||||
} server_diffie_hellman_params;
|
} server_diffie_hellman_params;
|
||||||
|
|
||||||
|
NamedCurve server_curve_choice;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TLSv12 final : public Core::Stream::Socket {
|
class TLSv12 final : public Core::Stream::Socket {
|
||||||
|
@ -461,6 +465,9 @@ private:
|
||||||
void build_dhe_rsa_pre_master_secret(PacketBuilder&);
|
void build_dhe_rsa_pre_master_secret(PacketBuilder&);
|
||||||
void build_ecdhe_rsa_pre_master_secret(PacketBuilder&);
|
void build_ecdhe_rsa_pre_master_secret(PacketBuilder&);
|
||||||
|
|
||||||
|
static ErrorOr<ByteBuffer> named_curve_multiply(NamedCurve curve, ReadonlyBytes a, ReadonlyBytes b);
|
||||||
|
static ErrorOr<ByteBuffer> named_curve_generator_point(NamedCurve curve);
|
||||||
|
|
||||||
ErrorOr<bool> flush();
|
ErrorOr<bool> flush();
|
||||||
void write_into_socket();
|
void write_into_socket();
|
||||||
ErrorOr<void> read_from_socket();
|
ErrorOr<void> read_from_socket();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue