Botan  2.11.0
Crypto and TLS for C++11
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 uint8_t in[], size_t length)
 
secure_vector< uint8_t > strip_leading_zeros (const secure_vector< uint8_t > &in)
 
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

Definition at line 339 of file ct_utils.h.

344  {
345  const auto mask = CT::Mask<T>::expand(cnd);
346  mask.select_n(to, from0, from1, elems);
347  return mask;
348  }
size_t elems
Definition: mem_ops.h:33

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

Referenced by Botan::bigint_monty_redc_16(), Botan::bigint_monty_redc_24(), Botan::bigint_monty_redc_32(), Botan::bigint_monty_redc_4(), Botan::bigint_monty_redc_6(), Botan::bigint_monty_redc_8(), and Botan::bigint_sub_abs().

◆ conditional_swap()

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

Definition at line 351 of file ct_utils.h.

352  {
353  const auto swap = CT::Mask<T>::expand(cnd);
354 
355  T t0 = swap.select(y, x);
356  T t1 = swap.select(x, y);
357  x = t0;
358  y = t1;
359  }
const botan_mp_t x
Definition: ffi.h:823
const uint8_t * y
Definition: ffi.h:139
fe T
Definition: ge.cpp:37

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

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 362 of file ct_utils.h.

363  {
364  uintptr_t xp = reinterpret_cast<uintptr_t>(x);
365  uintptr_t yp = reinterpret_cast<uintptr_t>(y);
366 
367  conditional_swap<uintptr_t>(cnd, xp, yp);
368 
369  x = reinterpret_cast<T>(xp);
370  y = reinterpret_cast<T>(yp);
371  }
const botan_mp_t x
Definition: ffi.h:823
const uint8_t * y
Definition: ffi.h:139

References Botan::x, and Botan::y.

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)
19  return secure_vector<uint8_t>();
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  /*
55  This is potentially not const time, depending on how std::vector is
56  implemented. But since we are always reducing length, it should
57  just amount to setting the member var holding the length.
58  */
59  CT::unpoison(output.data(), output.size());
60  CT::unpoison(output_bytes);
61  output.resize(output_bytes);
62  return output;
63  }
uint32_t uint8_t output[]
Definition: ffi.h:512
bool BigInt BigInt size_t size_t const std::vector< uint8_t > size_t offset
Definition: numthry.h:271
bool const OID & b
Definition: asn1_oid.h:109
size_t const uint8_t size_t input_length
Definition: base32.h:30
size_t const uint8_t input[]
Definition: base32.h:30
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59

References Botan::b, Botan::CT::Mask< T >::if_set_zero_out(), Botan::input, Botan::input_length, Botan::CT::Mask< T >::is_equal(), Botan::CT::Mask< T >::is_lte(), Botan::offset, Botan::output, and unpoison().

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

◆ 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  }
botan_rng_t size_t n
Definition: ffi.h:955
size_t const char const uint8_t size_t size_t size_t size_t p
Definition: ffi.h:628
#define BOTAN_UNUSED(...)
Definition: assert.h:142
fe T
Definition: ge.cpp:37

References BOTAN_UNUSED, Botan::n, Botan::p, and T.

Referenced by Botan::ct_inverse_mod_odd_modulus(), Botan::curve25519_donna(), Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption::finish(), and Botan::oaep_find_delim().

◆ strip_leading_zeros() [1/2]

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

Definition at line 65 of file ct_utils.cpp.

66  {
67  size_t leading_zeros = 0;
68 
69  auto only_zeros = Mask<uint8_t>::set();
70 
71  for(size_t i = 0; i != length; ++i)
72  {
73  only_zeros &= CT::Mask<uint8_t>::is_zero(in[i]);
74  leading_zeros += only_zeros.if_set_return(1);
75  }
76 
77  return copy_output(CT::Mask<uint8_t>::cleared(), in, length, leading_zeros);
78  }
const uint8_t * in
Definition: ffi.h:297
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::in, Botan::CT::Mask< T >::is_zero(), and Botan::CT::Mask< T >::set().

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

◆ strip_leading_zeros() [2/2]

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

Definition at line 385 of file ct_utils.h.

386  {
387  return strip_leading_zeros(in.data(), in.size());
388  }
secure_vector< uint8_t > strip_leading_zeros(const secure_vector< uint8_t > &in)
Definition: ct_utils.h:385
const uint8_t * in
Definition: ffi.h:297

References Botan::in, and strip_leading_zeros().

◆ unpoison() [1/2]

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

Definition at line 59 of file ct_utils.h.

60  {
61 #if defined(BOTAN_HAS_VALGRIND)
62  VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63 #else
64  BOTAN_UNUSED(p);
65  BOTAN_UNUSED(n);
66 #endif
67  }
botan_rng_t size_t n
Definition: ffi.h:955
size_t const char const uint8_t size_t size_t size_t size_t p
Definition: ffi.h:628
#define BOTAN_UNUSED(...)
Definition: assert.h:142
fe T
Definition: ge.cpp:37

References BOTAN_UNUSED, Botan::n, Botan::p, and T.

Referenced by Botan::bigint_cmp(), copy_output(), Botan::ct_inverse_mod_odd_modulus(), Botan::curve25519_donna(), Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption::finish(), Botan::oaep_find_delim(), Botan::redc_p192(), Botan::redc_p224(), Botan::redc_p256(), Botan::redc_p384(), Botan::CT::Mask< T >::select_and_unpoison(), and Botan::CT::Mask< T >::unpoisoned_value().

◆ 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  }
size_t const char const uint8_t size_t size_t size_t size_t p
Definition: ffi.h:628
#define BOTAN_UNUSED(...)
Definition: assert.h:142
fe T
Definition: ge.cpp:37

References BOTAN_UNUSED, Botan::p, and T.