From 932ea29845da1ae350d9c056cb2cb0379a66d642 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 30 Mar 2021 09:22:47 +0200 Subject: [PATCH] Port upstream hardening of EC scaler multiplication Some internal functions used in point multiplications are known to misbehave if the scaler is out-of-range. This performs canonical reduction on scalers, before point multiplication. Signed-off-by: Daiki Ueno --- ecc-ecdsa-sign.c | 7 +++++-- ecc-ecdsa-verify.c | 14 ++++++++++++-- eddsa-hash.c | 9 +++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/ecc-ecdsa-sign.c b/ecc-ecdsa-sign.c index 3b9e9cc1..45062528 100644 --- a/ecc-ecdsa-sign.c +++ b/ecc-ecdsa-sign.c @@ -62,6 +62,8 @@ ecc_ecdsa_sign (const struct ecc_curve *ecc, mp_limb_t *rp, mp_limb_t *sp, mp_limb_t *scratch) { + mp_limb_t cy; + #define P scratch #define kinv scratch /* Needs 5*ecc->p.size for computation */ #define hp (scratch + ecc->p.size) /* NOTE: ecc->p.size + 1 limbs! */ @@ -91,8 +93,9 @@ ecc_ecdsa_sign (const struct ecc_curve *ecc, ecc_modq_mul (ecc, tp, zp, rp); ecc_modq_add (ecc, hp, hp, tp); ecc_modq_mul (ecc, tp, hp, kinv); - - mpn_copyi (sp, tp, ecc->p.size); + /* Ensure canonical reduction. */ + cy = mpn_sub_n (sp, tp, ecc->q.m, ecc->q.size); + cnd_copy (cy, sp, tp, ecc->q.size); #undef P #undef hp #undef kinv diff --git a/ecc-ecdsa-verify.c b/ecc-ecdsa-verify.c index d7f5b684..6b8acb07 100644 --- a/ecc-ecdsa-verify.c +++ b/ecc-ecdsa-verify.c @@ -75,6 +75,8 @@ ecc_ecdsa_verify (const struct ecc_curve *ecc, const mp_limb_t *rp, const mp_limb_t *sp, mp_limb_t *scratch) { + mp_limb_t cy; + /* Procedure, according to RFC 6090, "KT-I". q denotes the group order. @@ -98,6 +100,7 @@ ecc_ecdsa_verify (const struct ecc_curve *ecc, #define P1 (scratch + 4*ecc->p.size) #define sinv (scratch) #define hp (scratch + ecc->p.size) +#define tp (scratch + 4*ecc->p.size) if (! (ecdsa_in_range (ecc, rp) && ecdsa_in_range (ecc, sp))) @@ -112,10 +115,16 @@ ecc_ecdsa_verify (const struct ecc_curve *ecc, /* u1 = h / s, P1 = u1 * G */ ecc_hash (&ecc->q, hp, length, digest); - ecc_modq_mul (ecc, u1, hp, sinv); + ecc_modq_mul (ecc, tp, hp, sinv); + /* Ensure canonical reduction. */ + cy = mpn_sub_n (u1, tp, ecc->q.m, ecc->q.size); + cnd_copy (cy, u1, tp, ecc->q.size); /* u2 = r / s, P2 = u2 * Y */ - ecc_modq_mul (ecc, u2, rp, sinv); + ecc_modq_mul (ecc, hp, rp, sinv); + /* Ensure canonical reduction. */ + cy = mpn_sub_n (u2, hp, ecc->q.m, ecc->q.size); + cnd_copy (cy, u2, hp, ecc->q.size); /* Total storage: 5*ecc->p.size + ecc->mul_itch */ ecc->mul (ecc, P2, u2, pp, u2 + ecc->p.size); @@ -154,4 +163,5 @@ ecc_ecdsa_verify (const struct ecc_curve *ecc, #undef u2 #undef hp #undef u1 +#undef tp } diff --git a/eddsa-hash.c b/eddsa-hash.c index 4fb79f1b..53c6fc49 100644 --- a/eddsa-hash.c +++ b/eddsa-hash.c @@ -45,7 +45,12 @@ void _eddsa_hash (const struct ecc_modulo *m, mp_limb_t *rp, const uint8_t *digest) { + mp_limb_t cy; + size_t nbytes = 1 + m->bit_size / 8; - mpn_set_base256_le (rp, 2*m->size, digest, 2*nbytes); - m->mod (m, rp); + mpn_set_base256_le (rp + m->size, 2*m->size, digest, 2*nbytes); + m->mod (m, rp + m->size); + /* Ensure canonical reduction. */ + cy = mpn_sub_n (rp, rp + m->size, m->m, m->size); + cnd_copy (cy, rp, rp + m->size, m->size); } -- 2.30.2