LibCrypto: Add a += operation to UnsignedBigIntegerAlgorithms

This new operation is immediately used in several existing algorithms.
This commit is contained in:
DexesTTP 2021-05-12 10:47:21 +02:00 committed by Linus Groh
parent f4e6f58cc6
commit 5071989545
Notes: sideshowbarker 2024-07-18 18:13:44 +09:00
10 changed files with 151 additions and 47 deletions

View file

@ -199,8 +199,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation(
temp_plus.set_to_0(); temp_plus.set_to_0();
temp_plus.m_words.append(carry_word); temp_plus.m_words.append(carry_word);
shift_left_by_n_words(temp_plus, temp_result.length(), temp_result); shift_left_by_n_words(temp_plus, temp_result.length(), temp_result);
add_without_allocation(output, temp_result, temp_plus); add_into_accumulator_without_allocation(output, temp_result);
output.set_to(temp_plus);
} }
} }

View file

@ -16,7 +16,6 @@ void UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(
UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_2,
UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_3,
UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_4,
UnsignedBigInteger& temp_plus,
UnsignedBigInteger& temp_minus, UnsignedBigInteger& temp_minus,
UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_quotient,
UnsignedBigInteger& temp_d, UnsignedBigInteger& temp_d,
@ -30,8 +29,7 @@ void UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(
temp_u.set_to(a); temp_u.set_to(a);
if (a.words()[0] % 2 == 0) { if (a.words()[0] % 2 == 0) {
// u += b // u += b
add_without_allocation(temp_u, b, temp_plus); add_into_accumulator_without_allocation(temp_u, b);
temp_u.set_to(temp_plus);
} }
temp_v.set_to(b); temp_v.set_to(b);
@ -47,14 +45,12 @@ void UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(
temp_u.set_to(temp_minus); temp_u.set_to(temp_minus);
// d += x // d += x
add_without_allocation(temp_d, temp_x, temp_plus); add_into_accumulator_without_allocation(temp_d, temp_x);
temp_d.set_to(temp_plus);
while (temp_u.words()[0] % 2 == 0) { while (temp_u.words()[0] % 2 == 0) {
if (temp_d.words()[0] % 2 == 1) { if (temp_d.words()[0] % 2 == 1) {
// d += b // d += b
add_without_allocation(temp_d, b, temp_plus); add_into_accumulator_without_allocation(temp_d, b);
temp_d.set_to(temp_plus);
} }
// u /= 2 // u /= 2
@ -72,14 +68,12 @@ void UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(
temp_v.set_to(temp_minus); temp_v.set_to(temp_minus);
// x += d // x += d
add_without_allocation(temp_x, temp_d, temp_plus); add_into_accumulator_without_allocation(temp_x, temp_d);
temp_x.set_to(temp_plus);
while (temp_v.words()[0] % 2 == 0) { while (temp_v.words()[0] % 2 == 0) {
if (temp_x.words()[0] % 2 == 1) { if (temp_x.words()[0] % 2 == 1) {
// x += b // x += b
add_without_allocation(temp_x, b, temp_plus); add_into_accumulator_without_allocation(temp_x, b);
temp_x.set_to(temp_plus);
} }
// v /= 2 // v /= 2

View file

@ -26,7 +26,7 @@ void UnsignedBigIntegerAlgorithms::destructive_modular_power_without_allocation(
while (!(ep < 1)) { while (!(ep < 1)) {
if (ep.words()[0] % 2 == 1) { if (ep.words()[0] % 2 == 1) {
// exp = (exp * base) % m; // exp = (exp * base) % m;
multiply_without_allocation(exp, base, temp_1, temp_2, temp_3, temp_4, temp_multiply); multiply_without_allocation(exp, base, temp_1, temp_2, temp_3, temp_multiply);
divide_without_allocation(temp_multiply, m, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); divide_without_allocation(temp_multiply, m, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder);
exp.set_to(temp_remainder); exp.set_to(temp_remainder);
} }
@ -36,7 +36,7 @@ void UnsignedBigIntegerAlgorithms::destructive_modular_power_without_allocation(
ep.set_to(temp_quotient); ep.set_to(temp_quotient);
// base = (base * base) % m; // base = (base * base) % m;
multiply_without_allocation(base, base, temp_1, temp_2, temp_3, temp_4, temp_multiply); multiply_without_allocation(base, base, temp_1, temp_2, temp_3, temp_multiply);
divide_without_allocation(temp_multiply, m, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); divide_without_allocation(temp_multiply, m, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder);
base.set_to(temp_remainder); base.set_to(temp_remainder);

View file

@ -23,7 +23,6 @@ FLATTEN void UnsignedBigIntegerAlgorithms::multiply_without_allocation(
UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_result,
UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift_plus,
UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_shift,
UnsignedBigInteger& temp_plus,
UnsignedBigInteger& output) UnsignedBigInteger& output)
{ {
output.set_to_0(); output.set_to_0();
@ -39,8 +38,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::multiply_without_allocation(
// output += (right << shift_amount); // output += (right << shift_amount);
shift_left_without_allocation(right, shift_amount, temp_shift_result, temp_shift_plus, temp_shift); shift_left_without_allocation(right, shift_amount, temp_shift_result, temp_shift_plus, temp_shift);
add_without_allocation(output, temp_shift, temp_plus); add_into_accumulator_without_allocation(output, temp_shift);
output.set_to(temp_plus);
} }
} }
} }

View file

@ -20,36 +20,51 @@ void UnsignedBigIntegerAlgorithms::add_without_allocation(
const UnsignedBigInteger* const longer = (left.length() > right.length()) ? &left : &right; const UnsignedBigInteger* const longer = (left.length() > right.length()) ? &left : &right;
const UnsignedBigInteger* const shorter = (longer == &right) ? &left : &right; const UnsignedBigInteger* const shorter = (longer == &right) ? &left : &right;
u8 carry = 0; output.set_to(*longer);
add_into_accumulator_without_allocation(output, *shorter);
}
output.set_to_0(); /**
output.m_words.resize_and_keep_capacity(longer->length()); * Complexity: O(N) where N is the number of words in the larger number
*/
void UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(UnsignedBigInteger& accumulator, UnsignedBigInteger const& value)
{
auto value_length = value.trimmed_length();
for (size_t i = 0; i < shorter->length(); ++i) { // If needed, resize the accumulator so it can fit the value.
u32 word_addition_result = shorter->m_words[i] + longer->m_words[i]; accumulator.resize_with_leading_zeros(value_length);
u8 carry_out = 0; auto final_length = accumulator.length();
// if there was a carry, the result will be smaller than any of the operands
if (word_addition_result + carry < shorter->m_words[i]) { // Add the words of the value into the accumulator, rippling any carry as we go
carry_out = 1; UnsignedBigInteger::Word last_carry_for_word = 0;
for (size_t i = 0; i < value_length; ++i) {
UnsignedBigInteger::Word current_carry_for_word = 0;
if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(value.m_words[i], accumulator.m_words[i])) {
current_carry_for_word = 1;
} }
if (carry) { UnsignedBigInteger::Word word_addition_result = value.m_words[i] + accumulator.m_words[i];
word_addition_result++; if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(word_addition_result, last_carry_for_word)) {
current_carry_for_word = 1;
} }
carry = carry_out; word_addition_result += last_carry_for_word;
output.m_words[i] = word_addition_result; last_carry_for_word = current_carry_for_word;
accumulator.m_words[i] = word_addition_result;
} }
for (size_t i = shorter->length(); i < longer->length(); ++i) { // Ripple the carry over the remaining words in the accumulator until either there is no carry left or we run out of words
u32 word_addition_result = longer->m_words[i] + carry; while (last_carry_for_word && final_length > value_length) {
UnsignedBigInteger::Word current_carry_for_word = 0;
if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(accumulator.m_words[value_length], last_carry_for_word)) {
current_carry_for_word = 1;
}
accumulator.m_words[value_length] += last_carry_for_word;
last_carry_for_word = current_carry_for_word;
value_length++;
}
carry = 0; if (last_carry_for_word) {
if (word_addition_result < longer->m_words[i]) { // Note : The accumulator couldn't add the carry directly, so we reached its end
carry = 1; accumulator.m_words.append(last_carry_for_word);
}
output.m_words[i] = word_addition_result;
}
if (carry) {
output.m_words.append(carry);
} }
} }

View file

@ -13,18 +13,19 @@ namespace Crypto {
class UnsignedBigIntegerAlgorithms { class UnsignedBigIntegerAlgorithms {
public: public:
static void add_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output); 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 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_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_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); static void bitwise_xor_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& output);
static void bitwise_not_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger& output); static void bitwise_not_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger& output);
static void shift_left_without_allocation(UnsignedBigInteger const& number, size_t bits_to_shift_by, UnsignedBigInteger& temp_result, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output); static void shift_left_without_allocation(UnsignedBigInteger const& number, size_t bits_to_shift_by, UnsignedBigInteger& temp_result, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output);
static void multiply_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output); static void multiply_without_allocation(UnsignedBigInteger const& left, UnsignedBigInteger const& right, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& output);
static void divide_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger const& denominator, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_minus, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); static void divide_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger const& denominator, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_minus, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder);
static void divide_u16_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger::Word denominator, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); static void divide_u16_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger::Word denominator, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder);
static void destructive_GCD_without_allocation(UnsignedBigInteger& temp_a, UnsignedBigInteger& temp_b, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_remainder, UnsignedBigInteger& output); static void destructive_GCD_without_allocation(UnsignedBigInteger& temp_a, UnsignedBigInteger& temp_b, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_remainder, UnsignedBigInteger& output);
static void modular_inverse_without_allocation(UnsignedBigInteger const& a_, UnsignedBigInteger const& b, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_plus, UnsignedBigInteger& temp_minus, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_d, UnsignedBigInteger& temp_u, UnsignedBigInteger& temp_v, UnsignedBigInteger& temp_x, UnsignedBigInteger& result); static void modular_inverse_without_allocation(UnsignedBigInteger const& a_, UnsignedBigInteger const& b, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_minus, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_d, UnsignedBigInteger& temp_u, UnsignedBigInteger& temp_v, UnsignedBigInteger& temp_x, UnsignedBigInteger& result);
static void destructive_modular_power_without_allocation(UnsignedBigInteger& ep, UnsignedBigInteger& base, UnsignedBigInteger const& m, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_multiply, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_remainder, UnsignedBigInteger& result); static void destructive_modular_power_without_allocation(UnsignedBigInteger& ep, UnsignedBigInteger& base, UnsignedBigInteger const& m, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_3, UnsignedBigInteger& temp_4, UnsignedBigInteger& temp_multiply, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_remainder, UnsignedBigInteger& result);
private: private:

