authorgravatar for clickingbuttons@pm.meclickingbuttons <clickingbuttons@pm.me> 2024-04-23 16:29:36-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-04-23 20:29:36+00:00
log7cf3167e989374d21280a29e29ed089bee9293fd
tree6a9e7d3ca455f2dae04c2d07df5424e9a3b7afff
parentb87baad0ff783be97f939a57fd9c10be3d34ee81
signaturebadge-check Signed by PGP key B5690EEEBB952194

std.crypto: make ff.ct_unprotected.limbsCmpLt compile (#19741)

* std.crypto: make ff.ct_unprotected.limbsCmpLt compile * std.crypto: add ff.ct test * fix testCt to work on x86 * disable test on stage2-c --------- Co-authored-by: Frank Denis <124872+jedisct1@users.noreply.github.com>

1 files changed, 31 insertions(+), 6 deletions(-)

lib/std/crypto/ff.zig+31-6
...@@ -843,7 +843,7 @@ const ct_protected = struct {...@@ -843,7 +843,7 @@ const ct_protected = struct {
843843
844 // Compares two big integers in constant time, returning true if x >= y.844 // Compares two big integers in constant time, returning true if x >= y.
845 fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool {845 fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool {
846 return !ct.limbsCmpLt(x, y);846 return !limbsCmpLt(x, y);
847 }847 }
848848
849 // Multiplies two limbs and returns the result as a wide limb.849 // Multiplies two limbs and returns the result as a wide limb.
...@@ -878,11 +878,11 @@ const ct_unprotected = struct {...@@ -878,11 +878,11 @@ const ct_unprotected = struct {
878878
879 // Compares two big integers in constant time, returning true if x < y.879 // Compares two big integers in constant time, returning true if x < y.
880 fn limbsCmpLt(x: anytype, y: @TypeOf(x)) bool {880 fn limbsCmpLt(x: anytype, y: @TypeOf(x)) bool {
881 assert(x.limbs_count() == y.limbs_count());881 const x_limbs = x.limbsConst();
882 const x_limbs = x.limbs.constSlice();882 const y_limbs = y.limbsConst();
883 const y_limbs = y.limbs.constSlice();883 assert(x_limbs.len == y_limbs.len);
884884
885 var i = x.limbs_count();885 var i = x_limbs.len;
886 while (i != 0) {886 while (i != 0) {
887 i -= 1;887 i -= 1;
888 if (x_limbs[i] != y_limbs[i]) {888 if (x_limbs[i] != y_limbs[i]) {
...@@ -894,7 +894,7 @@ const ct_unprotected = struct {...@@ -894,7 +894,7 @@ const ct_unprotected = struct {
894894
895 // Compares two big integers in constant time, returning true if x >= y.895 // Compares two big integers in constant time, returning true if x >= y.
896 fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool {896 fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool {
897 return !ct.limbsCmpLt(x, y);897 return !limbsCmpLt(x, y);
898 }898 }
899899
900 // Multiplies two limbs and returns the result as a wide limb.900 // Multiplies two limbs and returns the result as a wide limb.
...@@ -961,3 +961,28 @@ test "finite field arithmetic" {...@@ -961,3 +961,28 @@ test "finite field arithmetic" {
961 try testing.expect(x_sq3.eql(x_sq4));961 try testing.expect(x_sq3.eql(x_sq4));
962 try m.fromMontgomery(&x);962 try m.fromMontgomery(&x);
963}963}
964
965fn testCt(ct_: anytype) !void {
966 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
967
968 const l0: Limb = 0;
969 const l1: Limb = 1;
970 try testing.expectEqual(l1, ct_.select(true, l1, l0));
971 try testing.expectEqual(l0, ct_.select(false, l1, l0));
972 try testing.expectEqual(false, ct_.eql(l1, l0));
973 try testing.expectEqual(true, ct_.eql(l1, l1));
974
975 const M = Modulus(256);
976 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);
977 const x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);
978 const y = try M.Fe.fromPrimitive(u256, m, 24620149608466364616251608466389896540098571);
979 try testing.expectEqual(false, ct_.limbsCmpLt(x.v, y.v));
980 try testing.expectEqual(true, ct_.limbsCmpGeq(x.v, y.v));
981
982 try testing.expectEqual(WideLimb{ .hi = 0, .lo = 0x88 }, ct_.mulWide(1 << 3, (1 << 4) + 1));
983}
984
985test ct {
986 try testCt(ct_protected);
987 try testCt(ct_unprotected);
988}