summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-10-17 06:29:22 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-10-17 06:29:22 +0200
commita0751e06dc93b42c5ce93e22853577b55e933477 (patch)
treeaa41f1751596e9e1fc7df743b71e3089cc054e5e
parenta20ecf69d8f6ae40ef8758c5e87728233d6dc7f5 (diff)
downloadlibuecc-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.c29
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);