code wiki / (root) / nx_rsa_pkcs1_v1_5_k.nx

nx_rsa_pkcs1_v1_5_k.nx source

↩ module page · 125 lines · 5123 B

1// nx_rsa_pkcs1_v1_5_k.nx -- k-aware RSA-PKCS#1 v1.5 verify for RSA moduli 2// whose byte-length k is NOT exactly 256 or 512 (e.g. RSA-3072 = 384 bytes, 3// common on Sectigo/USERTrust intermediates like iana.org's chain). 4// 5// Mechanism: load the (zero-extended) k-byte signature into a u4096 and 6// mod-exp under the (zero-extended) modulus. The recovered EM value is 7// < n < 2^(8k), so its big-endian 512-byte form has the high (512-k) bytes 8// = 0x00 and the real k-byte PKCS#1 EM (00 01 PS 00 T H) in the LOW k bytes, 9// i.e. starting at offset zoff = 512-k. We verify the high zero-extension 10// AND the EM structure at zoff with PS_LEN = k-3-19-hashlen. 11// 12// For k=512 this reduces to the existing RSA-4096 check (zoff=0); we only 13// route here for k not in {256,512} so the proven 2048/4096 paths are 14// untouched. Verdicts reuse the SHA-384 module's enum (same shape). 15// 16// license_tier: INDEPENDENT_REDERIVE 17// genealogy_id: international-research-sources/ietf/rfc_8017 18// lineage_id: nishi_rsa_pkcs1_v1_5_k_q1 19 20import "nx_syscalls.nx" 21import "nx_sha256.nx" 22import "nx_sha512.nx" 23import "nx_u4096.nx" 24import "nx_rsa4096_mod_exp.nx" 25import "nx_rsa_pkcs1_v1_5_sha256.nx" // rsa_pkcs1_sha256_di_byte 26import "nx_rsa_pkcs1_v1_5_sha384.nx" // rsa_pkcs1_sha384_di_byte + NX_RSA_PKCS1_V15_384_* 27 28// Recover EM (512-byte BE) from a k-byte signature via the u4096 path. 29// Writes 512 bytes to em_out; returns OK or S_OUT_OF_RANGE. 30func _rsa_k_recover(sig_bytes: *u8, sig_len: i64, n_4096: *i64, e_i64: i64, em_out: *u8) -> i64 { 31 let sig512: *u8 = sys_mmap(512) 32 var i: i64 = 0 33 while i < 512 { sig512[i] = 0 as u8; i = i + 1 } 34 let off: i64 = 512 - sig_len 35 i = 0 36 while i < sig_len { sig512[off + i] = sig_bytes[i]; i = i + 1 } 37 let s_int: *i64 = u4096_alloc() 38 u4096_load_be(s_int, sig512) 39 let m_int: *i64 = u4096_alloc() 40 let rc: i64 = rsa4096_mod_exp(m_int, s_int, e_i64, n_4096) 41 if rc != NX_RSA4096_MOD_EXP_OK { return NX_RSA_PKCS1_V15_384_S_OUT_OF_RANGE } 42 u4096_store_be(em_out, m_int) 43 return NX_RSA_PKCS1_V15_384_OK 44} 45 46// Verify the leading zero-extension + PKCS#1 EM prefix (00 01 FF.. 00) at 47// offset zoff. Returns OK or BAD_PAD; leaves DigestInfo+hash to the caller. 48func _rsa_k_check_prefix(em: *u8, zoff: i64, ps_len: i64) -> i64 { 49 var i: i64 = 0 50 while i < zoff { 51 if (em[i] & 0xff) != 0x00 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 52 i = i + 1 53 } 54 if (em[zoff] & 0xff) != 0x00 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 55 if (em[zoff + 1] & 0xff) != 0x01 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 56 i = 0 57 while i < ps_len { 58 if (em[zoff + 2 + i] & 0xff) != 0xff { return NX_RSA_PKCS1_V15_384_BAD_PAD } 59 i = i + 1 60 } 61 if (em[zoff + 2 + ps_len] & 0xff) != 0x00 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 62 return NX_RSA_PKCS1_V15_384_OK 63} 64 65// k-aware RSA-PKCS#1 v1.5 + SHA-256 (sig_len = issuer modulus bytes, e.g. 384). 66func rsa_pkcs1_v1_5_sha256_k_verify(msg: *u8, msg_len: i64, 67 sig_bytes: *u8, sig_len: i64, 68 n_4096: *i64, e_i64: i64) -> i64 { 69 let em: *u8 = sys_mmap(512) 70 let rc: i64 = _rsa_k_recover(sig_bytes, sig_len, n_4096, e_i64, em) 71 if rc != NX_RSA_PKCS1_V15_384_OK { return rc } 72 let h: *u8 = sys_mmap(32) 73 sha256_digest(msg, msg_len, h) 74 let k: i64 = sig_len 75 let zoff: i64 = 512 - k 76 let ps_len: i64 = k - 3 - 19 - 32 77 let pc: i64 = _rsa_k_check_prefix(em, zoff, ps_len) 78 if pc != NX_RSA_PKCS1_V15_384_OK { return pc } 79 let di_off: i64 = zoff + 2 + ps_len + 1 80 var i: i64 = 0 81 while i < 19 { 82 if (em[di_off + i] & 0xff) != (rsa_pkcs1_sha256_di_byte(i) & 0xff) { return NX_RSA_PKCS1_V15_384_BAD_PAD } 83 i = i + 1 84 } 85 let h_off: i64 = di_off + 19 86 i = 0 87 while i < 32 { 88 if (em[h_off + i] & 0xff) != (h[i] & 0xff) { return NX_RSA_PKCS1_V15_384_HASH_MISMATCH } 89 i = i + 1 90 } 91 return NX_RSA_PKCS1_V15_384_OK 92} 93 94// k-aware RSA-PKCS#1 v1.5 + SHA-384. 95func rsa_pkcs1_v1_5_sha384_k_verify(msg: *u8, msg_len: i64, 96 sig_bytes: *u8, sig_len: i64, 97 n_4096: *i64, e_i64: i64) -> i64 { 98 let em: *u8 = sys_mmap(512) 99 let rc: i64 = _rsa_k_recover(sig_bytes, sig_len, n_4096, e_i64, em) 100 if rc != NX_RSA_PKCS1_V15_384_OK { return rc } 101 let h: *u8 = sys_mmap(48) 102 sha384_digest(msg, msg_len, h) 103 let k: i64 = sig_len 104 let zoff: i64 = 512 - k 105 let ps_len: i64 = k - 3 - 19 - 48 106 let pc: i64 = _rsa_k_check_prefix(em, zoff, ps_len) 107 if pc != NX_RSA_PKCS1_V15_384_OK { return pc } 108 let di_off: i64 = zoff + 2 + ps_len + 1 109 var i: i64 = 0 110 while i < 19 { 111 if (em[di_off + i] & 0xff) != (rsa_pkcs1_sha384_di_byte(i) & 0xff) { return NX_RSA_PKCS1_V15_384_BAD_PAD } 112 i = i + 1 113 } 114 let h_off: i64 = di_off + 19 115 i = 0 116 while i < 48 { 117 if (em[h_off + i] & 0xff) != (h[i] & 0xff) { return NX_RSA_PKCS1_V15_384_HASH_MISMATCH } 118 i = i + 1 119 } 120 return NX_RSA_PKCS1_V15_384_OK 121} 122 123func main() -> i64 { 124 return 0 125}