constant_time_test.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* crypto/constant_time_test.c */
  2. /*-
  3. * Utilities for constant-time cryptography.
  4. *
  5. * Author: Emilia Kasper (emilia@openssl.org)
  6. * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
  7. * (Google).
  8. * ====================================================================
  9. * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. All advertising materials mentioning features or use of this software
  20. * must display the following acknowledgement:
  21. * "This product includes cryptographic software written by
  22. * Eric Young (eay@cryptsoft.com)"
  23. * The word 'cryptographic' can be left out if the rouines from the library
  24. * being used are not cryptographic related :-).
  25. * 4. If you include any Windows specific code (or a derivative thereof) from
  26. * the apps directory (application code) you must include an acknowledgement:
  27. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  30. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  33. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  39. * SUCH DAMAGE.
  40. *
  41. * The licence and distribution terms for any publically available version or
  42. * derivative of this code cannot be changed. i.e. this code cannot simply be
  43. * copied and put under another distribution licence
  44. * [including the GNU Public Licence.]
  45. */
  46. #include "../crypto/constant_time_locl.h"
  47. #include <limits.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
  51. static const unsigned int CONSTTIME_FALSE = 0;
  52. static const unsigned char CONSTTIME_TRUE_8 = 0xff;
  53. static const unsigned char CONSTTIME_FALSE_8 = 0;
  54. static int test_binary_op(unsigned int (*op) (unsigned int a, unsigned int b),
  55. const char *op_name, unsigned int a, unsigned int b,
  56. int is_true)
  57. {
  58. unsigned c = op(a, b);
  59. if (is_true && c != CONSTTIME_TRUE) {
  60. fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
  61. "(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c);
  62. return 1;
  63. } else if (!is_true && c != CONSTTIME_FALSE) {
  64. fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
  65. "(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE, c);
  66. return 1;
  67. }
  68. return 0;
  69. }
  70. static int test_binary_op_8(unsigned
  71. char (*op) (unsigned int a, unsigned int b),
  72. const char *op_name, unsigned int a,
  73. unsigned int b, int is_true)
  74. {
  75. unsigned char c = op(a, b);
  76. if (is_true && c != CONSTTIME_TRUE_8) {
  77. fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
  78. "(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c);
  79. return 1;
  80. } else if (!is_true && c != CONSTTIME_FALSE_8) {
  81. fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
  82. "(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8, c);
  83. return 1;
  84. }
  85. return 0;
  86. }
  87. static int test_is_zero(unsigned int a)
  88. {
  89. unsigned int c = constant_time_is_zero(a);
  90. if (a == 0 && c != CONSTTIME_TRUE) {
  91. fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
  92. "expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c);
  93. return 1;
  94. } else if (a != 0 && c != CONSTTIME_FALSE) {
  95. fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
  96. "expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE, c);
  97. return 1;
  98. }
  99. return 0;
  100. }
  101. static int test_is_zero_8(unsigned int a)
  102. {
  103. unsigned char c = constant_time_is_zero_8(a);
  104. if (a == 0 && c != CONSTTIME_TRUE_8) {
  105. fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
  106. "expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c);
  107. return 1;
  108. } else if (a != 0 && c != CONSTTIME_FALSE) {
  109. fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
  110. "expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8, c);
  111. return 1;
  112. }
  113. return 0;
  114. }
  115. static int test_select(unsigned int a, unsigned int b)
  116. {
  117. unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
  118. if (selected != a) {
  119. fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
  120. "%du): expected %du(first value), got %du\n",
  121. CONSTTIME_TRUE, a, b, a, selected);
  122. return 1;
  123. }
  124. selected = constant_time_select(CONSTTIME_FALSE, a, b);
  125. if (selected != b) {
  126. fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
  127. "%du): expected %du(second value), got %du\n",
  128. CONSTTIME_FALSE, a, b, b, selected);
  129. return 1;
  130. }
  131. return 0;
  132. }
  133. static int test_select_8(unsigned char a, unsigned char b)
  134. {
  135. unsigned char selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
  136. if (selected != a) {
  137. fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
  138. "%u): expected %u(first value), got %u\n",
  139. CONSTTIME_TRUE, a, b, a, selected);
  140. return 1;
  141. }
  142. selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
  143. if (selected != b) {
  144. fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
  145. "%u): expected %u(second value), got %u\n",
  146. CONSTTIME_FALSE, a, b, b, selected);
  147. return 1;
  148. }
  149. return 0;
  150. }
  151. static int test_select_int(int a, int b)
  152. {
  153. int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
  154. if (selected != a) {
  155. fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
  156. "%d): expected %d(first value), got %d\n",
  157. CONSTTIME_TRUE, a, b, a, selected);
  158. return 1;
  159. }
  160. selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
  161. if (selected != b) {
  162. fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
  163. "%d): expected %d(second value), got %d\n",
  164. CONSTTIME_FALSE, a, b, b, selected);
  165. return 1;
  166. }
  167. return 0;
  168. }
  169. static int test_eq_int(int a, int b)
  170. {
  171. unsigned int equal = constant_time_eq_int(a, b);
  172. if (a == b && equal != CONSTTIME_TRUE) {
  173. fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
  174. "expected %du(TRUE), got %du\n", a, b, CONSTTIME_TRUE, equal);
  175. return 1;
  176. } else if (a != b && equal != CONSTTIME_FALSE) {
  177. fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
  178. "expected %du(FALSE), got %du\n",
  179. a, b, CONSTTIME_FALSE, equal);
  180. return 1;
  181. }
  182. return 0;
  183. }
  184. static int test_eq_int_8(int a, int b)
  185. {
  186. unsigned char equal = constant_time_eq_int_8(a, b);
  187. if (a == b && equal != CONSTTIME_TRUE_8) {
  188. fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
  189. "expected %u(TRUE), got %u\n", a, b, CONSTTIME_TRUE_8, equal);
  190. return 1;
  191. } else if (a != b && equal != CONSTTIME_FALSE_8) {
  192. fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
  193. "expected %u(FALSE), got %u\n",
  194. a, b, CONSTTIME_FALSE_8, equal);
  195. return 1;
  196. }
  197. return 0;
  198. }
  199. static unsigned int test_values[] =
  200. { 0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
  201. UINT_MAX / 2, UINT_MAX / 2 + 1, UINT_MAX - 1,
  202. UINT_MAX
  203. };
  204. static unsigned char test_values_8[] =
  205. { 0, 1, 2, 20, 32, 127, 128, 129, 255 };
  206. static int signed_test_values[] = { 0, 1, -1, 1024, -1024, 12345, -12345,
  207. 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1,
  208. INT_MIN + 1
  209. };
  210. int main(int argc, char *argv[])
  211. {
  212. unsigned int a, b, i, j;
  213. int c, d;
  214. unsigned char e, f;
  215. int num_failed = 0, num_all = 0;
  216. fprintf(stdout, "Testing constant time operations...\n");
  217. for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
  218. a = test_values[i];
  219. num_failed += test_is_zero(a);
  220. num_failed += test_is_zero_8(a);
  221. num_all += 2;
  222. for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
  223. b = test_values[j];
  224. num_failed += test_binary_op(&constant_time_lt,
  225. "constant_time_lt", a, b, a < b);
  226. num_failed += test_binary_op_8(&constant_time_lt_8,
  227. "constant_time_lt_8", a, b, a < b);
  228. num_failed += test_binary_op(&constant_time_lt,
  229. "constant_time_lt_8", b, a, b < a);
  230. num_failed += test_binary_op_8(&constant_time_lt_8,
  231. "constant_time_lt_8", b, a, b < a);
  232. num_failed += test_binary_op(&constant_time_ge,
  233. "constant_time_ge", a, b, a >= b);
  234. num_failed += test_binary_op_8(&constant_time_ge_8,
  235. "constant_time_ge_8", a, b,
  236. a >= b);
  237. num_failed +=
  238. test_binary_op(&constant_time_ge, "constant_time_ge", b, a,
  239. b >= a);
  240. num_failed +=
  241. test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8", b,
  242. a, b >= a);
  243. num_failed +=
  244. test_binary_op(&constant_time_eq, "constant_time_eq", a, b,
  245. a == b);
  246. num_failed +=
  247. test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", a,
  248. b, a == b);
  249. num_failed +=
  250. test_binary_op(&constant_time_eq, "constant_time_eq", b, a,
  251. b == a);
  252. num_failed +=
  253. test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", b,
  254. a, b == a);
  255. num_failed += test_select(a, b);
  256. num_all += 13;
  257. }
  258. }
  259. for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
  260. c = signed_test_values[i];
  261. for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
  262. d = signed_test_values[j];
  263. num_failed += test_select_int(c, d);
  264. num_failed += test_eq_int(c, d);
  265. num_failed += test_eq_int_8(c, d);
  266. num_all += 3;
  267. }
  268. }
  269. for (i = 0; i < sizeof(test_values_8); ++i) {
  270. e = test_values_8[i];
  271. for (j = 0; j < sizeof(test_values_8); ++j) {
  272. f = test_values_8[j];
  273. num_failed += test_select_8(e, f);
  274. num_all += 1;
  275. }
  276. }
  277. if (!num_failed) {
  278. fprintf(stdout, "ok (ran %d tests)\n", num_all);
  279. return EXIT_SUCCESS;
  280. } else {
  281. fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
  282. return EXIT_FAILURE;
  283. }
  284. }