The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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 */
30static 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 */
38static 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 */
47static 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 */
54static 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 */
76static 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 */
98static 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 */
113static 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 */
128static 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 */
141static 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 */
160static 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
171static 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