diff options
author | lloyd <[email protected]> | 2013-08-15 21:01:49 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-08-15 21:01:49 +0000 |
commit | 178fe54130c3582e5a292bac063f53a77dc4c4df (patch) | |
tree | cd45fbf943939862d84778761d080763fb653d0b /src/modes | |
parent | 7328d76b78c3c923c11cc01aa5cf8e5498ea02ff (diff) |
Simplify handling of CBC/ECB padding and move source to src/modes
Diffstat (limited to 'src/modes')
-rw-r--r-- | src/modes/cbc/cbc.cpp | 20 | ||||
-rw-r--r-- | src/modes/ecb/ecb.cpp | 20 | ||||
-rw-r--r-- | src/modes/mode_pad/info.txt | 1 | ||||
-rw-r--r-- | src/modes/mode_pad/mode_pad.cpp | 103 | ||||
-rw-r--r-- | src/modes/mode_pad/mode_pad.h | 124 |
5 files changed, 233 insertions, 35 deletions
diff --git a/src/modes/cbc/cbc.cpp b/src/modes/cbc/cbc.cpp index 96e5be6e2..822ad35ba 100644 --- a/src/modes/cbc/cbc.cpp +++ b/src/modes/cbc/cbc.cpp @@ -10,9 +10,6 @@ #include <botan/internal/xor_buf.h> #include <botan/internal/rounding.h> -#include <iostream> -#include <botan/hex.h> - namespace Botan { CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : @@ -126,24 +123,11 @@ void CBC_Encryption::finish(secure_vector<byte>& buffer, size_t offset) const size_t bytes_in_final_block = sz % BS; - const size_t pad_bytes = padding().pad_bytes(BS, bytes_in_final_block); + padding().add_padding(buffer, bytes_in_final_block, BS); - if((pad_bytes + bytes_in_final_block) % BS) + if(buffer.size() % BS) throw std::runtime_error("Did not pad to full block size in " + name()); -#if 0 - const size_t pad_offset = buffer.size(); - //buffer.resize(checked_add(buffer.size() + pad_bytes)); - buffer.resize(buffer.size() + pad_bytes); - - padder().pad(&buffer[pad_offset], BS, bytes_in_final_block); -#else - std::vector<byte> pad(BS); - padding().pad(&pad[0], BS, bytes_in_final_block); - - buffer.insert(buffer.end(), pad.begin(), pad.begin() + pad_bytes); -#endif - update(buffer, offset); } diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp index 8abf76433..1b73da64f 100644 --- a/src/modes/ecb/ecb.cpp +++ b/src/modes/ecb/ecb.cpp @@ -57,7 +57,7 @@ void ECB_Mode::key_schedule(const byte key[], size_t length) m_cipher->set_key(key, length); } -secure_vector<byte> ECB_Mode::start(const byte nonce[], size_t nonce_len) +secure_vector<byte> ECB_Mode::start(const byte[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); @@ -93,30 +93,16 @@ void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) { BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); const size_t sz = buffer.size() - offset; - //byte* buf = &buffer[offset]; const size_t BS = cipher().block_size(); const size_t bytes_in_final_block = sz % BS; - const size_t pad_bytes = padding().pad_bytes(BS, bytes_in_final_block); + padding().add_padding(buffer, bytes_in_final_block, BS); - if((pad_bytes + bytes_in_final_block) % BS) + if(buffer.size() % BS) throw std::runtime_error("Did not pad to full block size in " + name()); -#if 0 - const size_t pad_offset = buffer.size(); - //buffer.resize(checked_add(buffer.size() + pad_bytes)); - buffer.resize(buffer.size() + pad_bytes); - - padder().pad(&buffer[pad_offset], BS, bytes_in_final_block); -#else - std::vector<byte> pad(BS); - padding().pad(&pad[0], BS, bytes_in_final_block); - - buffer.insert(buffer.end(), pad.begin(), pad.begin() + pad_bytes); -#endif - update(buffer, offset); } diff --git a/src/modes/mode_pad/info.txt b/src/modes/mode_pad/info.txt new file mode 100644 index 000000000..e97ea03a5 --- /dev/null +++ b/src/modes/mode_pad/info.txt @@ -0,0 +1 @@ +define CIPHER_MODE_PADDING diff --git a/src/modes/mode_pad/mode_pad.cpp b/src/modes/mode_pad/mode_pad.cpp new file mode 100644 index 000000000..918964c74 --- /dev/null +++ b/src/modes/mode_pad/mode_pad.cpp @@ -0,0 +1,103 @@ +/* +* CBC Padding Methods +* (C) 1999-2007,2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/mode_pad.h> +#include <botan/exceptn.h> + +namespace Botan { + +/* +* Pad with PKCS #7 Method +*/ +void PKCS7_Padding::add_padding(secure_vector<byte>& buffer, + size_t last_byte_pos, + size_t block_size) const + { + const byte pad_value = block_size - last_byte_pos; + + for(size_t i = 0; i != pad_value; ++i) + buffer.push_back(pad_value); + } + +/* +* Unpad with PKCS #7 Method +*/ +size_t PKCS7_Padding::unpad(const byte block[], size_t size) const + { + size_t position = block[size-1]; + + if(position > size) + throw Decoding_Error("Bad padding in " + name()); + + for(size_t j = size-position; j != size-1; ++j) + if(block[j] != position) + throw Decoding_Error("Bad padding in " + name()); + + return (size-position); + } + +/* +* Pad with ANSI X9.23 Method +*/ +void ANSI_X923_Padding::add_padding(secure_vector<byte>& buffer, + size_t last_byte_pos, + size_t block_size) const + { + const byte pad_value = block_size - last_byte_pos; + + for(size_t i = last_byte_pos; i < block_size; ++i) + buffer.push_back(0); + buffer.push_back(pad_value); + } + +/* +* Unpad with ANSI X9.23 Method +*/ +size_t ANSI_X923_Padding::unpad(const byte block[], size_t size) const + { + size_t position = block[size-1]; + if(position > size) + throw Decoding_Error(name()); + for(size_t j = size-position; j != size-1; ++j) + if(block[j] != 0) + throw Decoding_Error(name()); + return (size-position); + } + +/* +* Pad with One and Zeros Method +*/ +void OneAndZeros_Padding::add_padding(secure_vector<byte>& buffer, + size_t last_byte_pos, + size_t block_size) const + { + buffer.push_back(0x80); + + for(size_t i = last_byte_pos + 1; i % block_size; ++i) + buffer.push_back(0x00); + } + +/* +* Unpad with One and Zeros Method +*/ +size_t OneAndZeros_Padding::unpad(const byte block[], size_t size) const + { + while(size) + { + if(block[size-1] == 0x80) + break; + if(block[size-1] != 0x00) + throw Decoding_Error(name()); + size--; + } + if(!size) + throw Decoding_Error(name()); + return (size-1); + } + + +} diff --git a/src/modes/mode_pad/mode_pad.h b/src/modes/mode_pad/mode_pad.h new file mode 100644 index 000000000..e7c38a196 --- /dev/null +++ b/src/modes/mode_pad/mode_pad.h @@ -0,0 +1,124 @@ +/* +* ECB/CBC Padding Methods +* (C) 1999-2008,2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MODE_PADDING_H__ +#define BOTAN_MODE_PADDING_H__ + +#include <botan/secmem.h> +#include <string> + +namespace Botan { + +/** +* Block Cipher Mode Padding Method +* This class is pretty limited, it cannot deal well with +* randomized padding methods, or any padding method that +* wants to add more than one block. For instance, it should +* be possible to define cipher text stealing mode as simply +* a padding mode for CBC, which happens to consume the last +* two block (and requires use of the block cipher). +*/ +class BOTAN_DLL BlockCipherModePaddingMethod + { + public: + virtual void add_padding(secure_vector<byte>& buffer, + size_t final_block_bytes, + size_t block_size) const = 0; + + /** + * @param block the last block + * @param size the of the block + */ + virtual size_t unpad(const byte block[], + size_t size) const = 0; + + /** + * @param block_size of the cipher + * @return valid block size for this padding mode + */ + virtual bool valid_blocksize(size_t block_size) const = 0; + + /** + * @return name of the mode + */ + virtual std::string name() const = 0; + + /** + * virtual destructor + */ + virtual ~BlockCipherModePaddingMethod() {} + }; + +/** +* PKCS#7 Padding +*/ +class BOTAN_DLL PKCS7_Padding : public BlockCipherModePaddingMethod + { + public: + void add_padding(secure_vector<byte>& buffer, + size_t final_block_bytes, + size_t block_size) const override; + + size_t unpad(const byte[], size_t) const; + + bool valid_blocksize(size_t bs) const { return (bs > 0 && bs < 256); } + + std::string name() const { return "PKCS7"; } + }; + +/** +* ANSI X9.23 Padding +*/ +class BOTAN_DLL ANSI_X923_Padding : public BlockCipherModePaddingMethod + { + public: + void add_padding(secure_vector<byte>& buffer, + size_t final_block_bytes, + size_t block_size) const override; + + size_t unpad(const byte[], size_t) const; + + bool valid_blocksize(size_t bs) const { return (bs > 0 && bs < 256); } + + std::string name() const { return "X9.23"; } + }; + +/** +* One And Zeros Padding +*/ +class BOTAN_DLL OneAndZeros_Padding : public BlockCipherModePaddingMethod + { + public: + void add_padding(secure_vector<byte>& buffer, + size_t final_block_bytes, + size_t block_size) const override; + + size_t unpad(const byte[], size_t) const; + + bool valid_blocksize(size_t bs) const { return (bs > 0); } + + std::string name() const { return "OneAndZeros"; } + }; + +/** +* Null Padding +*/ +class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod + { + public: + void add_padding(secure_vector<byte>&, size_t, size_t) const override {} + + size_t unpad(const byte[], size_t size) const { return size; } + + bool valid_blocksize(size_t) const { return true; } + + std::string name() const { return "NoPadding"; } + }; + +} + +#endif |