code wiki / (root) / nx_rsa_pkcs1_v1_5_sha384.nx

nx_rsa_pkcs1_v1_5_sha384.nx source

↩ module page · 119 lines · 4528 B

1// nx_rsa_pkcs1_v1_5_sha384.nx -- RSA-PKCS#1 v1.5 signature verify with 2// SHA-384, for RSA-2048 AND RSA-4096 keys. 3// 4// Parallel to nx_rsa_pkcs1_v1_5_sha256{,_4096}; sha384WithRSAEncryption 5// (OID 1.2.840.113549.1.1.12) is extremely common on intermediate/root 6// certs (Sectigo, USERTrust, DigiCert), so cert-chain validation needs it. 7// Differs from the SHA-256 variant only in: hash = SHA-384 (48 bytes), 8// the DigestInfo DER prefix, and PS length. RSA mod-exp is reused. 9// 10// RFC 8017 ยง8.2.2: s -> m = s^e mod n; EM = 00 01 PS(FF..) 00 T H, 11// T = SHA-384 DigestInfo prefix (19 bytes): 12// 30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 13// H = SHA-384(message) (48 bytes). 14// PS_LEN = 256-3-19-48 = 186 (RSA-2048) / 512-3-19-48 = 442 (RSA-4096). 15// 16// license_tier: INDEPENDENT_REDERIVE 17// genealogy_id: international-research-sources/ietf/rfc_8017 + nist/fips_180_4 18// lineage_id: nishi_rsa_pkcs1_v1_5_sha384_q1 19 20import "nx_syscalls.nx" 21import "nx_sha512.nx" 22import "nx_u2048.nx" 23import "nx_rsa2048_mod_exp.nx" 24import "nx_rsa2048_mont.nx" 25import "nx_u4096.nx" 26import "nx_rsa4096_mod_exp.nx" 27 28const NX_RSA_PKCS1_V15_384_OK: i64 = 1 29const NX_RSA_PKCS1_V15_384_S_OUT_OF_RANGE: i64 = 2 30const NX_RSA_PKCS1_V15_384_BAD_PAD: i64 = 3 31const NX_RSA_PKCS1_V15_384_HASH_MISMATCH: i64 = 4 32const NX_RSA_PKCS1_V15_384_VERDICT_N: i64 = 5 33 34// SHA-384 DigestInfo prefix byte i (0..18). 35func rsa_pkcs1_sha384_di_byte(i: i64) -> i64 { 36 if i == 0 { return 0x30 } 37 if i == 1 { return 0x41 } 38 if i == 2 { return 0x30 } 39 if i == 3 { return 0x0d } 40 if i == 4 { return 0x06 } 41 if i == 5 { return 0x09 } 42 if i == 6 { return 0x60 } 43 if i == 7 { return 0x86 } 44 if i == 8 { return 0x48 } 45 if i == 9 { return 0x01 } 46 if i == 10 { return 0x65 } 47 if i == 11 { return 0x03 } 48 if i == 12 { return 0x04 } 49 if i == 13 { return 0x02 } 50 if i == 14 { return 0x02 } 51 if i == 15 { return 0x05 } 52 if i == 16 { return 0x00 } 53 if i == 17 { return 0x04 } 54 if i == 18 { return 0x30 } 55 return 0 56} 57 58// Shared EM structural check given a recovered EM, its total byte length, 59// the precomputed SHA-384 of the message, and the PS length. 60func _rsa384_check_em(em: *u8, em_len: i64, h: *u8, ps_len: i64) -> i64 { 61 if (em[0] & 0xff) != 0x00 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 62 if (em[1] & 0xff) != 0x01 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 63 var i: i64 = 0 64 while i < ps_len { 65 if (em[2 + i] & 0xff) != 0xff { return NX_RSA_PKCS1_V15_384_BAD_PAD } 66 i = i + 1 67 } 68 if (em[2 + ps_len] & 0xff) != 0x00 { return NX_RSA_PKCS1_V15_384_BAD_PAD } 69 let di_off: i64 = 2 + ps_len + 1 70 i = 0 71 while i < 19 { 72 let expected: i64 = rsa_pkcs1_sha384_di_byte(i) 73 if (em[di_off + i] & 0xff) != (expected & 0xff) { return NX_RSA_PKCS1_V15_384_BAD_PAD } 74 i = i + 1 75 } 76 let h_off: i64 = di_off + 19 77 i = 0 78 while i < 48 { 79 if (em[h_off + i] & 0xff) != (h[i] & 0xff) { return NX_RSA_PKCS1_V15_384_HASH_MISMATCH } 80 i = i + 1 81 } 82 return NX_RSA_PKCS1_V15_384_OK 83} 84 85// RSA-2048: sig_bytes is 256 bytes BE, n_2048 is a 64-limb LE U2048. 86func rsa_pkcs1_v1_5_sha384_verify(msg: *u8, msg_len: i64, 87 sig_bytes: *u8, 88 n_2048: *i64, e_i64: i64) -> i64 { 89 let s_int: *i64 = u2048_alloc() 90 u2048_load_be(s_int, sig_bytes) 91 let m_int: *i64 = u2048_alloc() 92 let rc: i64 = rsa2048_mod_exp_mont(m_int, s_int, e_i64, n_2048) 93 if rc != NX_RSA2048_MONT_OK { return NX_RSA_PKCS1_V15_384_S_OUT_OF_RANGE } 94 let em: *u8 = sys_mmap(256) 95 u2048_store_be(em, m_int) 96 let h: *u8 = sys_mmap(48) 97 sha384_digest(msg, msg_len, h) 98 return _rsa384_check_em(em, 256, h, 186) 99} 100 101// RSA-4096: sig_bytes is 512 bytes BE, n_4096 is a 128-limb LE U4096. 102func rsa_pkcs1_v1_5_sha384_4096_verify(msg: *u8, msg_len: i64, 103 sig_bytes: *u8, 104 n_4096: *i64, e_i64: i64) -> i64 { 105 let s_int: *i64 = u4096_alloc() 106 u4096_load_be(s_int, sig_bytes) 107 let m_int: *i64 = u4096_alloc() 108 let rc: i64 = rsa4096_mod_exp(m_int, s_int, e_i64, n_4096) 109 if rc != NX_RSA4096_MOD_EXP_OK { return NX_RSA_PKCS1_V15_384_S_OUT_OF_RANGE } 110 let em: *u8 = sys_mmap(512) 111 u4096_store_be(em, m_int) 112 let h: *u8 = sys_mmap(48) 113 sha384_digest(msg, msg_len, h) 114 return _rsa384_check_em(em, 512, h, 442) 115} 116 117func main() -> i64 { 118 return 0 119}