From 4a686d9231d61e7f7b07ec3c0231f7f28aeb37b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Vejpustek?= Date: Tue, 19 Sep 2023 15:01:30 +0200 Subject: [PATCH] feat(crypto): introduce bn_read_be_512 --- crypto/bignum.c | 24 ++++++++++++++++++++++++ crypto/bignum.h | 1 + crypto/tests/test_bignum.py | 11 +++++++++++ 3 files changed, 36 insertions(+) diff --git a/crypto/bignum.c b/crypto/bignum.c index 1bc2f3698d..aa3b7ba30a 100644 --- a/crypto/bignum.c +++ b/crypto/bignum.c @@ -107,6 +107,30 @@ void bn_read_be(const uint8_t *in_number, bignum256 *out_number) { out_number->val[BN_LIMBS - 1] = temp; } +// out_number = (bignum512) in_number +// Assumes in_number is a raw bigendian 512-bit number +// Guarantees out_number is normalized +void bn_read_be_512(const uint8_t *in_number, bignum512 *out_number) { + bignum256 lower = {0}, upper = {0}; + + bn_read_be(in_number + 32, &lower); + bn_read_be(in_number, &upper); + + const int shift_length = BN_BITS_PER_LIMB * BN_LIMBS - 256; + uint32_t shift = upper.val[0] & ((1 << shift_length) - 1); + for (int i = 0; i < shift_length; i++) { + bn_rshift(&upper); + } + lower.val[BN_LIMBS - 1] |= shift << (BN_BITS_PER_LIMB - shift_length); + + for (int i = 0; i < BN_LIMBS; i++) { + out_number->val[i] = lower.val[i]; + } + for (int i = 0; i < BN_LIMBS; i++) { + out_number->val[i + BN_LIMBS] = upper.val[i]; + } +} + // out_number = (256BE) in_number // Assumes in_number < 2**256 // Guarantess out_number is a raw bigendian 256-bit number diff --git a/crypto/bignum.h b/crypto/bignum.h index 17ef553a5f..98a0b3c6c9 100644 --- a/crypto/bignum.h +++ b/crypto/bignum.h @@ -74,6 +74,7 @@ static inline void write_le(uint8_t *data, uint32_t x) { void bn_copy_lower(const bignum512 *x, bignum256 *y); void bn_read_be(const uint8_t *in_number, bignum256 *out_number); +void bn_read_be_512(const uint8_t *in_number, bignum512 *out_number); void bn_write_be(const bignum256 *in_number, uint8_t *out_number); void bn_read_le(const uint8_t *in_number, bignum256 *out_number); void bn_write_le(const bignum256 *in_number, uint8_t *out_number); diff --git a/crypto/tests/test_bignum.py b/crypto/tests/test_bignum.py index 800d05f6a6..ea6b4eac82 100755 --- a/crypto/tests/test_bignum.py +++ b/crypto/tests/test_bignum.py @@ -216,6 +216,13 @@ def assert_bn_read_be(in_number): assert bignum_is_normalised(bn_out_number) assert out_number == in_number + +def assert_bn_read_be_512(in_number): + raw_in_number = integer_to_raw_number512(in_number, "big") + bn_out_number = bignum512() + lib.bn_read_be_512(raw_in_number, bn_out_number) + out_number = bignum512_to_int(bn_out_number) + assert bignum_is_normalised(bn_out_number) assert out_number == in_number @@ -760,6 +767,10 @@ def test_bn_read_be(r): assert_bn_read_be(r.rand_int_256()) +def test_bn_read_be_512(r): + assert_bn_read_be_512(r.rand_int_512()) + + def test_bn_read_le(r): assert_bn_read_le(r.rand_int_256())