From 22ef4bbe77f6fdb42b27679134beb8c421323fa0 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 19 Jan 2025 08:04:52 -0500 Subject: [PATCH] Decouple support for explicit curves with legacy_ec_point Both are deprecated but for different reasons, and in the short term it's reasonable to want to disable legacy_ec_point while still supporting explicit curve encodings. --- src/lib/pubkey/ec_group/ec_group.cpp | 44 +++++++++++++++---- .../ec_group/legacy_ec_point/curve_gfp.h | 2 + .../ec_group/legacy_ec_point/ec_point.h | 12 +++-- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp index 2528ba04cc4..d60d0d89cfc 100644 --- a/src/lib/pubkey/ec_group/ec_group.cpp +++ b/src/lib/pubkey/ec_group/ec_group.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -219,8 +220,6 @@ std::pair, bool> EC_Group::BER_decode_EC_group(st return std::make_pair(data, false); } else if(next_obj_type == ASN1_Type::Sequence) { -#if defined(BOTAN_HAS_LEGACY_EC_POINT) - BigInt p, a, b, order, cofactor; std::vector base_pt; std::vector seed; @@ -246,7 +245,8 @@ std::pair, bool> EC_Group::BER_decode_EC_group(st throw Decoding_Error("ECC p parameter is invalid size"); } - if(p.is_negative() || !is_bailie_psw_probable_prime(p)) { + Modular_Reducer mod_p(p); + if(p.is_negative() || !is_bailie_psw_probable_prime(p, mod_p)) { throw Decoding_Error("ECC p parameter is not a prime"); } @@ -266,14 +266,42 @@ std::pair, bool> EC_Group::BER_decode_EC_group(st throw Decoding_Error("Invalid ECC cofactor parameter"); } - const auto [g_x, g_y] = Botan::OS2ECP(base_pt.data(), base_pt.size(), p, a, b); + auto [g_x, g_y] = [&]() { + const size_t p_bytes = p.bytes(); + const uint8_t hdr = base_pt[0]; + + if(hdr == 0x04 && base_pt.size() == 1 + 2 * p_bytes) { + BigInt x = BigInt::decode(&base_pt[1], p_bytes); + BigInt y = BigInt::decode(&base_pt[p_bytes + 1], p_bytes); + + if(x < p && y < p) { + return std::make_pair(x, y); + } + } else if((hdr == 0x02 || hdr == 0x03) && base_pt.size() == 1 + p_bytes) { + BigInt x = BigInt::decode(&base_pt[1], p_bytes); + BigInt y = sqrt_modulo_prime(((x * x + a) * x + b) % p, p); + + if(x < p && y >= 0) { + const bool y_mod_2 = (hdr & 0x01) == 1; + if(y.get_bit(0) != y_mod_2) { + y = p - y; + } + + return std::make_pair(x, y); + } + } + + throw Decoding_Error("Invalid ECC base point encoding"); + }(); + + auto y2 = mod_p.square(g_y); + auto x3_ax_b = mod_p.reduce(mod_p.cube(g_x) + mod_p.multiply(a, g_x) + b); + if(y2 != x3_ax_b) { + throw Decoding_Error("Invalid ECC base point"); + } auto data = ec_group_data().lookup_or_create(p, a, b, g_x, g_y, order, cofactor, OID(), source); return std::make_pair(data, true); -#else - BOTAN_UNUSED(source); - throw Decoding_Error("Decoding explicit ECC parameters is not supported"); -#endif } else if(next_obj_type == ASN1_Type::Null) { throw Decoding_Error("Decoding ImplicitCA ECC parameters is not supported"); } else { diff --git a/src/lib/pubkey/ec_group/legacy_ec_point/curve_gfp.h b/src/lib/pubkey/ec_group/legacy_ec_point/curve_gfp.h index c77c10899e3..c1ae02062ba 100644 --- a/src/lib/pubkey/ec_group/legacy_ec_point/curve_gfp.h +++ b/src/lib/pubkey/ec_group/legacy_ec_point/curve_gfp.h @@ -10,6 +10,8 @@ #ifndef BOTAN_GFP_CURVE_H_ #define BOTAN_GFP_CURVE_H_ +// TODO(Botan4) delete this header + #include // Currently exposed in EC_Point diff --git a/src/lib/pubkey/ec_group/legacy_ec_point/ec_point.h b/src/lib/pubkey/ec_group/legacy_ec_point/ec_point.h index 285970951d9..81ec302f4c2 100644 --- a/src/lib/pubkey/ec_group/legacy_ec_point/ec_point.h +++ b/src/lib/pubkey/ec_group/legacy_ec_point/ec_point.h @@ -10,6 +10,8 @@ #ifndef BOTAN_EC_POINT_H_ #define BOTAN_EC_POINT_H_ +// TODO(Botan4) delete this header + #include #include #include @@ -20,9 +22,13 @@ namespace Botan { /** * Deprecated elliptic curve type * -* Use EC_AffinePoint in new code +* Use EC_AffinePoint in new code; this type is no longer used internally at all +* except to support very unfortunate (and deprecated) curve types, specifically +* those with a cofactor, or with unreasonable sizes (above 521 bits), which +* cannot be accomodated by the new faster EC library in math/pcurves. For +* normal curves EC_AffinePoint will typically be 2 or 3 times faster. * -* This type will be removed/hidden in Botan4 +* This type will be completely removed in Botan4 */ class BOTAN_PUBLIC_API(2, 0) EC_Point final { public: @@ -438,7 +444,7 @@ BOTAN_DEPRECATED("Use EC_AffinePoint::deserialize") std::pair BOTAN_UNSTABLE_API OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b); -BOTAN_DEPRECATED("Use EC_Group::OS2ECP") +BOTAN_DEPRECATED("Use EC_AffinePoint::deserialize") EC_Point BOTAN_UNSTABLE_API OS2ECP(std::span data, const CurveGFp& curve); // The name used for this type in older versions