code wiki / _hdl_build / nx_connect_keyx_vm_gate.nx

nx_connect_keyx_vm_gate.nx source

↩ module page · 107 lines · 6762 B

1// nx_connect_keyx_vm_gate.nx -- THE FULL-E2E KEY-AGREEMENT CROWN TOOTH: prove the Diffie-Hellman 2// property on the EXACT wasm bytes the browsers run (web_assets/_video_build/nx_x25519.wasm), inside the 3// sovereign nx_wasm_vm, against RFC 7748 section 6.1's complete Alice/Bob exchange: 4// T2 X25519(alice_priv, 9) == alice_pub (keygen half, Alice) 5// T3 X25519(bob_priv, 9) == bob_pub (keygen half, Bob) 6// T4 X25519(alice_priv, bob_pub) == K (Alice derives the shared key) 7// T5 X25519(bob_priv, alice_pub) == K and == T4 (Bob derives the SAME key = agreement) 8// If GREEN, the two browsers in the CONNECT E2E client MUST agree on a conversation key without the 9// server ever seeing a private key -- proven on the shipped artifact, not on a reimplementation. 10// license_tier: ORIGINAL expect_exit: 0 11import "nx_syscalls.nx" 12import "nx_wasm_vm.nx" 13 14func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 15func g_pn(v: i64) -> i64 { 16 let b: *u8 = sys_mmap(28); var x: i64 = v 17 if x == 0 { b[0]=48; sys_write(1,b,1); return 0 } 18 var d: i64=0; var y: i64=x 19 while y>0 { d=d+1; y=y/10 } 20 var i: i64=d-1; y=x 21 while i>=0 { b[i]=(48+(y%10)) as u8; y=y/10; i=i-1 } 22 sys_write(1,b,d); return 0 23} 24func g_check(name: *u8, cond: i64) -> i64 { 25 if cond==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } 26 g_puts(name); g_puts("\n" as *u8); return cond 27} 28 29// run one scalarmult in the VM: scalar/point copied to fixed offsets, result copied OUT to res. 30func kx_mult(mod: *WasmMod, scalar: *i64, point: *i64, res: *i64) -> i64 { 31 var i: i64 = 0 32 while i < 32 { mod.mem[i] = scalar[i] as u8; mod.mem[64 + i] = point[i] as u8; i = i + 1 } 33 wm_run(mod, "nx_x25519_scalarmult" as *u8, 0, 64, 256, 2048, 0, 4) 34 i = 0 35 while i < 32 { res[i] = mod.mem[2048 + i] as i64; i = i + 1 } 36 return 0 37} 38func kx_eq(a: *i64, b: *i64) -> i64 { 39 var i: i64 = 0 40 while i < 32 { if a[i] != b[i] { return 0 } i = i + 1 } 41 return 1 42} 43 44func main() -> i64 { 45 g_puts("nx_connect_keyx_vm_gate (RFC 7748 6.1 full DH exchange, executed on the SHIPPED nx_x25519.wasm in nx_wasm_vm)\n" as *u8) 46 var pass: i64 = 0; var total: i64 = 0 47 let box: *i64 = sys_mmap(16) as *i64 48 let wasm: *u8 = sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/web_assets/_video_build/nx_x25519.wasm" as *u8, box) 49 if (wasm as i64) == 0 { g_puts(" FAIL read wasm\n" as *u8); g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 } 50 let mod: *WasmMod = wm_new(wasm, box[0]) 51 if wm_parse(mod) != 0 { g_puts(" FAIL parse\n" as *u8); g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 } 52 mod.mem = sys_mmap(131072) as *u8 53 let fidx: i64 = wm_find_export(mod, "nx_x25519_scalarmult" as *u8) 54 pass = pass + g_check("T1 nx_x25519_scalarmult exported by the shipped wasm" as *u8, fidx >= 0); total=total+1 55 56 // ---- RFC 7748 6.1 vectors ---- 57 let ap: *i64 = sys_mmap(32*8) as *i64 // Alice private 58 let apub: *i64 = sys_mmap(32*8) as *i64 // Alice public (expected) 59 let bp: *i64 = sys_mmap(32*8) as *i64 // Bob private 60 let bpub: *i64 = sys_mmap(32*8) as *i64 // Bob public (expected) 61 let shk: *i64 = sys_mmap(32*8) as *i64 // shared K (expected) 62 let base: *i64 = sys_mmap(32*8) as *i64 // the curve base point u=9 63 var z: i64=0 64 while z<32 { base[z]=0; z=z+1 } 65 base[0]=9 66 ap[0]=119; ap[1]=7; ap[2]=109; ap[3]=10; ap[4]=115; ap[5]=24; ap[6]=165; ap[7]=125 67 ap[8]=60; ap[9]=22; ap[10]=193; ap[11]=114; ap[12]=81; ap[13]=178; ap[14]=102; ap[15]=69 68 ap[16]=223; ap[17]=76; ap[18]=47; ap[19]=135; ap[20]=235; ap[21]=192; ap[22]=153; ap[23]=42 69 ap[24]=177; ap[25]=119; ap[26]=251; ap[27]=165; ap[28]=29; ap[29]=185; ap[30]=44; ap[31]=42 70 apub[0]=133; apub[1]=32; apub[2]=240; apub[3]=9; apub[4]=137; apub[5]=48; apub[6]=167; apub[7]=84 71 apub[8]=116; apub[9]=139; apub[10]=125; apub[11]=220; apub[12]=180; apub[13]=62; apub[14]=247; apub[15]=90 72 apub[16]=13; apub[17]=191; apub[18]=58; apub[19]=13; apub[20]=38; apub[21]=56; apub[22]=26; apub[23]=244 73 apub[24]=235; apub[25]=164; apub[26]=169; apub[27]=142; apub[28]=170; apub[29]=155; apub[30]=78; apub[31]=106 74 bp[0]=93; bp[1]=171; bp[2]=8; bp[3]=126; bp[4]=98; bp[5]=74; bp[6]=138; bp[7]=75 75 bp[8]=121; bp[9]=225; bp[10]=127; bp[11]=139; bp[12]=131; bp[13]=128; bp[14]=14; bp[15]=230 76 bp[16]=111; bp[17]=59; bp[18]=177; bp[19]=41; bp[20]=38; bp[21]=24; bp[22]=182; bp[23]=253 77 bp[24]=28; bp[25]=47; bp[26]=139; bp[27]=39; bp[28]=255; bp[29]=136; bp[30]=224; bp[31]=235 78 bpub[0]=222; bpub[1]=158; bpub[2]=219; bpub[3]=125; bpub[4]=123; bpub[5]=125; bpub[6]=193; bpub[7]=180 79 bpub[8]=211; bpub[9]=91; bpub[10]=97; bpub[11]=194; bpub[12]=236; bpub[13]=228; bpub[14]=53; bpub[15]=55 80 bpub[16]=63; bpub[17]=131; bpub[18]=67; bpub[19]=200; bpub[20]=91; bpub[21]=120; bpub[22]=103; bpub[23]=77 81 bpub[24]=173; bpub[25]=252; bpub[26]=126; bpub[27]=20; bpub[28]=111; bpub[29]=136; bpub[30]=43; bpub[31]=79 82 shk[0]=74; shk[1]=93; shk[2]=157; shk[3]=91; shk[4]=164; shk[5]=206; shk[6]=45; shk[7]=225 83 shk[8]=114; shk[9]=142; shk[10]=59; shk[11]=244; shk[12]=128; shk[13]=53; shk[14]=15; shk[15]=37 84 shk[16]=224; shk[17]=126; shk[18]=33; shk[19]=201; shk[20]=71; shk[21]=209; shk[22]=158; shk[23]=51 85 shk[24]=118; shk[25]=240; shk[26]=155; shk[27]=60; shk[28]=30; shk[29]=22; shk[30]=23; shk[31]=66 86 87 let r1: *i64 = sys_mmap(32*8) as *i64 88 let r2: *i64 = sys_mmap(32*8) as *i64 89 let r3: *i64 = sys_mmap(32*8) as *i64 90 let r4: *i64 = sys_mmap(32*8) as *i64 91 92 g_puts(" running 4 scalarmults in the interpreted VM (Montgomery ladder x4 -- slow is expected)...\n" as *u8) 93 kx_mult(mod, ap, base, r1) 94 pass = pass + g_check("T2 Alice keygen: X25519(alice_priv, 9) == RFC alice_pub" as *u8, kx_eq(r1, apub)); total=total+1 95 kx_mult(mod, bp, base, r2) 96 pass = pass + g_check("T3 Bob keygen: X25519(bob_priv, 9) == RFC bob_pub" as *u8, kx_eq(r2, bpub)); total=total+1 97 kx_mult(mod, ap, bpub, r3) 98 pass = pass + g_check("T4 Alice derives: X25519(alice_priv, bob_pub) == RFC shared K" as *u8, kx_eq(r3, shk)); total=total+1 99 kx_mult(mod, bp, apub, r4) 100 var t5: i64 = 0 101 if kx_eq(r4, shk)==1 { if kx_eq(r4, r3)==1 { t5=1 } } 102 pass = pass + g_check("T5 Bob derives the SAME key: X25519(bob_priv, alice_pub) == K == Alice's derivation (DH AGREEMENT)" as *u8, t5); total=total+1 103 104 g_puts("---- connect keyx VM gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 105 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 106 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 107}