CsCrypto  1.0.1
sym_process_msg.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_PROCESS_MSG_H
21 #define CS_CRYPTO_SYM_PROCESS_MSG_H
22 
23 #include <util/conversions/byte.h>
24 #include <util/tools/crypto_traits.h>
25 #include <util/tools/is_detected_traits.h>
26 #include <util/tools/span.h>
27 
28 #include <utility>
29 #include <cstddef>
30 #include <type_traits>
31 #include <vector>
32 
33 namespace cs_crypto::cipher {
34 
35 template <typename T>
36 using update_member_fn = decltype(std::declval<T &>().update(std::declval<cs_crypto::util::span<std::byte>>()));
37 
38 template <typename T>
39 using update_free_fn = decltype(update(std::declval<T &>(), std::declval<cs_crypto::util::span<std::byte>>()));
40 
41 struct update_dispatch_internal
42 {
43  template <typename CipherContext> constexpr auto operator()(CipherContext &ctx, cs_crypto::util::span<std::byte> bytes) const
44  {
45  if constexpr (cs_crypto::traits::is_detected_v<update_member_fn, CipherContext>) {
46  return ctx.update(bytes);
47 
48  } else if constexpr (cs_crypto::traits::is_detected_v<update_free_fn, CipherContext>) {
49  return update(ctx, bytes);
50 
51  } else {
52  static_assert(cs_crypto::traits::always_false<CipherContext>{},
53  "Driver incomplete, unable to locate update() as a method or free function");
54  }
55  }
56 };
57 
58 inline constexpr update_dispatch_internal dispatch_update{};
59 
60 template <typename CipherContext, typename T,
61  typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
62 constexpr auto internal_cipher_append(CipherContext &ctx, const T v)
63 {
64  return dispatch_update(ctx, {util::to_byte_ptr(std::addressof(v)), 1});
65 }
66 
67 template <typename CipherContext, typename T, std::size_t N,
68  typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
69 constexpr auto internal_cipher_append(CipherContext &ctx, const T (&arr)[N])
70 {
71  return dispatch_update(ctx, {util::to_byte_ptr(std::addressof(arr[0])), N});
72 }
73 
74 template <typename CipherContext, typename T, std::size_t N,
75  typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
76 constexpr auto internal_cipher_append(CipherContext &ctx, const std::array<T, N> &data)
77 {
78  return dispatch_update(ctx, {util::to_byte_ptr(data.data()), data.size()});
79 }
80 
81 template <typename CipherContext, typename T,
82  typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
83 constexpr auto internal_cipher_append(CipherContext &ctx, const std::vector<T> &data)
84 {
85  return dispatch_update(ctx, {util::to_byte_ptr(data.data()), data.size()});
86 }
87 
88 template <typename CipherContext>
89 constexpr auto internal_cipher_append(CipherContext &ctx, const std::string &s)
90 {
91  return dispatch_update(ctx, {util::to_byte_ptr(s.data()), s.size()});
92 }
93 
94 template <typename CipherContext, typename T, typename = std::enable_if_t<cs_crypto::traits::is_iterable_v<T>>>
95 constexpr auto internal_cipher_append(CipherContext &ctx, const T &data)
96 {
97  // error handling left unimplemented until user experience is reported
98 
99  for (const auto elem : data) {
100  internal_cipher_append(ctx, elem);
101  }
102 }
103 
104 template <typename CipherContext, typename It, typename End>
105 constexpr auto internal_cipher_append(CipherContext &ctx, It iter, End end)
106 {
107  // error handling left unimplemented until user experience is reported
108 
109  while (iter != end) {
110  internal_cipher_append(ctx, *iter);
111  iter = std::next(iter);
112  }
113 }
114 
115 template <typename Ctx>
116 [[maybe_unused]] inline constexpr bool is_appendable_cipher_context_v =
117  std::is_move_assignable_v<Ctx> && std::is_move_constructible_v<Ctx> &&
118  (cs_crypto::traits::is_detected_v<update_free_fn, Ctx> || cs_crypto::traits::is_detected_v<update_member_fn, Ctx>);
119 
120 struct cipher_append_internal
121 {
122  template <typename CipherContext, typename... Ts>
123  constexpr auto operator()(CipherContext &&context, Ts &&... args) const
124  {
125  static_assert(! std::is_same_v<CipherContext, cs_crypto::traits::nonesuch>,
126  "Driver does not support this operation");
127 
128  static_assert(is_appendable_cipher_context_v<std::remove_reference_t<CipherContext>>,
129  "Cipher context does not satisfy is_appendable_cipher_context type trait");
130 
131  return internal_cipher_append(std::forward<CipherContext>(context), std::forward<Ts>(args)...);
132  }
133 };
134 
135 inline constexpr const cipher_append_internal cipher_append = {};
136 
137 } // namespace cs_crypto::cipher
138 
139 #endif