/usr/include/botan-2/botan/mem_ops.h is in libbotan-2-dev 2.4.0-5ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | /*
* Memory Operations
* (C) 1999-2009,2012,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_MEMORY_OPS_H_
#define BOTAN_MEMORY_OPS_H_
#include <botan/types.h>
#include <cstring>
#include <vector>
namespace Botan {
/**
* Allocate a memory buffer by some method. This should only be used for
* primitive types (uint8_t, uint32_t, etc).
*
* @param elems the number of elements
* @param elem_size the size of each element
* @return pointer to allocated and zeroed memory, or throw std::bad_alloc on failure
*/
BOTAN_PUBLIC_API(2,3) BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size);
/**
* Free a pointer returned by allocate_memory
* @param p the pointer returned by allocate_memory
* @param elems the number of elements, as passed to allocate_memory
* @param elem_size the size of each element, as passed to allocate_memory
*/
BOTAN_PUBLIC_API(2,3) void deallocate_memory(void* p, size_t elems, size_t elem_size);
/**
* Scrub memory contents in a way that a compiler should not elide,
* using some system specific technique. Note that this function might
* not zero the memory (for example, in some hypothetical
* implementation it might combine the memory contents with the output
* of a system PRNG), but if you can detect any difference in behavior
* at runtime then the clearing is side-effecting and you can just
* use `clear_mem`.
*
* Use this function to scrub memory just before deallocating it, or on
* a stack buffer before returning from the function.
*
* @param ptr a pointer to memory to scrub
* @param n the number of bytes pointed to by ptr
*/
BOTAN_PUBLIC_API(2,0) void secure_scrub_memory(void* ptr, size_t n);
/**
* Memory comparison, input insensitive
* @param x a pointer to an array
* @param y a pointer to another array
* @param len the number of Ts in x and y
* @return true iff x[i] == y[i] forall i in [0...n)
*/
BOTAN_PUBLIC_API(2,3) bool constant_time_compare(const uint8_t x[],
const uint8_t y[],
size_t len);
/**
* Zero out some bytes
* @param ptr a pointer to memory to zero
* @param bytes the number of bytes to zero in ptr
*/
inline void clear_bytes(void* ptr, size_t bytes)
{
if(bytes > 0)
{
std::memset(ptr, 0, bytes);
}
}
/**
* Zero memory before use. This simply calls memset and should not be
* used in cases where the compiler cannot see the call as a
* side-effecting operation (for example, if calling clear_mem before
* deallocating memory, the compiler would be allowed to omit the call
* to memset entirely under the as-if rule.)
*
* @param ptr a pointer to an array of Ts to zero
* @param n the number of Ts pointed to by ptr
*/
template<typename T> inline void clear_mem(T* ptr, size_t n)
{
clear_bytes(ptr, sizeof(T)*n);
}
/**
* Copy memory
* @param out the destination array
* @param in the source array
* @param n the number of elements of in/out
*/
template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
{
if(n > 0)
{
std::memmove(out, in, sizeof(T)*n);
}
}
/**
* Set memory to a fixed value
* @param ptr a pointer to an array
* @param n the number of Ts pointed to by ptr
* @param val the value to set each byte to
*/
template<typename T>
inline void set_mem(T* ptr, size_t n, uint8_t val)
{
if(n > 0)
{
std::memset(ptr, val, sizeof(T)*n);
}
}
inline const uint8_t* cast_char_ptr_to_uint8(const char* s)
{
return reinterpret_cast<const uint8_t*>(s);
}
inline const char* cast_uint8_ptr_to_char(const uint8_t* b)
{
return reinterpret_cast<const char*>(b);
}
inline uint8_t* cast_char_ptr_to_uint8(char* s)
{
return reinterpret_cast<uint8_t*>(s);
}
inline char* cast_uint8_ptr_to_char(uint8_t* b)
{
return reinterpret_cast<char*>(b);
}
/**
* Memory comparison, input insensitive
* @param p1 a pointer to an array
* @param p2 a pointer to another array
* @param n the number of Ts in p1 and p2
* @return true iff p1[i] == p2[i] forall i in [0...n)
*/
template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
{
volatile T difference = 0;
for(size_t i = 0; i != n; ++i)
difference |= (p1[i] ^ p2[i]);
return difference == 0;
}
/**
* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
* @param out the input/output buffer
* @param in the read-only input buffer
* @param length the length of the buffers
*/
inline void xor_buf(uint8_t out[],
const uint8_t in[],
size_t length)
{
while(length >= 16)
{
uint64_t x0, x1, y0, y1;
std::memcpy(&x0, in, 8);
std::memcpy(&x1, in + 8, 8);
std::memcpy(&y0, out, 8);
std::memcpy(&y1, out + 8, 8);
y0 ^= x0;
y1 ^= x1;
std::memcpy(out, &y0, 8);
std::memcpy(out + 8, &y1, 8);
out += 16; in += 16; length -= 16;
}
while(length > 0)
{
out[0] ^= in[0];
out += 1;
in += 1;
length -= 1;
}
}
/**
* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
* @param out the output buffer
* @param in the first input buffer
* @param in2 the second output buffer
* @param length the length of the three buffers
*/
inline void xor_buf(uint8_t out[],
const uint8_t in[],
const uint8_t in2[],
size_t length)
{
while(length >= 16)
{
uint64_t x0, x1, y0, y1;
std::memcpy(&x0, in, 8);
std::memcpy(&x1, in + 8, 8);
std::memcpy(&y0, in2, 8);
std::memcpy(&y1, in2 + 8, 8);
x0 ^= y0;
x1 ^= y1;
std::memcpy(out, &x0, 8);
std::memcpy(out + 8, &x1, 8);
out += 16; in += 16; in2 += 16; length -= 16;
}
for(size_t i = 0; i != length; ++i)
out[i] = in[i] ^ in2[i];
}
template<typename Alloc, typename Alloc2>
void xor_buf(std::vector<uint8_t, Alloc>& out,
const std::vector<uint8_t, Alloc2>& in,
size_t n)
{
xor_buf(out.data(), in.data(), n);
}
template<typename Alloc>
void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
size_t n)
{
xor_buf(out.data(), in, n);
}
template<typename Alloc, typename Alloc2>
void xor_buf(std::vector<uint8_t, Alloc>& out,
const uint8_t* in,
const std::vector<uint8_t, Alloc2>& in2,
size_t n)
{
xor_buf(out.data(), in, in2.data(), n);
}
template<typename Alloc, typename Alloc2>
std::vector<uint8_t, Alloc>&
operator^=(std::vector<uint8_t, Alloc>& out,
const std::vector<uint8_t, Alloc2>& in)
{
if(out.size() < in.size())
out.resize(in.size());
xor_buf(out.data(), in.data(), in.size());
return out;
}
}
#endif
|