LibCrypto: Remove the concept of invalid big integers

This concept is rarely used in codebase and very much error-prone
if you forget to check it.

Instead, make it so that operations that would produce invalid integers
return an error instead.
This commit is contained in:
devgianlu 2025-04-25 21:28:00 +02:00 committed by Jelle Raaijmakers
commit 5f1a30197c
Notes: github-actions[bot] 2025-04-28 10:06:55 +00:00
12 changed files with 34 additions and 109 deletions

View file

@ -23,16 +23,6 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_or_without_allocation(
UnsignedBigInteger const& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
UnsignedBigInteger const *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
@ -62,16 +52,6 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_and_without_allocation(
UnsignedBigInteger const& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
UnsignedBigInteger const *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
@ -101,16 +81,6 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_xor_without_allocation(
UnsignedBigInteger const& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
UnsignedBigInteger const *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
@ -137,12 +107,6 @@ FLATTEN ErrorOr<void> UnsignedBigIntegerAlgorithms::bitwise_not_fill_to_one_base
size_t index,
UnsignedBigInteger& output)
{
// If the value is invalid, the output value is invalid as well.
if (right.is_invalid()) {
output.invalidate();
return {};
}
if (index == 0) {
output.set_to_0();
return {};

View file

@ -68,7 +68,7 @@ void UnsignedBigIntegerAlgorithms::extended_GCD_without_allocation(
while (gcd < temp_1) {
add_into_accumulator_without_allocation(gcd, b);
}
subtract_without_allocation(gcd, temp_1, temp_r);
MUST(subtract_without_allocation(gcd, temp_1, temp_r));
gcd.set_to(temp_2);
// (old_s, s) := (s, old_s quotient × s)
@ -77,7 +77,7 @@ void UnsignedBigIntegerAlgorithms::extended_GCD_without_allocation(
while (x < temp_1) {
add_into_accumulator_without_allocation(x, b);
}
subtract_without_allocation(x, temp_1, temp_s);
MUST(subtract_without_allocation(x, temp_1, temp_s));
x.set_to(temp_2);
// (old_t, t) := (t, old_t quotient × t)
@ -86,7 +86,7 @@ void UnsignedBigIntegerAlgorithms::extended_GCD_without_allocation(
while (y < temp_1) {
add_into_accumulator_without_allocation(y, b);
}
subtract_without_allocation(y, temp_1, temp_t);
MUST(subtract_without_allocation(y, temp_1, temp_t));
y.set_to(temp_2);
}
}

View file

@ -262,7 +262,7 @@ void UnsignedBigIntegerAlgorithms::montgomery_modular_power_with_minimal_allocat
// Note : Since we were using "almost montgomery" multiplications, we aren't guaranteed to be under the modulo already.
// So, if we're here, we need to respect the modulo.
// We can, however, start by trying to subtract the modulo, just in case we're close.
subtract_without_allocation(zz, modulo, result);
MUST(subtract_without_allocation(zz, modulo, result));
if (modulo < zz) {
// Note: This branch shouldn't happen in theory (as noted in https://github.com/rust-num/num-bigint/blob/master/src/biguint/monty.rs#L210)

View file

@ -73,14 +73,13 @@ void UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(Unsig
/**
* Complexity: O(N) where N is the number of words in the larger number
*/
void UnsignedBigIntegerAlgorithms::subtract_without_allocation(
ErrorOr<void> UnsignedBigIntegerAlgorithms::subtract_without_allocation(
UnsignedBigInteger const& left,
UnsignedBigInteger const& right,
UnsignedBigInteger& output)
{
if (left < right) {
output.invalidate();
return;
return Error::from_string_literal("Invalid subtraction: left < right");
}
u8 borrow = 0;
@ -103,6 +102,8 @@ void UnsignedBigIntegerAlgorithms::subtract_without_allocation(
// This assertion should not fail, because we verified that *this>=other at the beginning of the function
VERIFY(borrow == 0);
return {};
}
}

View file

@ -16,7 +16,7 @@ class UnsignedBigIntegerAlgorithms {
public:
static void add_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static void add_into_accumulator_without_allocation(UnsignedBigInteger& accumulator, UnsignedBigInteger const& value);
static void subtract_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static ErrorOr<void> subtract_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static void bitwise_or_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static void bitwise_and_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static void bitwise_xor_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);