diff options
author | lloyd <[email protected]> | 2008-09-28 18:15:52 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-28 18:15:52 +0000 |
commit | 983a8ecb42e844f89466d0ae52bba591d4fc4275 (patch) | |
tree | de01378ee9be0ba8bec28bc08d3bde6e422ff898 /modules | |
parent | d59f6a2c9e797ee22c21b2d85c662e0fe8d1cf35 (diff) |
Modularize cipher modes
Diffstat (limited to 'modules')
-rw-r--r-- | modules/modes/cbc/cbc.cpp | 157 | ||||
-rw-r--r-- | modules/modes/cbc/cbc.h | 49 | ||||
-rw-r--r-- | modules/modes/cbc/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/cfb/cfb.cpp | 142 | ||||
-rw-r--r-- | modules/modes/cfb/cfb.h | 45 | ||||
-rw-r--r-- | modules/modes/cfb/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/ctr/ctr.cpp | 74 | ||||
-rw-r--r-- | modules/modes/ctr/ctr.h | 29 | ||||
-rw-r--r-- | modules/modes/ctr/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/cts/cts.cpp | 175 | ||||
-rw-r--r-- | modules/modes/cts/cts.h | 46 | ||||
-rw-r--r-- | modules/modes/cts/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/eax/eax.cpp | 194 | ||||
-rw-r--r-- | modules/modes/eax/eax.h | 72 | ||||
-rw-r--r-- | modules/modes/eax/eax_dec.cpp | 126 | ||||
-rw-r--r-- | modules/modes/eax/modinfo.txt | 11 | ||||
-rw-r--r-- | modules/modes/ecb/ecb.cpp | 152 | ||||
-rw-r--r-- | modules/modes/ecb/ecb.h | 57 | ||||
-rw-r--r-- | modules/modes/ecb/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/ofb/modinfo.txt | 10 | ||||
-rw-r--r-- | modules/modes/ofb/ofb.cpp | 65 | ||||
-rw-r--r-- | modules/modes/ofb/ofb.h | 28 |
22 files changed, 1482 insertions, 0 deletions
diff --git a/modules/modes/cbc/cbc.cpp b/modules/modes/cbc/cbc.cpp new file mode 100644 index 000000000..9ad598bed --- /dev/null +++ b/modules/modes/cbc/cbc.cpp @@ -0,0 +1,157 @@ +/************************************************* +* CBC Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/cbc.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* CBC Encryption Constructor * +*************************************************/ +CBC_Encryption::CBC_Encryption(const std::string& cipher_name, + const std::string& padding_name) : + BlockCipherMode(cipher_name, "CBC", block_size_of(cipher_name)), + padder(get_bc_pad(padding_name)) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + } + +/************************************************* +* CBC Encryption Constructor * +*************************************************/ +CBC_Encryption::CBC_Encryption(const std::string& cipher_name, + const std::string& padding_name, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "CBC", block_size_of(cipher_name)), + padder(get_bc_pad(padding_name)) + { + 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(const std::string& cipher_name, + const std::string& padding_name) : + BlockCipherMode(cipher_name, "CBC", block_size_of(cipher_name)), + padder(get_bc_pad(padding_name)) + { + if(!padder->valid_blocksize(BLOCK_SIZE)) + throw Invalid_Block_Size(name(), padder->name()); + temp.create(BLOCK_SIZE); + } + +/************************************************* +* CBC Decryption Constructor * +*************************************************/ +CBC_Decryption::CBC_Decryption(const std::string& cipher_name, + const std::string& padding_name, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "CBC", block_size_of(cipher_name)), + padder(get_bc_pad(padding_name)) + { + 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()); + } + +} diff --git a/modules/modes/cbc/cbc.h b/modules/modes/cbc/cbc.h new file mode 100644 index 000000000..a0a30f90f --- /dev/null +++ b/modules/modes/cbc/cbc.h @@ -0,0 +1,49 @@ +/************************************************* +* CBC Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_CBC_H__ +#define BOTAN_CBC_H__ + +#include <botan/modebase.h> +#include <botan/mode_pad.h> + +namespace Botan { + +/************************************************* +* CBC Encryption * +*************************************************/ +class BOTAN_DLL CBC_Encryption : public BlockCipherMode + { + public: + CBC_Encryption(const std::string&, const std::string&); + CBC_Encryption(const std::string&, const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + std::string name() const; + void write(const byte[], u32bit); + void end_msg(); + const BlockCipherModePaddingMethod* padder; + }; + +/************************************************* +* CBC Decryption * +*************************************************/ +class BOTAN_DLL CBC_Decryption : public BlockCipherMode + { + public: + CBC_Decryption(const std::string&, const std::string&); + CBC_Decryption(const std::string&, const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + std::string name() const; + void write(const byte[], u32bit); + void end_msg(); + const BlockCipherModePaddingMethod* padder; + SecureVector<byte> temp; + }; + +} + +#endif diff --git a/modules/modes/cbc/modinfo.txt b/modules/modes/cbc/modinfo.txt new file mode 100644 index 000000000..4ebc7730a --- /dev/null +++ b/modules/modes/cbc/modinfo.txt @@ -0,0 +1,10 @@ +realname "CBC block cipher mode" + +define CBC + +load_on auto + +<add> +cbc.cpp +cbc.h +</add> diff --git a/modules/modes/cfb/cfb.cpp b/modules/modes/cfb/cfb.cpp new file mode 100644 index 000000000..dbfbff6ae --- /dev/null +++ b/modules/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; + } + +} diff --git a/modules/modes/cfb/cfb.h b/modules/modes/cfb/cfb.h new file mode 100644 index 000000000..e8133bcf4 --- /dev/null +++ b/modules/modes/cfb/cfb.h @@ -0,0 +1,45 @@ +/************************************************* +* CFB Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_CFB_H__ +#define BOTAN_CFB_H__ + +#include <botan/modebase.h> + +namespace Botan { + +/************************************************* +* CFB Encryption * +*************************************************/ +class BOTAN_DLL CFB_Encryption : public BlockCipherMode + { + public: + CFB_Encryption(const std::string&, u32bit = 0); + CFB_Encryption(const std::string&, const SymmetricKey&, + const InitializationVector&, u32bit = 0); + private: + void write(const byte[], u32bit); + void feedback(); + const u32bit FEEDBACK_SIZE; + }; + +/************************************************* +* CFB Decryption * +*************************************************/ +class BOTAN_DLL CFB_Decryption : public BlockCipherMode + { + public: + CFB_Decryption(const std::string&, u32bit = 0); + CFB_Decryption(const std::string&, const SymmetricKey&, + const InitializationVector&, u32bit = 0); + private: + void write(const byte[], u32bit); + void feedback(); + const u32bit FEEDBACK_SIZE; + }; + +} + +#endif diff --git a/modules/modes/cfb/modinfo.txt b/modules/modes/cfb/modinfo.txt new file mode 100644 index 000000000..edce3a7e3 --- /dev/null +++ b/modules/modes/cfb/modinfo.txt @@ -0,0 +1,10 @@ +realname "CFB block cipher mode" + +define CFB + +load_on auto + +<add> +cfb.cpp +cfb.h +</add> diff --git a/modules/modes/ctr/ctr.cpp b/modules/modes/ctr/ctr.cpp new file mode 100644 index 000000000..8b8c5f35f --- /dev/null +++ b/modules/modes/ctr/ctr.cpp @@ -0,0 +1,74 @@ +/************************************************* +* CTR Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/ctr.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* CTR-BE Constructor * +*************************************************/ +CTR_BE::CTR_BE(const std::string& cipher_name) : + BlockCipherMode(cipher_name, "CTR-BE", block_size_of(cipher_name), 1) + { + } + +/************************************************* +* CTR-BE Constructor * +*************************************************/ +CTR_BE::CTR_BE(const std::string& cipher_name, const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "CTR-BE", block_size_of(cipher_name), 1) + { + set_key(key); + set_iv(iv); + } + +/************************************************* +* CTR-BE Encryption/Decryption * +*************************************************/ +void CTR_BE::write(const byte input[], u32bit length) + { + u32bit copied = std::min(BLOCK_SIZE - position, length); + xor_buf(buffer + position, input, copied); + send(buffer + position, copied); + input += copied; + length -= copied; + position += copied; + + if(position == BLOCK_SIZE) + increment_counter(); + + while(length >= BLOCK_SIZE) + { + xor_buf(buffer, input, BLOCK_SIZE); + send(buffer, BLOCK_SIZE); + + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + increment_counter(); + } + + xor_buf(buffer + position, input, length); + send(buffer + position, length); + position += length; + } + +/************************************************* +* Increment the counter and update the buffer * +*************************************************/ +void CTR_BE::increment_counter() + { + for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) + if(++state[j]) + break; + cipher->encrypt(state, buffer); + position = 0; + } + +} diff --git a/modules/modes/ctr/ctr.h b/modules/modes/ctr/ctr.h new file mode 100644 index 000000000..c3217a5d1 --- /dev/null +++ b/modules/modes/ctr/ctr.h @@ -0,0 +1,29 @@ +/************************************************* +* CTR Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_CTR_H__ +#define BOTAN_CTR_H__ + +#include <botan/modebase.h> + +namespace Botan { + +/************************************************* +* CTR-BE Mode * +*************************************************/ +class BOTAN_DLL CTR_BE : public BlockCipherMode + { + public: + CTR_BE(const std::string&); + CTR_BE(const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + void write(const byte[], u32bit); + void increment_counter(); + }; + +} + +#endif diff --git a/modules/modes/ctr/modinfo.txt b/modules/modes/ctr/modinfo.txt new file mode 100644 index 000000000..912b80f51 --- /dev/null +++ b/modules/modes/ctr/modinfo.txt @@ -0,0 +1,10 @@ +realname "CTR block cipher mode" + +define CTR + +load_on auto + +<add> +ctr.cpp +ctr.h +</add> diff --git a/modules/modes/cts/cts.cpp b/modules/modes/cts/cts.cpp new file mode 100644 index 000000000..8af775713 --- /dev/null +++ b/modules/modes/cts/cts.cpp @@ -0,0 +1,175 @@ +/************************************************* +* CTS Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/cts.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* CTS Encryption Constructor * +*************************************************/ +CTS_Encryption::CTS_Encryption(const std::string& cipher_name) : + BlockCipherMode(cipher_name, "CTS", block_size_of(cipher_name), 0, 2) + { + } + +/************************************************* +* CTS Encryption Constructor * +*************************************************/ +CTS_Encryption::CTS_Encryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "CTS", block_size_of(cipher_name), 0, 2) + { + set_key(key); + set_iv(iv); + } + +/************************************************* +* Encrypt a block * +*************************************************/ +void CTS_Encryption::encrypt(const byte block[]) + { + xor_buf(state, block, BLOCK_SIZE); + cipher->encrypt(state); + send(state, BLOCK_SIZE); + } + +/************************************************* +* Encrypt in CTS mode * +*************************************************/ +void CTS_Encryption::write(const byte input[], u32bit length) + { + u32bit copied = std::min(BUFFER_SIZE - position, length); + buffer.copy(position, input, copied); + length -= copied; + input += copied; + position += copied; + + if(length == 0) return; + + encrypt(buffer); + if(length > BLOCK_SIZE) + { + encrypt(buffer + BLOCK_SIZE); + while(length > 2*BLOCK_SIZE) + { + encrypt(input); + length -= BLOCK_SIZE; + input += BLOCK_SIZE; + } + position = 0; + } + else + { + copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE); + position = BLOCK_SIZE; + } + buffer.copy(position, input, length); + position += length; + } + +/************************************************* +* Finish encrypting in CTS mode * +*************************************************/ +void CTS_Encryption::end_msg() + { + if(position < BLOCK_SIZE + 1) + throw Exception("CTS_Encryption: insufficient data to encrypt"); + xor_buf(state, buffer, BLOCK_SIZE); + cipher->encrypt(state); + SecureVector<byte> cn = state; + clear_mem(buffer + position, BUFFER_SIZE - position); + encrypt(buffer + BLOCK_SIZE); + send(cn, position - BLOCK_SIZE); + } + +/************************************************* +* CTS Decryption Constructor * +*************************************************/ +CTS_Decryption::CTS_Decryption(const std::string& cipher_name) : + BlockCipherMode(cipher_name, "CTS", block_size_of(cipher_name), 0, 2) + { + temp.create(BLOCK_SIZE); + } + +/************************************************* +* CTS Decryption Constructor * +*************************************************/ +CTS_Decryption::CTS_Decryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "CTS", block_size_of(cipher_name), 0, 2) + { + temp.create(BLOCK_SIZE); + set_key(key); + set_iv(iv); + } + +/************************************************* +* Decrypt a block * +*************************************************/ +void CTS_Decryption::decrypt(const byte block[]) + { + cipher->decrypt(block, temp); + xor_buf(temp, state, BLOCK_SIZE); + send(temp, BLOCK_SIZE); + state.copy(block, BLOCK_SIZE); + } + +/************************************************* +* Decrypt in CTS mode * +*************************************************/ +void CTS_Decryption::write(const byte input[], u32bit length) + { + u32bit copied = std::min(BUFFER_SIZE - position, length); + buffer.copy(position, input, copied); + length -= copied; + input += copied; + position += copied; + + if(length == 0) return; + + decrypt(buffer); + if(length > BLOCK_SIZE) + { + decrypt(buffer + BLOCK_SIZE); + while(length > 2*BLOCK_SIZE) + { + decrypt(input); + length -= BLOCK_SIZE; + input += BLOCK_SIZE; + } + position = 0; + } + else + { + copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE); + position = BLOCK_SIZE; + } + buffer.copy(position, input, length); + position += length; + } + +/************************************************* +* Finish decrypting in CTS mode * +*************************************************/ +void CTS_Decryption::end_msg() + { + cipher->decrypt(buffer, temp); + xor_buf(temp, buffer + BLOCK_SIZE, position - BLOCK_SIZE); + SecureVector<byte> xn = temp; + copy_mem(buffer + position, xn + (position - BLOCK_SIZE), + BUFFER_SIZE - position); + cipher->decrypt(buffer + BLOCK_SIZE, temp); + xor_buf(temp, state, BLOCK_SIZE); + send(temp, BLOCK_SIZE); + send(xn, position - BLOCK_SIZE); + } + +} diff --git a/modules/modes/cts/cts.h b/modules/modes/cts/cts.h new file mode 100644 index 000000000..6a07c4eb2 --- /dev/null +++ b/modules/modes/cts/cts.h @@ -0,0 +1,46 @@ +/************************************************* +* CTS Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_CTS_H__ +#define BOTAN_CTS_H__ + +#include <botan/modebase.h> + +namespace Botan { + +/************************************************* +* CTS Encryption * +*************************************************/ +class BOTAN_DLL CTS_Encryption : public BlockCipherMode + { + public: + CTS_Encryption(const std::string&); + CTS_Encryption(const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + void write(const byte[], u32bit); + void end_msg(); + void encrypt(const byte[]); + }; + +/************************************************* +* CTS Decryption * +*************************************************/ +class BOTAN_DLL CTS_Decryption : public BlockCipherMode + { + public: + CTS_Decryption(const std::string&); + CTS_Decryption(const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + void write(const byte[], u32bit); + void end_msg(); + void decrypt(const byte[]); + SecureVector<byte> temp; + }; + +} + +#endif diff --git a/modules/modes/cts/modinfo.txt b/modules/modes/cts/modinfo.txt new file mode 100644 index 000000000..9f36221b4 --- /dev/null +++ b/modules/modes/cts/modinfo.txt @@ -0,0 +1,10 @@ +realname "CTS block cipher mode" + +define CTS + +load_on auto + +<add> +cts.cpp +cts.h +</add> diff --git a/modules/modes/eax/eax.cpp b/modules/modes/eax/eax.cpp new file mode 100644 index 000000000..f246a9dea --- /dev/null +++ b/modules/modes/eax/eax.cpp @@ -0,0 +1,194 @@ +/************************************************* +* EAX Mode Encryption Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/eax.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <botan/parsing.h> +#include <algorithm> + +namespace Botan { + +namespace { + +/************************************************* +* EAX MAC-based PRF * +*************************************************/ +SecureVector<byte> eax_prf(byte tag, u32bit BLOCK_SIZE, + MessageAuthenticationCode* mac, + const byte in[], u32bit length) + { + for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j) + mac->update(0); + mac->update(tag); + mac->update(in, length); + return mac->final(); + } + +} + +/************************************************* +* EAX_Base Constructor * +*************************************************/ +EAX_Base::EAX_Base(const std::string& cipher_name, + u32bit tag_size) : + TAG_SIZE(tag_size ? tag_size / 8 : block_size_of(cipher_name)), + BLOCK_SIZE(block_size_of(cipher_name)) + { + const std::string mac_name = "CMAC(" + cipher_name + ")"; + + cipher = get_block_cipher(cipher_name); + mac = get_mac(mac_name); + + if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > mac->OUTPUT_LENGTH) + throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size)); + + state.create(BLOCK_SIZE); + buffer.create(BLOCK_SIZE); + position = 0; + } + +/************************************************* +* Check if a keylength is valid for EAX * +*************************************************/ +bool EAX_Base::valid_keylength(u32bit n) const + { + if(!cipher->valid_keylength(n)) + return false; + if(!mac->valid_keylength(n)) + return false; + return true; + } + +/************************************************* +* Set the EAX key * +*************************************************/ +void EAX_Base::set_key(const SymmetricKey& key) + { + cipher->set_key(key); + mac->set_key(key); + header_mac = eax_prf(1, BLOCK_SIZE, mac, 0, 0); + } + +/************************************************* +* Do setup at the start of each message * +*************************************************/ +void EAX_Base::start_msg() + { + for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j) + mac->update(0); + mac->update(2); + } + +/************************************************* +* Set the EAX nonce * +*************************************************/ +void EAX_Base::set_iv(const InitializationVector& iv) + { + nonce_mac = eax_prf(0, BLOCK_SIZE, mac, iv.begin(), iv.length()); + state = nonce_mac; + cipher->encrypt(state, buffer); + } + +/************************************************* +* Set the EAX header * +*************************************************/ +void EAX_Base::set_header(const byte header[], u32bit length) + { + header_mac = eax_prf(1, BLOCK_SIZE, mac, header, length); + } + +/************************************************* +* Return the name of this cipher mode * +*************************************************/ +std::string EAX_Base::name() const + { + return (cipher->name() + "/EAX"); + } + +/************************************************* +* Increment the counter and update the buffer * +*************************************************/ +void EAX_Base::increment_counter() + { + for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) + if(++state[j]) + break; + cipher->encrypt(state, buffer); + position = 0; + } + +/************************************************* +* EAX_Encryption Constructor * +*************************************************/ +EAX_Encryption::EAX_Encryption(const std::string& cipher_name, + u32bit tag_size) : + EAX_Base(cipher_name, tag_size) + { + } + +/************************************************* +* EAX_Encryption Constructor * +*************************************************/ +EAX_Encryption::EAX_Encryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit tag_size) : + EAX_Base(cipher_name, tag_size) + { + set_key(key); + set_iv(iv); + } + +/************************************************* +* Encrypt in EAX mode * +*************************************************/ +void EAX_Encryption::write(const byte input[], u32bit length) + { + u32bit copied = std::min(BLOCK_SIZE - position, length); + xor_buf(buffer + position, input, copied); + send(buffer + position, copied); + mac->update(buffer + position, copied); + input += copied; + length -= copied; + position += copied; + + if(position == BLOCK_SIZE) + increment_counter(); + + while(length >= BLOCK_SIZE) + { + xor_buf(buffer, input, BLOCK_SIZE); + send(buffer, BLOCK_SIZE); + mac->update(buffer, BLOCK_SIZE); + + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + increment_counter(); + } + + xor_buf(buffer + position, input, length); + send(buffer + position, length); + mac->update(buffer + position, length); + position += length; + } + +/************************************************* +* Finish encrypting in EAX mode * +*************************************************/ +void EAX_Encryption::end_msg() + { + SecureVector<byte> data_mac = mac->final(); + xor_buf(data_mac, nonce_mac, data_mac.size()); + xor_buf(data_mac, header_mac, data_mac.size()); + + send(data_mac, TAG_SIZE); + + state.clear(); + buffer.clear(); + position = 0; + } + +} diff --git a/modules/modes/eax/eax.h b/modules/modes/eax/eax.h new file mode 100644 index 000000000..676e5334e --- /dev/null +++ b/modules/modes/eax/eax.h @@ -0,0 +1,72 @@ +/************************************************* +* EAX Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_EAX_H__ +#define BOTAN_EAX_H__ + +#include <botan/basefilt.h> + +namespace Botan { + +/************************************************* +* EAX Base Class * +*************************************************/ +class BOTAN_DLL EAX_Base : public Keyed_Filter + { + public: + void set_key(const SymmetricKey&); + void set_iv(const InitializationVector&); + void set_header(const byte[], u32bit); + std::string name() const; + + bool valid_keylength(u32bit) const; + + ~EAX_Base() { delete cipher; delete mac; } + protected: + EAX_Base(const std::string&, u32bit); + void start_msg(); + void increment_counter(); + + const u32bit TAG_SIZE, BLOCK_SIZE; + BlockCipher* cipher; + MessageAuthenticationCode* mac; + SecureVector<byte> nonce_mac, header_mac, state, buffer; + u32bit position; + }; + +/************************************************* +* EAX Encryption * +*************************************************/ +class BOTAN_DLL EAX_Encryption : public EAX_Base + { + public: + EAX_Encryption(const std::string&, u32bit = 0); + EAX_Encryption(const std::string&, const SymmetricKey&, + const InitializationVector&, u32bit = 0); + private: + void write(const byte[], u32bit); + void end_msg(); + }; + +/************************************************* +* EAX Decryption * +*************************************************/ +class BOTAN_DLL EAX_Decryption : public EAX_Base + { + public: + EAX_Decryption(const std::string&, u32bit = 0); + EAX_Decryption(const std::string&, const SymmetricKey&, + const InitializationVector&, u32bit = 0); + private: + void write(const byte[], u32bit); + void do_write(const byte[], u32bit); + void end_msg(); + SecureVector<byte> queue; + u32bit queue_start, queue_end; + }; + +} + +#endif diff --git a/modules/modes/eax/eax_dec.cpp b/modules/modes/eax/eax_dec.cpp new file mode 100644 index 000000000..70cdd9863 --- /dev/null +++ b/modules/modes/eax/eax_dec.cpp @@ -0,0 +1,126 @@ +/************************************************* +* EAX Mode Encryption Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/eax.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <botan/parsing.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* EAX_Decryption Constructor * +*************************************************/ +EAX_Decryption::EAX_Decryption(const std::string& cipher_name, + u32bit tag_size) : + EAX_Base(cipher_name, tag_size) + { + queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE); + queue_start = queue_end = 0; + } + +/************************************************* +* EAX_Decryption Constructor * +*************************************************/ +EAX_Decryption::EAX_Decryption(const std::string& cipher_name, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit tag_size) : + EAX_Base(cipher_name, tag_size) + { + set_key(key); + set_iv(iv); + queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE); + queue_start = queue_end = 0; + } + +/************************************************* +* Decrypt in EAX mode * +*************************************************/ +void EAX_Decryption::write(const byte input[], u32bit length) + { + while(length) + { + const u32bit copied = std::min(length, queue.size() - queue_end); + + queue.copy(queue_end, input, copied); + input += copied; + length -= copied; + queue_end += copied; + + SecureVector<byte> block_buf(cipher->BLOCK_SIZE); + while((queue_end - queue_start) > TAG_SIZE) + { + u32bit removed = (queue_end - queue_start) - TAG_SIZE; + do_write(queue + queue_start, removed); + queue_start += removed; + } + + if(queue_start + TAG_SIZE == queue_end && + queue_start >= queue.size() / 2) + { + SecureVector<byte> queue_data(TAG_SIZE); + queue_data.copy(queue + queue_start, TAG_SIZE); + queue.copy(queue_data, TAG_SIZE); + queue_start = 0; + queue_end = TAG_SIZE; + } + } + } + +/************************************************* +* Decrypt in EAX mode * +*************************************************/ +void EAX_Decryption::do_write(const byte input[], u32bit length) + { + mac->update(input, length); + + u32bit copied = std::min(BLOCK_SIZE - position, length); + xor_buf(buffer + position, input, copied); + send(buffer + position, copied); + input += copied; + length -= copied; + position += copied; + + if(position == BLOCK_SIZE) + increment_counter(); + + while(length >= BLOCK_SIZE) + { + xor_buf(buffer, input, BLOCK_SIZE); + send(buffer, BLOCK_SIZE); + + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + increment_counter(); + } + + xor_buf(buffer + position, input, length); + send(buffer + position, length); + position += length; + } + +/************************************************* +* Finish decrypting in EAX mode * +*************************************************/ +void EAX_Decryption::end_msg() + { + if((queue_end - queue_start) != TAG_SIZE) + throw Integrity_Failure(name() + ": Message authentication failure"); + + SecureVector<byte> data_mac = mac->final(); + + for(u32bit j = 0; j != TAG_SIZE; ++j) + if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j])) + throw Integrity_Failure(name() + ": Message authentication failure"); + + state.clear(); + buffer.clear(); + position = 0; + queue_start = queue_end = 0; + } + +} diff --git a/modules/modes/eax/modinfo.txt b/modules/modes/eax/modinfo.txt new file mode 100644 index 000000000..7d5f7e98c --- /dev/null +++ b/modules/modes/eax/modinfo.txt @@ -0,0 +1,11 @@ +realname "EAX block cipher mode" + +define EAX + +load_on auto + +<add> +eax.cpp +eax.h +eax_dec.cpp +</add> diff --git a/modules/modes/ecb/ecb.cpp b/modules/modes/ecb/ecb.cpp new file mode 100644 index 000000000..8effac1d5 --- /dev/null +++ b/modules/modes/ecb/ecb.cpp @@ -0,0 +1,152 @@ +/************************************************* +* ECB Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/ecb.h> +#include <botan/lookup.h> + +namespace Botan { + +/************************************************* +* ECB Constructor * +*************************************************/ +ECB::ECB(const std::string& cipher_name, const std::string& padding_name) : + BlockCipherMode(cipher_name, "ECB", 0), padder(get_bc_pad(padding_name)) + { + } + +/************************************************* +* Verify the IV is not set * +*************************************************/ +bool ECB::valid_iv_size(u32bit iv_size) const + { + if(iv_size == 0) + return true; + return false; + } + +/************************************************* +* Return an ECB mode name * +*************************************************/ +std::string ECB::name() const + { + return (cipher->name() + "/" + mode_name + "/" + padder->name()); + } + +/************************************************* +* ECB Encryption Constructor * +*************************************************/ +ECB_Encryption::ECB_Encryption(const std::string& cipher_name, + const std::string& padding_name) : + ECB(cipher_name, padding_name) + { + } + +/************************************************* +* ECB Encryption Constructor * +*************************************************/ +ECB_Encryption::ECB_Encryption(const std::string& cipher_name, + const std::string& padding_name, + const SymmetricKey& key) : + ECB(cipher_name, padding_name) + { + set_key(key); + } + +/************************************************* +* Encrypt in ECB mode * +*************************************************/ +void ECB_Encryption::write(const byte input[], u32bit length) + { + buffer.copy(position, input, length); + if(position + length >= BLOCK_SIZE) + { + cipher->encrypt(buffer); + send(buffer, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + while(length >= BLOCK_SIZE) + { + cipher->encrypt(input, buffer); + send(buffer, BLOCK_SIZE); + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + } + buffer.copy(input, length); + position = 0; + } + position += length; + } + +/************************************************* +* Finish encrypting in ECB mode * +*************************************************/ +void ECB_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 Encoding_Error(name() + ": Did not pad to full blocksize"); + } + +/************************************************* +* ECB Decryption Constructor * +*************************************************/ +ECB_Decryption::ECB_Decryption(const std::string& cipher_name, + const std::string& padding_name) : + ECB(cipher_name, padding_name) + { + } + +/************************************************* +* ECB Decryption Constructor * +*************************************************/ +ECB_Decryption::ECB_Decryption(const std::string& cipher_name, + const std::string& padding_name, + const SymmetricKey& key) : + ECB(cipher_name, padding_name) + { + set_key(key); + } + +/************************************************* +* Decrypt in ECB mode * +*************************************************/ +void ECB_Decryption::write(const byte input[], u32bit length) + { + buffer.copy(position, input, length); + if(position + length > BLOCK_SIZE) + { + cipher->decrypt(buffer); + send(buffer, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + while(length > BLOCK_SIZE) + { + cipher->decrypt(input, buffer); + send(buffer, BLOCK_SIZE); + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + } + buffer.copy(input, length); + position = 0; + } + position += length; + } + +/************************************************* +* Finish decrypting in ECB mode * +*************************************************/ +void ECB_Decryption::end_msg() + { + if(position != BLOCK_SIZE) + throw Decoding_Error(name()); + cipher->decrypt(buffer); + send(buffer, padder->unpad(buffer, BLOCK_SIZE)); + state = buffer; + position = 0; + } + +} diff --git a/modules/modes/ecb/ecb.h b/modules/modes/ecb/ecb.h new file mode 100644 index 000000000..b730a4fd4 --- /dev/null +++ b/modules/modes/ecb/ecb.h @@ -0,0 +1,57 @@ +/************************************************* +* ECB Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ECB_H__ +#define BOTAN_ECB_H__ + +#include <botan/modebase.h> +#include <botan/mode_pad.h> + +namespace Botan { + +/************************************************* +* ECB * +*************************************************/ +class BOTAN_DLL ECB : public BlockCipherMode + { + protected: + ECB(const std::string&, const std::string&); + std::string name() const; + const BlockCipherModePaddingMethod* padder; + private: + bool valid_iv_size(u32bit) const; + }; + +/************************************************* +* ECB Encryption * +*************************************************/ +class BOTAN_DLL ECB_Encryption : public ECB + { + public: + ECB_Encryption(const std::string&, const std::string&); + ECB_Encryption(const std::string&, const std::string&, + const SymmetricKey&); + private: + void write(const byte[], u32bit); + void end_msg(); + }; + +/************************************************* +* ECB Decryption * +*************************************************/ +class BOTAN_DLL ECB_Decryption : public ECB + { + public: + ECB_Decryption(const std::string&, const std::string&); + ECB_Decryption(const std::string&, const std::string&, + const SymmetricKey&); + private: + void write(const byte[], u32bit); + void end_msg(); + }; + +} + +#endif diff --git a/modules/modes/ecb/modinfo.txt b/modules/modes/ecb/modinfo.txt new file mode 100644 index 000000000..fb0c8b7c6 --- /dev/null +++ b/modules/modes/ecb/modinfo.txt @@ -0,0 +1,10 @@ +realname "ECB block cipher mode" + +define ECB + +load_on auto + +<add> +ecb.cpp +ecb.h +</add> diff --git a/modules/modes/ofb/modinfo.txt b/modules/modes/ofb/modinfo.txt new file mode 100644 index 000000000..38a15d0b6 --- /dev/null +++ b/modules/modes/ofb/modinfo.txt @@ -0,0 +1,10 @@ +realname "OFB block cipher mode" + +define OFB + +load_on auto + +<add> +ofb.cpp +ofb.h +</add> diff --git a/modules/modes/ofb/ofb.cpp b/modules/modes/ofb/ofb.cpp new file mode 100644 index 000000000..db254d329 --- /dev/null +++ b/modules/modes/ofb/ofb.cpp @@ -0,0 +1,65 @@ +/************************************************* +* OFB Mode Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/ofb.h> +#include <botan/lookup.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* OFB Constructor * +*************************************************/ +OFB::OFB(const std::string& cipher_name) : + BlockCipherMode(cipher_name, "OFB", block_size_of(cipher_name), 2) + { + } + +/************************************************* +* OFB Constructor * +*************************************************/ +OFB::OFB(const std::string& cipher_name, const SymmetricKey& key, + const InitializationVector& iv) : + BlockCipherMode(cipher_name, "OFB", block_size_of(cipher_name), 2) + { + set_key(key); + set_iv(iv); + } + +/************************************************* +* OFB Encryption/Decryption * +*************************************************/ +void OFB::write(const byte input[], u32bit length) + { + u32bit copied = std::min(BLOCK_SIZE - position, length); + xor_buf(buffer, input, state + position, copied); + send(buffer, copied); + input += copied; + length -= copied; + position += copied; + + if(position == BLOCK_SIZE) + { + cipher->encrypt(state); + position = 0; + } + + while(length >= BLOCK_SIZE) + { + xor_buf(buffer, input, state, BLOCK_SIZE); + send(buffer, BLOCK_SIZE); + + input += BLOCK_SIZE; + length -= BLOCK_SIZE; + cipher->encrypt(state); + } + + xor_buf(buffer, input, state + position, length); + send(buffer, length); + position += length; + } + +} diff --git a/modules/modes/ofb/ofb.h b/modules/modes/ofb/ofb.h new file mode 100644 index 000000000..3bf6f9883 --- /dev/null +++ b/modules/modes/ofb/ofb.h @@ -0,0 +1,28 @@ +/************************************************* +* OFB Mode Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_OFB_H__ +#define BOTAN_OFB_H__ + +#include <botan/modebase.h> + +namespace Botan { + +/************************************************* +* OFB Mode * +*************************************************/ +class BOTAN_DLL OFB : public BlockCipherMode + { + public: + OFB(const std::string&); + OFB(const std::string&, + const SymmetricKey&, const InitializationVector&); + private: + void write(const byte[], u32bit); + }; + +} + +#endif |