| ... | @@ -6,115 +6,16 @@ | ... | @@ -6,115 +6,16 @@ |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | | 8 | |
| 9 | const field_size = [32]u8{ | 9 | /// 2^252 + 27742317777372353535851937790883648493 |
| | 10 | pub const field_size = [32]u8{ |
| 10 | 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // 2^252+27742317777372353535851937790883648493 | 11 | 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // 2^252+27742317777372353535851937790883648493 |
| 11 | }; | 12 | }; |
| 12 | | 13 | |
| 13 | const ScalarExpanded = struct { | 14 | /// A compressed scalar |
| 14 | limbs: [64]i64 = [_]i64{0} ** 64, | 15 | pub const CompressedScalar = [32]u8; |
| 15 | | 16 | |
| 16 | fn fromBytes(s: [32]u8) ScalarExpanded { | 17 | /// Zero |
| 17 | var limbs: [64]i64 = undefined; | 18 | pub const zero = [_]u8{0} ** 32; |
| 18 | for (s) |x, idx| { | | |
| 19 | limbs[idx] = @as(i64, x); | | |
| 20 | } | | |
| 21 | mem.set(i64, limbs[32..], 0); | | |
| 22 | return .{ .limbs = limbs }; | | |
| 23 | } | | |
| 24 | | | |
| 25 | fn fromBytes64(s: [64]u8) ScalarExpanded { | | |
| 26 | var limbs: [64]i64 = undefined; | | |
| 27 | for (s) |x, idx| { | | |
| 28 | limbs[idx] = @as(i64, x); | | |
| 29 | } | | |
| 30 | return .{ .limbs = limbs }; | | |
| 31 | } | | |
| 32 | | | |
| 33 | fn reduce(e: *ScalarExpanded) void { | | |
| 34 | const limbs = &e.limbs; | | |
| 35 | var carry: i64 = undefined; | | |
| 36 | var i: usize = 63; | | |
| 37 | while (i >= 32) : (i -= 1) { | | |
| 38 | carry = 0; | | |
| 39 | const k = i - 12; | | |
| 40 | const xi = limbs[i]; | | |
| 41 | var j = i - 32; | | |
| 42 | while (j < k) : (j += 1) { | | |
| 43 | const xj = limbs[j] + carry - 16 * xi * @as(i64, field_size[j - (i - 32)]); | | |
| 44 | carry = (xj + 128) >> 8; | | |
| 45 | limbs[j] = xj - carry * 256; | | |
| 46 | } | | |
| 47 | limbs[k] += carry; | | |
| 48 | limbs[i] = 0; | | |
| 49 | } | | |
| 50 | carry = 0; | | |
| 51 | comptime var j: usize = 0; | | |
| 52 | inline while (j < 32) : (j += 1) { | | |
| 53 | const xi = limbs[j] + carry - (limbs[31] >> 4) * @as(i64, field_size[j]); | | |
| 54 | carry = xi >> 8; | | |
| 55 | limbs[j] = xi & 255; | | |
| 56 | } | | |
| 57 | j = 0; | | |
| 58 | inline while (j < 32) : (j += 1) { | | |
| 59 | limbs[j] -= carry * @as(i64, field_size[j]); | | |
| 60 | } | | |
| 61 | j = 0; | | |
| 62 | inline while (j < 32) : (j += 1) { | | |
| 63 | limbs[j + 1] += limbs[j] >> 8; | | |
| 64 | } | | |
| 65 | } | | |
| 66 | | | |
| 67 | fn toBytes(e: *ScalarExpanded) [32]u8 { | | |
| 68 | e.reduce(); | | |
| 69 | var r: [32]u8 = undefined; | | |
| 70 | var i: usize = 0; | | |
| 71 | while (i < 32) : (i += 1) { | | |
| 72 | r[i] = @intCast(u8, e.limbs[i]); | | |
| 73 | } | | |
| 74 | return r; | | |
| 75 | } | | |
| 76 | | | |
| 77 | fn add(a: ScalarExpanded, b: ScalarExpanded) ScalarExpanded { | | |
| 78 | var r = ScalarExpanded{}; | | |
| 79 | comptime var i = 0; | | |
| 80 | inline while (i < 64) : (i += 1) { | | |
| 81 | r.limbs[i] = a.limbs[i] + b.limbs[i]; | | |
| 82 | } | | |
| 83 | return r; | | |
| 84 | } | | |
| 85 | | | |
| 86 | fn mul(a: ScalarExpanded, b: ScalarExpanded) ScalarExpanded { | | |
| 87 | var r = ScalarExpanded{}; | | |
| 88 | var i: usize = 0; | | |
| 89 | while (i < 32) : (i += 1) { | | |
| 90 | const ai = a.limbs[i]; | | |
| 91 | comptime var j = 0; | | |
| 92 | inline while (j < 32) : (j += 1) { | | |
| 93 | r.limbs[i + j] += ai * b.limbs[j]; | | |
| 94 | } | | |
| 95 | } | | |
| 96 | r.reduce(); | | |
| 97 | return r; | | |
| 98 | } | | |
| 99 | | | |
| 100 | fn sq(a: ScalarExpanded) ScalarExpanded { | | |
| 101 | return a.mul(a); | | |
| 102 | } | | |
| 103 | | | |
| 104 | fn mulAdd(a: ScalarExpanded, b: ScalarExpanded, c: ScalarExpanded) ScalarExpanded { | | |
| 105 | var r: ScalarExpanded = .{ .limbs = c.limbs }; | | |
| 106 | var i: usize = 0; | | |
| 107 | while (i < 32) : (i += 1) { | | |
| 108 | const ai = a.limbs[i]; | | |
| 109 | comptime var j = 0; | | |
| 110 | inline while (j < 32) : (j += 1) { | | |
| 111 | r.limbs[i + j] += ai * b.limbs[j]; | | |
| 112 | } | | |
| 113 | } | | |
| 114 | r.reduce(); | | |
| 115 | return r; | | |
| 116 | } | | |
| 117 | }; | | |
| 118 | | 19 | |
| 119 | /// Reject a scalar whose encoding is not canonical. | 20 | /// Reject a scalar whose encoding is not canonical. |
| 120 | pub fn rejectNonCanonical(s: [32]u8) !void { | 21 | pub fn rejectNonCanonical(s: [32]u8) !void { |
| ... | @@ -135,12 +36,12 @@ pub fn rejectNonCanonical(s: [32]u8) !void { | ... | @@ -135,12 +36,12 @@ pub fn rejectNonCanonical(s: [32]u8) !void { |
| 135 | | 36 | |
| 136 | /// Reduce a scalar to the field size. | 37 | /// Reduce a scalar to the field size. |
| 137 | pub fn reduce(s: [32]u8) [32]u8 { | 38 | pub fn reduce(s: [32]u8) [32]u8 { |
| 138 | return ScalarExpanded.fromBytes(s).toBytes(); | 39 | return Scalar.fromBytes(s).toBytes(); |
| 139 | } | 40 | } |
| 140 | | 41 | |
| 141 | /// Reduce a 64-bytes scalar to the field size. | 42 | /// Reduce a 64-bytes scalar to the field size. |
| 142 | pub fn reduce64(s: [64]u8) [32]u8 { | 43 | pub fn reduce64(s: [64]u8) [32]u8 { |
| 143 | return ScalarExpanded.fromBytes64(s).toBytes(); | 44 | return ScalarDouble.fromBytes64(s).toBytes(); |
| 144 | } | 45 | } |
| 145 | | 46 | |
| 146 | /// Perform the X25519 "clamping" operation. | 47 | /// Perform the X25519 "clamping" operation. |
| ... | @@ -150,14 +51,723 @@ pub inline fn clamp(s: *[32]u8) void { | ... | @@ -150,14 +51,723 @@ pub inline fn clamp(s: *[32]u8) void { |
| 150 | s[31] = (s[31] & 127) | 64; | 51 | s[31] = (s[31] & 127) | 64; |
| 151 | } | 52 | } |
| 152 | | 53 | |
| | 54 | /// Return a*b (mod L) |
| | 55 | pub fn mul(a: [32]u8, b: [32]u8) [32]u8 { |
| | 56 | return Scalar.fromBytes(a).mul(Scalar.fromBytes(b)).toBytes(); |
| | 57 | } |
| | 58 | |
| 153 | /// Return a*b+c (mod L) | 59 | /// Return a*b+c (mod L) |
| 154 | pub fn mulAdd(a: [32]u8, b: [32]u8, c: [32]u8) [32]u8 { | 60 | pub fn mulAdd(a: [32]u8, b: [32]u8, c: [32]u8) [32]u8 { |
| 155 | return ScalarExpanded.fromBytes(a).mulAdd(ScalarExpanded.fromBytes(b), ScalarExpanded.fromBytes(c)).toBytes(); | 61 | return Scalar.fromBytes(a).mul(Scalar.fromBytes(b)).add(Scalar.fromBytes(c)).toBytes(); |
| | 62 | } |
| | 63 | |
| | 64 | /// Return a*8 (mod L) |
| | 65 | pub fn mul8(s: [32]u8) [32]u8 { |
| | 66 | var x = Scalar.fromBytes(s); |
| | 67 | x = x.add(x); |
| | 68 | x = x.add(x); |
| | 69 | x = x.add(x); |
| | 70 | return x.toBytes(); |
| | 71 | } |
| | 72 | |
| | 73 | /// Return a+b (mod L) |
| | 74 | pub fn add(a: [32]u8, b: [32]u8) [32]u8 { |
| | 75 | return Scalar.fromBytes(a).add(Scalar.fromBytes(b)).toBytes(); |
| | 76 | } |
| | 77 | |
| | 78 | /// Return -s (mod L) |
| | 79 | pub fn neg(s: [32]u8) [32]u8 { |
| | 80 | const fs: [64]u8 = field_size ++ [_]u8{0} ** 32; |
| | 81 | var sx: [64]u8 = undefined; |
| | 82 | mem.copy(u8, sx[0..32], s[0..]); |
| | 83 | mem.set(u8, sx[32..], 0); |
| | 84 | var carry: u32 = 0; |
| | 85 | var i: usize = 0; |
| | 86 | while (i < 64) : (i += 1) { |
| | 87 | carry = @as(u32, fs[i]) -% sx[i] -% @as(u32, carry); |
| | 88 | sx[i] = @truncate(u8, carry); |
| | 89 | carry = (carry >> 8) & 1; |
| | 90 | } |
| | 91 | return reduce64(sx); |
| | 92 | } |
| | 93 | |
| | 94 | /// Return (a-b) (mod L) |
| | 95 | pub fn sub(a: [32]u8, b: [32]u8) [32]u8 { |
| | 96 | return add(a, neg(b)); |
| 156 | } | 97 | } |
| 157 | | 98 | |
| | 99 | /// A scalar in unpacked reprentation |
| | 100 | pub const Scalar = struct { |
| | 101 | const Limbs = [5]u64; |
| | 102 | limbs: Limbs = undefined, |
| | 103 | |
| | 104 | /// Unpack a 32-byte representation of a scalar |
| | 105 | pub fn fromBytes(bytes: [32]u8) Scalar { |
| | 106 | return ScalarDouble.fromBytes32(bytes).reduce(5); |
| | 107 | } |
| | 108 | |
| | 109 | /// Pack a scalar into bytes |
| | 110 | pub fn toBytes(expanded: *const Scalar) [32]u8 { |
| | 111 | var bytes: [32]u8 = undefined; |
| | 112 | var i: usize = 0; |
| | 113 | while (i < 4) : (i += 1) { |
| | 114 | mem.writeIntLittle(u64, bytes[i * 7 ..][0..8], expanded.limbs[i]); |
| | 115 | } |
| | 116 | mem.writeIntLittle(u32, bytes[i * 7 ..][0..4], @intCast(u32, expanded.limbs[i])); |
| | 117 | return bytes; |
| | 118 | } |
| | 119 | |
| | 120 | /// Return x+y (mod l) |
| | 121 | pub fn add(x: Scalar, y: Scalar) Scalar { |
| | 122 | const carry0 = (x.limbs[0] + y.limbs[0]) >> 56; |
| | 123 | const t0 = (x.limbs[0] + y.limbs[0]) & 0xffffffffffffff; |
| | 124 | const t00 = t0; |
| | 125 | const c0 = carry0; |
| | 126 | const carry1 = (x.limbs[1] + y.limbs[1] + c0) >> 56; |
| | 127 | const t1 = (x.limbs[1] + y.limbs[1] + c0) & 0xffffffffffffff; |
| | 128 | const t10 = t1; |
| | 129 | const c1 = carry1; |
| | 130 | const carry2 = (x.limbs[2] + y.limbs[2] + c1) >> 56; |
| | 131 | const t2 = (x.limbs[2] + y.limbs[2] + c1) & 0xffffffffffffff; |
| | 132 | const t20 = t2; |
| | 133 | const c2 = carry2; |
| | 134 | const carry = (x.limbs[3] + y.limbs[3] + c2) >> 56; |
| | 135 | const t3 = (x.limbs[3] + y.limbs[3] + c2) & 0xffffffffffffff; |
| | 136 | const t30 = t3; |
| | 137 | const c3 = carry; |
| | 138 | const t4 = x.limbs[4] + y.limbs[4] + c3; |
| | 139 | |
| | 140 | const y01: u64 = 5175514460705773; |
| | 141 | const y11: u64 = 70332060721272408; |
| | 142 | const y21: u64 = 5342; |
| | 143 | const y31: u64 = 0; |
| | 144 | const y41: u64 = 268435456; |
| | 145 | |
| | 146 | const b5 = (t00 -% y01) >> 63; |
| | 147 | const t5 = ((b5 << 56) + t00) -% y01; |
| | 148 | const b0 = b5; |
| | 149 | const t01 = t5; |
| | 150 | const b6 = (t10 -% (y11 + b0)) >> 63; |
| | 151 | const t6 = ((b6 << 56) + t10) -% (y11 + b0); |
| | 152 | const b1 = b6; |
| | 153 | const t11 = t6; |
| | 154 | const b7 = (t20 -% (y21 + b1)) >> 63; |
| | 155 | const t7 = ((b7 << 56) + t20) -% (y21 + b1); |
| | 156 | const b2 = b7; |
| | 157 | const t21 = t7; |
| | 158 | const b8 = (t30 -% (y31 + b2)) >> 63; |
| | 159 | const t8 = ((b8 << 56) + t30) -% (y31 + b2); |
| | 160 | const b3 = b8; |
| | 161 | const t31 = t8; |
| | 162 | const b = (t4 -% (y41 + b3)) >> 63; |
| | 163 | const t = ((b << 56) + t4) -% (y41 + b3); |
| | 164 | const b4 = b; |
| | 165 | const t41 = t; |
| | 166 | |
| | 167 | const mask = (b4 -% 1); |
| | 168 | const z00 = t00 ^ (mask & (t00 ^ t01)); |
| | 169 | const z10 = t10 ^ (mask & (t10 ^ t11)); |
| | 170 | const z20 = t20 ^ (mask & (t20 ^ t21)); |
| | 171 | const z30 = t30 ^ (mask & (t30 ^ t31)); |
| | 172 | const z40 = t4 ^ (mask & (t4 ^ t41)); |
| | 173 | |
| | 174 | return Scalar{ .limbs = .{ z00, z10, z20, z30, z40 } }; |
| | 175 | } |
| | 176 | |
| | 177 | /// Return x*r (mod l) |
| | 178 | pub fn mul(x: Scalar, y: Scalar) Scalar { |
| | 179 | const xy000 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[0]); |
| | 180 | const xy010 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[1]); |
| | 181 | const xy020 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[2]); |
| | 182 | const xy030 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[3]); |
| | 183 | const xy040 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[4]); |
| | 184 | const xy100 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[0]); |
| | 185 | const xy110 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[1]); |
| | 186 | const xy120 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[2]); |
| | 187 | const xy130 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[3]); |
| | 188 | const xy140 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[4]); |
| | 189 | const xy200 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[0]); |
| | 190 | const xy210 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[1]); |
| | 191 | const xy220 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[2]); |
| | 192 | const xy230 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[3]); |
| | 193 | const xy240 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[4]); |
| | 194 | const xy300 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[0]); |
| | 195 | const xy310 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[1]); |
| | 196 | const xy320 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[2]); |
| | 197 | const xy330 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[3]); |
| | 198 | const xy340 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[4]); |
| | 199 | const xy400 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[0]); |
| | 200 | const xy410 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[1]); |
| | 201 | const xy420 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[2]); |
| | 202 | const xy430 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[3]); |
| | 203 | const xy440 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[4]); |
| | 204 | const z00 = xy000; |
| | 205 | const z10 = xy010 + xy100; |
| | 206 | const z20 = xy020 + xy110 + xy200; |
| | 207 | const z30 = xy030 + xy120 + xy210 + xy300; |
| | 208 | const z40 = xy040 + xy130 + xy220 + xy310 + xy400; |
| | 209 | const z50 = xy140 + xy230 + xy320 + xy410; |
| | 210 | const z60 = xy240 + xy330 + xy420; |
| | 211 | const z70 = xy340 + xy430; |
| | 212 | const z80 = xy440; |
| | 213 | |
| | 214 | const carry0 = z00 >> 56; |
| | 215 | const t10 = @truncate(u64, z00) & 0xffffffffffffff; |
| | 216 | const c00 = carry0; |
| | 217 | const t00 = t10; |
| | 218 | const carry1 = (z10 + c00) >> 56; |
| | 219 | const t11 = @truncate(u64, (z10 + c00)) & 0xffffffffffffff; |
| | 220 | const c10 = carry1; |
| | 221 | const t12 = t11; |
| | 222 | const carry2 = (z20 + c10) >> 56; |
| | 223 | const t13 = @truncate(u64, (z20 + c10)) & 0xffffffffffffff; |
| | 224 | const c20 = carry2; |
| | 225 | const t20 = t13; |
| | 226 | const carry3 = (z30 + c20) >> 56; |
| | 227 | const t14 = @truncate(u64, (z30 + c20)) & 0xffffffffffffff; |
| | 228 | const c30 = carry3; |
| | 229 | const t30 = t14; |
| | 230 | const carry4 = (z40 + c30) >> 56; |
| | 231 | const t15 = @truncate(u64, (z40 + c30)) & 0xffffffffffffff; |
| | 232 | const c40 = carry4; |
| | 233 | const t40 = t15; |
| | 234 | const carry5 = (z50 + c40) >> 56; |
| | 235 | const t16 = @truncate(u64, (z50 + c40)) & 0xffffffffffffff; |
| | 236 | const c50 = carry5; |
| | 237 | const t50 = t16; |
| | 238 | const carry6 = (z60 + c50) >> 56; |
| | 239 | const t17 = @truncate(u64, (z60 + c50)) & 0xffffffffffffff; |
| | 240 | const c60 = carry6; |
| | 241 | const t60 = t17; |
| | 242 | const carry7 = (z70 + c60) >> 56; |
| | 243 | const t18 = @truncate(u64, (z70 + c60)) & 0xffffffffffffff; |
| | 244 | const c70 = carry7; |
| | 245 | const t70 = t18; |
| | 246 | const carry8 = (z80 + c70) >> 56; |
| | 247 | const t19 = @truncate(u64, (z80 + c70)) & 0xffffffffffffff; |
| | 248 | const c80 = carry8; |
| | 249 | const t80 = t19; |
| | 250 | const t90 = (@truncate(u64, c80)); |
| | 251 | const r0 = t00; |
| | 252 | const r1 = t12; |
| | 253 | const r2 = t20; |
| | 254 | const r3 = t30; |
| | 255 | const r4 = t40; |
| | 256 | const r5 = t50; |
| | 257 | const r6 = t60; |
| | 258 | const r7 = t70; |
| | 259 | const r8 = t80; |
| | 260 | const r9 = t90; |
| | 261 | |
| | 262 | const m0: u64 = 5175514460705773; |
| | 263 | const m1: u64 = 70332060721272408; |
| | 264 | const m2: u64 = 5342; |
| | 265 | const m3: u64 = 0; |
| | 266 | const m4: u64 = 268435456; |
| | 267 | const mu0: u64 = 44162584779952923; |
| | 268 | const mu1: u64 = 9390964836247533; |
| | 269 | const mu2: u64 = 72057594036560134; |
| | 270 | const mu3: u64 = 72057594037927935; |
| | 271 | const mu4: u64 = 68719476735; |
| | 272 | |
| | 273 | const y_ = (r5 & 0xffffff) << 32; |
| | 274 | const x_ = r4 >> 24; |
| | 275 | const z01 = (x_ | y_); |
| | 276 | const y_0 = (r6 & 0xffffff) << 32; |
| | 277 | const x_0 = r5 >> 24; |
| | 278 | const z11 = (x_0 | y_0); |
| | 279 | const y_1 = (r7 & 0xffffff) << 32; |
| | 280 | const x_1 = r6 >> 24; |
| | 281 | const z21 = (x_1 | y_1); |
| | 282 | const y_2 = (r8 & 0xffffff) << 32; |
| | 283 | const x_2 = r7 >> 24; |
| | 284 | const z31 = (x_2 | y_2); |
| | 285 | const y_3 = (r9 & 0xffffff) << 32; |
| | 286 | const x_3 = r8 >> 24; |
| | 287 | const z41 = (x_3 | y_3); |
| | 288 | const q0 = z01; |
| | 289 | const q1 = z11; |
| | 290 | const q2 = z21; |
| | 291 | const q3 = z31; |
| | 292 | const q4 = z41; |
| | 293 | const xy001 = @as(u128, q0) * @as(u128, mu0); |
| | 294 | const xy011 = @as(u128, q0) * @as(u128, mu1); |
| | 295 | const xy021 = @as(u128, q0) * @as(u128, mu2); |
| | 296 | const xy031 = @as(u128, q0) * @as(u128, mu3); |
| | 297 | const xy041 = @as(u128, q0) * @as(u128, mu4); |
| | 298 | const xy101 = @as(u128, q1) * @as(u128, mu0); |
| | 299 | const xy111 = @as(u128, q1) * @as(u128, mu1); |
| | 300 | const xy121 = @as(u128, q1) * @as(u128, mu2); |
| | 301 | const xy131 = @as(u128, q1) * @as(u128, mu3); |
| | 302 | const xy14 = @as(u128, q1) * @as(u128, mu4); |
| | 303 | const xy201 = @as(u128, q2) * @as(u128, mu0); |
| | 304 | const xy211 = @as(u128, q2) * @as(u128, mu1); |
| | 305 | const xy221 = @as(u128, q2) * @as(u128, mu2); |
| | 306 | const xy23 = @as(u128, q2) * @as(u128, mu3); |
| | 307 | const xy24 = @as(u128, q2) * @as(u128, mu4); |
| | 308 | const xy301 = @as(u128, q3) * @as(u128, mu0); |
| | 309 | const xy311 = @as(u128, q3) * @as(u128, mu1); |
| | 310 | const xy32 = @as(u128, q3) * @as(u128, mu2); |
| | 311 | const xy33 = @as(u128, q3) * @as(u128, mu3); |
| | 312 | const xy34 = @as(u128, q3) * @as(u128, mu4); |
| | 313 | const xy401 = @as(u128, q4) * @as(u128, mu0); |
| | 314 | const xy41 = @as(u128, q4) * @as(u128, mu1); |
| | 315 | const xy42 = @as(u128, q4) * @as(u128, mu2); |
| | 316 | const xy43 = @as(u128, q4) * @as(u128, mu3); |
| | 317 | const xy44 = @as(u128, q4) * @as(u128, mu4); |
| | 318 | const z02 = xy001; |
| | 319 | const z12 = xy011 + xy101; |
| | 320 | const z22 = xy021 + xy111 + xy201; |
| | 321 | const z32 = xy031 + xy121 + xy211 + xy301; |
| | 322 | const z42 = xy041 + xy131 + xy221 + xy311 + xy401; |
| | 323 | const z5 = xy14 + xy23 + xy32 + xy41; |
| | 324 | const z6 = xy24 + xy33 + xy42; |
| | 325 | const z7 = xy34 + xy43; |
| | 326 | const z8 = xy44; |
| | 327 | |
| | 328 | const carry9 = z02 >> 56; |
| | 329 | const c01 = carry9; |
| | 330 | const carry10 = (z12 + c01) >> 56; |
| | 331 | const t21 = @truncate(u64, z12 + c01) & 0xffffffffffffff; |
| | 332 | const c11 = carry10; |
| | 333 | const carry11 = (z22 + c11) >> 56; |
| | 334 | const t22 = @truncate(u64, z22 + c11) & 0xffffffffffffff; |
| | 335 | const c21 = carry11; |
| | 336 | const carry12 = (z32 + c21) >> 56; |
| | 337 | const t23 = @truncate(u64, z32 + c21) & 0xffffffffffffff; |
| | 338 | const c31 = carry12; |
| | 339 | const carry13 = (z42 + c31) >> 56; |
| | 340 | const t24 = @truncate(u64, z42 + c31) & 0xffffffffffffff; |
| | 341 | const c41 = carry13; |
| | 342 | const t41 = t24; |
| | 343 | const carry14 = (z5 + c41) >> 56; |
| | 344 | const t25 = @truncate(u64, z5 + c41) & 0xffffffffffffff; |
| | 345 | const c5 = carry14; |
| | 346 | const t5 = t25; |
| | 347 | const carry15 = (z6 + c5) >> 56; |
| | 348 | const t26 = @truncate(u64, z6 + c5) & 0xffffffffffffff; |
| | 349 | const c6 = carry15; |
| | 350 | const t6 = t26; |
| | 351 | const carry16 = (z7 + c6) >> 56; |
| | 352 | const t27 = @truncate(u64, z7 + c6) & 0xffffffffffffff; |
| | 353 | const c7 = carry16; |
| | 354 | const t7 = t27; |
| | 355 | const carry17 = (z8 + c7) >> 56; |
| | 356 | const t28 = @truncate(u64, z8 + c7) & 0xffffffffffffff; |
| | 357 | const c8 = carry17; |
| | 358 | const t8 = t28; |
| | 359 | const t9 = @truncate(u64, c8); |
| | 360 | |
| | 361 | const qmu4_ = t41; |
| | 362 | const qmu5_ = t5; |
| | 363 | const qmu6_ = t6; |
| | 364 | const qmu7_ = t7; |
| | 365 | const qmu8_ = t8; |
| | 366 | const qmu9_ = t9; |
| | 367 | const y_4 = (qmu5_ & 0xffffffffff) << 16; |
| | 368 | const x_4 = qmu4_ >> 40; |
| | 369 | const z03 = (x_4 | y_4); |
| | 370 | const y_5 = (qmu6_ & 0xffffffffff) << 16; |
| | 371 | const x_5 = qmu5_ >> 40; |
| | 372 | const z13 = (x_5 | y_5); |
| | 373 | const y_6 = (qmu7_ & 0xffffffffff) << 16; |
| | 374 | const x_6 = qmu6_ >> 40; |
| | 375 | const z23 = (x_6 | y_6); |
| | 376 | const y_7 = (qmu8_ & 0xffffffffff) << 16; |
| | 377 | const x_7 = qmu7_ >> 40; |
| | 378 | const z33 = (x_7 | y_7); |
| | 379 | const y_8 = (qmu9_ & 0xffffffffff) << 16; |
| | 380 | const x_8 = qmu8_ >> 40; |
| | 381 | const z43 = (x_8 | y_8); |
| | 382 | const qdiv0 = z03; |
| | 383 | const qdiv1 = z13; |
| | 384 | const qdiv2 = z23; |
| | 385 | const qdiv3 = z33; |
| | 386 | const qdiv4 = z43; |
| | 387 | const r01 = r0; |
| | 388 | const r11 = r1; |
| | 389 | const r21 = r2; |
| | 390 | const r31 = r3; |
| | 391 | const r41 = (r4 & 0xffffffffff); |
| | 392 | |
| | 393 | const xy00 = @as(u128, qdiv0) * @as(u128, m0); |
| | 394 | const xy01 = @as(u128, qdiv0) * @as(u128, m1); |
| | 395 | const xy02 = @as(u128, qdiv0) * @as(u128, m2); |
| | 396 | const xy03 = @as(u128, qdiv0) * @as(u128, m3); |
| | 397 | const xy04 = @as(u128, qdiv0) * @as(u128, m4); |
| | 398 | const xy10 = @as(u128, qdiv1) * @as(u128, m0); |
| | 399 | const xy11 = @as(u128, qdiv1) * @as(u128, m1); |
| | 400 | const xy12 = @as(u128, qdiv1) * @as(u128, m2); |
| | 401 | const xy13 = @as(u128, qdiv1) * @as(u128, m3); |
| | 402 | const xy20 = @as(u128, qdiv2) * @as(u128, m0); |
| | 403 | const xy21 = @as(u128, qdiv2) * @as(u128, m1); |
| | 404 | const xy22 = @as(u128, qdiv2) * @as(u128, m2); |
| | 405 | const xy30 = @as(u128, qdiv3) * @as(u128, m0); |
| | 406 | const xy31 = @as(u128, qdiv3) * @as(u128, m1); |
| | 407 | const xy40 = @as(u128, qdiv4) * @as(u128, m0); |
| | 408 | const carry18 = xy00 >> 56; |
| | 409 | const t29 = @truncate(u64, xy00) & 0xffffffffffffff; |
| | 410 | const c0 = carry18; |
| | 411 | const t01 = t29; |
| | 412 | const carry19 = (xy01 + xy10 + c0) >> 56; |
| | 413 | const t31 = @truncate(u64, xy01 + xy10 + c0) & 0xffffffffffffff; |
| | 414 | const c12 = carry19; |
| | 415 | const t110 = t31; |
| | 416 | const carry20 = (xy02 + xy11 + xy20 + c12) >> 56; |
| | 417 | const t32 = @truncate(u64, xy02 + xy11 + xy20 + c12) & 0xffffffffffffff; |
| | 418 | const c22 = carry20; |
| | 419 | const t210 = t32; |
| | 420 | const carry = (xy03 + xy12 + xy21 + xy30 + c22) >> 56; |
| | 421 | const t33 = @truncate(u64, xy03 + xy12 + xy21 + xy30 + c22) & 0xffffffffffffff; |
| | 422 | const c32 = carry; |
| | 423 | const t34 = t33; |
| | 424 | const t42 = @truncate(u64, xy04 + xy13 + xy22 + xy31 + xy40 + c32) & 0xffffffffff; |
| | 425 | |
| | 426 | const qmul0 = t01; |
| | 427 | const qmul1 = t110; |
| | 428 | const qmul2 = t210; |
| | 429 | const qmul3 = t34; |
| | 430 | const qmul4 = t42; |
| | 431 | const b5 = (r01 -% qmul0) >> 63; |
| | 432 | const t35 = ((b5 << 56) + r01) -% qmul0; |
| | 433 | const c1 = b5; |
| | 434 | const t02 = t35; |
| | 435 | const b6 = (r11 -% (qmul1 + c1)) >> 63; |
| | 436 | const t36 = ((b6 << 56) + r11) -% (qmul1 + c1); |
| | 437 | const c2 = b6; |
| | 438 | const t111 = t36; |
| | 439 | const b7 = (r21 -% (qmul2 + c2)) >> 63; |
| | 440 | const t37 = ((b7 << 56) + r21) -% (qmul2 + c2); |
| | 441 | const c3 = b7; |
| | 442 | const t211 = t37; |
| | 443 | const b8 = (r31 -% (qmul3 + c3)) >> 63; |
| | 444 | const t38 = ((b8 << 56) + r31) -% (qmul3 + c3); |
| | 445 | const c4 = b8; |
| | 446 | const t39 = t38; |
| | 447 | const b9 = (r41 -% (qmul4 + c4)) >> 63; |
| | 448 | const t43 = ((b9 << 40) + r41) -% (qmul4 + c4); |
| | 449 | const t44 = t43; |
| | 450 | const s0 = t02; |
| | 451 | const s1 = t111; |
| | 452 | const s2 = t211; |
| | 453 | const s3 = t39; |
| | 454 | const s4 = t44; |
| | 455 | |
| | 456 | const y01: u64 = 5175514460705773; |
| | 457 | const y11: u64 = 70332060721272408; |
| | 458 | const y21: u64 = 5342; |
| | 459 | const y31: u64 = 0; |
| | 460 | const y41: u64 = 268435456; |
| | 461 | |
| | 462 | const b10 = (s0 -% y01) >> 63; |
| | 463 | const t45 = ((b10 << 56) + s0) -% y01; |
| | 464 | const b0 = b10; |
| | 465 | const t0 = t45; |
| | 466 | const b11 = (s1 -% (y11 + b0)) >> 63; |
| | 467 | const t46 = ((b11 << 56) + s1) -% (y11 + b0); |
| | 468 | const b1 = b11; |
| | 469 | const t1 = t46; |
| | 470 | const b12 = (s2 -% (y21 + b1)) >> 63; |
| | 471 | const t47 = ((b12 << 56) + s2) -% (y21 + b1); |
| | 472 | const b2 = b12; |
| | 473 | const t2 = t47; |
| | 474 | const b13 = (s3 -% (y31 + b2)) >> 63; |
| | 475 | const t48 = ((b13 << 56) + s3) -% (y31 + b2); |
| | 476 | const b3 = b13; |
| | 477 | const t3 = t48; |
| | 478 | const b = (s4 -% (y41 + b3)) >> 63; |
| | 479 | const t = ((b << 56) + s4) -% (y41 + b3); |
| | 480 | const b4 = b; |
| | 481 | const t4 = t; |
| | 482 | const mask = (b4 -% @intCast(u64, ((1)))); |
| | 483 | const z04 = s0 ^ (mask & (s0 ^ t0)); |
| | 484 | const z14 = s1 ^ (mask & (s1 ^ t1)); |
| | 485 | const z24 = s2 ^ (mask & (s2 ^ t2)); |
| | 486 | const z34 = s3 ^ (mask & (s3 ^ t3)); |
| | 487 | const z44 = s4 ^ (mask & (s4 ^ t4)); |
| | 488 | |
| | 489 | return Scalar{ .limbs = .{ z04, z14, z24, z34, z44 } }; |
| | 490 | } |
| | 491 | }; |
| | 492 | |
| | 493 | const ScalarDouble = struct { |
| | 494 | const Limbs = [10]u64; |
| | 495 | limbs: Limbs = undefined, |
| | 496 | |
| | 497 | fn fromBytes64(bytes: [64]u8) ScalarDouble { |
| | 498 | var limbs: Limbs = undefined; |
| | 499 | var i: usize = 0; |
| | 500 | while (i < 9) : (i += 1) { |
| | 501 | limbs[i] = mem.readIntLittle(u64, bytes[i * 7 ..][0..8]) & 0xffffffffffffff; |
| | 502 | } |
| | 503 | limbs[i] = @as(u64, bytes[i * 7]); |
| | 504 | return ScalarDouble{ .limbs = limbs }; |
| | 505 | } |
| | 506 | |
| | 507 | fn fromBytes32(bytes: [32]u8) ScalarDouble { |
| | 508 | var limbs: Limbs = undefined; |
| | 509 | var i: usize = 0; |
| | 510 | while (i < 4) : (i += 1) { |
| | 511 | limbs[i] = mem.readIntLittle(u64, bytes[i * 7 ..][0..8]) & 0xffffffffffffff; |
| | 512 | } |
| | 513 | limbs[i] = @as(u64, mem.readIntLittle(u32, bytes[i * 7 ..][0..4])); |
| | 514 | mem.set(u64, limbs[5..], 0); |
| | 515 | return ScalarDouble{ .limbs = limbs }; |
| | 516 | } |
| | 517 | |
| | 518 | fn toBytes(expanded_double: *ScalarDouble) [32]u8 { |
| | 519 | return expanded_double.reduce(10).toBytes(); |
| | 520 | } |
| | 521 | |
| | 522 | /// Barrett reduction |
| | 523 | fn reduce(expanded: *ScalarDouble, comptime limbs_count: usize) Scalar { |
| | 524 | const t = expanded.limbs; |
| | 525 | const t0 = if (limbs_count <= 0) 0 else t[0]; |
| | 526 | const t1 = if (limbs_count <= 1) 0 else t[1]; |
| | 527 | const t2 = if (limbs_count <= 2) 0 else t[2]; |
| | 528 | const t3 = if (limbs_count <= 3) 0 else t[3]; |
| | 529 | const t4 = if (limbs_count <= 4) 0 else t[4]; |
| | 530 | const t5 = if (limbs_count <= 5) 0 else t[5]; |
| | 531 | const t6 = if (limbs_count <= 6) 0 else t[6]; |
| | 532 | const t7 = if (limbs_count <= 7) 0 else t[7]; |
| | 533 | const t8 = if (limbs_count <= 8) 0 else t[8]; |
| | 534 | const t9 = if (limbs_count <= 9) 0 else t[9]; |
| | 535 | |
| | 536 | const m0: u64 = 5175514460705773; |
| | 537 | const m1: u64 = 70332060721272408; |
| | 538 | const m2: u64 = 5342; |
| | 539 | const m3: u64 = 0; |
| | 540 | const m4: u64 = 268435456; |
| | 541 | const mu0: u64 = 44162584779952923; |
| | 542 | const mu1: u64 = 9390964836247533; |
| | 543 | const mu2: u64 = 72057594036560134; |
| | 544 | const mu3: u64 = 0xffffffffffffff; |
| | 545 | const mu4: u64 = 68719476735; |
| | 546 | |
| | 547 | const y_ = (t5 & 0xffffff) << 32; |
| | 548 | const x_ = t4 >> 24; |
| | 549 | const z00 = x_ | y_; |
| | 550 | const y_0 = (t6 & 0xffffff) << 32; |
| | 551 | const x_0 = t5 >> 24; |
| | 552 | const z10 = x_0 | y_0; |
| | 553 | const y_1 = (t7 & 0xffffff) << 32; |
| | 554 | const x_1 = t6 >> 24; |
| | 555 | const z20 = x_1 | y_1; |
| | 556 | const y_2 = (t8 & 0xffffff) << 32; |
| | 557 | const x_2 = t7 >> 24; |
| | 558 | const z30 = x_2 | y_2; |
| | 559 | const y_3 = (t9 & 0xffffff) << 32; |
| | 560 | const x_3 = t8 >> 24; |
| | 561 | const z40 = x_3 | y_3; |
| | 562 | const q0 = z00; |
| | 563 | const q1 = z10; |
| | 564 | const q2 = z20; |
| | 565 | const q3 = z30; |
| | 566 | const q4 = z40; |
| | 567 | |
| | 568 | const xy000 = @as(u128, q0) * @as(u128, mu0); |
| | 569 | const xy010 = @as(u128, q0) * @as(u128, mu1); |
| | 570 | const xy020 = @as(u128, q0) * @as(u128, mu2); |
| | 571 | const xy030 = @as(u128, q0) * @as(u128, mu3); |
| | 572 | const xy040 = @as(u128, q0) * @as(u128, mu4); |
| | 573 | const xy100 = @as(u128, q1) * @as(u128, mu0); |
| | 574 | const xy110 = @as(u128, q1) * @as(u128, mu1); |
| | 575 | const xy120 = @as(u128, q1) * @as(u128, mu2); |
| | 576 | const xy130 = @as(u128, q1) * @as(u128, mu3); |
| | 577 | const xy14 = @as(u128, q1) * @as(u128, mu4); |
| | 578 | const xy200 = @as(u128, q2) * @as(u128, mu0); |
| | 579 | const xy210 = @as(u128, q2) * @as(u128, mu1); |
| | 580 | const xy220 = @as(u128, q2) * @as(u128, mu2); |
| | 581 | const xy23 = @as(u128, q2) * @as(u128, mu3); |
| | 582 | const xy24 = @as(u128, q2) * @as(u128, mu4); |
| | 583 | const xy300 = @as(u128, q3) * @as(u128, mu0); |
| | 584 | const xy310 = @as(u128, q3) * @as(u128, mu1); |
| | 585 | const xy32 = @as(u128, q3) * @as(u128, mu2); |
| | 586 | const xy33 = @as(u128, q3) * @as(u128, mu3); |
| | 587 | const xy34 = @as(u128, q3) * @as(u128, mu4); |
| | 588 | const xy400 = @as(u128, q4) * @as(u128, mu0); |
| | 589 | const xy41 = @as(u128, q4) * @as(u128, mu1); |
| | 590 | const xy42 = @as(u128, q4) * @as(u128, mu2); |
| | 591 | const xy43 = @as(u128, q4) * @as(u128, mu3); |
| | 592 | const xy44 = @as(u128, q4) * @as(u128, mu4); |
| | 593 | const z01 = xy000; |
| | 594 | const z11 = xy010 + xy100; |
| | 595 | const z21 = xy020 + xy110 + xy200; |
| | 596 | const z31 = xy030 + xy120 + xy210 + xy300; |
| | 597 | const z41 = xy040 + xy130 + xy220 + xy310 + xy400; |
| | 598 | const z5 = xy14 + xy23 + xy32 + xy41; |
| | 599 | const z6 = xy24 + xy33 + xy42; |
| | 600 | const z7 = xy34 + xy43; |
| | 601 | const z8 = xy44; |
| | 602 | |
| | 603 | const carry0 = z01 >> 56; |
| | 604 | const c00 = carry0; |
| | 605 | const carry1 = (z11 + c00) >> 56; |
| | 606 | const t100 = @as(u64, @truncate(u64, z11 + c00)) & 0xffffffffffffff; |
| | 607 | const c10 = carry1; |
| | 608 | const carry2 = (z21 + c10) >> 56; |
| | 609 | const t101 = @as(u64, @truncate(u64, z21 + c10)) & 0xffffffffffffff; |
| | 610 | const c20 = carry2; |
| | 611 | const carry3 = (z31 + c20) >> 56; |
| | 612 | const t102 = @as(u64, @truncate(u64, z31 + c20)) & 0xffffffffffffff; |
| | 613 | const c30 = carry3; |
| | 614 | const carry4 = (z41 + c30) >> 56; |
| | 615 | const t103 = @as(u64, @truncate(u64, z41 + c30)) & 0xffffffffffffff; |
| | 616 | const c40 = carry4; |
| | 617 | const t410 = t103; |
| | 618 | const carry5 = (z5 + c40) >> 56; |
| | 619 | const t104 = @as(u64, @truncate(u64, z5 + c40)) & 0xffffffffffffff; |
| | 620 | const c5 = carry5; |
| | 621 | const t51 = t104; |
| | 622 | const carry6 = (z6 + c5) >> 56; |
| | 623 | const t105 = @as(u64, @truncate(u64, z6 + c5)) & 0xffffffffffffff; |
| | 624 | const c6 = carry6; |
| | 625 | const t61 = t105; |
| | 626 | const carry7 = (z7 + c6) >> 56; |
| | 627 | const t106 = @as(u64, @truncate(u64, z7 + c6)) & 0xffffffffffffff; |
| | 628 | const c7 = carry7; |
| | 629 | const t71 = t106; |
| | 630 | const carry8 = (z8 + c7) >> 56; |
| | 631 | const t107 = @as(u64, @truncate(u64, z8 + c7)) & 0xffffffffffffff; |
| | 632 | const c8 = carry8; |
| | 633 | const t81 = t107; |
| | 634 | const t91 = @as(u64, @truncate(u64, c8)); |
| | 635 | |
| | 636 | const qmu4_ = t410; |
| | 637 | const qmu5_ = t51; |
| | 638 | const qmu6_ = t61; |
| | 639 | const qmu7_ = t71; |
| | 640 | const qmu8_ = t81; |
| | 641 | const qmu9_ = t91; |
| | 642 | const y_4 = (qmu5_ & 0xffffffffff) << 16; |
| | 643 | const x_4 = qmu4_ >> 40; |
| | 644 | const z02 = x_4 | y_4; |
| | 645 | const y_5 = (qmu6_ & 0xffffffffff) << 16; |
| | 646 | const x_5 = qmu5_ >> 40; |
| | 647 | const z12 = x_5 | y_5; |
| | 648 | const y_6 = (qmu7_ & 0xffffffffff) << 16; |
| | 649 | const x_6 = qmu6_ >> 40; |
| | 650 | const z22 = x_6 | y_6; |
| | 651 | const y_7 = (qmu8_ & 0xffffffffff) << 16; |
| | 652 | const x_7 = qmu7_ >> 40; |
| | 653 | const z32 = x_7 | y_7; |
| | 654 | const y_8 = (qmu9_ & 0xffffffffff) << 16; |
| | 655 | const x_8 = qmu8_ >> 40; |
| | 656 | const z42 = x_8 | y_8; |
| | 657 | const qdiv0 = z02; |
| | 658 | const qdiv1 = z12; |
| | 659 | const qdiv2 = z22; |
| | 660 | const qdiv3 = z32; |
| | 661 | const qdiv4 = z42; |
| | 662 | const r0 = t0; |
| | 663 | const r1 = t1; |
| | 664 | const r2 = t2; |
| | 665 | const r3 = t3; |
| | 666 | const r4 = t4 & 0xffffffffff; |
| | 667 | |
| | 668 | const xy00 = @as(u128, qdiv0) * @as(u128, m0); |
| | 669 | const xy01 = @as(u128, qdiv0) * @as(u128, m1); |
| | 670 | const xy02 = @as(u128, qdiv0) * @as(u128, m2); |
| | 671 | const xy03 = @as(u128, qdiv0) * @as(u128, m3); |
| | 672 | const xy04 = @as(u128, qdiv0) * @as(u128, m4); |
| | 673 | const xy10 = @as(u128, qdiv1) * @as(u128, m0); |
| | 674 | const xy11 = @as(u128, qdiv1) * @as(u128, m1); |
| | 675 | const xy12 = @as(u128, qdiv1) * @as(u128, m2); |
| | 676 | const xy13 = @as(u128, qdiv1) * @as(u128, m3); |
| | 677 | const xy20 = @as(u128, qdiv2) * @as(u128, m0); |
| | 678 | const xy21 = @as(u128, qdiv2) * @as(u128, m1); |
| | 679 | const xy22 = @as(u128, qdiv2) * @as(u128, m2); |
| | 680 | const xy30 = @as(u128, qdiv3) * @as(u128, m0); |
| | 681 | const xy31 = @as(u128, qdiv3) * @as(u128, m1); |
| | 682 | const xy40 = @as(u128, qdiv4) * @as(u128, m0); |
| | 683 | const carry9 = xy00 >> 56; |
| | 684 | const t108 = @truncate(u64, xy00) & 0xffffffffffffff; |
| | 685 | const c0 = carry9; |
| | 686 | const t010 = t108; |
| | 687 | const carry10 = (xy01 + xy10 + c0) >> 56; |
| | 688 | const t109 = @truncate(u64, xy01 + xy10 + c0) & 0xffffffffffffff; |
| | 689 | const c11 = carry10; |
| | 690 | const t110 = t109; |
| | 691 | const carry11 = (xy02 + xy11 + xy20 + c11) >> 56; |
| | 692 | const t1010 = @truncate(u64, xy02 + xy11 + xy20 + c11) & 0xffffffffffffff; |
| | 693 | const c21 = carry11; |
| | 694 | const t210 = t1010; |
| | 695 | const carry = (xy03 + xy12 + xy21 + xy30 + c21) >> 56; |
| | 696 | const t1011 = @truncate(u64, xy03 + xy12 + xy21 + xy30 + c21) & 0xffffffffffffff; |
| | 697 | const c31 = carry; |
| | 698 | const t310 = t1011; |
| | 699 | const t411 = @truncate(u64, xy04 + xy13 + xy22 + xy31 + xy40 + c31) & 0xffffffffff; |
| | 700 | |
| | 701 | const qmul0 = t010; |
| | 702 | const qmul1 = t110; |
| | 703 | const qmul2 = t210; |
| | 704 | const qmul3 = t310; |
| | 705 | const qmul4 = t411; |
| | 706 | const b5 = (r0 -% qmul0) >> 63; |
| | 707 | const t1012 = ((b5 << 56) + r0) -% qmul0; |
| | 708 | const c1 = b5; |
| | 709 | const t011 = t1012; |
| | 710 | const b6 = (r1 -% (qmul1 + c1)) >> 63; |
| | 711 | const t1013 = ((b6 << 56) + r1) -% (qmul1 + c1); |
| | 712 | const c2 = b6; |
| | 713 | const t111 = t1013; |
| | 714 | const b7 = (r2 -% (qmul2 + c2)) >> 63; |
| | 715 | const t1014 = ((b7 << 56) + r2) -% (qmul2 + c2); |
| | 716 | const c3 = b7; |
| | 717 | const t211 = t1014; |
| | 718 | const b8 = (r3 -% (qmul3 + c3)) >> 63; |
| | 719 | const t1015 = ((b8 << 56) + r3) -% (qmul3 + c3); |
| | 720 | const c4 = b8; |
| | 721 | const t311 = t1015; |
| | 722 | const b9 = (r4 -% (qmul4 + c4)) >> 63; |
| | 723 | const t1016 = ((b9 << 40) + r4) -% (qmul4 + c4); |
| | 724 | const t412 = t1016; |
| | 725 | const s0 = t011; |
| | 726 | const s1 = t111; |
| | 727 | const s2 = t211; |
| | 728 | const s3 = t311; |
| | 729 | const s4 = t412; |
| | 730 | |
| | 731 | const y0: u64 = 5175514460705773; |
| | 732 | const y1: u64 = 70332060721272408; |
| | 733 | const y2: u64 = 5342; |
| | 734 | const y3: u64 = 0; |
| | 735 | const y4: u64 = 268435456; |
| | 736 | |
| | 737 | const b10 = (s0 -% y0) >> 63; |
| | 738 | const t1017 = ((b10 << 56) + s0) -% y0; |
| | 739 | const b0 = b10; |
| | 740 | const t01 = t1017; |
| | 741 | const b11 = (s1 -% (y1 + b0)) >> 63; |
| | 742 | const t1018 = ((b11 << 56) + s1) -% (y1 + b0); |
| | 743 | const b1 = b11; |
| | 744 | const t11 = t1018; |
| | 745 | const b12 = (s2 -% (y2 + b1)) >> 63; |
| | 746 | const t1019 = ((b12 << 56) + s2) -% (y2 + b1); |
| | 747 | const b2 = b12; |
| | 748 | const t21 = t1019; |
| | 749 | const b13 = (s3 -% (y3 + b2)) >> 63; |
| | 750 | const t1020 = ((b13 << 56) + s3) -% (y3 + b2); |
| | 751 | const b3 = b13; |
| | 752 | const t31 = t1020; |
| | 753 | const b = (s4 -% (y4 + b3)) >> 63; |
| | 754 | const t10 = ((b << 56) + s4) -% (y4 + b3); |
| | 755 | const b4 = b; |
| | 756 | const t41 = t10; |
| | 757 | const mask = b4 -% @as(u64, @as(u64, 1)); |
| | 758 | const z03 = s0 ^ (mask & (s0 ^ t01)); |
| | 759 | const z13 = s1 ^ (mask & (s1 ^ t11)); |
| | 760 | const z23 = s2 ^ (mask & (s2 ^ t21)); |
| | 761 | const z33 = s3 ^ (mask & (s3 ^ t31)); |
| | 762 | const z43 = s4 ^ (mask & (s4 ^ t41)); |
| | 763 | |
| | 764 | return Scalar{ .limbs = .{ z03, z13, z23, z33, z43 } }; |
| | 765 | } |
| | 766 | }; |
| | 767 | |
| 158 | test "scalar25519" { | 768 | test "scalar25519" { |
| 159 | const bytes: [32]u8 = .{ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 255 }; | 769 | const bytes: [32]u8 = .{ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 255 }; |
| 160 | var x = ScalarExpanded.fromBytes(bytes); | 770 | var x = Scalar.fromBytes(bytes); |
| 161 | var y = x.toBytes(); | 771 | var y = x.toBytes(); |
| 162 | try rejectNonCanonical(y); | 772 | try rejectNonCanonical(y); |
| 163 | var buf: [128]u8 = undefined; | 773 | var buf: [128]u8 = undefined; |