X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/a81dbb3fde151e754314a80042d721da4d759cbb..3709f7955d5d52033464831d5c07fc31783479d0:/pub/ed25519.c diff --git a/pub/ed25519.c b/pub/ed25519.c index 217cbeb0..c6b805c4 100644 --- a/pub/ed25519.c +++ b/pub/ed25519.c @@ -135,16 +135,34 @@ static void ptencode(octet q[32], static int ptdecode(f25519 *X, f25519 *Y, f25519 *Z, const octet q[32]) { octet b[32]; + unsigned i, a; f25519 t, u; uint32 m; - int rc; + int rc = 0; + /* Load the y-coordinate. */ memcpy(b, q, 32); b[31] &= 0x7fu; f25519_load(Y, b); + + /* Check that the coordinate was in range. If we store it, we'll get a + * canonical version which we can compare against Q; be careful not to + * check the top bit. + */ + f25519_store(b, Y); + for (i = a = 0; i < 31; i++) a |= b[i] ^ q[i]; + a |= (b[31] ^ q[31])&0x7fu; + a = ((a - 1) >> 8)&0x01u; /* 0 |-> 1, non-0 |-> 0 */ + rc |= (int)a - 1; + + /* Decompress the x-coordinate. */ f25519_sqr(&t, Y); f25519_mul(&u, &t, D); t.P[0] -= 1; u.P[0] += 1; - rc = f25519_quosqrt(X, &t, &u); - f25519_store(b, X); m = -(((q[31] >> 7) ^ b[0])&0x1u); + rc |= f25519_quosqrt(X, &t, &u); + f25519_store(b, X); m = -(uint32)(((q[31] >> 7) ^ b[0])&0x1u); f25519_condneg(X, X, m); + + /* Set Z. */ f25519_set(Z, 1); + + /* And we're done. */ return (rc); } @@ -154,7 +172,7 @@ static void ptadd(f25519 *X, f25519 *Y, f25519 *Z, const f25519 *X0, const f25519 *Y0, const f25519 *Z0, const f25519 *X1, const f25519 *Y1, const f25519 *Z1) { - f25519 t0, t1, t2, t3, t4, t5; + f25519 t0, t1, t2, t3; /* Bernstein, Birkner, Joye, Lange, and Peters, `Twisted Edwards Curves', * 2008-03-13, https://cr.yp.to/newelliptic/twisted-20080313.pdf shows the @@ -169,23 +187,23 @@ static void ptadd(f25519 *X, f25519 *Y, f25519 *Z, */ f25519_mul(&t0, Z0, Z1); /* t0 = A = Z0 Z1 */ - f25519_sqr(&t1, &t0); /* t1 = B = A^2 */ + f25519_add(&t1, X0, Y0); /* t1 = X0 + Y0 */ + f25519_add(&t2, X1, Y1); /* t2 = X1 + Y1 */ + f25519_mul(&t1, &t1, &t2); /* t1 = (X0 + Y0) (X1 + Y1) */ f25519_mul(&t2, X0, X1); /* t2 = C = X0 X1 */ f25519_mul(&t3, Y0, Y1); /* t3 = D = Y0 Y1 */ - f25519_mul(&t4, &t2, &t3); /* t4 = C D */ - f25519_mul(&t4, &t4, D); /* t4 = E = d C D */ - f25519_sub(&t5, &t1, &t4); /* t5 = F = B - E */ - f25519_add(&t4, &t1, &t4); /* t4 = G = B + E */ - f25519_add(&t1, &t2, &t3); /* t1 = C + D */ - f25519_add(&t2, X0, Y0); /* t2 = X0 + Y0 */ - f25519_add(&t3, X1, Y1); /* t3 = X1 + Y1 */ - f25519_mul(X, &t0, &t5); /* X = A F */ - f25519_mul(Y, &t0, &t4); /* Y = A G */ - f25519_mul(Z, &t5, &t4); /* Z = F G */ - f25519_mul(Y, Y, &t1); /* Y = A G (C + D) = A G (D - a C) */ - f25519_mul(&t0, &t2, &t3); /* t0 = (X0 + Y0) (X1 + Y1) */ - f25519_sub(&t0, &t0, &t1); /* t0 = (X0 + Y0) (X1 + Y1) - C - D */ - f25519_mul(X, X, &t0); /* X = A F ((X0 + Y0) (X1 + Y1) - C - D) */ + f25519_add(Y, &t2, &t3); /* Y = C + D = D - a C */ + f25519_sub(X, &t1, Y); /* X = (X0 + Y0) (X1 + Y1) - C - D */ + f25519_mul(X, X, &t0); /* X = A ((X0 + Y0) (X1 + Y1) - C - D) */ + f25519_mul(Y, Y, &t0); /* Y = A (D - a C) */ + f25519_sqr(&t0, &t0); /* t0 = B = A^2 */ + f25519_mul(&t1, &t2, &t3); /* t1 = C D */ + f25519_mul(&t1, &t1, D); /* t1 = E = d C D */ + f25519_sub(&t2, &t0, &t1); /* t2 = F = B - E */ + f25519_add(&t1, &t0, &t1); /* t1 = G = B + E */ + f25519_mul(X, X, &t2); /* X = A F ((X0 + Y0) (X1 + Y1) - C - D) */ + f25519_mul(Y, Y, &t1); /* Y = A G (D - a C) */ + f25519_mul(Z, &t1, &t2); /* Z = F G */ } static void ptdbl(f25519 *X, f25519 *Y, f25519 *Z, @@ -371,7 +389,7 @@ static void unpack_key(scaf_piece a[NPIECE], octet h1[32], sha512_init(&h); sha512_hash(&h, k, ksz); sha512_done(&h, b); b[0] &= 0xf8u; b[31] = (b[31]&0x3f) | 0x40; scaf_load(a, b, 32, NPIECE, PIECEWD); - memcpy(h1, b + 32, 32); + if (h1) memcpy(h1, b + 32, 32); } /*----- Main code ---------------------------------------------------------*/ @@ -391,9 +409,8 @@ void ed25519_pubkey(octet K[ED25519_PUBSZ], const void *k, size_t ksz) { scaf_piece a[NPIECE]; f25519 AX, AY, AZ; - octet h1[32]; - unpack_key(a, h1, k, ksz); + unpack_key(a, 0, k, ksz); ptmul(&AX, &AY, &AZ, a, BX, BY, BZ); ptencode(K, &AX, &AY, &AZ); } @@ -480,13 +497,20 @@ int ed25519_verify(const octet K[ED25519_PUBSZ], if (ptdecode(&AX, &AY, &AZ, K)) return (-1); f25519_neg(&AX, &AX); + /* Load the scalar and check that it's in range. The easy way is to store + * it again and see if the two match. + */ + scaf_loaddbl(tt, sig + 32, 32, 2*NPIECE, PIECEWD); + scaf_reduce(s, tt, l, mu, NPIECE, PIECEWD, scratch); + scaf_store(b, 32, s, NPIECE, PIECEWD); + if (memcmp(b, sig + 32, 32) != 0) return (-1); + /* Check the signature. */ sha512_init(&h); sha512_hash(&h, sig, 32); sha512_hash(&h, K, 32); sha512_hash(&h, m, msz); sha512_done(&h, b); - scaf_load(s, sig + 32, 32, NPIECE, PIECEWD); scaf_loaddbl(tt, b, 64, 2*NPIECE, PIECEWD); scaf_reduce(t, tt, l, mu, NPIECE, PIECEWD, scratch); ptsimmul(&RX, &RY, &RZ, s, BX, BY, BZ, t, &AX, &AY, &AZ); @@ -512,11 +536,11 @@ static int vrf_pubkey(dstr dv[]) dstr dpub = DSTR_INIT; int ok = 1; - if (dv[1].len != 32) die(1, "bad pub length"); + if (dv[1].len != ED25519_PUBSZ) die(1, "bad pub length"); - dstr_ensure(&dpub, 32); dpub.len = 32; + dstr_ensure(&dpub, ED25519_PUBSZ); dpub.len = ED25519_PUBSZ; ed25519_pubkey((octet *)dpub.buf, dv[0].buf, dv[0].len); - if (memcmp(dpub.buf, dv[1].buf, 64) != 0) { + if (memcmp(dpub.buf, dv[1].buf, ED25519_PUBSZ) != 0) { ok = 0; fprintf(stderr, "failed!"); fprintf(stderr, "\n\tpriv = "); type_hex.dump(&dv[0], stderr); @@ -535,13 +559,13 @@ static int vrf_sign(dstr dv[]) dstr dsig = DSTR_INIT; int ok = 1; - if (dv[2].len != 64) die(1, "bad result length"); + if (dv[2].len != ED25519_SIGSZ) die(1, "bad result length"); - dstr_ensure(&dsig, 64); dsig.len = 64; + dstr_ensure(&dsig, ED25519_SIGSZ); dsig.len = ED25519_SIGSZ; ed25519_pubkey(K, dv[0].buf, dv[0].len); ed25519_sign((octet *)dsig.buf, dv[0].buf, dv[0].len, K, dv[1].buf, dv[1].len); - if (memcmp(dsig.buf, dv[2].buf, 64) != 0) { + if (memcmp(dsig.buf, dv[2].buf, ED25519_SIGSZ) != 0) { ok = 0; fprintf(stderr, "failed!"); fprintf(stderr, "\n\tpriv = "); type_hex.dump(&dv[0], stderr); @@ -560,8 +584,8 @@ static int vrf_verify(dstr dv[]) int rc_want, rc_calc; int ok = 1; - if (dv[0].len != 32) die(1, "bad pub length"); - if (dv[2].len != 64) die(1, "bad sig length"); + if (dv[0].len != ED25519_PUBSZ) die(1, "bad pub length"); + if (dv[2].len != ED25519_SIGSZ) die(1, "bad sig length"); rc_want = *(int *)dv[3].buf; rc_calc = ed25519_verify((const octet *)dv[0].buf,