Skip to content

Commit e45bdc6

Browse files
authored
std.crypto.pcurves.*: simpler, smaller, faster u64 addition with carry (#19644)
signature/s: Algorithm Before After ---------------+---------+------- ecdsa-p256 3707 4396 ecdsa-p384 1067 1332 ecdsa-secp256k1 4490 5147 Add ECDSA to the benchmark by the way.
1 parent a59ad71 commit e45bdc6

File tree

7 files changed

+42
-73
lines changed

7 files changed

+42
-73
lines changed

lib/std/crypto/benchmark.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
131131
return throughput;
132132
}
133133

134-
const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};
134+
const signatures = [_]Crypto{
135+
Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" },
136+
Crypto{ .ty = crypto.sign.ecdsa.EcdsaP256Sha256, .name = "ecdsa-p256" },
137+
Crypto{ .ty = crypto.sign.ecdsa.EcdsaP384Sha384, .name = "ecdsa-p384" },
138+
Crypto{ .ty = crypto.sign.ecdsa.EcdsaSecp256k1Sha256, .name = "ecdsa-secp256k1" },
139+
};
135140

136141
pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
137142
const msg = [_]u8{0} ** 64;

lib/std/crypto/pcurves/p256/p256_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
7373
/// out1: [0x0 ~> 0xffffffffffffffff]
7474
/// out2: [0x0 ~> 0x1]
7575
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
76-
@setRuntimeSafety(mode == .Debug);
77-
78-
const ov1 = @addWithOverflow(arg2, arg3);
79-
const ov2 = @addWithOverflow(ov1[0], arg1);
80-
out1.* = ov2[0];
81-
out2.* = ov1[1] | ov2[1];
76+
const x = @as(u128, arg2) +% arg3 +% arg1;
77+
out1.* = @truncate(x);
78+
out2.* = @truncate(x >> 64);
8279
}
8380

8481
/// The function subborrowxU64 is a subtraction with borrow.
@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
9592
/// out1: [0x0 ~> 0xffffffffffffffff]
9693
/// out2: [0x0 ~> 0x1]
9794
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
98-
@setRuntimeSafety(mode == .Debug);
99-
100-
const ov1 = @subWithOverflow(arg2, arg3);
101-
const ov2 = @subWithOverflow(ov1[0], arg1);
102-
out1.* = ov2[0];
103-
out2.* = ov1[1] | ov2[1];
95+
const x = @as(u128, arg2) -% arg3 -% arg1;
96+
out1.* = @truncate(x);
97+
out2.* = @truncate(x >> 64);
10498
}
10599

106100
/// The function mulxU64 is a multiplication, returning the full double-width result.

lib/std/crypto/pcurves/p256/p256_scalar_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
7373
/// out1: [0x0 ~> 0xffffffffffffffff]
7474
/// out2: [0x0 ~> 0x1]
7575
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
76-
@setRuntimeSafety(mode == .Debug);
77-
78-
const ov1 = @addWithOverflow(arg2, arg3);
79-
const ov2 = @addWithOverflow(ov1[0], arg1);
80-
out1.* = ov2[0];
81-
out2.* = ov1[1] | ov2[1];
76+
const x = @as(u128, arg2) +% arg3 +% arg1;
77+
out1.* = @truncate(x);
78+
out2.* = @truncate(x >> 64);
8279
}
8380

8481
/// The function subborrowxU64 is a subtraction with borrow.
@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
9592
/// out1: [0x0 ~> 0xffffffffffffffff]
9693
/// out2: [0x0 ~> 0x1]
9794
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
98-
@setRuntimeSafety(mode == .Debug);
99-
100-
const ov1 = @subWithOverflow(arg2, arg3);
101-
const ov2 = @subWithOverflow(ov1[0], arg1);
102-
out1.* = ov2[0];
103-
out2.* = ov1[1] | ov2[1];
95+
const x = @as(u128, arg2) -% arg3 -% arg1;
96+
out1.* = @truncate(x);
97+
out2.* = @truncate(x >> 64);
10498
}
10599

106100
/// The function mulxU64 is a multiplication, returning the full double-width result.

lib/std/crypto/pcurves/p384/p384_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
4242
/// out1: [0x0 ~> 0xffffffffffffffff]
4343
/// out2: [0x0 ~> 0x1]
4444
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45-
@setRuntimeSafety(mode == .Debug);
46-
47-
const ov1 = @addWithOverflow(arg2, arg3);
48-
const ov2 = @addWithOverflow(ov1[0], arg1);
49-
out1.* = ov2[0];
50-
out2.* = ov1[1] | ov2[1];
45+
const x = @as(u128, arg2) +% arg3 +% arg1;
46+
out1.* = @truncate(x);
47+
out2.* = @truncate(x >> 64);
5148
}
5249

