• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.95
/src/lib/stream/ctr/ctr.cpp
1
/*
2
* Counter mode
3
* (C) 1999-2011,2014 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/internal/ctr.h>
9

10
#include <botan/exceptn.h>
11
#include <botan/internal/bit_ops.h>
12
#include <botan/internal/fmt.h>
13
#include <botan/internal/loadstor.h>
14

15
namespace Botan {
16

17
CTR_BE::CTR_BE(std::unique_ptr<BlockCipher> cipher) :
1,149✔
18
      m_cipher(std::move(cipher)),
1,149✔
19
      m_block_size(m_cipher->block_size()),
1,149✔
20
      m_ctr_size(m_block_size),
1,149✔
21
      m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
1,149✔
22
      m_counter(m_cipher->parallel_bytes()),
2,298✔
23
      m_pad(m_counter.size()),
1,149✔
24
      m_pad_pos(0) {}
2,298✔
25

26
CTR_BE::CTR_BE(std::unique_ptr<BlockCipher> cipher, size_t ctr_size) :
99,521✔
27
      m_cipher(std::move(cipher)),
99,521✔
28
      m_block_size(m_cipher->block_size()),
99,521✔
29
      m_ctr_size(ctr_size),
99,521✔
30
      m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
99,521✔
31
      m_counter(m_cipher->parallel_bytes()),
199,042✔
32
      m_pad(m_counter.size()),
99,521✔
33
      m_pad_pos(0) {
199,042✔
34
   BOTAN_ARG_CHECK(m_ctr_size >= 4 && m_ctr_size <= m_block_size, "Invalid CTR-BE counter size");
99,521✔
35
}
99,521✔
36

37
void CTR_BE::clear() {
2,217✔
38
   m_cipher->clear();
2,217✔
39
   zeroise(m_pad);
2,217✔
40
   zeroise(m_counter);
2,217✔
41
   zap(m_iv);
2,217✔
42
   m_pad_pos = 0;
2,217✔
43
}
2,217✔
44

45
size_t CTR_BE::default_iv_length() const { return m_block_size; }
1,638✔
46

47
bool CTR_BE::valid_iv_length(size_t iv_len) const { return (iv_len <= m_block_size); }
232,789✔
48

49
size_t CTR_BE::buffer_size() const { return m_pad.size(); }
844✔
50

51
Key_Length_Specification CTR_BE::key_spec() const { return m_cipher->key_spec(); }
289,553✔
52

53
std::unique_ptr<StreamCipher> CTR_BE::new_object() const {
1,740✔
54
   return std::make_unique<CTR_BE>(m_cipher->new_object(), m_ctr_size);
1,740✔
55
}
56

57
bool CTR_BE::has_keying_material() const { return m_cipher->has_keying_material(); }
417,109✔
58

59
void CTR_BE::key_schedule(const uint8_t key[], size_t key_len) {
104,104✔
60
   m_cipher->set_key(key, key_len);
104,104✔
61

62
   // Set a default all-zeros IV
63
   set_iv(nullptr, 0);
104,104✔
64
}
104,104✔
65

66
std::string CTR_BE::name() const {
7,539✔
67
   if(m_ctr_size == m_block_size) {
7,539✔
68
      return fmt("CTR-BE({})", m_cipher->name());
6,653✔
69
   } else {
70
      return fmt("CTR-BE({},{})", m_cipher->name(), m_ctr_size);
886✔
71
   }
72
}
73

74
void CTR_BE::cipher_bytes(const uint8_t in[], uint8_t out[], size_t length) {
38,628✔
75
   assert_key_material_set();
38,628✔
76

77
   const uint8_t* pad_bits = &m_pad[0];
36,334✔
78
   const size_t pad_size = m_pad.size();
36,334✔
79

80
   if(m_pad_pos > 0) {
36,334✔
81
      const size_t avail = pad_size - m_pad_pos;
19,143✔
82
      const size_t take = std::min(length, avail);
19,143✔
83
      xor_buf(out, in, pad_bits + m_pad_pos, take);
19,143✔
84
      length -= take;
19,143✔
85
      in += take;
19,143✔
86
      out += take;
19,143✔
87
      m_pad_pos += take;
19,143✔
88

89
      if(take == avail) {
19,143✔
90
         add_counter(m_ctr_blocks);
1,600✔
91
         m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
1,600✔
92
         m_pad_pos = 0;
1,600✔
93
      }
94
   }
95

96
   while(length >= pad_size) {
48,863✔
97
      xor_buf(out, in, pad_bits, pad_size);
12,529✔
98
      length -= pad_size;
12,529✔
99
      in += pad_size;
12,529✔
100
      out += pad_size;
12,529✔
101

102
      add_counter(m_ctr_blocks);
12,529✔
103
      m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
12,529✔
104
   }
105

106
   xor_buf(out, in, pad_bits, length);
36,334✔
107
   m_pad_pos += length;
36,334✔
108
}
36,334✔
109

110
void CTR_BE::generate_keystream(uint8_t out[], size_t length) {
138,422✔
111
   assert_key_material_set();
138,422✔
112

113
   const size_t avail = m_pad.size() - m_pad_pos;
138,422✔
114
   const size_t take = std::min(length, avail);
138,422✔
115
   copy_mem(out, &m_pad[m_pad_pos], take);
138,422✔
116
   length -= take;
138,422✔
117
   out += take;
138,422✔
118
   m_pad_pos += take;
138,422✔
119

120
   while(length >= m_pad.size()) {
289,314✔
121
      add_counter(m_ctr_blocks);
150,892✔
122
      m_cipher->encrypt_n(m_counter.data(), out, m_ctr_blocks);
150,892✔
123

124
      length -= m_pad.size();
150,892✔
125
      out += m_pad.size();
150,892✔
126
   }
127

128
   if(m_pad_pos == m_pad.size()) {
138,422✔
129
      add_counter(m_ctr_blocks);
103,064✔
130
      m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
103,064✔
131
      m_pad_pos = 0;
103,064✔
132
   }
133

134
   copy_mem(out, &m_pad[0], length);
138,422✔
135
   m_pad_pos += length;
138,422✔
136
   BOTAN_ASSERT_NOMSG(m_pad_pos < m_pad.size());
138,422✔
137
}
138,422✔
138

139
void CTR_BE::set_iv_bytes(const uint8_t iv[], size_t iv_len) {
230,316✔
140
   if(!valid_iv_length(iv_len)) {
230,316✔
141
      throw Invalid_IV_Length(name(), iv_len);
1,654✔
142
   }
143

144
   m_iv.resize(m_block_size);
229,489✔
145
   zeroise(m_iv);
229,489✔
146
   buffer_insert(m_iv, 0, iv, iv_len);
229,489✔
147

148
   seek(0);
229,489✔
149
}
228,356✔
150

151
void CTR_BE::add_counter(const uint64_t counter) {
268,241✔
152
   const size_t ctr_size = m_ctr_size;
268,241✔
153
   const size_t ctr_blocks = m_ctr_blocks;
268,241✔
154
   const size_t BS = m_block_size;
268,241✔
155

156
   if(ctr_size == 4) {
268,241✔
157
      const size_t off = (BS - 4);
10,402✔
158
      const uint32_t low32 = static_cast<uint32_t>(counter + load_be<uint32_t>(&m_counter[off], 0));
10,402✔
159

160
      for(size_t i = 0; i != ctr_blocks; ++i) {
161,594✔
161
         store_be(uint32_t(low32 + i), &m_counter[i * BS + off]);
151,192✔
162
      }
163
   } else if(ctr_size == 8) {
257,839✔
164
      const size_t off = (BS - 8);
4,888✔
165
      const uint64_t low64 = counter + load_be<uint64_t>(&m_counter[off], 0);
4,888✔
166

167
      for(size_t i = 0; i != ctr_blocks; ++i) {
25,400✔
168
         store_be(uint64_t(low64 + i), &m_counter[i * BS + off]);
20,512✔
169
      }
170
   } else if(ctr_size == 16) {
252,951✔
171
      const size_t off = (BS - 16);
252,951✔
172
      uint64_t b0 = load_be<uint64_t>(&m_counter[off], 0);
252,951✔
173
      uint64_t b1 = load_be<uint64_t>(&m_counter[off], 1);
252,951✔
174
      b1 += counter;
252,951✔
175
      b0 += (b1 < counter) ? 1 : 0;  // carry
252,951✔
176

177
      for(size_t i = 0; i != ctr_blocks; ++i) {
4,300,167✔
178
         store_be(b0, &m_counter[i * BS + off]);
4,047,216✔
179
         store_be(b1, &m_counter[i * BS + off + 8]);
4,047,216✔
180
         b1 += 1;
4,047,216✔
181
         b0 += (b1 == 0);  // carry
4,047,216✔
182
      }
183
   } else {
184
      for(size_t i = 0; i != ctr_blocks; ++i) {
×
185
         uint64_t local_counter = counter;
×
186
         uint16_t carry = static_cast<uint8_t>(local_counter);
×
187
         for(size_t j = 0; (carry || local_counter) && j != ctr_size; ++j) {
×
188
            const size_t off = i * BS + (BS - 1 - j);
×
189
            const uint16_t cnt = static_cast<uint16_t>(m_counter[off]) + carry;
×
190
            m_counter[off] = static_cast<uint8_t>(cnt);
×
191
            local_counter = (local_counter >> 8);
×
192
            carry = (cnt >> 8) + static_cast<uint8_t>(local_counter);
×
193
         }
194
      }
195
   }
196
}
268,241✔
197

198
void CTR_BE::seek(uint64_t offset) {
231,908✔
199
   assert_key_material_set();
231,908✔
200

201
   const uint64_t base_counter = m_ctr_blocks * (offset / m_counter.size());
229,956✔
202

203
   zeroise(m_counter);
229,956✔
204
   buffer_insert(m_counter, 0, m_iv);
229,956✔
205

206
   const size_t BS = m_block_size;
229,956✔
207

208
   // Set m_counter blocks to IV, IV + 1, ... IV + n
209

210
   if(m_ctr_size == 4 && BS >= 8) {
229,956✔
211
      const uint32_t low32 = load_be<uint32_t>(&m_counter[BS - 4], 0);
14,425✔
212

213
      if(m_ctr_blocks >= 4 && is_power_of_2(m_ctr_blocks)) {
14,425✔
214
         size_t written = 1;
215
         while(written < m_ctr_blocks) {
69,300✔
216
            copy_mem(&m_counter[written * BS], &m_counter[0], BS * written);
54,875✔
217
            written *= 2;
54,875✔
218
         }
219
      } else {
220
         for(size_t i = 1; i != m_ctr_blocks; ++i) {
×
221
            copy_mem(&m_counter[i * BS], &m_counter[0], BS - 4);
×
222
         }
223
      }
224

225
      for(size_t i = 1; i != m_ctr_blocks; ++i) {
209,680✔
226
         const uint32_t c = static_cast<uint32_t>(low32 + i);
195,255✔
227
         store_be(c, &m_counter[(BS - 4) + i * BS]);
195,255✔
228
      }
229
   } else {
230
      // do everything sequentially:
231
      for(size_t i = 1; i != m_ctr_blocks; ++i) {
3,402,224✔
232
         buffer_insert(m_counter, i * BS, &m_counter[(i - 1) * BS], BS);
3,186,693✔
233

234
         for(size_t j = 0; j != m_ctr_size; ++j) {
3,188,859✔
235
            if(++m_counter[i * BS + (BS - 1 - j)]) {
3,188,820✔
236
               break;
237
            }
238
         }
239
      }
240
   }
241

242
   if(base_counter > 0) {
229,956✔
243
      add_counter(base_counter);
156✔
244
   }
245

246
   m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
229,956✔
247
   m_pad_pos = offset % m_counter.size();
229,956✔
248
}
229,956✔
249
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc