New "i15" implementation of big integers (faster, and constant-time, on ARM Cortex M0/M0+); imported into EC, ECDSA, RSA.

This commit is contained in:
Thomas Pornin 2017-01-04 19:21:09 +01:00
parent 6dd8c51ba7
commit 28e4e120b8
29 changed files with 2993 additions and 326 deletions

View file

@ -532,11 +532,30 @@ MAX(uint32_t x, uint32_t y)
* (old) platforms where the default MUL31 is not. Unfortunately, it is
* also substantially slower, and yields larger code, on more modern
* platforms, which is why it is deactivated by default.
*
* MUL31_lo() must do some extra work because on some platforms, the
* _signed_ multiplication may return early if the top bits are 1.
* Simply truncating (casting) the output of MUL31() would not be
* sufficient, because the compiler may notice that we keep only the low
* word, and then replace automatically the unsigned multiplication with
* a signed multiplication opcode.
*/
#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \
* (uint64_t)((y) | (uint32_t)0x80000000) \
- ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \
- ((uint64_t)1 << 62))
static inline uint32_t
MUL31_lo(uint32_t x, uint32_t y)
{
uint32_t xl, xh;
uint32_t yl, yh;
xl = (x & 0xFFFF) | (uint32_t)0x80000000;
xh = (x >> 16) | (uint32_t)0x80000000;
yl = (y & 0xFFFF) | (uint32_t)0x80000000;
yh = (y >> 16) | (uint32_t)0x80000000;
return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF;
}
#else
@ -544,8 +563,10 @@ MAX(uint32_t x, uint32_t y)
* Multiply two 31-bit integers, with a 62-bit result. This default
* implementation assumes that the basic multiplication operator
* yields constant-time code.
* The MUL31_lo() macro returns only the low 31 bits of the product.
*/
#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y))
#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y))
#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF)
#endif
@ -558,7 +579,7 @@ MAX(uint32_t x, uint32_t y)
*/
#if BR_CT_MUL15
#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \
* ((uint32_t)(x) | (uint32_t)0x80000000) \
* ((uint32_t)(y) | (uint32_t)0x80000000) \
& (uint32_t)0x3FFFFFFF)
#else
#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y))
@ -1046,6 +1067,53 @@ void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/* ==================================================================== */
static inline void
br_i15_zero(uint16_t *x, uint16_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x);
}
uint32_t br_i15_iszero(const uint16_t *x);
uint16_t br_i15_ninv15(uint16_t x);
uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl);
uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl);
void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m);
void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
const uint16_t *m, uint16_t m0i);
void br_i15_to_monty(uint16_t *x, const uint16_t *m);
void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen,
const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2);
void br_i15_encode(void *dst, size_t len, const uint16_t *x);
uint32_t br_i15_decode_mod(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_rshift(uint16_t *x, int count);
uint32_t br_i15_bit_length(uint16_t *x, size_t xlen);
void br_i15_decode(uint16_t *x, const void *src, size_t len);
void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i);
void br_i15_decode_reduce(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m);
void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b);
/* ==================================================================== */
static inline size_t
br_digest_size(const br_hash_class *digest_class)
{
@ -1343,6 +1411,29 @@ unsigned br_aes_ct64_keysched(uint64_t *comp_skey,
void br_aes_ct64_skey_expand(uint64_t *skey,
unsigned num_rounds, const uint64_t *comp_skey);
/* ==================================================================== */
/*
* RSA.
*/
/*
* Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is
* the encoded hash function OID, or NULL.
*/
uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
uint32_t n_bitlen, unsigned char *x);
/*
* Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded
* hash function OID, or NULL. The provided 'sig' value is _after_ the
* modular exponentiation, i.e. it should be the padded hash. On
* success, the hashed message is extracted.
*/
uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
const unsigned char *hash_oid, size_t hash_len,
unsigned char *hash_out);
/* ==================================================================== */
/*
* Elliptic curves.
@ -1364,6 +1455,8 @@ extern const br_ec_curve_def br_secp256r1;
extern const br_ec_curve_def br_secp384r1;
extern const br_ec_curve_def br_secp521r1;
#if 0
/* obsolete */
/*
* Type for the parameters for a "prime curve":
* coordinates are in GF(p), with p prime
@ -1383,6 +1476,7 @@ extern const br_ec_prime_i31_curve br_ec_prime_i31_secp384r1;
extern const br_ec_prime_i31_curve br_ec_prime_i31_secp521r1;
#define BR_EC_I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
#endif
/*
* Decode some bytes as an i31 integer, with truncation (corresponding
@ -1394,6 +1488,16 @@ extern const br_ec_prime_i31_curve br_ec_prime_i31_secp521r1;
void br_ecdsa_i31_bits2int(uint32_t *x,
const void *src, size_t len, uint32_t ebitlen);
/*
* Decode some bytes as an i15 integer, with truncation (corresponding
* to the 'bits2int' operation in RFC 6979). The target ENCODED bit
* length is provided as last parameter. The resulting value will have
* this declared bit length, and consists the big-endian unsigned decoding
* of exactly that many bits in the source (capped at the source length).
*/
void br_ecdsa_i15_bits2int(uint16_t *x,
const void *src, size_t len, uint32_t ebitlen);
/* ==================================================================== */
/*
* SSL/TLS support functions.