Botan  2.8.0
Crypto and TLS for C++11
cfb.cpp
Go to the documentation of this file.
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/cfb.h>
10 
11 namespace Botan {
12 
13 CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) :
14  m_cipher(cipher),
15  m_block_size(m_cipher->block_size()),
16  m_feedback_bytes(feedback_bits ? feedback_bits / 8 : m_block_size)
17  {
18  if(feedback_bits % 8 || feedback() > cipher->block_size())
19  throw Invalid_Argument(name() + ": feedback bits " +
20  std::to_string(feedback_bits) + " not supported");
21  }
22 
24  {
25  m_cipher->clear();
26  m_keystream.clear();
27  reset();
28  }
29 
31  {
32  m_state.clear();
34  }
35 
36 std::string CFB_Mode::name() const
37  {
38  if(feedback() == cipher().block_size())
39  return cipher().name() + "/CFB";
40  else
41  return cipher().name() + "/CFB(" + std::to_string(feedback()*8) + ")";
42  }
43 
44 size_t CFB_Mode::output_length(size_t input_length) const
45  {
46  return input_length;
47  }
48 
50  {
51  return feedback();
52  }
53 
55  {
56  return 0;
57  }
58 
60  {
61  return cipher().key_spec();
62  }
63 
65  {
66  return block_size();
67  }
68 
69 bool CFB_Mode::valid_nonce_length(size_t n) const
70  {
71  return (n == 0 || n == block_size());
72  }
73 
74 void CFB_Mode::key_schedule(const uint8_t key[], size_t length)
75  {
76  m_cipher->set_key(key, length);
77  m_keystream.resize(m_cipher->block_size());
78  }
79 
80 void CFB_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
81  {
82  if(!valid_nonce_length(nonce_len))
83  throw Invalid_IV_Length(name(), nonce_len);
84 
86 
87  if(nonce_len == 0)
88  {
89  if(m_state.empty())
90  {
91  throw Invalid_State("CFB requires a non-empty initial nonce");
92  }
93  // No reason to encrypt state->keystream_buf, because no change
94  }
95  else
96  {
97  m_state.assign(nonce, nonce + nonce_len);
99  m_keystream_pos = 0;
100  }
101  }
102 
104  {
105  const size_t shift = feedback();
106  const size_t carryover = block_size() - shift;
107 
108  if(carryover > 0)
109  {
110  copy_mem(m_state.data(), &m_state[shift], carryover);
111  }
112  copy_mem(&m_state[carryover], m_keystream.data(), shift);
114  m_keystream_pos = 0;
115  }
116 
117 size_t CFB_Encryption::process(uint8_t buf[], size_t sz)
118  {
119  verify_key_set(m_keystream.size());
120  BOTAN_STATE_CHECK(m_state.empty() == false);
121 
122  const size_t shift = feedback();
123 
124  size_t left = sz;
125 
126  if(m_keystream_pos != 0)
127  {
128  const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
129 
130  xor_buf(m_keystream.data() + m_keystream_pos, buf, take);
131  copy_mem(buf, m_keystream.data() + m_keystream_pos, take);
132 
133  m_keystream_pos += take;
134  left -= take;
135  buf += take;
136 
137  if(m_keystream_pos == shift)
138  {
139  shift_register();
140  }
141  }
142 
143  while(left >= shift)
144  {
145  xor_buf(m_keystream.data(), buf, shift);
146  copy_mem(buf, m_keystream.data(), shift);
147 
148  left -= shift;
149  buf += shift;
150  shift_register();
151  }
152 
153  if(left > 0)
154  {
155  xor_buf(m_keystream.data(), buf, left);
156  copy_mem(buf, m_keystream.data(), left);
157  m_keystream_pos += left;
158  }
159 
160  return sz;
161  }
162 
163 void CFB_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
164  {
165  update(buffer, offset);
166  }
167 
168 namespace {
169 
170 inline void xor_copy(uint8_t buf[], uint8_t key_buf[], size_t len)
171  {
172  for(size_t i = 0; i != len; ++i)
173  {
174  uint8_t k = key_buf[i];
175  key_buf[i] = buf[i];
176  buf[i] ^= k;
177  }
178  }
179 
180 }
181 
182 size_t CFB_Decryption::process(uint8_t buf[], size_t sz)
183  {
184  verify_key_set(m_keystream.size());
185  BOTAN_STATE_CHECK(m_state.empty() == false);
186 
187  const size_t shift = feedback();
188 
189  size_t left = sz;
190 
191  if(m_keystream_pos != 0)
192  {
193  const size_t take = std::min<size_t>(left, shift - m_keystream_pos);
194 
195  xor_copy(buf, m_keystream.data() + m_keystream_pos, take);
196 
197  m_keystream_pos += take;
198  left -= take;
199  buf += take;
200 
201  if(m_keystream_pos == shift)
202  {
203  shift_register();
204  }
205  }
206 
207  while(left >= shift)
208  {
209  xor_copy(buf, m_keystream.data(), shift);
210  left -= shift;
211  buf += shift;
212  shift_register();
213  }
214 
215  if(left > 0)
216  {
217  xor_copy(buf, m_keystream.data(), left);
218  m_keystream_pos += left;
219  }
220 
221  return sz;
222  }
223 
224 void CFB_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
225  {
226  update(buffer, offset);
227  }
228 
229 }
void reset() override final
Definition: cfb.cpp:30
size_t minimum_final_size() const override final
Definition: cfb.cpp:54
bool valid_nonce_length(size_t n) const override final
Definition: cfb.cpp:69
void verify_key_set(bool cond) const
Definition: sym_algo.h:89
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: cfb.cpp:163
secure_vector< uint8_t > m_keystream
Definition: cfb.h:50
size_t feedback() const
Definition: cfb.h:45
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:49
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
void shift_register()
Definition: cfb.cpp:103
std::string name() const override final
Definition: cfb.cpp:36
CFB_Mode(BlockCipher *cipher, size_t feedback_bits)
Definition: cfb.cpp:13
size_t update_granularity() const override final
Definition: cfb.cpp:49
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:174
virtual std::string name() const =0
size_t output_length(size_t input_length) const override final
Definition: cfb.cpp:44
Key_Length_Specification key_spec() const override final
Definition: cfb.cpp:59
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: cfb.cpp:224
const BlockCipher & cipher() const
Definition: cfb.h:46
secure_vector< uint8_t > m_state
Definition: cfb.h:49
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
size_t m_keystream_pos
Definition: cfb.h:51
void clear() override final
Definition: cfb.cpp:23
size_t process(uint8_t buf[], size_t size) override
Definition: cfb.cpp:182
void encrypt(const uint8_t in[], uint8_t out[]) const
Definition: block_cipher.h:81
size_t block_size() const
Definition: cfb.h:47
virtual Key_Length_Specification key_spec() const =0
size_t default_nonce_length() const override final
Definition: cfb.cpp:64
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
size_t process(uint8_t buf[], size_t size) override
Definition: cfb.cpp:117
virtual size_t block_size() const =0
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:183