diff options
Diffstat (limited to 'src/modes/aead')
-rw-r--r-- | src/modes/aead/aead.cpp | 121 | ||||
-rw-r--r-- | src/modes/aead/aead.h | 66 | ||||
-rw-r--r-- | src/modes/aead/ccm/ccm.cpp | 266 | ||||
-rw-r--r-- | src/modes/aead/ccm/ccm.h | 128 | ||||
-rw-r--r-- | src/modes/aead/ccm/info.txt | 1 | ||||
-rw-r--r-- | src/modes/aead/eax/eax.cpp | 170 | ||||
-rw-r--r-- | src/modes/aead/eax/eax.h | 114 | ||||
-rw-r--r-- | src/modes/aead/eax/info.txt | 7 | ||||
-rw-r--r-- | src/modes/aead/gcm/clmul/clmul.cpp | 76 | ||||
-rw-r--r-- | src/modes/aead/gcm/clmul/clmul.h | 14 | ||||
-rw-r--r-- | src/modes/aead/gcm/clmul/info.txt | 8 | ||||
-rw-r--r-- | src/modes/aead/gcm/gcm.cpp | 290 | ||||
-rw-r--r-- | src/modes/aead/gcm/gcm.h | 150 | ||||
-rw-r--r-- | src/modes/aead/gcm/info.txt | 6 | ||||
-rw-r--r-- | src/modes/aead/info.txt | 1 | ||||
-rw-r--r-- | src/modes/aead/ocb/info.txt | 6 | ||||
-rw-r--r-- | src/modes/aead/ocb/ocb.cpp | 432 | ||||
-rw-r--r-- | src/modes/aead/ocb/ocb.h | 124 | ||||
-rw-r--r-- | src/modes/aead/siv/info.txt | 3 | ||||
-rw-r--r-- | src/modes/aead/siv/siv.cpp | 180 | ||||
-rw-r--r-- | src/modes/aead/siv/siv.h | 114 |
21 files changed, 0 insertions, 2277 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 |