nx_tls12_ske_verify.nx source
↩ module page · 132 lines · 6881 B
1// nx_tls12_ske_verify.nx -- TLS 1.2 ECDHE-RSA ServerKeyExchange signature
2// verification (rung 5 of the sovereign TLS 1.2 client; RFC 5246 §7.4.3 +
3// §7.4.1.4.1). The server proves ownership of its certificate's RSA key by
4// signing the ephemeral ECDHE parameters bound to both handshake randoms:
5//
6// signed_data = client_random(32) || server_random(32) || ECDHE_params
7// signature = RSASSA-PKCS1-v1_5( SHA-256(signed_data) ) // leaf RSA key
8//
9// ECDHE_params = curve_type(1=0x03 named_curve)
10// || named_curve(2=0x0017 secp256r1)
11// || point_len(1) || point(point_len, 0x04||X||Y uncompressed)
12//
13// On the TLS 1.2 wire the SKE body additionally carries, AFTER the params, a
14// 2-byte SignatureAndHashAlgorithm (e.g. 0x0401 = {sha256, rsa}) and a 2-byte
15// signature length -- but those frame the signature; the SIGNED bytes are
16// exactly client_random || server_random || ECDHE_params.
17//
18// COMPOSED, not re-implemented (verify-don't-rebuild):
19// - tls12_skx_signed_data -> nx_tls12_parse.nx (signed-data assembly)
20// - tls12_parse_server_key_exchange -> nx_tls12_parse.nx (wire field split)
21// - rsa_pkcs1_v1_5_sha256_verify -> nx_rsa_pkcs1_v1_5_sha256.nx (RSA-2048
22// PKCS1 v1.5 + SHA-256 verify, hashes
23// signed_data internally)
24// - u2048_load_be -> nx_u2048.nx (modulus load)
25//
26// This rung adds ONLY the glue: assemble -> hash+verify -> sealed verdict.
27//
28// license_tier: INDEPENDENT_REDERIVE
29// genealogy_id: international-research-sources/ietf/rfc_5246 + rfc_8017
30// lineage_id: nishi_tls12_ske_verify_q1
31//
32// nx_safety_envelope:
33// intended_use: "TLS 1.2 ECDHE-RSA ServerKeyExchange signature
34// verification (server authentication / anti-MITM)"
35// sil_target: SIL3 (authentication; a forged-accept = MITM)
36// evidence: [composed_from_rsa_pkcs1v15_sha256_verify,
37// openssl_signed_fixture_VERIFIED,
38// neg_control_flipped_sig_and_signed_data_REJECTED]
39// verdict: NOT_YET_EVALUATED
40
41import "nx_syscalls.nx"
42import "nx_u2048.nx"
43import "nx_rsa_pkcs1_v1_5_sha256.nx"
44import "nx_tls12_parse.nx"
45import "nx_x509_verify_ecdsa.nx" // ECDHE-ECDSA SKE: nx_x509_verify_ecdsa_p256 (hash+DER-parse+verify) + NX_X509_ECDSA_OK
46
47// Sealed verdict.
48const NX_TLS12_SKE_OK: i64 = 1
49const NX_TLS12_SKE_BAD_SIG: i64 = 2 // signature did not verify
50const NX_TLS12_SKE_BAD_PARAMS: i64 = 3 // malformed SKE wire body
51const NX_TLS12_SKE_VERDICT_N: i64 = 4
52
53func nx_tls12_ske_verdict_is_valid(v: i64) -> i64 {
54 if v < NX_TLS12_SKE_OK { return 0 }
55 if v >= NX_TLS12_SKE_VERDICT_N { return 0 }
56 return 1
57}
58
59// Verify against an already-loaded U2048 modulus.
60// params/params_len = the ECDHE_params bytes (curve_type..point), 69 bytes
61// for secp256r1 uncompressed.
62// sig/sig_len = the RSA signature (256 bytes for RSA-2048).
63func nx_tls12_ske_verify(client_random: *u8, server_random: *u8,
64 params: *u8, params_len: i64,
65 sig: *u8, sig_len: i64,
66 pub_n: *i64, pub_e: i64) -> i64 {
67 // RSA-2048 PKCS1 v1.5 signatures are exactly 256 bytes.
68 if sig_len != 256 { return NX_TLS12_SKE_BAD_SIG }
69 let signed_len: i64 = 64 + params_len
70 let signed: *u8 = sys_mmap(signed_len + 8)
71 tls12_skx_signed_data(client_random, server_random, params, params_len, signed)
72 let v: i64 = rsa_pkcs1_v1_5_sha256_verify(signed, signed_len, sig, pub_n, pub_e)
73 if v == NX_RSA_PKCS1_V15_OK { return NX_TLS12_SKE_OK }
74 return NX_TLS12_SKE_BAD_SIG
75}
76
77// ECDHE-ECDSA SKE signature verify (RFC 5246 §7.4.3 + §7.4.1.4.1, sig_alg ecdsa_secp256r1_sha256):
78// signed_data = client_random(32) || server_random(32) || ECDHE_params
79// signature = DER ECDSA(SHA-256(signed_data)) under the LEAF's EC P-256 key (pub_x,pub_y as u256 limbs)
80// Composes tls12_skx_signed_data (assemble) + the gated nx_x509_verify_ecdsa_p256 (which SHA-256-hashes the
81// message, parses the DER SEQUENCE{r,s}, and does u1*G+u2*Q). Same anti-MITM contract as the RSA path; a
82// forged/mismatched sig -> BAD_SIG (FAIL-CLOSED by construction -- a wrong signed_data can only make it reject).
83func nx_tls12_ske_verify_ecdsa(client_random: *u8, server_random: *u8,
84 params: *u8, params_len: i64,
85 sig: *u8, sig_len: i64,
86 pub_x: *i64, pub_y: *i64) -> i64 {
87 let signed_len: i64 = 64 + params_len
88 let signed: *u8 = sys_mmap(signed_len + 8)
89 tls12_skx_signed_data(client_random, server_random, params, params_len, signed)
90 let v: i64 = nx_x509_verify_ecdsa_p256(signed, signed_len, sig, sig_len, pub_x, pub_y)
91 if v == NX_X509_ECDSA_OK { return NX_TLS12_SKE_OK }
92 return NX_TLS12_SKE_BAD_SIG
93}
94
95// Convenience: verify with the leaf modulus as 256 raw big-endian bytes (the
96// form it appears in inside the X.509 certificate's RSAPublicKey).
97func nx_tls12_ske_verify_n(client_random: *u8, server_random: *u8,
98 params: *u8, params_len: i64,
99 sig: *u8, sig_len: i64,
100 n_bytes: *u8, pub_e: i64) -> i64 {
101 let n_int: *i64 = u2048_alloc()
102 u2048_load_be(n_int, n_bytes)
103 return nx_tls12_ske_verify(client_random, server_random,
104 params, params_len, sig, sig_len, n_int, pub_e)
105}
106
107// Full wire path: parse the ECDHE ServerKeyExchange handshake body (after the
108// 4-byte handshake header), then verify its signature with the leaf RSA key.
109// body layout: curve_type(1) || named_curve(2) || point_len(1) || point
110// || sig_alg(2) || sig_len(2 BE) || signature(sig_len)
111func nx_tls12_ske_verify_wire(client_random: *u8, server_random: *u8,
112 body: *u8, body_len: i64,
113 n_bytes: *u8, pub_e: i64) -> i64 {
114 let out_curve: *i64 = (sys_mmap(8)) as *i64
115 let out_pub: *u8 = sys_mmap(512)
116 let out_pub_len: *i64 = (sys_mmap(8)) as *i64
117 let out_sigalg: *i64 = (sys_mmap(8)) as *i64
118 let out_sig: *u8 = sys_mmap(512)
119 let out_sig_len: *i64 = (sys_mmap(8)) as *i64
120 let ok: i64 = tls12_parse_server_key_exchange(
121 body, body_len, out_curve, out_pub, out_pub_len,
122 out_sigalg, out_sig, out_sig_len
123 )
124 if ok != 1 { return NX_TLS12_SKE_BAD_PARAMS }
125 // ECDHE_params occupies the first (4 + point_len) bytes of the body:
126 // curve_type(1) + named_curve(2) + point_len(1) + point(point_len).
127 let params_len: i64 = 4 + out_pub_len[0]
128 return nx_tls12_ske_verify_n(
129 client_random, server_random, body, params_len,
130 out_sig, out_sig_len[0], n_bytes, pub_e
131 )
132}