Coverage Report

Created: 2024-11-21 07:00

/src/botan/build/include/public/botan/mem_ops.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Memory Operations
3
* (C) 1999-2009,2012,2015 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#ifndef BOTAN_MEMORY_OPS_H_
9
#define BOTAN_MEMORY_OPS_H_
10
11
#include <botan/concepts.h>
12
#include <botan/types.h>
13
#include <array>
14
#include <cstring>
15
#include <ranges>
16
#include <span>
17
#include <type_traits>
18
#include <vector>
19
20
/*
21
The header mem_ops.h previously included the contents of allocator.h
22
23
Library code should always include allocator.h to see these
24
declarations; however when we are not building the library continue to
25
include the header here to avoid breaking application code.
26
*/
27
#if !defined(BOTAN_IS_BEING_BUILT)
28
   #include <botan/allocator.h>
29
#endif
30
31
namespace Botan {
32
33
/**
34
* Scrub memory contents in a way that a compiler should not elide,
35
* using some system specific technique. Note that this function might
36
* not zero the memory (for example, in some hypothetical
37
* implementation it might combine the memory contents with the output
38
* of a system PRNG), but if you can detect any difference in behavior
39
* at runtime then the clearing is side-effecting and you can just
40
* use `clear_mem`.
41
*
42
* Use this function to scrub memory just before deallocating it, or on
43
* a stack buffer before returning from the function.
44
*
45
* @param ptr a pointer to memory to scrub
46
* @param n the number of bytes pointed to by ptr
47
*/
48
BOTAN_PUBLIC_API(2, 0) void secure_scrub_memory(void* ptr, size_t n);
49
50
/**
51
* Scrub memory contents in a way that a compiler should not elide,
52
* using some system specific technique. Note that this function might
53
* not zero the memory.
54
*
55
* @param data  the data region to be scrubbed
56
*/
57
void secure_scrub_memory(ranges::contiguous_output_range auto&& data) {
58
   secure_scrub_memory(std::ranges::data(data), ranges::size_bytes(data));
59
}
60
61
#if !defined(BOTAN_IS_BEGIN_BUILT)
62
63
/**
64
* Memory comparison, input insensitive
65
* @param x a pointer to an array
66
* @param y a pointer to another array
67
* @param len the number of Ts in x and y
68
* @return 0xFF iff x[i] == y[i] forall i in [0...n) or 0x00 otherwise
69
*/
70
BOTAN_DEPRECATED("This function is deprecated, use constant_time_compare()")
71
BOTAN_PUBLIC_API(2, 9) uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len);
72
73
#endif
74
75
/**
76
 * Memory comparison, input insensitive
77
 * @param x a range of bytes
78
 * @param y another range of bytes
79
 * @return true iff x and y have equal lengths and x[i] == y[i] forall i in [0...n)
80
 */
81
BOTAN_PUBLIC_API(3, 3) bool constant_time_compare(std::span<const uint8_t> x, std::span<const uint8_t> y);
82
83
/**
84
* Memory comparison, input insensitive
85
* @param x a pointer to an array
86
* @param y a pointer to another array
87
* @param len the number of Ts in x and y
88
* @return true iff x[i] == y[i] forall i in [0...n)
89
*/
90
0
inline bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len) {
91
0
   // simply assumes that *x and *y point to len allocated bytes at least
92
0
   return constant_time_compare({x, len}, {y, len});
93
0
}
94
95
/**
96
* Zero out some bytes. Warning: use secure_scrub_memory instead if the
97
* memory is about to be freed or otherwise the compiler thinks it can
98
* elide the writes.
99
*
100
* @param ptr a pointer to memory to zero
101
* @param bytes the number of bytes to zero in ptr
102
*/
103
152M
inline constexpr void clear_bytes(void* ptr, size_t bytes) {
104
152M
   if(bytes > 0) {
105
144M
      std::memset(ptr, 0, bytes);
106
144M
   }
107
152M
}
108
109
/**
110
* Zero memory before use. This simply calls memset and should not be
111
* used in cases where the compiler cannot see the call as a
112
* side-effecting operation (for example, if calling clear_mem before
113
* deallocating memory, the compiler would be allowed to omit the call
114
* to memset entirely under the as-if rule.)
115
*
116
* @param ptr a pointer to an array of Ts to zero
117
* @param n the number of Ts pointed to by ptr
118
*/
119
template <typename T>
120
152M
inline constexpr void clear_mem(T* ptr, size_t n) {
121
152M
   clear_bytes(ptr, sizeof(T) * n);
122
152M
}
void Botan::clear_mem<unsigned long>(unsigned long*, unsigned long)
Line
Count
Source
120
143M
inline constexpr void clear_mem(T* ptr, size_t n) {
121
143M
   clear_bytes(ptr, sizeof(T) * n);
122
143M
}
void Botan::clear_mem<unsigned char>(unsigned char*, unsigned long)
Line
Count
Source
120
7.18M
inline constexpr void clear_mem(T* ptr, size_t n) {
121
7.18M
   clear_bytes(ptr, sizeof(T) * n);
122
7.18M
}
void Botan::clear_mem<int>(int*, unsigned long)
Line
Count
Source
120
1.60M
inline constexpr void clear_mem(T* ptr, size_t n) {
121
1.60M
   clear_bytes(ptr, sizeof(T) * n);
122
1.60M
}
void Botan::clear_mem<unsigned int>(unsigned int*, unsigned long)
Line
Count
Source
120
12
inline constexpr void clear_mem(T* ptr, size_t n) {
121
12
   clear_bytes(ptr, sizeof(T) * n);
122
12
}
123
124
/**
125
* Zero memory before use. This simply calls memset and should not be
126
* used in cases where the compiler cannot see the call as a
127
* side-effecting operation.
128
*
129
* @param mem a contiguous range of Ts to zero
130
*/
131
template <ranges::contiguous_output_range R>
132
inline constexpr void clear_mem(R&& mem)
133
   requires std::is_trivially_copyable_v<std::ranges::range_value_t<R>>
