Path: blob/main/crypto/libecc/src/examples/sig/common/common.h
34927 views
/* Some common helpers useful for many algorithms */1#ifndef __COMMON_H__2#define __COMMON_H__34/* Include our arithmetic layer */5#include <libecc/libarith.h>67/* I2OSP and OS2IP internal primitives */8ATTRIBUTE_WARN_UNUSED_RET static inline int _i2osp(nn_src_t x, u8 *buf, u16 buflen)9{10int ret;11bitcnt_t blen;1213/* Sanity checks */14MUST_HAVE((buf != NULL), ret, err);15ret = nn_check_initialized(x); EG(ret, err);1617/* If x >= 256^xLen (the integer does not fit in the buffer),18* return an error.19*/20ret = nn_bitlen(x, &blen); EG(ret, err);21MUST_HAVE(((8 * buflen) >= blen), ret, err);2223/* Export to the buffer */24ret = nn_export_to_buf(buf, buflen, x);2526err:27return ret;28}2930ATTRIBUTE_WARN_UNUSED_RET static inline int _os2ip(nn_t x, const u8 *buf, u16 buflen)31{32int ret;3334/* We do not want to exceed our computation compatible35* size.36*/37MUST_HAVE((buflen <= NN_USABLE_MAX_BYTE_LEN), ret, err);3839/* Import the NN */40ret = nn_init_from_buf(x, buf, buflen);4142err:43return ret;44}4546/* Reverses the endiannes of a buffer in place */47ATTRIBUTE_WARN_UNUSED_RET static inline int _reverse_endianness(u8 *buf, u16 buf_size)48{49u16 i;50u8 tmp;51int ret;5253MUST_HAVE((buf != NULL), ret, err);5455if(buf_size > 1){56for(i = 0; i < (buf_size / 2); i++){57tmp = buf[i];58buf[i] = buf[buf_size - 1 - i];59buf[buf_size - 1 - i] = tmp;60}61}6263ret = 0;6465err:66return ret;67}6869/* Helper to fix the MSB of a scalar using the trick in70* https://eprint.iacr.org/2011/232.pdf71*72* We distinguish three situations:73* - The scalar m is < q (the order), in this case we compute:74* -75* | m' = m + (2 * q) if [log(k + q)] == [log(q)],76* | m' = m + q otherwise.77* -78* - The scalar m is >= q and < q**2, in this case we compute:79* -80* | m' = m + (2 * (q**2)) if [log(k + (q**2))] == [log(q**2)],81* | m' = m + (q**2) otherwise.82* -83* - The scalar m is >= (q**2), in this case m == m'84* We only deal with 0 <= m < (q**2) using the countermeasure. When m >= (q**2),85* we stick with m' = m, accepting MSB issues (not much can be done in this case86* anyways).87*/88ATTRIBUTE_WARN_UNUSED_RET static inline int _fix_scalar_msb(nn_src_t m, nn_src_t q, nn_t m_msb_fixed)89{90int ret, cmp;91/* _m_msb_fixed to handle aliasing */92nn q_square, _m_msb_fixed;93q_square.magic = _m_msb_fixed.magic = WORD(0);9495/* Sanity checks */96ret = nn_check_initialized(m); EG(ret, err);97ret = nn_check_initialized(q); EG(ret, err);98ret = nn_check_initialized(m_msb_fixed); EG(ret, err);99100ret = nn_init(&q_square, 0); EG(ret, err);101ret = nn_init(&_m_msb_fixed, 0); EG(ret, err);102103/* First compute q**2 */104ret = nn_sqr(&q_square, q); EG(ret, err);105/* Then compute m' depending on m size */106ret = nn_cmp(m, q, &cmp); EG(ret, err);107if (cmp < 0){108bitcnt_t msb_bit_len, q_bitlen;109110/* Case where m < q */111ret = nn_add(&_m_msb_fixed, m, q); EG(ret, err);112ret = nn_bitlen(&_m_msb_fixed, &msb_bit_len); EG(ret, err);113ret = nn_bitlen(q, &q_bitlen); EG(ret, err);114ret = nn_cnd_add((msb_bit_len == q_bitlen), m_msb_fixed,115&_m_msb_fixed, q); EG(ret, err);116} else {117ret = nn_cmp(m, &q_square, &cmp); EG(ret, err);118if (cmp < 0) {119bitcnt_t msb_bit_len, q_square_bitlen;120121/* Case where m >= q and m < (q**2) */122ret = nn_add(&_m_msb_fixed, m, &q_square); EG(ret, err);123ret = nn_bitlen(&_m_msb_fixed, &msb_bit_len); EG(ret, err);124ret = nn_bitlen(&q_square, &q_square_bitlen); EG(ret, err);125ret = nn_cnd_add((msb_bit_len == q_square_bitlen),126m_msb_fixed, &_m_msb_fixed, &q_square); EG(ret, err);127} else {128/* Case where m >= (q**2) */129ret = nn_copy(m_msb_fixed, m); EG(ret, err);130}131}132133err:134nn_uninit(&q_square);135nn_uninit(&_m_msb_fixed);136137return ret;138}139140/* Helper to blind the scalar.141* Compute m_blind = m + (b * q) where b is a random value modulo q.142* Aliasing is supported.143*/144ATTRIBUTE_WARN_UNUSED_RET static inline int _blind_scalar(nn_src_t m, nn_src_t q, nn_t m_blind)145{146int ret;147nn tmp;148tmp.magic = WORD(0);149150/* Sanity checks */151ret = nn_check_initialized(m); EG(ret, err);152ret = nn_check_initialized(q); EG(ret, err);153ret = nn_check_initialized(m_blind); EG(ret, err);154155ret = nn_get_random_mod(&tmp, q); EG(ret, err);156157ret = nn_mul(&tmp, &tmp, q); EG(ret, err);158ret = nn_add(m_blind, &tmp, m);159160err:161nn_uninit(&tmp);162163return ret;164}165166/*167* NOT constant time at all and not secure against side-channels. This is168* an internal function only used for DSA verification on public data.169*170* Compute (base ** exp) mod (mod) using a square and multiply algorithm.171* Internally, this computes Montgomery coefficients and uses the redc172* function.173*174* Returns 0 on success, -1 on error.175*/176ATTRIBUTE_WARN_UNUSED_RET static inline int _nn_mod_pow_insecure(nn_t out, nn_src_t base,177nn_src_t exp, nn_src_t mod)178{179int ret, isodd, cmp;180bitcnt_t explen;181u8 expbit;182nn r, r_square, _base, one;183word_t mpinv;184r.magic = r_square.magic = _base.magic = one.magic = WORD(0);185186/* Aliasing is not supported for this internal helper */187MUST_HAVE((out != base) && (out != exp) && (out != mod), ret, err);188189/* Check initializations */190ret = nn_check_initialized(base); EG(ret, err);191ret = nn_check_initialized(exp); EG(ret, err);192ret = nn_check_initialized(mod); EG(ret, err);193194ret = nn_bitlen(exp, &explen); EG(ret, err);195/* Sanity check */196MUST_HAVE((explen > 0), ret, err);197198/* Check that the modulo is indeed odd */199ret = nn_isodd(mod, &isodd); EG(ret, err);200MUST_HAVE(isodd, ret, err);201202/* Compute the Montgomery coefficients */203ret = nn_compute_redc1_coefs(&r, &r_square, mod, &mpinv); EG(ret, err);204205/* Reduce the base if necessary */206ret = nn_cmp(base, mod, &cmp); EG(ret, err);207if(cmp >= 0){208ret = nn_mod(&_base, base, mod); EG(ret, err);209}210else{211ret = nn_copy(&_base, base); EG(ret, err);212}213214ret = nn_mul_redc1(&_base, &_base, &r_square, mod, mpinv); EG(ret, err);215ret = nn_copy(out, &r); EG(ret, err);216217ret = nn_init(&one, 0); EG(ret, err);218ret = nn_one(&one); EG(ret, err);219220while (explen > 0) {221explen = (bitcnt_t)(explen - 1);222223/* Get the bit */224ret = nn_getbit(exp, explen, &expbit); EG(ret, err);225226/* Square */227ret = nn_mul_redc1(out, out, out, mod, mpinv); EG(ret, err);228229if(expbit){230/* Multiply */231ret = nn_mul_redc1(out, out, &_base, mod, mpinv); EG(ret, err);232}233}234/* Unredcify the output */235ret = nn_mul_redc1(out, out, &one, mod, mpinv);236237err:238nn_uninit(&r);239nn_uninit(&r_square);240nn_uninit(&_base);241nn_uninit(&one);242243return ret;244}245246247#endif /* __COMMON_H__ */248249250