diff options
Diffstat (limited to 'src/lib/prov/commoncrypto/commoncrypto_block.cpp')
-rw-r--r-- | src/lib/prov/commoncrypto/commoncrypto_block.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/lib/prov/commoncrypto/commoncrypto_block.cpp b/src/lib/prov/commoncrypto/commoncrypto_block.cpp new file mode 100644 index 000000000..e912ed57e --- /dev/null +++ b/src/lib/prov/commoncrypto/commoncrypto_block.cpp @@ -0,0 +1,152 @@ +/* +* Block Ciphers via CommonCrypto +* (C) 2018 Jose Luis Pereira +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/hex.h> + +#include <botan/block_cipher.h> +#include <botan/internal/commoncrypto.h> +#include <CommonCrypto/CommonCrypto.h> + +#include "commoncrypto_utils.h" + +namespace Botan { + +namespace { + +class CommonCrypto_BlockCipher final : public BlockCipher + { + public: + CommonCrypto_BlockCipher(const std::string& name, const CommonCryptor_Opts& opts); + + ~CommonCrypto_BlockCipher(); + + void clear() override; + std::string provider() const override { return "commoncrypto"; } + std::string name() const override { return m_cipher_name; } + BlockCipher* clone() const override; + + size_t block_size() const override { return m_opts.block_size; } + + Key_Length_Specification key_spec() const override { return m_opts.key_spec; } + + void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override + { + verify_key_set(m_key_set); + size_t total_len = blocks * m_opts.block_size; + size_t out_len = 0; + + CCCryptorStatus status = CCCryptorUpdate(m_encrypt, in, total_len, + out, total_len, &out_len); + if(status != kCCSuccess) + { + throw CommonCrypto_Error("CCCryptorUpdate encrypt", status); + } + } + + void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override + { + verify_key_set(m_key_set); + size_t total_len = blocks * m_opts.block_size; + size_t out_len = 0; + + CCCryptorStatus status = CCCryptorUpdate(m_decrypt, in, total_len, + out, total_len, &out_len); + if(status != kCCSuccess) + { + throw CommonCrypto_Error("CCCryptorUpdate decrypt", status); + } + } + + void key_schedule(const uint8_t key[], size_t key_len) override; + + std::string m_cipher_name; + CommonCryptor_Opts m_opts; + + CCCryptorRef m_encrypt = nullptr; + CCCryptorRef m_decrypt = nullptr; + bool m_key_set; + }; + +CommonCrypto_BlockCipher::CommonCrypto_BlockCipher(const std::string& algo_name, + const CommonCryptor_Opts& opts) : + m_cipher_name(algo_name), + m_opts(opts), + m_key_set(false) + { + } + +CommonCrypto_BlockCipher::~CommonCrypto_BlockCipher() + { + if(m_encrypt) + { + CCCryptorRelease(m_encrypt); + } + if(m_decrypt) + { + CCCryptorRelease(m_decrypt); + } + } + +/* +* Set the key +*/ +void CommonCrypto_BlockCipher::key_schedule(const uint8_t key[], size_t length) + { + secure_vector<uint8_t> full_key(key, key + length); + + commoncrypto_adjust_key_size(key, length, m_opts, full_key); + + CCCryptorStatus status; + status = CCCryptorCreate(kCCEncrypt, m_opts.algo, kCCOptionECBMode, + full_key.data(), full_key.size(), nullptr, &m_encrypt); + if(status != kCCSuccess) + { + throw CommonCrypto_Error("CCCryptorCreate encrypt", status); + } + status = CCCryptorCreate(kCCDecrypt, m_opts.algo, kCCOptionECBMode, + full_key.data(), full_key.size(), nullptr, &m_decrypt); + if(status != kCCSuccess) + { + throw CommonCrypto_Error("CCCryptorCreate decrypt", status); + } + + m_key_set = true; + } + +/* +* Return a clone of this object +*/ +BlockCipher* CommonCrypto_BlockCipher::clone() const + { + return new CommonCrypto_BlockCipher(m_cipher_name, m_opts); + } + +/* +* Clear memory of sensitive data +*/ +void CommonCrypto_BlockCipher::clear() + { + m_key_set = false; + } +} + +std::unique_ptr<BlockCipher> +make_commoncrypto_block_cipher(const std::string& name) + { + + try + { + CommonCryptor_Opts opts = commoncrypto_opts_from_algo(name); + return std::unique_ptr<BlockCipher>(new CommonCrypto_BlockCipher(name, opts)); + } + catch(CommonCrypto_Error e) + { + return nullptr; + } + } +} + |