Botan 2.19.3
Crypto and TLS for C&
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
11namespace Botan {
12
13CFB_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
36std::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
44size_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
63
65 {
66 return block_size();
67 }
68
69bool CFB_Mode::valid_nonce_length(size_t n) const
70 {
71 return (n == 0 || n == block_size());
72 }
73
74void 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
80void 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);
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
117size_t CFB_Encryption::process(uint8_t buf[], size_t sz)
118 {
119 verify_key_set(!m_keystream.empty());
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 {
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;
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
164 {
165 update(buffer, offset);
166 }
167
168namespace {
169
170inline 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
182size_t CFB_Decryption::process(uint8_t buf[], size_t sz)
183 {
184 verify_key_set(!m_keystream.empty());
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 {
204 }
205 }
206
207 while(left >= shift)
208 {
209 xor_copy(buf, m_keystream.data(), shift);
210 left -= shift;
211 buf += shift;
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
225 {
226 update(buffer, offset);
227 }
228
229}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
void encrypt(const uint8_t in[], uint8_t out[]) const
virtual size_t block_size() const =0
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition cfb.cpp:224
size_t process(uint8_t buf[], size_t size) override
Definition cfb.cpp:182
size_t process(uint8_t buf[], size_t size) override
Definition cfb.cpp:117
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition cfb.cpp:163
size_t block_size() const
Definition cfb.h:49
std::string name() const override final
Definition cfb.cpp:36
void clear() override final
Definition cfb.cpp:23
secure_vector< uint8_t > m_keystream
Definition cfb.h:52
void reset() override final
Definition cfb.cpp:30
void shift_register()
Definition cfb.cpp:103
size_t output_length(size_t input_length) const override final
Definition cfb.cpp:44
size_t feedback() const
Definition cfb.h:47
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
secure_vector< uint8_t > m_state
Definition cfb.h:51
const BlockCipher & cipher() const
Definition cfb.h:48
size_t m_keystream_pos
Definition cfb.h:53
Key_Length_Specification key_spec() const override final
Definition cfb.cpp:59
CFB_Mode(BlockCipher *cipher, size_t feedback_bits)
Definition cfb.cpp:13
size_t default_nonce_length() const override final
Definition cfb.cpp:64
size_t update_granularity() const override final
Definition cfb.cpp:49
void verify_key_set(bool cond) const
Definition sym_algo.h:171
virtual std::string name() const =0
virtual Key_Length_Specification key_spec() const =0
int(* update)(CTX *, const void *, CC_LONG len)
void zeroise(std::vector< T, Alloc > &vec)
Definition secmem.h:114
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:133
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition mem_ops.h:262
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65