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