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