Botan  1.11.15
src/lib/vendor/openssl/openssl_block.cpp
Go to the documentation of this file.
00001 /*
00002 * OpenSSL Block Cipher
00003 * (C) 1999-2010,2015 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/block_utils.h>
00009 #include <openssl/evp.h>
00010 
00011 namespace Botan {
00012 
00013 namespace {
00014 
00015 class OpenSSL_BlockCipher : public BlockCipher
00016    {
00017    public:
00018       void clear();
00019       std::string name() const { return cipher_name; }
00020       BlockCipher* clone() const;
00021 
00022       size_t block_size() const { return block_sz; }
00023 
00024       OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&);
00025 
00026       OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&,
00027                       size_t, size_t, size_t);
00028 
00029       Key_Length_Specification key_spec() const { return cipher_key_spec; }
00030 
00031       ~OpenSSL_BlockCipher();
00032    private:
00033       void encrypt_n(const byte in[], byte out[], size_t blocks) const
00034          {
00035          int out_len = 0;
00036          EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz);
00037          }
00038 
00039       void decrypt_n(const byte in[], byte out[], size_t blocks) const
00040          {
00041          int out_len = 0;
00042          EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz);
00043          }
00044 
00045       void key_schedule(const byte[], size_t);
00046 
00047       size_t block_sz;
00048       Key_Length_Specification cipher_key_spec;
00049       std::string cipher_name;
00050       mutable EVP_CIPHER_CTX encrypt, decrypt;
00051    };
00052 
00053 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo,
00054                                          const std::string& algo_name) :
00055    block_sz(EVP_CIPHER_block_size(algo)),
00056    cipher_key_spec(EVP_CIPHER_key_length(algo)),
00057    cipher_name(algo_name)
00058    {
00059    if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
00060       throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
00061 
00062    EVP_CIPHER_CTX_init(&encrypt);
00063    EVP_CIPHER_CTX_init(&decrypt);
00064 
00065    EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr);
00066    EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr);
00067 
00068    EVP_CIPHER_CTX_set_padding(&encrypt, 0);
00069    EVP_CIPHER_CTX_set_padding(&decrypt, 0);
00070    }
00071 
00072 OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo,
00073                                  const std::string& algo_name,
00074                                  size_t key_min, size_t key_max,
00075                                  size_t key_mod) :
00076    block_sz(EVP_CIPHER_block_size(algo)),
00077    cipher_key_spec(key_min, key_max, key_mod),
00078    cipher_name(algo_name)
00079    {
00080    if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
00081       throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in");
00082 
00083    EVP_CIPHER_CTX_init(&encrypt);
00084    EVP_CIPHER_CTX_init(&decrypt);
00085 
00086    EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr);
00087    EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr);
00088 
00089    EVP_CIPHER_CTX_set_padding(&encrypt, 0);
00090    EVP_CIPHER_CTX_set_padding(&decrypt, 0);
00091    }
00092 
00093 OpenSSL_BlockCipher::~OpenSSL_BlockCipher()
00094    {
00095    EVP_CIPHER_CTX_cleanup(&encrypt);
00096    EVP_CIPHER_CTX_cleanup(&decrypt);
00097    }
00098 
00099 /*
00100 * Set the key
00101 */
00102 void OpenSSL_BlockCipher::key_schedule(const byte key[], size_t length)
00103    {
00104    secure_vector<byte> full_key(key, key + length);
00105 
00106    if(cipher_name == "TripleDES" && length == 16)
00107       {
00108       full_key += std::make_pair(key, 8);
00109       }
00110    else
00111       if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
00112          EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
00113          throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " +
00114                                 cipher_name);
00115 
00116    EVP_EncryptInit_ex(&encrypt, nullptr, nullptr, &full_key[0], nullptr);
00117    EVP_DecryptInit_ex(&decrypt, nullptr, nullptr, &full_key[0], nullptr);
00118    }
00119 
00120 /*
00121 * Return a clone of this object
00122 */
00123 BlockCipher* OpenSSL_BlockCipher::clone() const
00124    {
00125    return new OpenSSL_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
00126                               cipher_name,
00127                               cipher_key_spec.minimum_keylength(),
00128                               cipher_key_spec.maximum_keylength(),
00129                               cipher_key_spec.keylength_multiple());
00130    }
00131 
00132 /*
00133 * Clear memory of sensitive data
00134 */
00135 void OpenSSL_BlockCipher::clear()
00136    {
00137    const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
00138 
00139    EVP_CIPHER_CTX_cleanup(&encrypt);
00140    EVP_CIPHER_CTX_cleanup(&decrypt);
00141    EVP_CIPHER_CTX_init(&encrypt);
00142    EVP_CIPHER_CTX_init(&decrypt);
00143    EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr);
00144    EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr);
00145    EVP_CIPHER_CTX_set_padding(&encrypt, 0);
00146    EVP_CIPHER_CTX_set_padding(&decrypt, 0);
00147    }
00148 
00149 std::function<BlockCipher* (const BlockCipher::Spec&)>
00150 make_evp_block_maker(const EVP_CIPHER* cipher, const char* algo)
00151    {
00152    return [cipher,algo](const BlockCipher::Spec&)
00153       {
00154       return new OpenSSL_BlockCipher(cipher, algo);
00155       };
00156    }
00157 
00158 std::function<BlockCipher* (const BlockCipher::Spec&)>
00159 make_evp_block_maker_keylen(const EVP_CIPHER* cipher, const char* algo,
00160                             size_t kmin, size_t kmax, size_t kmod)
00161    {
00162    return [cipher,algo,kmin,kmax,kmod](const BlockCipher::Spec&)
00163       {
00164       return new OpenSSL_BlockCipher(cipher, algo, kmin, kmax, kmod);
00165       };
00166    }
00167 
00168 #define BOTAN_REGISTER_OPENSSL_EVP_BLOCK(NAME, EVP)                            \
00169    BOTAN_REGISTER_TYPE(BlockCipher, EVP_BlockCipher ## EVP, NAME,              \
00170                        make_evp_block_maker(EVP(), NAME), "openssl", 96);
00171 
00172 #define BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN(NAME, EVP, KMIN, KMAX, KMOD)       \
00173    BOTAN_REGISTER_TYPE(BlockCipher, OpenSSL_BlockCipher ## EVP, NAME,              \
00174                        make_evp_block_maker_keylen(EVP(), NAME, KMIN, KMAX, KMOD), \
00175                        "openssl", 96);
00176 
00177 #if !defined(OPENSSL_NO_AES)
00178    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-128", EVP_aes_128_ecb);
00179    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-192", EVP_aes_192_ecb);
00180    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-256", EVP_aes_256_ecb);
00181 #endif
00182 
00183 #if !defined(OPENSSL_NO_DES)
00184    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("DES", EVP_des_ecb);
00185    BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("TripleDES", EVP_des_ede3_ecb, 16, 24, 8);
00186 #endif
00187 
00188 #if !defined(OPENSSL_NO_BF)
00189    BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("Blowfish", EVP_bf_ecb, 1, 56, 1);
00190 #endif
00191 
00192 #if !defined(OPENSSL_NO_CAST)
00193    BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("CAST-128", EVP_cast5_ecb, 1, 16, 1);
00194 #endif
00195 
00196 #if !defined(OPENSSL_NO_CAMELLIA)
00197    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-128", EVP_camellia_128_ecb);
00198    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-192", EVP_camellia_192_ecb);
00199    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-256", EVP_camellia_256_ecb);
00200 #endif
00201 
00202 #if !defined(OPENSSL_NO_IDEA)
00203    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("IDEA", EVP_idea_ecb);
00204 #endif
00205 
00206 #if !defined(OPENSSL_NO_SEED)
00207    BOTAN_REGISTER_OPENSSL_EVP_BLOCK("SEED", EVP_seed_ecb);
00208 #endif
00209 
00210 }
00211 
00212 }