man3/OPENSSL_ia32cap.pod: clarify AVX512 support in clang context.
[openssl.git] / test / constant_time_test.c
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 #include "internal/constant_time_locl.h"
11 #include "e_os.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15
16 #include "internal/numbers.h"
17
18 static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
19 static const unsigned int CONSTTIME_FALSE = 0;
20 static const unsigned char CONSTTIME_TRUE_8 = 0xff;
21 static const unsigned char CONSTTIME_FALSE_8 = 0;
22 static const size_t CONSTTIME_TRUE_S = ~((size_t)0);
23 static const size_t CONSTTIME_FALSE_S = 0;
24
25 static int test_binary_op(unsigned int (*op) (unsigned int a, unsigned int b),
26                           const char *op_name, unsigned int a, unsigned int b,
27                           int is_true)
28 {
29     unsigned c = op(a, b);
30     if (is_true && c != CONSTTIME_TRUE) {
31         fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
32                 "(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c);
33         return 1;
34     } else if (!is_true && c != CONSTTIME_FALSE) {
35         fprintf(stderr, "Test failed for  %s(%du, %du): expected %du "
36                 "(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE, c);
37         return 1;
38     }
39     return 0;
40 }
41
42 static int test_binary_op_8(unsigned
43                             char (*op) (unsigned int a, unsigned int b),
44                             const char *op_name, unsigned int a,
45                             unsigned int b, int is_true)
46 {
47     unsigned char c = op(a, b);
48     if (is_true && c != CONSTTIME_TRUE_8) {
49         fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
50                 "(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c);
51         return 1;
52     } else if (!is_true && c != CONSTTIME_FALSE_8) {
53         fprintf(stderr, "Test failed for  %s(%du, %du): expected %u "
54                 "(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8, c);
55         return 1;
56     }
57     return 0;
58 }
59
60 static int test_binary_op_s(size_t (*op) (size_t a, size_t b),
61                             const char *op_name, size_t a, size_t b,
62                             int is_true)
63 {
64     size_t c = op(a, b);
65     if (is_true && c != CONSTTIME_TRUE_S) {
66         fprintf(stderr, "Test failed for %s(%"OSSLzu", %"OSSLzu
67         "): expected %"OSSLzu" (TRUE), got %"OSSLzu"\n",
68         op_name, a, b, CONSTTIME_TRUE_S, c);
69         return 1;
70     } else if (!is_true && c != CONSTTIME_FALSE_S) {
71         fprintf(stderr, "Test failed for  %s(%"OSSLzu", %"OSSLzu
72         "): expected %" OSSLzu " (FALSE), got %"OSSLzu"\n",
73         op_name, a, b, CONSTTIME_FALSE_S, c);
74         return 1;
75     }
76     return 0;
77 }
78
79 static int test_is_zero(unsigned int a)
80 {
81     unsigned int c = constant_time_is_zero(a);
82     if (a == 0 && c != CONSTTIME_TRUE) {
83         fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
84                 "expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c);
85         return 1;
86     } else if (a != 0 && c != CONSTTIME_FALSE) {
87         fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
88                 "expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE, c);
89         return 1;
90     }
91     return 0;
92 }
93
94 static int test_is_zero_8(unsigned int a)
95 {
96     unsigned char c = constant_time_is_zero_8(a);
97     if (a == 0 && c != CONSTTIME_TRUE_8) {
98         fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
99                 "expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c);
100         return 1;
101     } else if (a != 0 && c != CONSTTIME_FALSE) {
102         fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
103                 "expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8, c);
104         return 1;
105     }
106     return 0;
107 }
108
109 static int test_is_zero_s(size_t a)
110 {
111     size_t c = constant_time_is_zero_s(a);
112     if (a == 0 && c != CONSTTIME_TRUE_S) {
113         fprintf(stderr, "Test failed for constant_time_is_zero_s(%"OSSLzu"): "
114                 "expected %"OSSLzu" (TRUE), got %"OSSLzu"\n",
115                 a, CONSTTIME_TRUE_S, c);
116         return 1;
117     } else if (a != 0 && c != CONSTTIME_FALSE) {
118         fprintf(stderr, "Test failed for constant_time_is_zero_s(%"OSSLzu"): "
119                 "expected %"OSSLzu" (FALSE), got %"OSSLzu"\n",
120                 a, CONSTTIME_FALSE_S, c);
121         return 1;
122     }
123     return 0;
124 }
125 static int test_select(unsigned int a, unsigned int b)
126 {
127     unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
128     if (selected != a) {
129         fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
130                 "%du): expected %du(first value), got %du\n",
131                 CONSTTIME_TRUE, a, b, a, selected);
132         return 1;
133     }
134     selected = constant_time_select(CONSTTIME_FALSE, a, b);
135     if (selected != b) {
136         fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
137                 "%du): expected %du(second value), got %du\n",
138                 CONSTTIME_FALSE, a, b, b, selected);
139         return 1;
140     }
141     return 0;
142 }
143
144 static int test_select_8(unsigned char a, unsigned char b)
145 {
146     unsigned char selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
147     if (selected != a) {
148         fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
149                 "%u): expected %u(first value), got %u\n",
150                 CONSTTIME_TRUE, a, b, a, selected);
151         return 1;
152     }
153     selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
154     if (selected != b) {
155         fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
156                 "%u): expected %u(second value), got %u\n",
157                 CONSTTIME_FALSE, a, b, b, selected);
158         return 1;
159     }
160     return 0;
161 }
162
163 static int test_select_int(int a, int b)
164 {
165     int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
166     if (selected != a) {
167         fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
168                 "%d): expected %d(first value), got %d\n",
169                 CONSTTIME_TRUE, a, b, a, selected);
170         return 1;
171     }
172     selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
173     if (selected != b) {
174         fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
175                 "%d): expected %d(second value), got %d\n",
176                 CONSTTIME_FALSE, a, b, b, selected);
177         return 1;
178     }
179     return 0;
180 }
181
182
183 static int test_select_s(size_t a, size_t b)
184 {
185     size_t selected = constant_time_select_s(CONSTTIME_TRUE_S, a, b);
186     if (selected != a) {
187         fprintf(stderr, "Test failed for constant_time_select_s(%"OSSLzu
188                 ", %"OSSLzu",%"OSSLzu"): expected %"OSSLzu
189                 "(first value), got %"OSSLzu"\n",
190                 CONSTTIME_TRUE_S, a, b, a, selected);
191         return 1;
192     }
193     selected = constant_time_select_s(CONSTTIME_FALSE_S, a, b);
194     if (selected != b) {
195         fprintf(stderr, "Test failed for constant_time_select_s(%"OSSLzu
196                 ", %"OSSLzu",%"OSSLzu"): expected %"OSSLzu
197                 "(second value), got %"OSSLzu"\n",
198                 CONSTTIME_FALSE_S, a, b, b, selected);
199         return 1;
200     }
201     return 0;
202 }
203
204 static int test_eq_int(int a, int b)
205 {
206     unsigned int equal = constant_time_eq_int(a, b);
207     if (a == b && equal != CONSTTIME_TRUE) {
208         fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
209                 "expected %du(TRUE), got %du\n", a, b, CONSTTIME_TRUE, equal);
210         return 1;
211     } else if (a != b && equal != CONSTTIME_FALSE) {
212         fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
213                 "expected %du(FALSE), got %du\n",
214                 a, b, CONSTTIME_FALSE, equal);
215         return 1;
216     }
217     return 0;
218 }
219
220 static int test_eq_int_8(int a, int b)
221 {
222     unsigned char equal = constant_time_eq_int_8(a, b);
223     if (a == b && equal != CONSTTIME_TRUE_8) {
224         fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
225                 "expected %u(TRUE), got %u\n", a, b, CONSTTIME_TRUE_8, equal);
226         return 1;
227     } else if (a != b && equal != CONSTTIME_FALSE_8) {
228         fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
229                 "expected %u(FALSE), got %u\n",
230                 a, b, CONSTTIME_FALSE_8, equal);
231         return 1;
232     }
233     return 0;
234 }
235
236 static int test_eq_s(size_t a, size_t b)
237 {
238     size_t equal = constant_time_eq_s(a, b);
239     if (a == b && equal != CONSTTIME_TRUE_S) {
240         fprintf(stderr, "Test failed for constant_time_eq_int(%"OSSLzu
241                 ", %"OSSLzu"): expected %"OSSLzu"(TRUE), got %"OSSLzu"\n",
242                 a, b, CONSTTIME_TRUE_S, equal);
243         return 1;
244     } else if (a != b && equal != CONSTTIME_FALSE_S) {
245         fprintf(stderr, "Test failed for constant_time_eq_int(%"OSSLzu", %"
246                 OSSLzu"): expected %"OSSLzu"(FALSE), got %"OSSLzu"\n",
247                 a, b, CONSTTIME_FALSE_S, equal);
248         return 1;
249     }
250     return 0;
251 }
252
253 static unsigned int test_values[] =
254     { 0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
255     UINT_MAX / 2, UINT_MAX / 2 + 1, UINT_MAX - 1,
256     UINT_MAX
257 };
258
259 static unsigned char test_values_8[] =
260     { 0, 1, 2, 20, 32, 127, 128, 129, 255 };
261
262 static int signed_test_values[] = { 0, 1, -1, 1024, -1024, 12345, -12345,
263     32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1,
264     INT_MIN + 1
265 };
266
267 static size_t test_values_s[] =
268     { 0, 1, 1024, 12345, 32000, SIZE_MAX / 2 - 1,
269     SIZE_MAX / 2, SIZE_MAX / 2 + 1, SIZE_MAX - 1,
270     SIZE_MAX
271 };
272
273 int main(int argc, char *argv[])
274 {
275     unsigned int a, b, i, j;
276     int c, d;
277     unsigned char e, f;
278     size_t g, h;
279     int num_failed = 0, num_all = 0;
280     fprintf(stdout, "Testing constant time operations...\n");
281
282     if (OSSL_NELEM(test_values) != OSSL_NELEM(test_values_s)) {
283         fprintf(stdout, "Unexpected number of tests\n");
284         return EXIT_FAILURE;
285     }
286
287     for (i = 0; i < OSSL_NELEM(test_values); ++i) {
288         a = test_values[i];
289         g = test_values_s[i];
290         num_failed += test_is_zero(a);
291         num_failed += test_is_zero_8(a);
292         num_failed += test_is_zero_s(g);
293         num_all += 3;
294         for (j = 0; j < OSSL_NELEM(test_values); ++j) {
295             b = test_values[j];
296             h = test_values[j];
297             num_failed += test_binary_op(&constant_time_lt,
298                                          "constant_time_lt", a, b, a < b);
299             num_failed += test_binary_op_8(&constant_time_lt_8,
300                                            "constant_time_lt_8", a, b, a < b);
301             num_failed += test_binary_op_s(&constant_time_lt_s,
302                                            "constant_time_lt_s", g, h, g < h);
303             num_failed += test_binary_op(&constant_time_lt,
304                                          "constant_time_lt", b, a, b < a);
305             num_failed += test_binary_op_8(&constant_time_lt_8,
306                                            "constant_time_lt_8", b, a, b < a);
307             num_failed += test_binary_op_s(&constant_time_lt_s,
308                                            "constant_time_lt_s", h, g, h < g);
309             num_failed += test_binary_op(&constant_time_ge,
310                                          "constant_time_ge", a, b, a >= b);
311             num_failed += test_binary_op_8(&constant_time_ge_8,
312                                            "constant_time_ge_8", a, b,
313                                            a >= b);
314             num_failed += test_binary_op_s(&constant_time_ge_s,
315                                            "constant_time_ge_s", g, h, g >= h);
316             num_failed +=
317                 test_binary_op(&constant_time_ge, "constant_time_ge", b, a,
318                                b >= a);
319             num_failed +=
320                 test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8", b,
321                                  a, b >= a);
322             num_failed +=
323                 test_binary_op_s(&constant_time_ge_s, "constant_time_ge_s", h, g,
324                                  h >= g);
325             num_failed +=
326                 test_binary_op(&constant_time_eq, "constant_time_eq", a, b,
327                                a == b);
328             num_failed +=
329                 test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", a,
330                                  b, a == b);
331             num_failed +=
332                 test_binary_op_s(&constant_time_eq_s, "constant_time_eq_s", g, h,
333                                  g == h);
334             num_failed +=
335                 test_binary_op(&constant_time_eq, "constant_time_eq", b, a,
336                                b == a);
337             num_failed +=
338                 test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", b,
339                                  a, b == a);
340             num_failed +=
341                 test_binary_op_s(&constant_time_eq_s, "constant_time_eq_s", h, g,
342                                  h == g);
343             num_failed += test_select(a, b);
344             num_failed += test_select_s(g, h);
345             num_failed += test_eq_s(g, h);
346             num_all += 21;
347         }
348     }
349
350     for (i = 0; i < OSSL_NELEM(signed_test_values); ++i) {
351         c = signed_test_values[i];
352         for (j = 0; j < OSSL_NELEM(signed_test_values); ++j) {
353             d = signed_test_values[j];
354             num_failed += test_select_int(c, d);
355             num_failed += test_eq_int(c, d);
356             num_failed += test_eq_int_8(c, d);
357             num_all += 3;
358         }
359     }
360
361     for (i = 0; i < sizeof(test_values_8); ++i) {
362         e = test_values_8[i];
363         for (j = 0; j < sizeof(test_values_8); ++j) {
364             f = test_values_8[j];
365             num_failed += test_select_8(e, f);
366             num_all += 1;
367         }
368     }
369
370     if (!num_failed) {
371         fprintf(stdout, "success (ran %d tests)\n", num_all);
372         return EXIT_SUCCESS;
373     } else {
374         fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
375         return EXIT_FAILURE;
376     }
377 }