code wiki / (root) / nx_x509_verify_ecdsa.nx

nx_x509_verify_ecdsa.nx source

↩ module page · 106 lines · 4159 B

1// nx_x509_verify_ecdsa.nx -- X.509 outer-signature verification for 2// ECDSA-P256-with-SHA-256 signed certs (the dominant Web PKI sig 3// algorithm). 4// 5// Phase 0b §I.4 piece 2 of the chain-walker arc. Composes: 6// - nx_sha256 (sha256_digest -- 256-bit hash of tbs) 7// - nx_ecdsa_sig_der (parse DER sig into r, s) 8// - nx_ecdsa_p256 (verify under issuer's pubkey) 9// 10// into the per-cert verify the chain-walker will call repeatedly: 11// "verify this cert's outer sig against this issuer's pubkey" 12// 13// What this primitive verifies: 14// - SHA-256(tbs_bytes) -> e (the 256-bit message hash) 15// - DER-decode the signature into r, s 16// - Call ecdsa_p256_verify(pub_x, pub_y, e, r, s) 17// 18// What it does NOT verify (caller / chain walker / X.509 leaf-check 19// responsibility): 20// - cert validity period 21// - cert SAN matches hostname 22// - cert sig_alg OID actually IS ecdsa-with-SHA-256 (caller dispatches 23// by sig_alg before calling this primitive) 24// - issuer's pubkey actually matches cert.issuer Subject DN 25// (chain walker resolves issuer first) 26// 27// Public API: 28// nx_x509_verify_ecdsa_p256(tbs, tbs_len, sig_der, sig_len, 29// pub_x, pub_y) -> verdict 30// nx_x509_verify_ecdsa_verdict_is_valid(v) -> 0|1 31// 32// Sealed verdict enum: 33// NX_X509_ECDSA_OK sig verifies 34// NX_X509_ECDSA_BAD_SIG_DER DER-decode failed 35// NX_X509_ECDSA_BAD_SIG verify returned BAD_SIG / range fail 36// NX_X509_ECDSA_BAD_PUBKEY pubkey off-curve or infinity 37// NX_X509_ECDSA_INFINITY u1*G + u2*Q = O (corrupt sig) 38// 39// Per Cardinals 9 (single-responsibility -- this primitive is JUST 40// the SHA-256 + parse + verify pipeline; caller selects the algo), 41// 22 (composition over configuration), 23 (preamble names what 42// caller MUST verify separately). 43// 44// license_tier: INDEPENDENT_REDERIVE 45// genealogy_id: international-research-sources/ietf/rfc_5280 + rfc_5480 46// lineage_id: nishi_x509_verify_ecdsa_p256_q10 47 48// nx_safety_envelope: 49// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 50// sil_target: SIL1 51// evidence: [bulk_applied_2026-05-19, x509-outer-sig-ecdsa-orchestrator] 52// verdict: NOT_YET_EVALUATED 53 54import "nx_syscalls.nx" 55import "nx_u256.nx" 56import "nx_sha256.nx" 57import "nx_ecdsa_sig_der.nx" 58import "nx_ecdsa_p256.nx" 59 60const NX_X509_ECDSA_OK: i64 = 1 61const NX_X509_ECDSA_BAD_SIG_DER: i64 = 2 62const NX_X509_ECDSA_BAD_SIG: i64 = 3 63const NX_X509_ECDSA_BAD_PUBKEY: i64 = 4 64const NX_X509_ECDSA_INFINITY: i64 = 5 65const NX_X509_ECDSA_VERDICT_N: i64 = 6 66 67func nx_x509_verify_ecdsa_verdict_is_valid(v: i64) -> i64 { 68 if v < NX_X509_ECDSA_OK { return 0 } 69 if v >= NX_X509_ECDSA_VERDICT_N { return 0 } 70 return 1 71} 72 73// Verify an X.509 outer signature for an ECDSA-P256-with-SHA-256 74// signed cert. 75// 76// Returns NX_X509_ECDSA_OK on valid signature, or a non-OK verdict. 77func nx_x509_verify_ecdsa_p256(tbs: *u8, tbs_len: i64, 78 sig_der: *u8, sig_len: i64, 79 pub_x: *i64, pub_y: *i64) -> i64 { 80 // ---- Hash tbs with SHA-256 ---- 81 let hash_bytes: *u8 = sys_mmap(32) 82 sha256_digest(tbs, tbs_len, hash_bytes) 83 84 let e: *i64 = u256_alloc() 85 u256_load_be(e, hash_bytes) 86 87 // ---- Parse DER signature into r, s ---- 88 let r: *i64 = u256_alloc() 89 let s: *i64 = u256_alloc() 90 let parse: i64 = nx_ecdsa_sig_parse_der(sig_der, sig_len, r, s) 91 if parse != NX_ECDSA_DER_OK { return NX_X509_ECDSA_BAD_SIG_DER } 92 93 // ---- Call ECDSA verify ---- 94 let v: i64 = nx_ecdsa_p256_verify(pub_x, pub_y, e, r, s) 95 if v == NX_ECDSA_OK { return NX_X509_ECDSA_OK } 96 if v == NX_ECDSA_PUBKEY_NOT_ON_CURVE { return NX_X509_ECDSA_BAD_PUBKEY } 97 if v == NX_ECDSA_PUBKEY_INFINITY { return NX_X509_ECDSA_BAD_PUBKEY } 98 if v == NX_ECDSA_INFINITY_RESULT { return NX_X509_ECDSA_INFINITY } 99 // BAD_R_RANGE, BAD_S_RANGE, BAD_SIG -> generic bad-sig verdict 100 return NX_X509_ECDSA_BAD_SIG 101} 102 103// Compile-only smoke. Real KAT in nx_x509_verify_ecdsa_test.nx. 104func main() -> i64 { 105 return 0 106}