diff options
Diffstat (limited to 'src/lib/modes')
-rw-r--r-- | src/lib/modes/aead/aead.cpp | 124 | ||||
-rw-r--r-- | src/lib/modes/aead/ccm/ccm.cpp | 7 | ||||
-rw-r--r-- | src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/eax/eax.cpp | 5 | ||||
-rw-r--r-- | src/lib/modes/aead/gcm/gcm.cpp | 5 | ||||
-rw-r--r-- | src/lib/modes/aead/ocb/ocb.cpp | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/siv/siv.cpp | 7 | ||||
-rw-r--r-- | src/lib/modes/cbc/cbc.cpp | 27 | ||||
-rw-r--r-- | src/lib/modes/cfb/cfb.cpp | 4 | ||||
-rw-r--r-- | src/lib/modes/cipher_mode.cpp | 59 | ||||
-rw-r--r-- | src/lib/modes/cipher_mode.h | 2 | ||||
-rw-r--r-- | src/lib/modes/ecb/ecb.cpp | 18 | ||||
-rw-r--r-- | src/lib/modes/info.txt | 8 | ||||
-rw-r--r-- | src/lib/modes/mode_pad/mode_pad.cpp | 20 | ||||
-rw-r--r-- | src/lib/modes/mode_pad/mode_pad.h | 2 | ||||
-rw-r--r-- | src/lib/modes/mode_utils.h | 76 | ||||
-rw-r--r-- | src/lib/modes/xts/xts.cpp | 6 |
17 files changed, 239 insertions, 143 deletions
diff --git a/src/lib/modes/aead/aead.cpp b/src/lib/modes/aead/aead.cpp index b1cce73e0..1f2099d2e 100644 --- a/src/lib/modes/aead/aead.cpp +++ b/src/lib/modes/aead/aead.cpp @@ -1,135 +1,23 @@ /* -* Interface for AEAD modes -* (C) 2013 Jack Lloyd +* (C) 2013,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/libstate.h> - -#if defined(BOTAN_HAS_AEAD_CCM) - #include <botan/ccm.h> -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - #include <botan/eax.h> -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - #include <botan/gcm.h> -#endif - -#if defined(BOTAN_HAS_AEAD_SIV) - #include <botan/siv.h> -#endif - -#if defined(BOTAN_HAS_AEAD_OCB) - #include <botan/ocb.h> -#endif - -#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) - #include <botan/chacha20poly1305.h> -#endif namespace Botan { AEAD_Mode* get_aead(const std::string& algo_spec, Cipher_Dir direction) { -#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) - if(algo_spec == "ChaCha20Poly1305") - { - if(direction == ENCRYPTION) - return new ChaCha20Poly1305_Encryption; - else - return new ChaCha20Poly1305_Decryption; - } -#endif - - Algorithm_Factory& af = global_state().algorithm_factory(); - - const std::vector<std::string> algo_parts = split_on(algo_spec, '/'); - if(algo_parts.empty()) - throw Invalid_Algorithm_Name(algo_spec); - - if(algo_parts.size() < 2) - return nullptr; - - const std::string cipher_name = algo_parts[0]; - const BlockCipher* cipher = af.prototype_block_cipher(cipher_name); - if(!cipher) - return nullptr; - - const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); - - if(mode_info.empty()) - return nullptr; - - const std::string mode_name = mode_info[0]; - - const size_t tag_size = (mode_info.size() > 1) ? to_u32bit(mode_info[1]) : cipher->block_size(); - -#if defined(BOTAN_HAS_AEAD_CCM) - if(mode_name == "CCM-8") - { - if(direction == ENCRYPTION) - return new CCM_Encryption(cipher->clone(), 8, 3); - else - return new CCM_Decryption(cipher->clone(), 8, 3); - } - - if(mode_name == "CCM" || mode_name == "CCM-8") - { - const size_t L = (mode_info.size() > 2) ? to_u32bit(mode_info[2]) : 3; - - if(direction == ENCRYPTION) - return new CCM_Encryption(cipher->clone(), tag_size, L); - else - return new CCM_Decryption(cipher->clone(), tag_size, L); - } -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - if(mode_name == "EAX") - { - if(direction == ENCRYPTION) - return new EAX_Encryption(cipher->clone(), tag_size); - else - return new EAX_Decryption(cipher->clone(), tag_size); - } -#endif - -#if defined(BOTAN_HAS_AEAD_SIV) - if(mode_name == "SIV") - { - BOTAN_ASSERT(tag_size == 16, "Valid tag size for SIV"); - if(direction == ENCRYPTION) - return new SIV_Encryption(cipher->clone()); - else - return new SIV_Decryption(cipher->clone()); - } -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - if(mode_name == "GCM") - { - if(direction == ENCRYPTION) - return new GCM_Encryption(cipher->clone(), tag_size); - else - return new GCM_Decryption(cipher->clone(), tag_size); - } -#endif + std::unique_ptr<Cipher_Mode> mode(get_cipher_mode(algo_spec, direction)); -#if defined(BOTAN_HAS_AEAD_OCB) - if(mode_name == "OCB") + if(AEAD_Mode* aead = dynamic_cast<AEAD_Mode*>(mode.get())) { - if(direction == ENCRYPTION) - return new OCB_Encryption(cipher->clone(), tag_size); - else - return new OCB_Decryption(cipher->clone(), tag_size); + mode.release(); + return aead; } -#endif return nullptr; } diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp index e0b247ddb..cc692e364 100644 --- a/src/lib/modes/aead/ccm/ccm.cpp +++ b/src/lib/modes/aead/ccm/ccm.cpp @@ -5,13 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ccm.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(CCM_Encryption, CCM_Decryption, 16, 3); + /* * CCM_Mode Constructor */ @@ -57,7 +58,7 @@ size_t CCM_Mode::update_granularity() const /* This value does not particularly matter as regardless CCM_Mode::update buffers all input, so in theory this could be 1. However as for instance - Transformation_Filter creates update_granularity() byte buffers, use a + Transform_Filter creates update_granularity() byte buffers, use a somewhat large size to avoid bouncing on a tiny buffer. */ return m_cipher->parallel_bytes(); diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp index 0961f1dc8..a278156eb 100644 --- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp +++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp @@ -5,14 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/chacha20poly1305.h> #include <botan/chacha.h> #include <botan/poly1305.h> -#include <botan/loadstor.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_TRANSFORM_NOARGS(ChaCha20Poly1305_Encryption); +BOTAN_REGISTER_TRANSFORM_NOARGS(ChaCha20Poly1305_Decryption); + bool ChaCha20Poly1305_Mode::valid_nonce_length(size_t n) const { return (n == 8 || n == 12); diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp index 289278a52..3b0c94416 100644 --- a/src/lib/modes/aead/eax/eax.cpp +++ b/src/lib/modes/aead/eax/eax.cpp @@ -5,15 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/eax.h> #include <botan/cmac.h> #include <botan/ctr.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(EAX_Encryption, EAX_Decryption, 0); + namespace { /* diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index 0acaa57e9..e4a2ad85c 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -6,9 +6,8 @@ */ #include <botan/gcm.h> +#include <botan/internal/mode_utils.h> #include <botan/ctr.h> -#include <botan/internal/xor_buf.h> -#include <botan/loadstor.h> #if defined(BOTAN_HAS_GCM_CLMUL) #include <botan/internal/clmul.h> @@ -17,6 +16,8 @@ namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(GCM_Encryption, GCM_Decryption, 16); + void GHASH::gcm_multiply(secure_vector<byte>& x) const { #if defined(BOTAN_HAS_GCM_CLMUL) diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp index 2ba30b2f9..2ba6d3ee6 100644 --- a/src/lib/modes/aead/ocb/ocb.cpp +++ b/src/lib/modes/aead/ocb/ocb.cpp @@ -5,14 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ocb.h> #include <botan/cmac.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/bit_ops.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(OCB_Encryption, OCB_Decryption, 16); + // Has to be in Botan namespace so unique_ptr can reference it class L_computer { diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp index b183bd6a0..c1416e209 100644 --- a/src/lib/modes/aead/siv/siv.cpp +++ b/src/lib/modes/aead/siv/siv.cpp @@ -5,15 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/siv.h> #include <botan/cmac.h> #include <botan/ctr.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE(SIV_Encryption, SIV_Decryption); + SIV_Mode::SIV_Mode(BlockCipher* cipher) : m_name(cipher->name() + "/SIV"), m_ctr(new CTR_BE(cipher->clone())), @@ -44,7 +45,7 @@ size_t SIV_Mode::update_granularity() const /* This value does not particularly matter as regardless SIV_Mode::update buffers all input, so in theory this could be 1. However as for instance - Transformation_Filter creates update_granularity() byte buffers, use a + Transform_Filter creates update_granularity() byte buffers, use a somewhat large size to avoid bouncing on a tiny buffer. */ return 128; diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp index e89635a5d..e54553d16 100644 --- a/src/lib/modes/cbc/cbc.cpp +++ b/src/lib/modes/cbc/cbc.cpp @@ -5,13 +5,34 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/cbc.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> +#include <botan/mode_pad.h> namespace Botan { +template<typename CBC_T, typename CTS_T> +Transform* make_cbc_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0)); + + if(bc) + { + const std::string padding = spec.arg(1, "PKCS7"); + + if(padding == "CTS") + return new CTS_T(bc->clone()); + else + return new CBC_T(bc->clone(), get_bc_pad(padding)); + } + + return nullptr; + } + +BOTAN_REGISTER_TRANSFORM(CBC_Encryption, (make_cbc_mode<CBC_Encryption,CTS_Encryption>)); +BOTAN_REGISTER_TRANSFORM(CBC_Decryption, (make_cbc_mode<CBC_Decryption,CTS_Decryption>)); + CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : m_cipher(cipher), m_padding(padding), diff --git a/src/lib/modes/cfb/cfb.cpp b/src/lib/modes/cfb/cfb.cpp index 5c33ee3cb..c1fd98dfb 100644 --- a/src/lib/modes/cfb/cfb.cpp +++ b/src/lib/modes/cfb/cfb.cpp @@ -5,12 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/cfb.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(CFB_Encryption, CFB_Decryption, 0); + CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) : m_cipher(cipher), m_feedback_bytes(feedback_bits ? feedback_bits / 8 : cipher->block_size()) diff --git a/src/lib/modes/cipher_mode.cpp b/src/lib/modes/cipher_mode.cpp new file mode 100644 index 000000000..ded7b4c81 --- /dev/null +++ b/src/lib/modes/cipher_mode.cpp @@ -0,0 +1,59 @@ +/* +* Cipher Modes +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/cipher_mode.h> +#include <sstream> + +namespace Botan { + +Cipher_Mode* get_cipher_mode(const std::string& algo_spec, Cipher_Dir direction) + { + const char* dir_string = (direction == ENCRYPTION) ? "_Encryption" : "_Decryption"; + + const std::string provider = ""; + + std::unique_ptr<Transform> t; + + t.reset(get_transform(algo_spec, provider, dir_string)); + + if(Cipher_Mode* cipher = dynamic_cast<Cipher_Mode*>(t.get())) + { + t.release(); + return cipher; + } + + const std::vector<std::string> algo_parts = split_on(algo_spec, '/'); + if(algo_parts.size() < 2) + return nullptr; + + const std::string cipher_name = algo_parts[0]; + const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); + + if(mode_info.empty()) + return nullptr; + + std::ostringstream t_name; + + t_name << mode_info[0] << dir_string << '(' << cipher_name; + for(size_t i = 1; i < mode_info.size(); ++i) + t_name << ',' << mode_info[i]; + for(size_t i = 2; i < algo_parts.size(); ++i) + t_name << ',' << algo_parts[i]; + t_name << ')'; + + t.reset(get_transform(t_name.str(), provider)); + + if(Cipher_Mode* cipher = dynamic_cast<Cipher_Mode*>(t.get())) + { + t.release(); + return cipher; + } + + return nullptr; + } + +} diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h index 2f75fad1c..691852214 100644 --- a/src/lib/modes/cipher_mode.h +++ b/src/lib/modes/cipher_mode.h @@ -25,6 +25,8 @@ class BOTAN_DLL Cipher_Mode : public Keyed_Transform virtual bool authenticated() const { return false; } }; +BOTAN_DLL Cipher_Mode* get_cipher_mode(const std::string& algo_spec, Cipher_Dir direction); + } #endif diff --git a/src/lib/modes/ecb/ecb.cpp b/src/lib/modes/ecb/ecb.cpp index 53f54da99..1db272d12 100644 --- a/src/lib/modes/ecb/ecb.cpp +++ b/src/lib/modes/ecb/ecb.cpp @@ -5,13 +5,25 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ecb.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> namespace Botan { +template<typename T> +Transform* make_ecb_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0)); + BlockCipherModePaddingMethod* pad = get_bc_pad(spec.arg(1, "NoPadding")); + if(bc && pad) + return new T(bc->clone(), pad); + return nullptr; + } + +BOTAN_REGISTER_TRANSFORM(ECB_Encryption, make_ecb_mode<ECB_Encryption>); +BOTAN_REGISTER_TRANSFORM(ECB_Decryption, make_ecb_mode<ECB_Decryption>); + ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : m_cipher(cipher), m_padding(padding) diff --git a/src/lib/modes/info.txt b/src/lib/modes/info.txt index 0dcb0cd59..b3d6d3b5f 100644 --- a/src/lib/modes/info.txt +++ b/src/lib/modes/info.txt @@ -2,3 +2,11 @@ <requires> block </requires> + +<header:public> +cipher_mode.h +</header:public> + +<header:internal> +mode_utils.h +</header:internal> diff --git a/src/lib/modes/mode_pad/mode_pad.cpp b/src/lib/modes/mode_pad/mode_pad.cpp index 946cd92c7..ecf241821 100644 --- a/src/lib/modes/mode_pad/mode_pad.cpp +++ b/src/lib/modes/mode_pad/mode_pad.cpp @@ -10,6 +10,26 @@ namespace Botan { +/** +* Get a block cipher padding method by name +*/ +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) + { + if(algo_spec == "NoPadding") + return new Null_Padding; + + if(algo_spec == "PKCS7") + return new PKCS7_Padding; + + if(algo_spec == "OneAndZeros") + return new OneAndZeros_Padding; + + if(algo_spec == "X9.23") + return new ANSI_X923_Padding; + + return nullptr; + } + /* * Pad with PKCS #7 Method */ diff --git a/src/lib/modes/mode_pad/mode_pad.h b/src/lib/modes/mode_pad/mode_pad.h index c60e25849..c4d5baf2e 100644 --- a/src/lib/modes/mode_pad/mode_pad.h +++ b/src/lib/modes/mode_pad/mode_pad.h @@ -119,6 +119,8 @@ class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod std::string name() const { return "NoPadding"; } }; +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec); + } #endif diff --git a/src/lib/modes/mode_utils.h b/src/lib/modes/mode_utils.h new file mode 100644 index 000000000..0333403a3 --- /dev/null +++ b/src/lib/modes/mode_utils.h @@ -0,0 +1,76 @@ +/* +* Helper include for mode implementations +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_MODE_UTILS_H__ +#define BOTAN_MODE_UTILS_H__ + +#include <botan/cipher_mode.h> +#include <botan/algo_registry.h> +#include <botan/block_cipher.h> +#include <botan/libstate.h> +#include <botan/loadstor.h> +#include <botan/internal/xor_buf.h> +#include <botan/internal/rounding.h> +#include <botan/internal/bit_ops.h> +#include <algorithm> + +namespace Botan { + +template<typename T> +T* make_block_cipher_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + return new T(bc->clone()); + return nullptr; + } + +template<typename T, size_t LEN1> +T* make_block_cipher_mode_len(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + { + const size_t len1 = spec.arg_as_integer(1, LEN1); + return new T(bc->clone(), len1); + } + + return nullptr; + } + +template<typename T, size_t LEN1, size_t LEN2> +T* make_block_cipher_mode_len2(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + { + const size_t len1 = spec.arg_as_integer(1, LEN1); + const size_t len2 = spec.arg_as_integer(2, LEN2); + return new T(bc->clone(), len1, len2); + } + + return nullptr; + } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE(E, D) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode<E>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode<D>); } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(E, D, LEN) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode_len<E, LEN>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode_len<D, LEN>); } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(E, D, LEN1, LEN2) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode_len2<E, LEN1, LEN2>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode_len2<D, LEN1, LEN2>); } + +} + +#endif diff --git a/src/lib/modes/xts/xts.cpp b/src/lib/modes/xts/xts.cpp index cd3a0c653..a4095580c 100644 --- a/src/lib/modes/xts/xts.cpp +++ b/src/lib/modes/xts/xts.cpp @@ -5,13 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/xts.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE(XTS_Encryption, XTS_Decryption); + namespace { void poly_double_128(byte out[], const byte in[]) |