View file

@ -144,6 +144,15 @@ void UnsignedBigInteger::clamp_to_trimmed_length()
m_words.resize(length); m_words.resize(length);
} }
void UnsignedBigInteger::resize_with_leading_zeros(size_t new_length)
{
size_t old_length = length();
if (old_length < new_length) {
m_words.resize_and_keep_capacity(new_length);
__builtin_memset(&m_words.data()[old_length], 0, (new_length - old_length) * sizeof(u32));
}
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) const FLATTEN UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) const
{ {
UnsignedBigInteger result; UnsignedBigInteger result;
@ -215,9 +224,8 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigIn
UnsignedBigInteger temp_shift_result; UnsignedBigInteger temp_shift_result;
UnsignedBigInteger temp_shift_plus; UnsignedBigInteger temp_shift_plus;
UnsignedBigInteger temp_shift; UnsignedBigInteger temp_shift;
UnsignedBigInteger temp_plus;
UnsignedBigIntegerAlgorithms::multiply_without_allocation(*this, other, temp_shift_result, temp_shift_plus, temp_shift, temp_plus, result); UnsignedBigIntegerAlgorithms::multiply_without_allocation(*this, other, temp_shift_result, temp_shift_plus, temp_shift, result);
return result; return result;
} }

View file

@ -65,6 +65,7 @@ public:
size_t trimmed_length() const; size_t trimmed_length() const;
void clamp_to_trimmed_length(); void clamp_to_trimmed_length();
void resize_with_leading_zeros(size_t num_words);
UnsignedBigInteger plus(const UnsignedBigInteger& other) const; UnsignedBigInteger plus(const UnsignedBigInteger& other) const;
UnsignedBigInteger minus(const UnsignedBigInteger& other) const; UnsignedBigInteger minus(const UnsignedBigInteger& other) const;

