Botan 2.19.5 Crypto and TLS for C&

Classes | Functions
Botan::CT Namespace Reference

## Classes
class | Mask

## Functions
template<typename T >
Mask< T > | conditional_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

Definition at line 363 of file ct_utils.h.

368 {
369 const auto mask = CT::Mask<T>::expand(cnd);
370 mask.select_n(to, from0, from1, elems);
371 return mask;
372 }
Botan::CT::Mask
Definition: ct_utils.h:88

References 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(), Botan::bigint_sub_abs(), and Botan::BigInt::mod_add().

## ◆ 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 }
T
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)
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 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 }
Botan::CT::Mask::if_set_zero_out
void if_set_zero_out(T buf[], size_t elems)
Definition: ct_utils.h:322
Botan::CT::unpoison
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59
Botan::secure_vector
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 }
BOTAN_UNUSED
#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 }
Botan::CT::strip_leading_zeros
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 }
Botan::CT::copy_output
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

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 }

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_cmp(), Botan::BigInt::const_time_lookup(), copy_output(), 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(), Botan::BigInt::top_bits_free(), Botan::PKCS7_Padding::unpad(), Botan::ANSI_X923_Padding::unpad(), Botan::OneAndZeros_Padding::unpad(), Botan::ESP_Padding::unpad(), Botan::EME_PKCS1v15::unpad(), 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 }

References BOTAN_UNUSED, and T.