CsCrypto  1.0.1
sym_encrypt_decrypt.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2021-2024 Tim van Deurzen
4 * Copyright (c) 2021-2024 Barbara Geller
5 * Copyright (c) 2021-2024 Ansel Sermersheim
6 *
7 * This file is part of CsCrypto.
8 *
9 * CsCrypto is free software, released under the BSD 2-Clause license.
10 * For license details refer to LICENSE provided with this project.
11 *
12 * CsCrypto is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * https://opensource.org/licenses/BSD-2-Clause
17 *
18 ***********************************************************************/
19 
20 #ifndef CS_CRYPTO_SYM_ENCRYPT_DECRYPT_H
21 #define CS_CRYPTO_SYM_ENCRYPT_DECRYPT_H
22 
23 #include <core/cipher/sym_process_msg.h>
24 #include <core/cipher/sym_secret_key.h>
25 #include <core/cipher/sym_init_vector.h>
26 #include <core/cipher/sym_traits.h>
27 #include <util/tools/crypto_traits.h>
28 #include <util/tools/is_detected_traits.h>
29 
30 #include <type_traits>
31 
32 namespace cs_crypto::cipher {
33 
34 template <typename T>
35 using finalize_member_fn = decltype(std::declval<T &&>().finalize());
36 
37 template <typename T>
38 using finalize_free_fn = decltype(finalize(std::declval<T &&>()));
39 
40 struct finalize_dispatch_internal {
41  template <typename CipherContext>
42  constexpr auto operator()(CipherContext &&ctx) const
43  {
44  if constexpr (cs_crypto::traits::is_detected<finalize_member_fn, CipherContext>{}) {
45  return std::move(ctx).finalize();
46 
47  } else if constexpr (cs_crypto::traits::is_detected<finalize_free_fn, CipherContext>{}) {
48  return finalize(std::move(ctx));
49 
50  } else {
51  static_assert(cs_crypto::traits::always_false<CipherContext>{},
52  "Driver incomplete, unable to locate finalize() as a method or free function");
53  }
54  }
55 };
56 
57 inline constexpr finalize_dispatch_internal finalize{};
58 
59 template <typename Ctx>
60 [[maybe_unused]] constexpr static bool is_cipher_context_v = is_appendable_cipher_context_v<Ctx> &&
61  (cs_crypto::traits::is_detected_v<finalize_free_fn, Ctx> || cs_crypto::traits::is_detected_v<finalize_member_fn, Ctx>);
62 
63 template <typename CipherContext>
64 struct encrypt_operation {
65  using key_type = typename CipherContext::key_type;
66  using iv_type = typename CipherContext::iv_type;
67 
68  using result_type = std::optional<cs_crypto::traits::remove_optional_t<decltype(finalize(std::declval<CipherContext>()))>>;
69 
70  template <typename... Ts>
71  constexpr auto operator()(key_type &&secret_key, iv_type &&iv, Ts &&... args) const -> result_type
72  {
73  static_assert(! std::is_same_v<CipherContext, cs_crypto::traits::nonesuch>,
74  "Selected driver does not support this operation");
75 
76  static_assert(is_cipher_context_v<CipherContext>,
77  "Cipher context does not satisfy is_cipher_context_v type trait");
78 
79  auto maybe_context = CipherContext::make_context(std::move(secret_key), std::move(iv));
80  if (! maybe_context.has_value()) {
81  return std::nullopt;
82  }
83 
84  auto context = std::move(maybe_context).value();
85  cipher_append(context, std::forward<Ts>(args)...);
86 
87  return finalize(std::move(context));
88  }
89 };
90 
91 template <typename CipherDriver, typename Cipher, typename Mode>
92 inline constexpr encrypt_operation<typename CipherDriver::template encrypt<Cipher, Mode>> encrypt;
93 
94 template <typename CipherDriver, typename Cipher, typename Mode>
95 inline constexpr encrypt_operation<typename CipherDriver::template decrypt<Cipher, Mode>> decrypt;
96 
97 } // namespace cs_crypto::cipher
98 
99 #endif