diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2015-10-17 06:29:22 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2015-10-17 06:29:22 +0200 |
commit | a0751e06dc93b42c5ce93e22853577b55e933477 (patch) | |
tree | aa41f1751596e9e1fc7df743b71e3089cc054e5e | |
parent | a20ecf69d8f6ae40ef8758c5e87728233d6dc7f5 (diff) | |
download | libuecc-a0751e06dc93b42c5ce93e22853577b55e933477.tar libuecc-a0751e06dc93b42c5ce93e22853577b55e933477.zip |
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.
-rw-r--r-- | src/ec25519.c | 29 |
1 files 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; @@ -165,6 +166,18 @@ static void freeze(uint32_t a[32]) { } /** + * 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) * * The result will be \em squeezed. @@ -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); |