1273138Sjkim/* crypto/constant_time_locl.h */ 2296341Sdelphij/*- 3273138Sjkim * Utilities for constant-time cryptography. 4273138Sjkim * 5273138Sjkim * Author: Emilia Kasper (emilia@openssl.org) 6273138Sjkim * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley 7273138Sjkim * (Google). 8273138Sjkim * ==================================================================== 9273138Sjkim * Copyright (c) 2014 The OpenSSL Project. All rights reserved. 10273138Sjkim * 11273138Sjkim * Redistribution and use in source and binary forms, with or without 12273138Sjkim * modification, are permitted provided that the following conditions 13273138Sjkim * are met: 14273138Sjkim * 1. Redistributions of source code must retain the copyright 15273138Sjkim * notice, this list of conditions and the following disclaimer. 16273138Sjkim * 2. Redistributions in binary form must reproduce the above copyright 17273138Sjkim * notice, this list of conditions and the following disclaimer in the 18273138Sjkim * documentation and/or other materials provided with the distribution. 19273138Sjkim * 3. All advertising materials mentioning features or use of this software 20273138Sjkim * must display the following acknowledgement: 21273138Sjkim * "This product includes cryptographic software written by 22273138Sjkim * Eric Young (eay@cryptsoft.com)" 23273138Sjkim * The word 'cryptographic' can be left out if the rouines from the library 24273138Sjkim * being used are not cryptographic related :-). 25273138Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 26273138Sjkim * the apps directory (application code) you must include an acknowledgement: 27273138Sjkim * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 28273138Sjkim * 29273138Sjkim * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 30273138Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31273138Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32273138Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 33273138Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34273138Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35273138Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36273138Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37273138Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38273138Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39273138Sjkim * SUCH DAMAGE. 40273138Sjkim * 41273138Sjkim * The licence and distribution terms for any publically available version or 42273138Sjkim * derivative of this code cannot be changed. i.e. this code cannot simply be 43273138Sjkim * copied and put under another distribution licence 44273138Sjkim * [including the GNU Public Licence.] 45273138Sjkim */ 46273138Sjkim 47273138Sjkim#ifndef HEADER_CONSTANT_TIME_LOCL_H 48296341Sdelphij# define HEADER_CONSTANT_TIME_LOCL_H 49273138Sjkim 50296341Sdelphij# include "e_os.h" /* For 'inline' */ 51273138Sjkim 52273138Sjkim#ifdef __cplusplus 53273138Sjkimextern "C" { 54273138Sjkim#endif 55273138Sjkim 56296341Sdelphij/*- 57273138Sjkim * The boolean methods return a bitmask of all ones (0xff...f) for true 58273138Sjkim * and 0 for false. This is useful for choosing a value based on the result 59273138Sjkim * of a conditional in constant time. For example, 60273138Sjkim * 61273138Sjkim * if (a < b) { 62273138Sjkim * c = a; 63273138Sjkim * } else { 64273138Sjkim * c = b; 65273138Sjkim * } 66273138Sjkim * 67273138Sjkim * can be written as 68273138Sjkim * 69273138Sjkim * unsigned int lt = constant_time_lt(a, b); 70273138Sjkim * c = constant_time_select(lt, a, b); 71273138Sjkim */ 72273138Sjkim 73273138Sjkim/* 74273138Sjkim * Returns the given value with the MSB copied to all the other 75273138Sjkim * bits. Uses the fact that arithmetic shift shifts-in the sign bit. 76273138Sjkim * However, this is not ensured by the C standard so you may need to 77273138Sjkim * replace this with something else on odd CPUs. 78273138Sjkim */ 79273138Sjkimstatic inline unsigned int constant_time_msb(unsigned int a); 80273138Sjkim 81273138Sjkim/* 82273138Sjkim * Returns 0xff..f if a < b and 0 otherwise. 83273138Sjkim */ 84273138Sjkimstatic inline unsigned int constant_time_lt(unsigned int a, unsigned int b); 85273138Sjkim/* Convenience method for getting an 8-bit mask. */ 86296341Sdelphijstatic inline unsigned char constant_time_lt_8(unsigned int a, 87296341Sdelphij unsigned int b); 88273138Sjkim 89273138Sjkim/* 90273138Sjkim * Returns 0xff..f if a >= b and 0 otherwise. 91273138Sjkim */ 92273138Sjkimstatic inline unsigned int constant_time_ge(unsigned int a, unsigned int b); 93273138Sjkim/* Convenience method for getting an 8-bit mask. */ 94296341Sdelphijstatic inline unsigned char constant_time_ge_8(unsigned int a, 95296341Sdelphij unsigned int b); 96273138Sjkim 97273138Sjkim/* 98273138Sjkim * Returns 0xff..f if a == 0 and 0 otherwise. 99273138Sjkim */ 100273138Sjkimstatic inline unsigned int constant_time_is_zero(unsigned int a); 101273138Sjkim/* Convenience method for getting an 8-bit mask. */ 102273138Sjkimstatic inline unsigned char constant_time_is_zero_8(unsigned int a); 103273138Sjkim 104273138Sjkim/* 105273138Sjkim * Returns 0xff..f if a == b and 0 otherwise. 106273138Sjkim */ 107273138Sjkimstatic inline unsigned int constant_time_eq(unsigned int a, unsigned int b); 108273138Sjkim/* Convenience method for getting an 8-bit mask. */ 109296341Sdelphijstatic inline unsigned char constant_time_eq_8(unsigned int a, 110296341Sdelphij unsigned int b); 111273138Sjkim/* Signed integers. */ 112273138Sjkimstatic inline unsigned int constant_time_eq_int(int a, int b); 113273138Sjkim/* Convenience method for getting an 8-bit mask. */ 114273138Sjkimstatic inline unsigned char constant_time_eq_int_8(int a, int b); 115273138Sjkim 116296341Sdelphij/*- 117273138Sjkim * Returns (mask & a) | (~mask & b). 118273138Sjkim * 119273138Sjkim * When |mask| is all 1s or all 0s (as returned by the methods above), 120273138Sjkim * the select methods return either |a| (if |mask| is nonzero) or |b| 121273138Sjkim * (if |mask| is zero). 122273138Sjkim */ 123273138Sjkimstatic inline unsigned int constant_time_select(unsigned int mask, 124296341Sdelphij unsigned int a, 125296341Sdelphij unsigned int b); 126273138Sjkim/* Convenience method for unsigned chars. */ 127273138Sjkimstatic inline unsigned char constant_time_select_8(unsigned char mask, 128296341Sdelphij unsigned char a, 129296341Sdelphij unsigned char b); 130273138Sjkim/* Convenience method for signed integers. */ 131273138Sjkimstatic inline int constant_time_select_int(unsigned int mask, int a, int b); 132273138Sjkim 133273138Sjkimstatic inline unsigned int constant_time_msb(unsigned int a) 134296341Sdelphij{ 135296341Sdelphij return 0 - (a >> (sizeof(a) * 8 - 1)); 136296341Sdelphij} 137273138Sjkim 138273138Sjkimstatic inline unsigned int constant_time_lt(unsigned int a, unsigned int b) 139296341Sdelphij{ 140296341Sdelphij return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); 141296341Sdelphij} 142273138Sjkim 143273138Sjkimstatic inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b) 144296341Sdelphij{ 145296341Sdelphij return (unsigned char)(constant_time_lt(a, b)); 146296341Sdelphij} 147273138Sjkim 148273138Sjkimstatic inline unsigned int constant_time_ge(unsigned int a, unsigned int b) 149296341Sdelphij{ 150296341Sdelphij return ~constant_time_lt(a, b); 151296341Sdelphij} 152273138Sjkim 153273138Sjkimstatic inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b) 154296341Sdelphij{ 155296341Sdelphij return (unsigned char)(constant_time_ge(a, b)); 156296341Sdelphij} 157273138Sjkim 158273138Sjkimstatic inline unsigned int constant_time_is_zero(unsigned int a) 159296341Sdelphij{ 160296341Sdelphij return constant_time_msb(~a & (a - 1)); 161296341Sdelphij} 162273138Sjkim 163273138Sjkimstatic inline unsigned char constant_time_is_zero_8(unsigned int a) 164296341Sdelphij{ 165296341Sdelphij return (unsigned char)(constant_time_is_zero(a)); 166296341Sdelphij} 167273138Sjkim 168273138Sjkimstatic inline unsigned int constant_time_eq(unsigned int a, unsigned int b) 169296341Sdelphij{ 170296341Sdelphij return constant_time_is_zero(a ^ b); 171296341Sdelphij} 172273138Sjkim 173273138Sjkimstatic inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b) 174296341Sdelphij{ 175296341Sdelphij return (unsigned char)(constant_time_eq(a, b)); 176296341Sdelphij} 177273138Sjkim 178273138Sjkimstatic inline unsigned int constant_time_eq_int(int a, int b) 179296341Sdelphij{ 180296341Sdelphij return constant_time_eq((unsigned)(a), (unsigned)(b)); 181296341Sdelphij} 182273138Sjkim 183273138Sjkimstatic inline unsigned char constant_time_eq_int_8(int a, int b) 184296341Sdelphij{ 185296341Sdelphij return constant_time_eq_8((unsigned)(a), (unsigned)(b)); 186296341Sdelphij} 187273138Sjkim 188273138Sjkimstatic inline unsigned int constant_time_select(unsigned int mask, 189296341Sdelphij unsigned int a, 190296341Sdelphij unsigned int b) 191296341Sdelphij{ 192296341Sdelphij return (mask & a) | (~mask & b); 193296341Sdelphij} 194273138Sjkim 195273138Sjkimstatic inline unsigned char constant_time_select_8(unsigned char mask, 196296341Sdelphij unsigned char a, 197296341Sdelphij unsigned char b) 198296341Sdelphij{ 199296341Sdelphij return (unsigned char)(constant_time_select(mask, a, b)); 200296341Sdelphij} 201273138Sjkim 202279264Sdelphijstatic inline int constant_time_select_int(unsigned int mask, int a, int b) 203296341Sdelphij{ 204296341Sdelphij return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b))); 205296341Sdelphij} 206273138Sjkim 207273138Sjkim#ifdef __cplusplus 208273138Sjkim} 209273138Sjkim#endif 210273138Sjkim 211296341Sdelphij#endif /* HEADER_CONSTANT_TIME_LOCL_H */ 212