134
0
{
135
0
   clear_bytes(std::ranges::data(mem), ranges::size_bytes(mem));
136
0
}
137
138
/**
139
* Copy memory
140
* @param out the destination array
141
* @param in the source array
142
* @param n the number of elements of in/out
143
*/
144
template <typename T>
145
   requires std::is_trivial<typename std::decay<T>::type>::value
146
42.8M
inline constexpr void copy_mem(T* out, const T* in, size_t n) {
147
42.8M
   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
148
149
42.8M
   if(in != nullptr && out != nullptr && n > 0) {
150
42.8M
      std::memmove(out, in, sizeof(T) * n);
151
42.8M
   }
152
42.8M
}
void Botan::copy_mem<unsigned char>(unsigned char*, unsigned char const*, unsigned long)
Line
Count
Source
146
2.02M
inline constexpr void copy_mem(T* out, const T* in, size_t n) {
147
2.02M
   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
148
149
2.02M
   if(in != nullptr && out != nullptr && n > 0) {
150
1.99M
      std::memmove(out, in, sizeof(T) * n);
151
1.99M
   }
152
2.02M
}
void Botan::copy_mem<unsigned long>(unsigned long*, unsigned long const*, unsigned long)
Line
Count
Source
146
40.8M
inline constexpr void copy_mem(T* out, const T* in, size_t n) {
147
40.8M
   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
148
149
40.8M
   if(in != nullptr && out != nullptr && n > 0) {
150
40.8M
      std::memmove(out, in, sizeof(T) * n);
151
40.8M
   }
152
40.8M
}
void Botan::copy_mem<int>(int*, int const*, unsigned long)
Line
Count
Source
146
3.12k
inline constexpr void copy_mem(T* out, const T* in, size_t n) {
147
3.12k
   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
148
149
3.12k
   if(in != nullptr && out != nullptr && n > 0) {
150
3.12k
      std::memmove(out, in, sizeof(T) * n);
151
3.12k
   }
152
3.12k
}
void Botan::copy_mem<unsigned int>(unsigned int*, unsigned int const*, unsigned long)
Line
Count
Source
146
2.42k
inline constexpr void copy_mem(T* out, const T* in, size_t n) {
147
2.42k
   BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr, "If n > 0 then args are not null");
148
149
2.42k
   if(in != nullptr && out != nullptr && n > 0) {
150
2.42k
      std::memmove(out, in, sizeof(T) * n);
151
2.42k
   }
152
2.42k
}
153
154
/**
155
* Copy memory
156
* @param out the destination array
157
* @param in the source array
158
*/
159
template <ranges::contiguous_output_range OutR, ranges::contiguous_range InR>
160
   requires std::is_same_v<std::ranges::range_value_t<OutR>, std::ranges::range_value_t<InR>> &&
161
            std::is_trivially_copyable_v<std::ranges::range_value_t<InR>>
162
99.4k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
99.4k
   ranges::assert_equal_byte_lengths(out, in);
164
99.4k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
99.4k
   } else if(ranges::size_bytes(out) > 0) {
167
99.3k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
99.3k
   }
169
99.4k
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned char, 18446744073709551615ul> >(std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned char, 18446744073709551615ul>&&)
void Botan::copy_mem<std::__1::span<unsigned char, 18446744073709551615ul>, std::__1::span<unsigned char const, 18446744073709551615ul>&>(std::__1::span<unsigned char, 18446744073709551615ul>&&, std::__1::span<unsigned char const, 18446744073709551615ul>&)
Line
Count
Source
162
85.6k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
85.6k
   ranges::assert_equal_byte_lengths(out, in);
164
85.6k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
85.6k
   } else if(ranges::size_bytes(out) > 0) {
167
85.5k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
85.5k
   }
169
85.6k
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul>&&)
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&>(std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
void Botan::copy_mem<std::__1::span<unsigned long, 4ul>, std::__1::array<unsigned long, 4ul> const&>(std::__1::span<unsigned long, 4ul>&&, std::__1::array<unsigned long, 4ul> const&)
Line
Count
Source
162
4.81k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
4.81k
   ranges::assert_equal_byte_lengths(out, in);
164
4.81k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
4.81k
   } else if(ranges::size_bytes(out) > 0) {
167
4.81k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
4.81k
   }
169
4.81k
}
void Botan::copy_mem<std::__1::span<unsigned char, 32ul>, std::__1::span<unsigned char const, 32ul>&>(std::__1::span<unsigned char, 32ul>&&, std::__1::span<unsigned char const, 32ul>&)
Line
Count
Source
162
52
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
52
   ranges::assert_equal_byte_lengths(out, in);
164
52
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
52
   } else if(ranges::size_bytes(out) > 0) {
167
52
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
52
   }
