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