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