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

randombit / botan / 26323460081

23 May 2026 12:00AM UTC coverage: 89.383% (+0.03%) from 89.349%
26323460081

push

github

web-flow
Merge pull request #5621 from randombit/jack/cli-port-shift

Move the cli test TCP/UDP port range downward

109787 of 122827 relevant lines covered (89.38%)

11032030.9 hits per line

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

98.33
/src/lib/modes/cfb/cfb.cpp
1
/*
2
* CFB Mode
3
* (C) 1999-2007,2013,2017 Jack Lloyd
4
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/internal/cfb.h>
10

11
#include <botan/exceptn.h>
12
#include <botan/mem_ops.h>
13
#include <botan/internal/fmt.h>
14

15
namespace Botan {
16

17
CFB_Mode::CFB_Mode(std::unique_ptr<BlockCipher> cipher, size_t feedback_bits) :
705✔
18
      m_cipher(std::move(cipher)),
705✔
19
      m_block_size(m_cipher->block_size()),
705✔
20
      m_feedback_bytes(feedback_bits != 0 ? feedback_bits / 8 : m_block_size) {
705✔
21
   if(feedback_bits % 8 != 0 || feedback() > m_block_size) {
705✔
22
      throw Invalid_Argument(fmt("{} does not support feedback bits of {}", name(), feedback_bits));
×
23
   }
24
}
705✔
25

26
void CFB_Mode::clear() {
158✔
27
   m_cipher->clear();
158✔
28
   m_keystream.clear();
158✔
29
   reset();
316✔
30
}
158✔
31

32
void CFB_Mode::reset() {
1,574✔
33
   m_state.clear();
18,640✔
34
   zeroise(m_keystream);
1,574✔
35
   m_keystream_pos = 0;
1,574✔
36
}
316✔
37

38
std::string CFB_Mode::name() const {
948✔
39
   if(feedback() == cipher().block_size()) {
948✔
40
      return fmt("{}/CFB", cipher().name());
396✔
41
   } else {
42
      return fmt("{}/CFB({})", cipher().name(), feedback() * 8);
552✔
43
   }
44
}
45

46
size_t CFB_Mode::output_length(size_t input_length) const {
158✔
47
   return input_length;
158✔
48
}
49

50
size_t CFB_Mode::update_granularity() const {
553✔
51
   return feedback();
553✔
52
}
53

54
size_t CFB_Mode::ideal_granularity() const {
478✔
55
   // Multiplier here is arbitrary
56
   return 16 * feedback();
478✔
57
}
58

59
size_t CFB_Mode::minimum_final_size() const {
160✔
60
   return 0;
160✔
61
}
62

63
Key_Length_Specification CFB_Mode::key_spec() const {
1,406✔
64
   return cipher().key_spec();
1,406✔
65
}
66

67
size_t CFB_Mode::default_nonce_length() const {
466✔
68
   return block_size();
466✔
69
}
70

71
bool CFB_Mode::valid_nonce_length(size_t n) const {
2,340✔
72
   return (n == 0 || n == block_size());
2,310✔
73
}
74

75
bool CFB_Mode::has_keying_material() const {
6,422✔
76
   return m_cipher->has_keying_material();
6,422✔
77
}
78

79
void CFB_Mode::key_schedule(std::span<const uint8_t> key) {
1,100✔
80
   m_cipher->set_key(key);
1,100✔
81
   m_keystream.resize(m_cipher->block_size());
1,100✔
82

83
   // Drop the IV/feedback register and keystream from any prior message;
84
   // they were computed under the previous key.
85
   reset();
1,100✔
86
}
1,100✔
87

88
void CFB_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) {
1,998✔
89
   if(!valid_nonce_length(nonce_len)) {
1,998✔
90
      throw Invalid_IV_Length(name(), nonce_len);
316✔
91
   }
92

93
   assert_key_material_set();
1,840✔
94

95
   if(nonce_len == 0) {
1,840✔
96
      if(m_state.empty()) {
30✔
97
         throw Invalid_State("CFB requires a non-empty initial nonce");
×
98
      }
99
      // No reason to encrypt state->keystream_buf, because no change
100
   } else {
101
      m_state.assign(nonce, nonce + nonce_len);
1,810✔
102
      cipher().encrypt(m_state, m_keystream);
1,810✔
103
      m_keystream_pos = 0;
1,810✔
104
   }
105
}
1,840✔
106

107
void CFB_Mode::shift_register() {
8,079✔
108
   const size_t shift = feedback();
8,079✔
109
   const size_t carryover = block_size() - shift;
8,079✔
110

111
   if(carryover > 0) {
8,079✔
112
      copy_mem(m_state.data(), &m_state[shift], carryover);
4,388✔
113
   }
114
   copy_mem(&m_state[carryover], m_keystream.data(), shift);
8,079✔
115
   cipher().encrypt(m_state, m_keystream);
8,079✔
116
   m_keystream_pos = 0;
8,079✔
117
}
8,079✔
118

119
size_t CFB_Encryption::process_msg(uint8_t buf[], size_t sz) {
2,002✔
120
   assert_key_material_set();
2,002✔
121
   BOTAN_STATE_CHECK(m_state.empty() == false);
1,686✔
122

123
   const size_t shift = feedback();
1,370✔
124

125
   size_t left = sz;
1,370✔
126

127
   if(m_keystream_pos != 0) {
1,370✔
128
      const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
13✔
129

130
      xor_buf(m_keystream.data() + m_keystream_pos, buf, take);
13✔
131
      copy_mem(buf, m_keystream.data() + m_keystream_pos, take);
13✔
132

133
      m_keystream_pos += take;
13✔
134
      left -= take;
13✔
135
      buf += take;
13✔
136

137
      if(m_keystream_pos == shift) {
13✔
138
         shift_register();
10✔
139
      }
140
   }
141

142
   while(left >= shift) {
4,892✔
143
      xor_buf(m_keystream.data(), buf, shift);
3,522✔
144
      copy_mem(buf, m_keystream.data(), shift);
3,522✔
145

146
      left -= shift;
3,522✔
147
      buf += shift;
3,522✔
148
      shift_register();
3,522✔
149
   }
150

151
   if(left > 0) {
1,370✔
152
      xor_buf(m_keystream.data(), buf, left);
147✔
153
      copy_mem(buf, m_keystream.data(), left);
147✔
154
      m_keystream_pos += left;
147✔
155
   }
156

157
   return sz;
1,370✔
158
}
159

160
void CFB_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
846✔
161
   update(buffer, offset);
846✔
162
}
530✔
163

164
namespace {
165

166
inline void xor_copy(uint8_t buf[], uint8_t key_buf[], size_t len) {
4,805✔
167
   for(size_t i = 0; i != len; ++i) {
44,653✔
168
      const uint8_t k = key_buf[i];
39,848✔
169
      key_buf[i] = buf[i];
39,848✔
170
      buf[i] ^= k;
39,848✔
171
   }
172
}
173

174
}  // namespace
175

176
size_t CFB_Decryption::process_msg(uint8_t buf[], size_t sz) {
2,106✔
177
   assert_key_material_set();
2,106✔
178
   BOTAN_STATE_CHECK(m_state.empty() == false);
1,790✔
179

180
   const size_t shift = feedback();
1,474✔
181

182
   size_t left = sz;
1,474✔
183

184
   if(m_keystream_pos != 0) {
1,474✔
185
      const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
13✔
186

187
      xor_copy(buf, m_keystream.data() + m_keystream_pos, take);
13✔
188

189
      m_keystream_pos += take;
13✔
190
      left -= take;
13✔
191
      buf += take;
13✔
192

193
      if(m_keystream_pos == shift) {
13✔
194
         shift_register();
10✔
195
      }
196
   }
197

198
   while(left >= shift) {
6,011✔
199
      xor_copy(buf, m_keystream.data(), shift);
4,537✔
200
      left -= shift;
4,537✔
201
      buf += shift;
4,537✔
202
      shift_register();
4,537✔
203
   }
204

205
   if(left > 0) {
1,474✔
206
      xor_copy(buf, m_keystream.data(), left);
255✔
207
      m_keystream_pos += left;
255✔
208
   }
209

210
   return sz;
1,474✔
211
}
212

213
void CFB_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
846✔
214
   update(buffer, offset);
846✔
215
}
530✔
216

217
}  // 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