diff options
Diffstat (limited to 'old/botan/src/modes/cbc/cbc.cpp')
-rw-r--r-- | old/botan/src/modes/cbc/cbc.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/old/botan/src/modes/cbc/cbc.cpp b/old/botan/src/modes/cbc/cbc.cpp new file mode 100644 index 0000000..f26d4d6 --- /dev/null +++ b/old/botan/src/modes/cbc/cbc.cpp @@ -0,0 +1,158 @@ +/* +* CBC Mode +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cbc.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/* +* CBC Encryption Constructor +*/ +CBC_Encryption::CBC_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) : + BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), + padder(pad) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + } + +/* +* CBC Encryption Constructor +*/ +CBC_Encryption::CBC_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), + padder(pad) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + set_key(key); + set_iv(iv); + } + +/* +* Encrypt in CBC mode +*/ +void CBC_Encryption::write(const byte input[], u32bit length) + { + while(length) + { + u32bit xored = std::min(BLOCK_SIZE - position, length); + xor_buf(state + position, input, xored); + input += xored; + length -= xored; + position += xored; + if(position == BLOCK_SIZE) + { + cipher->encrypt(state); + send(state, BLOCK_SIZE); + position = 0; + } + } + } + +/* +* Finish encrypting in CBC mode +*/ +void CBC_Encryption::end_msg() + { + SecureVector<byte> padding(BLOCK_SIZE); + padder->pad(padding, padding.size(), position); + write(padding, padder->pad_bytes(BLOCK_SIZE, position)); + if(position != 0) + throw Exception(name() + ": Did not pad to full blocksize"); + } + +/* +* Return a CBC mode name +*/ +std::string CBC_Encryption::name() const + { + return (cipher->name() + "/" + mode_name + "/" + padder->name()); + } + +/* +* CBC Decryption Constructor +*/ +CBC_Decryption::CBC_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) : + BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), + padder(pad) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + temp.create(BLOCK_SIZE); + } + +/* +* CBC Decryption Constructor +*/ +CBC_Decryption::CBC_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), + padder(pad) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + temp.create(BLOCK_SIZE); + set_key(key); + set_iv(iv); + } + +/* +* Decrypt in CBC mode +*/ +void CBC_Decryption::write(const byte input[], u32bit length) + { + while(length) + { + if(position == BLOCK_SIZE) + { + cipher->decrypt(buffer, temp); + xor_buf(temp, state, BLOCK_SIZE); + send(temp, BLOCK_SIZE); + state = buffer; + position = 0; + } + u32bit added = std::min(BLOCK_SIZE - position, length); + buffer.copy(position, input, added); + input += added; + length -= added; + position += added; + } + } + +/* +* Finish decrypting in CBC mode +*/ +void CBC_Decryption::end_msg() + { + if(position != BLOCK_SIZE) + throw Decoding_Error(name()); + cipher->decrypt(buffer, temp); + xor_buf(temp, state, BLOCK_SIZE); + send(temp, padder->unpad(temp, BLOCK_SIZE)); + state = buffer; + position = 0; + } + +/* +* Return a CBC mode name +*/ +std::string CBC_Decryption::name() const + { + return (cipher->name() + "/" + mode_name + "/" + padder->name()); + } + +} |