summaryrefslogtreecommitdiff
path: root/Libraries/LibCrypto
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-06-06 01:36:03 +0430
committerAndreas Kling <kling@serenityos.org>2020-06-07 19:29:40 +0200
commit02c53fd1f965ac470a14366650946339bcc8f0ab (patch)
tree1604d008f8d1679dcb0eb0e0d050adc8b9b7c40c /Libraries/LibCrypto
parentfbb1d9afe582362f62c7fc9c168b5361dec63031 (diff)
downloadserenity-02c53fd1f965ac470a14366650946339bcc8f0ab.zip
LibCrypto: Add bitwise operations (and/or/xor)
Diffstat (limited to 'Libraries/LibCrypto')
-rw-r--r--Libraries/LibCrypto/BigInt/SignedBigInteger.cpp51
-rw-r--r--Libraries/LibCrypto/BigInt/SignedBigInteger.h7
-rw-r--r--Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp183
-rw-r--r--Libraries/LibCrypto/BigInt/UnsignedBigInteger.h8
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);