be2730ea95b92eb343790c369a83820012f75a3c
[openssl.git] / include / internal / constant_time_locl.h
1 /*
2  * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #ifndef HEADER_CONSTANT_TIME_LOCL_H
11 # define HEADER_CONSTANT_TIME_LOCL_H
12
13 # include <stdlib.h>
14 # include <openssl/e_os2.h>              /* For 'ossl_inline' */
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 /*-
21  * The boolean methods return a bitmask of all ones (0xff...f) for true
22  * and 0 for false. This is useful for choosing a value based on the result
23  * of a conditional in constant time. For example,
24  *
25  * if (a < b) {
26  *   c = a;
27  * } else {
28  *   c = b;
29  * }
30  *
31  * can be written as
32  *
33  * unsigned int lt = constant_time_lt(a, b);
34  * c = constant_time_select(lt, a, b);
35  */
36
37 /*
38  * Returns the given value with the MSB copied to all the other
39  * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
40  * However, this is not ensured by the C standard so you may need to
41  * replace this with something else on odd CPUs.
42  */
43 static ossl_inline unsigned int constant_time_msb(unsigned int a);
44
45 /*
46  * Returns 0xff..f if a < b and 0 otherwise.
47  */
48 static ossl_inline unsigned int constant_time_lt(unsigned int a,
49                                                  unsigned int b);
50 /* Convenience method for getting an 8-bit mask. */
51 static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
52                                                     unsigned int b);
53
54 /*
55  * Returns 0xff..f if a >= b and 0 otherwise.
56  */
57 static ossl_inline unsigned int constant_time_ge(unsigned int a,
58                                                  unsigned int b);
59 /* Convenience method for getting an 8-bit mask. */
60 static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
61                                                     unsigned int b);
62
63 /*
64  * Returns 0xff..f if a == 0 and 0 otherwise.
65  */
66 static ossl_inline unsigned int constant_time_is_zero(unsigned int a);
67 /* Convenience method for getting an 8-bit mask. */
68 static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a);
69
70 /*
71  * Returns 0xff..f if a == b and 0 otherwise.
72  */
73 static ossl_inline unsigned int constant_time_eq(unsigned int a,
74                                                  unsigned int b);
75 /* Convenience method for getting an 8-bit mask. */
76 static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
77                                                     unsigned int b);
78 /* Signed integers. */
79 static ossl_inline unsigned int constant_time_eq_int(int a, int b);
80 /* Convenience method for getting an 8-bit mask. */
81 static ossl_inline unsigned char constant_time_eq_int_8(int a, int b);
82
83 /*-
84  * Returns (mask & a) | (~mask & b).
85  *
86  * When |mask| is all 1s or all 0s (as returned by the methods above),
87  * the select methods return either |a| (if |mask| is nonzero) or |b|
88  * (if |mask| is zero).
89  */
90 static ossl_inline unsigned int constant_time_select(unsigned int mask,
91                                                      unsigned int a,
92                                                      unsigned int b);
93 /* Convenience method for unsigned chars. */
94 static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
95                                                         unsigned char a,
96                                                         unsigned char b);
97 /* Convenience method for signed integers. */
98 static ossl_inline int constant_time_select_int(unsigned int mask, int a,
99                                                 int b);
100
101 static ossl_inline unsigned int constant_time_msb(unsigned int a)
102 {
103     return 0 - (a >> (sizeof(a) * 8 - 1));
104 }
105
106 static ossl_inline size_t constant_time_msb_s(size_t a)
107 {
108     return 0 - (a >> (sizeof(a) * 8 - 1));
109 }
110
111 static ossl_inline unsigned int constant_time_lt(unsigned int a,
112                                                  unsigned int b)
113 {
114     return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
115 }
116
117 static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
118 {
119     return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
120 }
121
122 static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
123                                                     unsigned int b)
124 {
125     return (unsigned char)(constant_time_lt(a, b));
126 }
127
128 static ossl_inline unsigned int constant_time_ge(unsigned int a,
129                                                  unsigned int b)
130 {
131     return ~constant_time_lt(a, b);
132 }
133
134 static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
135 {
136     return ~constant_time_lt_s(a, b);
137 }
138
139 static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
140                                                     unsigned int b)
141 {
142     return (unsigned char)(constant_time_ge(a, b));
143 }
144
145 static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
146 {
147     return (unsigned char)(constant_time_ge_s(a, b));
148 }
149
150 static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
151 {
152     return constant_time_msb(~a & (a - 1));
153 }
154
155 static ossl_inline size_t constant_time_is_zero_s(size_t a)
156 {
157     return constant_time_msb_s(~a & (a - 1));
158 }
159
160 static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
161 {
162     return (unsigned char)(constant_time_is_zero(a));
163 }
164
165 static ossl_inline unsigned int constant_time_eq(unsigned int a,
166                                                  unsigned int b)
167 {
168     return constant_time_is_zero(a ^ b);
169 }
170
171 static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
172 {
173     return constant_time_is_zero_s(a ^ b);
174 }
175
176 static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
177                                                     unsigned int b)
178 {
179     return (unsigned char)(constant_time_eq(a, b));
180 }
181
182 static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
183 {
184     return (unsigned char)(constant_time_eq_s(a, b));
185 }
186
187 static ossl_inline unsigned int constant_time_eq_int(int a, int b)
188 {
189     return constant_time_eq((unsigned)(a), (unsigned)(b));
190 }
191
192 static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
193 {
194     return constant_time_eq_8((unsigned)(a), (unsigned)(b));
195 }
196
197 static ossl_inline unsigned int constant_time_select(unsigned int mask,
198                                                      unsigned int a,
199                                                      unsigned int b)
200 {
201     return (mask & a) | (~mask & b);
202 }
203
204 static ossl_inline size_t constant_time_select_s(size_t mask,
205                                                  size_t a,
206                                                  size_t b)
207 {
208     return (mask & a) | (~mask & b);
209 }
210
211 static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
212                                                         unsigned char a,
213                                                         unsigned char b)
214 {
215     return (unsigned char)(constant_time_select(mask, a, b));
216 }
217
218 static ossl_inline int constant_time_select_int(unsigned int mask, int a,
219                                                 int b)
220 {
221     return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
222 }
223
224 static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
225 {
226     return (int)(constant_time_select((unsigned)mask, (unsigned)(a),
227                                       (unsigned)(b)));
228 }
229
230 #ifdef __cplusplus
231 }
232 #endif
233
234 #endif                          /* HEADER_CONSTANT_TIME_LOCL_H */