169
52
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned long, 1ul>, std::__1::array<unsigned long, 1ul>&>(std::__1::span<unsigned long, 1ul>&&, std::__1::array<unsigned long, 1ul>&)
Unexecuted instantiation: void Botan::copy_mem<std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned long, 4ul> >(std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned long, 4ul>&&)
void Botan::copy_mem<std::__1::span<unsigned long, 6ul>, std::__1::array<unsigned long, 6ul> const&>(std::__1::span<unsigned long, 6ul>&&, std::__1::array<unsigned long, 6ul> const&)
Line
Count
Source
162
2.47k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
2.47k
   ranges::assert_equal_byte_lengths(out, in);
164
2.47k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
2.47k
   } else if(ranges::size_bytes(out) > 0) {
167
2.47k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
2.47k
   }
169
2.47k
}
void Botan::copy_mem<std::__1::span<unsigned char, 48ul>, std::__1::span<unsigned char const, 48ul>&>(std::__1::span<unsigned char, 48ul>&&, std::__1::span<unsigned char const, 48ul>&)
Line
Count
Source
162
19
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
19
   ranges::assert_equal_byte_lengths(out, in);
164
19
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
19
   } else if(ranges::size_bytes(out) > 0) {
167
19
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
19
   }
169
19
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::array<unsigned long, 6ul>&, std::__1::span<unsigned long, 6ul> >(std::__1::array<unsigned long, 6ul>&, std::__1::span<unsigned long, 6ul>&&)
void Botan::copy_mem<std::__1::span<unsigned long, 8ul>, std::__1::array<unsigned long, 8ul> const&>(std::__1::span<unsigned long, 8ul>&&, std::__1::array<unsigned long, 8ul> const&)
Line
Count
Source
162
1.52k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
1.52k
   ranges::assert_equal_byte_lengths(out, in);
164
1.52k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
1.52k
   } else if(ranges::size_bytes(out) > 0) {
167
1.52k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
1.52k
   }
169
1.52k
}
void Botan::copy_mem<std::__1::span<unsigned char, 64ul>, std::__1::span<unsigned char const, 64ul>&>(std::__1::span<unsigned char, 64ul>&&, std::__1::span<unsigned char const, 64ul>&)
Line
Count
Source
162
5
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
5
   ranges::assert_equal_byte_lengths(out, in);
164
5
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
5
   } else if(ranges::size_bytes(out) > 0) {
167
5
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
5
   }
169
5
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::array<unsigned long, 8ul>&, std::__1::span<unsigned long, 8ul> >(std::__1::array<unsigned long, 8ul>&, std::__1::span<unsigned long, 8ul>&&)
void Botan::copy_mem<std::__1::span<unsigned long, 3ul>, std::__1::array<unsigned long, 3ul> const&>(std::__1::span<unsigned long, 3ul>&&, std::__1::array<unsigned long, 3ul> const&)
Line
Count
Source
162
714
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
714
   ranges::assert_equal_byte_lengths(out, in);
164
714
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
714
   } else if(ranges::size_bytes(out) > 0) {
167
714
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
714
   }
169
714
}
void Botan::copy_mem<std::__1::span<unsigned char, 24ul>, std::__1::span<unsigned char const, 24ul>&>(std::__1::span<unsigned char, 24ul>&&, std::__1::span<unsigned char const, 24ul>&)
Line
Count
Source
162
2
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
2
   ranges::assert_equal_byte_lengths(out, in);
164
2
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
2
   } else if(ranges::size_bytes(out) > 0) {
167
2
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
2
   }
169
2
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::array<unsigned long, 3ul>&, std::__1::span<unsigned long, 3ul> >(std::__1::array<unsigned long, 3ul>&, std::__1::span<unsigned long, 3ul>&&)
void Botan::copy_mem<std::__1::span<unsigned char, 28ul>&, std::__1::span<unsigned char const, 28ul> >(std::__1::span<unsigned char, 28ul>&, std::__1::span<unsigned char const, 28ul>&&)
Line
Count
Source
162
1.51k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
1.51k
   ranges::assert_equal_byte_lengths(out, in);
164
1.51k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
1.51k
   } else if(ranges::size_bytes(out) > 0) {
167
1.51k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
1.51k
   }
169
1.51k
}
void Botan::copy_mem<std::__1::span<unsigned char, 28ul>, std::__1::span<unsigned char const, 28ul>&>(std::__1::span<unsigned char, 28ul>&&, std::__1::span<unsigned char const, 28ul>&)
Line
Count
Source
162
13
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
13
   ranges::assert_equal_byte_lengths(out, in);
164
13
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
13
   } else if(ranges::size_bytes(out) > 0) {
167
13
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
13
   }
169
13
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned char, 72ul>, std::__1::span<unsigned char const, 72ul>&>(std::__1::span<unsigned char, 72ul>&&, std::__1::span<unsigned char const, 72ul>&)
void Botan::copy_mem<std::__1::span<unsigned long, 9ul>, std::__1::array<unsigned long, 9ul> const&>(std::__1::span<unsigned long, 9ul>&&, std::__1::array<unsigned long, 9ul> const&)
Line
Count
Source
162
564
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
564
   ranges::assert_equal_byte_lengths(out, in);
164
564
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
564
   } else if(ranges::size_bytes(out) > 0) {
167
564
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
564
   }
