code wiki / _hdl_build / nx_email_send_gate.nx

nx_email_send_gate.nx source

↩ module page · 95 lines · 4188 B

1// nx_email_send_gate.nx -- GATE for outbound DKIM send (nx_email_send). 2// 3// COMPLETENESS : compose a message, DKIM ed25519-sha256 sign it, and 4// verify the signature validates against the public key. 5// TAMPER : flip a BODY byte -> verify fails (bh mismatch); flip a 6// signed HEADER byte -> verify fails (sig mismatch). 7// NEG-CONTROL : verify under a DIFFERENT public key -> fails (it truly 8// checks the signature, not just structure). 9// 10// Evidence -> knowledge/status/email_send.log (SENDGATE ... verdict=GREEN) 11// license_tier: ORIGINAL 12import "nx_email_send.nx" 13import "nx_csprng.nx" 14import "nx_syscalls.nx" 15 16const SEND_LOG: *u8 = "knowledge/status/email_send.log" 17 18func ew(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 } 19func epf(fd: i64, label: *u8, pass: i64) -> i64 { ew(fd, label); if pass == 1 { ew(fd, "PASS" as *u8) } else { ew(fd, "FAIL" as *u8) } return 0 } 20func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 21func cp(dst: *u8, src: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { dst[i] = src[i]; i = i + 1 } return 0 } 22func g_find(hay: *u8, hlen: i64, needle: *u8) -> i64 { 23 let nl: i64 = slen(needle); var i: i64 = 0 24 while i + nl <= hlen { 25 var k: i64 = 0; var hit: i64 = 1 26 while k < nl { if (hay[i + k] & 0xff) != (needle[k] & 0xff) { hit = 0; k = nl } else { k = k + 1 } } 27 if hit == 1 { return i } 28 i = i + 1 29 } 30 return 0 - 1 31} 32func contains(hay: *u8, hlen: i64, needle: *u8) -> i64 { if g_find(hay, hlen, needle) >= 0 { return 1 } return 0 } 33 34func main() -> i64 { 35 var ok: i64 = 1 36 37 // keypair 38 let priv: *u8 = sys_mmap(32) 39 nx_csprng_fill(priv, 32) 40 let pub: *u8 = sys_mmap(32) 41 ed25519_pub_from_priv(priv, pub) 42 43 // compose + sign 44 let msg: *u8 = sys_mmap(4096) 45 let mlen: i64 = nx_email_compose("self@jasonewest.com" as *u8, "bob@remote.test" as *u8, "Hello from self" as *u8, "This is a DKIM-signed message from the sovereign stack.\r\n" as *u8, msg, 4096) 46 let signed: *u8 = sys_mmap(8192) 47 let sln: i64 = nx_email_dkim_sign_message(msg, mlen, priv, "nishi1" as *u8, "jasonewest.com" as *u8, signed, 8192) 48 49 var header_present: i64 = contains(signed, sln, "DKIM-Signature: v=1; a=ed25519-sha256" as *u8) 50 if header_present != 1 { ok = 0 } 51 52 var verify_self: i64 = 0 53 if nx_email_dkim_verify_message(signed, sln, pub) == 1 { verify_self = 1 } else { ok = 0 } 54 55 // tamper body (flip a byte near the end = in the body) 56 let t1: *u8 = sys_mmap(8192) 57 cp(t1, signed, sln) 58 t1[sln - 3] = (t1[sln - 3] + 1) as u8 59 var tamper_body: i64 = 0 60 if nx_email_dkim_verify_message(t1, sln, pub) == 0 { tamper_body = 1 } else { ok = 0 } 61 62 // tamper a signed header (flip a byte in the Subject value) 63 let t2: *u8 = sys_mmap(8192) 64 cp(t2, signed, sln) 65 let sp: i64 = g_find(t2, sln, "Hello from self" as *u8) 66 if sp >= 0 { t2[sp] = (t2[sp] + 1) as u8 } 67 var tamper_header: i64 = 0 68 if nx_email_dkim_verify_message(t2, sln, pub) == 0 { tamper_header = 1 } else { ok = 0 } 69 70 // wrong key 71 let priv2: *u8 = sys_mmap(32) 72 nx_csprng_fill(priv2, 32) 73 let pub2: *u8 = sys_mmap(32) 74 ed25519_pub_from_priv(priv2, pub2) 75 var wrongkey: i64 = 0 76 if nx_email_dkim_verify_message(signed, sln, pub2) == 0 { wrongkey = 1 } else { ok = 0 } 77 78 var fd: i64 = 1 79 while fd >= 1 { 80 ew(fd, "SENDGATE authored=organ dkim=ed25519-sha256 domain=jasonewest.com " as *u8) 81 epf(fd, "header_present=" as *u8, header_present) 82 epf(fd, " verify_self=" as *u8, verify_self) 83 epf(fd, " tamper_body=" as *u8, tamper_body) 84 epf(fd, " tamper_header=" as *u8, tamper_header) 85 epf(fd, " wrongkey_negctrl=" as *u8, wrongkey) 86 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 87 if fd == 1 { 88 let lf: i64 = sys_openat_append(SEND_LOG, 420) 89 if lf >= 1 { fd = lf } else { fd = 0 } 90 } else { sys_close(fd); fd = 0 } 91 } 92 93 if ok == 1 { return 0 } 94 return 1 95}