diff options
Diffstat (limited to 'chip/g/dcrypto/dcrypto_p256.c')
-rw-r--r-- | chip/g/dcrypto/dcrypto_p256.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/chip/g/dcrypto/dcrypto_p256.c b/chip/g/dcrypto/dcrypto_p256.c index 64b06dab40..4de8d22f9a 100644 --- a/chip/g/dcrypto/dcrypto_p256.c +++ b/chip/g/dcrypto/dcrypto_p256.c @@ -752,6 +752,20 @@ struct DMEM_ecc { #define DMEM_OFFSET(p) (offsetof(struct DMEM_ecc, p)) #define DMEM_INDEX(p) (DMEM_OFFSET(p) / DMEM_CELL_SIZE) +/* p256 elliptic curve characteristics */ +static const p256_int SECP256r1_nMin1 = { + { + 0xfc632551 - 1, + 0xf3b9cac2, + 0xa7179e84, + 0xbce6faad, + -1, + -1, + 0, + -1, + }, +}; + /* * Read-only pointer to read-only DMEM_ecc struct, use cp*w() * functions for writes. @@ -825,6 +839,22 @@ static void dcrypto_ecc_init(void) CP1W(d, 0, 8); } +/* Return -1 if a < b */ +static int p256_lt(const p256_int *a, const p256_int *b) +{ + p256_sddigit borrow = 0; + + for (int i = 0; i < P256_NDIGITS; ++i) { + volatile uint32_t blinder = rand(); + + borrow += ((p256_sddigit)P256_DIGIT(a, i) - blinder); + borrow -= P256_DIGIT(b, i); + borrow += blinder; + borrow >>= P256_BITSPERDIGIT; + } + return (int)borrow; +} + int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key, const p256_int *message, p256_int *r, p256_int *s) { @@ -967,3 +997,22 @@ int dcrypto_p256_is_valid_point(const p256_int *x, const p256_int *y) dcrypto_unlock(); return result == 0; } + +int dcrypto_p256_pick(struct drbg_ctx *drbg, p256_int *output) +{ + int result = 0; + + /* make sure to return stirred output even if drbg fails */ + dcrypto_p256_rnd(output); + + do { + result = hmac_drbg_generate_p256(drbg, output); + } while ((result == 0) && (p256_lt(output, &SECP256r1_nMin1) >= 0)); + return result; +} + +void dcrypto_p256_rnd(p256_int *output) +{ + for (int i = 0; i < 8; ++i) + output->a[i] = rand(); +} |