mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
bignum: introduce read/write_le
This commit is contained in:
parent
ec316b6afc
commit
62a0db8c4e
@ -4,6 +4,7 @@ Jochen Hoenicke <hoenicke@gmail.com>
|
||||
Dustin Laurence <dustin@laurences.net>
|
||||
Ondrej Mikle <ondrej.mikle@nic.cz>
|
||||
Roman Zeyde <roman.zeyde@gmail.com>
|
||||
Alex Beregszaszi <alex@rtfs.hu>
|
||||
netanelkl <netanel.keidar@gmail.com>
|
||||
Jan Pochyla <jpochyla@gmail.com>
|
||||
Ondrej Mikle <ondrej.mikle@gmail.com>
|
||||
|
52
bignum.c
52
bignum.c
@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
* Copyright (c) 2015 Jochen Hoenicke
|
||||
* Copyright (c) 2016 Alex Beregszaszi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
@ -69,6 +70,22 @@ inline void write_be(uint8_t *data, uint32_t x)
|
||||
data[3] = x;
|
||||
}
|
||||
|
||||
inline uint32_t read_le(const uint8_t *data)
|
||||
{
|
||||
return (((uint32_t)data[3]) << 24) |
|
||||
(((uint32_t)data[2]) << 16) |
|
||||
(((uint32_t)data[1]) << 8) |
|
||||
(((uint32_t)data[0]));
|
||||
}
|
||||
|
||||
inline void write_le(uint8_t *data, uint32_t x)
|
||||
{
|
||||
data[3] = x >> 24;
|
||||
data[2] = x >> 16;
|
||||
data[1] = x >> 8;
|
||||
data[0] = x;
|
||||
}
|
||||
|
||||
// convert a raw bigendian 256 bit value into a normalized bignum.
|
||||
// out_number is partly reduced (since it fits in 256 bit).
|
||||
void bn_read_be(const uint8_t *in_number, bignum256 *out_number)
|
||||
@ -104,6 +121,41 @@ void bn_write_be(const bignum256 *in_number, uint8_t *out_number)
|
||||
}
|
||||
}
|
||||
|
||||
// convert a raw little endian 256 bit value into a normalized bignum.
|
||||
// out_number is partly reduced (since it fits in 256 bit).
|
||||
void bn_read_le(const uint8_t *in_number, bignum256 *out_number)
|
||||
{
|
||||
int i;
|
||||
uint32_t temp = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
// invariant: temp = (in_number % 2^(32i)) >> 30i
|
||||
// get next limb = (in_number % 2^(32(i+1))) >> 32i
|
||||
uint32_t limb = read_le(in_number + i * 4);
|
||||
// temp = (in_number % 2^(32(i+1))) << 30i
|
||||
temp |= limb << (2*i);
|
||||
// store 30 bits into val[i]
|
||||
out_number->val[i]= temp & 0x3FFFFFFF;
|
||||
// prepare temp for next round
|
||||
temp = limb >> (30 - 2*i);
|
||||
}
|
||||
out_number->val[8] = temp;
|
||||
}
|
||||
|
||||
// convert a normalized bignum to a raw little endian 256 bit number.
|
||||
// in_number must be fully reduced.
|
||||
void bn_write_le(const bignum256 *in_number, uint8_t *out_number)
|
||||
{
|
||||
int i;
|
||||
uint32_t temp = in_number->val[8] << 16;
|
||||
for (i = 0; i < 8; i++) {
|
||||
// invariant: temp = (in_number >> 30*(8-i)) << (16 + 2i)
|
||||
uint32_t limb = in_number->val[7 - i];
|
||||
temp |= limb >> (14 - 2*i);
|
||||
write_le(out_number + (7 - i) * 4, temp);
|
||||
temp = limb << (18 + 2*i);
|
||||
}
|
||||
}
|
||||
|
||||
// sets a bignum to zero.
|
||||
void bn_zero(bignum256 *a)
|
||||
{
|
||||
|
10
bignum.h
10
bignum.h
@ -39,10 +39,20 @@ uint32_t read_be(const uint8_t *data);
|
||||
// write 4 big endian bytes
|
||||
void write_be(uint8_t *data, uint32_t x);
|
||||
|
||||
// read 4 little endian bytes into uint32
|
||||
uint32_t read_le(const uint8_t *data);
|
||||
|
||||
// write 4 little endian bytes
|
||||
void write_le(uint8_t *data, uint32_t x);
|
||||
|
||||
void bn_read_be(const uint8_t *in_number, bignum256 *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);
|
||||
|
||||
void bn_zero(bignum256 *a);
|
||||
|
||||
int bn_is_zero(const bignum256 *a);
|
||||
|
32
tests.c
32
tests.c
@ -123,6 +123,36 @@ START_TEST(test_bignum_equal)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bignum_read_le)
|
||||
{
|
||||
bignum256 a;
|
||||
bignum256 b;
|
||||
|
||||
bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a);
|
||||
bn_read_le(fromhex("d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), &b);
|
||||
|
||||
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bignum_write_le)
|
||||
{
|
||||
bignum256 a;
|
||||
bignum256 b;
|
||||
uint8_t tmp[32];
|
||||
|
||||
bn_read_be(fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), &a);
|
||||
bn_write_le(&a, tmp);
|
||||
|
||||
bn_read_le(tmp, &b);
|
||||
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
|
||||
|
||||
bn_read_be(fromhex("d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"), &a);
|
||||
bn_read_be(tmp, &b);
|
||||
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
// from https://github.com/bitcoin/bitcoin/blob/master/src/test/data/base58_keys_valid.json
|
||||
START_TEST(test_base58)
|
||||
{
|
||||
@ -2371,6 +2401,8 @@ Suite *test_suite(void)
|
||||
tcase_add_test(tc, test_bignum_read_be);
|
||||
tcase_add_test(tc, test_bignum_write_be);
|
||||
tcase_add_test(tc, test_bignum_equal);
|
||||
tcase_add_test(tc, test_bignum_read_le);
|
||||
tcase_add_test(tc, test_bignum_write_le);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("base58");
|
||||
|
Loading…
Reference in New Issue
Block a user