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