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