code wiki / (root) / nx_tls13_server_session_emit_ee_alpn.nx

nx_tls13_server_session_emit_ee_alpn.nx source

↩ module page · 138 lines · 5881 B

1// nx_tls13_server_session_emit_ee_alpn.nx -- TUTOR-BOOTSTRAP SCAFFOLD (Claude, 2// authored under the B1 rung(3) ALPN-h2 SERVER workflow of the R4-H2 3// HTTP/2-transport ladder), NOT credited as team self-authoring. 4// 5// The ALPN-h2 SIBLING of the base 6th TLS server stone 6// nx_tls13_server_session_emit_ee (runtime/nx_tls13_server_session_emit_ee.nx). 7// The base stone emits an EMPTY EncryptedExtensions inner '08 00 00 02 00 00' 8// (no extensions -> no ALPN negotiated). THIS variant emits the byte-exact 9// ALPN-h2 EE inner so a sovereign h2 client (which advertises "h2" via 10// tls13_ext_emit_alpn_h2_only) sees its protocol SELECTED: 11// 12// 08 00 00 0b 00 09 00 10 00 05 00 03 02 68 32 (15 bytes) 13// HT_ENCRYPTED_EXTENSIONS = 0x08 14// body_len u24 = 0x00000b = 11 15// ext_list_len = 0x0009 = 9 (one ALPN EE ext, 9 wire bytes) 16// ALPN EE ext = 00 10 00 05 00 03 02 68 32 17// ext_type 0x0010, ext_data_len 0x0005, protocol_name_list_len 0x0003, 18// name_len 0x02, "h2" = 0x68 0x32 19// 20// The trailing 9 ALPN bytes are NOT reinvented here: they are emitted BYTE-FOR- 21// BYTE by the GREEN client emitter tls13_ext_emit_alpn_h2_only 22// (runtime/nx_tls13_ext.nx:236, KAT '00 10 00 05 00 03 02 68 32' at :235), 23// which we call into inner+6. The CLIENT'S tls13_ext_parse_alpn_selected 24// recovers "h2" from exactly the trailing ext_data (00 03 02 68 32). 25// 26// NO-STRIP (rule 25): the base emit_ee + emit_ee_test are left BYTE-INTACT. 27// This is a NEW path used only by the run_h2 server variant; the base server 28// run keeps emitting the empty no-ext EE. 29// 30// Everything else is copied VERBATIM from the base stone: encrypt under 31// server_hs_traffic_key/iv/server_seq via nx_tls13_record_encrypt_v2 32// (CT_HANDSHAKE), feed the 15 PLAINTEXT inner bytes (not the AEAD record) to 33// nx_tls13_transcript_update, ++server_seq, advance EE_SENT -> CERT_SENT. 34// 35// BACK-FILL: the team RE-AUTHORS this from the DATA spec via the 36// emitter-of-emitters (X-AUT-006c/e/f); this hand scaffold is the sanctioned 37// one-time bootstrap only (meter-integrity, mirror 38// nx_tls13_server_session_emit_ee.nx:1-22). 39// 40// Precondition: state == EE_SENT. Postcondition: state == CERT_SENT. 41// 42// license_tier: INDEPENDENT_REDERIVE 43// genealogy_id: international-research-sources/ietf/rfc_8446 + ietf/rfc_7301 44// lineage_id: nishi_tls13_server_ee_alpn_b1r3 45 46import "nx_syscalls.nx" 47import "nx_tls13.nx" 48import "nx_tls13_record.nx" 49import "nx_tls13_transcript.nx" 50import "nx_tls13_server_session.nx" 51import "nx_tls13_ext.nx" 52 53const NX_TLS13_EE_ALPN_INNER_LEN: i64 = 15 // HT + u24 + ext_list_len(2) + ALPN ext(9) 54const NX_TLS13_EE_ALPN_REC_HEADER: i64 = 5 55const NX_TLS13_EE_ALPN_REC_TAG: i64 = 16 56 57func nx_tls13_server_session_emit_ee_alpn( 58 session: *Tls13ServerSession, 59 out: *u8, out_cap: i64 60) -> i64 { 61 if (session as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE } 62 if (out as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE } 63 if session.state != NX_TLS13_SSTATE_EE_SENT { 64 return 0 - NX_TLS13_SSESSION_BAD_STATE 65 } 66 if (session.server_hs_traffic_key as i64) == 0 { 67 return 0 - NX_TLS13_SSESSION_INTERNAL 68 } 69 if (session.server_hs_iv as i64) == 0 { 70 return 0 - NX_TLS13_SSESSION_INTERNAL 71 } 72 73 // Build the 15-byte ALPN-h2 EncryptedExtensions plaintext. 74 // inner[0..6) = handshake header + ext_list_len 75 // inner[6..15) = ALPN EE ext via the GREEN client emitter (DRY, not reinvented) 76 let inner: *u8 = sys_mmap(NX_TLS13_EE_ALPN_INNER_LEN) 77 inner[0] = HT_ENCRYPTED_EXTENSIONS & 0xff // 0x08 78 inner[1] = 0 // body_len[0] 79 inner[2] = 0 // body_len[1] 80 inner[3] = 11 // body_len[2] = 0x0b = ext_list_len(2) + ext(9) 81 inner[4] = 0 // ext_list_len[0] 82 inner[5] = 9 // ext_list_len[1] = 0x09 83 // ALPN EE ext '00 10 00 05 00 03 02 68 32' -- byte-identical to the GREEN 84 // client emitter tls13_ext_emit_alpn_h2_only (nx_tls13_ext.nx:236). 85 let alpn_off: i64 = 6 86 let an: i64 = tls13_ext_emit_alpn_h2_only((inner as i64 + alpn_off) as *u8, NX_TLS13_EE_ALPN_INNER_LEN - alpn_off) 87 if an != 9 { return 0 - NX_TLS13_SSESSION_INTERNAL } 88 89 // record layout: header(5) + ct(15+1+pad) + tag(16) 90 let total_needed: i64 = NX_TLS13_EE_ALPN_REC_HEADER + NX_TLS13_EE_ALPN_INNER_LEN + 1 + NX_TLS13_EE_ALPN_REC_TAG 91 if out_cap < total_needed { return 0 - NX_TLS13_SSESSION_BUF_OVERFLOW } 92 93 let header_buf: *u8 = sys_mmap(NX_TLS13_EE_ALPN_REC_HEADER) 94 let ct_len: i64 = NX_TLS13_EE_ALPN_INNER_LEN + 1 // plaintext + inner type 95 let ct_buf: *u8 = sys_mmap(ct_len + 16) 96 let tag_buf: *u8 = sys_mmap(NX_TLS13_EE_ALPN_REC_TAG) 97 98 let rv: i64 = nx_tls13_record_encrypt_v2( 99 session.cipher_suite, 100 session.server_hs_traffic_key, 101 session.server_hs_iv, 102 session.server_seq, 103 inner, NX_TLS13_EE_ALPN_INNER_LEN, 104 CT_HANDSHAKE, 105 0, // no padding 106 header_buf, ct_buf, tag_buf) 107 if rv != NX_TLS13_REC_VERDICT_OK { 108 return 0 - NX_TLS13_SSESSION_INTERNAL 109 } 110 111 // Write header + ct + tag to output buffer. 112 var w: i64 = 0 113 var i: i64 = 0 114 while i < NX_TLS13_EE_ALPN_REC_HEADER { 115 out[w + i] = header_buf[i] 116 i = i + 1 117 } 118 w = w + NX_TLS13_EE_ALPN_REC_HEADER 119 var j: i64 = 0 120 while j < ct_len { 121 out[w + j] = ct_buf[j] 122 j = j + 1 123 } 124 w = w + ct_len 125 var k: i64 = 0 126 while k < NX_TLS13_EE_ALPN_REC_TAG { 127 out[w + k] = tag_buf[k] 128 k = k + 1 129 } 130 w = w + NX_TLS13_EE_ALPN_REC_TAG 131 132 // Feed the PLAINTEXT EE handshake bytes into transcript hash. 133 nx_tls13_transcript_update(session.transcript, inner, NX_TLS13_EE_ALPN_INNER_LEN) 134 135 session.server_seq = session.server_seq + 1 136 session.state = NX_TLS13_SSTATE_CERT_SENT 137 return w 138}