s2n_quic_core/crypto/application/
limited.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::crypto::OneRttKey;
5
6//= https://www.rfc-editor.org/rfc/rfc9001#section-6.6
7//# Endpoints MUST count the number of encrypted packets for each set of
8//# keys.
9pub struct Key<K> {
10    key: K,
11
12    // Keeping encrypted_packets out of the key allow keys to be immutable, which allows optimizations
13    // later on.
14    encrypted_packets: u64,
15    decrypted_packets: u64,
16    confidentiality_limit: u64,
17}
18
19#[derive(Copy, Clone, Debug)]
20#[non_exhaustive]
21pub struct Limits {
22    /// The number of packets before the limit at which a key update will be scheduled
23    pub key_update_window: u64,
24}
25
26impl Default for Limits {
27    fn default() -> Self {
28        Self {
29            key_update_window: KEY_UPDATE_WINDOW,
30        }
31    }
32}
33
34const KEY_UPDATE_WINDOW: u64 = 10_000;
35
36impl<K: OneRttKey> Key<K> {
37    pub fn new(key: K) -> Self {
38        Key {
39            confidentiality_limit: key.aead_confidentiality_limit(),
40            key,
41            encrypted_packets: 0,
42            decrypted_packets: 0,
43        }
44    }
45
46    /// Keys used past the confidentiality_limit are expired
47    #[inline]
48    pub fn expired(&self) -> bool {
49        // We check >= because we don't want to encrypt an additional packet if the key has
50        // already been used up to the limit.
51        self.encrypted_packets >= self.confidentiality_limit
52    }
53
54    /// If the key is within the update window, an update should be initiated.
55    #[inline]
56    pub fn needs_update(&self, limits: &Limits) -> bool {
57        self.encrypted_packets
58            > (self
59                .confidentiality_limit
60                .saturating_sub(limits.key_update_window))
61    }
62
63    pub fn derive_next_key(&self) -> K {
64        self.key.derive_next_key()
65    }
66
67    #[inline]
68    pub fn encrypted_packets(&self) -> u64 {
69        self.encrypted_packets
70    }
71
72    #[inline]
73    pub fn on_packet_encryption(&mut self) {
74        self.encrypted_packets += 1;
75    }
76
77    #[inline]
78    pub fn on_packet_decryption(&mut self) {
79        self.decrypted_packets += 1;
80    }
81
82    #[inline]
83    pub fn key_mut(&mut self) -> &mut K {
84        &mut self.key
85    }
86}