1
13
14
15
16
17
18
19
22
23
24
25
26
31
36
37
38
39
40
45
46
47
48
52
53
54
55
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
99
100
101
105
106
107
114
115
120
121
122
129
133
134
135
142
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
170
171
172
173
174
175
176
177
178
179
180
181
187
188
189
190
191
/* ... */
#ifndef CONST_TIME_H
#define CONST_TIME_H
#if defined(__clang__)
#define NO_UBSAN_UINT_OVERFLOW \
__attribute__((no_sanitize("unsigned-integer-overflow")))...
/* ... */#else
#define NO_UBSAN_UINT_OVERFLOW
#endif
/* ... */
static inline unsigned int const_time_fill_msb(unsigned int val)
{
return (val >> (sizeof(val) * 8 - 1)) * ~0U;
}{ ... }
static inline unsigned int const_time_is_zero(unsigned int val)
NO_UBSAN_UINT_OVERFLOW
{
return const_time_fill_msb(~val & (val - 1));
}{...}
static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
{
return const_time_is_zero(a ^ b);
}{ ... }
static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
{
return (u8) const_time_eq(a, b);
}{ ... }
/* ... */
static inline unsigned int const_time_eq_bin(const void *a, const void *b,
size_t len)
{
const u8 *aa = a;
const u8 *bb = b;
size_t i;
u8 res = 0;
for (i = 0; i < len; i++)
res |= aa[i] ^ bb[i];
return const_time_is_zero(res);
}{ ... }
/* ... */
static inline unsigned int const_time_select(unsigned int mask,
unsigned int true_val,
unsigned int false_val)
{
return (mask & true_val) | (~mask & false_val);
}{ ... }
/* ... */
static inline int const_time_select_int(unsigned int mask, int true_val,
int false_val)
{
return (int) const_time_select(mask, (unsigned int) true_val,
(unsigned int) false_val);
}{ ... }
/* ... */
static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
{
return (u8) const_time_select(mask, true_val, false_val);
}{ ... }
/* ... */
static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
{
return (s8) const_time_select(mask, (unsigned int) true_val,
(unsigned int) false_val);
}{ ... }
/* ... */
static inline void const_time_select_bin(u8 mask, const u8 *true_val,
const u8 *false_val, size_t len,
u8 *dst)
{
size_t i;
for (i = 0; i < len; i++)
dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
}{ ... }
static inline int const_time_memcmp(const void *a, const void *b, size_t len)
{
const u8 *aa = a;
const u8 *bb = b;
int diff, res = 0;
unsigned int mask;
if (len == 0)
return 0;
do {
len--;
diff = (int) aa[len] - (int) bb[len];
mask = const_time_is_zero((unsigned int) diff);
res = const_time_select_int(mask, res, diff);
}{...} while (len);
return res;
}{ ... }
/* ... */#endif