117f01e99SJung-uk Kim /* 2*b077aed3SPierre Pronchery * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. 317f01e99SJung-uk Kim * 4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 517f01e99SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 617f01e99SJung-uk Kim * in the file LICENSE in the source distribution or at 717f01e99SJung-uk Kim * https://www.openssl.org/source/license.html 817f01e99SJung-uk Kim */ 917f01e99SJung-uk Kim 1017f01e99SJung-uk Kim #ifndef OSSL_INTERNAL_CONSTANT_TIME_H 1117f01e99SJung-uk Kim # define OSSL_INTERNAL_CONSTANT_TIME_H 12*b077aed3SPierre Pronchery # pragma once 1317f01e99SJung-uk Kim 1417f01e99SJung-uk Kim # include <stdlib.h> 1517f01e99SJung-uk Kim # include <string.h> 1617f01e99SJung-uk Kim # include <openssl/e_os2.h> /* For 'ossl_inline' */ 1717f01e99SJung-uk Kim 1817f01e99SJung-uk Kim /*- 1917f01e99SJung-uk Kim * The boolean methods return a bitmask of all ones (0xff...f) for true 2017f01e99SJung-uk Kim * and 0 for false. This is useful for choosing a value based on the result 2117f01e99SJung-uk Kim * of a conditional in constant time. For example, 2217f01e99SJung-uk Kim * if (a < b) { 2317f01e99SJung-uk Kim * c = a; 2417f01e99SJung-uk Kim * } else { 2517f01e99SJung-uk Kim * c = b; 2617f01e99SJung-uk Kim * } 2717f01e99SJung-uk Kim * can be written as 2817f01e99SJung-uk Kim * unsigned int lt = constant_time_lt(a, b); 2917f01e99SJung-uk Kim * c = constant_time_select(lt, a, b); 3017f01e99SJung-uk Kim */ 3117f01e99SJung-uk Kim 3217f01e99SJung-uk Kim /* Returns the given value with the MSB copied to all the other bits. */ 3317f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_msb(unsigned int a); 3417f01e99SJung-uk Kim /* Convenience method for uint32_t. */ 3517f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_msb_32(uint32_t a); 3617f01e99SJung-uk Kim /* Convenience method for uint64_t. */ 3717f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_msb_64(uint64_t a); 3817f01e99SJung-uk Kim 3917f01e99SJung-uk Kim /* Returns 0xff..f if a < b and 0 otherwise. */ 4017f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_lt(unsigned int a, 4117f01e99SJung-uk Kim unsigned int b); 4217f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */ 4317f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_lt_8(unsigned int a, 4417f01e99SJung-uk Kim unsigned int b); 4517f01e99SJung-uk Kim /* Convenience method for uint64_t. */ 4617f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b); 4717f01e99SJung-uk Kim 4817f01e99SJung-uk Kim /* Returns 0xff..f if a >= b and 0 otherwise. */ 4917f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_ge(unsigned int a, 5017f01e99SJung-uk Kim unsigned int b); 5117f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */ 5217f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8(unsigned int a, 5317f01e99SJung-uk Kim unsigned int b); 5417f01e99SJung-uk Kim 5517f01e99SJung-uk Kim /* Returns 0xff..f if a == 0 and 0 otherwise. */ 5617f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_is_zero(unsigned int a); 5717f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */ 5817f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a); 5917f01e99SJung-uk Kim /* Convenience method for getting a 32-bit mask. */ 6017f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a); 6117f01e99SJung-uk Kim 6217f01e99SJung-uk Kim /* Returns 0xff..f if a == b and 0 otherwise. */ 6317f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq(unsigned int a, 6417f01e99SJung-uk Kim unsigned int b); 6517f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */ 6617f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8(unsigned int a, 6717f01e99SJung-uk Kim unsigned int b); 6817f01e99SJung-uk Kim /* Signed integers. */ 6917f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq_int(int a, int b); 7017f01e99SJung-uk Kim /* Convenience method for getting an 8-bit mask. */ 7117f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_int_8(int a, int b); 7217f01e99SJung-uk Kim 7317f01e99SJung-uk Kim /*- 7417f01e99SJung-uk Kim * Returns (mask & a) | (~mask & b). 7517f01e99SJung-uk Kim * 7617f01e99SJung-uk Kim * When |mask| is all 1s or all 0s (as returned by the methods above), 7717f01e99SJung-uk Kim * the select methods return either |a| (if |mask| is nonzero) or |b| 7817f01e99SJung-uk Kim * (if |mask| is zero). 7917f01e99SJung-uk Kim */ 8017f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_select(unsigned int mask, 8117f01e99SJung-uk Kim unsigned int a, 8217f01e99SJung-uk Kim unsigned int b); 8317f01e99SJung-uk Kim /* Convenience method for unsigned chars. */ 8417f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_select_8(unsigned char mask, 8517f01e99SJung-uk Kim unsigned char a, 8617f01e99SJung-uk Kim unsigned char b); 8717f01e99SJung-uk Kim 8817f01e99SJung-uk Kim /* Convenience method for uint32_t. */ 8917f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, 9017f01e99SJung-uk Kim uint32_t b); 9117f01e99SJung-uk Kim 9217f01e99SJung-uk Kim /* Convenience method for uint64_t. */ 9317f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, 9417f01e99SJung-uk Kim uint64_t b); 9517f01e99SJung-uk Kim /* Convenience method for signed integers. */ 9617f01e99SJung-uk Kim static ossl_inline int constant_time_select_int(unsigned int mask, int a, 9717f01e99SJung-uk Kim int b); 9817f01e99SJung-uk Kim 9917f01e99SJung-uk Kim 10017f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_msb(unsigned int a) 10117f01e99SJung-uk Kim { 10217f01e99SJung-uk Kim return 0 - (a >> (sizeof(a) * 8 - 1)); 10317f01e99SJung-uk Kim } 10417f01e99SJung-uk Kim 10517f01e99SJung-uk Kim 10617f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_msb_32(uint32_t a) 10717f01e99SJung-uk Kim { 10817f01e99SJung-uk Kim return 0 - (a >> 31); 10917f01e99SJung-uk Kim } 11017f01e99SJung-uk Kim 11117f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_msb_64(uint64_t a) 11217f01e99SJung-uk Kim { 11317f01e99SJung-uk Kim return 0 - (a >> 63); 11417f01e99SJung-uk Kim } 11517f01e99SJung-uk Kim 11617f01e99SJung-uk Kim static ossl_inline size_t constant_time_msb_s(size_t a) 11717f01e99SJung-uk Kim { 11817f01e99SJung-uk Kim return 0 - (a >> (sizeof(a) * 8 - 1)); 11917f01e99SJung-uk Kim } 12017f01e99SJung-uk Kim 12117f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_lt(unsigned int a, 12217f01e99SJung-uk Kim unsigned int b) 12317f01e99SJung-uk Kim { 12417f01e99SJung-uk Kim return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); 12517f01e99SJung-uk Kim } 12617f01e99SJung-uk Kim 12717f01e99SJung-uk Kim static ossl_inline size_t constant_time_lt_s(size_t a, size_t b) 12817f01e99SJung-uk Kim { 12917f01e99SJung-uk Kim return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); 13017f01e99SJung-uk Kim } 13117f01e99SJung-uk Kim 13217f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_lt_8(unsigned int a, 13317f01e99SJung-uk Kim unsigned int b) 13417f01e99SJung-uk Kim { 13517f01e99SJung-uk Kim return (unsigned char)constant_time_lt(a, b); 13617f01e99SJung-uk Kim } 13717f01e99SJung-uk Kim 13817f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) 13917f01e99SJung-uk Kim { 14017f01e99SJung-uk Kim return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); 14117f01e99SJung-uk Kim } 14217f01e99SJung-uk Kim 14317f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_ge(unsigned int a, 14417f01e99SJung-uk Kim unsigned int b) 14517f01e99SJung-uk Kim { 14617f01e99SJung-uk Kim return ~constant_time_lt(a, b); 14717f01e99SJung-uk Kim } 14817f01e99SJung-uk Kim 14917f01e99SJung-uk Kim static ossl_inline size_t constant_time_ge_s(size_t a, size_t b) 15017f01e99SJung-uk Kim { 15117f01e99SJung-uk Kim return ~constant_time_lt_s(a, b); 15217f01e99SJung-uk Kim } 15317f01e99SJung-uk Kim 15417f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8(unsigned int a, 15517f01e99SJung-uk Kim unsigned int b) 15617f01e99SJung-uk Kim { 15717f01e99SJung-uk Kim return (unsigned char)constant_time_ge(a, b); 15817f01e99SJung-uk Kim } 15917f01e99SJung-uk Kim 16017f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b) 16117f01e99SJung-uk Kim { 16217f01e99SJung-uk Kim return (unsigned char)constant_time_ge_s(a, b); 16317f01e99SJung-uk Kim } 16417f01e99SJung-uk Kim 16517f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_is_zero(unsigned int a) 16617f01e99SJung-uk Kim { 16717f01e99SJung-uk Kim return constant_time_msb(~a & (a - 1)); 16817f01e99SJung-uk Kim } 16917f01e99SJung-uk Kim 17017f01e99SJung-uk Kim static ossl_inline size_t constant_time_is_zero_s(size_t a) 17117f01e99SJung-uk Kim { 17217f01e99SJung-uk Kim return constant_time_msb_s(~a & (a - 1)); 17317f01e99SJung-uk Kim } 17417f01e99SJung-uk Kim 17517f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a) 17617f01e99SJung-uk Kim { 17717f01e99SJung-uk Kim return (unsigned char)constant_time_is_zero(a); 17817f01e99SJung-uk Kim } 17917f01e99SJung-uk Kim 18017f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a) 18117f01e99SJung-uk Kim { 18217f01e99SJung-uk Kim return constant_time_msb_32(~a & (a - 1)); 18317f01e99SJung-uk Kim } 18417f01e99SJung-uk Kim 185*b077aed3SPierre Pronchery static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a) 186*b077aed3SPierre Pronchery { 187*b077aed3SPierre Pronchery return constant_time_msb_64(~a & (a - 1)); 188*b077aed3SPierre Pronchery } 189*b077aed3SPierre Pronchery 19017f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq(unsigned int a, 19117f01e99SJung-uk Kim unsigned int b) 19217f01e99SJung-uk Kim { 19317f01e99SJung-uk Kim return constant_time_is_zero(a ^ b); 19417f01e99SJung-uk Kim } 19517f01e99SJung-uk Kim 19617f01e99SJung-uk Kim static ossl_inline size_t constant_time_eq_s(size_t a, size_t b) 19717f01e99SJung-uk Kim { 19817f01e99SJung-uk Kim return constant_time_is_zero_s(a ^ b); 19917f01e99SJung-uk Kim } 20017f01e99SJung-uk Kim 20117f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8(unsigned int a, 20217f01e99SJung-uk Kim unsigned int b) 20317f01e99SJung-uk Kim { 20417f01e99SJung-uk Kim return (unsigned char)constant_time_eq(a, b); 20517f01e99SJung-uk Kim } 20617f01e99SJung-uk Kim 20717f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b) 20817f01e99SJung-uk Kim { 20917f01e99SJung-uk Kim return (unsigned char)constant_time_eq_s(a, b); 21017f01e99SJung-uk Kim } 21117f01e99SJung-uk Kim 21217f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_eq_int(int a, int b) 21317f01e99SJung-uk Kim { 21417f01e99SJung-uk Kim return constant_time_eq((unsigned)(a), (unsigned)(b)); 21517f01e99SJung-uk Kim } 21617f01e99SJung-uk Kim 21717f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_eq_int_8(int a, int b) 21817f01e99SJung-uk Kim { 21917f01e99SJung-uk Kim return constant_time_eq_8((unsigned)(a), (unsigned)(b)); 22017f01e99SJung-uk Kim } 22117f01e99SJung-uk Kim 22217f01e99SJung-uk Kim /* 22317f01e99SJung-uk Kim * Returns the value unmodified, but avoids optimizations. 22417f01e99SJung-uk Kim * The barriers prevent the compiler from narrowing down the 22517f01e99SJung-uk Kim * possible value range of the mask and ~mask in the select 22617f01e99SJung-uk Kim * statements, which avoids the recognition of the select 22717f01e99SJung-uk Kim * and turning it into a conditional load or branch. 22817f01e99SJung-uk Kim */ 22917f01e99SJung-uk Kim static ossl_inline unsigned int value_barrier(unsigned int a) 23017f01e99SJung-uk Kim { 23117f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) 23217f01e99SJung-uk Kim unsigned int r; 23317f01e99SJung-uk Kim __asm__("" : "=r"(r) : "0"(a)); 23417f01e99SJung-uk Kim #else 23517f01e99SJung-uk Kim volatile unsigned int r = a; 23617f01e99SJung-uk Kim #endif 23717f01e99SJung-uk Kim return r; 23817f01e99SJung-uk Kim } 23917f01e99SJung-uk Kim 24017f01e99SJung-uk Kim /* Convenience method for uint32_t. */ 24117f01e99SJung-uk Kim static ossl_inline uint32_t value_barrier_32(uint32_t a) 24217f01e99SJung-uk Kim { 24317f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) 24417f01e99SJung-uk Kim uint32_t r; 24517f01e99SJung-uk Kim __asm__("" : "=r"(r) : "0"(a)); 24617f01e99SJung-uk Kim #else 24717f01e99SJung-uk Kim volatile uint32_t r = a; 24817f01e99SJung-uk Kim #endif 24917f01e99SJung-uk Kim return r; 25017f01e99SJung-uk Kim } 25117f01e99SJung-uk Kim 25217f01e99SJung-uk Kim /* Convenience method for uint64_t. */ 25317f01e99SJung-uk Kim static ossl_inline uint64_t value_barrier_64(uint64_t a) 25417f01e99SJung-uk Kim { 25517f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) 25617f01e99SJung-uk Kim uint64_t r; 25717f01e99SJung-uk Kim __asm__("" : "=r"(r) : "0"(a)); 25817f01e99SJung-uk Kim #else 25917f01e99SJung-uk Kim volatile uint64_t r = a; 26017f01e99SJung-uk Kim #endif 26117f01e99SJung-uk Kim return r; 26217f01e99SJung-uk Kim } 26317f01e99SJung-uk Kim 26417f01e99SJung-uk Kim /* Convenience method for size_t. */ 26517f01e99SJung-uk Kim static ossl_inline size_t value_barrier_s(size_t a) 26617f01e99SJung-uk Kim { 26717f01e99SJung-uk Kim #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) 26817f01e99SJung-uk Kim size_t r; 26917f01e99SJung-uk Kim __asm__("" : "=r"(r) : "0"(a)); 27017f01e99SJung-uk Kim #else 27117f01e99SJung-uk Kim volatile size_t r = a; 27217f01e99SJung-uk Kim #endif 27317f01e99SJung-uk Kim return r; 27417f01e99SJung-uk Kim } 27517f01e99SJung-uk Kim 27617f01e99SJung-uk Kim static ossl_inline unsigned int constant_time_select(unsigned int mask, 27717f01e99SJung-uk Kim unsigned int a, 27817f01e99SJung-uk Kim unsigned int b) 27917f01e99SJung-uk Kim { 28017f01e99SJung-uk Kim return (value_barrier(mask) & a) | (value_barrier(~mask) & b); 28117f01e99SJung-uk Kim } 28217f01e99SJung-uk Kim 28317f01e99SJung-uk Kim static ossl_inline size_t constant_time_select_s(size_t mask, 28417f01e99SJung-uk Kim size_t a, 28517f01e99SJung-uk Kim size_t b) 28617f01e99SJung-uk Kim { 28717f01e99SJung-uk Kim return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b); 28817f01e99SJung-uk Kim } 28917f01e99SJung-uk Kim 29017f01e99SJung-uk Kim static ossl_inline unsigned char constant_time_select_8(unsigned char mask, 29117f01e99SJung-uk Kim unsigned char a, 29217f01e99SJung-uk Kim unsigned char b) 29317f01e99SJung-uk Kim { 29417f01e99SJung-uk Kim return (unsigned char)constant_time_select(mask, a, b); 29517f01e99SJung-uk Kim } 29617f01e99SJung-uk Kim 29717f01e99SJung-uk Kim static ossl_inline int constant_time_select_int(unsigned int mask, int a, 29817f01e99SJung-uk Kim int b) 29917f01e99SJung-uk Kim { 30017f01e99SJung-uk Kim return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b)); 30117f01e99SJung-uk Kim } 30217f01e99SJung-uk Kim 30317f01e99SJung-uk Kim static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b) 30417f01e99SJung-uk Kim { 30517f01e99SJung-uk Kim return (int)constant_time_select((unsigned)mask, (unsigned)(a), 30617f01e99SJung-uk Kim (unsigned)(b)); 30717f01e99SJung-uk Kim } 30817f01e99SJung-uk Kim 30917f01e99SJung-uk Kim static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, 31017f01e99SJung-uk Kim uint32_t b) 31117f01e99SJung-uk Kim { 31217f01e99SJung-uk Kim return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b); 31317f01e99SJung-uk Kim } 31417f01e99SJung-uk Kim 31517f01e99SJung-uk Kim static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, 31617f01e99SJung-uk Kim uint64_t b) 31717f01e99SJung-uk Kim { 31817f01e99SJung-uk Kim return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b); 31917f01e99SJung-uk Kim } 32017f01e99SJung-uk Kim 32117f01e99SJung-uk Kim /* 32217f01e99SJung-uk Kim * mask must be 0xFFFFFFFF or 0x00000000. 32317f01e99SJung-uk Kim * 32417f01e99SJung-uk Kim * if (mask) { 32517f01e99SJung-uk Kim * uint32_t tmp = *a; 32617f01e99SJung-uk Kim * 32717f01e99SJung-uk Kim * *a = *b; 32817f01e99SJung-uk Kim * *b = tmp; 32917f01e99SJung-uk Kim * } 33017f01e99SJung-uk Kim */ 33117f01e99SJung-uk Kim static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a, 33217f01e99SJung-uk Kim uint32_t *b) 33317f01e99SJung-uk Kim { 33417f01e99SJung-uk Kim uint32_t xor = *a ^ *b; 33517f01e99SJung-uk Kim 33617f01e99SJung-uk Kim xor &= mask; 33717f01e99SJung-uk Kim *a ^= xor; 33817f01e99SJung-uk Kim *b ^= xor; 33917f01e99SJung-uk Kim } 34017f01e99SJung-uk Kim 34117f01e99SJung-uk Kim /* 34217f01e99SJung-uk Kim * mask must be 0xFFFFFFFF or 0x00000000. 34317f01e99SJung-uk Kim * 34417f01e99SJung-uk Kim * if (mask) { 34517f01e99SJung-uk Kim * uint64_t tmp = *a; 34617f01e99SJung-uk Kim * 34717f01e99SJung-uk Kim * *a = *b; 34817f01e99SJung-uk Kim * *b = tmp; 34917f01e99SJung-uk Kim * } 35017f01e99SJung-uk Kim */ 35117f01e99SJung-uk Kim static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a, 35217f01e99SJung-uk Kim uint64_t *b) 35317f01e99SJung-uk Kim { 35417f01e99SJung-uk Kim uint64_t xor = *a ^ *b; 35517f01e99SJung-uk Kim 35617f01e99SJung-uk Kim xor &= mask; 35717f01e99SJung-uk Kim *a ^= xor; 35817f01e99SJung-uk Kim *b ^= xor; 35917f01e99SJung-uk Kim } 36017f01e99SJung-uk Kim 36117f01e99SJung-uk Kim /* 362*b077aed3SPierre Pronchery * mask must be 0xFF or 0x00. 363*b077aed3SPierre Pronchery * "constant time" is per len. 364*b077aed3SPierre Pronchery * 365*b077aed3SPierre Pronchery * if (mask) { 366*b077aed3SPierre Pronchery * unsigned char tmp[len]; 367*b077aed3SPierre Pronchery * 368*b077aed3SPierre Pronchery * memcpy(tmp, a, len); 369*b077aed3SPierre Pronchery * memcpy(a, b); 370*b077aed3SPierre Pronchery * memcpy(b, tmp); 371*b077aed3SPierre Pronchery * } 372*b077aed3SPierre Pronchery */ 373*b077aed3SPierre Pronchery static ossl_inline void constant_time_cond_swap_buff(unsigned char mask, 374*b077aed3SPierre Pronchery unsigned char *a, 375*b077aed3SPierre Pronchery unsigned char *b, 376*b077aed3SPierre Pronchery size_t len) 377*b077aed3SPierre Pronchery { 378*b077aed3SPierre Pronchery size_t i; 379*b077aed3SPierre Pronchery unsigned char tmp; 380*b077aed3SPierre Pronchery 381*b077aed3SPierre Pronchery for (i = 0; i < len; i++) { 382*b077aed3SPierre Pronchery tmp = a[i] ^ b[i]; 383*b077aed3SPierre Pronchery tmp &= mask; 384*b077aed3SPierre Pronchery a[i] ^= tmp; 385*b077aed3SPierre Pronchery b[i] ^= tmp; 386*b077aed3SPierre Pronchery } 387*b077aed3SPierre Pronchery } 388*b077aed3SPierre Pronchery 389*b077aed3SPierre Pronchery /* 39017f01e99SJung-uk Kim * table is a two dimensional array of bytes. Each row has rowsize elements. 39117f01e99SJung-uk Kim * Copies row number idx into out. rowsize and numrows are not considered 39217f01e99SJung-uk Kim * private. 39317f01e99SJung-uk Kim */ 39417f01e99SJung-uk Kim static ossl_inline void constant_time_lookup(void *out, 39517f01e99SJung-uk Kim const void *table, 39617f01e99SJung-uk Kim size_t rowsize, 39717f01e99SJung-uk Kim size_t numrows, 39817f01e99SJung-uk Kim size_t idx) 39917f01e99SJung-uk Kim { 40017f01e99SJung-uk Kim size_t i, j; 40117f01e99SJung-uk Kim const unsigned char *tablec = (const unsigned char *)table; 40217f01e99SJung-uk Kim unsigned char *outc = (unsigned char *)out; 40317f01e99SJung-uk Kim unsigned char mask; 40417f01e99SJung-uk Kim 40517f01e99SJung-uk Kim memset(out, 0, rowsize); 40617f01e99SJung-uk Kim 40717f01e99SJung-uk Kim /* Note idx may underflow - but that is well defined */ 40817f01e99SJung-uk Kim for (i = 0; i < numrows; i++, idx--) { 40917f01e99SJung-uk Kim mask = (unsigned char)constant_time_is_zero_s(idx); 41017f01e99SJung-uk Kim for (j = 0; j < rowsize; j++) 41117f01e99SJung-uk Kim *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0); 41217f01e99SJung-uk Kim } 41317f01e99SJung-uk Kim } 41417f01e99SJung-uk Kim 41517f01e99SJung-uk Kim /* 41617f01e99SJung-uk Kim * Expected usage pattern is to unconditionally set error and then 41717f01e99SJung-uk Kim * wipe it if there was no actual error. |clear| is 1 or 0. 41817f01e99SJung-uk Kim */ 41917f01e99SJung-uk Kim void err_clear_last_constant_time(int clear); 42017f01e99SJung-uk Kim 42117f01e99SJung-uk Kim #endif /* OSSL_INTERNAL_CONSTANT_TIME_H */ 422