20 #ifndef CS_CRYPTO_DRIVERS_OPENSSL_AES_H
21 #define CS_CRYPTO_DRIVERS_OPENSSL_AES_H
23 #ifdef CSCRYPTO_HAVE_OPENSSL
25 #include <core/cipher/block/aes.h>
26 #include <core/cipher/block/mode.h>
27 #include <core/cipher/sym_secret_key.h>
28 #include <core/cipher/sym_init_vector.h>
29 #include <core/cipher/sym_traits.h>
30 #include <drivers/base/aes.h>
31 #include <util/conversions/byte.h>
32 #include <util/tools/crypto_traits.h>
33 #include <util/tools/span.h>
43 #include <openssl/evp.h>
45 namespace cs_crypto::drivers::openssl {
47 template <
typename Cipher,
typename Mode>
48 struct initialization_fn {
49 static_assert(cs_crypto::traits::always_false<Cipher>{},
"Cipher and Mode combination is not available");
52 template <
typename Cipher,
typename Mode,
bool Encryption =
true>
56 using cipher_type = Cipher;
57 using mode_type = Mode;
59 using key_type = cipher::secret_key<cipher::traits::key_size_v<Cipher>>;
60 using iv_type = cipher::init_vector<cipher::traits::iv_size_v<Mode>>;
62 ~aes_interface() =
default;
64 aes_interface(
const aes_interface &) =
delete;
65 aes_interface(aes_interface &&) =
default;
67 aes_interface &operator=(
const aes_interface &) & =
delete;
68 aes_interface &operator=(aes_interface &&) & =
default;
70 static std::optional<aes_interface> make_context(key_type &&secret_key, iv_type &&iv)
75 context_type context(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
79 if constexpr (Encryption) {
80 result = EVP_EncryptInit_ex(context.get(), initializer(),
nullptr,
81 util::from_byte_ptr(secret_key.data()), util::from_byte_ptr(iv.data()));
84 result = EVP_DecryptInit_ex(context.get(), initializer(),
nullptr,
85 util::from_byte_ptr(secret_key.data()), util::from_byte_ptr(iv.data()));
92 return aes_interface(std::move(context));
95 void update(util::span<std::byte> plaintext_block) &
97 int len = m_ciphertext.size();
98 m_ciphertext.resize(len + plaintext_block.size() + Cipher::block_size);
100 if constexpr (Encryption) {
101 EVP_EncryptUpdate(m_context.get(), util::from_byte_ptr(m_ciphertext.data() + m_last_byte_written),
102 &len, util::from_byte_ptr(plaintext_block.data()), plaintext_block.size());
105 EVP_DecryptUpdate(m_context.get(), util::from_byte_ptr(m_ciphertext.data() + m_last_byte_written),
106 &len, util::from_byte_ptr(plaintext_block.data()), plaintext_block.size());
109 m_last_byte_written += len;
112 std::vector<std::byte> finalize() &&
114 std::vector<std::byte> result;
116 m_ciphertext.resize(m_ciphertext.size() + Cipher::block_size);
118 if constexpr (Encryption) {
119 EVP_EncryptFinal_ex(m_context.get(),
120 util::from_byte_ptr(m_ciphertext.data()) + m_last_byte_written, &len);
122 EVP_DecryptFinal_ex(m_context.get(),
123 util::from_byte_ptr(m_ciphertext.data()) + m_last_byte_written, &len);
126 result.resize(m_last_byte_written + len);
127 std::copy_n(m_ciphertext.begin(), m_last_byte_written + len, result.begin());
132 using context_type = std::unique_ptr<EVP_CIPHER_CTX,
decltype(&::EVP_CIPHER_CTX_free)>;
133 context_type m_context;
135 std::vector<std::byte> m_ciphertext = {};
136 std::size_t m_last_byte_written = 0;
138 constexpr static const auto initializer = initialization_fn<Cipher, Mode>::init_function;
140 aes_interface(context_type &&context)
141 : m_context(std::move(context))
147 struct initialization_fn<block_cipher::aes128, block_cipher::mode::CBC> {
148 constexpr static const auto init_function = EVP_aes_128_cbc;
152 struct initialization_fn<block_cipher::aes192, block_cipher::mode::CBC> {
153 constexpr static const auto init_function = EVP_aes_192_cbc;
157 struct initialization_fn<block_cipher::aes256, block_cipher::mode::CBC> {
158 constexpr static const auto init_function = EVP_aes_256_cbc;
161 struct cipher_mode :
public basic_cipher_mode {
162 template <
typename Cipher,
typename Mode>
163 using encrypt = aes_interface<Cipher, Mode,
true>;
165 template <
typename Cipher,
typename Mode>
166 using decrypt = aes_interface<Cipher, Mode,
false>;