aboutsummaryrefslogtreecommitdiffstats
path: root/lib/tls/tls_seq_numbers.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tls/tls_seq_numbers.h')
-rw-r--r--lib/tls/tls_seq_numbers.h125
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