From 030fa5e7ebc21339728c79f33bf5d5d22e0a760e Mon Sep 17 00:00:00 2001 From: Frank Denis <124872+jedisct1@users.noreply.github.com> Date: Mon, 26 Apr 2021 22:25:48 +0200 Subject: [PATCH] 25519: remove unused const, safeguard against unreduced scalars (#8624) * 25519: remove unused const, safeguard against unreduced scalars No behavior change, but it makes the existing code better match the forthcoming code for other curves. Rename nonAdjacentForm() to slide(), remove an unneeded and confusing constant, and do a reduction in slide() if 257 bits would be required. Note that in all the high-level functions, the top bit is always cleared, so the reduction is never necessary. But since the low-level functions are public, the check is a safe thing to have. * 25519: make identityElement public, deprecate neutralElement Also fix a few comments by the way. --- lib/std/crypto/25519/edwards25519.zig | 25 +++++++++---------------- lib/std/crypto/25519/field.zig | 2 +- lib/std/crypto/25519/scalar.zig | 2 +- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index e8163a3960806879d9e9ccc32b8aae550857a630..4e3d1560075f921f339cbf7fa2fb6b8fe8ae0ad7 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -75,16 +75,8 @@ pub const Edwards25519 = struct { .is_base = true, }; - /// The edwards25519 neutral element. - pub const neutralElement = Edwards25519{ - .x = Fe{ .limbs = .{ 2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247 } }, - .y = Fe{ .limbs = .{ 1507481815385608, 2223447444246085, 1083941587175919, 2059929906842505, 1581435440146976 } }, - .z = Fe{ .limbs = .{ 1507481815385608, 2223447444246085, 1083941587175919, 2059929906842505, 1581435440146976 } }, - .t = Fe{ .limbs = .{ 2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247 } }, - .is_base = false, - }; - - const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; + pub const neutralElement = @compileError("deprecated: use identityElement instead"); + pub const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; /// Reject the neutral element. pub fn rejectIdentity(p: Edwards25519) IdentityElementError!void { @@ -160,9 +152,10 @@ pub const Edwards25519 = struct { return t; } - fn nonAdjacentForm(s: [32]u8) [2 * 32]i8 { + fn slide(s: [32]u8) [2 * 32]i8 { + const reduced = if ((s[s.len - 1] & 0x80) != 0) s else scalar.reduce(s); var e: [2 * 32]i8 = undefined; - for (s) |x, i| { + for (reduced) |x, i| { e[i * 2 + 0] = @as(i8, @truncate(u4, x)); e[i * 2 + 1] = @as(i8, @truncate(u4, x >> 4)); } @@ -185,7 +178,7 @@ pub const Edwards25519 = struct { // avoid these to keep the standard library lightweight. fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 { std.debug.assert(vartime); - const e = nonAdjacentForm(s); + const e = slide(s); var q = Edwards25519.identityElement; var pos: usize = 2 * 32 - 1; while (true) : (pos -= 1) { @@ -280,8 +273,8 @@ pub const Edwards25519 = struct { xpc[4].rejectIdentity() catch return error.WeakPublicKey; break :pc xpc; }; - const e1 = nonAdjacentForm(s1); - const e2 = nonAdjacentForm(s2); + const e1 = slide(s1); + const e2 = slide(s2); var q = Edwards25519.identityElement; var pos: usize = 2 * 32 - 1; while (true) : (pos -= 1) { @@ -318,7 +311,7 @@ pub const Edwards25519 = struct { } var es: [count][2 * 32]i8 = undefined; for (ss) |s, i| { - es[i] = nonAdjacentForm(s); + es[i] = slide(s); } var q = Edwards25519.identityElement; var pos: usize = 2 * 32 - 1; diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig index 5ac184080cacaa312ebc89648a24a981202ec940..aae53e9081ec8fc0088c7c3a2dc014e67b7b770d 100644 --- a/lib/std/crypto/25519/field.zig +++ b/lib/std/crypto/25519/field.zig @@ -355,7 +355,7 @@ pub const Fe = struct { return fe; } - /// Compute the inverse of a field element + /// Return the inverse of a field element, or 0 if a=0. pub fn invert(a: Fe) Fe { var t0 = a.sq(); var t1 = t0.sqn(2).mul(a); diff --git a/lib/std/crypto/25519/scalar.zig b/lib/std/crypto/25519/scalar.zig index 21578486e896e993040da40f910ab6ae008d45da..e8564ff57708d2f390a5623f872cfcff60700d74 100644 --- a/lib/std/crypto/25519/scalar.zig +++ b/lib/std/crypto/25519/scalar.zig @@ -98,7 +98,7 @@ pub fn sub(a: [32]u8, b: [32]u8) [32]u8 { return add(a, neg(b)); } -/// A scalar in unpacked reprentation +/// A scalar in unpacked representation pub const Scalar = struct { const Limbs = [5]u64; limbs: Limbs = undefined, -- 2.54.0