Wrap `inner_frame` in an authenticated envelope, appending to `out`. MAC covers `[env_ver, from_node_id, seq, inner_len, inner_frame]`.
(
from_node_id: u64,
seq: u64,
inner_frame: &[u8],
key: &MacKey,
out: &mut Vec<u8>,
)
| 60 | /// |
| 61 | /// MAC covers `[env_ver, from_node_id, seq, inner_len, inner_frame]`. |
| 62 | pub fn write_envelope( |
| 63 | from_node_id: u64, |
| 64 | seq: u64, |
| 65 | inner_frame: &[u8], |
| 66 | key: &MacKey, |
| 67 | out: &mut Vec<u8>, |
| 68 | ) -> Result<()> { |
| 69 | let inner_len: u32 = inner_frame |
| 70 | .len() |
| 71 | .try_into() |
| 72 | .map_err(|_| ClusterError::Codec { |
| 73 | detail: format!("inner frame too large: {} bytes", inner_frame.len()), |
| 74 | })?; |
| 75 | if inner_len > MAX_RPC_PAYLOAD_SIZE { |
| 76 | return Err(ClusterError::Codec { |
| 77 | detail: format!( |
| 78 | "inner frame length {inner_len} exceeds maximum {MAX_RPC_PAYLOAD_SIZE}" |
| 79 | ), |
| 80 | }); |
| 81 | } |
| 82 | |
| 83 | let start = out.len(); |
| 84 | out.reserve(ENVELOPE_OVERHEAD + inner_frame.len()); |
| 85 | out.push(ENVELOPE_VERSION); |
| 86 | out.extend_from_slice(&from_node_id.to_le_bytes()); |
| 87 | out.extend_from_slice(&seq.to_le_bytes()); |
| 88 | out.extend_from_slice(&inner_len.to_le_bytes()); |
| 89 | out.extend_from_slice(inner_frame); |
| 90 | let tag = compute_hmac(key, &out[start..]); |
| 91 | out.extend_from_slice(&tag); |
| 92 | Ok(()) |
| 93 | } |
| 94 | |
| 95 | /// Validate the envelope + MAC and return `(fields, inner_frame)`. |
| 96 | /// |