mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:07:34 +00:00
LibCrypto+LibTLS: Generalize the elliptic curve interface
These changes generalize the interface with an elliptic curve implementation. This allows LibTLS to support elliptic curves generally without needing the specifics of elliptic curve implementations. This should allow for easier addition of other elliptic curves.
This commit is contained in:
parent
21bbff0349
commit
c1b041e761
10 changed files with 133 additions and 122 deletions
|
@ -10,8 +10,6 @@
|
|||
#include <AK/Random.h>
|
||||
#include <LibCrypto/ASN1/DER.h>
|
||||
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
||||
#include <LibCrypto/Curves/X25519.h>
|
||||
#include <LibCrypto/Curves/X448.h>
|
||||
#include <LibCrypto/NumberTheory/ModularFunctions.h>
|
||||
#include <LibCrypto/PK/Code/EMSA_PSS.h>
|
||||
#include <LibTLS/TLSv12.h>
|
||||
|
@ -295,86 +293,44 @@ void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
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)
|
||||
{
|
||||
size_t const key_size = named_curve_key_size(m_context.server_curve_choice) / 8;
|
||||
auto generator_point_result = named_curve_generator_point(m_context.server_curve_choice);
|
||||
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
|
||||
auto private_key_result = ByteBuffer::create_uninitialized(key_size);
|
||||
auto private_key_result = m_context.server_key_exchange_curve->generate_private_key();
|
||||
if (private_key_result.is_error()) {
|
||||
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 the generator point
|
||||
auto public_key_result = named_curve_multiply(m_context.server_curve_choice, private_key_bytes, generator_point_bytes);
|
||||
// Calculate the public key from the private key
|
||||
auto public_key_result = m_context.server_key_exchange_curve->generate_public_key(private_key);
|
||||
if (public_key_result.is_error()) {
|
||||
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||
return;
|
||||
}
|
||||
auto public_key = public_key_result.release_value();
|
||||
|
||||
// Calculate the pre master secret by multiplying the client private key and the server public key
|
||||
// Calculate the shared point by multiplying the client private key and the server public key
|
||||
ReadonlyBytes server_public_key_bytes = m_context.server_diffie_hellman_params.p;
|
||||
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()) {
|
||||
auto shared_point_result = m_context.server_key_exchange_curve->compute_coordinate(private_key, server_public_key_bytes);
|
||||
if (shared_point_result.is_error()) {
|
||||
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||
return;
|
||||
}
|
||||
m_context.premaster_key = pre_master_secret_result.release_value();
|
||||
auto shared_point = shared_point_result.release_value();
|
||||
|
||||
// Derive the premaster key from the shared point
|
||||
auto premaster_key_result = m_context.server_key_exchange_curve->derive_premaster_key(shared_point);
|
||||
if (premaster_key_result.is_error()) {
|
||||
dbgln("Failed to build ECDHE_RSA premaster secret: not enough memory");
|
||||
return;
|
||||
}
|
||||
m_context.premaster_key = premaster_key_result.release_value();
|
||||
|
||||
if constexpr (TLS_DEBUG) {
|
||||
dbgln("Build ECDHE_RSA pre master secret");
|
||||
dbgln("client private key: {:hex-dump}", private_key_bytes);
|
||||
dbgln("client private key: {:hex-dump}", (ReadonlyBytes)private_key);
|
||||
dbgln("client public key: {:hex-dump}", (ReadonlyBytes)public_key);
|
||||
dbgln("premaster key: {:hex-dump}", (ReadonlyBytes)m_context.premaster_key);
|
||||
}
|
||||
|
@ -384,8 +340,8 @@ void TLSv12::build_ecdhe_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
return;
|
||||
}
|
||||
|
||||
builder.append_u24(key_size + 1);
|
||||
builder.append((u8)key_size);
|
||||
builder.append_u24(public_key.size() + 1);
|
||||
builder.append((u8)public_key.size());
|
||||
builder.append(public_key);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue