• 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

98.13
/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/internal/fmt.h>
12

13
namespace Botan {
14

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

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

30
void CFB_Mode::reset() {
474✔
31
   m_state.clear();
474✔
32
   zeroise(m_keystream);
474✔
33
}
474✔
34

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

43
size_t CFB_Mode::output_length(size_t input_length) const { return input_length; }
158✔
44

45
size_t CFB_Mode::update_granularity() const { return feedback(); }
553✔
46

47
size_t CFB_Mode::ideal_granularity() const {
478✔
48
   // Multiplier here is arbitrary
49
   return 16 * feedback();
478✔
50
}
51

52
size_t CFB_Mode::minimum_final_size() const { return 0; }
160✔
53

54
Key_Length_Specification CFB_Mode::key_spec() const { return cipher().key_spec(); }
478✔
55

56
size_t CFB_Mode::default_nonce_length() const { return block_size(); }
160✔
57

58
bool CFB_Mode::valid_nonce_length(size_t n) const { return (n == 0 || n == block_size()); }
1,544✔
59

60
bool CFB_Mode::has_keying_material() const { return m_cipher->has_keying_material(); }
4,430✔
61

62
void CFB_Mode::key_schedule(const uint8_t key[], size_t length) {
478✔
63
   m_cipher->set_key(key, length);
478✔
64
   m_keystream.resize(m_cipher->block_size());
478✔
65
}
478✔
66

67
void CFB_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) {
1,232✔
68
   if(!valid_nonce_length(nonce_len)) {
1,232✔
69
      throw Invalid_IV_Length(name(), nonce_len);
316✔
70
   }
71

72
   assert_key_material_set();
1,074✔
73

74
   if(nonce_len == 0) {
1,074✔
75
      if(m_state.empty()) {
30✔
76
         throw Invalid_State("CFB requires a non-empty initial nonce");
×
77
      }
78
      // No reason to encrypt state->keystream_buf, because no change
79
   } else {
80
      m_state.assign(nonce, nonce + nonce_len);
1,044✔
81
      cipher().encrypt(m_state, m_keystream);
1,044✔
82
      m_keystream_pos = 0;
1,044✔
83
   }
84
}
1,074✔
85

86
void CFB_Mode::shift_register() {
3,966✔
87
   const size_t shift = feedback();
3,966✔
88
   const size_t carryover = block_size() - shift;
3,966✔
89

90
   if(carryover > 0) {
3,966✔
91
      copy_mem(m_state.data(), &m_state[shift], carryover);
3,104✔
92
   }
93
   copy_mem(&m_state[carryover], m_keystream.data(), shift);
3,966✔
94
   cipher().encrypt(m_state, m_keystream);
3,966✔
95
   m_keystream_pos = 0;
3,966✔
96
}
3,966✔
97

98
size_t CFB_Encryption::process_msg(uint8_t buf[], size_t sz) {
1,441✔
99
   assert_key_material_set();
1,441✔
100
   BOTAN_STATE_CHECK(m_state.empty() == false);
1,125✔
101

102
   const size_t shift = feedback();
967✔
103

104
   size_t left = sz;
967✔
105

106
   if(m_keystream_pos != 0) {
967✔
107
      const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
13✔
108

109
      xor_buf(m_keystream.data() + m_keystream_pos, buf, take);
13✔
110
      copy_mem(buf, m_keystream.data() + m_keystream_pos, take);
13✔
111

112
      m_keystream_pos += take;
13✔
113
      left -= take;
13✔
114
      buf += take;
13✔
115

116
      if(m_keystream_pos == shift) {
13✔
117
         shift_register();
10✔
118
      }
119
   }
120

121
   while(left >= shift) {
2,940✔
122
      xor_buf(m_keystream.data(), buf, shift);
1,973✔
123
      copy_mem(buf, m_keystream.data(), shift);
1,973✔
124

125
      left -= shift;
1,973✔
126
      buf += shift;
1,973✔
127
      shift_register();
1,973✔
128
   }
129

130
   if(left > 0) {
967✔
131
      xor_buf(m_keystream.data(), buf, left);
72✔
132
      copy_mem(buf, m_keystream.data(), left);
72✔
133
      m_keystream_pos += left;
72✔
134
   }
135

136
   return sz;
967✔
137
}
138

139
void CFB_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) { update(buffer, offset); }
616✔
140

141
namespace {
142

143
inline void xor_copy(uint8_t buf[], uint8_t key_buf[], size_t len) {
2,058✔
144
   for(size_t i = 0; i != len; ++i) {
9,865✔
145
      uint8_t k = key_buf[i];
7,807✔
146
      key_buf[i] = buf[i];
7,807✔
147
      buf[i] ^= k;
7,807✔
148
   }
149
}
150

151
}  // namespace
152

153
size_t CFB_Decryption::process_msg(uint8_t buf[], size_t sz) {
1,441✔
154
   assert_key_material_set();
1,441✔
155
   BOTAN_STATE_CHECK(m_state.empty() == false);
1,125✔
156

157
   const size_t shift = feedback();
967✔
158

159
   size_t left = sz;
967✔
160

161
   if(m_keystream_pos != 0) {
967✔
162
      const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
13✔
163

164
      xor_copy(buf, m_keystream.data() + m_keystream_pos, take);
13✔
165

166
      m_keystream_pos += take;
13✔
167
      left -= take;
13✔
168
      buf += take;
13✔
169

170
      if(m_keystream_pos == shift) {
13✔
171
         shift_register();
10✔
172
      }
173
   }
174

175
   while(left >= shift) {
2,940✔
176
      xor_copy(buf, m_keystream.data(), shift);
1,973✔
177
      left -= shift;
1,973✔
178
      buf += shift;
1,973✔
179
      shift_register();
1,973✔
180
   }
181

182
   if(left > 0) {
967✔
183
      xor_copy(buf, m_keystream.data(), left);
72✔
184
      m_keystream_pos += left;
72✔
185
   }
186

187
   return sz;
967✔
188
}
189

190
void CFB_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) { update(buffer, offset); }
616✔
191

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