20 #ifndef CS_CRYPTO_DRIVERS_BOTAN_AES_H
21 #define CS_CRYPTO_DRIVERS_BOTAN_AES_H
23 #ifdef CSCRYPTO_HAVE_BOTAN
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>
38 #include <botan/aes.h>
39 #include <botan/cipher_mode.h>
40 #include <botan/cbc.h>
41 #include <botan/cfb.h>
43 namespace cs_crypto::drivers::botan {
45 template <
typename Botan_T>
46 class aes_interface :
public Botan_T
49 using cipher_type =
typename Botan_T::cipher_type;
50 using mode_type =
typename Botan_T::mode_type;
52 using key_type =
typename Botan_T::key_type;
53 using iv_type =
typename Botan_T::iv_type;
55 aes_interface(
const aes_interface &) =
delete;
57 ~aes_interface() =
default;
59 aes_interface &operator=(
const aes_interface &) & =
delete;
61 aes_interface(aes_interface&&) =
default;
62 aes_interface &operator=(aes_interface&&) & =
default;
64 static std::optional<aes_interface> make_context(key_type &&secret_key, iv_type &&iv)
66 auto context = Botan_T::make_context();
68 if (context ==
nullptr) {
75 context->set_key(util::from_byte_ptr(secret_key.data()), secret_key.size());
76 context->start(util::from_byte_ptr(iv.data()), iv.size());
78 return aes_interface(std::move(context));
81 void update(cs_crypto::util::span<std::byte> plaintext_block) &
83 cs_crypto::util::span<uint8_t> uint_view = {util::from_byte_ptr(plaintext_block.data()), plaintext_block.size()};
84 m_plaintext.insert(m_plaintext.end(), uint_view.begin(), uint_view.end());
87 std::vector<std::byte> finalize() &&
89 std::vector<std::byte> result;
90 m_context->finish(m_plaintext);
92 result.resize(m_plaintext.size());
93 cs_crypto::util::span<std::byte> byte_view = {util::to_byte_ptr(m_plaintext.data()), m_plaintext.size()};
94 std::copy(byte_view.begin(), byte_view.end(), result.begin());
100 Botan::secure_vector<uint8_t> m_plaintext;
101 std::unique_ptr<
typename Botan_T::botan_context> m_context;
103 explicit aes_interface(std::unique_ptr<
typename Botan_T::botan_context> &&context)
104 : m_plaintext(), m_context(std::move(context))
109 template <
typename Cipher,
typename Mode,
bool Encryption>
110 struct aes_internal {
111 static_assert(cs_crypto::traits::always_false<Cipher>{},
"Cipher and Mode combination is not available");
114 template <
typename Cipher,
bool Encryption>
115 struct aes_internal<Cipher, block_cipher::mode::CBC, Encryption> {
116 using cipher_type = Cipher;
117 using mode_type = block_cipher::mode::CBC;
119 using key_type = cipher::secret_key<cipher::traits::key_size_v<cipher_type>>;
120 using iv_type = cipher::init_vector<cipher::traits::iv_size_v<mode_type>>;
122 using botan_context = std::conditional_t<Encryption, Botan::CBC_Encryption, Botan::CBC_Decryption>;
124 ~aes_internal() =
default;
126 static std::unique_ptr<botan_context> make_context()
noexcept
128 std::unique_ptr<botan_context> context;
130 if constexpr (std::is_same_v<Cipher, block_cipher::aes128>) {
131 return std::make_unique<botan_context>(
new Botan::AES_128,
new Botan::PKCS7_Padding);
133 }
else if constexpr (std::is_same_v<Cipher, block_cipher::aes192>) {
134 return std::make_unique<botan_context>(
new Botan::AES_192,
new Botan::PKCS7_Padding);
136 }
else if constexpr (std::is_same_v<Cipher, block_cipher::aes256>) {
137 return std::make_unique<botan_context>(
new Botan::AES_256,
new Botan::PKCS7_Padding);
144 struct cipher_mode :
public basic_cipher_mode {
145 template <
typename Cipher,
typename Mode>
146 using encrypt = aes_interface<aes_internal<Cipher, Mode,
true>>;
148 template <
typename Cipher,
typename Mode>
149 using decrypt = aes_interface<aes_internal<Cipher, Mode,
false>>;