The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
const_time.h
Go to the documentation of this file.
1 /*
2  * Helper functions for constant time operations
3  * Copyright (c) 2019, The Linux Foundation
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  *
8  * These helper functions can be used to implement logic that needs to minimize
9  * externally visible differences in execution path by avoiding use of branches,
10  * avoiding early termination or other time differences, and forcing same memory
11  * access pattern regardless of values.
12  */
13 
14 #ifndef CONST_TIME_H
15 #define CONST_TIME_H
16 
17 
18 #if defined(__clang__)
19 #define NO_UBSAN_UINT_OVERFLOW \
20  __attribute__((no_sanitize("unsigned-integer-overflow")))
21 #else
22 #define NO_UBSAN_UINT_OVERFLOW
23 #endif
24 
25 /**
26  * const_time_fill_msb - Fill all bits with MSB value
27  * @param val Input value
28  * @return Value with all the bits set to the MSB of the input val
29  */
30 static inline unsigned int const_time_fill_msb(unsigned int val)
31 {
32  /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
33  return (val >> (sizeof(val) * 8 - 1)) * ~0U;
34 }
35 
36 
37 /* @return -1 if val is zero; 0 if val is not zero */
38 static inline unsigned int const_time_is_zero(unsigned int val)
40 {
41  /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
42  return const_time_fill_msb(~val & (val - 1));
43 }
44 
45 
46 /* @return -1 if a == b; 0 if a != b */
47 static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
48 {
49  return const_time_is_zero(a ^ b);
50 }
51 
52 
53 /* @return -1 if a == b; 0 if a != b */
54 static inline unsigned char const_time_eq_u8(unsigned int a, unsigned int b)
55 {
56  return (unsigned char) const_time_eq(a, b);
57 }
58 
59 
60 /**
61  * const_time_eq_bin - Constant time memory comparison
62  * @param a First buffer to compare
63  * @param b Second buffer to compare
64  * @param len Number of octets to compare
65  * @return -1 if buffers are equal, 0 if not
66  *
67  * This function is meant for comparing passwords or hash values where
68  * difference in execution time or memory access pattern could provide external
69  * observer information about the location of the difference in the memory
70  * buffers. The return value does not behave like memcmp(), i.e.,
71  * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
72  * memcmp(), the execution time of const_time_eq_bin() does not depend on the
73  * contents of the compared memory buffers, but only on the total compared
74  * length.
75  */
76 static inline unsigned int const_time_eq_bin(const void *a, const void *b,
77  size_t len)
78 {
79  const unsigned char *aa = a;
80  const unsigned char *bb = b;
81  size_t i;
82  unsigned char res = 0;
83 
84  for (i = 0; i < len; i++)
85  res |= aa[i] ^ bb[i];
86 
87  return const_time_is_zero(res);
88 }
89 
90 
91 /**
92  * const_time_select - Constant time unsigned int selection
93  * @param mask 0 (false) or -1 (true) to identify which value to select
94  * @param true_val Value to select for the true case
95  * @param false_val Value to select for the false case
96  * @return true_val if mask == -1, false_val if mask == 0
97  */
98 static inline unsigned int const_time_select(unsigned int mask,
99  unsigned int true_val,
100  unsigned int false_val)
101 {
102  return (mask & true_val) | (~mask & false_val);
103 }
104 
105 
106 /**
107  * const_time_select_int - Constant time int selection
108  * @param mask 0 (false) or -1 (true) to identify which value to select
109  * @param true_val Value to select for the true case
110  * @param false_val Value to select for the false case
111  * @return true_val if mask == -1, false_val if mask == 0
112  */
113 static inline int const_time_select_int(unsigned int mask, int true_val,
114  int false_val)
115 {
116  return (int) const_time_select(mask, (unsigned int) true_val,
117  (unsigned int) false_val);
118 }
119 
120 
121 /**
122  * const_time_select_u8 - Constant time u8 selection
123  * @param mask 0 (false) or -1 (true) to identify which value to select
124  * @param true_val Value to select for the true case
125  * @param false_val Value to select for the false case
126  * @return true_val if mask == -1, false_val if mask == 0
127  */
128 static inline unsigned char const_time_select_u8(unsigned char mask, unsigned char true_val, unsigned char false_val)
129 {
130  return (unsigned char) const_time_select(mask, true_val, false_val);
131 }
132 
133 
134 /**
135  * const_time_select_s8 - Constant time s8 selection
136  * @param mask 0 (false) or -1 (true) to identify which value to select
137  * @param true_val Value to select for the true case
138  * @param false_val Value to select for the false case
139  * @return true_val if mask == -1, false_val if mask == 0
140  */
141 static inline char const_time_select_s8(char mask, char true_val, char false_val)
142 {
143  return (char) const_time_select(mask, (unsigned int) true_val,
144  (unsigned int) false_val);
145 }
146 
147 
148 /**
149  * const_time_select_bin - Constant time binary buffer selection copy
150  * @param mask 0 (false) or -1 (true) to identify which value to copy
151  * @param true_val Buffer to copy for the true case
152  * @param false_val Buffer to copy for the false case
153  * @param len Number of octets to copy
154  * @param dst Destination buffer for the copy
155  *
156  * This function copies the specified buffer into the destination buffer using
157  * operations with identical memory access pattern regardless of which buffer
158  * is being copied.
159  */
160 static inline void const_time_select_bin(unsigned char mask, const unsigned char *true_val,
161  const unsigned char *false_val, size_t len,
162  unsigned char *dst)
163 {
164  size_t i;
165 
166  for (i = 0; i < len; i++)
167  dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
168 }
169 
170 
171 static inline int const_time_memcmp(const void *a, const void *b, size_t len)
172 {
173  const unsigned char *aa = a;
174  const unsigned char *bb = b;
175  int diff, res = 0;
176  unsigned int mask;
177 
178  if (len == 0)
179  return 0;
180  do {
181  len--;
182  diff = (int) aa[len] - (int) bb[len];
183  mask = const_time_is_zero((unsigned int) diff);
184  res = const_time_select_int(mask, res, diff);
185  } while (len);
186 
187  return res;
188 }
189 
190 #endif /* CONST_TIME_H */
#define NO_UBSAN_UINT_OVERFLOW
Definition: const_time.h:22
static int const_time_select_int(unsigned int mask, int true_val, int false_val)
const_time_select_int - Constant time int selection
Definition: const_time.h:113
static char const_time_select_s8(char mask, char true_val, char false_val)
const_time_select_s8 - Constant time s8 selection
Definition: const_time.h:141
static void const_time_select_bin(unsigned char mask, const unsigned char *true_val, const unsigned char *false_val, size_t len, unsigned char *dst)
const_time_select_bin - Constant time binary buffer selection copy
Definition: const_time.h:160
static unsigned char const_time_eq_u8(unsigned int a, unsigned int b)
Definition: const_time.h:54
static unsigned int const_time_is_zero(unsigned int val) NO_UBSAN_UINT_OVERFLOW
Definition: const_time.h:38
static unsigned char const_time_select_u8(unsigned char mask, unsigned char true_val, unsigned char false_val)
const_time_select_u8 - Constant time u8 selection
Definition: const_time.h:128
static unsigned int const_time_eq(unsigned int a, unsigned int b)
Definition: const_time.h:47
static int const_time_memcmp(const void *a, const void *b, size_t len)
Definition: const_time.h:171
static unsigned int const_time_fill_msb(unsigned int val)
const_time_fill_msb - Fill all bits with MSB value
Definition: const_time.h:30
static unsigned int const_time_eq_bin(const void *a, const void *b, size_t len)
const_time_eq_bin - Constant time memory comparison
Definition: const_time.h:76
static unsigned int const_time_select(unsigned int mask, unsigned int true_val, unsigned int false_val)
const_time_select - Constant time unsigned int selection
Definition: const_time.h:98
static uint32_t mask
Definition: rbmonkey.c:39