From: Loup Vaillant Date: Sat, 14 Jul 2018 11:55:59 +0000 (+0200) Subject: Separated EdDSA scalarmult internal APIs X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=a41408b63aabca6d5058b684da664f9c75fc4430;p=Monocypher.git Separated EdDSA scalarmult internal APIs - crypto_sign() and crypto_sign() public keys only use ge_scalarmult_base(). - crypto_check() only use ge_double_scalarmult_vartime(). They will be optimised separately. --- diff --git a/src/monocypher.c b/src/monocypher.c index ec65ed1..af40185 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -1383,7 +1383,7 @@ static void ge_tobytes(u8 s[32], const ge *h) } // Variable time! s must not be secret! -static int ge_frombytes_neg(ge *h, const u8 s[32]) +static int ge_frombytes_neg_vartime(ge *h, const u8 s[32]) { static const fe d = { -10913610, 13857413, -15372611, 6949391, 114729, @@ -1515,6 +1515,25 @@ static void ge_scalarmult_base(ge *p, const u8 scalar[32]) ge_scalarmult(p, &base_point, scalar); } +// Variable time! P, sP, and sB must not be secret! +static void ge_double_scalarmult_vartime(ge *sum, const ge *P, + u8 p[32], u8 b[32]) +{ + // base point; + static const fe X = { + 0x325d51a, 0x18b5823, 0x0f6592a, 0x104a92d, 0x1a4b31d, + 0x1d6dc5c, 0x27118fe, 0x07fd814, 0x13cd6e5, 0x085a4db}; + static const fe Y = { + 0x2666658, 0x1999999, 0x0cccccc, 0x1333333, 0x1999999, + 0x0666666, 0x3333333, 0x0cccccc, 0x2666666, 0x1999999}; + ge B; + ge_from_xy(&B, X, Y); + ge pP, bB; + ge_scalarmult(&pP, P, p); + ge_scalarmult(&bB, &B, b); + ge_add(sum, &pP, &bB); +} + static void modL(u8 *r, i64 x[64]) { static const u64 L[32] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, @@ -1678,18 +1697,18 @@ void crypto_check_update(crypto_check_ctx *ctx, const u8 *msg, size_t msg_size) int crypto_check_final(crypto_check_ctx *ctx) { - ge p, sB, diff, A; + ge diff, A; u8 h_ram[64], R_check[32]; - if (ge_frombytes_neg(&A, ctx->pk)) { // -A + u8 *s = ctx->sig + 32; // s + u8 *R = ctx->sig; // R + if (ge_frombytes_neg_vartime(&A, ctx->pk)) { // -A return -1; } HASH_FINAL(&ctx->hash, h_ram); reduce(h_ram); - ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram - ge_scalarmult_base(&sB, ctx->sig + 32); - ge_add(&diff, &p, &sB); // diff = s - A*h_ram - ge_tobytes(R_check, &diff); - return crypto_verify32(ctx->sig, R_check); // R == s - A*h_ram ? OK : fail + ge_double_scalarmult_vartime(&diff, &A, h_ram, s); + ge_tobytes(R_check, &diff); // R_check = s*B - h_ram*A + return crypto_verify32(R, R_check); // R == R_check ? OK : fail // No secret, no wipe }