Botan  1.11.15
src/lib/tls/tls_seq_numbers.h
Go to the documentation of this file.
00001 /*
00002 * TLS Sequence Number Handling
00003 * (C) 2012 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_TLS_SEQ_NUMBERS_H__
00009 #define BOTAN_TLS_SEQ_NUMBERS_H__
00010 
00011 #include <botan/types.h>
00012 #include <stdexcept>
00013 
00014 namespace Botan {
00015 
00016 namespace TLS {
00017 
00018 class Connection_Sequence_Numbers
00019    {
00020    public:
00021       virtual void new_read_cipher_state() = 0;
00022       virtual void new_write_cipher_state() = 0;
00023 
00024       virtual u16bit current_read_epoch() const = 0;
00025       virtual u16bit current_write_epoch() const = 0;
00026 
00027       virtual u64bit next_write_sequence(u16bit) = 0;
00028       virtual u64bit next_read_sequence() = 0;
00029 
00030       virtual bool already_seen(u64bit seq) const = 0;
00031       virtual void read_accept(u64bit seq) = 0;
00032    };
00033 
00034 class Stream_Sequence_Numbers : public Connection_Sequence_Numbers
00035    {
00036    public:
00037       void new_read_cipher_state() override { m_read_seq_no = 0; m_read_epoch += 1; }
00038       void new_write_cipher_state() override { m_write_seq_no = 0; m_write_epoch += 1; }
00039 
00040       u16bit current_read_epoch() const override { return m_read_epoch; }
00041       u16bit current_write_epoch() const override { return m_write_epoch; }
00042 
00043       u64bit next_write_sequence(u16bit) override { return m_write_seq_no++; }
00044       u64bit next_read_sequence() override { return m_read_seq_no; }
00045 
00046       bool already_seen(u64bit) const override { return false; }
00047       void read_accept(u64bit) override { m_read_seq_no++; }
00048    private:
00049       u64bit m_write_seq_no = 0;
00050       u64bit m_read_seq_no = 0;
00051       u16bit m_read_epoch = 0;
00052       u16bit m_write_epoch = 0;
00053    };
00054 
00055 class Datagram_Sequence_Numbers : public Connection_Sequence_Numbers
00056    {
00057    public:
00058       Datagram_Sequence_Numbers() { m_write_seqs[0] = 0; }
00059 
00060       void new_read_cipher_state() override { m_read_epoch += 1; }
00061 
00062       void new_write_cipher_state() override
00063          {
00064          m_write_epoch += 1;
00065          m_write_seqs[m_write_epoch] = 0;
00066          }
00067 
00068       u16bit current_read_epoch() const override { return m_read_epoch; }
00069       u16bit current_write_epoch() const override { return m_write_epoch; }
00070 
00071       u64bit next_write_sequence(u16bit epoch) override
00072          {
00073          auto i = m_write_seqs.find(epoch);
00074          BOTAN_ASSERT(i != m_write_seqs.end(), "Found epoch");
00075          return (static_cast<u64bit>(epoch) << 48) | i->second++;
00076          }
00077 
00078       u64bit next_read_sequence() override
00079          {
00080          throw std::runtime_error("DTLS uses explicit sequence numbers");
00081          }
00082 
00083       bool already_seen(u64bit sequence) const override
00084          {
00085          const size_t window_size = sizeof(m_window_bits) * 8;
00086 
00087          if(sequence > m_window_highest)
00088             return false;
00089 
00090          const u64bit offset = m_window_highest - sequence;
00091 
00092          if(offset >= window_size)
00093             return true; // really old?
00094 
00095          return (((m_window_bits >> offset) & 1) == 1);
00096          }
00097 
00098       void read_accept(u64bit sequence) override
00099          {
00100          const size_t window_size = sizeof(m_window_bits) * 8;
00101 
00102          if(sequence > m_window_highest)
00103             {
00104             const size_t offset = sequence - m_window_highest;
00105             m_window_highest += offset;
00106 
00107             if(offset >= window_size)
00108                m_window_bits = 0;
00109             else
00110                m_window_bits <<= offset;
00111 
00112             m_window_bits |= 0x01;
00113             }
00114          else
00115             {
00116             const u64bit offset = m_window_highest - sequence;
00117             m_window_bits |= (static_cast<u64bit>(1) << offset);
00118             }
00119          }
00120 
00121    private:
00122       std::map<u16bit, u64bit> m_write_seqs;
00123       u16bit m_write_epoch = 0;
00124       u16bit m_read_epoch = 0;
00125       u64bit m_window_highest = 0;
00126       u64bit m_window_bits = 0;
00127    };
00128 
00129 }
00130 
00131 }
00132 
00133 #endif