Botan 2.19.1
Crypto and TLS for C&
Classes | Functions
Botan::CT Namespace Reference

Classes

class  Mask
 

Functions

template<typename T >
Mask< Tconditional_copy_mem (T cnd, T *to, const T *from0, const T *from1, size_t elems)
 
template<typename T >
void conditional_swap (bool cnd, T &x, T &y)
 
template<typename T >
void conditional_swap_ptr (bool cnd, T &x, T &y)
 
secure_vector< uint8_t > copy_output (CT::Mask< uint8_t > bad_input, const uint8_t input[], size_t input_length, size_t offset)
 
template<typename T >
void poison (const T *p, size_t n)
 
secure_vector< uint8_t > strip_leading_zeros (const secure_vector< uint8_t > &in)
 
secure_vector< uint8_t > strip_leading_zeros (const uint8_t in[], size_t length)
 
template<typename T >
void unpoison (const T *p, size_t n)
 
template<typename T >
void unpoison (T &p)
 

Function Documentation

◆ conditional_copy_mem()

template<typename T >
Mask< T > Botan::CT::conditional_copy_mem ( T  cnd,
T to,
const T from0,
const T from1,
size_t  elems 
)
inline

◆ conditional_swap()

template<typename T >
void Botan::CT::conditional_swap ( bool  cnd,
T x,
T y 
)
inline

Definition at line 375 of file ct_utils.h.

376 {
377 const auto swap = CT::Mask<T>::expand(cnd);
378
379 T t0 = swap.select(y, x);
380 T t1 = swap.select(x, y);
381 x = t0;
382 y = t1;
383 }
fe T
Definition: ge.cpp:37

References Botan::CT::Mask< T >::expand(), and T.

Referenced by Botan::bigint_sub_abs().

◆ conditional_swap_ptr()

template<typename T >
void Botan::CT::conditional_swap_ptr ( bool  cnd,
T x,
T y 
)
inline

Definition at line 386 of file ct_utils.h.

387 {
388 uintptr_t xp = reinterpret_cast<uintptr_t>(x);
389 uintptr_t yp = reinterpret_cast<uintptr_t>(y);
390
391 conditional_swap<uintptr_t>(cnd, xp, yp);
392
393 x = reinterpret_cast<T>(xp);
394 y = reinterpret_cast<T>(yp);
395 }

References T.

Referenced by Botan::bigint_sub_abs().

◆ copy_output()

secure_vector< uint8_t > Botan::CT::copy_output ( CT::Mask< uint8_t >  bad_input,
const uint8_t  input[],
size_t  input_length,
size_t  delim_idx 
)

If bad_mask is unset, return in[delim_idx:input_length] copied to new buffer. If bad_mask is set, return an all zero vector of unspecified length.

Definition at line 13 of file ct_utils.cpp.

17 {
18 if(input_length == 0)
20
21 /*
22 * Ensure at runtime that offset <= input_length. This is an invalid input,
23 * but we can't throw without using the poisoned value. Instead, if it happens,
24 * set offset to be equal to the input length (so output_bytes becomes 0 and
25 * the returned vector is empty)
26 */
27 const auto valid_offset = CT::Mask<size_t>::is_lte(offset, input_length);
28 offset = valid_offset.select(offset, input_length);
29
30 const size_t output_bytes = input_length - offset;
31
32 secure_vector<uint8_t> output(input_length);
33
34 /*
35 Move the desired output bytes to the front using a slow (O^n)
36 but constant time loop that does not leak the value of the offset
37 */
38 for(size_t i = 0; i != input_length; ++i)
39 {
40 /*
41 start index from i rather than 0 since we know j must be >= i + offset
42 to have any effect, and starting from i does not reveal information
43 */
44 for(size_t j = i; j != input_length; ++j)
45 {
46 const uint8_t b = input[j];
47 const auto is_eq = CT::Mask<size_t>::is_equal(j, offset + i);
48 output[i] |= is_eq.if_set_return(b);
49 }
50 }
51
52 bad_input.if_set_zero_out(output.data(), output.size());
53
54 CT::unpoison(output.data(), output.size());
55 CT::unpoison(output_bytes);
56
57 /*
58 This is potentially not const time, depending on how std::vector is
59 implemented. But since we are always reducing length, it should
60 just amount to setting the member var holding the length.
61 */
62 output.resize(output_bytes);
63 return output;
64 }
void if_set_zero_out(T buf[], size_t elems)
Definition: ct_utils.h:322
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65

