diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-06-06 01:36:03 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-06-07 19:29:40 +0200 |
commit | 02c53fd1f965ac470a14366650946339bcc8f0ab (patch) | |
tree | 1604d008f8d1679dcb0eb0e0d050adc8b9b7c40c /Libraries/LibCrypto | |
parent | fbb1d9afe582362f62c7fc9c168b5361dec63031 (diff) | |
download | serenity-02c53fd1f965ac470a14366650946339bcc8f0ab.zip |
LibCrypto: Add bitwise operations (and/or/xor)
Diffstat (limited to 'Libraries/LibCrypto')
-rw-r--r-- | Libraries/LibCrypto/BigInt/SignedBigInteger.cpp | 51 | ||||
-rw-r--r-- | Libraries/LibCrypto/BigInt/SignedBigInteger.h | 7 | ||||
-rw-r--r-- | Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp | 183 | ||||
-rw-r--r-- | Libraries/LibCrypto/BigInt/UnsignedBigInteger.h | 8 |
4 files changed, 249 insertions, 0 deletions
diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp index da17c8935d..bda62f698c 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp @@ -139,6 +139,57 @@ FLATTEN SignedBigInteger SignedBigInteger::minus(const UnsignedBigInteger& other return { other.minus(m_unsigned_data), true }; } +FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const UnsignedBigInteger& other) const +{ + return { unsigned_value().bitwise_or(other), m_sign }; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const UnsignedBigInteger& other) const +{ + return { unsigned_value().bitwise_and(other), false }; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const UnsignedBigInteger& other) const +{ + return { unsigned_value().bitwise_xor(other), m_sign }; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const +{ + return { unsigned_value().bitwise_not(), !m_sign }; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const SignedBigInteger& other) const +{ + auto result = bitwise_or(other.unsigned_value()); + + // The sign bit will have to be OR'd manually. + if (other.is_negative()) + result.negate(); + + return result; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const SignedBigInteger& other) const +{ + auto result = bitwise_and(other.unsigned_value()); + + // The sign bit will have to be AND'd manually. + result.m_sign = is_negative() || other.is_negative(); + + return result; +} + +FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const SignedBigInteger& other) const +{ + auto result = bitwise_xor(other.unsigned_value()); + + // The sign bit will have to be XOR'd manually. + result.m_sign = is_negative() ^ other.is_negative(); + + return result; +} + bool SignedBigInteger::operator==(const UnsignedBigInteger& other) const { if (m_sign) diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.h b/Libraries/LibCrypto/BigInt/SignedBigInteger.h index d784c007fc..1ff220daa1 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.h @@ -107,12 +107,19 @@ public: SignedBigInteger plus(const SignedBigInteger& other) const; SignedBigInteger minus(const SignedBigInteger& other) const; + SignedBigInteger bitwise_or(const SignedBigInteger& other) const; + SignedBigInteger bitwise_and(const SignedBigInteger& other) const; + SignedBigInteger bitwise_xor(const SignedBigInteger& other) const; + SignedBigInteger bitwise_not() const; SignedBigInteger shift_left(size_t num_bits) const; SignedBigInteger multiplied_by(const SignedBigInteger& other) const; SignedDivisionResult divided_by(const SignedBigInteger& divisor) const; SignedBigInteger plus(const UnsignedBigInteger& other) const; SignedBigInteger minus(const UnsignedBigInteger& other) const; + SignedBigInteger bitwise_or(const UnsignedBigInteger& other) const; + SignedBigInteger bitwise_and(const UnsignedBigInteger& other) const; + SignedBigInteger bitwise_xor(const UnsignedBigInteger& other) const; SignedBigInteger multiplied_by(const UnsignedBigInteger& other) const; SignedDivisionResult divided_by(const UnsignedBigInteger& divisor) const; diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp index 60676fc9b6..bfc141f38d 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp @@ -158,6 +158,42 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::minus(const UnsignedBigInteger& o return result; } +FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_or(const UnsignedBigInteger& other) const +{ + UnsignedBigInteger result; + + bitwise_or_without_allocation(*this, other, result); + + return result; +} + +FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_and(const UnsignedBigInteger& other) const +{ + UnsignedBigInteger result; + + bitwise_and_without_allocation(*this, other, result); + + return result; +} + +FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_xor(const UnsignedBigInteger& other) const +{ + UnsignedBigInteger result; + + bitwise_xor_without_allocation(*this, other, result); + + return result; +} + +FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_not() const +{ + UnsignedBigInteger result; + + bitwise_not_without_allocation(*this, result); + + return result; +} + FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const { UnsignedBigInteger output; @@ -341,6 +377,153 @@ void UnsignedBigInteger::subtract_without_allocation( } /** + * Complexity: O(N) where N is the number of words in the shorter value + * Method: + * Apply <op> word-wise until words in the shorter value are used up + * then copy the rest of the words verbatim from the longer value. + */ +FLATTEN void UnsignedBigInteger::bitwise_or_without_allocation( + const UnsignedBigInteger& left, + const UnsignedBigInteger& 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; + } + + const UnsignedBigInteger *shorter, *longer; + if (left.length() < right.length()) { + shorter = &left; + longer = &right; + } else { + shorter = &right; + longer = &left; + } + + output.m_words.resize_and_keep_capacity(longer->length()); + + size_t longer_offset = longer->length() - shorter->length(); + for (size_t i = 0; i < shorter->length(); ++i) + output.m_words[i] = longer->words()[i] | shorter->words()[i]; + + __builtin_memcpy(output.m_words.data() + shorter->length(), longer->words().data() + shorter->length(), sizeof(u32) * longer_offset); +} + +/** + * Complexity: O(N) where N is the number of words in the shorter value + * Method: + * Apply 'and' word-wise until words in the shorter value are used up + * and zero the rest. + */ +FLATTEN void UnsignedBigInteger::bitwise_and_without_allocation( + const UnsignedBigInteger& left, + const UnsignedBigInteger& 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; + } + + const UnsignedBigInteger *shorter, *longer; + if (left.length() < right.length()) { + shorter = &left; + longer = &right; + } else { + shorter = &right; + longer = &left; + } + + output.m_words.resize_and_keep_capacity(longer->length()); + + size_t longer_offset = longer->length() - shorter->length(); + for (size_t i = 0; i < shorter->length(); ++i) + output.m_words[i] = longer->words()[i] & shorter->words()[i]; + + __builtin_memset(output.m_words.data() + shorter->length(), 0, sizeof(u32) * longer_offset); +} + +/** + * Complexity: O(N) where N is the number of words in the shorter value + * Method: + * Apply 'xor' word-wise until words in the shorter value are used up + * and copy the rest. + */ +FLATTEN void UnsignedBigInteger::bitwise_xor_without_allocation( + const UnsignedBigInteger& left, + const UnsignedBigInteger& 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; + } + + const UnsignedBigInteger *shorter, *longer; + if (left.length() < right.length()) { + shorter = &left; + longer = &right; + } else { + shorter = &right; + longer = &left; + } + + output.m_words.resize_and_keep_capacity(longer->length()); + + size_t longer_offset = longer->length() - shorter->length(); + for (size_t i = 0; i < shorter->length(); ++i) + output.m_words[i] = longer->words()[i] ^ shorter->words()[i]; + + __builtin_memcpy(output.m_words.data() + shorter->length(), longer->words().data() + shorter->length(), sizeof(u32) * longer_offset); +} + +/** + * Complexity: O(N) where N is the number of words + */ +FLATTEN void UnsignedBigInteger::bitwise_not_without_allocation( + const UnsignedBigInteger& right, + UnsignedBigInteger& output) +{ + // If the value is invalid, the output value is invalid as well. + if (right.is_invalid()) { + output.invalidate(); + return; + } + if (right.length() == 0) { + output.set_to_0(); + return; + } + + output.m_words.resize_and_keep_capacity(right.length()); + + if (right.length() > 1) { + for (size_t i = 0; i < right.length() - 1; ++i) + output.m_words[i] = ~right.words()[i]; + } + + auto last_word_index = right.length() - 1; + auto last_word = right.words()[last_word_index]; + + output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> __builtin_clz(last_word)) & ~last_word; +} + +/** * 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), diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h index d19707fbc7..e9aaef04a0 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h @@ -83,6 +83,10 @@ public: UnsignedBigInteger plus(const UnsignedBigInteger& other) const; UnsignedBigInteger minus(const UnsignedBigInteger& other) const; + UnsignedBigInteger bitwise_or(const UnsignedBigInteger& other) const; + UnsignedBigInteger bitwise_and(const UnsignedBigInteger& other) const; + UnsignedBigInteger bitwise_xor(const UnsignedBigInteger& other) const; + UnsignedBigInteger bitwise_not() const; UnsignedBigInteger shift_left(size_t num_bits) const; UnsignedBigInteger multiplied_by(const UnsignedBigInteger& other) const; UnsignedDivisionResult divided_by(const UnsignedBigInteger& divisor) const; @@ -91,6 +95,10 @@ public: static void add_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output); static void subtract_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output); + static void bitwise_or_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output); + static void bitwise_and_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output); + static void bitwise_xor_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output); + static void bitwise_not_without_allocation(const UnsignedBigInteger& left, UnsignedBigInteger& output); static void shift_left_without_allocation(const UnsignedBigInteger& number, size_t bits_to_shift_by, UnsignedBigInteger& temp_result, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output); static void multiply_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output); static void divide_without_allocation(const UnsignedBigInteger& numerator, const UnsignedBigInteger& denominator, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_minus, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); |