aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/prov/commoncrypto/commoncrypto_block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/prov/commoncrypto/commoncrypto_block.cpp')
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto_block.cpp152
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;
+ }
+ }
+}
+