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