View file

@ -20,7 +20,6 @@ UnsignedBigInteger ModularInverse(const UnsignedBigInteger& a_, const UnsignedBi
UnsignedBigInteger temp_2; UnsignedBigInteger temp_2;
UnsignedBigInteger temp_3; UnsignedBigInteger temp_3;
UnsignedBigInteger temp_4; UnsignedBigInteger temp_4;
UnsignedBigInteger temp_plus;
UnsignedBigInteger temp_minus; UnsignedBigInteger temp_minus;
UnsignedBigInteger temp_quotient; UnsignedBigInteger temp_quotient;
UnsignedBigInteger temp_d; UnsignedBigInteger temp_d;
@ -29,7 +28,7 @@ UnsignedBigInteger ModularInverse(const UnsignedBigInteger& a_, const UnsignedBi
UnsignedBigInteger temp_x; UnsignedBigInteger temp_x;
UnsignedBigInteger result; UnsignedBigInteger result;
UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(a_, b, temp_1, temp_2, temp_3, temp_4, temp_plus, temp_minus, temp_quotient, temp_d, temp_u, temp_v, temp_x, result); UnsignedBigIntegerAlgorithms::modular_inverse_without_allocation(a_, b, temp_1, temp_2, temp_3, temp_4, temp_minus, temp_quotient, temp_d, temp_u, temp_v, temp_x, result);
return result; return result;
} }
@ -93,7 +92,7 @@ UnsignedBigInteger LCM(const UnsignedBigInteger& a, const UnsignedBigInteger& b)
// output = (a / gcd_output) * b // output = (a / gcd_output) * b
UnsignedBigIntegerAlgorithms::divide_without_allocation(a, gcd_output, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); UnsignedBigIntegerAlgorithms::divide_without_allocation(a, gcd_output, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder);
UnsignedBigIntegerAlgorithms::multiply_without_allocation(temp_quotient, b, temp_1, temp_2, temp_3, temp_4, output); UnsignedBigIntegerAlgorithms::multiply_without_allocation(temp_quotient, b, temp_1, temp_2, temp_3, output);
dbgln_if(NT_DEBUG, "quot: {} rem: {} out: {}", temp_quotient, temp_remainder, output); dbgln_if(NT_DEBUG, "quot: {} rem: {} out: {}", temp_quotient, temp_remainder, output);

