From a0751e06dc93b42c5ce93e22853577b55e933477 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 17 Oct 2015 06:29:22 +0200 Subject: Fix loading of packed points in edge case The parity bit was not handled correctly when the squeezed value of Y is not fully reduced. --- src/ec25519.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/ec25519.c b/src/ec25519.c index d9a8528..f2bc288 100644 --- a/src/ec25519.c +++ b/src/ec25519.c @@ -138,19 +138,20 @@ static void squeeze(uint32_t a[32]) { a[31] = u; } + +static const uint32_t minusp[32] = { + 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128 +}; + /** * Ensures that the output of a previous \ref squeeze is fully reduced * * After a \ref freeze, only the lower byte of each integer part holds a meaningful value. */ static void freeze(uint32_t a[32]) { - static const uint32_t minusp[32] = { - 19, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 128 - }; - uint32_t aorig[32]; unsigned int j; uint32_t negative; @@ -164,6 +165,18 @@ static void freeze(uint32_t a[32]) { a[j] ^= negative & (aorig[j] ^ a[j]); } +/** + * Returns the parity (lowest bit of the fully reduced value) of a + * + * The input must be \em squeezed. + */ +static int parity(uint32_t a[32]) { + uint32_t b[32]; + + add(b, a, minusp); + return (a[0] ^ (b[31] >> 7) ^ 1) & 1; +} + /** * Multiplies two unpacked integers (modulo p) * @@ -554,7 +567,7 @@ int ecc_25519_load_packed(ecc_25519_work_t *out, const ecc_int256_t *in) { /* No squeeze is necessary after subtractions from zero if the subtrahend is squeezed */ sub(Yt, zero, Y); - select(out->Y, Y, Yt, (in->p[31] >> 7) ^ (Y[0] & 1)); + select(out->Y, Y, Yt, (in->p[31] >> 7) ^ parity(Y)); mult(out->T, out->X, out->Y); -- cgit v1.2.3