Home | History | Annotate | Download | only in crypto
      1 /* crypto/constant_time_locl.h */
      2 /*
      3  * Utilities for constant-time cryptography.
      4  *
      5  * Author: Emilia Kasper (emilia (at) openssl.org)
      6  * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
      7  * (Google).
      8  * ====================================================================
      9  * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *    "This product includes cryptographic software written by
     22  *     Eric Young (eay (at) cryptsoft.com)"
     23  *    The word 'cryptographic' can be left out if the rouines from the library
     24  *    being used are not cryptographic related :-).
     25  * 4. If you include any Windows specific code (or a derivative thereof) from
     26  *    the apps directory (application code) you must include an acknowledgement:
     27  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     28  *
     29  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     39  * SUCH DAMAGE.
     40  *
     41  * The licence and distribution terms for any publically available version or
     42  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     43  * copied and put under another distribution licence
     44  * [including the GNU Public Licence.]
     45  */
     46 
     47 #ifndef HEADER_CONSTANT_TIME_LOCL_H
     48 #define HEADER_CONSTANT_TIME_LOCL_H
     49 
     50 #include "e_os.h"  /* For 'inline' */
     51 
     52 #ifdef __cplusplus
     53 extern "C" {
     54 #endif
     55 
     56 /*
     57  * The boolean methods return a bitmask of all ones (0xff...f) for true
     58  * and 0 for false. This is useful for choosing a value based on the result
     59  * of a conditional in constant time. For example,
     60  *
     61  * if (a < b) {
     62  *   c = a;
     63  * } else {
     64  *   c = b;
     65  * }
     66  *
     67  * can be written as
     68  *
     69  * unsigned int lt = constant_time_lt(a, b);
     70  * c = constant_time_select(lt, a, b);
     71  */
     72 
     73 /*
     74  * Returns the given value with the MSB copied to all the other
     75  * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
     76  * However, this is not ensured by the C standard so you may need to
     77  * replace this with something else on odd CPUs.
     78  */
     79 static inline unsigned int constant_time_msb(unsigned int a);
     80 
     81 /*
     82  * Returns 0xff..f if a < b and 0 otherwise.
     83  */
     84 static inline unsigned int constant_time_lt(unsigned int a, unsigned int b);
     85 /* Convenience method for getting an 8-bit mask. */
     86 static inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b);
     87 
     88 /*
     89  * Returns 0xff..f if a >= b and 0 otherwise.
     90  */
     91 static inline unsigned int constant_time_ge(unsigned int a, unsigned int b);
     92 /* Convenience method for getting an 8-bit mask. */
     93 static inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b);
     94 
     95 /*
     96  * Returns 0xff..f if a == 0 and 0 otherwise.
     97  */
     98 static inline unsigned int constant_time_is_zero(unsigned int a);
     99 /* Convenience method for getting an 8-bit mask. */
    100 static inline unsigned char constant_time_is_zero_8(unsigned int a);
    101 
    102 
    103 /*
    104  * Returns 0xff..f if a == b and 0 otherwise.
    105  */
    106 static inline unsigned int constant_time_eq(unsigned int a, unsigned int b);
    107 /* Convenience method for getting an 8-bit mask. */
    108 static inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b);
    109 /* Signed integers. */
    110 static inline unsigned int constant_time_eq_int(int a, int b);
    111 /* Convenience method for getting an 8-bit mask. */
    112 static inline unsigned char constant_time_eq_int_8(int a, int b);
    113 
    114 
    115 /*
    116  * Returns (mask & a) | (~mask & b).
    117  *
    118  * When |mask| is all 1s or all 0s (as returned by the methods above),
    119  * the select methods return either |a| (if |mask| is nonzero) or |b|
    120  * (if |mask| is zero).
    121  */
    122 static inline unsigned int constant_time_select(unsigned int mask,
    123 	unsigned int a, unsigned int b);
    124 /* Convenience method for unsigned chars. */
    125 static inline unsigned char constant_time_select_8(unsigned char mask,
    126 	unsigned char a, unsigned char b);
    127 /* Convenience method for signed integers. */
    128 static inline int constant_time_select_int(unsigned int mask, int a, int b);
    129 
    130 static inline unsigned int constant_time_msb(unsigned int a)
    131 	{
    132 	return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
    133 	}
    134 
    135 static inline unsigned int constant_time_lt(unsigned int a, unsigned int b)
    136 	{
    137 	unsigned int lt;
    138 	/* Case 1: msb(a) == msb(b). a < b iff the MSB of a - b is set.*/
    139 	lt = ~(a ^ b) & (a - b);
    140 	/* Case 2: msb(a) != msb(b). a < b iff the MSB of b is set. */
    141 	lt |= ~a & b;
    142 	return constant_time_msb(lt);
    143 	}
    144 
    145 static inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b)
    146 	{
    147 	return (unsigned char)(constant_time_lt(a, b));
    148 	}
    149 
    150 static inline unsigned int constant_time_ge(unsigned int a, unsigned int b)
    151 	{
    152 	unsigned int ge;
    153 	/* Case 1: msb(a) == msb(b). a >= b iff the MSB of a - b is not set.*/
    154 	ge = ~((a ^ b) | (a - b));
    155 	/* Case 2: msb(a) != msb(b). a >= b iff the MSB of a is set. */
    156 	ge |= a & ~b;
    157 	return constant_time_msb(ge);
    158 	}
    159 
    160 static inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b)
    161 	{
    162 	return (unsigned char)(constant_time_ge(a, b));
    163 	}
    164 
    165 static inline unsigned int constant_time_is_zero(unsigned int a)
    166 	{
    167 	return constant_time_msb(~a & (a - 1));
    168 	}
    169 
    170 static inline unsigned char constant_time_is_zero_8(unsigned int a)
    171 	{
    172 	return (unsigned char)(constant_time_is_zero(a));
    173 	}
    174 
    175 static inline unsigned int constant_time_eq(unsigned int a, unsigned int b)
    176 	{
    177 	return constant_time_is_zero(a ^ b);
    178 	}
    179 
    180 static inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b)
    181 	{
    182 	return (unsigned char)(constant_time_eq(a, b));
    183 	}
    184 
    185 static inline unsigned int constant_time_eq_int(int a, int b)
    186 	{
    187 	return constant_time_eq((unsigned)(a), (unsigned)(b));
    188 	}
    189 
    190 static inline unsigned char constant_time_eq_int_8(int a, int b)
    191 	{
    192 	return constant_time_eq_8((unsigned)(a), (unsigned)(b));
    193 	}
    194 
    195 static inline unsigned int constant_time_select(unsigned int mask,
    196 	unsigned int a, unsigned int b)
    197 	{
    198 	return (mask & a) | (~mask & b);
    199 	}
    200 
    201 static inline unsigned char constant_time_select_8(unsigned char mask,
    202 	unsigned char a, unsigned char b)
    203 	{
    204 	return (unsigned char)(constant_time_select(mask, a, b));
    205 	}
    206 
    207 inline int constant_time_select_int(unsigned int mask, int a, int b)
    208 	{
    209 	return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
    210 	}
    211 
    212 #ifdef __cplusplus
    213 }
    214 #endif
    215 
    216 #endif  /* HEADER_CONSTANT_TIME_LOCL_H */
    217