s2n_quic_core/crypto/
header_crypto.rs1use crate::{
5 crypto::{EncryptedPayload, ProtectedPayload},
6 packet::number::{PacketNumberSpace, TruncatedPacketNumber},
7};
8use s2n_codec::{DecoderBuffer, DecoderError};
9
10pub trait HeaderKey: Send {
12 fn opening_header_protection_mask(&self, ciphertext_sample: &[u8]) -> HeaderProtectionMask;
17
18 fn opening_sample_len(&self) -> usize;
21
22 fn sealing_header_protection_mask(&self, ciphertext_sample: &[u8]) -> HeaderProtectionMask;
27
28 fn sealing_sample_len(&self) -> usize;
31}
32
33pub const HEADER_PROTECTION_MASK_LEN: usize = 5;
38pub type HeaderProtectionMask = [u8; HEADER_PROTECTION_MASK_LEN];
39
40const LONG_HEADER_TAG: u8 = 0x80;
60pub(crate) const LONG_HEADER_MASK: u8 = 0x0f;
61pub(crate) const SHORT_HEADER_MASK: u8 = 0x1f;
62
63#[inline(always)]
64fn mask_from_packet_tag(tag: u8) -> u8 {
65 if tag & LONG_HEADER_TAG == LONG_HEADER_TAG {
66 LONG_HEADER_MASK
67 } else {
68 SHORT_HEADER_MASK
69 }
70}
71
72#[inline(always)]
73fn xor_mask(payload: &mut [u8], mask: &[u8]) {
74 for (payload_byte, mask_byte) in payload.iter_mut().zip(&mask[1..]) {
75 *payload_byte ^= mask_byte;
76 }
77}
78
79#[inline]
80pub(crate) fn apply_header_protection(
81 mask: HeaderProtectionMask,
82 payload: EncryptedPayload,
83) -> ProtectedPayload {
84 let header_len = payload.header_len;
85 let packet_number_len = payload.packet_number_len;
86 let payload = payload.buffer.into_less_safe_slice();
87
88 payload[0] ^= mask[0] & mask_from_packet_tag(payload[0]);
89
90 let header_with_pn_len = packet_number_len.bytesize() + header_len;
91 let packet_number_bytes = &mut payload[header_len..header_with_pn_len];
92 xor_mask(packet_number_bytes, &mask);
93
94 ProtectedPayload::new(header_len, payload)
95}
96
97#[inline]
98pub(crate) fn remove_header_protection(
99 space: PacketNumberSpace,
100 mask: HeaderProtectionMask,
101 payload: ProtectedPayload,
102) -> Result<(TruncatedPacketNumber, EncryptedPayload), DecoderError> {
103 let header_len = payload.header_len;
104 let payload = payload.buffer.into_less_safe_slice();
105
106 payload[0] ^= mask[0] & mask_from_packet_tag(payload[0]);
107 let packet_number_len = space.new_packet_number_len(payload[0]);
108
109 let header_with_pn_len = packet_number_len.bytesize() + header_len;
110 let packet_number = {
111 let packet_number_bytes = &mut payload[header_len..header_with_pn_len];
112 xor_mask(packet_number_bytes, &mask);
113
114 let (packet_number, _) = packet_number_len
115 .decode_truncated_packet_number(DecoderBuffer::new(packet_number_bytes))?;
116 packet_number
117 };
118
119 Ok((
120 packet_number,
121 EncryptedPayload::new(header_len, packet_number_len, payload),
122 ))
123}