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}