169
564
}
void Botan::copy_mem<std::__1::span<unsigned char, 66ul>&, std::__1::span<unsigned char const, 66ul> >(std::__1::span<unsigned char, 66ul>&, std::__1::span<unsigned char const, 66ul>&&)
Line
Count
Source
162
2.14k
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
2.14k
   ranges::assert_equal_byte_lengths(out, in);
164
2.14k
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
2.14k
   } else if(ranges::size_bytes(out) > 0) {
167
2.14k
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
2.14k
   }
169
2.14k
}
void Botan::copy_mem<std::__1::span<unsigned char, 66ul>, std::__1::span<unsigned char const, 66ul>&>(std::__1::span<unsigned char, 66ul>&&, std::__1::span<unsigned char const, 66ul>&)
Line
Count
Source
162
12
inline constexpr void copy_mem(OutR&& out, InR&& in) {
163
12
   ranges::assert_equal_byte_lengths(out, in);
164
12
   if(std::is_constant_evaluated()) {
165
0
      std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
166
12
   } else if(ranges::size_bytes(out) > 0) {
167
12
      std::memmove(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
168
12
   }
169
12
}
Unexecuted instantiation: void Botan::copy_mem<std::__1::span<unsigned char, 98ul>, std::__1::span<unsigned char const, 98ul>&>(std::__1::span<unsigned char, 98ul>&&, std::__1::span<unsigned char const, 98ul>&)
Unexecuted instantiation: void Botan::copy_mem<std::__1::array<unsigned long, 9ul>&, std::__1::span<unsigned long, 9ul> >(std::__1::array<unsigned long, 9ul>&, std::__1::span<unsigned long, 9ul>&&)
170
171
/**
172
 * Copy a range of a trivially copyable type into another range of trivially
173
 * copyable type of matching byte length.
174
 */
175
template <ranges::contiguous_output_range ToR, ranges::contiguous_range FromR>
176
   requires std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>> &&
177
            std::is_trivially_copyable_v<std::ranges::range_value_t<ToR>>
178
77.8M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
77.8M
   ranges::assert_equal_byte_lengths(out, in);
180
77.8M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
77.8M
}
void Botan::typecast_copy<std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned char, 32ul>&>(std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned char, 32ul>&)
Line
Count
Source
178
851k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
851k
   ranges::assert_equal_byte_lengths(out, in);
180
851k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
851k
}
void Botan::typecast_copy<std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned char const, 32ul>&>(std::__1::array<unsigned long, 4ul>&, std::__1::span<unsigned char const, 32ul>&)
Line
Count
Source
178
2.18M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
2.18M
   ranges::assert_equal_byte_lengths(out, in);
180
2.18M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
2.18M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 32ul>, std::__1::array<unsigned long, 4ul>&>(std::__1::span<unsigned char, 32ul>&&, std::__1::array<unsigned long, 4ul>&)
Line
Count
Source
178
1.51M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
1.51M
   ranges::assert_equal_byte_lengths(out, in);
180
1.51M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
1.51M
}
void Botan::typecast_copy<std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul>&>(std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul>&)
Line
Count
Source
178
6.14M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
6.14M
   ranges::assert_equal_byte_lengths(out, in);
180
6.14M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
6.14M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&)
Line
Count
Source
178
2.86M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
2.86M
   ranges::assert_equal_byte_lengths(out, in);
180
2.86M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
2.86M
}
void Botan::typecast_copy<std::__1::span<unsigned long, 1ul>, std::__1::span<unsigned char const, 8ul>&>(std::__1::span<unsigned long, 1ul>&&, std::__1::span<unsigned char const, 8ul>&)
Line
Count
Source
178
16.9M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
16.9M
   ranges::assert_equal_byte_lengths(out, in);
180
16.9M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
16.9M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 8ul>&, std::__1::span<unsigned long const, 1ul> >(std::__1::span<unsigned char, 8ul>&, std::__1::span<unsigned long const, 1ul>&&)
Line
Count
Source
178
2.65M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
2.65M
   ranges::assert_equal_byte_lengths(out, in);
180
2.65M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
2.65M
}
void Botan::typecast_copy<std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul>&>(std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned char const, 18446744073709551615ul>&)
Line
Count
Source
178
304k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
304k
   ranges::assert_equal_byte_lengths(out, in);
180
304k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
304k
}
void Botan::typecast_copy<std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned char, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&)
Line
Count
Source
178
179k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
179k
   ranges::assert_equal_byte_lengths(out, in);
180
179k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
179k
}
void Botan::typecast_copy<std::__1::span<unsigned int, 1ul>, std::__1::span<unsigned char const, 4ul>&>(std::__1::span<unsigned int, 1ul>&&, std::__1::span<unsigned char const, 4ul>&)
Line
Count
Source
178
33.2M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
33.2M
   ranges::assert_equal_byte_lengths(out, in);
180
33.2M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
33.2M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 4ul>&, std::__1::span<unsigned int const, 1ul> >(std::__1::span<unsigned char, 4ul>&, std::__1::span<unsigned int const, 1ul>&&)
Line
Count
Source
178
8.84M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
8.84M
   ranges::assert_equal_byte_lengths(out, in);
180
8.84M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
8.84M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 2ul>&, std::__1::span<unsigned short const, 1ul> >(std::__1::span<unsigned char, 2ul>&, std::__1::span<unsigned short const, 1ul>&&)
Line
Count
Source
178
7.39k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
7.39k
   ranges::assert_equal_byte_lengths(out, in);
180
7.39k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
7.39k
}
void Botan::typecast_copy<std::__1::array<unsigned int, 16ul>&, std::__1::span<unsigned char const, 64ul>&>(std::__1::array<unsigned int, 16ul>&, std::__1::span<unsigned char const, 64ul>&)
Line
Count
Source
178
2.05M
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
2.05M
   ranges::assert_equal_byte_lengths(out, in);
180
2.05M
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
2.05M
}
void Botan::typecast_copy<std::__1::span<unsigned long, 1ul>, std::__1::span<unsigned char, 8ul>&>(std::__1::span<unsigned long, 1ul>&&, std::__1::span<unsigned char, 8ul>&)
Line
Count
Source
178
79.4k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
79.4k
   ranges::assert_equal_byte_lengths(out, in);
180
79.4k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
79.4k
}
void Botan::typecast_copy<std::__1::span<unsigned short, 1ul>, std::__1::span<unsigned char const, 2ul>&>(std::__1::span<unsigned short, 1ul>&&, std::__1::span<unsigned char const, 2ul>&)
Line
Count
Source
178
6.97k
inline constexpr void typecast_copy(ToR&& out, FromR&& in) {
179
6.97k
   ranges::assert_equal_byte_lengths(out, in);
180
6.97k
   std::memcpy(std::ranges::data(out), std::ranges::data(in), ranges::size_bytes(out));
181
6.97k
}
182
183
/**
184
 * Copy a range of trivially copyable type into an instance of trivially
185
 * copyable type with matching length.
186
 */
187
template <typename ToT, ranges::contiguous_range FromR>
188
   requires std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>> && std::is_trivially_copyable_v<ToT> &&
189
            (!std::ranges::range<ToT>)
190
50.2M
inline constexpr void typecast_copy(ToT& out, FromR&& in) noexcept {
191
50.2M
   typecast_copy(std::span<ToT, 1>(&out, 1), in);
192
50.2M
}
void Botan::typecast_copy<unsigned long, std::__1::span<unsigned char const, 8ul>&>(unsigned long&, std::__1::span<unsigned char const, 8ul>&)
Line
Count
Source
190
16.9M
inline constexpr void typecast_copy(ToT& out, FromR&& in) noexcept {
191
16.9M
   typecast_copy(std::span<ToT, 1>(&out, 1), in);
192
16.9M
}
void Botan::typecast_copy<unsigned int, std::__1::span<unsigned char const, 4ul>&>(unsigned int&, std::__1::span<unsigned char const, 4ul>&)
Line
Count
Source
190
33.2M
inline constexpr void typecast_copy(ToT& out, FromR&& in) noexcept {
191
33.2M
   typecast_copy(std::span<ToT, 1>(&out, 1), in);
192
33.2M
}
void Botan::typecast_copy<unsigned long, std::__1::span<unsigned char, 8ul>&>(unsigned long&, std::__1::span<unsigned char, 8ul>&)
Line
Count
Source
190
79.4k
inline constexpr void typecast_copy(ToT& out, FromR&& in) noexcept {
191
79.4k
   typecast_copy(std::span<ToT, 1>(&out, 1), in);
192
79.4k
}
void Botan::typecast_copy<unsigned short, std::__1::span<unsigned char const, 2ul>&>(unsigned short&, std::__1::span<unsigned char const, 2ul>&)
Line
Count
Source
190
6.97k
inline constexpr void typecast_copy(ToT& out, FromR&& in) noexcept {
191
6.97k
   typecast_copy(std::span<ToT, 1>(&out, 1), in);
192
6.97k
}
193
194
/**
195
 * Copy an instance of trivially copyable type into a range of trivially
196
 * copyable type with matching length.
197
 */
198
template <ranges::contiguous_output_range ToR, typename FromT>
199
   requires std::is_trivially_copyable_v<FromT> &&
200
            (!std::ranges::range<FromT>) && std::is_trivially_copyable_v<std::ranges::range_value_t<ToR>>
201
11.5M
inline constexpr void typecast_copy(ToR&& out, const FromT& in) {
202
11.5M
   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
203
11.5M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 8ul>&, unsigned long>(std::__1::span<unsigned char, 8ul>&, unsigned long const&)
Line
Count
Source
201
2.65M
inline constexpr void typecast_copy(ToR&& out, const FromT& in) {
202
2.65M
   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
203
2.65M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 4ul>&, unsigned int>(std::__1::span<unsigned char, 4ul>&, unsigned int const&)
Line
Count
Source
201
8.84M
inline constexpr void typecast_copy(ToR&& out, const FromT& in) {
202
8.84M
   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
203
8.84M
}
void Botan::typecast_copy<std::__1::span<unsigned char, 2ul>&, unsigned short>(std::__1::span<unsigned char, 2ul>&, unsigned short const&)
Line
Count
Source
201
7.39k
inline constexpr void typecast_copy(ToR&& out, const FromT& in) {
202
7.39k
   typecast_copy(out, std::span<const FromT, 1>(&in, 1));
203
7.39k
}
204
205
/**
206
 * Create a trivial type by bit-casting a range of trivially copyable type with
207
 * matching length into it.
208
 */
209
template <typename ToT, ranges::contiguous_range FromR>
210
   requires std::is_default_constructible_v<ToT> && std::is_trivially_copyable_v<ToT> &&
211
            std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>>
212
53.2M
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
53.2M
   ToT dst;
214
53.2M
   typecast_copy(dst, src);
215
53.2M
   return dst;
216
53.2M
}
std::__1::array<unsigned long, 4ul> Botan::typecast_copy<std::__1::array<unsigned long, 4ul>, std::__1::span<unsigned char, 32ul> >(std::__1::span<unsigned char, 32ul>&&)
Line
Count
Source
212
851k
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
851k
   ToT dst;
214
851k
   typecast_copy(dst, src);
215
851k
   return dst;
216
851k
}
std::__1::array<unsigned long, 4ul> Botan::typecast_copy<std::__1::array<unsigned long, 4ul>, std::__1::span<unsigned char const, 32ul> >(std::__1::span<unsigned char const, 32ul>&&)
Line
Count
Source
212
2.18M
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
2.18M
   ToT dst;
