| author | |
| committer | |
| log | 7674a8b43d42434a2ed424ca0778bb348e1e3d70 |
| tree | 24eeca98b8cd5d8dcbc476690a7f030420311f37 |
| parent | d8d92dafe8763ac18d964bb1a6e88de0b13da152 |
fiat-crypto now generates proper types, so take advantage of that.
Add mixed subtraction and double base multiplication.
We will eventually leverage mixed addition/subtraction for fixed
base multiplication. The reason we don't right now is that
precomputing the tables at comptime would take forever.
We don't use combs for the same reason. Stage2 + less function
calls in the fiat-crypto generated code will eventually address
that.
Also make the edwards25519 code consistent with these changes.
No functional changes.6 files changed, 195 insertions(+), 163 deletions(-)
lib/std/crypto/25519/edwards25519.zig+21-20| ... | @@ -143,7 +143,7 @@ pub const Edwards25519 = struct { | ... | @@ -143,7 +143,7 @@ pub const Edwards25519 = struct { |
| 143 | p.t.cMov(a.t, c); | 143 | p.t.cMov(a.t, c); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | inline fn pcSelect(comptime n: usize, pc: [n]Edwards25519, b: u8) Edwards25519 { | 146 | inline fn pcSelect(comptime n: usize, pc: *const [n]Edwards25519, b: u8) Edwards25519 { |
| 147 | var t = Edwards25519.identityElement; | 147 | var t = Edwards25519.identityElement; |
| 148 | comptime var i: u8 = 1; | 148 | comptime var i: u8 = 1; |
| 149 | inline while (i < pc.len) : (i += 1) { | 149 | inline while (i < pc.len) : (i += 1) { |
| ... | @@ -176,7 +176,7 @@ pub const Edwards25519 = struct { | ... | @@ -176,7 +176,7 @@ pub const Edwards25519 = struct { |
| 176 | // Based on real-world benchmarks, we only use this for multi-scalar multiplication. | 176 | // Based on real-world benchmarks, we only use this for multi-scalar multiplication. |
| 177 | // NAF could be useful to half the size of precomputation tables, but we intentionally | 177 | // NAF could be useful to half the size of precomputation tables, but we intentionally |
| 178 | // avoid these to keep the standard library lightweight. | 178 | // avoid these to keep the standard library lightweight. |
| 179 | fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 { | 179 | fn pcMul(pc: *const [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 { |
| 180 | std.debug.assert(vartime); | 180 | std.debug.assert(vartime); |
| 181 | const e = slide(s); | 181 | const e = slide(s); |
| 182 | var q = Edwards25519.identityElement; | 182 | var q = Edwards25519.identityElement; |
| ... | @@ -196,7 +196,7 @@ pub const Edwards25519 = struct { | ... | @@ -196,7 +196,7 @@ pub const Edwards25519 = struct { |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | // Scalar multiplication with a 4-bit window and the first 15 multiples. | 198 | // Scalar multiplication with a 4-bit window and the first 15 multiples. |
| 199 | fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 { | 199 | fn pcMul16(pc: *const [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 { |
| 200 | var q = Edwards25519.identityElement; | 200 | var q = Edwards25519.identityElement; |
| 201 | var pos: usize = 252; | 201 | var pos: usize = 252; |
| 202 | while (true) : (pos -= 4) { | 202 | while (true) : (pos -= 4) { |
| ... | @@ -231,11 +231,6 @@ pub const Edwards25519 = struct { | ... | @@ -231,11 +231,6 @@ pub const Edwards25519 = struct { |
| 231 | break :pc precompute(Edwards25519.basePoint, 15); | 231 | break :pc precompute(Edwards25519.basePoint, 15); |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | const basePointPc8 = pc: { | ||
| 235 | @setEvalBranchQuota(10000); | ||
| 236 | break :pc precompute(Edwards25519.basePoint, 8); | ||
| 237 | }; | ||
| 238 | |||
| 239 | /// Multiply an Edwards25519 point by a scalar without clamping it. | 234 | /// Multiply an Edwards25519 point by a scalar without clamping it. |
| 240 | /// Return error.WeakPublicKey if the base generates a small-order group, | 235 | /// Return error.WeakPublicKey if the base generates a small-order group, |
| 241 | /// and error.IdentityElement if the result is the identity element. | 236 | /// and error.IdentityElement if the result is the identity element. |
| ... | @@ -245,33 +240,35 @@ pub const Edwards25519 = struct { | ... | @@ -245,33 +240,35 @@ pub const Edwards25519 = struct { |
| 245 | xpc[4].rejectIdentity() catch return error.WeakPublicKey; | 240 | xpc[4].rejectIdentity() catch return error.WeakPublicKey; |
| 246 | break :pc xpc; | 241 | break :pc xpc; |
| 247 | }; | 242 | }; |
| 248 | return pcMul16(pc, s, false); | 243 | return pcMul16(&pc, s, false); |
| 249 | } | 244 | } |
| 250 | 245 | ||
| 251 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* | 246 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 252 | /// This can be used for signature verification. | 247 | /// This can be used for signature verification. |
| 253 | pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { | 248 | pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { |
| 254 | if (p.is_base) { | 249 | if (p.is_base) { |
| 255 | return pcMul16(basePointPc, s, true); | 250 | return pcMul16(&basePointPc, s, true); |
| 256 | } else { | 251 | } else { |
| 257 | const pc = precompute(p, 8); | 252 | const pc = precompute(p, 8); |
| 258 | pc[4].rejectIdentity() catch return error.WeakPublicKey; | 253 | pc[4].rejectIdentity() catch return error.WeakPublicKey; |
| 259 | return pcMul(pc, s, true); | 254 | return pcMul(&pc, s, true); |
| 260 | } | 255 | } |
| 261 | } | 256 | } |
| 262 | 257 | ||
| 263 | /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* | 258 | /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* |
| 264 | /// This can be used for signature verification. | 259 | /// This can be used for signature verification. |
| 265 | pub fn mulDoubleBasePublic(p1: Edwards25519, s1: [32]u8, p2: Edwards25519, s2: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { | 260 | pub fn mulDoubleBasePublic(p1: Edwards25519, s1: [32]u8, p2: Edwards25519, s2: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { |
| 266 | const pc1 = if (p1.is_base) basePointPc8 else pc: { | 261 | var pc1_array: [9]Edwards25519 = undefined; |
| 267 | const xpc = precompute(p1, 8); | 262 | const pc1 = if (p1.is_base) basePointPc[0..9] else pc: { |
| 268 | xpc[4].rejectIdentity() catch return error.WeakPublicKey; | 263 | pc1_array = precompute(p1, 8); |
| 269 | break :pc xpc; | 264 | pc1_array[4].rejectIdentity() catch return error.WeakPublicKey; |
| 265 | break :pc &pc1_array; | ||
| 270 | }; | 266 | }; |
| 271 | const pc2 = if (p2.is_base) basePointPc8 else pc: { | 267 | var pc2_array: [9]Edwards25519 = undefined; |
| 272 | const xpc = precompute(p2, 8); | 268 | const pc2 = if (p2.is_base) basePointPc[0..9] else pc: { |
| 273 | xpc[4].rejectIdentity() catch return error.WeakPublicKey; | 269 | pc2_array = precompute(p2, 8); |
| 274 | break :pc xpc; | 270 | pc2_array[4].rejectIdentity() catch return error.WeakPublicKey; |
| 271 | break :pc &pc2_array; | ||
| 275 | }; | 272 | }; |
| 276 | const e1 = slide(s1); | 273 | const e1 = slide(s1); |
| 277 | const e2 = slide(s2); | 274 | const e2 = slide(s2); |
| ... | @@ -301,9 +298,13 @@ pub const Edwards25519 = struct { | ... | @@ -301,9 +298,13 @@ pub const Edwards25519 = struct { |
| 301 | /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually | 298 | /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually |
| 302 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { | 299 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 { |
| 303 | var pcs: [count][9]Edwards25519 = undefined; | 300 | var pcs: [count][9]Edwards25519 = undefined; |
| 301 | |||
| 302 | var bpc: [9]Edwards25519 = undefined; | ||
| 303 | mem.copy(Edwards25519, bpc[0..], basePointPc[0..bpc.len]); | ||
| 304 | |||
| 304 | for (ps) |p, i| { | 305 | for (ps) |p, i| { |
| 305 | if (p.is_base) { | 306 | if (p.is_base) { |
| 306 | pcs[i] = basePointPc8; | 307 | pcs[i] = bpc; |
| 307 | } else { | 308 | } else { |
| 308 | pcs[i] = precompute(p, 8); | 309 | pcs[i] = precompute(p, 8); |
| 309 | pcs[i][4].rejectIdentity() catch return error.WeakPublicKey; | 310 | pcs[i][4].rejectIdentity() catch return error.WeakPublicKey; |
lib/std/crypto/pcurves/common.zig+8-6| ... | @@ -20,12 +20,13 @@ pub const FieldParams = struct { | ... | @@ -20,12 +20,13 @@ pub const FieldParams = struct { |
| 20 | /// A field element, internally stored in Montgomery domain. | 20 | /// A field element, internally stored in Montgomery domain. |
| 21 | pub fn Field(comptime params: FieldParams) type { | 21 | pub fn Field(comptime params: FieldParams) type { |
| 22 | const fiat = params.fiat; | 22 | const fiat = params.fiat; |
| 23 | const Limbs = fiat.Limbs; | 23 | const MontgomeryDomainFieldElement = fiat.MontgomeryDomainFieldElement; |
| 24 | const NonMontgomeryDomainFieldElement = fiat.NonMontgomeryDomainFieldElement; | ||
| 24 | 25 | ||
| 25 | return struct { | 26 | return struct { |
| 26 | const Fe = @This(); | 27 | const Fe = @This(); |
| 27 | 28 | ||
| 28 | limbs: Limbs, | 29 | limbs: MontgomeryDomainFieldElement, |
| 29 | 30 | ||
| 30 | /// Field size. | 31 | /// Field size. |
| 31 | pub const field_order = params.field_order; | 32 | pub const field_order = params.field_order; |
| ... | @@ -40,7 +41,7 @@ pub fn Field(comptime params: FieldParams) type { | ... | @@ -40,7 +41,7 @@ pub fn Field(comptime params: FieldParams) type { |
| 40 | pub const encoded_length = params.encoded_length; | 41 | pub const encoded_length = params.encoded_length; |
| 41 | 42 | ||
| 42 | /// Zero. | 43 | /// Zero. |
| 43 | pub const zero: Fe = Fe{ .limbs = mem.zeroes(Limbs) }; | 44 | pub const zero: Fe = Fe{ .limbs = mem.zeroes(MontgomeryDomainFieldElement) }; |
| 44 | 45 | ||
| 45 | /// One. | 46 | /// One. |
| 46 | pub const one = one: { | 47 | pub const one = one: { |
| ... | @@ -73,16 +74,16 @@ pub fn Field(comptime params: FieldParams) type { | ... | @@ -73,16 +74,16 @@ pub fn Field(comptime params: FieldParams) type { |
| 73 | pub fn fromBytes(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!Fe { | 74 | pub fn fromBytes(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!Fe { |
| 74 | var s = if (endian == .Little) s_ else orderSwap(s_); | 75 | var s = if (endian == .Little) s_ else orderSwap(s_); |
| 75 | try rejectNonCanonical(s, .Little); | 76 | try rejectNonCanonical(s, .Little); |
| 76 | var limbs_z: Limbs = undefined; | 77 | var limbs_z: NonMontgomeryDomainFieldElement = undefined; |
| 77 | fiat.fromBytes(&limbs_z, s); | 78 | fiat.fromBytes(&limbs_z, s); |
| 78 | var limbs: Limbs = undefined; | 79 | var limbs: MontgomeryDomainFieldElement = undefined; |
| 79 | fiat.toMontgomery(&limbs, limbs_z); | 80 | fiat.toMontgomery(&limbs, limbs_z); |
| 80 | return Fe{ .limbs = limbs }; | 81 | return Fe{ .limbs = limbs }; |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | /// Pack a field element. | 84 | /// Pack a field element. |
| 84 | pub fn toBytes(fe: Fe, endian: builtin.Endian) [encoded_length]u8 { | 85 | pub fn toBytes(fe: Fe, endian: builtin.Endian) [encoded_length]u8 { |
| 85 | var limbs_z: Limbs = undefined; | 86 | var limbs_z: NonMontgomeryDomainFieldElement = undefined; |
| 86 | fiat.fromMontgomery(&limbs_z, fe.limbs); | 87 | fiat.fromMontgomery(&limbs_z, fe.limbs); |
| 87 | var s: [encoded_length]u8 = undefined; | 88 | var s: [encoded_length]u8 = undefined; |
| 88 | fiat.toBytes(&s, limbs_z); | 89 | fiat.toBytes(&s, limbs_z); |
| ... | @@ -198,6 +199,7 @@ pub fn Field(comptime params: FieldParams) type { | ... | @@ -198,6 +199,7 @@ pub fn Field(comptime params: FieldParams) type { |
| 198 | // Field inversion from https://eprint.iacr.org/2021/549.pdf | 199 | // Field inversion from https://eprint.iacr.org/2021/549.pdf |
| 199 | pub fn invert(a: Fe) Fe { | 200 | pub fn invert(a: Fe) Fe { |
| 200 | const iterations = (49 * field_bits + 57) / 17; | 201 | const iterations = (49 * field_bits + 57) / 17; |
| 202 | const Limbs = @TypeOf(a.limbs); | ||
| 201 | const Word = @TypeOf(a.limbs[0]); | 203 | const Word = @TypeOf(a.limbs[0]); |
| 202 | const XLimbs = [a.limbs.len + 1]Word; | 204 | const XLimbs = [a.limbs.len + 1]Word; |
| 203 | 205 |
lib/std/crypto/pcurves/p256.zig+60-19| ... | @@ -286,6 +286,11 @@ pub const P256 = struct { | ... | @@ -286,6 +286,11 @@ pub const P256 = struct { |
| 286 | return p.add(q.neg()); | 286 | return p.add(q.neg()); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /// Subtract P256 points, the second being specified using affine coordinates. | ||
| 290 | pub fn subMixed(p: P256, q: AffineCoordinates) P256 { | ||
| 291 | return p.addMixed(q.neg()); | ||
| 292 | } | ||
| 293 | |||
| 289 | /// Return affine coordinates. | 294 | /// Return affine coordinates. |
| 290 | pub fn affineCoordinates(p: P256) AffineCoordinates { | 295 | pub fn affineCoordinates(p: P256) AffineCoordinates { |
| 291 | const zinv = p.z.invert(); | 296 | const zinv = p.z.invert(); |
| ... | @@ -312,7 +317,7 @@ pub const P256 = struct { | ... | @@ -312,7 +317,7 @@ pub const P256 = struct { |
| 312 | p.z.cMov(a.z, c); | 317 | p.z.cMov(a.z, c); |
| 313 | } | 318 | } |
| 314 | 319 | ||
| 315 | fn pcSelect(comptime n: usize, pc: [n]P256, b: u8) P256 { | 320 | fn pcSelect(comptime n: usize, pc: *const [n]P256, b: u8) P256 { |
| 316 | var t = P256.identityElement; | 321 | var t = P256.identityElement; |
| 317 | comptime var i: u8 = 1; | 322 | comptime var i: u8 = 1; |
| 318 | inline while (i < pc.len) : (i += 1) { | 323 | inline while (i < pc.len) : (i += 1) { |
| ... | @@ -341,7 +346,7 @@ pub const P256 = struct { | ... | @@ -341,7 +346,7 @@ pub const P256 = struct { |
| 341 | return e; | 346 | return e; |
| 342 | } | 347 | } |
| 343 | 348 | ||
| 344 | fn pcMul(pc: [9]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { | 349 | fn pcMul(pc: *const [9]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { |
| 345 | std.debug.assert(vartime); | 350 | std.debug.assert(vartime); |
| 346 | const e = slide(s); | 351 | const e = slide(s); |
| 347 | var q = P256.identityElement; | 352 | var q = P256.identityElement; |
| ... | @@ -360,7 +365,7 @@ pub const P256 = struct { | ... | @@ -360,7 +365,7 @@ pub const P256 = struct { |
| 360 | return q; | 365 | return q; |
| 361 | } | 366 | } |
| 362 | 367 | ||
| 363 | fn pcMul16(pc: [16]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { | 368 | fn pcMul16(pc: *const [16]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { |
| 364 | var q = P256.identityElement; | 369 | var q = P256.identityElement; |
| 365 | var pos: usize = 252; | 370 | var pos: usize = 252; |
| 366 | while (true) : (pos -= 4) { | 371 | while (true) : (pos -= 4) { |
| ... | @@ -395,33 +400,69 @@ pub const P256 = struct { | ... | @@ -395,33 +400,69 @@ pub const P256 = struct { |
| 395 | break :pc precompute(P256.basePoint, 15); | 400 | break :pc precompute(P256.basePoint, 15); |
| 396 | }; | 401 | }; |
| 397 | 402 | ||
| 398 | const basePointPc8 = pc: { | ||
| 399 | @setEvalBranchQuota(50000); | ||
| 400 | break :pc precompute(P256.basePoint, 8); | ||
| 401 | }; | ||
| 402 | |||
| 403 | /// Multiply an elliptic curve point by a scalar. | 403 | /// Multiply an elliptic curve point by a scalar. |
| 404 | /// Return error.IdentityElement if the result is the identity element. | 404 | /// Return error.IdentityElement if the result is the identity element. |
| 405 | pub fn mul(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { | 405 | pub fn mul(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { |
| 406 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); | 406 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); |
| 407 | const pc = if (p.is_base) basePointPc else pc: { | 407 | if (p.is_base) { |
| 408 | try p.rejectIdentity(); | 408 | return pcMul16(&basePointPc, s, false); |
| 409 | const xpc = precompute(p, 15); | 409 | } |
| 410 | break :pc xpc; | 410 | try p.rejectIdentity(); |
| 411 | }; | 411 | const pc = precompute(p, 15); |
| 412 | return pcMul16(pc, s, false); | 412 | return pcMul16(&pc, s, false); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* | 415 | /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 416 | /// This can be used for signature verification. | 416 | /// This can be used for signature verification. |
| 417 | pub fn mulPublic(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { | 417 | pub fn mulPublic(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { |
| 418 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); | 418 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); |
| 419 | const pc = if (p.is_base) basePointPc8 else pc: { | 419 | if (p.is_base) { |
| 420 | try p.rejectIdentity(); | 420 | return pcMul16(&basePointPc, s, true); |
| 421 | const xpc = precompute(p, 8); | 421 | } |
| 422 | break :pc xpc; | 422 | try p.rejectIdentity(); |
| 423 | const pc = precompute(p, 8); | ||
| 424 | return pcMul(&pc, s, true); | ||
| 425 | } | ||
| 426 | |||
| 427 | /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* | ||
| 428 | /// This can be used for signature verification. | ||
| 429 | pub fn mulDoubleBasePublic(p1: P256, s1_: [32]u8, p2: P256, s2_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { | ||
| 430 | const s1 = if (endian == .Little) s1_ else Fe.orderSwap(s1_); | ||
| 431 | const s2 = if (endian == .Little) s2_ else Fe.orderSwap(s2_); | ||
| 432 | try p1.rejectIdentity(); | ||
| 433 | var pc1_array: [9]P256 = undefined; | ||
| 434 | const pc1 = if (p1.is_base) basePointPc[0..9] else pc: { | ||
| 435 | pc1_array = precompute(p1, 8); | ||
| 436 | break :pc &pc1_array; | ||
| 423 | }; | 437 | }; |
| 424 | return pcMul(pc, s, true); | 438 | try p2.rejectIdentity(); |
| 439 | var pc2_array: [9]P256 = undefined; | ||
| 440 | const pc2 = if (p2.is_base) basePointPc[0..9] else pc: { | ||
| 441 | pc2_array = precompute(p2, 8); | ||
| 442 | break :pc &pc2_array; | ||
| 443 | }; | ||
| 444 | const e1 = slide(s1); | ||
| 445 | const e2 = slide(s2); | ||
| 446 | var q = P256.identityElement; | ||
| 447 | var pos: usize = 2 * 32 - 1; | ||
| 448 | while (true) : (pos -= 1) { | ||
| 449 | const slot1 = e1[pos]; | ||
| 450 | if (slot1 > 0) { | ||
| 451 | q = q.add(pc1[@intCast(usize, slot1)]); | ||
| 452 | } else if (slot1 < 0) { | ||
| 453 | q = q.sub(pc1[@intCast(usize, -slot1)]); | ||
| 454 | } | ||
| 455 | const slot2 = e2[pos]; | ||
| 456 | if (slot2 > 0) { | ||
| 457 | q = q.add(pc2[@intCast(usize, slot2)]); | ||
| 458 | } else if (slot2 < 0) { | ||
| 459 | q = q.sub(pc2[@intCast(usize, -slot2)]); | ||
| 460 | } | ||
| 461 | if (pos == 0) break; | ||
| 462 | q = q.dbl().dbl().dbl().dbl(); | ||
| 463 | } | ||
| 464 | try q.rejectIdentity(); | ||
| 465 | return q; | ||
| 425 | } | 466 | } |
| 426 | }; | 467 | }; |
| 427 | 468 |
lib/std/crypto/pcurves/p256/p256_64.zig+40-51| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | // Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --no-prefix-fiat --package-name p256 '' 64 '2^256 - 2^224 + 2^192 + 2^96 - 1' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp | 1 | // Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --public-type-case UpperCamelCase --private-type-case UpperCamelCase --no-prefix-fiat --package-name p256 '' 64 '2^256 - 2^224 + 2^192 + 2^96 - 1' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp |
| 2 | // curve description (via package name): p256 | 2 | // curve description (via package name): p256 |
| 3 | // machine_wordsize = 64 (from "64") | 3 | // machine_wordsize = 64 (from "64") |
| 4 | // requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp | 4 | // requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp |
| ... | @@ -12,18 +12,25 @@ | ... | @@ -12,18 +12,25 @@ |
| 12 | // return values. | 12 | // return values. |
| 13 | // | 13 | // |
| 14 | // Computed values: | 14 | // Computed values: |
| 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) | 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) |
| 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) | 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) |
| 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in | 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in |
| 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 | 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 |
| 19 | 19 | ||
| 20 | const std = @import("std"); | 20 | const std = @import("std"); |
| 21 | const cast = std.meta.cast; | 21 | const cast = std.meta.cast; |
| 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels | 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels |
| 23 | 23 | ||
| 24 | pub const Limbs = [4]u64; | 24 | // The type MontgomeryDomainFieldElement is a field element in the Montgomery domain. |
| 25 | // Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 26 | pub const MontgomeryDomainFieldElement = [4]u64; | ||
| 27 | |||
| 28 | // The type NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. | ||
| 29 | // Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 30 | pub const NonMontgomeryDomainFieldElement = [4]u64; | ||
| 25 | 31 | ||
| 26 | /// The function addcarryxU64 is an addition with carry. | 32 | /// The function addcarryxU64 is an addition with carry. |
| 33 | /// | ||
| 27 | /// Postconditions: | 34 | /// Postconditions: |
| 28 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 | 35 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 |
| 29 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ | 36 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ |
| ... | @@ -45,6 +52,7 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo | ... | @@ -45,6 +52,7 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | /// The function subborrowxU64 is a subtraction with borrow. | 54 | /// The function subborrowxU64 is a subtraction with borrow. |
| 55 | /// | ||
| 48 | /// Postconditions: | 56 | /// Postconditions: |
| 49 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 | 57 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 |
| 50 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ | 58 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ |
| ... | @@ -66,6 +74,7 @@ inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) v | ... | @@ -66,6 +74,7 @@ inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) v |
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | /// The function mulxU64 is a multiplication, returning the full double-width result. | 76 | /// The function mulxU64 is a multiplication, returning the full double-width result. |
| 77 | /// | ||
| 69 | /// Postconditions: | 78 | /// Postconditions: |
| 70 | /// out1 = (arg1 * arg2) mod 2^64 | 79 | /// out1 = (arg1 * arg2) mod 2^64 |
| 71 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ | 80 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ |
| ... | @@ -85,6 +94,7 @@ inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { | ... | @@ -85,6 +94,7 @@ inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 85 | } | 94 | } |
| 86 | 95 | ||
| 87 | /// The function cmovznzU64 is a single-word conditional move. | 96 | /// The function cmovznzU64 is a single-word conditional move. |
| 97 | /// | ||
| 88 | /// Postconditions: | 98 | /// Postconditions: |
| 89 | /// out1 = (if arg1 = 0 then arg2 else arg3) | 99 | /// out1 = (if arg1 = 0 then arg2 else arg3) |
| 90 | /// | 100 | /// |
| ... | @@ -102,6 +112,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { | ... | @@ -102,6 +112,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 102 | } | 112 | } |
| 103 | 113 | ||
| 104 | /// The function mul multiplies two field elements in the Montgomery domain. | 114 | /// The function mul multiplies two field elements in the Montgomery domain. |
| 115 | /// | ||
| 105 | /// Preconditions: | 116 | /// Preconditions: |
| 106 | /// 0 ≤ eval arg1 < m | 117 | /// 0 ≤ eval arg1 < m |
| 107 | /// 0 ≤ eval arg2 < m | 118 | /// 0 ≤ eval arg2 < m |
| ... | @@ -109,12 +120,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { | ... | @@ -109,12 +120,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 109 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m | 120 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m |
| 110 | /// 0 ≤ eval out1 < m | 121 | /// 0 ≤ eval out1 < m |
| 111 | /// | 122 | /// |
| 112 | /// Input Bounds: | 123 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 113 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 114 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 115 | /// Output Bounds: | ||
| 116 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 117 | pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 118 | @setRuntimeSafety(mode == .Debug); | 124 | @setRuntimeSafety(mode == .Debug); |
| 119 | 125 | ||
| 120 | const x1 = (arg1[1]); | 126 | const x1 = (arg1[1]); |
| ... | @@ -399,17 +405,14 @@ pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -399,17 +405,14 @@ pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 399 | } | 405 | } |
| 400 | 406 | ||
| 401 | /// The function square squares a field element in the Montgomery domain. | 407 | /// The function square squares a field element in the Montgomery domain. |
| 408 | /// | ||
| 402 | /// Preconditions: | 409 | /// Preconditions: |
| 403 | /// 0 ≤ eval arg1 < m | 410 | /// 0 ≤ eval arg1 < m |
| 404 | /// Postconditions: | 411 | /// Postconditions: |
| 405 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m | 412 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m |
| 406 | /// 0 ≤ eval out1 < m | 413 | /// 0 ≤ eval out1 < m |
| 407 | /// | 414 | /// |
| 408 | /// Input Bounds: | 415 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 409 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 410 | /// Output Bounds: | ||
| 411 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 412 | pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ||
| 413 | @setRuntimeSafety(mode == .Debug); | 416 | @setRuntimeSafety(mode == .Debug); |
| 414 | 417 | ||
| 415 | const x1 = (arg1[1]); | 418 | const x1 = (arg1[1]); |
| ... | @@ -694,6 +697,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -694,6 +697,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { |
| 694 | } | 697 | } |
| 695 | 698 | ||
| 696 | /// The function add adds two field elements in the Montgomery domain. | 699 | /// The function add adds two field elements in the Montgomery domain. |
| 700 | /// | ||
| 697 | /// Preconditions: | 701 | /// Preconditions: |
| 698 | /// 0 ≤ eval arg1 < m | 702 | /// 0 ≤ eval arg1 < m |
| 699 | /// 0 ≤ eval arg2 < m | 703 | /// 0 ≤ eval arg2 < m |
| ... | @@ -701,12 +705,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -701,12 +705,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { |
| 701 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m | 705 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m |
| 702 | /// 0 ≤ eval out1 < m | 706 | /// 0 ≤ eval out1 < m |
| 703 | /// | 707 | /// |
| 704 | /// Input Bounds: | 708 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 705 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 706 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 707 | /// Output Bounds: | ||
| 708 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 709 | pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 710 | @setRuntimeSafety(mode == .Debug); | 709 | @setRuntimeSafety(mode == .Debug); |
| 711 | 710 | ||
| 712 | var x1: u64 = undefined; | 711 | var x1: u64 = undefined; |
| ... | @@ -751,6 +750,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -751,6 +750,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 751 | } | 750 | } |
| 752 | 751 | ||
| 753 | /// The function sub subtracts two field elements in the Montgomery domain. | 752 | /// The function sub subtracts two field elements in the Montgomery domain. |
| 753 | /// | ||
| 754 | /// Preconditions: | 754 | /// Preconditions: |
| 755 | /// 0 ≤ eval arg1 < m | 755 | /// 0 ≤ eval arg1 < m |
| 756 | /// 0 ≤ eval arg2 < m | 756 | /// 0 ≤ eval arg2 < m |
| ... | @@ -758,12 +758,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -758,12 +758,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 758 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m | 758 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m |
| 759 | /// 0 ≤ eval out1 < m | 759 | /// 0 ≤ eval out1 < m |
| 760 | /// | 760 | /// |
| 761 | /// Input Bounds: | 761 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 762 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 763 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 764 | /// Output Bounds: | ||
| 765 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 766 | pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 767 | @setRuntimeSafety(mode == .Debug); | 762 | @setRuntimeSafety(mode == .Debug); |
| 768 | 763 | ||
| 769 | var x1: u64 = undefined; | 764 | var x1: u64 = undefined; |
| ... | @@ -799,17 +794,14 @@ pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -799,17 +794,14 @@ pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 799 | } | 794 | } |
| 800 | 795 | ||
| 801 | /// The function opp negates a field element in the Montgomery domain. | 796 | /// The function opp negates a field element in the Montgomery domain. |
| 797 | /// | ||
| 802 | /// Preconditions: | 798 | /// Preconditions: |
| 803 | /// 0 ≤ eval arg1 < m | 799 | /// 0 ≤ eval arg1 < m |
| 804 | /// Postconditions: | 800 | /// Postconditions: |
| 805 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m | 801 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m |
| 806 | /// 0 ≤ eval out1 < m | 802 | /// 0 ≤ eval out1 < m |
| 807 | /// | 803 | /// |
| 808 | /// Input Bounds: | 804 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 809 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 810 | /// Output Bounds: | ||
| 811 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 812 | pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ||
| 813 | @setRuntimeSafety(mode == .Debug); | 805 | @setRuntimeSafety(mode == .Debug); |
| 814 | 806 | ||
| 815 | var x1: u64 = undefined; | 807 | var x1: u64 = undefined; |
| ... | @@ -845,17 +837,14 @@ pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -845,17 +837,14 @@ pub fn opp(out1: *[4]u64, arg1: [4]u64) void { |
| 845 | } | 837 | } |
| 846 | 838 | ||
| 847 | /// The function fromMontgomery translates a field element out of the Montgomery domain. | 839 | /// The function fromMontgomery translates a field element out of the Montgomery domain. |
| 840 | /// | ||
| 848 | /// Preconditions: | 841 | /// Preconditions: |
| 849 | /// 0 ≤ eval arg1 < m | 842 | /// 0 ≤ eval arg1 < m |
| 850 | /// Postconditions: | 843 | /// Postconditions: |
| 851 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m | 844 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m |
| 852 | /// 0 ≤ eval out1 < m | 845 | /// 0 ≤ eval out1 < m |
| 853 | /// | 846 | /// |
| 854 | /// Input Bounds: | 847 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 855 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 856 | /// Output Bounds: | ||
| 857 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 858 | pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 859 | @setRuntimeSafety(mode == .Debug); | 848 | @setRuntimeSafety(mode == .Debug); |
| 860 | 849 | ||
| 861 | const x1 = (arg1[0]); | 850 | const x1 = (arg1[0]); |
| ... | @@ -1001,17 +990,14 @@ pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -1001,17 +990,14 @@ pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { |
| 1001 | } | 990 | } |
| 1002 | 991 | ||
| 1003 | /// The function toMontgomery translates a field element into the Montgomery domain. | 992 | /// The function toMontgomery translates a field element into the Montgomery domain. |
| 993 | /// | ||
| 1004 | /// Preconditions: | 994 | /// Preconditions: |
| 1005 | /// 0 ≤ eval arg1 < m | 995 | /// 0 ≤ eval arg1 < m |
| 1006 | /// Postconditions: | 996 | /// Postconditions: |
| 1007 | /// eval (from_montgomery out1) mod m = eval arg1 mod m | 997 | /// eval (from_montgomery out1) mod m = eval arg1 mod m |
| 1008 | /// 0 ≤ eval out1 < m | 998 | /// 0 ≤ eval out1 < m |
| 1009 | /// | 999 | /// |
| 1010 | /// Input Bounds: | 1000 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1011 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1012 | /// Output Bounds: | ||
| 1013 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1014 | pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 1015 | @setRuntimeSafety(mode == .Debug); | 1001 | @setRuntimeSafety(mode == .Debug); |
| 1016 | 1002 | ||
| 1017 | const x1 = (arg1[1]); | 1003 | const x1 = (arg1[1]); |
| ... | @@ -1276,6 +1262,7 @@ pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -1276,6 +1262,7 @@ pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { |
| 1276 | } | 1262 | } |
| 1277 | 1263 | ||
| 1278 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. | 1264 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. |
| 1265 | /// | ||
| 1279 | /// Preconditions: | 1266 | /// Preconditions: |
| 1280 | /// 0 ≤ eval arg1 < m | 1267 | /// 0 ≤ eval arg1 < m |
| 1281 | /// Postconditions: | 1268 | /// Postconditions: |
| ... | @@ -1293,6 +1280,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { | ... | @@ -1293,6 +1280,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1293 | } | 1280 | } |
| 1294 | 1281 | ||
| 1295 | /// The function selectznz is a multi-limb conditional select. | 1282 | /// The function selectznz is a multi-limb conditional select. |
| 1283 | /// | ||
| 1296 | /// Postconditions: | 1284 | /// Postconditions: |
| 1297 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) | 1285 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) |
| 1298 | /// | 1286 | /// |
| ... | @@ -1320,6 +1308,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { | ... | @@ -1320,6 +1308,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1320 | } | 1308 | } |
| 1321 | 1309 | ||
| 1322 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. | 1310 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. |
| 1311 | /// | ||
| 1323 | /// Preconditions: | 1312 | /// Preconditions: |
| 1324 | /// 0 ≤ eval arg1 < m | 1313 | /// 0 ≤ eval arg1 < m |
| 1325 | /// Postconditions: | 1314 | /// Postconditions: |
| ... | @@ -1427,6 +1416,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { | ... | @@ -1427,6 +1416,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1427 | } | 1416 | } |
| 1428 | 1417 | ||
| 1429 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. | 1418 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. |
| 1419 | /// | ||
| 1430 | /// Preconditions: | 1420 | /// Preconditions: |
| 1431 | /// 0 ≤ bytes_eval arg1 < m | 1421 | /// 0 ≤ bytes_eval arg1 < m |
| 1432 | /// Postconditions: | 1422 | /// Postconditions: |
| ... | @@ -1507,14 +1497,12 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { | ... | @@ -1507,14 +1497,12 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1507 | } | 1497 | } |
| 1508 | 1498 | ||
| 1509 | /// The function setOne returns the field element one in the Montgomery domain. | 1499 | /// The function setOne returns the field element one in the Montgomery domain. |
| 1500 | /// | ||
| 1510 | /// Postconditions: | 1501 | /// Postconditions: |
| 1511 | /// eval (from_montgomery out1) mod m = 1 mod m | 1502 | /// eval (from_montgomery out1) mod m = 1 mod m |
| 1512 | /// 0 ≤ eval out1 < m | 1503 | /// 0 ≤ eval out1 < m |
| 1513 | /// | 1504 | /// |
| 1514 | /// Input Bounds: | 1505 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1515 | /// Output Bounds: | ||
| 1516 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1517 | pub fn setOne(out1: *[4]u64) void { | ||
| 1518 | @setRuntimeSafety(mode == .Debug); | 1506 | @setRuntimeSafety(mode == .Debug); |
| 1519 | 1507 | ||
| 1520 | out1[0] = cast(u64, 0x1); | 1508 | out1[0] = cast(u64, 0x1); |
| ... | @@ -1524,11 +1512,11 @@ pub fn setOne(out1: *[4]u64) void { | ... | @@ -1524,11 +1512,11 @@ pub fn setOne(out1: *[4]u64) void { |
| 1524 | } | 1512 | } |
| 1525 | 1513 | ||
| 1526 | /// The function msat returns the saturated representation of the prime modulus. | 1514 | /// The function msat returns the saturated representation of the prime modulus. |
| 1515 | /// | ||
| 1527 | /// Postconditions: | 1516 | /// Postconditions: |
| 1528 | /// twos_complement_eval out1 = m | 1517 | /// twos_complement_eval out1 = m |
| 1529 | /// 0 ≤ eval out1 < m | 1518 | /// 0 ≤ eval out1 < m |
| 1530 | /// | 1519 | /// |
| 1531 | /// Input Bounds: | ||
| 1532 | /// Output Bounds: | 1520 | /// Output Bounds: |
| 1533 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | 1521 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1534 | pub fn msat(out1: *[5]u64) void { | 1522 | pub fn msat(out1: *[5]u64) void { |
| ... | @@ -1542,6 +1530,7 @@ pub fn msat(out1: *[5]u64) void { | ... | @@ -1542,6 +1530,7 @@ pub fn msat(out1: *[5]u64) void { |
| 1542 | } | 1530 | } |
| 1543 | 1531 | ||
| 1544 | /// The function divstep computes a divstep. | 1532 | /// The function divstep computes a divstep. |
| 1533 | /// | ||
| 1545 | /// Preconditions: | 1534 | /// Preconditions: |
| 1546 | /// 0 ≤ eval arg4 < m | 1535 | /// 0 ≤ eval arg4 < m |
| 1547 | /// 0 ≤ eval arg5 < m | 1536 | /// 0 ≤ eval arg5 < m |
| ... | @@ -1795,11 +1784,11 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ | ... | @@ -1795,11 +1784,11 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ |
| 1795 | } | 1784 | } |
| 1796 | 1785 | ||
| 1797 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). | 1786 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). |
| 1787 | /// | ||
| 1798 | /// Postconditions: | 1788 | /// Postconditions: |
| 1799 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if (log2 m) + 1 < 46 then ⌊(49 * ((log2 m) + 1) + 80) / 17⌋ else ⌊(49 * ((log2 m) + 1) + 57) / 17⌋) | 1789 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if ⌊log2 m⌋ + 1 < 46 then ⌊(49 * (⌊log2 m⌋ + 1) + 80) / 17⌋ else ⌊(49 * (⌊log2 m⌋ + 1) + 57) / 17⌋) |
| 1800 | /// 0 ≤ eval out1 < m | 1790 | /// 0 ≤ eval out1 < m |
| 1801 | /// | 1791 | /// |
| 1802 | /// Input Bounds: | ||
| 1803 | /// Output Bounds: | 1792 | /// Output Bounds: |
| 1804 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | 1793 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1805 | pub fn divstepPrecomp(out1: *[4]u64) void { | 1794 | pub fn divstepPrecomp(out1: *[4]u64) void { |
lib/std/crypto/pcurves/p256/p256_scalar_64.zig+56-67| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --no-prefix-fiat --package-name p256-scalar '' 64 115792089210356248762697446949407573529996955224135760342422259061068512044369 | 1 | // Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --public-type-case UpperCamelCase --private-type-case UpperCamelCase --no-prefix-fiat --package-name p256-scalar '' 64 115792089210356248762697446949407573529996955224135760342422259061068512044369 mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp |
| 2 | // curve description (via package name): p256-scalar | 2 | // curve description (via package name): p256-scalar |
| 3 | // machine_wordsize = 64 (from "64") | 3 | // machine_wordsize = 64 (from "64") |
| 4 | // requested operations: (all) | 4 | // requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp |
| 5 | // m = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 (from "115792089210356248762697446949407573529996955224135760342422259061068512044369") | 5 | // m = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 (from "115792089210356248762697446949407573529996955224135760342422259061068512044369") |
| 6 | // | 6 | // |
| 7 | // NOTE: In addition to the bounds specified above each function, all | 7 | // NOTE: In addition to the bounds specified above each function, all |
| ... | @@ -12,18 +12,25 @@ | ... | @@ -12,18 +12,25 @@ |
| 12 | // return values. | 12 | // return values. |
| 13 | // | 13 | // |
| 14 | // Computed values: | 14 | // Computed values: |
| 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) | 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) |
| 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) | 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) |
| 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in | 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in |
| 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 | 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 |
| 19 | 19 | ||
| 20 | const std = @import("std"); | 20 | const std = @import("std"); |
| 21 | const cast = std.meta.cast; | 21 | const cast = std.meta.cast; |
| 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels | 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels |
| 23 | 23 | ||
| 24 | pub const Limbs = [4]u64; | 24 | // The type MontgomeryDomainFieldElement is a field element in the Montgomery domain. |
| 25 | // Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 26 | pub const MontgomeryDomainFieldElement = [4]u64; | ||
| 27 | |||
| 28 | // The type NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. | ||
| 29 | // Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 30 | pub const NonMontgomeryDomainFieldElement = [4]u64; | ||
| 25 | 31 | ||
| 26 | /// The function addcarryxU64 is an addition with carry. | 32 | /// The function addcarryxU64 is an addition with carry. |
| 33 | /// | ||
| 27 | /// Postconditions: | 34 | /// Postconditions: |
| 28 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 | 35 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 |
| 29 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ | 36 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ |
| ... | @@ -45,6 +52,7 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo | ... | @@ -45,6 +52,7 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | /// The function subborrowxU64 is a subtraction with borrow. | 54 | /// The function subborrowxU64 is a subtraction with borrow. |
| 55 | /// | ||
| 48 | /// Postconditions: | 56 | /// Postconditions: |
| 49 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 | 57 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 |
| 50 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ | 58 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ |
| ... | @@ -66,6 +74,7 @@ inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) v | ... | @@ -66,6 +74,7 @@ inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) v |
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | /// The function mulxU64 is a multiplication, returning the full double-width result. | 76 | /// The function mulxU64 is a multiplication, returning the full double-width result. |
| 77 | /// | ||
| 69 | /// Postconditions: | 78 | /// Postconditions: |
| 70 | /// out1 = (arg1 * arg2) mod 2^64 | 79 | /// out1 = (arg1 * arg2) mod 2^64 |
| 71 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ | 80 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ |
| ... | @@ -85,6 +94,7 @@ inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { | ... | @@ -85,6 +94,7 @@ inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 85 | } | 94 | } |
| 86 | 95 | ||
| 87 | /// The function cmovznzU64 is a single-word conditional move. | 96 | /// The function cmovznzU64 is a single-word conditional move. |
| 97 | /// | ||
| 88 | /// Postconditions: | 98 | /// Postconditions: |
| 89 | /// out1 = (if arg1 = 0 then arg2 else arg3) | 99 | /// out1 = (if arg1 = 0 then arg2 else arg3) |
| 90 | /// | 100 | /// |
| ... | @@ -102,6 +112,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { | ... | @@ -102,6 +112,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 102 | } | 112 | } |
| 103 | 113 | ||
| 104 | /// The function mul multiplies two field elements in the Montgomery domain. | 114 | /// The function mul multiplies two field elements in the Montgomery domain. |
| 115 | /// | ||
| 105 | /// Preconditions: | 116 | /// Preconditions: |
| 106 | /// 0 ≤ eval arg1 < m | 117 | /// 0 ≤ eval arg1 < m |
| 107 | /// 0 ≤ eval arg2 < m | 118 | /// 0 ≤ eval arg2 < m |
| ... | @@ -109,12 +120,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { | ... | @@ -109,12 +120,7 @@ inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 109 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m | 120 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m |
| 110 | /// 0 ≤ eval out1 < m | 121 | /// 0 ≤ eval out1 < m |
| 111 | /// | 122 | /// |
| 112 | /// Input Bounds: | 123 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 113 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 114 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 115 | /// Output Bounds: | ||
| 116 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 117 | pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 118 | @setRuntimeSafety(mode == .Debug); | 124 | @setRuntimeSafety(mode == .Debug); |
| 119 | 125 | ||
| 120 | const x1 = (arg1[1]); | 126 | const x1 = (arg1[1]); |
| ... | @@ -447,17 +453,14 @@ pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -447,17 +453,14 @@ pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 447 | } | 453 | } |
| 448 | 454 | ||
| 449 | /// The function square squares a field element in the Montgomery domain. | 455 | /// The function square squares a field element in the Montgomery domain. |
| 456 | /// | ||
| 450 | /// Preconditions: | 457 | /// Preconditions: |
| 451 | /// 0 ≤ eval arg1 < m | 458 | /// 0 ≤ eval arg1 < m |
| 452 | /// Postconditions: | 459 | /// Postconditions: |
| 453 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m | 460 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m |
| 454 | /// 0 ≤ eval out1 < m | 461 | /// 0 ≤ eval out1 < m |
| 455 | /// | 462 | /// |
| 456 | /// Input Bounds: | 463 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 457 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 458 | /// Output Bounds: | ||
| 459 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 460 | pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ||
| 461 | @setRuntimeSafety(mode == .Debug); | 464 | @setRuntimeSafety(mode == .Debug); |
| 462 | 465 | ||
| 463 | const x1 = (arg1[1]); | 466 | const x1 = (arg1[1]); |
| ... | @@ -790,6 +793,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -790,6 +793,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { |
| 790 | } | 793 | } |
| 791 | 794 | ||
| 792 | /// The function add adds two field elements in the Montgomery domain. | 795 | /// The function add adds two field elements in the Montgomery domain. |
| 796 | /// | ||
| 793 | /// Preconditions: | 797 | /// Preconditions: |
| 794 | /// 0 ≤ eval arg1 < m | 798 | /// 0 ≤ eval arg1 < m |
| 795 | /// 0 ≤ eval arg2 < m | 799 | /// 0 ≤ eval arg2 < m |
| ... | @@ -797,12 +801,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -797,12 +801,7 @@ pub fn square(out1: *[4]u64, arg1: [4]u64) void { |
| 797 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m | 801 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m |
| 798 | /// 0 ≤ eval out1 < m | 802 | /// 0 ≤ eval out1 < m |
| 799 | /// | 803 | /// |
| 800 | /// Input Bounds: | 804 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 801 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 802 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 803 | /// Output Bounds: | ||
| 804 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 805 | pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 806 | @setRuntimeSafety(mode == .Debug); | 805 | @setRuntimeSafety(mode == .Debug); |
| 807 | 806 | ||
| 808 | var x1: u64 = undefined; | 807 | var x1: u64 = undefined; |
| ... | @@ -847,6 +846,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -847,6 +846,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 847 | } | 846 | } |
| 848 | 847 | ||
| 849 | /// The function sub subtracts two field elements in the Montgomery domain. | 848 | /// The function sub subtracts two field elements in the Montgomery domain. |
| 849 | /// | ||
| 850 | /// Preconditions: | 850 | /// Preconditions: |
| 851 | /// 0 ≤ eval arg1 < m | 851 | /// 0 ≤ eval arg1 < m |
| 852 | /// 0 ≤ eval arg2 < m | 852 | /// 0 ≤ eval arg2 < m |
| ... | @@ -854,12 +854,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -854,12 +854,7 @@ pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 854 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m | 854 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m |
| 855 | /// 0 ≤ eval out1 < m | 855 | /// 0 ≤ eval out1 < m |
| 856 | /// | 856 | /// |
| 857 | /// Input Bounds: | 857 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 858 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 859 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 860 | /// Output Bounds: | ||
| 861 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 862 | pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 863 | @setRuntimeSafety(mode == .Debug); | 858 | @setRuntimeSafety(mode == .Debug); |
| 864 | 859 | ||
| 865 | var x1: u64 = undefined; | 860 | var x1: u64 = undefined; |
| ... | @@ -895,17 +890,14 @@ pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ... | @@ -895,17 +890,14 @@ pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { |
| 895 | } | 890 | } |
| 896 | 891 | ||
| 897 | /// The function opp negates a field element in the Montgomery domain. | 892 | /// The function opp negates a field element in the Montgomery domain. |
| 893 | /// | ||
| 898 | /// Preconditions: | 894 | /// Preconditions: |
| 899 | /// 0 ≤ eval arg1 < m | 895 | /// 0 ≤ eval arg1 < m |
| 900 | /// Postconditions: | 896 | /// Postconditions: |
| 901 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m | 897 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m |
| 902 | /// 0 ≤ eval out1 < m | 898 | /// 0 ≤ eval out1 < m |
| 903 | /// | 899 | /// |
| 904 | /// Input Bounds: | 900 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 905 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 906 | /// Output Bounds: | ||
| 907 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 908 | pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ||
| 909 | @setRuntimeSafety(mode == .Debug); | 901 | @setRuntimeSafety(mode == .Debug); |
| 910 | 902 | ||
| 911 | var x1: u64 = undefined; | 903 | var x1: u64 = undefined; |
| ... | @@ -941,17 +933,14 @@ pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -941,17 +933,14 @@ pub fn opp(out1: *[4]u64, arg1: [4]u64) void { |
| 941 | } | 933 | } |
| 942 | 934 | ||
| 943 | /// The function fromMontgomery translates a field element out of the Montgomery domain. | 935 | /// The function fromMontgomery translates a field element out of the Montgomery domain. |
| 936 | /// | ||
| 944 | /// Preconditions: | 937 | /// Preconditions: |
| 945 | /// 0 ≤ eval arg1 < m | 938 | /// 0 ≤ eval arg1 < m |
| 946 | /// Postconditions: | 939 | /// Postconditions: |
| 947 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m | 940 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m |
| 948 | /// 0 ≤ eval out1 < m | 941 | /// 0 ≤ eval out1 < m |
| 949 | /// | 942 | /// |
| 950 | /// Input Bounds: | 943 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 951 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 952 | /// Output Bounds: | ||
| 953 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 954 | pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 955 | @setRuntimeSafety(mode == .Debug); | 944 | @setRuntimeSafety(mode == .Debug); |
| 956 | 945 | ||
| 957 | const x1 = (arg1[0]); | 946 | const x1 = (arg1[0]); |
| ... | @@ -1157,17 +1146,14 @@ pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -1157,17 +1146,14 @@ pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { |
| 1157 | } | 1146 | } |
| 1158 | 1147 | ||
| 1159 | /// The function toMontgomery translates a field element into the Montgomery domain. | 1148 | /// The function toMontgomery translates a field element into the Montgomery domain. |
| 1149 | /// | ||
| 1160 | /// Preconditions: | 1150 | /// Preconditions: |
| 1161 | /// 0 ≤ eval arg1 < m | 1151 | /// 0 ≤ eval arg1 < m |
| 1162 | /// Postconditions: | 1152 | /// Postconditions: |
| 1163 | /// eval (from_montgomery out1) mod m = eval arg1 mod m | 1153 | /// eval (from_montgomery out1) mod m = eval arg1 mod m |
| 1164 | /// 0 ≤ eval out1 < m | 1154 | /// 0 ≤ eval out1 < m |
| 1165 | /// | 1155 | /// |
| 1166 | /// Input Bounds: | 1156 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1167 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1168 | /// Output Bounds: | ||
| 1169 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1170 | pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 1171 | @setRuntimeSafety(mode == .Debug); | 1157 | @setRuntimeSafety(mode == .Debug); |
| 1172 | 1158 | ||
| 1173 | const x1 = (arg1[1]); | 1159 | const x1 = (arg1[1]); |
| ... | @@ -1480,6 +1466,7 @@ pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ... | @@ -1480,6 +1466,7 @@ pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { |
| 1480 | } | 1466 | } |
| 1481 | 1467 | ||
| 1482 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. | 1468 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. |
| 1469 | /// | ||
| 1483 | /// Preconditions: | 1470 | /// Preconditions: |
| 1484 | /// 0 ≤ eval arg1 < m | 1471 | /// 0 ≤ eval arg1 < m |
| 1485 | /// Postconditions: | 1472 | /// Postconditions: |
| ... | @@ -1497,6 +1484,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { | ... | @@ -1497,6 +1484,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1497 | } | 1484 | } |
| 1498 | 1485 | ||
| 1499 | /// The function selectznz is a multi-limb conditional select. | 1486 | /// The function selectznz is a multi-limb conditional select. |
| 1487 | /// | ||
| 1500 | /// Postconditions: | 1488 | /// Postconditions: |
| 1501 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) | 1489 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) |
| 1502 | /// | 1490 | /// |
| ... | @@ -1524,6 +1512,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { | ... | @@ -1524,6 +1512,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1524 | } | 1512 | } |
| 1525 | 1513 | ||
| 1526 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. | 1514 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. |
| 1515 | /// | ||
| 1527 | /// Preconditions: | 1516 | /// Preconditions: |
| 1528 | /// 0 ≤ eval arg1 < m | 1517 | /// 0 ≤ eval arg1 < m |
| 1529 | /// Postconditions: | 1518 | /// Postconditions: |
| ... | @@ -1631,6 +1620,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { | ... | @@ -1631,6 +1620,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1631 | } | 1620 | } |
| 1632 | 1621 | ||
| 1633 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. | 1622 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. |
| 1623 | /// | ||
| 1634 | /// Preconditions: | 1624 | /// Preconditions: |
| 1635 | /// 0 ≤ bytes_eval arg1 < m | 1625 | /// 0 ≤ bytes_eval arg1 < m |
| 1636 | /// Postconditions: | 1626 | /// Postconditions: |
| ... | @@ -1711,14 +1701,12 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { | ... | @@ -1711,14 +1701,12 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1711 | } | 1701 | } |
| 1712 | 1702 | ||
| 1713 | /// The function setOne returns the field element one in the Montgomery domain. | 1703 | /// The function setOne returns the field element one in the Montgomery domain. |
| 1704 | /// | ||
| 1714 | /// Postconditions: | 1705 | /// Postconditions: |
| 1715 | /// eval (from_montgomery out1) mod m = 1 mod m | 1706 | /// eval (from_montgomery out1) mod m = 1 mod m |
| 1716 | /// 0 ≤ eval out1 < m | 1707 | /// 0 ≤ eval out1 < m |
| 1717 | /// | 1708 | /// |
| 1718 | /// Input Bounds: | 1709 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1719 | /// Output Bounds: | ||
| 1720 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1721 | pub fn setOne(out1: *[4]u64) void { | ||
| 1722 | @setRuntimeSafety(mode == .Debug); | 1710 | @setRuntimeSafety(mode == .Debug); |
| 1723 | 1711 | ||
| 1724 | out1[0] = 0xc46353d039cdaaf; | 1712 | out1[0] = 0xc46353d039cdaaf; |
| ... | @@ -1728,11 +1716,11 @@ pub fn setOne(out1: *[4]u64) void { | ... | @@ -1728,11 +1716,11 @@ pub fn setOne(out1: *[4]u64) void { |
| 1728 | } | 1716 | } |
| 1729 | 1717 | ||
| 1730 | /// The function msat returns the saturated representation of the prime modulus. | 1718 | /// The function msat returns the saturated representation of the prime modulus. |
| 1719 | /// | ||
| 1731 | /// Postconditions: | 1720 | /// Postconditions: |
| 1732 | /// twos_complement_eval out1 = m | 1721 | /// twos_complement_eval out1 = m |
| 1733 | /// 0 ≤ eval out1 < m | 1722 | /// 0 ≤ eval out1 < m |
| 1734 | /// | 1723 | /// |
| 1735 | /// Input Bounds: | ||
| 1736 | /// Output Bounds: | 1724 | /// Output Bounds: |
| 1737 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | 1725 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1738 | pub fn msat(out1: *[5]u64) void { | 1726 | pub fn msat(out1: *[5]u64) void { |
| ... | @@ -1745,24 +1733,8 @@ pub fn msat(out1: *[5]u64) void { | ... | @@ -1745,24 +1733,8 @@ pub fn msat(out1: *[5]u64) void { |
| 1745 | out1[4] = cast(u64, 0x0); | 1733 | out1[4] = cast(u64, 0x0); |
| 1746 | } | 1734 | } |
| 1747 | 1735 | ||
| 1748 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). | ||
| 1749 | /// Postconditions: | ||
| 1750 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if (log2 m) + 1 < 46 then ⌊(49 * ((log2 m) + 1) + 80) / 17⌋ else ⌊(49 * ((log2 m) + 1) + 57) / 17⌋) | ||
| 1751 | /// 0 ≤ eval out1 < m | ||
| 1752 | /// | ||
| 1753 | /// Input Bounds: | ||
| 1754 | /// Output Bounds: | ||
| 1755 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1756 | pub fn divstepPrecomp(out1: *[4]u64) void { | ||
| 1757 | @setRuntimeSafety(mode == .Debug); | ||
| 1758 | |||
| 1759 | out1[0] = 0xd739262fb7fcfbb5; | ||
| 1760 | out1[1] = 0x8ac6f75d20074414; | ||
| 1761 | out1[2] = 0xc67428bfb5e3c256; | ||
| 1762 | out1[3] = 0x444962f2eda7aedf; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | /// The function divstep computes a divstep. | 1736 | /// The function divstep computes a divstep. |
| 1737 | /// | ||
| 1766 | /// Preconditions: | 1738 | /// Preconditions: |
| 1767 | /// 0 ≤ eval arg4 < m | 1739 | /// 0 ≤ eval arg4 < m |
| 1768 | /// 0 ≤ eval arg5 < m | 1740 | /// 0 ≤ eval arg5 < m |
| ... | @@ -2014,3 +1986,20 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ | ... | @@ -2014,3 +1986,20 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ |
| 2014 | out5[2] = x125; | 1986 | out5[2] = x125; |
| 2015 | out5[3] = x126; | 1987 | out5[3] = x126; |
| 2016 | } | 1988 | } |
| 1989 | |||
| 1990 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). | ||
| 1991 | /// | ||
| 1992 | /// Postconditions: | ||
| 1993 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if ⌊log2 m⌋ + 1 < 46 then ⌊(49 * (⌊log2 m⌋ + 1) + 80) / 17⌋ else ⌊(49 * (⌊log2 m⌋ + 1) + 57) / 17⌋) | ||
| 1994 | /// 0 ≤ eval out1 < m | ||
| 1995 | /// | ||
| 1996 | /// Output Bounds: | ||
| 1997 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1998 | pub fn divstepPrecomp(out1: *[4]u64) void { | ||
| 1999 | @setRuntimeSafety(mode == .Debug); | ||
| 2000 | |||
| 2001 | out1[0] = 0xd739262fb7fcfbb5; | ||
| 2002 | out1[1] = 0x8ac6f75d20074414; | ||
| 2003 | out1[2] = 0xc67428bfb5e3c256; | ||
| 2004 | out1[3] = 0x444962f2eda7aedf; | ||
| 2005 | } |
lib/std/crypto/pcurves/tests.zig+10| ... | @@ -107,3 +107,13 @@ test "p256 neutral element decoding" { | ... | @@ -107,3 +107,13 @@ test "p256 neutral element decoding" { |
| 107 | const p = try P256.fromAffineCoordinates(.{ .x = P256.Fe.zero, .y = P256.Fe.one }); | 107 | const p = try P256.fromAffineCoordinates(.{ .x = P256.Fe.zero, .y = P256.Fe.one }); |
| 108 | try testing.expectError(error.IdentityElement, p.rejectIdentity()); | 108 | try testing.expectError(error.IdentityElement, p.rejectIdentity()); |
| 109 | } | 109 | } |
| 110 | |||
| 111 | test "p256 double base multiplication" { | ||
| 112 | const p1 = P256.basePoint; | ||
| 113 | const p2 = P256.basePoint.dbl(); | ||
| 114 | const s1 = [_]u8{0x01} ** 32; | ||
| 115 | const s2 = [_]u8{0x02} ** 32; | ||
| 116 | const pr1 = try P256.mulDoubleBasePublic(p1, s1, p2, s2, .Little); | ||
| 117 | const pr2 = (try p1.mul(s1, .Little)).add(try p2.mul(s2, .Little)); | ||
| 118 | try testing.expect(pr1.equivalent(pr2)); | ||
| 119 | } |