diff options
Diffstat (limited to 'lib/tls/tls_seq_numbers.h')
-rw-r--r-- | lib/tls/tls_seq_numbers.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/lib/tls/tls_seq_numbers.h b/lib/tls/tls_seq_numbers.h new file mode 100644 index 000000000..87edf3130 --- /dev/null +++ b/lib/tls/tls_seq_numbers.h @@ -0,0 +1,125 @@ +/* +* TLS Sequence Number Handling +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SEQ_NUMBERS_H__ +#define BOTAN_TLS_SEQ_NUMBERS_H__ + +#include <botan/types.h> +#include <stdexcept> + +namespace Botan { + +namespace TLS { + +class Connection_Sequence_Numbers + { + public: + virtual void new_read_cipher_state() = 0; + virtual void new_write_cipher_state() = 0; + + virtual u16bit current_read_epoch() const = 0; + virtual u16bit current_write_epoch() const = 0; + + virtual u64bit next_write_sequence() = 0; + virtual u64bit next_read_sequence() = 0; + + virtual bool already_seen(u64bit seq) const = 0; + virtual void read_accept(u64bit seq) = 0; + }; + +class Stream_Sequence_Numbers : public Connection_Sequence_Numbers + { + public: + void new_read_cipher_state() override { m_read_seq_no = 0; m_read_epoch += 1; } + void new_write_cipher_state() override { m_write_seq_no = 0; m_write_epoch += 1; } + + u16bit current_read_epoch() const override { return m_read_epoch; } + u16bit current_write_epoch() const override { return m_write_epoch; } + + u64bit next_write_sequence() override { return m_write_seq_no++; } + u64bit next_read_sequence() override { return m_read_seq_no; } + + bool already_seen(u64bit) const override { return false; } + void read_accept(u64bit) override { m_read_seq_no++; } + private: + u64bit m_write_seq_no = 0; + u64bit m_read_seq_no = 0; + u16bit m_read_epoch = 0; + u16bit m_write_epoch = 0; + }; + +class Datagram_Sequence_Numbers : public Connection_Sequence_Numbers + { + public: + void new_read_cipher_state() override { m_read_epoch += 1; } + + void new_write_cipher_state() override + { + // increment epoch + m_write_seq_no = ((m_write_seq_no >> 48) + 1) << 48; + } + + u16bit current_read_epoch() const override { return m_read_epoch; } + u16bit current_write_epoch() const override { return (m_write_seq_no >> 48); } + + u64bit next_write_sequence() override { return m_write_seq_no++; } + + u64bit next_read_sequence() override + { + throw std::runtime_error("DTLS uses explicit sequence numbers"); + } + + bool already_seen(u64bit sequence) const override + { + const size_t window_size = sizeof(m_window_bits) * 8; + + if(sequence > m_window_highest) + return false; + + const u64bit offset = m_window_highest - sequence; + + if(offset >= window_size) + return true; // really old? + + return (((m_window_bits >> offset) & 1) == 1); + } + + void read_accept(u64bit sequence) override + { + const size_t window_size = sizeof(m_window_bits) * 8; + + if(sequence > m_window_highest) + { + const size_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 u64bit offset = m_window_highest - sequence; + m_window_bits |= (static_cast<u64bit>(1) << offset); + } + } + + private: + u64bit m_write_seq_no = 0; + u16bit m_read_epoch = 0; + u64bit m_window_highest = 0; + u64bit m_window_bits = 0; + }; + +} + +} + +#endif |