diff options
author | lloyd <[email protected]> | 2012-09-10 19:42:44 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-09-10 19:42:44 +0000 |
commit | 8c0160098e9bffa1a124a8951ba1a9c074f5509c (patch) | |
tree | 438bcd9b17bd0f3f122cb2450cc6851ded4faeac /src/tls/tls_seq_numbers.h | |
parent | ad949688f2903d6b59e3178fc2d6a0022bdfa79f (diff) |
New logic for DTLS replay detection. Abstracts the sequence handling
out a bit. Handling of initial server record is pretty nasty.
Diffstat (limited to 'src/tls/tls_seq_numbers.h')
-rw-r--r-- | src/tls/tls_seq_numbers.h | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/tls/tls_seq_numbers.h b/src/tls/tls_seq_numbers.h new file mode 100644 index 000000000..c9a334e4b --- /dev/null +++ b/src/tls/tls_seq_numbers.h @@ -0,0 +1,112 @@ +/* +* 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 <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 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; } + void new_write_cipher_state() override { m_write_seq_no = 0; } + + 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; + }; + +class Datagram_Sequence_Numbers : public Connection_Sequence_Numbers + { + public: + void new_read_cipher_state() override {} + + void new_write_cipher_state() override + { + // increment epoch + m_write_seq_no = ((m_write_seq_no >> 48) + 1) << 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; + u64bit m_window_highest = 0; + u64bit m_window_bits = 0; + }; + +} + +} + +#endif |