References Botan::CT::Mask< T >::if_set_zero_out(), Botan::CT::Mask< T >::is_equal(), Botan::CT::Mask< T >::is_lte(), and unpoison().

Referenced by Botan::oaep_find_delim(), strip_leading_zeros(), and Botan::EME_PKCS1v15::unpad().

◆ poison()

template<typename T >
void Botan::CT::poison ( const T p,
size_t  n 
)
inline

Use valgrind to mark the contents of memory as being undefined. Valgrind will accept operations which manipulate undefined values, but will warn if an undefined value is used to decided a conditional jump or a load/store address. So if we poison all of our inputs we can confirm that the operations in question are truly const time when compiled by whatever compiler is in use.

Even better, the VALGRIND_MAKE_MEM_* macros work even when the program is not run under valgrind (though with a few cycles of overhead, which is unfortunate in final binaries as these annotations tend to be used in fairly important loops).

This approach was first used in ctgrind (https://github.com/agl/ctgrind) but calling the valgrind mecheck API directly works just as well and doesn't require a custom patched valgrind.

Definition at line 48 of file ct_utils.h.

49 {
50#if defined(BOTAN_HAS_VALGRIND)
51 VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52#else
53 BOTAN_UNUSED(p);
54 BOTAN_UNUSED(n);
55#endif
56 }
#define BOTAN_UNUSED(...)
Definition: assert.h:142

References BOTAN_UNUSED, and T.

Referenced by Botan::PKCS7_Padding::add_padding(), Botan::ANSI_X923_Padding::add_padding(), Botan::OneAndZeros_Padding::add_padding(), Botan::ESP_Padding::add_padding(), Botan::BigInt::const_time_lookup(), Botan::curve25519_donna(), Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption::finish(), Botan::oaep_find_delim(), Botan::PKCS7_Padding::unpad(), Botan::ANSI_X923_Padding::unpad(), Botan::OneAndZeros_Padding::unpad(), Botan::ESP_Padding::unpad(), and Botan::EME_PKCS1v15::unpad().

◆ strip_leading_zeros() [1/2]

secure_vector< uint8_t > Botan::CT::strip_leading_zeros ( const secure_vector< uint8_t > &  in)
inline

Definition at line 409 of file ct_utils.h.

410 {
411 return strip_leading_zeros(in.data(), in.size());
412 }
secure_vector< uint8_t > strip_leading_zeros(const secure_vector< uint8_t > &in)
Definition: ct_utils.h:409

References strip_leading_zeros().

◆ strip_leading_zeros() [2/2]

secure_vector< uint8_t > Botan::CT::strip_leading_zeros ( const uint8_t  in[],
size_t  length 
)

Definition at line 66 of file ct_utils.cpp.

67 {
68 size_t leading_zeros = 0;
69
70 auto only_zeros = Mask<uint8_t>::set();
71
72 for(size_t i = 0; i != length; ++i)
73 {
74 only_zeros &= CT::Mask<uint8_t>::is_zero(in[i]);
75 leading_zeros += only_zeros.if_set_return(1);
76 }
77
78 return copy_output(CT::Mask<uint8_t>::cleared(), in, length, leading_zeros);
79 }
secure_vector< uint8_t > copy_output(CT::Mask< uint8_t > bad_input, const uint8_t input[], size_t input_length, size_t offset)
Definition: ct_utils.cpp:13

References copy_output(), Botan::CT::Mask< T >::is_zero(), and Botan::CT::Mask< T >::set().

Referenced by Botan::TLS::Client_Key_Exchange::Client_Key_Exchange(), strip_leading_zeros(), and Botan::TLS::Callbacks::tls_dh_agree().

◆ unpoison() [1/2]

template<typename T >
void Botan::CT::unpoison ( const T p,
size_t  n 
)
inline

◆ unpoison() [2/2]

template<typename T >
void Botan::CT::unpoison ( T p)
inline

Definition at line 70 of file ct_utils.h.

71 {
72#if defined(BOTAN_HAS_VALGRIND)
73 VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74#else
75 BOTAN_UNUSED(p);
76#endif
77 }

References BOTAN_UNUSED, and T.