2 * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #ifndef HEADER_CONSTANT_TIME_LOCL_H
11 # define HEADER_CONSTANT_TIME_LOCL_H
15 # include <openssl/e_os2.h> /* For 'ossl_inline' */
22 * The boolean methods return a bitmask of all ones (0xff...f) for true
23 * and 0 for false. This is useful for choosing a value based on the result
24 * of a conditional in constant time. For example,
31 * unsigned int lt = constant_time_lt(a, b);
32 * c = constant_time_select(lt, a, b);
35 /* Returns the given value with the MSB copied to all the other bits. */
36 static ossl_inline unsigned int constant_time_msb(unsigned int a);
37 /* Convenience method for uint32_t. */
38 static ossl_inline uint32_t constant_time_msb_32(uint32_t a);
39 /* Convenience method for uint64_t. */
40 static ossl_inline uint64_t constant_time_msb_64(uint64_t a);
42 /* Returns 0xff..f if a < b and 0 otherwise. */
43 static ossl_inline unsigned int constant_time_lt(unsigned int a,
45 /* Convenience method for getting an 8-bit mask. */
46 static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
48 /* Convenience method for uint64_t. */
49 static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b);
51 /* Returns 0xff..f if a >= b and 0 otherwise. */
52 static ossl_inline unsigned int constant_time_ge(unsigned int a,
54 /* Convenience method for getting an 8-bit mask. */
55 static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
58 /* Returns 0xff..f if a == 0 and 0 otherwise. */
59 static ossl_inline unsigned int constant_time_is_zero(unsigned int a);
60 /* Convenience method for getting an 8-bit mask. */
61 static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a);
62 /* Convenience method for getting a 32-bit mask. */
63 static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a);
65 /* Returns 0xff..f if a == b and 0 otherwise. */
66 static ossl_inline unsigned int constant_time_eq(unsigned int a,
68 /* Convenience method for getting an 8-bit mask. */
69 static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
71 /* Signed integers. */
72 static ossl_inline unsigned int constant_time_eq_int(int a, int b);
73 /* Convenience method for getting an 8-bit mask. */
74 static ossl_inline unsigned char constant_time_eq_int_8(int a, int b);
77 * Returns (mask & a) | (~mask & b).
79 * When |mask| is all 1s or all 0s (as returned by the methods above),
80 * the select methods return either |a| (if |mask| is nonzero) or |b|
81 * (if |mask| is zero).
83 static ossl_inline unsigned int constant_time_select(unsigned int mask,
86 /* Convenience method for unsigned chars. */
87 static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
91 /* Convenience method for uint32_t. */
92 static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
95 /* Convenience method for uint64_t. */
96 static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
98 /* Convenience method for signed integers. */
99 static ossl_inline int constant_time_select_int(unsigned int mask, int a,
103 static ossl_inline unsigned int constant_time_msb(unsigned int a)
105 return 0 - (a >> (sizeof(a) * 8 - 1));
109 static ossl_inline uint32_t constant_time_msb_32(uint32_t a)
111 return 0 - (a >> 31);
114 static ossl_inline uint64_t constant_time_msb_64(uint64_t a)
116 return 0 - (a >> 63);
119 static ossl_inline size_t constant_time_msb_s(size_t a)
121 return 0 - (a >> (sizeof(a) * 8 - 1));
124 static ossl_inline unsigned int constant_time_lt(unsigned int a,
127 return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
130 static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
132 return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
135 static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
138 return (unsigned char)constant_time_lt(a, b);
141 static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b)
143 return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b)));
146 static ossl_inline unsigned int constant_time_ge(unsigned int a,
149 return ~constant_time_lt(a, b);
152 static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
154 return ~constant_time_lt_s(a, b);
157 static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
160 return (unsigned char)constant_time_ge(a, b);
163 static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
165 return (unsigned char)constant_time_ge_s(a, b);
168 static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
170 return constant_time_msb(~a & (a - 1));
173 static ossl_inline size_t constant_time_is_zero_s(size_t a)
175 return constant_time_msb_s(~a & (a - 1));
178 static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
180 return (unsigned char)constant_time_is_zero(a);
183 static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
185 return constant_time_msb_32(~a & (a - 1));
188 static ossl_inline unsigned int constant_time_eq(unsigned int a,
191 return constant_time_is_zero(a ^ b);
194 static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
196 return constant_time_is_zero_s(a ^ b);
199 static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
202 return (unsigned char)constant_time_eq(a, b);
205 static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
207 return (unsigned char)constant_time_eq_s(a, b);
210 static ossl_inline unsigned int constant_time_eq_int(int a, int b)
212 return constant_time_eq((unsigned)(a), (unsigned)(b));
215 static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
217 return constant_time_eq_8((unsigned)(a), (unsigned)(b));
220 static ossl_inline unsigned int constant_time_select(unsigned int mask,
224 return (mask & a) | (~mask & b);
227 static ossl_inline size_t constant_time_select_s(size_t mask,
231 return (mask & a) | (~mask & b);
234 static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
238 return (unsigned char)constant_time_select(mask, a, b);
241 static ossl_inline int constant_time_select_int(unsigned int mask, int a,
244 return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b));
247 static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
249 return (int)constant_time_select((unsigned)mask, (unsigned)(a),
253 static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
256 return (mask & a) | (~mask & b);
259 static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
262 return (mask & a) | (~mask & b);
266 * mask must be 0xFFFFFFFF or 0x00000000.
275 static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a,
278 uint32_t xor = *a ^ *b;
286 * mask must be 0xFFFFFFFF or 0x00000000.
295 static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
298 uint64_t xor = *a ^ *b;
306 * table is a two dimensional array of bytes. Each row has rowsize elements.
307 * Copies row number idx into out. rowsize and numrows are not considered
310 static ossl_inline void constant_time_lookup(void *out,
317 const unsigned char *tablec = (const unsigned char *)table;
318 unsigned char *outc = (unsigned char *)out;
321 memset(out, 0, rowsize);
323 /* Note idx may underflow - but that is well defined */
324 for (i = 0; i < numrows; i++, idx--) {
325 mask = (unsigned char)constant_time_is_zero_s(idx);
326 for (j = 0; j < rowsize; j++)
327 *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0);
335 #endif /* HEADER_CONSTANT_TIME_LOCL_H */