mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-31 06:38:22 +00:00
LibCrypto: De-templetize and move SECPxxxr1
methods out of line
This commit is contained in:
parent
cceb7110fc
commit
1d207aa0d8
Notes:
github-actions[bot]
2025-01-27 11:25:51 +00:00
Author: https://github.com/devgianlu
Commit: 1d207aa0d8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3374
Reviewed-by: https://github.com/alimpfard ✅
3 changed files with 228 additions and 202 deletions
|
@ -28,6 +28,7 @@ set(SOURCES
|
|||
Curves/Curve25519.cpp
|
||||
Curves/Ed25519.cpp
|
||||
Curves/Ed448.cpp
|
||||
Curves/SECPxxxr1.cpp
|
||||
Curves/X25519.cpp
|
||||
Curves/X448.cpp
|
||||
Hash/BLAKE2b.cpp
|
||||
|
|
184
Libraries/LibCrypto/Curves/SECPxxxr1.cpp
Normal file
184
Libraries/LibCrypto/Curves/SECPxxxr1.cpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCrypto/Curves/SECPxxxr1.h>
|
||||
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/param_build.h>
|
||||
|
||||
namespace Crypto::Curves {
|
||||
|
||||
ErrorOr<UnsignedBigInteger> SECPxxxr1::generate_private_key_scalar()
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, "EC", m_curve_name)));
|
||||
|
||||
auto priv_bn = TRY(OpenSSL_BN::create());
|
||||
auto* priv_bn_ptr = priv_bn.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_get_bn_param(key.ptr(), OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn_ptr));
|
||||
|
||||
return TRY(openssl_bignum_to_unsigned_big_integer(priv_bn));
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Point> SECPxxxr1::generate_public_key_point(UnsignedBigInteger scalar)
|
||||
{
|
||||
auto* group = EC_GROUP_new_by_curve_name(EC_curve_nist2nid(m_curve_name));
|
||||
ScopeGuard const free_group = [&] { EC_GROUP_free(group); };
|
||||
|
||||
auto scalar_int = TRY(unsigned_big_integer_to_openssl_bignum(scalar));
|
||||
|
||||
auto* r = EC_POINT_new(group);
|
||||
ScopeGuard const free_r = [&] { EC_POINT_free(r); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_mul(group, r, scalar_int.ptr(), nullptr, nullptr, nullptr));
|
||||
|
||||
auto x = TRY(OpenSSL_BN::create());
|
||||
auto y = TRY(OpenSSL_BN::create());
|
||||
|
||||
OPENSSL_TRY(EC_POINT_get_affine_coordinates(group, r, x.ptr(), y.ptr(), nullptr));
|
||||
|
||||
return SECPxxxr1Point {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(x)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(y)),
|
||||
m_scalar_size,
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Point> SECPxxxr1::compute_coordinate_point(UnsignedBigInteger scalar, SECPxxxr1Point point)
|
||||
{
|
||||
auto* group = EC_GROUP_new_by_curve_name(EC_curve_nist2nid(m_curve_name));
|
||||
ScopeGuard const free_group = [&] { EC_GROUP_free(group); };
|
||||
|
||||
auto scalar_int = TRY(unsigned_big_integer_to_openssl_bignum(scalar));
|
||||
|
||||
auto qx = TRY(unsigned_big_integer_to_openssl_bignum(point.x));
|
||||
auto qy = TRY(unsigned_big_integer_to_openssl_bignum(point.y));
|
||||
|
||||
auto* q = EC_POINT_new(group);
|
||||
ScopeGuard const free_q = [&] { EC_POINT_free(q); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_set_affine_coordinates(group, q, qx.ptr(), qy.ptr(), nullptr));
|
||||
|
||||
auto* r = EC_POINT_new(group);
|
||||
ScopeGuard const free_r = [&] { EC_POINT_free(r); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_mul(group, r, nullptr, q, scalar_int.ptr(), nullptr));
|
||||
|
||||
auto rx = TRY(OpenSSL_BN::create());
|
||||
auto ry = TRY(OpenSSL_BN::create());
|
||||
|
||||
OPENSSL_TRY(EC_POINT_get_affine_coordinates(group, r, rx.ptr(), ry.ptr(), nullptr));
|
||||
|
||||
return SECPxxxr1Point {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(rx)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(ry)),
|
||||
m_scalar_size,
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<bool> SECPxxxr1::verify_point(ReadonlyBytes hash, SECPxxxr1Point pubkey, SECPxxxr1Signature signature)
|
||||
{
|
||||
auto ctx_import = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata_init(ctx_import.ptr()));
|
||||
|
||||
auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new());
|
||||
ScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); };
|
||||
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_utf8_string(params_bld, OSSL_PKEY_PARAM_GROUP_NAME, m_curve_name, strlen(m_curve_name)));
|
||||
|
||||
auto pubkey_bytes = TRY(pubkey.to_uncompressed());
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_octet_string(params_bld, OSSL_PKEY_PARAM_PUB_KEY, pubkey_bytes.data(), pubkey_bytes.size()));
|
||||
|
||||
auto* params = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_to_param(params_bld));
|
||||
ScopeGuard const free_params = [&] { OSSL_PARAM_free(params); };
|
||||
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new()));
|
||||
auto* key_ptr = key.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata(ctx_import.ptr(), &key_ptr, EVP_PKEY_PUBLIC_KEY, params));
|
||||
|
||||
auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_pkey(nullptr, key.ptr(), nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_verify_init(ctx.ptr()));
|
||||
|
||||
auto* sig_obj = OPENSSL_TRY_PTR(ECDSA_SIG_new());
|
||||
ScopeGuard const free_sig_obj = [&] { ECDSA_SIG_free(sig_obj); };
|
||||
|
||||
auto r = TRY(unsigned_big_integer_to_openssl_bignum(signature.r));
|
||||
auto s = TRY(unsigned_big_integer_to_openssl_bignum(signature.s));
|
||||
|
||||
// Let sig_obj own a copy of r and s
|
||||
OPENSSL_TRY(ECDSA_SIG_set0(sig_obj, BN_dup(r.ptr()), BN_dup(s.ptr())));
|
||||
|
||||
u8* sig = nullptr;
|
||||
ScopeGuard const free_sig = [&] { OPENSSL_free(sig); };
|
||||
|
||||
auto sig_len = TRY([&] -> ErrorOr<int> {
|
||||
auto ret = i2d_ECDSA_SIG(sig_obj, &sig);
|
||||
if (ret <= 0) {
|
||||
OPENSSL_TRY(ret);
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
return ret;
|
||||
}());
|
||||
|
||||
auto ret = EVP_PKEY_verify(ctx.ptr(), sig, sig_len, hash.data(), hash.size());
|
||||
if (ret == 1)
|
||||
return true;
|
||||
if (ret == 0)
|
||||
return false;
|
||||
OPENSSL_TRY(ret);
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Signature> SECPxxxr1::sign_scalar(ReadonlyBytes hash, UnsignedBigInteger private_key)
|
||||
{
|
||||
auto ctx_import = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata_init(ctx_import.ptr()));
|
||||
|
||||
auto d = TRY(unsigned_big_integer_to_openssl_bignum(private_key));
|
||||
|
||||
auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new());
|
||||
ScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); };
|
||||
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_utf8_string(params_bld, OSSL_PKEY_PARAM_GROUP_NAME, m_curve_name, strlen(m_curve_name)));
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_BN(params_bld, OSSL_PKEY_PARAM_PRIV_KEY, d.ptr()));
|
||||
|
||||
auto* params = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_to_param(params_bld));
|
||||
ScopeGuard const free_params = [&] { OSSL_PARAM_free(params); };
|
||||
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new()));
|
||||
auto* key_ptr = key.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata(ctx_import.ptr(), &key_ptr, EVP_PKEY_KEYPAIR, params));
|
||||
|
||||
auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_pkey(nullptr, key.ptr(), nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_sign_init(ctx.ptr()));
|
||||
|
||||
size_t sig_len = 0;
|
||||
OPENSSL_TRY(EVP_PKEY_sign(ctx.ptr(), nullptr, &sig_len, hash.data(), hash.size()));
|
||||
|
||||
auto sig = TRY(ByteBuffer::create_uninitialized(sig_len));
|
||||
OPENSSL_TRY(EVP_PKEY_sign(ctx.ptr(), sig.data(), &sig_len, hash.data(), hash.size()));
|
||||
|
||||
auto const* sig_data = sig.data();
|
||||
auto* sig_obj = OPENSSL_TRY_PTR(d2i_ECDSA_SIG(nullptr, &sig_data, sig.size()));
|
||||
ScopeGuard const free_sig_obj = [&] { ECDSA_SIG_free(sig_obj); };
|
||||
|
||||
// Duplicate r and s so that sig_obj can own them
|
||||
auto r = TRY(OpenSSL_BN::wrap(BN_dup(OPENSSL_TRY_PTR(ECDSA_SIG_get0_r(sig_obj)))));
|
||||
auto s = TRY(OpenSSL_BN::wrap(BN_dup(OPENSSL_TRY_PTR(ECDSA_SIG_get0_s(sig_obj)))));
|
||||
|
||||
return SECPxxxr1Signature {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(r)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(s)),
|
||||
m_scalar_size,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -14,11 +14,6 @@
|
|||
#include <LibCrypto/Curves/EllipticCurve.h>
|
||||
#include <LibCrypto/OpenSSL.h>
|
||||
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/param_build.h>
|
||||
|
||||
namespace {
|
||||
// Used by ASN1 macros
|
||||
static String s_error_string;
|
||||
|
@ -26,10 +21,6 @@ static String s_error_string;
|
|||
|
||||
namespace Crypto::Curves {
|
||||
|
||||
struct SECPxxxr1CurveParameters {
|
||||
char const* name;
|
||||
};
|
||||
|
||||
struct SECPxxxr1Point {
|
||||
UnsignedBigInteger x;
|
||||
UnsignedBigInteger y;
|
||||
|
@ -138,36 +129,31 @@ struct SECPxxxr1Signature {
|
|||
}
|
||||
};
|
||||
|
||||
template<size_t bit_size, SECPxxxr1CurveParameters const& CURVE_PARAMETERS>
|
||||
class SECPxxxr1 : public EllipticCurve {
|
||||
static constexpr size_t KEY_BIT_SIZE = bit_size;
|
||||
static constexpr size_t KEY_BYTE_SIZE = ceil_div(KEY_BIT_SIZE, 8ull);
|
||||
static constexpr size_t POINT_BYTE_SIZE = 1 + 2 * KEY_BYTE_SIZE;
|
||||
|
||||
public:
|
||||
size_t key_size() override { return POINT_BYTE_SIZE; }
|
||||
size_t key_size() override { return 1 + (2 * m_scalar_size); }
|
||||
|
||||
ErrorOr<UnsignedBigInteger> generate_private_key_scalar();
|
||||
ErrorOr<SECPxxxr1Point> generate_public_key_point(UnsignedBigInteger scalar);
|
||||
ErrorOr<SECPxxxr1Point> compute_coordinate_point(UnsignedBigInteger scalar, SECPxxxr1Point point);
|
||||
ErrorOr<bool> verify_point(ReadonlyBytes hash, SECPxxxr1Point pubkey, SECPxxxr1Signature signature);
|
||||
ErrorOr<SECPxxxr1Signature> sign_scalar(ReadonlyBytes hash, UnsignedBigInteger private_key);
|
||||
|
||||
ErrorOr<SECPxxxr1Point> derive_premaster_key_point(SECPxxxr1Point shared_point)
|
||||
{
|
||||
return shared_point;
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> generate_private_key() override
|
||||
{
|
||||
auto key = TRY(generate_private_key_scalar());
|
||||
|
||||
auto buffer = TRY(ByteBuffer::create_uninitialized(KEY_BYTE_SIZE));
|
||||
auto buffer = TRY(ByteBuffer::create_uninitialized(m_scalar_size));
|
||||
auto buffer_bytes = buffer.bytes();
|
||||
auto size = key.export_data(buffer_bytes);
|
||||
return buffer.slice(0, size);
|
||||
}
|
||||
|
||||
ErrorOr<UnsignedBigInteger> generate_private_key_scalar()
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, "EC", CURVE_PARAMETERS.name)));
|
||||
|
||||
auto priv_bn = TRY(OpenSSL_BN::create());
|
||||
auto* priv_bn_ptr = priv_bn.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_get_bn_param(key.ptr(), OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn_ptr));
|
||||
|
||||
return TRY(openssl_bignum_to_unsigned_big_integer(priv_bn));
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes a) override
|
||||
{
|
||||
auto a_int = UnsignedBigInteger::import_data(a);
|
||||
|
@ -175,70 +161,14 @@ public:
|
|||
return point.to_uncompressed();
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Point> generate_public_key_point(UnsignedBigInteger scalar)
|
||||
{
|
||||
auto* group = EC_GROUP_new_by_curve_name(EC_curve_nist2nid(CURVE_PARAMETERS.name));
|
||||
ScopeGuard const free_group = [&] { EC_GROUP_free(group); };
|
||||
|
||||
auto scalar_int = TRY(unsigned_big_integer_to_openssl_bignum(scalar));
|
||||
|
||||
auto* r = EC_POINT_new(group);
|
||||
ScopeGuard const free_r = [&] { EC_POINT_free(r); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_mul(group, r, scalar_int.ptr(), nullptr, nullptr, nullptr));
|
||||
|
||||
auto x = TRY(OpenSSL_BN::create());
|
||||
auto y = TRY(OpenSSL_BN::create());
|
||||
|
||||
OPENSSL_TRY(EC_POINT_get_affine_coordinates(group, r, x.ptr(), y.ptr(), nullptr));
|
||||
|
||||
return SECPxxxr1Point {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(x)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(y)),
|
||||
KEY_BYTE_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override
|
||||
{
|
||||
auto scalar = UnsignedBigInteger::import_data(scalar_bytes);
|
||||
auto point = TRY(SECPxxxr1Point::from_uncompressed(point_bytes));
|
||||
auto result = TRY(compute_coordinate_point(scalar, { point.x, point.y, KEY_BYTE_SIZE }));
|
||||
auto result = TRY(compute_coordinate_point(scalar, { point.x, point.y, m_scalar_size }));
|
||||
return result.to_uncompressed();
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Point> compute_coordinate_point(UnsignedBigInteger scalar, SECPxxxr1Point point)
|
||||
{
|
||||
auto* group = EC_GROUP_new_by_curve_name(EC_curve_nist2nid(CURVE_PARAMETERS.name));
|
||||
ScopeGuard const free_group = [&] { EC_GROUP_free(group); };
|
||||
|
||||
auto scalar_int = TRY(unsigned_big_integer_to_openssl_bignum(scalar));
|
||||
|
||||
auto qx = TRY(unsigned_big_integer_to_openssl_bignum(point.x));
|
||||
auto qy = TRY(unsigned_big_integer_to_openssl_bignum(point.y));
|
||||
|
||||
auto* q = EC_POINT_new(group);
|
||||
ScopeGuard const free_q = [&] { EC_POINT_free(q); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_set_affine_coordinates(group, q, qx.ptr(), qy.ptr(), nullptr));
|
||||
|
||||
auto* r = EC_POINT_new(group);
|
||||
ScopeGuard const free_r = [&] { EC_POINT_free(r); };
|
||||
|
||||
OPENSSL_TRY(EC_POINT_mul(group, r, nullptr, q, scalar_int.ptr(), nullptr));
|
||||
|
||||
auto rx = TRY(OpenSSL_BN::create());
|
||||
auto ry = TRY(OpenSSL_BN::create());
|
||||
|
||||
OPENSSL_TRY(EC_POINT_get_affine_coordinates(group, r, rx.ptr(), ry.ptr(), nullptr));
|
||||
|
||||
return SECPxxxr1Point {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(rx)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(ry)),
|
||||
KEY_BYTE_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> derive_premaster_key(ReadonlyBytes shared_point_bytes) override
|
||||
{
|
||||
auto shared_point = TRY(SECPxxxr1Point::from_uncompressed(shared_point_bytes));
|
||||
|
@ -246,141 +176,52 @@ public:
|
|||
return premaster_key_point.to_uncompressed();
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Point> derive_premaster_key_point(SECPxxxr1Point shared_point)
|
||||
{
|
||||
return shared_point;
|
||||
}
|
||||
|
||||
ErrorOr<bool> verify_point(ReadonlyBytes hash, SECPxxxr1Point pubkey, SECPxxxr1Signature signature)
|
||||
{
|
||||
auto ctx_import = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata_init(ctx_import.ptr()));
|
||||
|
||||
auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new());
|
||||
ScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); };
|
||||
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_utf8_string(params_bld, OSSL_PKEY_PARAM_GROUP_NAME, CURVE_PARAMETERS.name, strlen(CURVE_PARAMETERS.name)));
|
||||
|
||||
auto pubkey_bytes = TRY(pubkey.to_uncompressed());
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_octet_string(params_bld, OSSL_PKEY_PARAM_PUB_KEY, pubkey_bytes.data(), pubkey_bytes.size()));
|
||||
|
||||
auto* params = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_to_param(params_bld));
|
||||
ScopeGuard const free_params = [&] { OSSL_PARAM_free(params); };
|
||||
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new()));
|
||||
auto* key_ptr = key.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata(ctx_import.ptr(), &key_ptr, EVP_PKEY_PUBLIC_KEY, params));
|
||||
|
||||
auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_pkey(nullptr, key.ptr(), nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_verify_init(ctx.ptr()));
|
||||
|
||||
auto* sig_obj = OPENSSL_TRY_PTR(ECDSA_SIG_new());
|
||||
ScopeGuard const free_sig_obj = [&] { ECDSA_SIG_free(sig_obj); };
|
||||
|
||||
auto r = TRY(unsigned_big_integer_to_openssl_bignum(signature.r));
|
||||
auto s = TRY(unsigned_big_integer_to_openssl_bignum(signature.s));
|
||||
|
||||
// Let sig_obj own a copy of r and s
|
||||
OPENSSL_TRY(ECDSA_SIG_set0(sig_obj, BN_dup(r.ptr()), BN_dup(s.ptr())));
|
||||
|
||||
u8* sig = nullptr;
|
||||
ScopeGuard const free_sig = [&] { OPENSSL_free(sig); };
|
||||
|
||||
auto sig_len = TRY([&] -> ErrorOr<int> {
|
||||
auto ret = i2d_ECDSA_SIG(sig_obj, &sig);
|
||||
if (ret <= 0) {
|
||||
OPENSSL_TRY(ret);
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
return ret;
|
||||
}());
|
||||
|
||||
auto ret = EVP_PKEY_verify(ctx.ptr(), sig, sig_len, hash.data(), hash.size());
|
||||
if (ret == 1)
|
||||
return true;
|
||||
if (ret == 0)
|
||||
return false;
|
||||
OPENSSL_TRY(ret);
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<bool> verify(ReadonlyBytes hash, ReadonlyBytes pubkey, SECPxxxr1Signature signature)
|
||||
{
|
||||
auto pubkey_point = TRY(SECPxxxr1Point::from_uncompressed(pubkey));
|
||||
return verify_point(hash, pubkey_point, signature);
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Signature> sign_scalar(ReadonlyBytes hash, UnsignedBigInteger private_key)
|
||||
{
|
||||
auto ctx_import = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata_init(ctx_import.ptr()));
|
||||
|
||||
auto d = TRY(unsigned_big_integer_to_openssl_bignum(private_key));
|
||||
|
||||
auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new());
|
||||
ScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); };
|
||||
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_utf8_string(params_bld, OSSL_PKEY_PARAM_GROUP_NAME, CURVE_PARAMETERS.name, strlen(CURVE_PARAMETERS.name)));
|
||||
OPENSSL_TRY(OSSL_PARAM_BLD_push_BN(params_bld, OSSL_PKEY_PARAM_PRIV_KEY, d.ptr()));
|
||||
|
||||
auto* params = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_to_param(params_bld));
|
||||
ScopeGuard const free_params = [&] { OSSL_PARAM_free(params); };
|
||||
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new()));
|
||||
auto* key_ptr = key.ptr();
|
||||
OPENSSL_TRY(EVP_PKEY_fromdata(ctx_import.ptr(), &key_ptr, EVP_PKEY_KEYPAIR, params));
|
||||
|
||||
auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_pkey(nullptr, key.ptr(), nullptr)));
|
||||
|
||||
OPENSSL_TRY(EVP_PKEY_sign_init(ctx.ptr()));
|
||||
|
||||
size_t sig_len = 0;
|
||||
OPENSSL_TRY(EVP_PKEY_sign(ctx.ptr(), nullptr, &sig_len, hash.data(), hash.size()));
|
||||
|
||||
auto sig = TRY(ByteBuffer::create_uninitialized(sig_len));
|
||||
OPENSSL_TRY(EVP_PKEY_sign(ctx.ptr(), sig.data(), &sig_len, hash.data(), hash.size()));
|
||||
|
||||
auto const* sig_data = sig.data();
|
||||
auto* sig_obj = OPENSSL_TRY_PTR(d2i_ECDSA_SIG(nullptr, &sig_data, sig.size()));
|
||||
ScopeGuard const free_sig_obj = [&] { ECDSA_SIG_free(sig_obj); };
|
||||
|
||||
// Duplicate r and s so that sig_obj can own them
|
||||
auto r = TRY(OpenSSL_BN::wrap(BN_dup(OPENSSL_TRY_PTR(ECDSA_SIG_get0_r(sig_obj)))));
|
||||
auto s = TRY(OpenSSL_BN::wrap(BN_dup(OPENSSL_TRY_PTR(ECDSA_SIG_get0_s(sig_obj)))));
|
||||
|
||||
return SECPxxxr1Signature {
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(r)),
|
||||
TRY(openssl_bignum_to_unsigned_big_integer(s)),
|
||||
KEY_BYTE_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<SECPxxxr1Signature> sign(ReadonlyBytes hash, ReadonlyBytes private_key_bytes)
|
||||
{
|
||||
auto signature = TRY(sign_scalar(hash, UnsignedBigInteger::import_data(private_key_bytes.data(), private_key_bytes.size())));
|
||||
return signature;
|
||||
}
|
||||
|
||||
protected:
|
||||
SECPxxxr1(char const* curve_name, size_t scalar_size)
|
||||
: m_curve_name(curve_name)
|
||||
, m_scalar_size(scalar_size)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
char const* m_curve_name;
|
||||
size_t m_scalar_size;
|
||||
};
|
||||
|
||||
// SECP256r1 curve
|
||||
static constexpr SECPxxxr1CurveParameters SECP256r1_CURVE_PARAMETERS {
|
||||
.name = "P-256",
|
||||
class SECP256r1 : public SECPxxxr1 {
|
||||
public:
|
||||
SECP256r1()
|
||||
: SECPxxxr1("P-256", 32)
|
||||
{
|
||||
}
|
||||
};
|
||||
using SECP256r1 = SECPxxxr1<256, SECP256r1_CURVE_PARAMETERS>;
|
||||
|
||||
// SECP384r1 curve
|
||||
static constexpr SECPxxxr1CurveParameters SECP384r1_CURVE_PARAMETERS {
|
||||
.name = "P-384",
|
||||
class SECP384r1 : public SECPxxxr1 {
|
||||
public:
|
||||
SECP384r1()
|
||||
: SECPxxxr1("P-384", 48)
|
||||
{
|
||||
}
|
||||
};
|
||||
using SECP384r1 = SECPxxxr1<384, SECP384r1_CURVE_PARAMETERS>;
|
||||
|
||||
// SECP521r1 curve
|
||||
static constexpr SECPxxxr1CurveParameters SECP521r1_CURVE_PARAMETERS {
|
||||
.name = "P-521",
|
||||
class SECP521r1 : public SECPxxxr1 {
|
||||
public:
|
||||
SECP521r1()
|
||||
: SECPxxxr1("P-521", 66)
|
||||
{
|
||||
}
|
||||
};
|
||||
using SECP521r1 = SECPxxxr1<521, SECP521r1_CURVE_PARAMETERS>;
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue