8#ifndef BOTAN_MEMORY_OPS_H_
9#define BOTAN_MEMORY_OPS_H_
11#include <botan/assert.h>
12#include <botan/concepts.h>
13#include <botan/types.h>
28#if !defined(BOTAN_IS_BEING_BUILT)
29 #include <botan/allocator.h>
62#if !defined(BOTAN_IS_BEGIN_BUILT)
106 std::memset(ptr, 0, bytes);
132template <ranges::contiguous_output_range R>
134 requires std::is_trivially_copyable_v<std::ranges::range_value_t<R>>
146 requires std::is_trivial<typename std::decay<T>::type>::value
147inline constexpr void copy_mem(
T* out,
const T* in,
size_t n) {
150 if(in !=
nullptr && out !=
nullptr && n > 0) {
151 std::memmove(out, in,
sizeof(
T) * n);
160template <ranges::contiguous_output_range OutR, ranges::contiguous_range InR>
161 requires std::is_same_v<std::ranges::range_value_t<OutR>, std::ranges::range_value_t<InR>> &&
162 std::is_trivially_copyable_v<std::ranges::range_value_t<InR>>
163inline constexpr void copy_mem(OutR&& out, InR&& in) {
165 if(std::is_constant_evaluated()) {
166 std::copy(std::ranges::begin(in), std::ranges::end(in), std::ranges::begin(out));
176template <ranges::contiguous_output_range ToR, ranges::contiguous_range FromR>
177 requires std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>> &&
178 std::is_trivially_copyable_v<std::ranges::range_value_t<ToR>>
188template <
typename ToT, ranges::contiguous_range FromR>
189 requires std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>> && std::is_trivially_copyable_v<ToT> &&
190 (!std::ranges::range<ToT>)
199template <ranges::contiguous_output_range ToR,
typename FromT>
200 requires std::is_trivially_copyable_v<FromT> &&
201 (!std::ranges::range<FromT>) && std::is_trivially_copyable_v<std::ranges::range_value_t<ToR>>
210template <
typename ToT, ranges::contiguous_range FromR>
211 requires std::is_default_constructible_v<ToT> && std::is_trivially_copyable_v<ToT> &&
212 std::is_trivially_copyable_v<std::ranges::range_value_t<FromR>>
222 requires std::is_trivially_copyable<T>::value
225 typecast_copy(std::span<uint8_t>(out,
sizeof(
T) * N), std::span<const T>(in, N));
231 requires std::is_trivial<T>::value
234 typecast_copy(std::span<T>(out, N), std::span<const uint8_t>(in, N *
sizeof(
T)));
246 requires std::is_trivial<typename std::decay<T>::type>::value
249 typecast_copy(out, std::span<
const uint8_t,
sizeof(
T)>(in,
sizeof(
T)));
253template <
typename To>
254 requires std::is_trivial<To>::value
260#if !defined(BOTAN_IS_BEGIN_BUILT)
269 std::memset(ptr, val, n);
275 return reinterpret_cast<const uint8_t*
>(s);
279 return reinterpret_cast<const char*
>(
b);
283 return reinterpret_cast<uint8_t*
>(s);
287 return reinterpret_cast<char*
>(
b);
290#if !defined(BOTAN_IS_BEING_BUILT)
301 volatile T difference = 0;
303 for(
size_t i = 0; i != n; ++i) {
304 difference = difference | (p1[i] ^ p2[i]);
307 return difference == 0;
311#if !defined(BOTAN_IS_BEING_BUILT)
313template <
typename T,
typename Alloc>
315size_t
buffer_insert(std::vector<
T, Alloc>& buf,
size_t buf_offset, const
T input[],
size_t input_length) {
317 const size_t to_copy = std::min(input_length, buf.size() - buf_offset);
319 copy_mem(&buf[buf_offset], input, to_copy);
315size_t
buffer_insert(std::vector<
T, Alloc>& buf,
size_t buf_offset, const
T input[],
size_t input_length) {
…}
324template <
typename T,
typename Alloc,
typename Alloc2>
326size_t
buffer_insert(std::vector<
T, Alloc>& buf,
size_t buf_offset, const std::vector<
T, Alloc2>& input) {
328 const size_t to_copy = std::min(input.size(), buf.size() - buf_offset);
330 copy_mem(&buf[buf_offset], input.data(), to_copy);
326size_t
buffer_insert(std::vector<
T, Alloc>& buf,
size_t buf_offset, const std::vector<
T, Alloc2>& input) {
…}
346 std::span<uint8_t> o(out);
347 std::span<const uint8_t> i(in);
349 for(; o.size_bytes() >= 32; o = o.subspan(32), i = i.subspan(32)) {
361 for(
size_t off = 0; off != o.size_bytes(); ++off) {
381 for(; o.size_bytes() >= 32; o = o.subspan(32), i1 = i1.subspan(32), i2 = i2.subspan(32)) {
393 for(
size_t off = 0; off != o.size_bytes(); ++off) {
394 o[off] = i1[off] ^ i2[off];
404inline void xor_buf(uint8_t out[],
const uint8_t in[],
size_t length) {
406 xor_buf(std::span{out, length}, std::span{in, length});
404inline void xor_buf(uint8_t out[],
const uint8_t in[],
size_t length) {
…}
416inline void xor_buf(uint8_t out[],
const uint8_t in[],
const uint8_t in2[],
size_t length) {
418 xor_buf(std::span{out, length}, std::span{in, length}, std::span{in2, length});
416inline void xor_buf(uint8_t out[],
const uint8_t in[],
const uint8_t in2[],
size_t length) {
…}
422inline void xor_buf(std::span<uint8_t> out, std::span<const uint8_t> in,
size_t n) {
425 xor_buf(out.first(n), in.first(n));
422inline void xor_buf(std::span<uint8_t> out, std::span<const uint8_t> in,
size_t n) {
…}
429template <
typename Alloc>
430void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
size_t n) {
433 xor_buf(std::span{out}.first(n), std::span{in, n});
430void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
size_t n) {
…}
437template <
typename Alloc,
typename Alloc2>
438void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
const std::vector<uint8_t, Alloc2>& in2,
size_t n) {
442 xor_buf(std::span{out}.first(n), std::span{in, n}, std::span{in2}.first(n));
438void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
const std::vector<uint8_t, Alloc2>& in2,
size_t n) {
…}
445template <
typename Alloc,
typename Alloc2>
446std::vector<uint8_t, Alloc>&
operator^=(std::vector<uint8_t, Alloc>& out,
const std::vector<uint8_t, Alloc2>& in) {
447 if(out.size() < in.size()) {
448 out.resize(in.size());
451 xor_buf(std::span{out}.first(in.size()), in);
446std::vector<uint8_t, Alloc>&
operator^=(std::vector<uint8_t, Alloc>& out,
const std::vector<uint8_t, Alloc2>& in) {
…}
#define BOTAN_PUBLIC_API(maj, min)
#define BOTAN_DEPRECATED(msg)
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
#define BOTAN_ARG_CHECK(expr, msg)
constexpr size_t size_bytes(spanable_range auto &&r)
constexpr void assert_equal_byte_lengths(R0 &&r0, Rs &&... rs)
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
constexpr void typecast_copy(ToR &&out, FromR &&in)
constexpr void set_mem(uint8_t *ptr, size_t n, uint8_t val)
constexpr void clear_bytes(void *ptr, size_t bytes)
void secure_scrub_memory(void *ptr, size_t n)
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
std::vector< uint8_t, Alloc > & operator^=(std::vector< uint8_t, Alloc > &out, const std::vector< uint8_t, Alloc2 > &in)
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
bool same_mem(const T *p1, const T *p2, size_t n)
const char * cast_uint8_ptr_to_char(const uint8_t *b)
bool constant_time_compare(std::span< const uint8_t > x, std::span< const uint8_t > y)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)
const uint8_t * cast_char_ptr_to_uint8(const char *s)