aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_seq_numbers.h
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-09-10 19:42:44 +0000
committerlloyd <[email protected]>2012-09-10 19:42:44 +0000
commit8c0160098e9bffa1a124a8951ba1a9c074f5509c (patch)
tree438bcd9b17bd0f3f122cb2450cc6851ded4faeac /src/tls/tls_seq_numbers.h
parentad949688f2903d6b59e3178fc2d6a0022bdfa79f (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.h112
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