5350
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
6461
/// out1: [0x0 ~> 0xffffffffffffffff]
6562
/// out2: [0x0 ~> 0x1]
6663
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67-
@setRuntimeSafety(mode == .Debug);
68-
69-
const ov1 = @subWithOverflow(arg2, arg3);
70-
const ov2 = @subWithOverflow(ov1[0], arg1);
71-
out1.* = ov2[0];
72-
out2.* = ov1[1] | ov2[1];
64+
const x = @as(u128, arg2) -% arg3 -% arg1;
65+
out1.* = @truncate(x);
66+
out2.* = @truncate(x >> 64);
7367
}
7468

7569
/// The function mulxU64 is a multiplication, returning the full double-width result.

lib/std/crypto/pcurves/p384/p384_scalar_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
4242
/// out1: [0x0 ~> 0xffffffffffffffff]
4343
/// out2: [0x0 ~> 0x1]
4444
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45-
@setRuntimeSafety(mode == .Debug);
46-
47-
const ov1 = @addWithOverflow(arg2, arg3);
48-
const ov2 = @addWithOverflow(ov1[0], arg1);
49-
out1.* = ov2[0];
50-
out2.* = ov1[1] | ov2[1];
45+
const x = @as(u128, arg2) +% arg3 +% arg1;
46+
out1.* = @truncate(x);
47+
out2.* = @truncate(x >> 64);
5148
}
5249

5350
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
6461
/// out1: [0x0 ~> 0xffffffffffffffff]
6562
/// out2: [0x0 ~> 0x1]
6663
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67-
@setRuntimeSafety(mode == .Debug);
68-
69-
const ov1 = @subWithOverflow(arg2, arg3);
70-
const ov2 = @subWithOverflow(ov1[0], arg1);
71-
out1.* = ov2[0];
72-
out2.* = ov1[1] | ov2[1];
64+
const x = @as(u128, arg2) -% arg3 -% arg1;
65+
out1.* = @truncate(x);
66+
out2.* = @truncate(x >> 64);
7367
}
7468

7569
/// The function mulxU64 is a multiplication, returning the full double-width result.

lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
4242
/// out1: [0x0 ~> 0xffffffffffffffff]
4343
/// out2: [0x0 ~> 0x1]
4444
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45-
@setRuntimeSafety(mode == .Debug);
46-
47-
const ov1 = @addWithOverflow(arg2, arg3);
48-
const ov2 = @addWithOverflow(ov1[0], arg1);
49-
out1.* = ov2[0];
50-
out2.* = ov1[1] | ov2[1];
45+
const x = @as(u128, arg2) +% arg3 +% arg1;
46+
out1.* = @truncate(x);
47+
out2.* = @truncate(x >> 64);
5148
}
5249

5350
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
6461
/// out1: [0x0 ~> 0xffffffffffffffff]
6562
/// out2: [0x0 ~> 0x1]
6663
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67-
@setRuntimeSafety(mode == .Debug);
68-
69-
const ov1 = @subWithOverflow(arg2, arg3);
70-
const ov2 = @subWithOverflow(ov1[0], arg1);
71-
out1.* = ov2[0];
72-
out2.* = ov1[1] | ov2[1];
64+
const x = @as(u128, arg2) -% arg3 -% arg1;
65+
out1.* = @truncate(x);
66+
out2.* = @truncate(x >> 64);
7367
}
7468

7569
/// The function mulxU64 is a multiplication, returning the full double-width result.

lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
4242
/// out1: [0x0 ~> 0xffffffffffffffff]
4343
/// out2: [0x0 ~> 0x1]
4444
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45-
@setRuntimeSafety(mode == .Debug);
46-
47-
const ov1 = @addWithOverflow(arg2, arg3);
48-
const ov2 = @addWithOverflow(ov1[0], arg1);
49-
out1.* = ov2[0];
50-
out2.* = ov1[1] | ov2[1];
45+
const x = @as(u128, arg2) +% arg3 +% arg1;
46+
out1.* = @truncate(x);
47+
out2.* = @truncate(x >> 64);
5148
}
5249

5350
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
6461
/// out1: [0x0 ~> 0xffffffffffffffff]
6562
/// out2: [0x0 ~> 0x1]
6663
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67-
@setRuntimeSafety(mode == .Debug);
68-
69-
const ov1 = @subWithOverflow(arg2, arg3);
70-
const ov2 = @subWithOverflow(ov1[0], arg1);
71-
out1.* = ov2[0];
72-
out2.* = ov1[1] | ov2[1];
64+
const x = @as(u128, arg2) -% arg3 -% arg1;
65+
out1.* = @truncate(x);
66+
out2.* = @truncate(x >> 64);
7367
}
7468

7569
/// The function mulxU64 is a multiplication, returning the full double-width result.

0 commit comments

Comments
 (0)