nx_p384_field_mul_fast_gate.nx source
↩ module page · 75 lines · 2646 B
1// nx_p384_field_mul_fast_gate.nx -- pin p384_field_mul_fast: it MUST equal the
2// trusted bit-by-bit p384_field_mul for the same a*b mod p, across edge + random
3// inputs, before it replaces the slow path in ECDSA-P384 cert verification.
4//
5// expect_exit: 0
6
7import "nx_syscalls.nx"
8import "nx_u384.nx"
9import "nx_u384_mul.nx"
10import "nx_p384_field.nx"
11import "nx_p384_field_mul.nx"
12import "nx_p384_field_mul_fast.nx"
13
14func g_ps(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 }
15func g_pn(v: i64) -> i64 {
16 let b: *u8 = sys_mmap(24)
17 var x: i64 = v
18 if x < 0 { x = 0 - x }
19 var i: i64 = 22
20 if x == 0 { b[i] = 0x30 as u8; i = i - 1 }
21 else { while x > 0 { b[i] = (0x30 + (x - (x/10)*10)) as u8; x = x / 10; i = i - 1 } }
22 sys_write(1, ((b as i64) + i + 1) as *u8, 22 - i)
23 return 0
24}
25
26// pseudo-random 12-word value (full 384-bit range incl. top word).
27func mk(x: *i64, seed: i64) -> i64 {
28 var i: i64 = 0
29 while i < NX_U384_LIMBS {
30 x[i] = ((seed + i * 2654435761) * 1103515245 + 12345) & NX_U384_LIMB_MASK
31 i = i + 1
32 }
33 return 0
34}
35
36func cmp_case(a: *i64, b: *i64, tag: i64) -> i64 {
37 let r1: *i64 = u384_alloc()
38 let r2: *i64 = u384_alloc()
39 p384_field_mul_bitwise(r1, a, b) // bit-by-bit reference
40 p384_field_mul_fast(r2, a, b) // fast fold
41 if u384_eq(r1, r2) == 1 { return 1 }
42 g_ps(" MISMATCH tag=" as *u8, 13); g_pn(tag); g_ps("\n" as *u8, 1)
43 return 0
44}
45
46func main() -> i64 {
47 var pass: i64 = 0
48 var total: i64 = 0
49 let a: *i64 = u384_alloc()
50 let b: *i64 = u384_alloc()
51 let p: *i64 = u384_alloc()
52 p384_field_load_p(p)
53
54 // edge cases
55 u384_zero(a); u384_zero(b); total = total + 1; pass = pass + cmp_case(a, b, 1) // 0*0
56 u384_one(a); u384_copy(b, p); b[0] = (b[0] - 1) & NX_U384_LIMB_MASK
57 total = total + 1; pass = pass + cmp_case(a, b, 2) // 1*(p-1)
58 u384_copy(a, p); a[0] = (a[0] - 1) & NX_U384_LIMB_MASK; u384_copy(b, a)
59 total = total + 1; pass = pass + cmp_case(a, b, 3) // (p-1)^2
60
61 // random cases (full-range a,b)
62 var s: i64 = 1
63 while s <= 24 {
64 mk(a, s); mk(b, s * 7 + 3)
65 total = total + 1; pass = pass + cmp_case(a, b, 100 + s)
66 mk(a, s * 131 + 5)
67 total = total + 1; pass = pass + cmp_case(a, a, 200 + s) // square
68 s = s + 1
69 }
70
71 g_ps("p384-field-mul-fast gate: " as *u8, 26); g_pn(pass); g_ps("/" as *u8, 1); g_pn(total); g_ps(" match\n" as *u8, 7)
72 if pass == total { sys_exit(0); return 0 }
73 sys_exit(1)
74 return 1
75}