diff --git a/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp b/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp index 980596181ca..5d240970959 100644 --- a/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp +++ b/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp @@ -160,13 +160,23 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_not_fill_to_one_based_index_w output.m_words[last_word_index] = (NumericLimits::max() >> (UnsignedBigInteger::BITS_IN_WORD - index)) & ~last_word; } +FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation( + UnsignedBigInteger const& number, + size_t num_bits, + UnsignedBigInteger& temp_result, + UnsignedBigInteger& temp_plus, + UnsignedBigInteger& output) +{ + MUST(try_shift_left_without_allocation(number, num_bits, temp_result, temp_plus, output)); +} + /** * Complexity : O(N + num_bits % 8) where N is the number of words in the number * Shift method : * Start by shifting by whole words in num_bits (by putting missing words at the start), * then shift the number's words two by two by the remaining amount of bits. */ -FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation( +FLATTEN ErrorOr UnsignedBigIntegerAlgorithms::try_shift_left_without_allocation( UnsignedBigInteger const& number, size_t num_bits, UnsignedBigInteger& temp_result, @@ -177,7 +187,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation( // where the shift amount is <= size of word (32). // But we do know how to shift by a multiple of word size (e.g 64=32*2) // So we first shift the result by how many whole words fit in 'num_bits' - shift_left_by_n_words(number, num_bits / UnsignedBigInteger::BITS_IN_WORD, temp_result); + TRY(try_shift_left_by_n_words(number, num_bits / UnsignedBigInteger::BITS_IN_WORD, temp_result)); output.set_to(temp_result); @@ -185,7 +195,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation( num_bits %= UnsignedBigInteger::BITS_IN_WORD; if (num_bits == 0) { - return; + return {}; } for (size_t i = 0; i < temp_result.length(); ++i) { @@ -202,9 +212,11 @@ FLATTEN void UnsignedBigIntegerAlgorithms::shift_left_without_allocation( // efficient nor pretty. Maybe we should have an "add_with_shift" method ? temp_plus.set_to_0(); temp_plus.m_words.append(carry_word); - shift_left_by_n_words(temp_plus, temp_result.length(), temp_result); + TRY(try_shift_left_by_n_words(temp_plus, temp_result.length(), temp_result)); add_into_accumulator_without_allocation(output, temp_result); } + + return {}; } FLATTEN void UnsignedBigIntegerAlgorithms::shift_right_without_allocation( @@ -220,13 +232,23 @@ void UnsignedBigIntegerAlgorithms::shift_left_by_n_words( UnsignedBigInteger const& number, size_t number_of_words, UnsignedBigInteger& output) +{ + MUST(try_shift_left_by_n_words(number, number_of_words, output)); +} + +ErrorOr UnsignedBigIntegerAlgorithms::try_shift_left_by_n_words( + UnsignedBigInteger const& number, + size_t number_of_words, + UnsignedBigInteger& output) { // shifting left by N words means just inserting N zeroes to the beginning of the words vector output.set_to_0(); - output.m_words.resize_and_keep_capacity(number_of_words + number.length()); + TRY(output.m_words.try_resize_and_keep_capacity(number_of_words + number.length())); __builtin_memset(output.m_words.data(), 0, number_of_words * sizeof(unsigned)); __builtin_memcpy(&output.m_words.data()[number_of_words], number.m_words.data(), number.m_words.size() * sizeof(unsigned)); + + return {}; } void UnsignedBigIntegerAlgorithms::shift_right_by_n_words( diff --git a/Libraries/LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h b/Libraries/LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h index d40961b89a2..bd166c807c7 100644 --- a/Libraries/LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h +++ b/Libraries/LibCrypto/BigInt/Algorithms/UnsignedBigIntegerAlgorithms.h @@ -27,6 +27,8 @@ public: static void divide_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger const& denominator, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); static void divide_u16_without_allocation(UnsignedBigInteger const& numerator, UnsignedBigInteger::Word denominator, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); + static ErrorOr try_shift_left_without_allocation(UnsignedBigInteger const& number, size_t bits_to_shift_by, UnsignedBigInteger& temp_result, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output); + static void extended_GCD_without_allocation(UnsignedBigInteger const& a, UnsignedBigInteger const& b, UnsignedBigInteger& x, UnsignedBigInteger& y, UnsignedBigInteger& gcd, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_r, UnsignedBigInteger& temp_s, UnsignedBigInteger& temp_t); static void destructive_GCD_without_allocation(UnsignedBigInteger& temp_a, UnsignedBigInteger& temp_b, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_remainder, UnsignedBigInteger& output); static void modular_inverse_without_allocation(UnsignedBigInteger const& a, UnsignedBigInteger const& b, UnsignedBigInteger& result, UnsignedBigInteger& temp_y, UnsignedBigInteger& temp_gcd, UnsignedBigInteger& temp_quotient, UnsignedBigInteger& temp_1, UnsignedBigInteger& temp_2, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_r, UnsignedBigInteger& temp_s, UnsignedBigInteger& temp_t); @@ -39,6 +41,8 @@ private: static void shift_left_by_n_words(UnsignedBigInteger const& number, size_t number_of_words, UnsignedBigInteger& output); static void shift_right_by_n_words(UnsignedBigInteger const& number, size_t number_of_words, UnsignedBigInteger& output); ALWAYS_INLINE static UnsignedBigInteger::Word shift_left_get_one_word(UnsignedBigInteger const& number, size_t num_bits, size_t result_word_index); + + static ErrorOr try_shift_left_by_n_words(UnsignedBigInteger const& number, size_t number_of_words, UnsignedBigInteger& output); }; } diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp index a158d9db73a..f1f89069c05 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp @@ -276,9 +276,14 @@ bool SignedBigInteger::operator>(UnsignedBigInteger const& other) const return *this != other && !(*this < other); } +FLATTEN ErrorOr SignedBigInteger::try_shift_left(size_t num_bits) const +{ + return SignedBigInteger { TRY(m_unsigned_data.try_shift_left(num_bits)), m_sign }; +} + FLATTEN SignedBigInteger SignedBigInteger::shift_left(size_t num_bits) const { - return SignedBigInteger { m_unsigned_data.shift_left(num_bits), m_sign }; + return MUST(try_shift_left(num_bits)); } FLATTEN SignedBigInteger SignedBigInteger::shift_right(size_t num_bits) const diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.h b/Libraries/LibCrypto/BigInt/SignedBigInteger.h index a410da22d09..73771567774 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.h @@ -120,6 +120,8 @@ public: [[nodiscard]] SignedBigInteger multiplied_by(SignedBigInteger const& other) const; [[nodiscard]] SignedDivisionResult divided_by(SignedBigInteger const& divisor) const; + [[nodiscard]] ErrorOr try_shift_left(size_t num_bits) const; + [[nodiscard]] SignedBigInteger plus(UnsignedBigInteger const& other) const; [[nodiscard]] SignedBigInteger minus(UnsignedBigInteger const& other) const; [[nodiscard]] SignedBigInteger multiplied_by(UnsignedBigInteger const& other) const; diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp index 4496a30c8d8..73054427599 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp @@ -481,17 +481,22 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_not_fill_to_one_based_ind return result; } -FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const +FLATTEN ErrorOr UnsignedBigInteger::try_shift_left(size_t num_bits) const { UnsignedBigInteger output; UnsignedBigInteger temp_result; UnsignedBigInteger temp_plus; - UnsignedBigIntegerAlgorithms::shift_left_without_allocation(*this, num_bits, temp_result, temp_plus, output); + TRY(UnsignedBigIntegerAlgorithms::try_shift_left_without_allocation(*this, num_bits, temp_result, temp_plus, output)); return output; } +FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const +{ + return MUST(try_shift_left(num_bits)); +} + FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_right(size_t num_bits) const { UnsignedBigInteger output; diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h index c133e37ca99..0e354a51161 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h @@ -120,6 +120,8 @@ public: [[nodiscard]] UnsignedBigInteger multiplied_by(UnsignedBigInteger const& other) const; [[nodiscard]] UnsignedDivisionResult divided_by(UnsignedBigInteger const& divisor) const; + [[nodiscard]] ErrorOr try_shift_left(size_t num_bits) const; + [[nodiscard]] u32 hash() const; void set_bit_inplace(size_t bit_index);