214
2.18M
   typecast_copy(dst, src);
215
2.18M
   return dst;
216
2.18M
}
unsigned long Botan::typecast_copy<unsigned long, std::__1::span<unsigned char const, 8ul>&>(std::__1::span<unsigned char const, 8ul>&)
Line
Count
Source
212
16.9M
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
16.9M
   ToT dst;
214
16.9M
   typecast_copy(dst, src);
215
16.9M
   return dst;
216
16.9M
}
unsigned int Botan::typecast_copy<unsigned int, std::__1::span<unsigned char const, 4ul>&>(std::__1::span<unsigned char const, 4ul>&)
Line
Count
Source
212
33.2M
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
33.2M
   ToT dst;
214
33.2M
   typecast_copy(dst, src);
215
33.2M
   return dst;
216
33.2M
}
unsigned long Botan::typecast_copy<unsigned long, std::__1::span<unsigned char, 8ul>&>(std::__1::span<unsigned char, 8ul>&)
Line
Count
Source
212
79.4k
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
79.4k
   ToT dst;
214
79.4k
   typecast_copy(dst, src);
215
79.4k
   return dst;
216
79.4k
}
unsigned short Botan::typecast_copy<unsigned short, std::__1::span<unsigned char const, 2ul>&>(std::__1::span<unsigned char const, 2ul>&)
Line
Count
Source
212
6.97k
inline constexpr ToT typecast_copy(FromR&& src) noexcept {
213
6.97k
   ToT dst;
214
6.97k
   typecast_copy(dst, src);
215
6.97k
   return dst;
216
6.97k
}
217
218
// TODO: deprecate and replace
219
template <typename T>
220
inline constexpr void typecast_copy(uint8_t out[], T in[], size_t N)
221
   requires std::is_trivially_copyable<T>::value
222
{
223
   // asserts that *in and *out point to the correct amount of memory
224
   typecast_copy(std::span<uint8_t>(out, sizeof(T) * N), std::span<const T>(in, N));
225
}
226
227
// TODO: deprecate and replace
228
template <typename T>
229
inline constexpr void typecast_copy(T out[], const uint8_t in[], size_t N)
230
   requires std::is_trivial<T>::value
231
{
232
   // asserts that *in and *out point to the correct amount of memory
233
   typecast_copy(std::span<T>(out, N), std::span<const uint8_t>(in, N * sizeof(T)));
234
}
235
236
// TODO: deprecate and replace
237
template <typename T>
238
inline constexpr void typecast_copy(uint8_t out[], const T& in) {
239
   // asserts that *out points to the correct amount of memory
240
   typecast_copy(std::span<uint8_t, sizeof(T)>(out, sizeof(T)), in);
241
}
242
243
// TODO: deprecate and replace
244
template <typename T>
245
   requires std::is_trivial<typename std::decay<T>::type>::value
246
inline constexpr void typecast_copy(T& out, const uint8_t in[]) {
247
   // asserts that *in points to the correct amount of memory
248
   typecast_copy(out, std::span<const uint8_t, sizeof(T)>(in, sizeof(T)));
249
}
250
251
// TODO: deprecate and replace
252
template <typename To>
253
   requires std::is_trivial<To>::value
