constant_time_locl.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright 2014-2018 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. #ifndef HEADER_CONSTANT_TIME_LOCL_H
  10. # define HEADER_CONSTANT_TIME_LOCL_H
  11. # include <stdlib.h>
  12. # include <string.h>
  13. # include <openssl/e_os2.h> /* For 'ossl_inline' */
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. /*-
  18. * The boolean methods return a bitmask of all ones (0xff...f) for true
  19. * and 0 for false. This is useful for choosing a value based on the result
  20. * of a conditional in constant time. For example,
  21. * if (a < b) {
  22. * c = a;
  23. * } else {
  24. * c = b;
  25. * }
  26. * can be written as
  27. * unsigned int lt = constant_time_lt(a, b);
  28. * c = constant_time_select(lt, a, b);
  29. */
  30. /* Returns the given value with the MSB copied to all the other bits. */
  31. static ossl_inline unsigned int constant_time_msb(unsigned int a);
  32. /* Convenience method for uint32_t. */
  33. static ossl_inline uint32_t constant_time_msb_32(uint32_t a);
  34. /* Convenience method for uint64_t. */
  35. static ossl_inline uint64_t constant_time_msb_64(uint64_t a);
  36. /* Returns 0xff..f if a < b and 0 otherwise. */
  37. static ossl_inline unsigned int constant_time_lt(unsigned int a,
  38. unsigned int b);
  39. /* Convenience method for getting an 8-bit mask. */
  40. static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
  41. unsigned int b);
  42. /* Convenience method for uint64_t. */
  43. static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b);
  44. /* Returns 0xff..f if a >= b and 0 otherwise. */
  45. static ossl_inline unsigned int constant_time_ge(unsigned int a,
  46. unsigned int b);
  47. /* Convenience method for getting an 8-bit mask. */
  48. static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
  49. unsigned int b);
  50. /* Returns 0xff..f if a == 0 and 0 otherwise. */
  51. static ossl_inline unsigned int constant_time_is_zero(unsigned int a);
  52. /* Convenience method for getting an 8-bit mask. */
  53. static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a);
  54. /* Convenience method for getting a 32-bit mask. */
  55. static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a);
  56. /* Returns 0xff..f if a == b and 0 otherwise. */
  57. static ossl_inline unsigned int constant_time_eq(unsigned int a,
  58. unsigned int b);
  59. /* Convenience method for getting an 8-bit mask. */
  60. static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
  61. unsigned int b);
  62. /* Signed integers. */
  63. static ossl_inline unsigned int constant_time_eq_int(int a, int b);
  64. /* Convenience method for getting an 8-bit mask. */
  65. static ossl_inline unsigned char constant_time_eq_int_8(int a, int b);
  66. /*-
  67. * Returns (mask & a) | (~mask & b).
  68. *
  69. * When |mask| is all 1s or all 0s (as returned by the methods above),
  70. * the select methods return either |a| (if |mask| is nonzero) or |b|
  71. * (if |mask| is zero).
  72. */
  73. static ossl_inline unsigned int constant_time_select(unsigned int mask,
  74. unsigned int a,
  75. unsigned int b);
  76. /* Convenience method for unsigned chars. */
  77. static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
  78. unsigned char a,
  79. unsigned char b);
  80. /* Convenience method for uint32_t. */
  81. static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
  82. uint32_t b);
  83. /* Convenience method for uint64_t. */
  84. static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
  85. uint64_t b);
  86. /* Convenience method for signed integers. */
  87. static ossl_inline int constant_time_select_int(unsigned int mask, int a,
  88. int b);
  89. static ossl_inline unsigned int constant_time_msb(unsigned int a)
  90. {
  91. return 0 - (a >> (sizeof(a) * 8 - 1));
  92. }
  93. static ossl_inline uint32_t constant_time_msb_32(uint32_t a)
  94. {
  95. return 0 - (a >> 31);
  96. }
  97. static ossl_inline uint64_t constant_time_msb_64(uint64_t a)
  98. {
  99. return 0 - (a >> 63);
  100. }
  101. static ossl_inline size_t constant_time_msb_s(size_t a)
  102. {
  103. return 0 - (a >> (sizeof(a) * 8 - 1));
  104. }
  105. static ossl_inline unsigned int constant_time_lt(unsigned int a,
  106. unsigned int b)
  107. {
  108. return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
  109. }
  110. static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
  111. {
  112. return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
  113. }
  114. static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
  115. unsigned int b)
  116. {
  117. return (unsigned char)constant_time_lt(a, b);
  118. }
  119. static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b)
  120. {
  121. return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b)));
  122. }
  123. static ossl_inline unsigned int constant_time_ge(unsigned int a,
  124. unsigned int b)
  125. {
  126. return ~constant_time_lt(a, b);
  127. }
  128. static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
  129. {
  130. return ~constant_time_lt_s(a, b);
  131. }
  132. static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
  133. unsigned int b)
  134. {
  135. return (unsigned char)constant_time_ge(a, b);
  136. }
  137. static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
  138. {
  139. return (unsigned char)constant_time_ge_s(a, b);
  140. }
  141. static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
  142. {
  143. return constant_time_msb(~a & (a - 1));
  144. }
  145. static ossl_inline size_t constant_time_is_zero_s(size_t a)
  146. {
  147. return constant_time_msb_s(~a & (a - 1));
  148. }
  149. static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
  150. {
  151. return (unsigned char)constant_time_is_zero(a);
  152. }
  153. static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a)
  154. {
  155. return constant_time_msb_32(~a & (a - 1));
  156. }
  157. static ossl_inline unsigned int constant_time_eq(unsigned int a,
  158. unsigned int b)
  159. {
  160. return constant_time_is_zero(a ^ b);
  161. }
  162. static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
  163. {
  164. return constant_time_is_zero_s(a ^ b);
  165. }
  166. static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
  167. unsigned int b)
  168. {
  169. return (unsigned char)constant_time_eq(a, b);
  170. }
  171. static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
  172. {
  173. return (unsigned char)constant_time_eq_s(a, b);
  174. }
  175. static ossl_inline unsigned int constant_time_eq_int(int a, int b)
  176. {
  177. return constant_time_eq((unsigned)(a), (unsigned)(b));
  178. }
  179. static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
  180. {
  181. return constant_time_eq_8((unsigned)(a), (unsigned)(b));
  182. }
  183. static ossl_inline unsigned int constant_time_select(unsigned int mask,
  184. unsigned int a,
  185. unsigned int b)
  186. {
  187. return (mask & a) | (~mask & b);
  188. }
  189. static ossl_inline size_t constant_time_select_s(size_t mask,
  190. size_t a,
  191. size_t b)
  192. {
  193. return (mask & a) | (~mask & b);
  194. }
  195. static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
  196. unsigned char a,
  197. unsigned char b)
  198. {
  199. return (unsigned char)constant_time_select(mask, a, b);
  200. }
  201. static ossl_inline int constant_time_select_int(unsigned int mask, int a,
  202. int b)
  203. {
  204. return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b));
  205. }
  206. static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
  207. {
  208. return (int)constant_time_select((unsigned)mask, (unsigned)(a),
  209. (unsigned)(b));
  210. }
  211. static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
  212. uint32_t b)
  213. {
  214. return (mask & a) | (~mask & b);
  215. }
  216. static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
  217. uint64_t b)
  218. {
  219. return (mask & a) | (~mask & b);
  220. }
  221. /*
  222. * mask must be 0xFFFFFFFF or 0x00000000.
  223. *
  224. * if (mask) {
  225. * uint32_t tmp = *a;
  226. *
  227. * *a = *b;
  228. * *b = tmp;
  229. * }
  230. */
  231. static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a,
  232. uint32_t *b)
  233. {
  234. uint32_t xor = *a ^ *b;
  235. xor &= mask;
  236. *a ^= xor;
  237. *b ^= xor;
  238. }
  239. /*
  240. * mask must be 0xFFFFFFFF or 0x00000000.
  241. *
  242. * if (mask) {
  243. * uint64_t tmp = *a;
  244. *
  245. * *a = *b;
  246. * *b = tmp;
  247. * }
  248. */
  249. static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a,
  250. uint64_t *b)
  251. {
  252. uint64_t xor = *a ^ *b;
  253. xor &= mask;
  254. *a ^= xor;
  255. *b ^= xor;
  256. }
  257. /*
  258. * table is a two dimensional array of bytes. Each row has rowsize elements.
  259. * Copies row number idx into out. rowsize and numrows are not considered
  260. * private.
  261. */
  262. static ossl_inline void constant_time_lookup(void *out,
  263. const void *table,
  264. size_t rowsize,
  265. size_t numrows,
  266. size_t idx)
  267. {
  268. size_t i, j;
  269. const unsigned char *tablec = (const unsigned char *)table;
  270. unsigned char *outc = (unsigned char *)out;
  271. unsigned char mask;
  272. memset(out, 0, rowsize);
  273. /* Note idx may underflow - but that is well defined */
  274. for (i = 0; i < numrows; i++, idx--) {
  275. mask = (unsigned char)constant_time_is_zero_s(idx);
  276. for (j = 0; j < rowsize; j++)
  277. *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0);
  278. }
  279. }
  280. #ifdef __cplusplus
  281. }
  282. #endif
  283. #endif /* HEADER_CONSTANT_TIME_LOCL_H */