Open andrewkozlik opened 3 years ago
1 - 3
Correct observations
- There are a lot of functions which are declared, but do not seem to be defined anywhere like
bn_fast_mod_old
,bn_inverse_fast_1()
,bn_inverse_fast_2()
,bn_inverse_fast_3()
orbn_inverse_old()
.
These are probably just leftovers which can be deleted. We removed these functions, but forgot to remove declarations. PR in https://github.com/trezor/trezor-firmware/pull/1525
I am not sure how feasible the following changes are given that the
bn_*
functions might already be being used downstream, but let's see what we can do. The bignum functions have a very inconsistent API, which makes them rather error-prone to use and difficult to read any code that uses them, because it's nearly impossible to tell what each function does without looking at the declaration every single time.There is no clear position for the return value. For example:
bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime)
bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime)
bn_power_mod(const bignum256 *x, const bignum256 *e, const bignum256 *prime, bignum256 *res)
The first function uses the first argument to return the result, the second uses the middle argument and the last uses the last argument to return the result. I am unable to discern any pattern among the functions. It would help if they respected some convention, ideally if the first argument was the return value as is common in the standard C library functions likememcpy(dest, source, n)
.The function name
bn_mod()
is misleading, because what it does is actuallybn_mod(k, n) = k < n ? k : k - n
. Perhaps rename tobn_mod_finish()
. Also the signature of the functionvoid bn_mod(bignum256 *x, const bignum256 *prime)
is misleading, because the second parameter can be any nonzero normalizedbignum256
.The interface is rather inconsistent in terms of how similarly named functions behave, for example:
bn_add(bignum256 *x, const bignum256 *y)
bn_subtract(const bignum256 *x, const bignum256 *y, bignum256 *res)
The first isx += y
and the second isres = x - y
. I actually don't have a problem with this, because you can tell from the number of parameters, so this can stay. However, the following is a total mess:bn_addi(bignum256 *x, uint32_t y)
bn_subi(bignum256 *x, uint32_t y, const bignum256 *prime)
bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime)
bn_read_uint32(uint32_t in_number, bignum256 *out_number)
The names of the second and third function should end with_mod
and they should all be consistent in indicating that one of the operands is a small integer. For examplebn_add_uint32
,bn_sub_uint32_mod
,bn_mult_uint8_mod
and the last function should have the arguments swapped as noted in point 1. It's important that the width of the integer type be clearly indicated in the function name, since if anuint32_t
is passed tobn_mult_k()
as the second argument, then it will get truncated touint8_t
without any warning.There are a lot of functions which are declared, but do not seem to be defined anywhere like
bn_fast_mod_old()
,bn_inverse_fast_1()
,bn_inverse_fast_2()
,bn_inverse_fast_3()
orbn_inverse_old()
.The above are just examples. Someone would need to go through the functions one-by-one to unify the naming and argument order.