1279265Sdelphij/* crypto/constant_time_locl.h */
2296465Sdelphij/*-
3279265Sdelphij * Utilities for constant-time cryptography.
4279265Sdelphij *
5279265Sdelphij * Author: Emilia Kasper (emilia@openssl.org)
6279265Sdelphij * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
7279265Sdelphij * (Google).
8279265Sdelphij * ====================================================================
9279265Sdelphij * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
10279265Sdelphij *
11279265Sdelphij * Redistribution and use in source and binary forms, with or without
12279265Sdelphij * modification, are permitted provided that the following conditions
13279265Sdelphij * are met:
14279265Sdelphij * 1. Redistributions of source code must retain the copyright
15279265Sdelphij *    notice, this list of conditions and the following disclaimer.
16279265Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
17279265Sdelphij *    notice, this list of conditions and the following disclaimer in the
18279265Sdelphij *    documentation and/or other materials provided with the distribution.
19279265Sdelphij * 3. All advertising materials mentioning features or use of this software
20279265Sdelphij *    must display the following acknowledgement:
21279265Sdelphij *    "This product includes cryptographic software written by
22279265Sdelphij *     Eric Young (eay@cryptsoft.com)"
23279265Sdelphij *    The word 'cryptographic' can be left out if the rouines from the library
24279265Sdelphij *    being used are not cryptographic related :-).
25279265Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
26279265Sdelphij *    the apps directory (application code) you must include an acknowledgement:
27279265Sdelphij *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
28279265Sdelphij *
29279265Sdelphij * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
30279265Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31279265Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32279265Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33279265Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34279265Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35279265Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36279265Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37279265Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38279265Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39279265Sdelphij * SUCH DAMAGE.
40279265Sdelphij *
41279265Sdelphij * The licence and distribution terms for any publically available version or
42279265Sdelphij * derivative of this code cannot be changed.  i.e. this code cannot simply be
43279265Sdelphij * copied and put under another distribution licence
44279265Sdelphij * [including the GNU Public Licence.]
45279265Sdelphij */
46279265Sdelphij
47279265Sdelphij#ifndef HEADER_CONSTANT_TIME_LOCL_H
48296465Sdelphij# define HEADER_CONSTANT_TIME_LOCL_H
49279265Sdelphij
50296465Sdelphij# include "e_os.h"              /* For 'inline' */
51279265Sdelphij
52279265Sdelphij#ifdef __cplusplus
53279265Sdelphijextern "C" {
54279265Sdelphij#endif
55279265Sdelphij
56296465Sdelphij/*-
57279265Sdelphij * The boolean methods return a bitmask of all ones (0xff...f) for true
58279265Sdelphij * and 0 for false. This is useful for choosing a value based on the result
59279265Sdelphij * of a conditional in constant time. For example,
60279265Sdelphij *
61279265Sdelphij * if (a < b) {
62279265Sdelphij *   c = a;
63279265Sdelphij * } else {
64279265Sdelphij *   c = b;
65279265Sdelphij * }
66279265Sdelphij *
67279265Sdelphij * can be written as
68279265Sdelphij *
69279265Sdelphij * unsigned int lt = constant_time_lt(a, b);
70279265Sdelphij * c = constant_time_select(lt, a, b);
71279265Sdelphij */
72279265Sdelphij
73279265Sdelphij/*
74279265Sdelphij * Returns the given value with the MSB copied to all the other
75279265Sdelphij * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
76279265Sdelphij * However, this is not ensured by the C standard so you may need to
77279265Sdelphij * replace this with something else on odd CPUs.
78279265Sdelphij */
79279265Sdelphijstatic inline unsigned int constant_time_msb(unsigned int a);
80279265Sdelphij
81279265Sdelphij/*
82279265Sdelphij * Returns 0xff..f if a < b and 0 otherwise.
83279265Sdelphij */
84279265Sdelphijstatic inline unsigned int constant_time_lt(unsigned int a, unsigned int b);
85279265Sdelphij/* Convenience method for getting an 8-bit mask. */
86296465Sdelphijstatic inline unsigned char constant_time_lt_8(unsigned int a,
87296465Sdelphij                                               unsigned int b);
88279265Sdelphij
89279265Sdelphij/*
90279265Sdelphij * Returns 0xff..f if a >= b and 0 otherwise.
91279265Sdelphij */
92279265Sdelphijstatic inline unsigned int constant_time_ge(unsigned int a, unsigned int b);
93279265Sdelphij/* Convenience method for getting an 8-bit mask. */
94296465Sdelphijstatic inline unsigned char constant_time_ge_8(unsigned int a,
95296465Sdelphij                                               unsigned int b);
96279265Sdelphij
97279265Sdelphij/*
98279265Sdelphij * Returns 0xff..f if a == 0 and 0 otherwise.
99279265Sdelphij */
100279265Sdelphijstatic inline unsigned int constant_time_is_zero(unsigned int a);
101279265Sdelphij/* Convenience method for getting an 8-bit mask. */
102279265Sdelphijstatic inline unsigned char constant_time_is_zero_8(unsigned int a);
103279265Sdelphij
104279265Sdelphij/*
105279265Sdelphij * Returns 0xff..f if a == b and 0 otherwise.
106279265Sdelphij */
107279265Sdelphijstatic inline unsigned int constant_time_eq(unsigned int a, unsigned int b);
108279265Sdelphij/* Convenience method for getting an 8-bit mask. */
109296465Sdelphijstatic inline unsigned char constant_time_eq_8(unsigned int a,
110296465Sdelphij                                               unsigned int b);
111279265Sdelphij/* Signed integers. */
112279265Sdelphijstatic inline unsigned int constant_time_eq_int(int a, int b);
113279265Sdelphij/* Convenience method for getting an 8-bit mask. */
114279265Sdelphijstatic inline unsigned char constant_time_eq_int_8(int a, int b);
115279265Sdelphij
116296465Sdelphij/*-
117279265Sdelphij * Returns (mask & a) | (~mask & b).
118279265Sdelphij *
119279265Sdelphij * When |mask| is all 1s or all 0s (as returned by the methods above),
120279265Sdelphij * the select methods return either |a| (if |mask| is nonzero) or |b|
121279265Sdelphij * (if |mask| is zero).
122279265Sdelphij */
123279265Sdelphijstatic inline unsigned int constant_time_select(unsigned int mask,
124296465Sdelphij                                                unsigned int a,
125296465Sdelphij                                                unsigned int b);
126279265Sdelphij/* Convenience method for unsigned chars. */
127279265Sdelphijstatic inline unsigned char constant_time_select_8(unsigned char mask,
128296465Sdelphij                                                   unsigned char a,
129296465Sdelphij                                                   unsigned char b);
130279265Sdelphij/* Convenience method for signed integers. */
131279265Sdelphijstatic inline int constant_time_select_int(unsigned int mask, int a, int b);
132279265Sdelphij
133279265Sdelphijstatic inline unsigned int constant_time_msb(unsigned int a)
134296465Sdelphij{
135296465Sdelphij    return 0 - (a >> (sizeof(a) * 8 - 1));
136296465Sdelphij}
137279265Sdelphij
138279265Sdelphijstatic inline unsigned int constant_time_lt(unsigned int a, unsigned int b)
139296465Sdelphij{
140296465Sdelphij    return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
141296465Sdelphij}
142279265Sdelphij
143279265Sdelphijstatic inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b)
144296465Sdelphij{
145296465Sdelphij    return (unsigned char)(constant_time_lt(a, b));
146296465Sdelphij}
147279265Sdelphij
148279265Sdelphijstatic inline unsigned int constant_time_ge(unsigned int a, unsigned int b)
149296465Sdelphij{
150296465Sdelphij    return ~constant_time_lt(a, b);
151296465Sdelphij}
152279265Sdelphij
153279265Sdelphijstatic inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b)
154296465Sdelphij{
155296465Sdelphij    return (unsigned char)(constant_time_ge(a, b));
156296465Sdelphij}
157279265Sdelphij
158279265Sdelphijstatic inline unsigned int constant_time_is_zero(unsigned int a)
159296465Sdelphij{
160296465Sdelphij    return constant_time_msb(~a & (a - 1));
161296465Sdelphij}
162279265Sdelphij
163279265Sdelphijstatic inline unsigned char constant_time_is_zero_8(unsigned int a)
164296465Sdelphij{
165296465Sdelphij    return (unsigned char)(constant_time_is_zero(a));
166296465Sdelphij}
167279265Sdelphij
168279265Sdelphijstatic inline unsigned int constant_time_eq(unsigned int a, unsigned int b)
169296465Sdelphij{
170296465Sdelphij    return constant_time_is_zero(a ^ b);
171296465Sdelphij}
172279265Sdelphij
173279265Sdelphijstatic inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b)
174296465Sdelphij{
175296465Sdelphij    return (unsigned char)(constant_time_eq(a, b));
176296465Sdelphij}
177279265Sdelphij
178279265Sdelphijstatic inline unsigned int constant_time_eq_int(int a, int b)
179296465Sdelphij{
180296465Sdelphij    return constant_time_eq((unsigned)(a), (unsigned)(b));
181296465Sdelphij}
182279265Sdelphij
183279265Sdelphijstatic inline unsigned char constant_time_eq_int_8(int a, int b)
184296465Sdelphij{
185296465Sdelphij    return constant_time_eq_8((unsigned)(a), (unsigned)(b));
186296465Sdelphij}
187279265Sdelphij
188279265Sdelphijstatic inline unsigned int constant_time_select(unsigned int mask,
189296465Sdelphij                                                unsigned int a,
190296465Sdelphij                                                unsigned int b)
191296465Sdelphij{
192296465Sdelphij    return (mask & a) | (~mask & b);
193296465Sdelphij}
194279265Sdelphij
195279265Sdelphijstatic inline unsigned char constant_time_select_8(unsigned char mask,
196296465Sdelphij                                                   unsigned char a,
197296465Sdelphij                                                   unsigned char b)
198296465Sdelphij{
199296465Sdelphij    return (unsigned char)(constant_time_select(mask, a, b));
200296465Sdelphij}
201279265Sdelphij
202279265Sdelphijstatic inline int constant_time_select_int(unsigned int mask, int a, int b)
203296465Sdelphij{
204296465Sdelphij    return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
205296465Sdelphij}
206279265Sdelphij
207279265Sdelphij#ifdef __cplusplus
208279265Sdelphij}
209279265Sdelphij#endif
210279265Sdelphij
211296465Sdelphij#endif                          /* HEADER_CONSTANT_TIME_LOCL_H */
212