code wiki / (root) / nx_x509_pubkey_rsa_4096.nx

nx_x509_pubkey_rsa_4096.nx source

↩ module page · 117 lines · 3885 B

1// nx_x509_pubkey_rsa_4096.nx -- extract an RSA-4096 public key (n, e) 2// from an X.509 SubjectPublicKeyInfo. Parallel to 3// nx_x509_pubkey_rsa.nx (the 2048 variant). 4// 5// Same DER walk as the 2048 variant; only differences: 6// - mag_len cap is 512 (was 256) 7// - leading-0 sign byte case handles n_len == 513 (was 257) 8// - loads into a 128-limb u4096 buffer (was 64-limb u2048) 9// 10// Public API: 11// nx_x509_pubkey_extract_rsa_4096(buf, cert, out_n_4096, out_e_p) -> verdict 12// 13// Sealed verdict shape mirrors the 2048 variant. 14// 15// license_tier: INDEPENDENT_REDERIVE 16// genealogy_id: international-research-sources/ietf/rfc_8017 + rfc_5280 17// lineage_id: nishi_x509_pubkey_rsa_4096_q1 18 19import "nx_syscalls.nx" 20import "nx_asn1.nx" 21import "nx_u4096.nx" 22import "nx_x509.nx" 23 24const NX_X509_PUBKEY_RSA_4096_OK: i64 = 1 25const NX_X509_PUBKEY_RSA_4096_BAD_SEQUENCE: i64 = 2 26const NX_X509_PUBKEY_RSA_4096_BAD_N: i64 = 3 27const NX_X509_PUBKEY_RSA_4096_BAD_E: i64 = 4 28const NX_X509_PUBKEY_RSA_4096_VERDICT_N: i64 = 5 29 30func nx_x509_pubkey_rsa_4096_verdict_is_valid(v: i64) -> i64 { 31 if v < NX_X509_PUBKEY_RSA_4096_OK { return 0 } 32 if v >= NX_X509_PUBKEY_RSA_4096_VERDICT_N { return 0 } 33 return 1 34} 35 36func nx_x509_pubkey_extract_rsa_4096(buf: *u8, cert: *X509Cert, 37 out_n: *i64, out_e: *i64) -> i64 { 38 let pubkey_off: i64 = cert.pubkey_off 39 let pubkey_len: i64 = cert.pubkey_len 40 41 let c_raw: *u8 = sys_mmap(32) 42 let c: *Asn1Cursor = c_raw as *Asn1Cursor 43 c.pos = pubkey_off 44 c.end = pubkey_off + pubkey_len 45 46 // Outer SEQUENCE 47 let seq_len_p: *i64 = sys_mmap(16) as *i64 48 let rc1: i64 = asn1_expect_tag(buf, c, ASN1_SEQUENCE, seq_len_p) 49 if rc1 < 0 { return NX_X509_PUBKEY_RSA_4096_BAD_SEQUENCE } 50 let seq_end: i64 = c.pos + *seq_len_p 51 if seq_end > c.end { return NX_X509_PUBKEY_RSA_4096_BAD_SEQUENCE } 52 53 // n INTEGER 54 let n_len_p: *i64 = sys_mmap(16) as *i64 55 let rc2: i64 = asn1_expect_tag(buf, c, ASN1_INTEGER, n_len_p) 56 if rc2 < 0 { return NX_X509_PUBKEY_RSA_4096_BAD_N } 57 let n_off: i64 = c.pos 58 let n_len: i64 = *n_len_p 59 c.pos = c.pos + n_len 60 if c.pos > seq_end { return NX_X509_PUBKEY_RSA_4096_BAD_N } 61 62 // DER may include a leading 0x00 sign byte if MSB set. 63 // For 4096-bit modulus: n_len is 513 (with leading 0) or 512 (without). 64 var skip: i64 = 0 65 var mag_len: i64 = n_len 66 if n_len == 513 { 67 if (buf[n_off] & 0xff) != 0 { return NX_X509_PUBKEY_RSA_4096_BAD_N } 68 skip = 1 69 mag_len = 512 70 } 71 if mag_len > 512 { return NX_X509_PUBKEY_RSA_4096_BAD_N } 72 if mag_len < 1 { return NX_X509_PUBKEY_RSA_4096_BAD_N } 73 74 // Zero-pad up to 512 bytes BE then load as u4096. 75 let padded: *u8 = sys_mmap(512) 76 var i: i64 = 0 77 while i < 512 { 78 padded[i] = 0 79 i = i + 1 80 } 81 let pad_off: i64 = 512 - mag_len 82 i = 0 83 while i < mag_len { 84 padded[pad_off + i] = buf[n_off + skip + i] 85 i = i + 1 86 } 87 u4096_load_be(out_n, padded) 88 89 // e INTEGER (small; accept up to 8 bytes magnitude) 90 let e_len_p: *i64 = sys_mmap(16) as *i64 91 let rc3: i64 = asn1_expect_tag(buf, c, ASN1_INTEGER, e_len_p) 92 if rc3 < 0 { return NX_X509_PUBKEY_RSA_4096_BAD_E } 93 let e_off: i64 = c.pos 94 let e_len: i64 = *e_len_p 95 c.pos = c.pos + e_len 96 if c.pos > seq_end { return NX_X509_PUBKEY_RSA_4096_BAD_E } 97 if e_len < 1 { return NX_X509_PUBKEY_RSA_4096_BAD_E } 98 if e_len > 8 { return NX_X509_PUBKEY_RSA_4096_BAD_E } 99 100 var e_val: i64 = 0 101 var skip_e: i64 = 0 102 if (buf[e_off] & 0xff) == 0 { 103 if e_len > 1 { skip_e = 1 } 104 } 105 i = skip_e 106 while i < e_len { 107 e_val = (e_val << 8) | (buf[e_off + i] & 0xff) 108 i = i + 1 109 } 110 *out_e = e_val 111 112 return NX_X509_PUBKEY_RSA_4096_OK 113} 114 115func main() -> i64 { 116 return 0 117}