View file

@ -12,6 +12,7 @@
#include <LibCrypto/ASN1/ASN1.h> #include <LibCrypto/ASN1/ASN1.h>
#include <LibCrypto/Authentication/GHash.h> #include <LibCrypto/Authentication/GHash.h>
#include <LibCrypto/Authentication/HMAC.h> #include <LibCrypto/Authentication/HMAC.h>
#include <LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h>
#include <LibCrypto/BigInt/SignedBigInteger.h> #include <LibCrypto/BigInt/SignedBigInteger.h>
#include <LibCrypto/BigInt/UnsignedBigInteger.h> #include <LibCrypto/BigInt/UnsignedBigInteger.h>
#include <LibCrypto/Checksum/Adler32.h> #include <LibCrypto/Checksum/Adler32.h>
@ -2244,6 +2245,94 @@ static void bigint_addition_edgecases()
FAIL(Incorrect Result); FAIL(Incorrect Result);
} }
} }
{
I_TEST((BigInteger | Basic add to accumulator));
Crypto::UnsignedBigInteger num1(10);
Crypto::UnsignedBigInteger num2(70);
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 80 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to empty accumulator));
Crypto::UnsignedBigInteger num1({});
Crypto::UnsignedBigInteger num2(10);
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 10 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to smaller accumulator));
Crypto::UnsignedBigInteger num1(10);
Crypto::UnsignedBigInteger num2({ 10, 10 });
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 20, 10 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to accumulator with carry));
Crypto::UnsignedBigInteger num1(UINT32_MAX - 1);
Crypto::UnsignedBigInteger num2(2);
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 0, 1 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to accumulator with multiple carries));
Crypto::UnsignedBigInteger num1({ UINT32_MAX - 2, UINT32_MAX - 1 });
Crypto::UnsignedBigInteger num2({ 5, 1 });
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 2, 0, 1 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to accumulator with multiple carry levels));
Crypto::UnsignedBigInteger num1({ UINT32_MAX - 2, UINT32_MAX });
Crypto::UnsignedBigInteger num2(5);
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 2, 0, 1 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to accumulator with leading zero));
Crypto::UnsignedBigInteger num1(1);
Crypto::UnsignedBigInteger num2({ 1, 0 });
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 2 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
{
I_TEST((BigInteger | Add to accumulator with carry and leading zero));
Crypto::UnsignedBigInteger num1({ UINT32_MAX, 0, 0, 0 });
Crypto::UnsignedBigInteger num2({ 1, 0 });
Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2);
if (num1.words() == Vector<u32> { 0, 1, 0, 0 }) {
PASS;
} else {
FAIL(Incorrect Result);
}
}
} }
static void bigint_subtraction() static void bigint_subtraction()