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

randombit / botan / 16675351906

01 Aug 2025 12:42PM UTC coverage: 90.677% (-0.005%) from 90.682%
16675351906

Pull #5032

github

web-flow
Merge a58f968aa into a361efb2e
Pull Request #5032: Fix some readability-implict-bool-conversion warnings from clang-tidy

99982 of 110262 relevant lines covered (90.68%)

12222015.95 hits per line

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

92.73
/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,151✔
18
      m_cipher(std::move(cipher)),
1,151✔
19
      m_block_size(m_cipher->block_size()),
1,151✔
20
      m_ctr_size(m_block_size),
1,151✔
21
      m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
1,151✔
22
      m_counter(m_cipher->parallel_bytes()),
2,302✔
23
      m_pad(m_counter.size()),
1,151✔
24
      m_pad_pos(0) {}
3,453✔
25

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

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

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

49
bool CTR_BE::valid_iv_length(size_t iv_len) const {
315,861✔
50
   return (iv_len <= m_block_size);
315,861✔
51
}
52

53
size_t CTR_BE::buffer_size() const {
840✔
54
   return m_pad.size();
840✔
55
}
56

57
Key_Length_Specification CTR_BE::key_spec() const {
203,138✔
58
   return m_cipher->key_spec();
203,138✔
59
}
60

61
std::unique_ptr<StreamCipher> CTR_BE::new_object() const {
819✔
62
   return std::make_unique<CTR_BE>(m_cipher->new_object(), m_ctr_size);
819✔
63
}
64

65
bool CTR_BE::has_keying_material() const {
20,867,039✔
66
   return m_cipher->has_keying_material();
20,867,039✔
67
}
68

69
void CTR_BE::key_schedule(std::span<const uint8_t> key) {
101,980✔
70
   m_cipher->set_key(key);
101,980✔
71

72
   // Set a default all-zeros IV
73
   set_iv(nullptr, 0);
101,980✔
74
}
101,980✔
75

76
std::string CTR_BE::name() const {
7,443✔
77
   if(m_ctr_size == m_block_size) {
7,443✔
78
      return fmt("CTR-BE({})", m_cipher->name());
6,545✔
79
   } else {
80
      return fmt("CTR-BE({},{})", m_cipher->name(), m_ctr_size);
898✔
81
   }
82
}
83

84
void CTR_BE::cipher_bytes(const uint8_t in[], uint8_t out[], size_t length) {
60,063✔
85
   assert_key_material_set();
60,063✔
86

87
   const uint8_t* pad_bits = m_pad.data();
57,857✔
88
   const size_t pad_size = m_pad.size();
57,857✔
89

90
   if(m_pad_pos > 0) {
57,857✔
91
      const size_t avail = pad_size - m_pad_pos;
38,979✔
92
      const size_t take = std::min(length, avail);
38,979✔
93
      xor_buf(out, in, pad_bits + m_pad_pos, take);
38,979✔
94
      length -= take;
38,979✔
95
      in += take;
38,979✔
96
      out += take;
38,979✔
97
      m_pad_pos += take;
38,979✔
98

99
      if(take == avail) {
38,979✔
100
         add_counter(m_ctr_blocks);
2,003✔
101
         m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
2,003✔
102
         m_pad_pos = 0;
2,003✔
103
      }
104
   }
105

106
   while(length >= pad_size) {
66,073✔
107
      xor_buf(out, in, pad_bits, pad_size);
8,216✔
108
      length -= pad_size;
8,216✔
109
      in += pad_size;
8,216✔
110
      out += pad_size;
8,216✔
111

112
      add_counter(m_ctr_blocks);
8,216✔
113
      m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
8,216✔
114
   }
115

116
   xor_buf(out, in, pad_bits, length);
57,857✔
117
   m_pad_pos += length;
57,857✔
118
}
57,857✔
119

120
void CTR_BE::generate_keystream(uint8_t out[], size_t length) {
20,577,905✔
121
   assert_key_material_set();
20,577,905✔
122

123
   const size_t avail = m_pad.size() - m_pad_pos;
20,577,905✔
124
   const size_t take = std::min(length, avail);
20,577,905✔
125
   copy_mem(out, &m_pad[m_pad_pos], take);
20,577,905✔
126
   length -= take;
20,577,905✔
127
   out += take;
20,577,905✔
128
   m_pad_pos += take;
20,577,905✔
129

130
   while(length >= m_pad.size()) {
20,578,633✔
131
      add_counter(m_ctr_blocks);
728✔
132
      m_cipher->encrypt_n(m_counter.data(), out, m_ctr_blocks);
728✔
133

134
      length -= m_pad.size();
728✔
135
      out += m_pad.size();
728✔
136
   }
137

138
   if(m_pad_pos == m_pad.size()) {
20,577,905✔
139
      add_counter(m_ctr_blocks);
82,974✔
140
      m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
82,974✔
141
      m_pad_pos = 0;
82,974✔
142
   }
143

144
   copy_mem(out, m_pad.data(), length);
20,577,905✔
145
   m_pad_pos += length;
20,577,905✔
146
   BOTAN_ASSERT_NOMSG(m_pad_pos < m_pad.size());
20,577,905✔
147
}
20,577,905✔
148

149
void CTR_BE::set_iv_bytes(const uint8_t iv[], size_t iv_len) {
219,308✔
150
   if(!valid_iv_length(iv_len)) {
219,308✔
151
      throw Invalid_IV_Length(name(), iv_len);
1,646✔
152
   }
153

154
   m_iv.resize(m_block_size);
218,485✔
155
   zeroise(m_iv);
218,485✔
156
   copy_mem(m_iv.data(), iv, iv_len);
218,485✔
157

158
   seek(0);
218,485✔
159
}
217,352✔
160

