code wiki / _hdl_build / nx_x25519_kat_gate.nx
nx_x25519_kat_gate.nx source
↩ module page · 111 lines · 10940 B
1// nx_x25519_kat_gate.nx -- RIGOROUS standing KAT for X25519 (RFC 7748). Supersedes the compile-only smoke
2// in nx_x25519_test.nx. Proves the shared primitive (TLS 1.3 + ntor + browser arc depend on it) is correct
3// across a huge input space, and RESOLVES the misdiagnosed 'base-point bug': the impl is correct; the old
4// expected value 99381de5.. (from RFC 8448 3, whose ephemeral x25519 triple is internally inconsistent --
5// its ECDHE 8bd4054f.. is ALSO wrong per OpenSSL, true value fab1d4c6..) was the error. Correct value
6// X25519(49af,9)=88fd30ab.. is asserted here.
7// T1 RFC 7748 5.2 test-1 T2 5.2 test-2
8// T3 6.1 base-point Alice T4 6.1 base-point Bob
9// T5 6.1 DH golden dir1 == K T6 6.1 DH golden dir2 == K T7 DH commutes (dir1==dir2, needs no oracle)
10// T8 5.2 iterated x1 == golden T9 5.2 iterated x1000 == golden (the canonical acceptance KAT)
11// T10 X25519(49af,spub)==fab1d4c6 (OpenSSL-verified) T11 X25519(49af,9)==88fd30ab (CORRECTED base-point value)
12// license_tier: ORIGINAL expect_exit: 0
13import "nx_syscalls.nx"
14import "nx_x25519.nx"
15import "nx_x25519_ephemeral.nx"
16
17func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
18func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o:*u8=sys_mmap(24); var i:i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
19func g_fw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
20func g_fn(fd: i64, v: i64) -> i64 { var m: i64=v; let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o:*u8=sys_mmap(24); var i:i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(fd,o,k); return 0 }
21func g_row(id: *u8, ok: i64, pass: *i64, tot: *i64) -> i64 { tot[0]=tot[0]+1; g_w(" " as *u8); g_w(id); if ok==1 { g_w(": OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w(": FAIL\n" as *u8) } return 0 }
22func g_eq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
23
24func main() -> i64 {
25 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0
26 let tot: *i64 = sys_mmap(8) as *i64; tot[0]=0
27 g_w("=== NX-X25519-KAT GATE (RFC 7748: single + 6.1 DH golden + 5.2 iterated 1000x) ===\n" as *u8)
28
29 // scalars/points
30 let alice: *u8 = sys_mmap(32)
31 alice[0]=0x77;alice[1]=0x07;alice[2]=0x6d;alice[3]=0x0a;alice[4]=0x73;alice[5]=0x18;alice[6]=0xa5;alice[7]=0x7d;alice[8]=0x3c;alice[9]=0x16;alice[10]=0xc1;alice[11]=0x72;alice[12]=0x51;alice[13]=0xb2;alice[14]=0x66;alice[15]=0x45;alice[16]=0xdf;alice[17]=0x4c;alice[18]=0x2f;alice[19]=0x87;alice[20]=0xeb;alice[21]=0xc0;alice[22]=0x99;alice[23]=0x2a;alice[24]=0xb1;alice[25]=0x77;alice[26]=0xfb;alice[27]=0xa5;alice[28]=0x1d;alice[29]=0xb9;alice[30]=0x2c;alice[31]=0x2a
32 let bob: *u8 = sys_mmap(32)
33 bob[0]=0x5d;bob[1]=0xab;bob[2]=0x08;bob[3]=0x7e;bob[4]=0x62;bob[5]=0x4a;bob[6]=0x8a;bob[7]=0x4b;bob[8]=0x79;bob[9]=0xe1;bob[10]=0x7f;bob[11]=0x8b;bob[12]=0x83;bob[13]=0x80;bob[14]=0x0e;bob[15]=0xe6;bob[16]=0x6f;bob[17]=0x3b;bob[18]=0xb1;bob[19]=0x29;bob[20]=0x26;bob[21]=0x18;bob[22]=0xb6;bob[23]=0xfd;bob[24]=0x1c;bob[25]=0x2f;bob[26]=0x8b;bob[27]=0x27;bob[28]=0xff;bob[29]=0x88;bob[30]=0xe0;bob[31]=0xeb
34 let bp: *u8 = sys_mmap(32); x25519_base_point(bp)
35
36 // T1 5.2 test-1
37 let k1: *u8 = sys_mmap(32)
38 k1[0]=0xa5;k1[1]=0x46;k1[2]=0xe3;k1[3]=0x6b;k1[4]=0xf0;k1[5]=0x52;k1[6]=0x7c;k1[7]=0x9d;k1[8]=0x3b;k1[9]=0x16;k1[10]=0x15;k1[11]=0x4b;k1[12]=0x82;k1[13]=0x46;k1[14]=0x5e;k1[15]=0xdd;k1[16]=0x62;k1[17]=0x14;k1[18]=0x4c;k1[19]=0x0a;k1[20]=0xc1;k1[21]=0xfc;k1[22]=0x5a;k1[23]=0x18;k1[24]=0x50;k1[25]=0x6a;k1[26]=0x22;k1[27]=0x44;k1[28]=0xba;k1[29]=0x44;k1[30]=0x9a;k1[31]=0xc4
39 let u1: *u8 = sys_mmap(32)
40 u1[0]=0xe6;u1[1]=0xdb;u1[2]=0x68;u1[3]=0x67;u1[4]=0x58;u1[5]=0x30;u1[6]=0x30;u1[7]=0xdb;u1[8]=0x35;u1[9]=0x94;u1[10]=0xc1;u1[11]=0xa4;u1[12]=0x24;u1[13]=0xb1;u1[14]=0x5f;u1[15]=0x7c;u1[16]=0x72;u1[17]=0x66;u1[18]=0x24;u1[19]=0xec;u1[20]=0x26;u1[21]=0xb3;u1[22]=0x35;u1[23]=0x3b;u1[24]=0x10;u1[25]=0xa9;u1[26]=0x03;u1[27]=0xa6;u1[28]=0xd0;u1[29]=0xab;u1[30]=0x1c;u1[31]=0x4c
41 let r1: *u8 = sys_mmap(32); x25519(k1, u1, r1)
42 var t1: i64=1; if (r1[0]&0xff)!=0xc3 {t1=0} if (r1[7]&0xff)!=0x90 {t1=0} if (r1[15]&0xff)!=0x4f {t1=0} if (r1[31]&0xff)!=0x52 {t1=0}
43 g_row("T1 RFC 7748 5.2 test-1 (c3da..52)" as *u8, t1, pass, tot)
44
45 // T2 5.2 test-2
46 let k2: *u8 = sys_mmap(32)
47 k2[0]=0x4b;k2[1]=0x66;k2[2]=0xe9;k2[3]=0xd4;k2[4]=0xd1;k2[5]=0xb4;k2[6]=0x67;k2[7]=0x3c;k2[8]=0x5a;k2[9]=0xd2;k2[10]=0x26;k2[11]=0x91;k2[12]=0x95;k2[13]=0x7d;k2[14]=0x6a;k2[15]=0xf5;k2[16]=0xc1;k2[17]=0x1b;k2[18]=0x64;k2[19]=0x21;k2[20]=0xe0;k2[21]=0xea;k2[22]=0x01;k2[23]=0xd4;k2[24]=0x2c;k2[25]=0xa4;k2[26]=0x16;k2[27]=0x9e;k2[28]=0x79;k2[29]=0x18;k2[30]=0xba;k2[31]=0x0d
48 let u2: *u8 = sys_mmap(32)
49 u2[0]=0xe5;u2[1]=0x21;u2[2]=0x0f;u2[3]=0x12;u2[4]=0x78;u2[5]=0x68;u2[6]=0x11;u2[7]=0xd3;u2[8]=0xf4;u2[9]=0xb7;u2[10]=0x95;u2[11]=0x9d;u2[12]=0x05;u2[13]=0x38;u2[14]=0xae;u2[15]=0x2c;u2[16]=0x31;u2[17]=0xdb;u2[18]=0xe7;u2[19]=0x10;u2[20]=0x6f;u2[21]=0xc0;u2[22]=0x3c;u2[23]=0x3e;u2[24]=0xfc;u2[25]=0x4c;u2[26]=0xd5;u2[27]=0x49;u2[28]=0xc7;u2[29]=0x15;u2[30]=0xa4;u2[31]=0x93
50 let r2: *u8 = sys_mmap(32); x25519(k2, u2, r2)
51 var t2: i64=1; if (r2[0]&0xff)!=0x95 {t2=0} if (r2[7]&0xff)!=0x7d {t2=0} if (r2[15]&0xff)!=0xf8 {t2=0} if (r2[31]&0xff)!=0x57 {t2=0}
52 g_row("T2 RFC 7748 5.2 test-2 (95cb..57)" as *u8, t2, pass, tot)
53
54 // T3/T4 base-point: Alice, Bob
55 let apub: *u8 = sys_mmap(32); x25519(alice, bp, apub)
56 var t3: i64=1; if (apub[0]&0xff)!=0x85 {t3=0} if (apub[31]&0xff)!=0x6a {t3=0}
57 g_row("T3 RFC 7748 6.1 base-point Alice (8520..6a)" as *u8, t3, pass, tot)
58 let bpub: *u8 = sys_mmap(32); x25519(bob, bp, bpub)
59 var t4: i64=1; if (bpub[0]&0xff)!=0xde {t4=0} if (bpub[31]&0xff)!=0x4f {t4=0}
60 g_row("T4 RFC 7748 6.1 base-point Bob (de9e..4f) [was claimed to trip the 'bug'; it does not]" as *u8, t4, pass, tot)
61
62 // T5/T6/T7 6.1 DH golden K = 4a5d9d5b..161742
63 let d1: *u8 = sys_mmap(32); x25519(alice, bpub, d1) // Alice * Bob_pub
64 let d2: *u8 = sys_mmap(32); x25519(bob, apub, d2) // Bob * Alice_pub
65 var t5: i64=1; if (d1[0]&0xff)!=0x4a {t5=0} if (d1[1]&0xff)!=0x5d {t5=0} if (d1[31]&0xff)!=0x42 {t5=0}
66 g_row("T5 RFC 7748 6.1 DH dir1 (Alice*Bpub) == K (4a5d..42)" as *u8, t5, pass, tot)
67 var t6: i64=1; if (d2[0]&0xff)!=0x4a {t6=0} if (d2[1]&0xff)!=0x5d {t6=0} if (d2[31]&0xff)!=0x42 {t6=0}
68 g_row("T6 RFC 7748 6.1 DH dir2 (Bob*Apub) == K (4a5d..42)" as *u8, t6, pass, tot)
69 var t7: i64=0; if g_eq(d1, d2, 32)==1 { t7=1 }
70 g_row("T7 DH commutes: Alice*Bpub == Bob*Apub (self-consistent, no external oracle)" as *u8, t7, pass, tot)
71
72 // T8/T9 5.2 iterated KAT (the canonical acceptance test; exercises ~1000 scalar/u pairs)
73 let ik: *u8 = sys_mmap(32); let iu: *u8 = sys_mmap(32); let ir: *u8 = sys_mmap(32); let itmp: *u8 = sys_mmap(32)
74 var z: i64=0; while z<32 { ik[z]=0 as u8; iu[z]=0 as u8; z=z+1 } ik[0]=9 as u8; iu[0]=9 as u8
75 let g1: *u8 = sys_mmap(32)
76 g1[0]=0x42;g1[1]=0x2c;g1[2]=0x8e;g1[3]=0x7a;g1[4]=0x62;g1[5]=0x27;g1[6]=0xd7;g1[7]=0xbc;g1[8]=0xa1;g1[9]=0x35;g1[10]=0x0b;g1[11]=0x3e;g1[12]=0x2b;g1[13]=0xb7;g1[14]=0x27;g1[15]=0x9f;g1[16]=0x78;g1[17]=0x97;g1[18]=0xb8;g1[19]=0x7b;g1[20]=0xb6;g1[21]=0x85;g1[22]=0x4b;g1[23]=0x78;g1[24]=0x3c;g1[25]=0x60;g1[26]=0xe8;g1[27]=0x03;g1[28]=0x11;g1[29]=0xae;g1[30]=0x30;g1[31]=0x79
77 let g1000: *u8 = sys_mmap(32)
78 g1000[0]=0x68;g1000[1]=0x4c;g1000[2]=0xf5;g1000[3]=0x9b;g1000[4]=0xa8;g1000[5]=0x33;g1000[6]=0x09;g1000[7]=0x55;g1000[8]=0x28;g1000[9]=0x00;g1000[10]=0xef;g1000[11]=0x56;g1000[12]=0x6f;g1000[13]=0x2f;g1000[14]=0x4d;g1000[15]=0x3c;g1000[16]=0x1c;g1000[17]=0x38;g1000[18]=0x87;g1000[19]=0xc4;g1000[20]=0x93;g1000[21]=0x60;g1000[22]=0xe3;g1000[23]=0x87;g1000[24]=0x5f;g1000[25]=0x2e;g1000[26]=0xb9;g1000[27]=0x4d;g1000[28]=0x99;g1000[29]=0x53;g1000[30]=0x2c;g1000[31]=0x51
79 var t8: i64=0; var it: i64=0
80 while it < 1000 {
81 x25519(ik, iu, ir)
82 var j: i64=0; while j<32 { itmp[j]=ik[j]; j=j+1 }
83 j=0; while j<32 { ik[j]=ir[j]; iu[j]=itmp[j]; j=j+1 }
84 it = it + 1
85 if it == 1 { if g_eq(ik, g1, 32)==1 { t8=1 } }
86 }
87 g_row("T8 RFC 7748 5.2 iterated x1 == golden (422c..79)" as *u8, t8, pass, tot)
88 var t9: i64=0; if g_eq(ik, g1000, 32)==1 { t9=1 }
89 g_row("T9 RFC 7748 5.2 iterated x1000 == golden (684c..51) [CANONICAL acceptance KAT]" as *u8, t9, pass, tot)
90
91 // T10/T11 the '49af' case: DH vs OpenSSL, and the CORRECTED base-point value
92 let sc: *u8 = sys_mmap(32)
93 sc[0]=0x49;sc[1]=0xaf;sc[2]=0x42;sc[3]=0xba;sc[4]=0x7f;sc[5]=0x99;sc[6]=0x94;sc[7]=0x85;sc[8]=0x2d;sc[9]=0x71;sc[10]=0x3e;sc[11]=0xf2;sc[12]=0x78;sc[13]=0x4b;sc[14]=0xcb;sc[15]=0xca;sc[16]=0xa7;sc[17]=0x91;sc[18]=0x1d;sc[19]=0xe2;sc[20]=0x6a;sc[21]=0xdc;sc[22]=0x56;sc[23]=0x42;sc[24]=0xcb;sc[25]=0x63;sc[26]=0x45;sc[27]=0x40;sc[28]=0xe7;sc[29]=0xea;sc[30]=0x50;sc[31]=0x05
94 let spub: *u8 = sys_mmap(32)
95 spub[0]=0xc9;spub[1]=0x82;spub[2]=0x88;spub[3]=0x76;spub[4]=0x11;spub[5]=0x20;spub[6]=0x95;spub[7]=0xfe;spub[8]=0x66;spub[9]=0x76;spub[10]=0x2b;spub[11]=0xdb;spub[12]=0xf7;spub[13]=0xc6;spub[14]=0x72;spub[15]=0xe1;spub[16]=0x56;spub[17]=0xd6;spub[18]=0xcc;spub[19]=0x25;spub[20]=0x3b;spub[21]=0x83;spub[22]=0x3d;spub[23]=0xf1;spub[24]=0xdd;spub[25]=0x69;spub[26]=0xb1;spub[27]=0xb0;spub[28]=0x4e;spub[29]=0x75;spub[30]=0x1f;spub[31]=0x0f
96 let dh: *u8 = sys_mmap(32); x25519(sc, spub, dh)
97 var t10: i64=1; if (dh[0]&0xff)!=0xfa {t10=0} if (dh[31]&0xff)!=0x5c {t10=0}
98 g_row("T10 X25519(49af,spub) == fab1..5c (OpenSSL-verified; RFC 8448's 8bd4054f is wrong)" as *u8, t10, pass, tot)
99 let p9: *u8 = sys_mmap(32); x25519(sc, bp, p9)
100 var t11: i64=1; if (p9[0]&0xff)!=0x88 {t11=0} if (p9[1]&0xff)!=0xfd {t11=0} if (p9[31]&0xff)!=0x5b {t11=0}
101 g_row("T11 X25519(49af,9) == 88fd..5b (CORRECT value; RFC 8448's 99381de5 is inconsistent)" as *u8, t11, pass, tot)
102
103 g_w("X25519-KAT rows=" as *u8); g_n(tot[0]); g_w(" pass=" as *u8); g_n(pass[0])
104 if pass[0]==tot[0] {
105 g_w(" verdict=GREEN (x25519 CORRECT across single+DH+1000-iter; no crypto bug -- misdiagnosed test expectation)\n" as *u8)
106 let lg: i64 = sys_openat_append("knowledge/status/x25519_kat_gate.log" as *u8, 0x1a4)
107 if lg>=0 { g_fw(lg, "X25519-KAT pass=" as *u8); g_fn(lg, pass[0]); g_fw(lg, "/" as *u8); g_fn(lg, tot[0]); g_fw(lg, " verdict=GREEN (RFC7748 5.2+6.1+iterated-1000x; base-point-bug=MISDIAGNOSIS resolved; browser arc unblocked) epoch=" as *u8); g_fn(lg, sys_now_realtime_sec()); g_fw(lg, "\n" as *u8); sys_close(lg) }
108 sys_exit(0); return 0
109 }
110 g_w(" verdict=RED\n" as *u8); sys_exit(1); return 1
111}