Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

308 linhas
11 KiB

  1. /*
  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. #include "internal.h"
  46. #include <limits.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
  50. static const unsigned int CONSTTIME_FALSE = 0;
  51. static const uint8_t CONSTTIME_TRUE_8 = 0xff;
  52. static const uint8_t CONSTTIME_FALSE_8 = 0;
  53. static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
  54. const char* op_name, unsigned int a, unsigned int b,
  55. int is_true) {
  56. unsigned c = op(a, b);
  57. if (is_true && c != CONSTTIME_TRUE) {
  58. fprintf(stderr,
  59. "Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
  60. op_name, a, b, CONSTTIME_TRUE, c);
  61. return 1;
  62. } else if (!is_true && c != CONSTTIME_FALSE) {
  63. fprintf(stderr,
  64. "Test failed for %s(%du, %du): expected %du (FALSE), got %du\n",
  65. op_name, a, b, CONSTTIME_FALSE, c);
  66. return 1;
  67. }
  68. return 0;
  69. }
  70. static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
  71. const char* op_name, unsigned int a, unsigned int b,
  72. int is_true) {
  73. uint8_t c = op(a, b);
  74. if (is_true && c != CONSTTIME_TRUE_8) {
  75. fprintf(stderr,
  76. "Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
  77. op_name, a, b, CONSTTIME_TRUE_8, c);
  78. return 1;
  79. } else if (!is_true && c != CONSTTIME_FALSE_8) {
  80. fprintf(stderr,
  81. "Test failed for %s(%du, %du): expected %u (FALSE), got %u\n",
  82. 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. unsigned int c = constant_time_is_zero(a);
  89. if (a == 0 && c != CONSTTIME_TRUE) {
  90. fprintf(stderr,
  91. "Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
  92. "got %du\n",
  93. a, CONSTTIME_TRUE, c);
  94. return 1;
  95. } else if (a != 0 && c != CONSTTIME_FALSE) {
  96. fprintf(stderr,
  97. "Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
  98. "got %du\n",
  99. a, CONSTTIME_FALSE, c);
  100. return 1;
  101. }
  102. return 0;
  103. }
  104. static int test_is_zero_8(unsigned int a) {
  105. uint8_t c = constant_time_is_zero_8(a);
  106. if (a == 0 && c != CONSTTIME_TRUE_8) {
  107. fprintf(stderr,
  108. "Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
  109. "got %u\n",
  110. a, CONSTTIME_TRUE_8, c);
  111. return 1;
  112. } else if (a != 0 && c != CONSTTIME_FALSE) {
  113. fprintf(stderr,
  114. "Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
  115. "got %u\n",
  116. a, CONSTTIME_FALSE_8, c);
  117. return 1;
  118. }
  119. return 0;
  120. }
  121. static int test_select(unsigned int a, unsigned int b) {
  122. unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
  123. if (selected != a) {
  124. fprintf(stderr,
  125. "Test failed for constant_time_select(%du, %du,"
  126. "%du): expected %du(first value), got %du\n",
  127. CONSTTIME_TRUE, a, b, a, selected);
  128. return 1;
  129. }
  130. selected = constant_time_select(CONSTTIME_FALSE, a, b);
  131. if (selected != b) {
  132. fprintf(stderr,
  133. "Test failed for constant_time_select(%du, %du,"
  134. "%du): expected %du(second value), got %du\n",
  135. CONSTTIME_FALSE, a, b, b, selected);
  136. return 1;
  137. }
  138. return 0;
  139. }
  140. static int test_select_8(uint8_t a, uint8_t b) {
  141. uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
  142. if (selected != a) {
  143. fprintf(stderr,
  144. "Test failed for constant_time_select(%u, %u,"
  145. "%u): expected %u(first value), got %u\n",
  146. CONSTTIME_TRUE, a, b, a, selected);
  147. return 1;
  148. }
  149. selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
  150. if (selected != b) {
  151. fprintf(stderr,
  152. "Test failed for constant_time_select(%u, %u,"
  153. "%u): expected %u(second value), got %u\n",
  154. CONSTTIME_FALSE, a, b, b, selected);
  155. return 1;
  156. }
  157. return 0;
  158. }
  159. static int test_select_int(int a, int b) {
  160. int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
  161. if (selected != a) {
  162. fprintf(stderr,
  163. "Test failed for constant_time_select(%du, %d,"
  164. "%d): expected %d(first value), got %d\n",
  165. CONSTTIME_TRUE, a, b, a, selected);
  166. return 1;
  167. }
  168. selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
  169. if (selected != b) {
  170. fprintf(stderr,
  171. "Test failed for constant_time_select(%du, %d,"
  172. "%d): expected %d(second value), got %d\n",
  173. CONSTTIME_FALSE, a, b, b, selected);
  174. return 1;
  175. }
  176. return 0;
  177. }
  178. static int test_eq_int(int a, int b) {
  179. unsigned int equal = constant_time_eq_int(a, b);
  180. if (a == b && equal != CONSTTIME_TRUE) {
  181. fprintf(stderr,
  182. "Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
  183. "got %du\n",
  184. a, b, CONSTTIME_TRUE, equal);
  185. return 1;
  186. } else if (a != b && equal != CONSTTIME_FALSE) {
  187. fprintf(stderr,
  188. "Test failed for constant_time_eq_int(%d, %d): expected "
  189. "%du(FALSE), got %du\n",
  190. a, b, CONSTTIME_FALSE, equal);
  191. return 1;
  192. }
  193. return 0;
  194. }
  195. static int test_eq_int_8(int a, int b) {
  196. uint8_t equal = constant_time_eq_int_8(a, b);
  197. if (a == b && equal != CONSTTIME_TRUE_8) {
  198. fprintf(stderr,
  199. "Test failed for constant_time_eq_int_8(%d, %d): expected "
  200. "%u(TRUE), got %u\n",
  201. a, b, CONSTTIME_TRUE_8, equal);
  202. return 1;
  203. } else if (a != b && equal != CONSTTIME_FALSE_8) {
  204. fprintf(stderr,
  205. "Test failed for constant_time_eq_int_8(%d, %d): expected "
  206. "%u(FALSE), got %u\n",
  207. a, b, CONSTTIME_FALSE_8, equal);
  208. return 1;
  209. }
  210. return 0;
  211. }
  212. static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
  213. UINT_MAX / 2, UINT_MAX / 2 + 1,
  214. UINT_MAX - 1, UINT_MAX};
  215. static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
  216. static int signed_test_values[] = {
  217. 0, 1, -1, 1024, -1024, 12345, -12345,
  218. 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
  219. int main(int argc, char* argv[]) {
  220. unsigned int a, b, i, j;
  221. int c, d;
  222. uint8_t e, f;
  223. int num_failed = 0, num_all = 0;
  224. fprintf(stdout, "Testing constant time operations...\n");
  225. for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
  226. a = test_values[i];
  227. num_failed += test_is_zero(a);
  228. num_failed += test_is_zero_8(a);
  229. num_all += 2;
  230. for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
  231. b = test_values[j];
  232. num_failed +=
  233. test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
  234. num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
  235. a, b, a < b);
  236. num_failed +=
  237. test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
  238. num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
  239. b, a, b < a);
  240. num_failed +=
  241. test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
  242. num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
  243. a, b, a >= b);
  244. num_failed +=
  245. test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
  246. num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
  247. b, a, b >= a);
  248. num_failed +=
  249. test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
  250. num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
  251. a, b, a == b);
  252. num_failed +=
  253. test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
  254. num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
  255. b, a, b == a);
  256. num_failed += test_select(a, b);
  257. num_all += 13;
  258. }
  259. }
  260. for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
  261. c = signed_test_values[i];
  262. for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
  263. d = signed_test_values[j];
  264. num_failed += test_select_int(c, d);
  265. num_failed += test_eq_int(c, d);
  266. num_failed += test_eq_int_8(c, d);
  267. num_all += 3;
  268. }
  269. }
  270. for (i = 0; i < sizeof(test_values_8); ++i) {
  271. e = test_values_8[i];
  272. for (j = 0; j < sizeof(test_values_8); ++j) {
  273. f = test_values_8[j];
  274. num_failed += test_select_8(e, f);
  275. num_all += 1;
  276. }
  277. }
  278. if (!num_failed) {
  279. fprintf(stdout, "ok (ran %d tests)\n", num_all);
  280. fprintf(stdout, "PASS\n");
  281. return EXIT_SUCCESS;
  282. } else {
  283. fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
  284. return EXIT_FAILURE;
  285. }
  286. }