161
void CTR_BE::add_counter(const uint64_t counter) {
94,077✔
162
   const size_t ctr_size = m_ctr_size;
94,077✔
163
   const size_t ctr_blocks = m_ctr_blocks;
94,077✔
164
   const size_t BS = m_block_size;
94,077✔
165

166
   if(ctr_size == 4) {
94,077✔
167
      const size_t off = (BS - 4);
6,629✔
168
      const uint32_t low32 = static_cast<uint32_t>(counter + load_be<uint32_t>(&m_counter[off], 0));
6,629✔
169

170
      for(size_t i = 0; i != ctr_blocks; ++i) {
179,893✔
171
         store_be(uint32_t(low32 + i), &m_counter[i * BS + off]);
173,264✔
172
      }
173
   } else if(ctr_size == 8) {
87,448✔
174
      const size_t off = (BS - 8);
4,818✔
175
      const uint64_t low64 = counter + load_be<uint64_t>(&m_counter[off], 0);
4,818✔
176

177
      for(size_t i = 0; i != ctr_blocks; ++i) {
24,370✔
178
         store_be(uint64_t(low64 + i), &m_counter[i * BS + off]);
19,552✔
179
      }
180
   } else if(ctr_size == 16) {
82,630✔
181
      const size_t off = (BS - 16);
82,630✔
182
      uint64_t b0 = load_be<uint64_t>(&m_counter[off], 0);
82,630✔
183
      uint64_t b1 = load_be<uint64_t>(&m_counter[off], 1);
82,630✔
184
      b1 += counter;
82,630✔
185
      b0 += (b1 < counter) ? 1 : 0;  // carry
82,630✔
186

187
      for(size_t i = 0; i != ctr_blocks; ++i) {
2,726,790✔
188
         store_be(b0, &m_counter[i * BS + off]);
2,644,160✔
189
         store_be(b1, &m_counter[i * BS + off + 8]);
2,644,160✔
190
         b1 += 1;
2,644,160✔
191
         if(b1 == 0) {
2,644,160✔
192
            b0 += 1;  // carry
×
193
         }
194
      }
195
   } else {
196
      for(size_t i = 0; i != ctr_blocks; ++i) {
×
197
         uint64_t local_counter = counter;
×
198
         uint16_t carry = static_cast<uint8_t>(local_counter);
×
199
         for(size_t j = 0; (carry > 0 || local_counter > 0) && j != ctr_size; ++j) {
×
200
            const size_t off = i * BS + (BS - 1 - j);
×
201
            const uint16_t cnt = static_cast<uint16_t>(m_counter[off]) + carry;
×
202
            m_counter[off] = static_cast<uint8_t>(cnt);
×
203
            local_counter = (local_counter >> 8);
×
204
            carry = (cnt >> 8) + static_cast<uint8_t>(local_counter);
×
205
         }
206
      }
207
   }
208
}
94,077✔
209

210
void CTR_BE::seek(uint64_t offset) {
220,904✔
211
   assert_key_material_set();
220,904✔
212

213
   const uint64_t base_counter = m_ctr_blocks * (offset / m_counter.size());
218,952✔
214

215
   zeroise(m_counter);
218,952✔
216
   BOTAN_ASSERT_NOMSG(m_counter.size() >= m_iv.size());
218,952✔
217
   copy_mem(m_counter.data(), m_iv.data(), m_iv.size());
218,952✔
218

219
   const size_t BS = m_block_size;
218,952✔
220

221
   // Set m_counter blocks to IV, IV + 1, ... IV + n
222

223
   if(m_ctr_size == 4 && BS >= 8) {
218,952✔
224
      const uint32_t low32 = load_be<uint32_t>(&m_counter[BS - 4], 0);
16,594✔
225

226
      if(m_ctr_blocks >= 4 && is_power_of_2(m_ctr_blocks)) {
16,594✔
227
         size_t written = 1;
228
         while(written < m_ctr_blocks) {
98,190✔
229
            copy_mem(&m_counter[written * BS], &m_counter[0], BS * written);  // NOLINT(*container-data-pointer)
81,596✔
230
            written *= 2;
81,596✔
231
         }
232
      } else {
233
         for(size_t i = 1; i != m_ctr_blocks; ++i) {
×
234
            copy_mem(&m_counter[i * BS], &m_counter[0], BS - 4);  // NOLINT(*container-data-pointer)
×
235
         }
236
      }
237

238
      for(size_t i = 1; i != m_ctr_blocks; ++i) {
518,144✔
239
         const uint32_t c = static_cast<uint32_t>(low32 + i);
501,550✔
240
         store_be(c, &m_counter[(BS - 4) + i * BS]);
501,550✔
241
      }
242
   } else {
243
      // do everything sequentially:
244
      for(size_t i = 1; i != m_ctr_blocks; ++i) {
6,317,616✔
245
         copy_mem(&m_counter[i * BS], &m_counter[(i - 1) * BS], BS);
6,115,258✔
246

247
         for(size_t j = 0; j != m_ctr_size; ++j) {
6,117,754✔
248
            uint8_t& c = m_counter[i * BS + (BS - 1 - j)];
6,117,715✔
249
            c += 1;
6,117,715✔
250
            if(c > 0) {
6,117,715✔
251
               break;
252
            }
253
         }
254
      }
255
   }
256

257
   if(base_counter > 0) {
218,952✔
258
      add_counter(base_counter);
156✔
259
   }
260

261
   m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
218,952✔
262
   m_pad_pos = offset % m_counter.size();
218,952✔
263
}
218,952✔
264
}  // 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

© 2026 Coveralls, Inc