diff options
Diffstat (limited to 'src/modes')
38 files changed, 0 insertions, 3832 deletions
diff --git a/src/modes/aead/aead.cpp b/src/modes/aead/aead.cpp deleted file mode 100644 index 26a7091fd..000000000 --- a/src/modes/aead/aead.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -* Interface for AEAD modes -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/aead.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 - -namespace Botan { - -AEAD_Mode* get_aead(const std::string& algo_spec, Cipher_Dir direction) - { - 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 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]) : 16; - - const BlockCipher* cipher = af.prototype_block_cipher(cipher_name); - if(!cipher) - return nullptr; - -#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 - -#if defined(BOTAN_HAS_AEAD_OCB) - if(mode_name == "OCB") - { - if(direction == ENCRYPTION) - return new OCB_Encryption(cipher->clone(), tag_size); - else - return new OCB_Decryption(cipher->clone(), tag_size); - } -#endif - - return nullptr; - } - -} diff --git a/src/modes/aead/aead.h b/src/modes/aead/aead.h deleted file mode 100644 index 8df98fcad..000000000 --- a/src/modes/aead/aead.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Interface for AEAD modes -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_MODE_H__ -#define BOTAN_AEAD_MODE_H__ - -#include <botan/cipher_mode.h> - -namespace Botan { - -/** -* Interface for AEAD (Authenticated Encryption with Associated Data) -* modes. These modes provide both encryption and message -* authentication, and can authenticate additional per-message data -* which is not included in the ciphertext (for instance a sequence -* number). -*/ -class BOTAN_DLL AEAD_Mode : public Cipher_Mode - { - public: - bool authenticated() const override { return true; } - - /** - * Set associated data that is not included in the ciphertext but - * that should be authenticated. Must be called after set_key - * and before finish. - * - * Unless reset by another call, the associated data is kept - * between messages. Thus, if the AD does not change, calling - * once (after set_key) is the optimum. - * - * @param ad the associated data - * @param ad_len length of add in bytes - */ - virtual void set_associated_data(const byte ad[], size_t ad_len) = 0; - - template<typename Alloc> - void set_associated_data_vec(const std::vector<byte, Alloc>& ad) - { - set_associated_data(&ad[0], ad.size()); - } - - /** - * Default AEAD nonce size (a commonly supported value among AEAD - * modes, and large enough that random collisions are unlikely). - */ - size_t default_nonce_length() const override { return 12; } - - /** - * Return the size of the authentication tag used (in bytes) - */ - virtual size_t tag_size() const = 0; - }; - -/** -* Get an AEAD mode by name (eg "AES-128/GCM" or "Serpent/EAX") -*/ -BOTAN_DLL AEAD_Mode* get_aead(const std::string& name, Cipher_Dir direction); - -} - -#endif diff --git a/src/modes/aead/ccm/ccm.cpp b/src/modes/aead/ccm/ccm.cpp deleted file mode 100644 index 50fc38738..000000000 --- a/src/modes/aead/ccm/ccm.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* -* CCM Mode Encryption -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ccm.h> -#include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> - -namespace Botan { - -/* -* CCM_Mode Constructor -*/ -CCM_Mode::CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L) : - m_tag_size(tag_size), - m_L(L), - m_cipher(cipher) - { - if(m_cipher->block_size() != BS) - throw std::invalid_argument(m_cipher->name() + " cannot be used with CCM mode"); - - if(L < 2 || L > 8) - throw std::invalid_argument("Invalid CCM L value " + std::to_string(L)); - - if(tag_size < 4 || tag_size > 16 || tag_size % 2 != 0) - throw std::invalid_argument("invalid CCM tag length " + std::to_string(tag_size)); - } - -void CCM_Mode::clear() - { - m_cipher.reset(); - m_msg_buf.clear(); - m_ad_buf.clear(); - } - -std::string CCM_Mode::name() const - { - return (m_cipher->name() + "/CCM(" + std::to_string(tag_size()) + "," + std::to_string(L())) + ")"; - } - -bool CCM_Mode::valid_nonce_length(size_t n) const - { - return (n == (15-L())); - } - -size_t CCM_Mode::default_nonce_length() const - { - return (15-L()); - } - -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 - somewhat large size to avoid bouncing on a tiny buffer. - */ - return m_cipher->parallel_bytes(); - } - -Key_Length_Specification CCM_Mode::key_spec() const - { - return m_cipher->key_spec(); - } - -void CCM_Mode::key_schedule(const byte key[], size_t length) - { - m_cipher->set_key(key, length); - } - -void CCM_Mode::set_associated_data(const byte ad[], size_t length) - { - m_ad_buf.clear(); - - if(length) - { - // FIXME: support larger AD using length encoding rules - BOTAN_ASSERT(length < (0xFFFF - 0xFF), "Supported CCM AD length"); - - m_ad_buf.push_back(get_byte<u16bit>(0, length)); - m_ad_buf.push_back(get_byte<u16bit>(1, length)); - m_ad_buf += std::make_pair(ad, length); - while(m_ad_buf.size() % BS) - m_ad_buf.push_back(0); // pad with zeros to full block size - } - } - -secure_vector<byte> CCM_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - m_nonce.assign(nonce, nonce + nonce_len); - m_msg_buf.clear(); - - return secure_vector<byte>(); - } - -void CCM_Mode::update(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]; - - m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); - buffer.resize(offset); // truncate msg - } - -void CCM_Mode::encode_length(size_t len, byte out[]) - { - const size_t len_bytes = L(); - - BOTAN_ASSERT(len_bytes < sizeof(size_t), "Length field fits"); - - for(size_t i = 0; i != len_bytes; ++i) - out[i] = get_byte(sizeof(size_t)-i, len); - - BOTAN_ASSERT((len >> (len_bytes*8)) == 0, "Message length fits in field"); - } - -void CCM_Mode::inc(secure_vector<byte>& C) - { - for(size_t i = 0; i != C.size(); ++i) - if(++C[C.size()-i-1]) - break; - } - -secure_vector<byte> CCM_Mode::format_b0(size_t sz) - { - secure_vector<byte> B0(BS); - - const byte b_flags = (m_ad_buf.size() ? 64 : 0) + (((tag_size()/2)-1) << 3) + (L()-1); - - B0[0] = b_flags; - copy_mem(&B0[1], &m_nonce[0], m_nonce.size()); - encode_length(sz, &B0[m_nonce.size()+1]); - - return B0; - } - -secure_vector<byte> CCM_Mode::format_c0() - { - secure_vector<byte> C(BS); - - const byte a_flags = L()-1; - - C[0] = a_flags; - copy_mem(&C[1], &m_nonce[0], m_nonce.size()); - - return C; - } - -void CCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - - buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); - - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - const secure_vector<byte>& ad = ad_buf(); - BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple"); - - const BlockCipher& E = cipher(); - - secure_vector<byte> T(BS); - E.encrypt(format_b0(sz), T); - - for(size_t i = 0; i != ad.size(); i += BS) - { - xor_buf(&T[0], &ad[i], BS); - E.encrypt(T); - } - - secure_vector<byte> C = format_c0(); - secure_vector<byte> S0(BS); - E.encrypt(C, S0); - inc(C); - - secure_vector<byte> X(BS); - - const byte* buf_end = &buf[sz]; - - while(buf != buf_end) - { - const size_t to_proc = std::min<size_t>(BS, buf_end - buf); - - xor_buf(&T[0], buf, to_proc); - E.encrypt(T); - - E.encrypt(C, X); - xor_buf(buf, &X[0], to_proc); - inc(C); - - buf += to_proc; - } - - T ^= S0; - - buffer += std::make_pair(&T[0], tag_size()); - } - -void CCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - - buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); - - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); - - const secure_vector<byte>& ad = ad_buf(); - BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple"); - - const BlockCipher& E = cipher(); - - secure_vector<byte> T(BS); - E.encrypt(format_b0(sz - tag_size()), T); - - for(size_t i = 0; i != ad.size(); i += BS) - { - xor_buf(&T[0], &ad[i], BS); - E.encrypt(T); - } - - secure_vector<byte> C = format_c0(); - - secure_vector<byte> S0(BS); - E.encrypt(C, S0); - inc(C); - - secure_vector<byte> X(BS); - - const byte* buf_end = &buf[sz - tag_size()]; - - while(buf != buf_end) - { - const size_t to_proc = std::min<size_t>(BS, buf_end - buf); - - E.encrypt(C, X); - xor_buf(buf, &X[0], to_proc); - inc(C); - - xor_buf(&T[0], buf, to_proc); - E.encrypt(T); - - buf += to_proc; - } - - T ^= S0; - - if(!same_mem(&T[0], buf_end, tag_size())) - throw Integrity_Failure("CCM tag check failed"); - - buffer.resize(buffer.size() - tag_size()); - } - -} diff --git a/src/modes/aead/ccm/ccm.h b/src/modes/aead/ccm/ccm.h deleted file mode 100644 index 87dd5805c..000000000 --- a/src/modes/aead/ccm/ccm.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -* CCM Mode -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_CCM_H__ -#define BOTAN_AEAD_CCM_H__ - -#include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/stream_cipher.h> -#include <botan/mac.h> -#include <memory> - -namespace Botan { - -/** -* Base class for CCM encryption and decryption -* @see RFC 3610 -*/ -class BOTAN_DLL CCM_Mode : public AEAD_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void set_associated_data(const byte ad[], size_t ad_len) override; - - std::string name() const override; - - size_t update_granularity() const; - - Key_Length_Specification key_spec() const override; - - bool valid_nonce_length(size_t) const override; - - size_t default_nonce_length() const override; - - void clear(); - - size_t tag_size() const { return m_tag_size; } - - protected: - const size_t BS = 16; // intrinsic to CCM definition - - CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L); - - size_t L() const { return m_L; } - - const BlockCipher& cipher() const { return *m_cipher; } - - void encode_length(size_t len, byte out[]); - - void inc(secure_vector<byte>& C); - - const secure_vector<byte>& ad_buf() const { return m_ad_buf; } - - secure_vector<byte>& msg_buf() { return m_msg_buf; } - - secure_vector<byte> format_b0(size_t msg_size); - secure_vector<byte> format_c0(); - private: - void key_schedule(const byte key[], size_t length) override; - - const size_t m_tag_size; - const size_t m_L; - - std::unique_ptr<BlockCipher> m_cipher; - secure_vector<byte> m_nonce, m_msg_buf, m_ad_buf; - }; - -/** -* CCM Encryption -*/ -class BOTAN_DLL CCM_Encryption : public CCM_Mode - { - public: - /** - * @param cipher a 128-bit block cipher - * @param tag_size is how big the auth tag will be (even values - * between 4 and 16 are accepted) - * @param L length of L parameter. The total message length - * must be less than 2**L bytes, and the nonce is 15-L bytes. - */ - CCM_Encryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) : - CCM_Mode(cipher, tag_size, L) {} - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override - { return input_length + tag_size(); } - - size_t minimum_final_size() const override { return 0; } - }; - -/** -* CCM Decryption -*/ -class BOTAN_DLL CCM_Decryption : public CCM_Mode - { - public: - /** - * @param cipher a 128-bit block cipher - * @param tag_size is how big the auth tag will be (even values - * between 4 and 16 are accepted) - * @param L length of L parameter. The total message length - * must be less than 2**L bytes, and the nonce is 15-L bytes. - */ - CCM_Decryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) : - CCM_Mode(cipher, tag_size, L) {} - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override - { - BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); - return input_length - tag_size(); - } - - size_t minimum_final_size() const override { return tag_size(); } - }; - -} - -#endif diff --git a/src/modes/aead/ccm/info.txt b/src/modes/aead/ccm/info.txt deleted file mode 100644 index ee8373caf..000000000 --- a/src/modes/aead/ccm/info.txt +++ /dev/null @@ -1 +0,0 @@ -define AEAD_CCM 20131128 diff --git a/src/modes/aead/eax/eax.cpp b/src/modes/aead/eax/eax.cpp deleted file mode 100644 index 249bf5f7e..000000000 --- a/src/modes/aead/eax/eax.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* EAX Mode Encryption -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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 { - -namespace { - -/* -* EAX MAC-based PRF -*/ -secure_vector<byte> eax_prf(byte tag, size_t block_size, - MessageAuthenticationCode& mac, - const byte in[], size_t length) - { - for(size_t i = 0; i != block_size - 1; ++i) - mac.update(0); - mac.update(tag); - mac.update(in, length); - return mac.final(); - } - -} - -/* -* EAX_Mode Constructor -*/ -EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) : - m_tag_size(tag_size ? tag_size : cipher->block_size()), - m_cipher(cipher), - m_ctr(new CTR_BE(m_cipher->clone())), - m_cmac(new CMAC(m_cipher->clone())) - { - if(m_tag_size < 8 || m_tag_size > m_cmac->output_length()) - throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size)); - } - -void EAX_Mode::clear() - { - m_cipher.reset(); - m_ctr.reset(); - m_cmac.reset(); - zeroise(m_ad_mac); - zeroise(m_nonce_mac); - } - -std::string EAX_Mode::name() const - { - return (m_cipher->name() + "/EAX"); - } - -size_t EAX_Mode::update_granularity() const - { - return 8 * m_cipher->parallel_bytes(); - } - -Key_Length_Specification EAX_Mode::key_spec() const - { - return m_cipher->key_spec(); - } - -/* -* Set the EAX key -*/ -void EAX_Mode::key_schedule(const byte key[], size_t length) - { - /* - * These could share the key schedule, which is one nice part of EAX, - * but it's much easier to ignore that here... - */ - m_ctr->set_key(key, length); - m_cmac->set_key(key, length); - - m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0); - } - -/* -* Set the EAX associated data -*/ -void EAX_Mode::set_associated_data(const byte ad[], size_t length) - { - m_ad_mac = eax_prf(1, block_size(), *m_cmac, ad, length); - } - -secure_vector<byte> EAX_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - m_nonce_mac = eax_prf(0, block_size(), *m_cmac, nonce, nonce_len); - - m_ctr->set_iv(&m_nonce_mac[0], m_nonce_mac.size()); - - for(size_t i = 0; i != block_size() - 1; ++i) - m_cmac->update(0); - m_cmac->update(2); - - return secure_vector<byte>(); - } - -void EAX_Encryption::update(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]; - - m_ctr->cipher(buf, buf, sz); - m_cmac->update(buf, sz); - } - -void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - update(buffer, offset); - - secure_vector<byte> data_mac = m_cmac->final(); - xor_buf(data_mac, m_nonce_mac, data_mac.size()); - xor_buf(data_mac, m_ad_mac, data_mac.size()); - - buffer += std::make_pair(&data_mac[0], tag_size()); - } - -void EAX_Decryption::update(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]; - - m_cmac->update(buf, sz); - m_ctr->cipher(buf, buf, sz); - } - -void EAX_Decryption::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]; - - BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input"); - - const size_t remaining = sz - tag_size(); - - if(remaining) - { - m_cmac->update(buf, remaining); - m_ctr->cipher(buf, buf, remaining); - } - - const byte* included_tag = &buf[remaining]; - - secure_vector<byte> mac = m_cmac->final(); - mac ^= m_nonce_mac; - mac ^= m_ad_mac; - - if(!same_mem(&mac[0], included_tag, tag_size())) - throw Integrity_Failure("EAX tag check failed"); - - buffer.resize(offset + remaining); - } - -} diff --git a/src/modes/aead/eax/eax.h b/src/modes/aead/eax/eax.h deleted file mode 100644 index 224fb5298..000000000 --- a/src/modes/aead/eax/eax.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -* EAX Mode -* (C) 1999-2007,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_EAX_H__ -#define BOTAN_AEAD_EAX_H__ - -#include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/stream_cipher.h> -#include <botan/mac.h> -#include <memory> - -namespace Botan { - -/** -* EAX base class -*/ -class BOTAN_DLL EAX_Mode : public AEAD_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - void set_associated_data(const byte ad[], size_t ad_len) override; - - std::string name() const override; - - size_t update_granularity() const; - - Key_Length_Specification key_spec() const override; - - // EAX supports arbitrary nonce lengths - bool valid_nonce_length(size_t) const override { return true; } - - size_t tag_size() const { return m_tag_size; } - - void clear(); - protected: - void key_schedule(const byte key[], size_t length) override; - - /** - * @param cipher the cipher to use - * @param tag_size is how big the auth tag will be - */ - EAX_Mode(BlockCipher* cipher, size_t tag_size); - - size_t block_size() const { return m_cipher->block_size(); } - - size_t m_tag_size; - - std::unique_ptr<BlockCipher> m_cipher; - std::unique_ptr<StreamCipher> m_ctr; - std::unique_ptr<MessageAuthenticationCode> m_cmac; - - secure_vector<byte> m_ad_mac; - - secure_vector<byte> m_nonce_mac; - }; - -/** -* EAX Encryption -*/ -class BOTAN_DLL EAX_Encryption : public EAX_Mode - { - public: - /** - * @param cipher a 128-bit block cipher - * @param tag_size is how big the auth tag will be - */ - EAX_Encryption(BlockCipher* cipher, size_t tag_size = 0) : - EAX_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { return input_length + tag_size(); } - - size_t minimum_final_size() const override { return 0; } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -/** -* EAX Decryption -*/ -class BOTAN_DLL EAX_Decryption : public EAX_Mode - { - public: - /** - * @param cipher a 128-bit block cipher - * @param tag_size is how big the auth tag will be - */ - EAX_Decryption(BlockCipher* cipher, size_t tag_size = 0) : - EAX_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { - BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); - return input_length - tag_size(); - } - - size_t minimum_final_size() const override { return tag_size(); } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -} - -#endif diff --git a/src/modes/aead/eax/info.txt b/src/modes/aead/eax/info.txt deleted file mode 100644 index 75775fa16..000000000 --- a/src/modes/aead/eax/info.txt +++ /dev/null @@ -1,7 +0,0 @@ -define AEAD_EAX 20131128 - -<requires> -block -cmac -ctr -</requires> diff --git a/src/modes/aead/gcm/clmul/clmul.cpp b/src/modes/aead/gcm/clmul/clmul.cpp deleted file mode 100644 index cc6d581e3..000000000 --- a/src/modes/aead/gcm/clmul/clmul.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -* CLMUL hook -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/clmul.h> -#include <immintrin.h> - -namespace Botan { - -void gcm_multiply_clmul(byte x[16], const byte H[16]) - { - /* - * Algorithms 1 and 5 from Intel's CLMUL guide - */ - const __m128i BSWAP_MASK = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - - __m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&x[0])); - __m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&H[0])); - - a = _mm_shuffle_epi8(a, BSWAP_MASK); - b = _mm_shuffle_epi8(b, BSWAP_MASK); - - __m128i T0, T1, T2, T3, T4, T5; - - T0 = _mm_clmulepi64_si128(a, b, 0x00); - T1 = _mm_clmulepi64_si128(a, b, 0x01); - T2 = _mm_clmulepi64_si128(a, b, 0x10); - T3 = _mm_clmulepi64_si128(a, b, 0x11); - - T1 = _mm_xor_si128(T1, T2); - T2 = _mm_slli_si128(T1, 8); - T1 = _mm_srli_si128(T1, 8); - T0 = _mm_xor_si128(T0, T2); - T3 = _mm_xor_si128(T3, T1); - - T4 = _mm_srli_epi32(T0, 31); - T0 = _mm_slli_epi32(T0, 1); - - T5 = _mm_srli_epi32(T3, 31); - T3 = _mm_slli_epi32(T3, 1); - - T2 = _mm_srli_si128(T4, 12); - T5 = _mm_slli_si128(T5, 4); - T4 = _mm_slli_si128(T4, 4); - T0 = _mm_or_si128(T0, T4); - T3 = _mm_or_si128(T3, T5); - T3 = _mm_or_si128(T3, T2); - - T4 = _mm_slli_epi32(T0, 31); - T5 = _mm_slli_epi32(T0, 30); - T2 = _mm_slli_epi32(T0, 25); - - T4 = _mm_xor_si128(T4, T5); - T4 = _mm_xor_si128(T4, T2); - T5 = _mm_srli_si128(T4, 4); - T3 = _mm_xor_si128(T3, T5); - T4 = _mm_slli_si128(T4, 12); - T0 = _mm_xor_si128(T0, T4); - T3 = _mm_xor_si128(T3, T0); - - T4 = _mm_srli_epi32(T0, 1); - T1 = _mm_srli_epi32(T0, 2); - T2 = _mm_srli_epi32(T0, 7); - T3 = _mm_xor_si128(T3, T1); - T3 = _mm_xor_si128(T3, T2); - T3 = _mm_xor_si128(T3, T4); - - T3 = _mm_shuffle_epi8(T3, BSWAP_MASK); - - _mm_storeu_si128(reinterpret_cast<__m128i*>(&x[0]), T3); - } - -} diff --git a/src/modes/aead/gcm/clmul/clmul.h b/src/modes/aead/gcm/clmul/clmul.h deleted file mode 100644 index ba197f2f7..000000000 --- a/src/modes/aead/gcm/clmul/clmul.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -* CLMUL hook -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/types.h> - -namespace Botan { - -void gcm_multiply_clmul(byte x[16], const byte H[16]); - -} diff --git a/src/modes/aead/gcm/clmul/info.txt b/src/modes/aead/gcm/clmul/info.txt deleted file mode 100644 index 8a21b6ac2..000000000 --- a/src/modes/aead/gcm/clmul/info.txt +++ /dev/null @@ -1,8 +0,0 @@ - -define GCM_CLMUL 20131227 - -need_isa clmul,ssse3 - -<header:internal> -clmul.h -</header:internal> diff --git a/src/modes/aead/gcm/gcm.cpp b/src/modes/aead/gcm/gcm.cpp deleted file mode 100644 index b39e6ac92..000000000 --- a/src/modes/aead/gcm/gcm.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* -* GCM Mode Encryption -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/gcm.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> - #include <botan/cpuid.h> -#endif - -namespace Botan { - -void GHASH::gcm_multiply(secure_vector<byte>& x) const - { -#if defined(BOTAN_HAS_GCM_CLMUL) - if(CPUID::has_clmul()) - return gcm_multiply_clmul(&x[0], &m_H[0]); -#endif - - static const u64bit R = 0xE100000000000000; - - u64bit H[2] = { - load_be<u64bit>(&m_H[0], 0), - load_be<u64bit>(&m_H[0], 1) - }; - - u64bit Z[2] = { 0, 0 }; - - // SSE2 might be useful here - - for(size_t i = 0; i != 2; ++i) - { - const u64bit X = load_be<u64bit>(&x[0], i); - - for(size_t j = 0; j != 64; ++j) - { - if((X >> (63-j)) & 1) - { - Z[0] ^= H[0]; - Z[1] ^= H[1]; - } - - const u64bit r = (H[1] & 1) ? R : 0; - - H[1] = (H[0] << 63) | (H[1] >> 1); - H[0] = (H[0] >> 1) ^ r; - } - } - - store_be<u64bit>(&x[0], Z[0], Z[1]); - } - -void GHASH::ghash_update(secure_vector<byte>& ghash, - const byte input[], size_t length) - { - const size_t BS = 16; - - /* - This assumes if less than block size input then we're just on the - final block and should pad with zeros - */ - while(length) - { - const size_t to_proc = std::min(length, BS); - - xor_buf(&ghash[0], &input[0], to_proc); - - gcm_multiply(ghash); - - input += to_proc; - length -= to_proc; - } - } - -void GHASH::key_schedule(const byte key[], size_t length) - { - m_H.assign(key, key+length); - m_H_ad.resize(16); - m_ad_len = 0; - m_text_len = 0; - } - -void GHASH::start(const byte nonce[], size_t len) - { - m_nonce.assign(nonce, nonce + len); - m_ghash = m_H_ad; - } - -void GHASH::set_associated_data(const byte input[], size_t length) - { - zeroise(m_H_ad); - - ghash_update(m_H_ad, input, length); - m_ad_len = length; - } - -void GHASH::update(const byte input[], size_t length) - { - BOTAN_ASSERT(m_ghash.size() == 16, "Key was set"); - - m_text_len += length; - - ghash_update(m_ghash, input, length); - } - -void GHASH::add_final_block(secure_vector<byte>& hash, - size_t ad_len, size_t text_len) - { - secure_vector<byte> final_block(16); - store_be<u64bit>(&final_block[0], 8*ad_len, 8*text_len); - ghash_update(hash, &final_block[0], final_block.size()); - } - -secure_vector<byte> GHASH::final() - { - add_final_block(m_ghash, m_ad_len, m_text_len); - - secure_vector<byte> mac; - mac.swap(m_ghash); - - mac ^= m_nonce; - m_text_len = 0; - return mac; - } - -secure_vector<byte> GHASH::nonce_hash(const byte nonce[], size_t nonce_len) - { - BOTAN_ASSERT(m_ghash.size() == 0, "nonce_hash called during wrong time"); - secure_vector<byte> y0(16); - - ghash_update(y0, nonce, nonce_len); - add_final_block(y0, 0, nonce_len); - - return y0; - } - -void GHASH::clear() - { - zeroise(m_H); - zeroise(m_H_ad); - m_ghash.clear(); - m_text_len = m_ad_len = 0; - } - -/* -* GCM_Mode Constructor -*/ -GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) : - m_tag_size(tag_size), - m_cipher_name(cipher->name()) - { - if(cipher->block_size() != BS) - throw std::invalid_argument("GCM requires a 128 bit cipher so cannot be used with " + - cipher->name()); - - m_ghash.reset(new GHASH); - - m_ctr.reset(new CTR_BE(cipher)); // CTR_BE takes ownership of cipher - - if(m_tag_size != 8 && m_tag_size != 16) - throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(m_tag_size)); - } - -void GCM_Mode::clear() - { - m_ctr->clear(); - m_ghash->clear(); - } - -std::string GCM_Mode::name() const - { - return (m_cipher_name + "/GCM"); - } - -size_t GCM_Mode::update_granularity() const - { - return 4096; // CTR-BE's internal block size - } - -Key_Length_Specification GCM_Mode::key_spec() const - { - return m_ctr->key_spec(); - } - -void GCM_Mode::key_schedule(const byte key[], size_t keylen) - { - m_ctr->set_key(key, keylen); - - const std::vector<byte> zeros(BS); - m_ctr->set_iv(&zeros[0], zeros.size()); - - secure_vector<byte> H(BS); - m_ctr->encipher(H); - m_ghash->set_key(H); - } - -void GCM_Mode::set_associated_data(const byte ad[], size_t ad_len) - { - m_ghash->set_associated_data(ad, ad_len); - } - -secure_vector<byte> GCM_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - secure_vector<byte> y0(BS); - - if(nonce_len == 12) - { - copy_mem(&y0[0], nonce, nonce_len); - y0[15] = 1; - } - else - { - y0 = m_ghash->nonce_hash(nonce, nonce_len); - } - - m_ctr->set_iv(&y0[0], y0.size()); - - secure_vector<byte> m_enc_y0(BS); - m_ctr->encipher(m_enc_y0); - - m_ghash->start(&m_enc_y0[0], m_enc_y0.size()); - - return secure_vector<byte>(); - } - -void GCM_Encryption::update(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]; - - m_ctr->cipher(buf, buf, sz); - m_ghash->update(buf, sz); - } - -void GCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - update(buffer, offset); - auto mac = m_ghash->final(); - buffer += std::make_pair(&mac[0], tag_size()); - } - -void GCM_Decryption::update(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]; - - m_ghash->update(buf, sz); - m_ctr->cipher(buf, buf, sz); - } - -void GCM_Decryption::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]; - - BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input"); - - const size_t remaining = sz - tag_size(); - - // handle any final input before the tag - if(remaining) - { - m_ghash->update(buf, remaining); - m_ctr->cipher(buf, buf, remaining); - } - - auto mac = m_ghash->final(); - - const byte* included_tag = &buffer[remaining]; - - if(!same_mem(&mac[0], included_tag, tag_size())) - throw Integrity_Failure("GCM tag check failed"); - - buffer.resize(offset + remaining); - } - -} diff --git a/src/modes/aead/gcm/gcm.h b/src/modes/aead/gcm/gcm.h deleted file mode 100644 index 12d66a3d1..000000000 --- a/src/modes/aead/gcm/gcm.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -* GCM Mode -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_GCM_H__ -#define BOTAN_AEAD_GCM_H__ - -#include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/stream_cipher.h> -#include <memory> - -namespace Botan { - -class GHASH; - -/** -* GCM Mode -*/ -class BOTAN_DLL GCM_Mode : public AEAD_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - void set_associated_data(const byte ad[], size_t ad_len) override; - - std::string name() const override; - - size_t update_granularity() const; - - Key_Length_Specification key_spec() const override; - - // GCM supports arbitrary nonce lengths - bool valid_nonce_length(size_t) const override { return true; } - - size_t tag_size() const { return m_tag_size; } - - void clear(); - protected: - void key_schedule(const byte key[], size_t length) override; - - GCM_Mode(BlockCipher* cipher, size_t tag_size); - - const size_t BS = 16; - - const size_t m_tag_size; - const std::string m_cipher_name; - - std::unique_ptr<StreamCipher> m_ctr; - std::unique_ptr<GHASH> m_ghash; - }; - -/** -* GCM Encryption -*/ -class BOTAN_DLL GCM_Encryption : public GCM_Mode - { - public: - /** - * @param cipher the 128 bit block cipher to use - * @param tag_size is how big the auth tag will be - */ - GCM_Encryption(BlockCipher* cipher, size_t tag_size = 16) : - GCM_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { return input_length + tag_size(); } - - size_t minimum_final_size() const override { return 0; } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -/** -* GCM Decryption -*/ -class BOTAN_DLL GCM_Decryption : public GCM_Mode - { - public: - /** - * @param cipher the 128 bit block cipher to use - * @param tag_size is how big the auth tag will be - */ - GCM_Decryption(BlockCipher* cipher, size_t tag_size = 16) : - GCM_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { - BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); - return input_length - tag_size(); - } - - size_t minimum_final_size() const override { return tag_size(); } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -/** -* GCM's GHASH -* Maybe a Transform? -*/ -class BOTAN_DLL GHASH : public SymmetricAlgorithm - { - public: - void set_associated_data(const byte ad[], size_t ad_len); - - secure_vector<byte> nonce_hash(const byte nonce[], size_t len); - - void start(const byte nonce[], size_t len); - - /* - * Assumes input len is multiple of 16 - */ - void update(const byte in[], size_t len); - - secure_vector<byte> final(); - - Key_Length_Specification key_spec() const { return Key_Length_Specification(16); } - - void clear(); - - std::string name() const { return "GHASH"; } - private: - void key_schedule(const byte key[], size_t key_len) override; - - void gcm_multiply(secure_vector<byte>& x) const; - - void ghash_update(secure_vector<byte>& x, - const byte input[], size_t input_len); - - void add_final_block(secure_vector<byte>& x, - size_t ad_len, size_t pt_len); - - secure_vector<byte> m_H; - secure_vector<byte> m_H_ad; - secure_vector<byte> m_nonce; - secure_vector<byte> m_ghash; - size_t m_ad_len = 0, m_text_len = 0; - }; - -} - -#endif diff --git a/src/modes/aead/gcm/info.txt b/src/modes/aead/gcm/info.txt deleted file mode 100644 index cf5f68bb5..000000000 --- a/src/modes/aead/gcm/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define AEAD_GCM 20131128 - -<requires> -block -ctr -</requires> diff --git a/src/modes/aead/info.txt b/src/modes/aead/info.txt deleted file mode 100644 index 102f05b7b..000000000 --- a/src/modes/aead/info.txt +++ /dev/null @@ -1 +0,0 @@ -define AEAD_MODES 20131128 diff --git a/src/modes/aead/ocb/info.txt b/src/modes/aead/ocb/info.txt deleted file mode 100644 index be4cefdd0..000000000 --- a/src/modes/aead/ocb/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define AEAD_OCB 20131128 - -<requires> -block -cmac -</requires> diff --git a/src/modes/aead/ocb/ocb.cpp b/src/modes/aead/ocb/ocb.cpp deleted file mode 100644 index fd66bb2e9..000000000 --- a/src/modes/aead/ocb/ocb.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* -* OCB Mode -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ocb.h> -#include <botan/cmac.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/bit_ops.h> -#include <algorithm> - -namespace Botan { - -namespace { - -const size_t BS = 16; // intrinsic to OCB definition - -} - -// Has to be in Botan namespace so unique_ptr can reference it -class L_computer - { - public: - L_computer(const BlockCipher& cipher) - { - m_L_star.resize(cipher.block_size()); - cipher.encrypt(m_L_star); - m_L_dollar = poly_double(star()); - m_L.push_back(poly_double(dollar())); - } - - const secure_vector<byte>& star() const { return m_L_star; } - - const secure_vector<byte>& dollar() const { return m_L_dollar; } - - const secure_vector<byte>& operator()(size_t i) const { return get(i); } - - const secure_vector<byte>& compute_offsets(secure_vector<byte>& offset, - size_t block_index, - size_t blocks) const - { - m_offset_buf.resize(blocks*BS); - - for(size_t i = 0; i != blocks; ++i) - { // could be done in parallel - offset ^= get(ctz(block_index + 1 + i)); - copy_mem(&m_offset_buf[BS*i], &offset[0], BS); - } - - return m_offset_buf; - } - - private: - const secure_vector<byte>& get(size_t i) const - { - while(m_L.size() <= i) - m_L.push_back(poly_double(m_L.back())); - - return m_L.at(i); - } - - secure_vector<byte> poly_double(const secure_vector<byte>& in) const - { - return CMAC::poly_double(in, 0x87); - } - - secure_vector<byte> m_L_dollar, m_L_star; - mutable std::vector<secure_vector<byte>> m_L; - mutable secure_vector<byte> m_offset_buf; - }; - -namespace { - -/* -* OCB's HASH -*/ -secure_vector<byte> ocb_hash(const L_computer& L, - const BlockCipher& cipher, - const byte ad[], size_t ad_len) - { - secure_vector<byte> sum(BS); - secure_vector<byte> offset(BS); - - secure_vector<byte> buf(BS); - - const size_t ad_blocks = (ad_len / BS); - const size_t ad_remainder = (ad_len % BS); - - for(size_t i = 0; i != ad_blocks; ++i) - { - // this loop could run in parallel - offset ^= L(ctz(i+1)); - - buf = offset; - xor_buf(&buf[0], &ad[BS*i], BS); - - cipher.encrypt(buf); - - sum ^= buf; - } - - if(ad_remainder) - { - offset ^= L.star(); - - buf = offset; - xor_buf(&buf[0], &ad[BS*ad_blocks], ad_remainder); - buf[ad_len % BS] ^= 0x80; - - cipher.encrypt(buf); - - sum ^= buf; - } - - return sum; - } - -} - -OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size) : - m_cipher(cipher), - m_checksum(m_cipher->parallel_bytes()), - m_offset(BS), - m_ad_hash(BS), - m_tag_size(tag_size) - { - if(m_cipher->block_size() != BS) - throw std::invalid_argument("OCB requires a 128 bit cipher so cannot be used with " + - m_cipher->name()); - - if(m_tag_size != 8 && m_tag_size != 12 && m_tag_size != 16) - throw std::invalid_argument("OCB cannot produce a " + std::to_string(m_tag_size) + - " byte tag"); - - } - -OCB_Mode::~OCB_Mode() { /* for unique_ptr destructor */ } - -void OCB_Mode::clear() - { - m_cipher.reset(); - m_L.reset(); - - zeroise(m_ad_hash); - zeroise(m_offset); - zeroise(m_checksum); - } - -bool OCB_Mode::valid_nonce_length(size_t length) const - { - return (length > 0 && length < 16); - } - -std::string OCB_Mode::name() const - { - return m_cipher->name() + "/OCB"; // include tag size - } - -size_t OCB_Mode::update_granularity() const - { - return m_cipher->parallel_bytes(); - } - -Key_Length_Specification OCB_Mode::key_spec() const - { - return m_cipher->key_spec(); - } - -void OCB_Mode::key_schedule(const byte key[], size_t length) - { - m_cipher->set_key(key, length); - m_L.reset(new L_computer(*m_cipher)); - } - -void OCB_Mode::set_associated_data(const byte ad[], size_t ad_len) - { - BOTAN_ASSERT(m_L, "A key was set"); - m_ad_hash = ocb_hash(*m_L, *m_cipher, &ad[0], ad_len); - } - -secure_vector<byte> -OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) - { - BOTAN_ASSERT(nonce_len < BS, "Nonce is less than 128 bits"); - - secure_vector<byte> nonce_buf(BS); - - copy_mem(&nonce_buf[BS - nonce_len], nonce, nonce_len); - nonce_buf[0] = ((tag_size() * 8) % 128) << 1; - nonce_buf[BS - nonce_len - 1] = 1; - - const byte bottom = nonce_buf[15] & 0x3F; - nonce_buf[15] &= 0xC0; - - const bool need_new_stretch = (m_last_nonce != nonce_buf); - - if(need_new_stretch) - { - m_last_nonce = nonce_buf; - - m_cipher->encrypt(nonce_buf); - - for(size_t i = 0; i != 8; ++i) - nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]); - - m_stretch = nonce_buf; - } - - // now set the offset from stretch and bottom - - const size_t shift_bytes = bottom / 8; - const size_t shift_bits = bottom % 8; - - secure_vector<byte> offset(BS); - for(size_t i = 0; i != BS; ++i) - { - offset[i] = (m_stretch[i+shift_bytes] << shift_bits); - offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits)); - } - - return offset; - } - -secure_vector<byte> OCB_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - BOTAN_ASSERT(m_L, "A key was set"); - - m_offset = update_nonce(nonce, nonce_len); - zeroise(m_checksum); - m_block_index = 0; - - return secure_vector<byte>(); - } - -void OCB_Encryption::encrypt(byte buffer[], size_t blocks) - { - const L_computer& L = *m_L; // convenient name - - const size_t par_blocks = m_checksum.size() / BS; - - while(blocks) - { - const size_t proc_blocks = std::min(blocks, par_blocks); - const size_t proc_bytes = proc_blocks * BS; - - const auto& offsets = L.compute_offsets(m_offset, m_block_index, proc_blocks); - - xor_buf(&m_checksum[0], &buffer[0], proc_bytes); - - xor_buf(&buffer[0], &offsets[0], proc_bytes); - m_cipher->encrypt_n(&buffer[0], &buffer[0], proc_blocks); - xor_buf(&buffer[0], &offsets[0], proc_bytes); - - buffer += proc_bytes; - blocks -= proc_blocks; - m_block_index += proc_blocks; - } - } - -void OCB_Encryption::update(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]; - - BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); - - encrypt(buf, sz / BS); - } - -void OCB_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]; - - if(sz) - { - const size_t final_full_blocks = sz / BS; - const size_t remainder_bytes = sz - (final_full_blocks * BS); - - encrypt(buf, final_full_blocks); - - if(remainder_bytes) - { - BOTAN_ASSERT(remainder_bytes < BS, "Only a partial block left"); - byte* remainder = &buf[sz - remainder_bytes]; - - xor_buf(&m_checksum[0], &remainder[0], remainder_bytes); - m_checksum[remainder_bytes] ^= 0x80; - - m_offset ^= m_L->star(); // Offset_* - - secure_vector<byte> buf(BS); - m_cipher->encrypt(m_offset, buf); - xor_buf(&remainder[0], &buf[0], remainder_bytes); - } - } - - secure_vector<byte> checksum(BS); - - // fold checksum - for(size_t i = 0; i != m_checksum.size(); ++i) - checksum[i % checksum.size()] ^= m_checksum[i]; - - // now compute the tag - secure_vector<byte> mac = m_offset; - mac ^= checksum; - mac ^= m_L->dollar(); - - m_cipher->encrypt(mac); - - mac ^= m_ad_hash; - - buffer += std::make_pair(&mac[0], tag_size()); - - zeroise(m_checksum); - zeroise(m_offset); - m_block_index = 0; - } - -void OCB_Decryption::decrypt(byte buffer[], size_t blocks) - { - const L_computer& L = *m_L; // convenient name - - const size_t par_bytes = m_cipher->parallel_bytes(); - - BOTAN_ASSERT(par_bytes % BS == 0, "Cipher is parallel in full blocks"); - - const size_t par_blocks = par_bytes / BS; - - while(blocks) - { - const size_t proc_blocks = std::min(blocks, par_blocks); - const size_t proc_bytes = proc_blocks * BS; - - const auto& offsets = L.compute_offsets(m_offset, m_block_index, proc_blocks); - - xor_buf(&buffer[0], &offsets[0], proc_bytes); - m_cipher->decrypt_n(&buffer[0], &buffer[0], proc_blocks); - xor_buf(&buffer[0], &offsets[0], proc_bytes); - - xor_buf(&m_checksum[0], &buffer[0], proc_bytes); - - buffer += proc_bytes; - blocks -= proc_blocks; - m_block_index += proc_blocks; - } - } - -void OCB_Decryption::update(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]; - - BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); - - decrypt(buf, sz / BS); - } - -void OCB_Decryption::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]; - - BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); - - const size_t remaining = sz - tag_size(); - - if(remaining) - { - const size_t final_full_blocks = remaining / BS; - const size_t final_bytes = remaining - (final_full_blocks * BS); - - decrypt(&buf[0], final_full_blocks); - - if(final_bytes) - { - BOTAN_ASSERT(final_bytes < BS, "Only a partial block left"); - - byte* remainder = &buf[remaining - final_bytes]; - - m_offset ^= m_L->star(); // Offset_* - - secure_vector<byte> pad(BS); - m_cipher->encrypt(m_offset, pad); // P_* - - xor_buf(&remainder[0], &pad[0], final_bytes); - - xor_buf(&m_checksum[0], &remainder[0], final_bytes); - m_checksum[final_bytes] ^= 0x80; - } - } - - secure_vector<byte> checksum(BS); - - // fold checksum - for(size_t i = 0; i != m_checksum.size(); ++i) - checksum[i % checksum.size()] ^= m_checksum[i]; - - // compute the mac - secure_vector<byte> mac = m_offset; - mac ^= checksum; - mac ^= m_L->dollar(); - - m_cipher->encrypt(mac); - - mac ^= m_ad_hash; - - // reset state - zeroise(m_checksum); - zeroise(m_offset); - m_block_index = 0; - - // compare mac - const byte* included_tag = &buf[remaining]; - - if(!same_mem(&mac[0], included_tag, tag_size())) - throw Integrity_Failure("OCB tag check failed"); - - // remove tag from end of message - buffer.resize(remaining + offset); - } - -} diff --git a/src/modes/aead/ocb/ocb.h b/src/modes/aead/ocb/ocb.h deleted file mode 100644 index e7d042de3..000000000 --- a/src/modes/aead/ocb/ocb.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -* OCB Mode -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_OCB_H__ -#define BOTAN_AEAD_OCB_H__ - -#include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/buf_filt.h> -#include <memory> - -namespace Botan { - -class L_computer; - -/** -* OCB Mode (base class for OCB_Encryption and OCB_Decryption). Note -* that OCB is patented, but is freely licensed in some circumstances. -* -* @see "The OCB Authenticated-Encryption Algorithm" internet draft - http://tools.ietf.org/html/draft-irtf-cfrg-ocb-03 -* @see Free Licenses http://www.cs.ucdavis.edu/~rogaway/ocb/license.htm -* @see OCB home page http://www.cs.ucdavis.edu/~rogaway/ocb -*/ -class BOTAN_DLL OCB_Mode : public AEAD_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - void set_associated_data(const byte ad[], size_t ad_len) override; - - std::string name() const override; - - size_t update_granularity() const; - - Key_Length_Specification key_spec() const override; - - bool valid_nonce_length(size_t) const override; - - size_t tag_size() const { return m_tag_size; } - - void clear(); - - ~OCB_Mode(); - protected: - /** - * @param cipher the 128-bit block cipher to use - * @param tag_size is how big the auth tag will be - */ - OCB_Mode(BlockCipher* cipher, size_t tag_size); - - void key_schedule(const byte key[], size_t length) override; - - // fixme make these private - std::unique_ptr<BlockCipher> m_cipher; - std::unique_ptr<L_computer> m_L; - - size_t m_block_index = 0; - - secure_vector<byte> m_checksum; - secure_vector<byte> m_offset; - secure_vector<byte> m_ad_hash; - private: - secure_vector<byte> update_nonce(const byte nonce[], size_t nonce_len); - - size_t m_tag_size = 0; - secure_vector<byte> m_last_nonce; - secure_vector<byte> m_stretch; - }; - -class BOTAN_DLL OCB_Encryption : public OCB_Mode - { - public: - /** - * @param cipher the 128-bit block cipher to use - * @param tag_size is how big the auth tag will be - */ - OCB_Encryption(BlockCipher* cipher, size_t tag_size = 16) : - OCB_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { return input_length + tag_size(); } - - size_t minimum_final_size() const override { return 0; } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - private: - void encrypt(byte input[], size_t blocks); - }; - -class BOTAN_DLL OCB_Decryption : public OCB_Mode - { - public: - /** - * @param cipher the 128-bit block cipher to use - * @param tag_size is how big the auth tag will be - */ - OCB_Decryption(BlockCipher* cipher, size_t tag_size = 16) : - OCB_Mode(cipher, tag_size) {} - - size_t output_length(size_t input_length) const override - { - BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); - return input_length - tag_size(); - } - - size_t minimum_final_size() const override { return tag_size(); } - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - private: - void decrypt(byte input[], size_t blocks); - }; - -} - -#endif diff --git a/src/modes/aead/siv/info.txt b/src/modes/aead/siv/info.txt deleted file mode 100644 index b1e38568e..000000000 --- a/src/modes/aead/siv/info.txt +++ /dev/null @@ -1,3 +0,0 @@ -define AEAD_SIV 20131202 - -load_on auto diff --git a/src/modes/aead/siv/siv.cpp b/src/modes/aead/siv/siv.cpp deleted file mode 100644 index a89c3dd08..000000000 --- a/src/modes/aead/siv/siv.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* -* SIV Mode Encryption -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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 { - -SIV_Mode::SIV_Mode(BlockCipher* cipher) : - m_name(cipher->name() + "/SIV"), - m_ctr(new CTR_BE(cipher->clone())), - m_cmac(new CMAC(cipher)) - { - } - -void SIV_Mode::clear() - { - m_ctr.reset(); - m_nonce.clear(); - m_msg_buf.clear(); - m_ad_macs.clear(); - } - -std::string SIV_Mode::name() const - { - return m_name; - } - -bool SIV_Mode::valid_nonce_length(size_t) const - { - return true; - } - -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 - somewhat large size to avoid bouncing on a tiny buffer. - */ - return 128; - } - -Key_Length_Specification SIV_Mode::key_spec() const - { - return m_cmac->key_spec().multiple(2); - } - -void SIV_Mode::key_schedule(const byte key[], size_t length) - { - const size_t keylen = length / 2; - m_cmac->set_key(key, keylen); - m_ctr->set_key(key + keylen, keylen); - m_ad_macs.clear(); - } - -void SIV_Mode::set_associated_data_n(size_t n, const byte ad[], size_t length) - { - if(n >= m_ad_macs.size()) - m_ad_macs.resize(n+1); - - m_ad_macs[n] = m_cmac->process(ad, length); - } - -secure_vector<byte> SIV_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - if(nonce_len) - m_nonce = m_cmac->process(nonce, nonce_len); - else - m_nonce.clear(); - - m_msg_buf.clear(); - - return secure_vector<byte>(); - } - -void SIV_Mode::update(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]; - - m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); - buffer.resize(offset); // truncate msg - } - -secure_vector<byte> SIV_Mode::S2V(const byte* text, size_t text_len) - { - const byte zero[16] = { 0 }; - - secure_vector<byte> V = cmac().process(zero, 16); - - for(size_t i = 0; i != m_ad_macs.size(); ++i) - { - V = CMAC::poly_double(V, 0x87); - V ^= m_ad_macs[i]; - } - - if(m_nonce.size()) - { - V = CMAC::poly_double(V, 0x87); - V ^= m_nonce; - } - - if(text_len < 16) - { - V = CMAC::poly_double(V, 0x87); - xor_buf(&V[0], text, text_len); - V[text_len] ^= 0x80; - return cmac().process(V); - } - - cmac().update(text, text_len - 16); - xor_buf(&V[0], &text[text_len - 16], 16); - cmac().update(V); - - return cmac().final(); - } - -void SIV_Mode::set_ctr_iv(secure_vector<byte> V) - { - V[8] &= 0x7F; - V[12] &= 0x7F; - - ctr().set_iv(&V[0], V.size()); - } - -void SIV_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - - buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); - - secure_vector<byte> V = S2V(&buffer[offset], buffer.size() - offset); - - buffer.insert(buffer.begin() + offset, V.begin(), V.end()); - - set_ctr_iv(V); - ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size()); - } - -void SIV_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - - buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); - - const size_t sz = buffer.size() - offset; - - BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); - - secure_vector<byte> V(&buffer[offset], &buffer[offset + 16]); - - set_ctr_iv(V); - - ctr().cipher(&buffer[offset + V.size()], - &buffer[offset], - buffer.size() - offset - V.size()); - - secure_vector<byte> T = S2V(&buffer[offset], buffer.size() - offset - V.size()); - - if(T != V) - throw Integrity_Failure("SIV tag check failed"); - - buffer.resize(buffer.size() - tag_size()); - } - -} diff --git a/src/modes/aead/siv/siv.h b/src/modes/aead/siv/siv.h deleted file mode 100644 index 31df4d049..000000000 --- a/src/modes/aead/siv/siv.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -* SIV Mode -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_AEAD_SIV_H__ -#define BOTAN_AEAD_SIV_H__ - -#include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/stream_cipher.h> -#include <botan/mac.h> -#include <memory> - -namespace Botan { - -/** -* Base class for SIV encryption and decryption (@see RFC 5297) -*/ -class BOTAN_DLL SIV_Mode : public AEAD_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void set_associated_data_n(size_t n, const byte ad[], size_t ad_len); - - void set_associated_data(const byte ad[], size_t ad_len) override - { - set_associated_data_n(0, ad, ad_len); - } - - std::string name() const override; - - size_t update_granularity() const; - - Key_Length_Specification key_spec() const override; - - bool valid_nonce_length(size_t) const override; - - void clear(); - - size_t tag_size() const { return 16; } - - protected: - SIV_Mode(BlockCipher* cipher); - - StreamCipher& ctr() { return *m_ctr; } - - void set_ctr_iv(secure_vector<byte> V); - - secure_vector<byte>& msg_buf() { return m_msg_buf; } - - secure_vector<byte> S2V(const byte text[], size_t text_len); - private: - MessageAuthenticationCode& cmac() { return *m_cmac; } - - void key_schedule(const byte key[], size_t length) override; - - const std::string m_name; - - std::unique_ptr<StreamCipher> m_ctr; - std::unique_ptr<MessageAuthenticationCode> m_cmac; - secure_vector<byte> m_nonce, m_msg_buf; - std::vector<secure_vector<byte>> m_ad_macs; - }; - -/** -* SIV Encryption -*/ -class BOTAN_DLL SIV_Encryption : public SIV_Mode - { - public: - /** - * @param cipher a block cipher - */ - SIV_Encryption(BlockCipher* cipher) : SIV_Mode(cipher) {} - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override - { return input_length + tag_size(); } - - size_t minimum_final_size() const override { return 0; } - }; - -/** -* SIV Decryption -*/ -class BOTAN_DLL SIV_Decryption : public SIV_Mode - { - public: - /** - * @param cipher a 128-bit block cipher - */ - SIV_Decryption(BlockCipher* cipher) : SIV_Mode(cipher) {} - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override - { - BOTAN_ASSERT(input_length > tag_size(), "Sufficient input"); - return input_length - tag_size(); - } - - size_t minimum_final_size() const override { return tag_size(); } - }; - -} - -#endif diff --git a/src/modes/cbc/cbc.cpp b/src/modes/cbc/cbc.cpp deleted file mode 100644 index 31834bade..000000000 --- a/src/modes/cbc/cbc.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* -* CBC Mode -* (C) 1999-2007,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/cbc.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> - -namespace Botan { - -CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - m_cipher(cipher), - m_padding(padding), - m_state(m_cipher->block_size()) - { - if(m_padding && !m_padding->valid_blocksize(cipher->block_size())) - throw std::invalid_argument("Padding " + m_padding->name() + - " cannot be used with " + - cipher->name() + "/CBC"); - } - -void CBC_Mode::clear() - { - m_cipher->clear(); - m_state.clear(); - } - -std::string CBC_Mode::name() const - { - if(m_padding) - return cipher().name() + "/CBC/" + padding().name(); - else - return cipher().name() + "/CBC/CTS"; - } - -size_t CBC_Mode::update_granularity() const - { - return cipher().parallel_bytes(); - } - -Key_Length_Specification CBC_Mode::key_spec() const - { - return cipher().key_spec(); - } - -size_t CBC_Mode::default_nonce_length() const - { - return cipher().block_size(); - } - -bool CBC_Mode::valid_nonce_length(size_t n) const - { - return (n == 0 || n == cipher().block_size()); - } - -void CBC_Mode::key_schedule(const byte key[], size_t length) - { - m_cipher->set_key(key, length); - } - -secure_vector<byte> CBC_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - /* - * A nonce of zero length means carry the last ciphertext value over - * as the new IV, as unfortunately some protocols require this. If - * this is the first message then we use an IV of all zeros. - */ - if(nonce_len) - m_state.assign(nonce, nonce + nonce_len); - - return secure_vector<byte>(); - } - -size_t CBC_Encryption::minimum_final_size() const - { - return 0; - } - -size_t CBC_Encryption::output_length(size_t input_length) const - { - return round_up(input_length, cipher().block_size()); - } - -void CBC_Encryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "CBC input is full blocks"); - const size_t blocks = sz / BS; - - if(blocks) - { - xor_buf(&buf[0], state_ptr(), BS); - cipher().encrypt(&buf[0]); - - for(size_t i = 1; i != blocks; ++i) - { - xor_buf(&buf[BS*i], &buf[BS*(i-1)], BS); - cipher().encrypt(&buf[BS*i]); - } - - state().assign(&buf[BS*(blocks-1)], &buf[BS*blocks]); - } - } - -void CBC_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - - const size_t BS = cipher().block_size(); - - const size_t bytes_in_final_block = (buffer.size()-offset) % BS; - - padding().add_padding(buffer, bytes_in_final_block, BS); - - if((buffer.size()-offset) % BS) - throw std::runtime_error("Did not pad to full block size in " + name()); - - update(buffer, offset); - } - -bool CTS_Encryption::valid_nonce_length(size_t n) const - { - return (n == cipher().block_size()); - } - -size_t CTS_Encryption::minimum_final_size() const - { - return cipher().block_size() + 1; - } - -size_t CTS_Encryption::output_length(size_t input_length) const - { - return input_length; // no ciphertext expansion in CTS - } - -void CTS_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - byte* buf = &buffer[offset]; - const size_t sz = buffer.size() - offset; - - const size_t BS = cipher().block_size(); - - if(sz < BS + 1) - throw Encoding_Error(name() + ": insufficient data to encrypt"); - - if(sz % BS == 0) - { - update(buffer, offset); - - // swap last two blocks - for(size_t i = 0; i != BS; ++i) - std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]); - } - else - { - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - xor_buf(&last[0], state_ptr(), BS); - cipher().encrypt(&last[0]); - - for(size_t i = 0; i != final_bytes - BS; ++i) - { - std::swap(last[i], last[i + BS]); - last[i] ^= last[i + BS]; - } - - cipher().encrypt(&last[0]); - - buffer += last; - } - } - -size_t CBC_Decryption::output_length(size_t input_length) const - { - return input_length; // precise for CTS, worst case otherwise - } - -size_t CBC_Decryption::minimum_final_size() const - { - return cipher().block_size(); - } - -void CBC_Decryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - while(blocks) - { - const size_t to_proc = std::min(BS * blocks, m_tempbuf.size()); - - cipher().decrypt_n(buf, &m_tempbuf[0], to_proc / BS); - - xor_buf(&m_tempbuf[0], state_ptr(), BS); - xor_buf(&m_tempbuf[BS], buf, to_proc - BS); - copy_mem(state_ptr(), buf + (to_proc - BS), BS); - - copy_mem(buf, &m_tempbuf[0], to_proc); - - buf += to_proc; - blocks -= to_proc / BS; - } - } - -void CBC_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - - const size_t BS = cipher().block_size(); - - if(sz == 0 || sz % BS) - throw Decoding_Error(name() + ": Ciphertext not a multiple of block size"); - - update(buffer, offset); - - const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS); - buffer.resize(buffer.size() - pad_bytes); // remove padding - } - -bool CTS_Decryption::valid_nonce_length(size_t n) const - { - return (n == cipher().block_size()); - } - -size_t CTS_Decryption::minimum_final_size() const - { - return cipher().block_size() + 1; - } - -void CTS_Decryption::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(); - - if(sz < BS + 1) - throw Encoding_Error(name() + ": insufficient data to decrypt"); - - if(sz % BS == 0) - { - // swap last two blocks - for(size_t i = 0; i != BS; ++i) - std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]); - - update(buffer, offset); - } - else - { - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - cipher().decrypt(&last[0]); - xor_buf(&last[0], &last[BS], final_bytes - BS); - - for(size_t i = 0; i != final_bytes - BS; ++i) - std::swap(last[i], last[i + BS]); - - cipher().decrypt(&last[0]); - xor_buf(&last[0], state_ptr(), BS); - - buffer += last; - } - - } - -} diff --git a/src/modes/cbc/cbc.h b/src/modes/cbc/cbc.h deleted file mode 100644 index 0a10f3661..000000000 --- a/src/modes/cbc/cbc.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -* CBC mode -* (C) 1999-2007,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MODE_CBC_H__ -#define BOTAN_MODE_CBC_H__ - -#include <botan/cipher_mode.h> -#include <botan/block_cipher.h> -#include <botan/mode_pad.h> -#include <memory> - -namespace Botan { - -/** -* CBC Mode -*/ -class BOTAN_DLL CBC_Mode : public Cipher_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - std::string name() const override; - - size_t update_granularity() const override; - - Key_Length_Specification key_spec() const override; - - size_t default_nonce_length() const override; - - bool valid_nonce_length(size_t n) const override; - - void clear(); - protected: - CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding); - - const BlockCipher& cipher() const { return *m_cipher; } - - const BlockCipherModePaddingMethod& padding() const - { - BOTAN_ASSERT_NONNULL(m_padding); - return *m_padding; - } - - secure_vector<byte>& state() { return m_state; } - - byte* state_ptr() { return &m_state[0]; } - - private: - void key_schedule(const byte key[], size_t length) override; - - std::unique_ptr<BlockCipher> m_cipher; - std::unique_ptr<BlockCipherModePaddingMethod> m_padding; - secure_vector<byte> m_state; - }; - -/** -* CBC Encryption -*/ -class BOTAN_DLL CBC_Encryption : public CBC_Mode - { - public: - CBC_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - CBC_Mode(cipher, padding) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - - size_t minimum_final_size() const override; - }; - -/** -* CBC Encryption with ciphertext stealing (CBC-CS3 variant) -*/ -class BOTAN_DLL CTS_Encryption : public CBC_Encryption - { - public: - CTS_Encryption(BlockCipher* cipher) : CBC_Encryption(cipher, nullptr) {} - - size_t output_length(size_t input_length) const override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t minimum_final_size() const override; - - bool valid_nonce_length(size_t n) const; - }; - -/** -* CBC Decryption -*/ -class BOTAN_DLL CBC_Decryption : public CBC_Mode - { - public: - CBC_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - CBC_Mode(cipher, padding), m_tempbuf(update_granularity()) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - - size_t minimum_final_size() const override; - private: - secure_vector<byte> m_tempbuf; - }; - -/** -* CBC Decryption with ciphertext stealing (CBC-CS3 variant) -*/ -class BOTAN_DLL CTS_Decryption : public CBC_Decryption - { - public: - CTS_Decryption(BlockCipher* cipher) : CBC_Decryption(cipher, nullptr) {} - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t minimum_final_size() const override; - - bool valid_nonce_length(size_t n) const; - }; - -} - -#endif diff --git a/src/modes/cbc/info.txt b/src/modes/cbc/info.txt deleted file mode 100644 index ce59deba0..000000000 --- a/src/modes/cbc/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define MODE_CBC 20131128 - -<requires> -mode_pad -</requires> diff --git a/src/modes/cfb/cfb.cpp b/src/modes/cfb/cfb.cpp deleted file mode 100644 index 7721e1487..000000000 --- a/src/modes/cfb/cfb.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* -* CFB Mode -* (C) 1999-2007,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/cfb.h> -#include <botan/parsing.h> -#include <botan/internal/xor_buf.h> - -namespace Botan { - -CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) : - m_cipher(cipher), - m_feedback_bytes(feedback_bits ? feedback_bits / 8 : cipher->block_size()) - { - if(feedback_bits % 8 || feedback() > cipher->block_size()) - throw std::invalid_argument(name() + ": feedback bits " + - std::to_string(feedback_bits) + " not supported"); - } - -void CFB_Mode::clear() - { - m_cipher->clear(); - m_shift_register.clear(); - } - -std::string CFB_Mode::name() const - { - if(feedback() == cipher().block_size()) - return cipher().name() + "/CFB"; - else - return cipher().name() + "/CFB(" + std::to_string(feedback()*8) + ")"; - } - -size_t CFB_Mode::output_length(size_t input_length) const - { - return input_length; - } - -size_t CFB_Mode::update_granularity() const - { - return feedback(); - } - -size_t CFB_Mode::minimum_final_size() const - { - return 0; - } - -Key_Length_Specification CFB_Mode::key_spec() const - { - return cipher().key_spec(); - } - -size_t CFB_Mode::default_nonce_length() const - { - return cipher().block_size(); - } - -bool CFB_Mode::valid_nonce_length(size_t n) const - { - return (n == cipher().block_size()); - } - -void CFB_Mode::key_schedule(const byte key[], size_t length) - { - m_cipher->set_key(key, length); - } - -secure_vector<byte> CFB_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - m_shift_register.assign(nonce, nonce + nonce_len); - m_keystream_buf.resize(m_shift_register.size()); - cipher().encrypt(m_shift_register, m_keystream_buf); - - return secure_vector<byte>(); - } - -void CFB_Encryption::update(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - const size_t BS = cipher().block_size(); - - secure_vector<byte>& state = shift_register(); - const size_t shift = feedback(); - - while(sz) - { - const size_t took = std::min(shift, sz); - xor_buf(&buf[0], &keystream_buf()[0], took); - - // Assumes feedback-sized block except for last input - copy_mem(&state[0], &state[shift], BS - shift); - copy_mem(&state[BS-shift], &buf[0], shift); - cipher().encrypt(state, keystream_buf()); - - buf += took; - sz -= took; - } - } - -void CFB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - update(buffer, offset); - } - -void CFB_Decryption::update(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - const size_t BS = cipher().block_size(); - - secure_vector<byte>& state = shift_register(); - const size_t shift = feedback(); - - while(sz) - { - const size_t took = std::min(shift, sz); - - // first update shift register with ciphertext - copy_mem(&state[0], &state[shift], BS - shift); - copy_mem(&state[BS-shift], &buf[0], took); - - // then decrypt - xor_buf(&buf[0], &keystream_buf()[0], took); - - // then update keystream - cipher().encrypt(state, keystream_buf()); - - buf += took; - sz -= took; - } - } - -void CFB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - update(buffer, offset); - } - -} diff --git a/src/modes/cfb/cfb.h b/src/modes/cfb/cfb.h deleted file mode 100644 index 48be0a2d9..000000000 --- a/src/modes/cfb/cfb.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -* CFB mode -* (C) 1999-2007,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MODE_CFB_H__ -#define BOTAN_MODE_CFB_H__ - -#include <botan/cipher_mode.h> -#include <botan/block_cipher.h> -#include <botan/mode_pad.h> -#include <memory> - -namespace Botan { - -/** -* CFB Mode -*/ -class BOTAN_DLL CFB_Mode : public Cipher_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - std::string name() const override; - - size_t update_granularity() const override; - - size_t minimum_final_size() const override; - - Key_Length_Specification key_spec() const override; - - size_t output_length(size_t input_length) const override; - - size_t default_nonce_length() const override; - - bool valid_nonce_length(size_t n) const override; - - void clear(); - protected: - CFB_Mode(BlockCipher* cipher, size_t feedback_bits); - - const BlockCipher& cipher() const { return *m_cipher; } - - size_t feedback() const { return m_feedback_bytes; } - - secure_vector<byte>& shift_register() { return m_shift_register; } - - secure_vector<byte>& keystream_buf() { return m_keystream_buf; } - - private: - void key_schedule(const byte key[], size_t length) override; - - std::unique_ptr<BlockCipher> m_cipher; - secure_vector<byte> m_shift_register; - secure_vector<byte> m_keystream_buf; - size_t m_feedback_bytes; - }; - -/** -* CFB Encryption -*/ -class BOTAN_DLL CFB_Encryption : public CFB_Mode - { - public: - CFB_Encryption(BlockCipher* cipher, size_t feedback_bits) : - CFB_Mode(cipher, feedback_bits) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -/** -* CFB Decryption -*/ -class BOTAN_DLL CFB_Decryption : public CFB_Mode - { - public: - CFB_Decryption(BlockCipher* cipher, size_t feedback_bits) : - CFB_Mode(cipher, feedback_bits) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - }; - -} - -#endif diff --git a/src/modes/cfb/info.txt b/src/modes/cfb/info.txt deleted file mode 100644 index 8d0e20a84..000000000 --- a/src/modes/cfb/info.txt +++ /dev/null @@ -1 +0,0 @@ -define MODE_CFB 20131128 diff --git a/src/modes/cipher_mode.h b/src/modes/cipher_mode.h deleted file mode 100644 index 91e2af5a9..000000000 --- a/src/modes/cipher_mode.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -* Cipher Modes -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_CIPHER_MODE_H__ -#define BOTAN_CIPHER_MODE_H__ - -#include <botan/transform.h> - -namespace Botan { - -/** -* Interface for cipher modes -*/ -class BOTAN_DLL Cipher_Mode : public Transformation - { - public: - /** - * Returns true iff this mode provides authentication as well as - * confidentiality. - */ - virtual bool authenticated() const { return false; } - }; - -} - -#endif diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp deleted file mode 100644 index f026eb035..000000000 --- a/src/modes/ecb/ecb.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -* ECB Mode -* (C) 1999-2009,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ecb.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> - -namespace Botan { - -ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - m_cipher(cipher), - m_padding(padding) - { - if(!m_padding->valid_blocksize(cipher->block_size())) - throw std::invalid_argument("Padding " + m_padding->name() + - " cannot be used with " + - cipher->name() + "/ECB"); - } - -void ECB_Mode::clear() - { - m_cipher->clear(); - } - -std::string ECB_Mode::name() const - { - return cipher().name() + "/ECB/" + padding().name(); - } - -size_t ECB_Mode::update_granularity() const - { - return cipher().parallel_bytes(); - } - -Key_Length_Specification ECB_Mode::key_spec() const - { - return cipher().key_spec(); - } - -size_t ECB_Mode::default_nonce_length() const - { - return 0; - } - -bool ECB_Mode::valid_nonce_length(size_t n) const - { - return (n == 0); - } - -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[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - return secure_vector<byte>(); - } - -size_t ECB_Encryption::minimum_final_size() const - { - return 0; - } - -size_t ECB_Encryption::output_length(size_t input_length) const - { - return round_up(input_length, cipher().block_size()); - } - -void ECB_Encryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks"); - const size_t blocks = sz / BS; - - cipher().encrypt_n(&buf[0], &buf[0], blocks); - } - -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; - - const size_t BS = cipher().block_size(); - - const size_t bytes_in_final_block = sz % BS; - - padding().add_padding(buffer, bytes_in_final_block, BS); - - if(buffer.size() % BS) - throw std::runtime_error("Did not pad to full block size in " + name()); - - update(buffer, offset); - } - -size_t ECB_Decryption::output_length(size_t input_length) const - { - return input_length; - } - -size_t ECB_Decryption::minimum_final_size() const - { - return cipher().block_size(); - } - -void ECB_Decryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - cipher().decrypt_n(&buf[0], &buf[0], blocks); - } - -void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - - const size_t BS = cipher().block_size(); - - if(sz == 0 || sz % BS) - throw Decoding_Error(name() + ": Ciphertext not a multiple of block size"); - - update(buffer, offset); - - const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS); - buffer.resize(buffer.size() - pad_bytes); // remove padding - } - -} diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h deleted file mode 100644 index 441eafbc1..000000000 --- a/src/modes/ecb/ecb.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -* ECB Mode -* (C) 1999-2009,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MODE_ECB_H__ -#define BOTAN_MODE_ECB_H__ - -#include <botan/cipher_mode.h> -#include <botan/block_cipher.h> -#include <botan/mode_pad.h> -#include <memory> - -namespace Botan { - -/** -* ECB mode -*/ -class BOTAN_DLL ECB_Mode : public Cipher_Mode - { - public: - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - std::string name() const override; - - size_t update_granularity() const override; - - Key_Length_Specification key_spec() const override; - - size_t default_nonce_length() const override; - - bool valid_nonce_length(size_t n) const override; - - void clear(); - protected: - ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding); - - const BlockCipher& cipher() const { return *m_cipher; } - - const BlockCipherModePaddingMethod& padding() const { return *m_padding; } - - private: - void key_schedule(const byte key[], size_t length) override; - - std::unique_ptr<BlockCipher> m_cipher; - std::unique_ptr<BlockCipherModePaddingMethod> m_padding; - }; - -/** -* ECB Encryption -*/ -class BOTAN_DLL ECB_Encryption : public ECB_Mode - { - public: - ECB_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - ECB_Mode(cipher, padding) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - - size_t minimum_final_size() const override; - }; - -/** -* ECB Decryption -*/ -class BOTAN_DLL ECB_Decryption : public ECB_Mode - { - public: - ECB_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : - ECB_Mode(cipher, padding) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - - size_t minimum_final_size() const override; - }; - -} - -#endif diff --git a/src/modes/ecb/info.txt b/src/modes/ecb/info.txt deleted file mode 100644 index 5e7737717..000000000 --- a/src/modes/ecb/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define MODE_ECB 20131128 - -<requires> -mode_pad -</requires> diff --git a/src/modes/info.txt b/src/modes/info.txt deleted file mode 100644 index 0dcb0cd59..000000000 --- a/src/modes/info.txt +++ /dev/null @@ -1,4 +0,0 @@ - -<requires> -block -</requires> diff --git a/src/modes/mode_pad/info.txt b/src/modes/mode_pad/info.txt deleted file mode 100644 index e9df6334b..000000000 --- a/src/modes/mode_pad/info.txt +++ /dev/null @@ -1 +0,0 @@ -define CIPHER_MODE_PADDING 20131128 diff --git a/src/modes/mode_pad/mode_pad.cpp b/src/modes/mode_pad/mode_pad.cpp deleted file mode 100644 index 918964c74..000000000 --- a/src/modes/mode_pad/mode_pad.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -* 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 deleted file mode 100644 index e7c38a196..000000000 --- a/src/modes/mode_pad/mode_pad.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -* 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 diff --git a/src/modes/xts/info.txt b/src/modes/xts/info.txt deleted file mode 100644 index 5f5dc7834..000000000 --- a/src/modes/xts/info.txt +++ /dev/null @@ -1 +0,0 @@ -define MODE_XTS 20131128 diff --git a/src/modes/xts/xts.cpp b/src/modes/xts/xts.cpp deleted file mode 100644 index 02da5fa5d..000000000 --- a/src/modes/xts/xts.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* -* XTS Mode -* (C) 2009,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/xts.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> - -namespace Botan { - -namespace { - -void poly_double_128(byte out[], const byte in[]) - { - u64bit X0 = load_le<u64bit>(in, 0); - u64bit X1 = load_le<u64bit>(in, 1); - - const bool carry = (X1 >> 63); - - X1 = (X1 << 1) | (X0 >> 63); - X0 = (X0 << 1); - - if(carry) - X0 ^= 0x87; - - store_le(out, X0, X1); - } - -void poly_double_64(byte out[], const byte in[]) - { - u64bit X = load_le<u64bit>(in, 0); - const bool carry = (X >> 63); - X <<= 1; - if(carry) - X ^= 0x1B; - store_le(X, out); - } - -inline void poly_double(byte out[], const byte in[], size_t size) - { - if(size == 8) - poly_double_64(out, in); - else - poly_double_128(out, in); - } - -} - -XTS_Mode::XTS_Mode(BlockCipher* cipher) : m_cipher(cipher) - { - if(m_cipher->block_size() != 8 && m_cipher->block_size() != 16) - throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); - - m_tweak_cipher.reset(m_cipher->clone()); - m_tweak.resize(update_granularity()); - } - -void XTS_Mode::clear() - { - m_cipher->clear(); - m_tweak_cipher->clear(); - zeroise(m_tweak); - } - -std::string XTS_Mode::name() const - { - return cipher().name() + "/XTS"; - } - -size_t XTS_Mode::update_granularity() const - { - return cipher().parallel_bytes(); - } - -size_t XTS_Mode::minimum_final_size() const - { - return cipher().block_size() + 1; - } - -Key_Length_Specification XTS_Mode::key_spec() const - { - return cipher().key_spec().multiple(2); - } - -size_t XTS_Mode::default_nonce_length() const - { - return cipher().block_size(); - } - -bool XTS_Mode::valid_nonce_length(size_t n) const - { - return cipher().block_size() == n; - } - -void XTS_Mode::key_schedule(const byte key[], size_t length) - { - const size_t key_half = length / 2; - - if(length % 2 == 1 || !m_cipher->valid_keylength(key_half)) - throw Invalid_Key_Length(name(), length); - - m_cipher->set_key(&key[0], key_half); - m_tweak_cipher->set_key(&key[key_half], key_half); - } - -secure_vector<byte> XTS_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - copy_mem(&m_tweak[0], nonce, nonce_len); - m_tweak_cipher->encrypt(&m_tweak[0]); - - update_tweak(0); - - return secure_vector<byte>(); - } - -void XTS_Mode::update_tweak(size_t which) - { - const size_t BS = m_tweak_cipher->block_size(); - - if(which > 0) - poly_double(&m_tweak[0], &m_tweak[(which-1)*BS], BS); - - const size_t blocks_in_tweak = update_granularity() / BS; - - for(size_t i = 1; i < blocks_in_tweak; ++i) - poly_double(&m_tweak[i*BS], &m_tweak[(i-1)*BS], BS); - } - -size_t XTS_Encryption::output_length(size_t input_length) const - { - return round_up(input_length, cipher().block_size()); - } - -void XTS_Encryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - const size_t blocks_in_tweak = update_granularity() / BS; - - while(blocks) - { - const size_t to_proc = std::min(blocks, blocks_in_tweak); - const size_t to_proc_bytes = to_proc * BS; - - xor_buf(buf, tweak(), to_proc_bytes); - cipher().encrypt_n(buf, buf, to_proc); - xor_buf(buf, tweak(), to_proc_bytes); - - buf += to_proc * BS; - blocks -= to_proc; - - update_tweak(to_proc); - } - } - -void XTS_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]; - - BOTAN_ASSERT(sz >= minimum_final_size(), "Have sufficient final input"); - - const size_t BS = cipher().block_size(); - - if(sz % BS == 0) - { - update(buffer, offset); - } - else - { - // steal ciphertext - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - xor_buf(last, tweak(), BS); - cipher().encrypt(last); - xor_buf(last, tweak(), BS); - - for(size_t i = 0; i != final_bytes - BS; ++i) - std::swap(last[i], last[i + BS]); - - xor_buf(last, tweak() + BS, BS); - cipher().encrypt(last); - xor_buf(last, tweak() + BS, BS); - - buffer += last; - } - } - -size_t XTS_Decryption::output_length(size_t input_length) const - { - // might be less - return input_length; - } - -void XTS_Decryption::update(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(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - const size_t blocks_in_tweak = update_granularity() / BS; - - while(blocks) - { - const size_t to_proc = std::min(blocks, blocks_in_tweak); - const size_t to_proc_bytes = to_proc * BS; - - xor_buf(buf, tweak(), to_proc_bytes); - cipher().decrypt_n(buf, buf, to_proc); - xor_buf(buf, tweak(), to_proc_bytes); - - buf += to_proc * BS; - blocks -= to_proc; - - update_tweak(to_proc); - } - } - -void XTS_Decryption::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]; - - BOTAN_ASSERT(sz >= minimum_final_size(), "Have sufficient final input"); - - const size_t BS = cipher().block_size(); - - if(sz % BS == 0) - { - update(buffer, offset); - } - else - { - // steal ciphertext - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - xor_buf(last, tweak() + BS, BS); - cipher().decrypt(last); - xor_buf(last, tweak() + BS, BS); - - for(size_t i = 0; i != final_bytes - BS; ++i) - std::swap(last[i], last[i + BS]); - - xor_buf(last, tweak(), BS); - cipher().decrypt(last); - xor_buf(last, tweak(), BS); - - buffer += last; - } - } - -} diff --git a/src/modes/xts/xts.h b/src/modes/xts/xts.h deleted file mode 100644 index 21bc495e1..000000000 --- a/src/modes/xts/xts.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -* XTS mode, from IEEE P1619 -* (C) 2009,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MODE_XTS_H__ -#define BOTAN_MODE_XTS_H__ - -#include <botan/cipher_mode.h> -#include <botan/block_cipher.h> -#include <memory> - -namespace Botan { - -/** -* IEEE P1619 XTS Mode -*/ -class BOTAN_DLL XTS_Mode : public Cipher_Mode - { - public: - std::string name() const override; - - secure_vector<byte> start(const byte nonce[], size_t nonce_len) override; - - size_t update_granularity() const override; - - size_t minimum_final_size() const override; - - Key_Length_Specification key_spec() const override; - - size_t default_nonce_length() const override; - - bool valid_nonce_length(size_t n) const override; - - void clear(); - protected: - XTS_Mode(BlockCipher* cipher); - - const byte* tweak() const { return &m_tweak[0]; } - - const BlockCipher& cipher() const { return *m_cipher; } - - void update_tweak(size_t last_used); - - private: - void key_schedule(const byte key[], size_t length) override; - - std::unique_ptr<BlockCipher> m_cipher, m_tweak_cipher; - secure_vector<byte> m_tweak; - }; - -/** -* IEEE P1619 XTS Encryption -*/ -class BOTAN_DLL XTS_Encryption : public XTS_Mode - { - public: - XTS_Encryption(BlockCipher* cipher) : XTS_Mode(cipher) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - }; - -/** -* IEEE P1619 XTS Decryption -*/ -class BOTAN_DLL XTS_Decryption : public XTS_Mode - { - public: - XTS_Decryption(BlockCipher* cipher) : XTS_Mode(cipher) {} - - void update(secure_vector<byte>& blocks, size_t offset = 0) override; - - void finish(secure_vector<byte>& final_block, size_t offset = 0) override; - - size_t output_length(size_t input_length) const override; - }; - -} - -#endif |