diff options
Diffstat (limited to 'src/modes/cfb/cfb.cpp')
-rw-r--r-- | src/modes/cfb/cfb.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/modes/cfb/cfb.cpp b/src/modes/cfb/cfb.cpp new file mode 100644 index 000000000..dbfbff6ae --- /dev/null +++ b/src/modes/cfb/cfb.cpp @@ -0,0 +1,142 @@ +/************************************************* +* CFB Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/cfb.h> +#include <botan/lookup.h> +#include <botan/parsing.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +namespace { + +/************************************************* +* Check the feedback size * +*************************************************/ +void check_feedback(u32bit BLOCK_SIZE, u32bit FEEDBACK_SIZE, u32bit bits, + const std::string& name) + { + if(FEEDBACK_SIZE == 0 || FEEDBACK_SIZE > BLOCK_SIZE || bits % 8 != 0) + throw Invalid_Argument(name + ": Invalid feedback size " + + to_string(bits)); + } + +} + +/************************************************* +* CFB Encryption Constructor * +*************************************************/ +CFB_Encryption::CFB_Encryption(const std::string& cipher_name, + u32bit fback_bits) : + BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1), + FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE) + { + check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + } + +/************************************************* +* CFB Encryption Constructor * +*************************************************/ +CFB_Encryption::CFB_Encryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit fback_bits) : + BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1), + FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE) + { + check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + set_key(key); + set_iv(iv); + } + +/************************************************* +* Encrypt data in CFB mode * +*************************************************/ +void CFB_Encryption::write(const byte input[], u32bit length) + { + while(length) + { + u32bit xored = std::min(FEEDBACK_SIZE - position, length); + xor_buf(buffer + position, input, xored); + send(buffer + position, xored); + input += xored; + length -= xored; + position += xored; + if(position == FEEDBACK_SIZE) + feedback(); + } + } + +/************************************************* +* Do the feedback * +*************************************************/ +void CFB_Encryption::feedback() + { + for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j) + state[j] = state[j + FEEDBACK_SIZE]; + state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE); + cipher->encrypt(state, buffer); + position = 0; + } + +/************************************************* +* CFB Decryption Constructor * +*************************************************/ +CFB_Decryption::CFB_Decryption(const std::string& cipher_name, + u32bit fback_bits) : + BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1), + FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE) + { + check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + } + +/************************************************* +* CFB Decryption Constructor * +*************************************************/ +CFB_Decryption::CFB_Decryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit fback_bits) : + BlockCipherMode(cipher_name, "CFB", block_size_of(cipher_name), 1), + FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE) + { + check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + set_key(key); + set_iv(iv); + } + +/************************************************* +* Decrypt data in CFB mode * +*************************************************/ +void CFB_Decryption::write(const byte input[], u32bit length) + { + while(length) + { + u32bit xored = std::min(FEEDBACK_SIZE - position, length); + xor_buf(buffer + position, input, xored); + send(buffer + position, xored); + buffer.copy(position, input, xored); + input += xored; + length -= xored; + position += xored; + if(position == FEEDBACK_SIZE) + feedback(); + } + } + +/************************************************* +* Do the feedback * +*************************************************/ +void CFB_Decryption::feedback() + { + for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j) + state[j] = state[j + FEEDBACK_SIZE]; + state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE); + cipher->encrypt(state, buffer); + position = 0; + } + +} |