diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/lib/tls/tls_seq_numbers.h | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/lib/tls/tls_seq_numbers.h')
-rw-r--r-- | comm/third_party/botan/src/lib/tls/tls_seq_numbers.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/tls/tls_seq_numbers.h b/comm/third_party/botan/src/lib/tls/tls_seq_numbers.h new file mode 100644 index 0000000000..0a0a416f8f --- /dev/null +++ b/comm/third_party/botan/src/lib/tls/tls_seq_numbers.h @@ -0,0 +1,174 @@ +/* +* TLS Sequence Number Handling +* (C) 2012 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_TLS_SEQ_NUMBERS_H_ +#define BOTAN_TLS_SEQ_NUMBERS_H_ + +#include <botan/types.h> +#include <map> + +namespace Botan { + +namespace TLS { + +class Connection_Sequence_Numbers + { + public: + virtual ~Connection_Sequence_Numbers() = default; + + virtual void new_read_cipher_state() = 0; + virtual void new_write_cipher_state() = 0; + + virtual uint16_t current_read_epoch() const = 0; + virtual uint16_t current_write_epoch() const = 0; + + virtual uint64_t next_write_sequence(uint16_t) = 0; + virtual uint64_t next_read_sequence() = 0; + + virtual bool already_seen(uint64_t seq) const = 0; + virtual void read_accept(uint64_t seq) = 0; + + virtual void reset() = 0; + }; + +class Stream_Sequence_Numbers final : public Connection_Sequence_Numbers + { + public: + Stream_Sequence_Numbers() { Stream_Sequence_Numbers::reset(); } + + void reset() override + { + m_write_seq_no = 0; + m_read_seq_no = 0; + m_read_epoch = 0; + m_write_epoch = 0; + } + + void new_read_cipher_state() override { m_read_seq_no = 0; m_read_epoch++; } + void new_write_cipher_state() override { m_write_seq_no = 0; m_write_epoch++; } + + uint16_t current_read_epoch() const override { return m_read_epoch; } + uint16_t current_write_epoch() const override { return m_write_epoch; } + + uint64_t next_write_sequence(uint16_t) override { return m_write_seq_no++; } + uint64_t next_read_sequence() override { return m_read_seq_no; } + + bool already_seen(uint64_t) const override { return false; } + void read_accept(uint64_t) override { m_read_seq_no++; } + + private: + uint64_t m_write_seq_no; + uint64_t m_read_seq_no; + uint16_t m_read_epoch; + uint16_t m_write_epoch; + }; + +class Datagram_Sequence_Numbers final : public Connection_Sequence_Numbers + { + public: + Datagram_Sequence_Numbers() { Datagram_Sequence_Numbers::reset(); } + + void reset() override + { + m_write_seqs.clear(); + m_write_seqs[0] = 0; + m_write_epoch = 0; + m_read_epoch = 0; + m_window_highest = 0; + m_window_bits = 0; + } + + void new_read_cipher_state() override { m_read_epoch++; } + + void new_write_cipher_state() override + { + m_write_epoch++; + m_write_seqs[m_write_epoch] = 0; + } + + uint16_t current_read_epoch() const override { return m_read_epoch; } + uint16_t current_write_epoch() const override { return m_write_epoch; } + + uint64_t next_write_sequence(uint16_t epoch) override + { + auto i = m_write_seqs.find(epoch); + BOTAN_ASSERT(i != m_write_seqs.end(), "Found epoch"); + return (static_cast<uint64_t>(epoch) << 48) | i->second++; + } + + uint64_t next_read_sequence() override + { + throw Invalid_State("DTLS uses explicit sequence numbers"); + } + + bool already_seen(uint64_t sequence) const override + { + const size_t window_size = sizeof(m_window_bits) * 8; + + if(sequence > m_window_highest) + { + return false; + } + + const uint64_t offset = m_window_highest - sequence; + + if(offset >= window_size) + { + return true; // really old? + } + + return (((m_window_bits >> offset) & 1) == 1); + } + + void read_accept(uint64_t sequence) override + { + const size_t window_size = sizeof(m_window_bits) * 8; + + if(sequence > m_window_highest) + { + // We've received a later sequence which advances our window + const uint64_t offset = sequence - m_window_highest; + m_window_highest += offset; + + if(offset >= window_size) + m_window_bits = 0; + else + m_window_bits <<= offset; + + m_window_bits |= 0x01; + } + else + { + const uint64_t offset = m_window_highest - sequence; + + if(offset < window_size) + { + // We've received an old sequence but still within our window + m_window_bits |= (static_cast<uint64_t>(1) << offset); + } + else + { + // This occurs only if we have reset state (DTLS reconnection case) + m_window_highest = sequence; + m_window_bits = 0; + } + } + } + + private: + std::map<uint16_t, uint64_t> m_write_seqs; + uint16_t m_write_epoch = 0; + uint16_t m_read_epoch = 0; + uint64_t m_window_highest = 0; + uint64_t m_window_bits = 0; + }; + +} + +} + +#endif |