xref: /freebsd-src/crypto/openssl/include/internal/constant_time.h (revision 17f01e9963948a18f55eb97173123702c5dae671)
1*17f01e99SJung-uk Kim /*
2*17f01e99SJung-uk Kim  * Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
3*17f01e99SJung-uk Kim  *
4*17f01e99SJung-uk Kim  * Licensed under the OpenSSL license (the "License").  You may not use
5*17f01e99SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6*17f01e99SJung-uk Kim  * in the file LICENSE in the source distribution or at
7*17f01e99SJung-uk Kim  * https://www.openssl.org/source/license.html
8*17f01e99SJung-uk Kim  */
9*17f01e99SJung-uk Kim 
10*17f01e99SJung-uk Kim #ifndef OSSL_INTERNAL_CONSTANT_TIME_H
11*17f01e99SJung-uk Kim # define OSSL_INTERNAL_CONSTANT_TIME_H
12*17f01e99SJung-uk Kim 
13*17f01e99SJung-uk Kim # include <stdlib.h>
14*17f01e99SJung-uk Kim # include <string.h>
15*17f01e99SJung-uk Kim # include <openssl/e_os2.h>              /* For 'ossl_inline' */
16*17f01e99SJung-uk Kim 
17*17f01e99SJung-uk Kim /*-
18*17f01e99SJung-uk Kim  * The boolean methods return a bitmask of all ones (0xff...f) for true
19*17f01e99SJung-uk Kim  * and 0 for false. This is useful for choosing a value based on the result
20*17f01e99SJung-uk Kim  * of a conditional in constant time. For example,
21*17f01e99SJung-uk Kim  *      if (a < b) {
22*17f01e99SJung-uk Kim  *        c = a;
23*17f01e99SJung-uk Kim  *      } else {
24*17f01e99SJung-uk Kim  *        c = b;
25*17f01e99SJung-uk Kim  *      }
26*17f01e99SJung-uk Kim  * can be written as
27*17f01e99SJung-uk Kim  *      unsigned int lt = constant_time_lt(a, b);
28*17f01e99SJung-uk Kim  *      c = constant_time_select(lt, a, b);
29*17f01e99SJung-uk Kim  */
30*17f01e99SJung-uk Kim 
31*17f01e99SJung-uk Kim /* Returns the given value with the MSB copied to all the other bits. */
32*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_msb(unsigned int a);
33*17f01e99SJung-uk Kim /* Convenience method for uint32_t. */
34*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_msb_32(uint32_t a);
35*17f01e99SJung-uk Kim /* Convenience method for uint64_t. */
36*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_msb_64(uint64_t a);
37*17f01e99SJung-uk Kim 
38*17f01e99SJung-uk Kim /* Returns 0xff..f if a < b and 0 otherwise. */
39*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_lt(unsigned int a,
40*17f01e99SJung-uk Kim                                                  unsigned int b);
41*17f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */
42*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
43*17f01e99SJung-uk Kim                                                     unsigned int b);
44*17f01e99SJung-uk Kim /* Convenience method for uint64_t. */
45*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b);
46*17f01e99SJung-uk Kim 
47*17f01e99SJung-uk Kim /* Returns 0xff..f if a >= b and 0 otherwise. */
48*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_ge(unsigned int a,
49*17f01e99SJung-uk Kim                                                  unsigned int b);
50*17f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */
51*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
52*17f01e99SJung-uk Kim                                                     unsigned int b);
53*17f01e99SJung-uk Kim 
54*17f01e99SJung-uk Kim /* Returns 0xff..f if a == 0 and 0 otherwise. */
55*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_is_zero(unsigned int a);
56*17f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */
57*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a);
58*17f01e99SJung-uk Kim /* Convenience method for getting a 32-bit mask. */
59*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a);
60*17f01e99SJung-uk Kim 
61*17f01e99SJung-uk Kim /* Returns 0xff..f if a == b and 0 otherwise. */
62*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq(unsigned int a,
63*17f01e99SJung-uk Kim                                                  unsigned int b);
64*17f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */
65*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
66*17f01e99SJung-uk Kim                                                     unsigned int b);
67*17f01e99SJung-uk Kim /* Signed integers. */
68*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq_int(int a, int b);
69*17f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */
70*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_int_8(int a, int b);
71*17f01e99SJung-uk Kim 
72*17f01e99SJung-uk Kim /*-
73*17f01e99SJung-uk Kim  * Returns (mask & a) | (~mask & b).
74*17f01e99SJung-uk Kim  *
75*17f01e99SJung-uk Kim  * When |mask| is all 1s or all 0s (as returned by the methods above),
76*17f01e99SJung-uk Kim  * the select methods return either |a| (if |mask| is nonzero) or |b|
77*17f01e99SJung-uk Kim  * (if |mask| is zero).
78*17f01e99SJung-uk Kim  */
79*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_select(unsigned int mask,
80*17f01e99SJung-uk Kim                                                      unsigned int a,
81*17f01e99SJung-uk Kim                                                      unsigned int b);
82*17f01e99SJung-uk Kim /* Convenience method for unsigned chars. */
83*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
84*17f01e99SJung-uk Kim                                                         unsigned char a,
85*17f01e99SJung-uk Kim                                                         unsigned char b);
86*17f01e99SJung-uk Kim 
87*17f01e99SJung-uk Kim /* Convenience method for uint32_t. */
88*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
89*17f01e99SJung-uk Kim                                                     uint32_t b);
90*17f01e99SJung-uk Kim 
91*17f01e99SJung-uk Kim /* Convenience method for uint64_t. */
92*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
93*17f01e99SJung-uk Kim                                                     uint64_t b);
94*17f01e99SJung-uk Kim /* Convenience method for signed integers. */
95*17f01e99SJung-uk Kim static ossl_inline int constant_time_select_int(unsigned int mask, int a,
96*17f01e99SJung-uk Kim                                                 int b);
97*17f01e99SJung-uk Kim 
98*17f01e99SJung-uk Kim 
99*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_msb(unsigned int a)
100*17f01e99SJung-uk Kim {
101*17f01e99SJung-uk Kim     return 0 - (a >> (sizeof(a) * 8 - 1));
102*17f01e99SJung-uk Kim }
103*17f01e99SJung-uk Kim 
104*17f01e99SJung-uk Kim 
105*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_msb_32(uint32_t a)
106*17f01e99SJung-uk Kim {
107*17f01e99SJung-uk Kim     return 0 - (a >> 31);
108*17f01e99SJung-uk Kim }
109*17f01e99SJung-uk Kim 
110*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_msb_64(uint64_t a)
111*17f01e99SJung-uk Kim {
112*17f01e99SJung-uk Kim     return 0 - (a >> 63);
113*17f01e99SJung-uk Kim }
114*17f01e99SJung-uk Kim 
115*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_msb_s(size_t a)
116*17f01e99SJung-uk Kim {
117*17f01e99SJung-uk Kim     return 0 - (a >> (sizeof(a) * 8 - 1));
118*17f01e99SJung-uk Kim }
119*17f01e99SJung-uk Kim 
120*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_lt(unsigned int a,
121*17f01e99SJung-uk Kim                                                  unsigned int b)
122*17f01e99SJung-uk Kim {
123*17f01e99SJung-uk Kim     return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
124*17f01e99SJung-uk Kim }
125*17f01e99SJung-uk Kim 
126*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
127*17f01e99SJung-uk Kim {
128*17f01e99SJung-uk Kim     return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
129*17f01e99SJung-uk Kim }
130*17f01e99SJung-uk Kim 
131*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
132*17f01e99SJung-uk Kim                                                     unsigned int b)
133*17f01e99SJung-uk Kim {
134*17f01e99SJung-uk Kim     return (unsigned char)constant_time_lt(a, b);
135*17f01e99SJung-uk Kim }
136*17f01e99SJung-uk Kim 
137*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b)
138*17f01e99SJung-uk Kim {
139*17f01e99SJung-uk Kim     return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b)));
140*17f01e99SJung-uk Kim }
141*17f01e99SJung-uk Kim 
142*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_ge(unsigned int a,
143*17f01e99SJung-uk Kim                                                  unsigned int b)
144*17f01e99SJung-uk Kim {
145*17f01e99SJung-uk Kim     return ~constant_time_lt(a, b);
146*17f01e99SJung-uk Kim }
147*17f01e99SJung-uk Kim 
148*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
149*17f01e99SJung-uk Kim {
150*17f01e99SJung-uk Kim     return ~constant_time_lt_s(a, b);
151*17f01e99SJung-uk Kim }
152*17f01e99SJung-uk Kim 
153*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
154*17f01e99SJung-uk Kim                                                     unsigned int b)
155*17f01e99SJung-uk Kim {
156*17f01e99SJung-uk Kim     return (unsigned char)constant_time_ge(a, b);
157*17f01e99SJung-uk Kim }
158*17f01e99SJung-uk Kim 
159*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
160*17f01e99SJung-uk Kim {
161*17f01e99SJung-uk Kim     return (unsigned char)constant_time_ge_s(a, b);
162*17f01e99SJung-uk Kim }
163*17f01e99SJung-uk Kim 
164*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
165*17f01e99SJung-uk Kim {
166*17f01e99SJung-uk Kim     return constant_time_msb(~a & (a - 1));
167*17f01e99SJung-uk Kim }
168*17f01e99SJung-uk Kim 
169*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_is_zero_s(size_t a)
170*17f01e99SJung-uk Kim {
171*17f01e99SJung-uk Kim     return constant_time_msb_s(~a & (a - 1));
172*17f01e99SJung-uk Kim }
173*17f01e99SJung-uk Kim 
174*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
175*17f01e99SJung-uk Kim {
176*17f01e99SJung-uk Kim     return (unsigned char)constant_time_is_zero(a);
177*17f01e99SJung-uk Kim }
178*17f01e99SJung-uk Kim 
179*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
180*17f01e99SJung-uk Kim {
181*17f01e99SJung-uk Kim     return constant_time_msb_32(~a & (a - 1));
182*17f01e99SJung-uk Kim }
183*17f01e99SJung-uk Kim 
184*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq(unsigned int a,
185*17f01e99SJung-uk Kim                                                  unsigned int b)
186*17f01e99SJung-uk Kim {
187*17f01e99SJung-uk Kim     return constant_time_is_zero(a ^ b);
188*17f01e99SJung-uk Kim }
189*17f01e99SJung-uk Kim 
190*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
191*17f01e99SJung-uk Kim {
192*17f01e99SJung-uk Kim     return constant_time_is_zero_s(a ^ b);
193*17f01e99SJung-uk Kim }
194*17f01e99SJung-uk Kim 
195*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
196*17f01e99SJung-uk Kim                                                     unsigned int b)
197*17f01e99SJung-uk Kim {
198*17f01e99SJung-uk Kim     return (unsigned char)constant_time_eq(a, b);
199*17f01e99SJung-uk Kim }
200*17f01e99SJung-uk Kim 
201*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
202*17f01e99SJung-uk Kim {
203*17f01e99SJung-uk Kim     return (unsigned char)constant_time_eq_s(a, b);
204*17f01e99SJung-uk Kim }
205*17f01e99SJung-uk Kim 
206*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq_int(int a, int b)
207*17f01e99SJung-uk Kim {
208*17f01e99SJung-uk Kim     return constant_time_eq((unsigned)(a), (unsigned)(b));
209*17f01e99SJung-uk Kim }
210*17f01e99SJung-uk Kim 
211*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
212*17f01e99SJung-uk Kim {
213*17f01e99SJung-uk Kim     return constant_time_eq_8((unsigned)(a), (unsigned)(b));
214*17f01e99SJung-uk Kim }
215*17f01e99SJung-uk Kim 
216*17f01e99SJung-uk Kim /*
217*17f01e99SJung-uk Kim  * Returns the value unmodified, but avoids optimizations.
218*17f01e99SJung-uk Kim  * The barriers prevent the compiler from narrowing down the
219*17f01e99SJung-uk Kim  * possible value range of the mask and ~mask in the select
220*17f01e99SJung-uk Kim  * statements, which avoids the recognition of the select
221*17f01e99SJung-uk Kim  * and turning it into a conditional load or branch.
222*17f01e99SJung-uk Kim  */
223*17f01e99SJung-uk Kim static ossl_inline unsigned int value_barrier(unsigned int a)
224*17f01e99SJung-uk Kim {
225*17f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
226*17f01e99SJung-uk Kim     unsigned int r;
227*17f01e99SJung-uk Kim     __asm__("" : "=r"(r) : "0"(a));
228*17f01e99SJung-uk Kim #else
229*17f01e99SJung-uk Kim     volatile unsigned int r = a;
230*17f01e99SJung-uk Kim #endif
231*17f01e99SJung-uk Kim     return r;
232*17f01e99SJung-uk Kim }
233*17f01e99SJung-uk Kim 
234*17f01e99SJung-uk Kim /* Convenience method for uint32_t. */
235*17f01e99SJung-uk Kim static ossl_inline uint32_t value_barrier_32(uint32_t a)
236*17f01e99SJung-uk Kim {
237*17f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
238*17f01e99SJung-uk Kim     uint32_t r;
239*17f01e99SJung-uk Kim     __asm__("" : "=r"(r) : "0"(a));
240*17f01e99SJung-uk Kim #else
241*17f01e99SJung-uk Kim     volatile uint32_t r = a;
242*17f01e99SJung-uk Kim #endif
243*17f01e99SJung-uk Kim     return r;
244*17f01e99SJung-uk Kim }
245*17f01e99SJung-uk Kim 
246*17f01e99SJung-uk Kim /* Convenience method for uint64_t. */
247*17f01e99SJung-uk Kim static ossl_inline uint64_t value_barrier_64(uint64_t a)
248*17f01e99SJung-uk Kim {
249*17f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
250*17f01e99SJung-uk Kim     uint64_t r;
251*17f01e99SJung-uk Kim     __asm__("" : "=r"(r) : "0"(a));
252*17f01e99SJung-uk Kim #else
253*17f01e99SJung-uk Kim     volatile uint64_t r = a;
254*17f01e99SJung-uk Kim #endif
255*17f01e99SJung-uk Kim     return r;
256*17f01e99SJung-uk Kim }
257*17f01e99SJung-uk Kim 
258*17f01e99SJung-uk Kim /* Convenience method for size_t. */
259*17f01e99SJung-uk Kim static ossl_inline size_t value_barrier_s(size_t a)
260*17f01e99SJung-uk Kim {
261*17f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
262*17f01e99SJung-uk Kim     size_t r;
263*17f01e99SJung-uk Kim     __asm__("" : "=r"(r) : "0"(a));
264*17f01e99SJung-uk Kim #else
265*17f01e99SJung-uk Kim     volatile size_t r = a;
266*17f01e99SJung-uk Kim #endif
267*17f01e99SJung-uk Kim     return r;
268*17f01e99SJung-uk Kim }
269*17f01e99SJung-uk Kim 
270*17f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_select(unsigned int mask,
271*17f01e99SJung-uk Kim                                                      unsigned int a,
272*17f01e99SJung-uk Kim                                                      unsigned int b)
273*17f01e99SJung-uk Kim {
274*17f01e99SJung-uk Kim     return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
275*17f01e99SJung-uk Kim }
276*17f01e99SJung-uk Kim 
277*17f01e99SJung-uk Kim static ossl_inline size_t constant_time_select_s(size_t mask,
278*17f01e99SJung-uk Kim                                                  size_t a,
279*17f01e99SJung-uk Kim                                                  size_t b)
280*17f01e99SJung-uk Kim {
281*17f01e99SJung-uk Kim     return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
282*17f01e99SJung-uk Kim }
283*17f01e99SJung-uk Kim 
284*17f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
285*17f01e99SJung-uk Kim                                                         unsigned char a,
286*17f01e99SJung-uk Kim                                                         unsigned char b)
287*17f01e99SJung-uk Kim {
288*17f01e99SJung-uk Kim     return (unsigned char)constant_time_select(mask, a, b);
289*17f01e99SJung-uk Kim }
290*17f01e99SJung-uk Kim 
291*17f01e99SJung-uk Kim static ossl_inline int constant_time_select_int(unsigned int mask, int a,
292*17f01e99SJung-uk Kim                                                 int b)
293*17f01e99SJung-uk Kim {
294*17f01e99SJung-uk Kim     return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b));
295*17f01e99SJung-uk Kim }
296*17f01e99SJung-uk Kim 
297*17f01e99SJung-uk Kim static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
298*17f01e99SJung-uk Kim {
299*17f01e99SJung-uk Kim     return (int)constant_time_select((unsigned)mask, (unsigned)(a),
300*17f01e99SJung-uk Kim                                       (unsigned)(b));
301*17f01e99SJung-uk Kim }
302*17f01e99SJung-uk Kim 
303*17f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
304*17f01e99SJung-uk Kim                                                     uint32_t b)
305*17f01e99SJung-uk Kim {
306*17f01e99SJung-uk Kim     return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b);
307*17f01e99SJung-uk Kim }
308*17f01e99SJung-uk Kim 
309*17f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
310*17f01e99SJung-uk Kim                                                     uint64_t b)
311*17f01e99SJung-uk Kim {
312*17f01e99SJung-uk Kim     return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b);
313*17f01e99SJung-uk Kim }
314*17f01e99SJung-uk Kim 
315*17f01e99SJung-uk Kim /*
316*17f01e99SJung-uk Kim  * mask must be 0xFFFFFFFF or 0x00000000.
317*17f01e99SJung-uk Kim  *
318*17f01e99SJung-uk Kim  * if (mask) {
319*17f01e99SJung-uk Kim  *     uint32_t tmp = *a;
320*17f01e99SJung-uk Kim  *
321*17f01e99SJung-uk Kim  *     *a = *b;
322*17f01e99SJung-uk Kim  *     *b = tmp;
323*17f01e99SJung-uk Kim  * }
324*17f01e99SJung-uk Kim  */
325*17f01e99SJung-uk Kim static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a,
326*17f01e99SJung-uk Kim                                                    uint32_t *b)
327*17f01e99SJung-uk Kim {
328*17f01e99SJung-uk Kim     uint32_t xor = *a ^ *b;
329*17f01e99SJung-uk Kim 
330*17f01e99SJung-uk Kim     xor &= mask;
331*17f01e99SJung-uk Kim     *a ^= xor;
332*17f01e99SJung-uk Kim     *b ^= xor;
333*17f01e99SJung-uk Kim }
334*17f01e99SJung-uk Kim 
335*17f01e99SJung-uk Kim /*
336*17f01e99SJung-uk Kim  * mask must be 0xFFFFFFFF or 0x00000000.
337*17f01e99SJung-uk Kim  *
338*17f01e99SJung-uk Kim  * if (mask) {
339*17f01e99SJung-uk Kim  *     uint64_t tmp = *a;
340*17f01e99SJung-uk Kim  *
341*17f01e99SJung-uk Kim  *     *a = *b;
342*17f01e99SJung-uk Kim  *     *b = tmp;
343*17f01e99SJung-uk Kim  * }
344*17f01e99SJung-uk Kim  */
345*17f01e99SJung-uk Kim static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
346*17f01e99SJung-uk Kim                                                    uint64_t *b)
347*17f01e99SJung-uk Kim {
348*17f01e99SJung-uk Kim     uint64_t xor = *a ^ *b;
349*17f01e99SJung-uk Kim 
350*17f01e99SJung-uk Kim     xor &= mask;
351*17f01e99SJung-uk Kim     *a ^= xor;
352*17f01e99SJung-uk Kim     *b ^= xor;
353*17f01e99SJung-uk Kim }
354*17f01e99SJung-uk Kim 
355*17f01e99SJung-uk Kim /*
356*17f01e99SJung-uk Kim  * table is a two dimensional array of bytes. Each row has rowsize elements.
357*17f01e99SJung-uk Kim  * Copies row number idx into out. rowsize and numrows are not considered
358*17f01e99SJung-uk Kim  * private.
359*17f01e99SJung-uk Kim  */
360*17f01e99SJung-uk Kim static ossl_inline void constant_time_lookup(void *out,
361*17f01e99SJung-uk Kim                                              const void *table,
362*17f01e99SJung-uk Kim                                              size_t rowsize,
363*17f01e99SJung-uk Kim                                              size_t numrows,
364*17f01e99SJung-uk Kim                                              size_t idx)
365*17f01e99SJung-uk Kim {
366*17f01e99SJung-uk Kim     size_t i, j;
367*17f01e99SJung-uk Kim     const unsigned char *tablec = (const unsigned char *)table;
368*17f01e99SJung-uk Kim     unsigned char *outc = (unsigned char *)out;
369*17f01e99SJung-uk Kim     unsigned char mask;
370*17f01e99SJung-uk Kim 
371*17f01e99SJung-uk Kim     memset(out, 0, rowsize);
372*17f01e99SJung-uk Kim 
373*17f01e99SJung-uk Kim     /* Note idx may underflow - but that is well defined */
374*17f01e99SJung-uk Kim     for (i = 0; i < numrows; i++, idx--) {
375*17f01e99SJung-uk Kim         mask = (unsigned char)constant_time_is_zero_s(idx);
376*17f01e99SJung-uk Kim         for (j = 0; j < rowsize; j++)
377*17f01e99SJung-uk Kim             *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0);
378*17f01e99SJung-uk Kim     }
379*17f01e99SJung-uk Kim }
380*17f01e99SJung-uk Kim 
381*17f01e99SJung-uk Kim /*
382*17f01e99SJung-uk Kim  * Expected usage pattern is to unconditionally set error and then
383*17f01e99SJung-uk Kim  * wipe it if there was no actual error. |clear| is 1 or 0.
384*17f01e99SJung-uk Kim  */
385*17f01e99SJung-uk Kim void err_clear_last_constant_time(int clear);
386*17f01e99SJung-uk Kim 
387*17f01e99SJung-uk Kim #endif                          /* OSSL_INTERNAL_CONSTANT_TIME_H */
388