Botan 3.6.1
Crypto and TLS for C&
tls_seq_numbers.h
Go to the documentation of this file.
1/*
2* TLS Sequence Number Handling
3* (C) 2012 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_TLS_SEQ_NUMBERS_H_
9#define BOTAN_TLS_SEQ_NUMBERS_H_
10
11#include <botan/exceptn.h>
12#include <map>
13
14namespace Botan::TLS {
15
17 public:
18 virtual ~Connection_Sequence_Numbers() = default;
19
20 virtual void new_read_cipher_state() = 0;
21 virtual void new_write_cipher_state() = 0;
22
23 virtual uint16_t current_read_epoch() const = 0;
24 virtual uint16_t current_write_epoch() const = 0;
25
26 virtual uint64_t next_write_sequence(uint16_t) = 0;
27 virtual uint64_t next_read_sequence() = 0;
28
29 virtual bool already_seen(uint64_t seq) const = 0;
30 virtual void read_accept(uint64_t seq) = 0;
31
32 virtual void reset() = 0;
33};
34
36 public:
38
39 void reset() override {
40 m_write_seq_no = 0;
41 m_read_seq_no = 0;
42 m_read_epoch = 0;
43 m_write_epoch = 0;
44 }
45
46 void new_read_cipher_state() override {
47 m_read_seq_no = 0;
48 m_read_epoch++;
49 }
50
51 void new_write_cipher_state() override {
52 m_write_seq_no = 0;
53 m_write_epoch++;
54 }
55
56 uint16_t current_read_epoch() const override { return m_read_epoch; }
57
58 uint16_t current_write_epoch() const override { return m_write_epoch; }
59
60 uint64_t next_write_sequence(uint16_t) override { return m_write_seq_no++; }
61
62 uint64_t next_read_sequence() override { return m_read_seq_no; }
63
64 bool already_seen(uint64_t) const override { return false; }
65
66 void read_accept(uint64_t) override { m_read_seq_no++; }
67
68 private:
69 uint64_t m_write_seq_no;
70 uint64_t m_read_seq_no;
71 uint16_t m_read_epoch;
72 uint16_t m_write_epoch;
73};
74
76 public:
78
79 void reset() override {
80 m_write_seqs.clear();
81 m_write_seqs[0] = 0;
82 m_write_epoch = 0;
83 m_read_epoch = 0;
84 m_window_highest = 0;
85 m_window_bits = 0;
86 }
87
88 void new_read_cipher_state() override { m_read_epoch++; }
89
90 void new_write_cipher_state() override {
91 m_write_epoch++;
92 m_write_seqs[m_write_epoch] = 0;
93 }
94
95 uint16_t current_read_epoch() const override { return m_read_epoch; }
96
97 uint16_t current_write_epoch() const override { return m_write_epoch; }
98
99 uint64_t next_write_sequence(uint16_t epoch) override {
100 auto i = m_write_seqs.find(epoch);
101 BOTAN_ASSERT(i != m_write_seqs.end(), "Found epoch");
102 return (static_cast<uint64_t>(epoch) << 48) | i->second++;
103 }
104
105 uint64_t next_read_sequence() override { throw Invalid_State("DTLS uses explicit sequence numbers"); }
106
107 bool already_seen(uint64_t sequence) const override {
108 const size_t window_size = sizeof(m_window_bits) * 8;
109
110 if(sequence > m_window_highest) {
111 return false;
112 }
113
114 const uint64_t offset = m_window_highest - sequence;
115
116 if(offset >= window_size) {
117 return true; // really old?
118 }
119
120 return (((m_window_bits >> offset) & 1) == 1);
121 }
122
123 void read_accept(uint64_t sequence) override {
124 const size_t window_size = sizeof(m_window_bits) * 8;
125
126 if(sequence > m_window_highest) {
127 // We've received a later sequence which advances our window
128 const uint64_t offset = sequence - m_window_highest;
129 m_window_highest += offset;
130
131 if(offset >= window_size) {
132 m_window_bits = 0;
133 } else {
134 m_window_bits <<= offset;
135 }
136
137 m_window_bits |= 0x01;
138 } else {
139 const uint64_t offset = m_window_highest - sequence;
140
141 if(offset < window_size) {
142 // We've received an old sequence but still within our window
143 m_window_bits |= (static_cast<uint64_t>(1) << offset);
144 } else {
145 // This occurs only if we have reset state (DTLS reconnection case)
146 m_window_highest = sequence;
147 m_window_bits = 0;
148 }
149 }
150 }
151
152 private:
153 std::map<uint16_t, uint64_t> m_write_seqs;
154 uint16_t m_write_epoch = 0;
155 uint16_t m_read_epoch = 0;
156 uint64_t m_window_highest = 0;
157 uint64_t m_window_bits = 0;
158};
159
160} // namespace Botan::TLS
161
162#endif
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
virtual uint16_t current_read_epoch() const =0
virtual ~Connection_Sequence_Numbers()=default
virtual void read_accept(uint64_t seq)=0
virtual uint16_t current_write_epoch() const =0
virtual bool already_seen(uint64_t seq) const =0
virtual uint64_t next_write_sequence(uint16_t)=0
void read_accept(uint64_t sequence) override
uint16_t current_read_epoch() const override
uint16_t current_write_epoch() const override
uint64_t next_write_sequence(uint16_t epoch) override
bool already_seen(uint64_t sequence) const override
uint64_t next_write_sequence(uint16_t) override
void read_accept(uint64_t) override
uint16_t current_read_epoch() const override
bool already_seen(uint64_t) const override
uint16_t current_write_epoch() const override
int(* final)(unsigned char *, CTX *)