Coverage Report

Created: 2020-05-23 13:54

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