254
inline constexpr To typecast_copy(const uint8_t src[]) noexcept {
255
   // asserts that *src points to the correct amount of memory
256
   return typecast_copy<To>(std::span<const uint8_t, sizeof(To)>(src, sizeof(To)));
257
}
258
259
#if !defined(BOTAN_IS_BEGIN_BUILT)
260
/**
261
* Set memory to a fixed value
262
* @param ptr a pointer to an array of bytes
263
* @param n the number of Ts pointed to by ptr
264
* @param val the value to set each byte to
265
*/
266
0
BOTAN_DEPRECATED("This function is deprecated") inline constexpr void set_mem(uint8_t* ptr, size_t n, uint8_t val) {
267
0
   if(n > 0) {
268
0
      std::memset(ptr, val, n);
269
0
   }
270
0
}
271
#endif
272
273
56.8k
inline const uint8_t* cast_char_ptr_to_uint8(const char* s) {
274
56.8k
   return reinterpret_cast<const uint8_t*>(s);
275
56.8k
}
276
277
304
inline const char* cast_uint8_ptr_to_char(const uint8_t* b) {
278
304
   return reinterpret_cast<const char*>(b);
279
304
}
280
281
0
inline uint8_t* cast_char_ptr_to_uint8(char* s) {
282
0
   return reinterpret_cast<uint8_t*>(s);
283
0
}
284
285
0
inline char* cast_uint8_ptr_to_char(uint8_t* b) {
286
0
   return reinterpret_cast<char*>(b);
287
0
}
288
289
#if !defined(BOTAN_IS_BEING_BUILT)
290
/**
291
* Memory comparison, input insensitive
292
* @param p1 a pointer to an array
293
* @param p2 a pointer to another array
294
* @param n the number of Ts in p1 and p2
295
* @return true iff p1[i] == p2[i] forall i in [0...n)
296
*/
297
template <typename T>
298
BOTAN_DEPRECATED("This function is deprecated")
299
inline bool same_mem(const T* p1, const T* p2, size_t n) {
300
   volatile T difference = 0;
301
302
   for(size_t i = 0; i != n; ++i) {
303
      difference = difference | (p1[i] ^ p2[i]);
304
   }
305
306
   return difference == 0;
307
}
308
#endif
309
310
#if !defined(BOTAN_IS_BEING_BUILT)
311
312
template <typename T, typename Alloc>
313
BOTAN_DEPRECATED("The buffer_insert functions are deprecated")
314
size_t buffer_insert(std::vector<T, Alloc>& buf, size_t buf_offset, const T input[], size_t input_length) {
315
   BOTAN_ASSERT_NOMSG(buf_offset <= buf.size());
316
   const size_t to_copy = std::min(input_length, buf.size() - buf_offset);
317
   if(to_copy > 0) {
318
      copy_mem(&buf[buf_offset], input, to_copy);
319
   }
320
   return to_copy;
321
}
322
323
template <typename T, typename Alloc, typename Alloc2>
324
BOTAN_DEPRECATED("The buffer_insert functions are deprecated")
325
size_t buffer_insert(std::vector<T, Alloc>& buf, size_t buf_offset, const std::vector<T, Alloc2>& input) {
326
   BOTAN_ASSERT_NOMSG(buf_offset <= buf.size());
327
   const size_t to_copy = std::min(input.size(), buf.size() - buf_offset);
328
   if(to_copy > 0) {
329
      copy_mem(&buf[buf_offset], input.data(), to_copy);
330
   }
331
   return to_copy;
332
}
333
334
#endif
335
336
/**
337
* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
338
* @param out the input/output range
339
* @param in the read-only input range
340
*/
341
inline constexpr void xor_buf(ranges::contiguous_output_range<uint8_t> auto&& out,
342
808k
                              ranges::contiguous_range<uint8_t> auto&& in) {
343
808k
   ranges::assert_equal_byte_lengths(out, in);
344
345
808k
   std::span<uint8_t> o(out);
346
808k
   std::span<const uint8_t> i(in);
347
348
1.66M
   for(; o.size_bytes() >= 32; o = o.subspan(32), i = i.subspan(32)) {
349
851k
      auto x = typecast_copy<std::array<uint64_t, 4>>(o.template first<32>());
350
851k
      const auto y = typecast_copy<std::array<uint64_t, 4>>(i.template first<32>());
351
352
851k
      x[0] ^= y[0];
353
851k
      x[1] ^= y[1];
354
851k
      x[2] ^= y[2];
355
851k
      x[3] ^= y[3];
356
357
851k
      typecast_copy(o.template first<32>(), x);
358
851k
   }
359
360
1.78M
   for(size_t off = 0; off != o.size_bytes(); ++off) {
361
974k
      o[off] ^= i[off];
362
974k
   }
363
808k
}
void Botan::xor_buf<std::__1::span<unsigned char, 18446744073709551615ul>, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::span<unsigned char, 18446744073709551615ul>&&, std::__1::span<unsigned char const, 18446744073709551615ul>&&)
Line
Count
Source
342
807k
                              ranges::contiguous_range<uint8_t> auto&& in) {
343
807k
   ranges::assert_equal_byte_lengths(out, in);
344
345
807k
   std::span<uint8_t> o(out);
346
807k
   std::span<const uint8_t> i(in);
347
348
1.65M
   for(; o.size_bytes() >= 32; o = o.subspan(32), i = i.subspan(32)) {
349
851k
      auto x = typecast_copy<std::array<uint64_t, 4>>(o.template first<32>());
350
851k
      const auto y = typecast_copy<std::array<uint64_t, 4>>(i.template first<32>());
351
352
851k
      x[0] ^= y[0];
353
851k
      x[1] ^= y[1];
354
851k
      x[2] ^= y[2];
355
851k
      x[3] ^= y[3];
356
357
851k
      typecast_copy(o.template first<32>(), x);
358
851k
   }
359
360
1.76M
   for(size_t off = 0; off != o.size_bytes(); ++off) {
361
953k
      o[off] ^= i[off];
362
953k
   }
363
807k
}
void Botan::xor_buf<std::__1::span<unsigned char, 18446744073709551615ul>, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&>(std::__1::span<unsigned char, 18446744073709551615ul>&&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
Line
Count
Source
342
1.31k
                              ranges::contiguous_range<uint8_t> auto&& in) {
343
1.31k
   ranges::assert_equal_byte_lengths(out, in);
344
345
1.31k
   std::span<uint8_t> o(out);
346
1.31k
   std::span<const uint8_t> i(in);
347
348
1.31k
   for(; o.size_bytes() >= 32; o = o.subspan(32), i = i.subspan(32)) {
349
0
      auto x = typecast_copy<std::array<uint64_t, 4>>(o.template first<32>());
350
0
      const auto y = typecast_copy<std::array<uint64_t, 4>>(i.template first<32>());
351
352
0
      x[0] ^= y[0];
353
0
      x[1] ^= y[1];
354
0
      x[2] ^= y[2];
355
0
      x[3] ^= y[3];
356
357
0
      typecast_copy(o.template first<32>(), x);
358
0
   }
359
360
22.3k
   for(size_t off = 0; off != o.size_bytes(); ++off) {
361
21.0k
      o[off] ^= i[off];
362
21.0k
   }
363
1.31k
}
364
365
/**
366
* XOR arrays. Postcondition out[i] = in1[i] ^ in2[i] forall i = 0...length
367
* @param out the output range
368
* @param in1 the first input range
369
* @param in2 the second input range
370
*/
371
inline constexpr void xor_buf(ranges::contiguous_output_range<uint8_t> auto&& out,
372
                              ranges::contiguous_range<uint8_t> auto&& in1,
373
659k
                              ranges::contiguous_range<uint8_t> auto&& in2) {
374
659k
   ranges::assert_equal_byte_lengths(out, in1, in2);
375
376
659k
   std::span o{out};
377
659k
   std::span i1{in1};
378
659k
   std::span i2{in2};
379
380
1.32M
   for(; o.size_bytes() >= 32; o = o.subspan(32), i1 = i1.subspan(32), i2 = i2.subspan(32)) {
381
667k
      auto x = typecast_copy<std::array<uint64_t, 4>>(i1.template first<32>());
382
667k
      const auto y = typecast_copy<std::array<uint64_t, 4>>(i2.template first<32>());
383
384
667k
      x[0] ^= y[0];
385
667k
      x[1] ^= y[1];
386
667k
      x[2] ^= y[2];
387
667k
      x[3] ^= y[3];
388
389
667k
      typecast_copy(o.template first<32>(), x);
390
667k
   }
391
392
735k
   for(size_t off = 0; off != o.size_bytes(); ++off) {
393
75.8k
      o[off] = i1[off] ^ i2[off];
394
75.8k
   }
395
659k
}
396
397
/**
398
* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
399
* @param out the input/output buffer
400
* @param in the read-only input buffer
401
* @param length the length of the buffers
402
*/
403
749k
inline void xor_buf(uint8_t out[], const uint8_t in[], size_t length) {
404
   // simply assumes that *out and *in point to "length" allocated bytes at least
405
749k
   xor_buf(std::span{out, length}, std::span{in, length});
406
749k
}
407
408
/**
409
* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
410
* @param out the output buffer
411
* @param in the first input buffer
412
* @param in2 the second input buffer
413
* @param length the length of the three buffers
414
*/
415
659k
inline void xor_buf(uint8_t out[], const uint8_t in[], const uint8_t in2[], size_t length) {
416
   // simply assumes that *out, *in, and *in2 point to "length" allocated bytes at least
417
659k
   xor_buf(std::span{out, length}, std::span{in, length}, std::span{in2, length});
418
659k
}
419
420
// TODO: deprecate and replace, use .subspan()
421
54.0k
inline void xor_buf(std::span<uint8_t> out, std::span<const uint8_t> in, size_t n) {
422
54.0k
   BOTAN_ARG_CHECK(out.size() >= n, "output span is too small");
423
54.0k
   BOTAN_ARG_CHECK(in.size() >= n, "input span is too small");
424
54.0k
   xor_buf(out.first(n), in.first(n));
425
54.0k
}
426
427
// TODO: deprecate and replace, use .subspan()
428
template <typename Alloc>
429
3.31k
void xor_buf(std::vector<uint8_t, Alloc>& out, const uint8_t* in, size_t n) {
430
3.31k
   BOTAN_ARG_CHECK(out.size() >= n, "output vector is too small");
431
   // simply assumes that *in points to "n" allocated bytes at least
432
3.31k
   xor_buf(std::span{out}.first(n), std::span{in, n});
433
3.31k
}
434
435
// TODO: deprecate and replace
436
template <typename Alloc, typename Alloc2>
437
void xor_buf(std::vector<uint8_t, Alloc>& out, const uint8_t* in, const std::vector<uint8_t, Alloc2>& in2, size_t n) {
438
   BOTAN_ARG_CHECK(out.size() >= n, "output vector is too small");
439
   BOTAN_ARG_CHECK(in2.size() >= n, "input vector is too small");
440
   // simply assumes that *in points to "n" allocated bytes at least
441
   xor_buf(std::span{out}.first(n), std::span{in, n}, std::span{in2}.first(n));
442
}
443
444
template <typename Alloc, typename Alloc2>
445
1.31k
std::vector<uint8_t, Alloc>& operator^=(std::vector<uint8_t, Alloc>& out, const std::vector<uint8_t, Alloc2>& in) {
446
1.31k
   if(out.size() < in.size()) {
447
0
      out.resize(in.size());
448
0
   }
449
450
1.31k
   xor_buf(std::span{out}.first(in.size()), in);
451
1.31k
   return out;
452
1.31k
}
453
454
}  // namespace Botan
455
456
#endif