authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2024-04-14 01:13:22+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-04-14 01:13:22+02:00
loge45bdc6bd6e47ec3f7a06dbb48f24e842bf43a0d
tree40e21d48696c1ed7c51535500da10b8f94c380ea
parenta59ad719d2b838846ffd5ea77e06322b5427b4e5
signaturebadge-check Signed by PGP key B5690EEEBB952194

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.

7 files changed, 42 insertions(+), 73 deletions(-)

lib/std/crypto/benchmark.zig+6-1
...@@ -131,7 +131,12 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c...@@ -131,7 +131,12 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
131 return throughput;131 return throughput;
132}132}
133133
134const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};134const 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
136pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {141pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
137 const msg = [_]u8{0} ** 64;142 const msg = [_]u8{0} ** 64;
lib/std/crypto/pcurves/p256/p256_64.zig+6-12
...@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;...@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
73/// out1: [0x0 ~> 0xffffffffffffffff]73/// out1: [0x0 ~> 0xffffffffffffffff]
74/// out2: [0x0 ~> 0x1]74/// out2: [0x0 ~> 0x1]
75inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {75inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
76 @setRuntimeSafety(mode == .Debug);76 const x = @as(u128, arg2) +% arg3 +% arg1;
7777 out1.* = @truncate(x);
78 const ov1 = @addWithOverflow(arg2, arg3);78 out2.* = @truncate(x >> 64);
79 const ov2 = @addWithOverflow(ov1[0], arg1);
80 out1.* = ov2[0];
81 out2.* = ov1[1] | ov2[1];
82}79}
8380
84/// The function subborrowxU64 is a subtraction with borrow.81/// 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...@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
95/// out1: [0x0 ~> 0xffffffffffffffff]92/// out1: [0x0 ~> 0xffffffffffffffff]
96/// out2: [0x0 ~> 0x1]93/// out2: [0x0 ~> 0x1]
97inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {94inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
98 @setRuntimeSafety(mode == .Debug);95 const x = @as(u128, arg2) -% arg3 -% arg1;
9996 out1.* = @truncate(x);
100 const ov1 = @subWithOverflow(arg2, arg3);97 out2.* = @truncate(x >> 64);
101 const ov2 = @subWithOverflow(ov1[0], arg1);
102 out1.* = ov2[0];
103 out2.* = ov1[1] | ov2[1];
104}98}
10599
106/// The function mulxU64 is a multiplication, returning the full double-width result.100/// The function mulxU64 is a multiplication, returning the full double-width result.
lib/std/crypto/pcurves/p256/p256_scalar_64.zig+6-12
...@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;...@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
73/// out1: [0x0 ~> 0xffffffffffffffff]73/// out1: [0x0 ~> 0xffffffffffffffff]
74/// out2: [0x0 ~> 0x1]74/// out2: [0x0 ~> 0x1]
75inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {75inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
76 @setRuntimeSafety(mode == .Debug);76 const x = @as(u128, arg2) +% arg3 +% arg1;
7777 out1.* = @truncate(x);
78 const ov1 = @addWithOverflow(arg2, arg3);78 out2.* = @truncate(x >> 64);
79 const ov2 = @addWithOverflow(ov1[0], arg1);
80 out1.* = ov2[0];
81 out2.* = ov1[1] | ov2[1];
82}79}
8380
84/// The function subborrowxU64 is a subtraction with borrow.81/// 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...@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
95/// out1: [0x0 ~> 0xffffffffffffffff]92/// out1: [0x0 ~> 0xffffffffffffffff]
96/// out2: [0x0 ~> 0x1]93/// out2: [0x0 ~> 0x1]
97inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {94inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
98 @setRuntimeSafety(mode == .Debug);95 const x = @as(u128, arg2) -% arg3 -% arg1;
9996 out1.* = @truncate(x);
100 const ov1 = @subWithOverflow(arg2, arg3);97 out2.* = @truncate(x >> 64);
101 const ov2 = @subWithOverflow(ov1[0], arg1);
102 out1.* = ov2[0];
103 out2.* = ov1[1] | ov2[1];
104}98}
10599
106/// The function mulxU64 is a multiplication, returning the full double-width result.100/// The function mulxU64 is a multiplication, returning the full double-width result.
lib/std/crypto/pcurves/p384/p384_64.zig+6-12
...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
42/// out1: [0x0 ~> 0xffffffffffffffff]42/// out1: [0x0 ~> 0xffffffffffffffff]
43/// out2: [0x0 ~> 0x1]43/// out2: [0x0 ~> 0x1]
44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45 @setRuntimeSafety(mode == .Debug);45 const x = @as(u128, arg2) +% arg3 +% arg1;
4646 out1.* = @truncate(x);
47 const ov1 = @addWithOverflow(arg2, arg3);47 out2.* = @truncate(x >> 64);
48 const ov2 = @addWithOverflow(ov1[0], arg1);
49 out1.* = ov2[0];
50 out2.* = ov1[1] | ov2[1];
51}48}
5249
53/// The function subborrowxU64 is a subtraction with borrow.50/// 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...@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
64/// out1: [0x0 ~> 0xffffffffffffffff]61/// out1: [0x0 ~> 0xffffffffffffffff]
65/// out2: [0x0 ~> 0x1]62/// out2: [0x0 ~> 0x1]
66inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {63inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67 @setRuntimeSafety(mode == .Debug);64 const x = @as(u128, arg2) -% arg3 -% arg1;
6865 out1.* = @truncate(x);
69 const ov1 = @subWithOverflow(arg2, arg3);66 out2.* = @truncate(x >> 64);
70 const ov2 = @subWithOverflow(ov1[0], arg1);
71 out1.* = ov2[0];
72 out2.* = ov1[1] | ov2[1];
73}67}
7468
75/// The function mulxU64 is a multiplication, returning the full double-width result.69/// The function mulxU64 is a multiplication, returning the full double-width result.
lib/std/crypto/pcurves/p384/p384_scalar_64.zig+6-12
...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
42/// out1: [0x0 ~> 0xffffffffffffffff]42/// out1: [0x0 ~> 0xffffffffffffffff]
43/// out2: [0x0 ~> 0x1]43/// out2: [0x0 ~> 0x1]
44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45 @setRuntimeSafety(mode == .Debug);45 const x = @as(u128, arg2) +% arg3 +% arg1;
4646 out1.* = @truncate(x);
47 const ov1 = @addWithOverflow(arg2, arg3);47 out2.* = @truncate(x >> 64);
48 const ov2 = @addWithOverflow(ov1[0], arg1);
49 out1.* = ov2[0];
50 out2.* = ov1[1] | ov2[1];
51}48}
5249
53/// The function subborrowxU64 is a subtraction with borrow.50/// 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...@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
64/// out1: [0x0 ~> 0xffffffffffffffff]61/// out1: [0x0 ~> 0xffffffffffffffff]
65/// out2: [0x0 ~> 0x1]62/// out2: [0x0 ~> 0x1]
66inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {63inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67 @setRuntimeSafety(mode == .Debug);64 const x = @as(u128, arg2) -% arg3 -% arg1;
6865 out1.* = @truncate(x);
69 const ov1 = @subWithOverflow(arg2, arg3);66 out2.* = @truncate(x >> 64);
70 const ov2 = @subWithOverflow(ov1[0], arg1);
71 out1.* = ov2[0];
72 out2.* = ov1[1] | ov2[1];
73}67}
7468
75/// The function mulxU64 is a multiplication, returning the full double-width result.69/// The function mulxU64 is a multiplication, returning the full double-width result.
lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig+6-12
...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
42/// out1: [0x0 ~> 0xffffffffffffffff]42/// out1: [0x0 ~> 0xffffffffffffffff]
43/// out2: [0x0 ~> 0x1]43/// out2: [0x0 ~> 0x1]
44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45 @setRuntimeSafety(mode == .Debug);45 const x = @as(u128, arg2) +% arg3 +% arg1;
4646 out1.* = @truncate(x);
47 const ov1 = @addWithOverflow(arg2, arg3);47 out2.* = @truncate(x >> 64);
48 const ov2 = @addWithOverflow(ov1[0], arg1);
49 out1.* = ov2[0];
50 out2.* = ov1[1] | ov2[1];
51}48}
5249
53/// The function subborrowxU64 is a subtraction with borrow.50/// 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...@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
64/// out1: [0x0 ~> 0xffffffffffffffff]61/// out1: [0x0 ~> 0xffffffffffffffff]
65/// out2: [0x0 ~> 0x1]62/// out2: [0x0 ~> 0x1]
66inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {63inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67 @setRuntimeSafety(mode == .Debug);64 const x = @as(u128, arg2) -% arg3 -% arg1;
6865 out1.* = @truncate(x);
69 const ov1 = @subWithOverflow(arg2, arg3);66 out2.* = @truncate(x >> 64);
70 const ov2 = @subWithOverflow(ov1[0], arg1);
71 out1.* = ov2[0];
72 out2.* = ov1[1] | ov2[1];
73}67}
7468
75/// The function mulxU64 is a multiplication, returning the full double-width result.69/// The function mulxU64 is a multiplication, returning the full double-width result.
lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig+6-12
...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;...@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
42/// out1: [0x0 ~> 0xffffffffffffffff]42/// out1: [0x0 ~> 0xffffffffffffffff]
43/// out2: [0x0 ~> 0x1]43/// out2: [0x0 ~> 0x1]
44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {44inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
45 @setRuntimeSafety(mode == .Debug);45 const x = @as(u128, arg2) +% arg3 +% arg1;
4646 out1.* = @truncate(x);
47 const ov1 = @addWithOverflow(arg2, arg3);47 out2.* = @truncate(x >> 64);
48 const ov2 = @addWithOverflow(ov1[0], arg1);
49 out1.* = ov2[0];
50 out2.* = ov1[1] | ov2[1];
51}48}
5249
53/// The function subborrowxU64 is a subtraction with borrow.50/// 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...@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
64/// out1: [0x0 ~> 0xffffffffffffffff]61/// out1: [0x0 ~> 0xffffffffffffffff]
65/// out2: [0x0 ~> 0x1]62/// out2: [0x0 ~> 0x1]
66inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {63inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
67 @setRuntimeSafety(mode == .Debug);64 const x = @as(u128, arg2) -% arg3 -% arg1;
6865 out1.* = @truncate(x);
69 const ov1 = @subWithOverflow(arg2, arg3);66 out2.* = @truncate(x >> 64);
70 const ov2 = @subWithOverflow(ov1[0], arg1);
71 out1.* = ov2[0];
72 out2.* = ov1[1] | ov2[1];
73}67}
7468
75/// The function mulxU64 is a multiplication, returning the full double-width result.69/// The function mulxU64 is a multiplication, returning the full double-width result.