constant_time_internal.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /**
  2. * Constant-time functions
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. #ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H
  8. #define MBEDTLS_CONSTANT_TIME_INTERNAL_H
  9. #include <stdint.h>
  10. #include <stddef.h>
  11. #include "common.h"
  12. #if defined(MBEDTLS_BIGNUM_C)
  13. #include "mbedtls/bignum.h"
  14. #endif
  15. /* The constant-time interface provides various operations that are likely
  16. * to result in constant-time code that does not branch or use conditional
  17. * instructions for secret data (for secret pointers, this also applies to
  18. * the data pointed to).
  19. *
  20. * It has three main parts:
  21. *
  22. * - boolean operations
  23. * These are all named mbedtls_ct_<type>_<operation>.
  24. * They operate over <type> and return mbedtls_ct_condition_t.
  25. * All arguments are considered secret.
  26. * example: bool x = y | z => x = mbedtls_ct_bool_or(y, z)
  27. * example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z)
  28. *
  29. * - conditional data selection
  30. * These are all named mbedtls_ct_<type>_if and mbedtls_ct_<type>_if_else_0
  31. * All arguments are considered secret.
  32. * example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c)
  33. * example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint_if_else_0(x, b)
  34. *
  35. * - block memory operations
  36. * Only some arguments are considered secret, as documented for each
  37. * function.
  38. * example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...)
  39. *
  40. * mbedtls_ct_condition_t must be treated as opaque and only created and
  41. * manipulated via the functions in this header. The compiler should never
  42. * be able to prove anything about its value at compile-time.
  43. *
  44. * mbedtls_ct_uint_t is an unsigned integer type over which constant time
  45. * operations may be performed via the functions in this header. It is as big
  46. * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast
  47. * to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other
  48. * not-larger integer types).
  49. *
  50. * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations
  51. * are used to ensure that the generated code is constant time. For other
  52. * architectures, it uses a plain C fallback designed to yield constant-time code
  53. * (this has been observed to be constant-time on latest gcc, clang and MSVC
  54. * as of May 2023).
  55. *
  56. * For readability, the static inline definitions are separated out into
  57. * constant_time_impl.h.
  58. */
  59. #if (SIZE_MAX > 0xffffffffffffffffULL)
  60. /* Pointer size > 64-bit */
  61. typedef size_t mbedtls_ct_condition_t;
  62. typedef size_t mbedtls_ct_uint_t;
  63. typedef ptrdiff_t mbedtls_ct_int_t;
  64. #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX))
  65. #elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64)
  66. /* 32-bit < pointer size <= 64-bit, or 64-bit MPI */
  67. typedef uint64_t mbedtls_ct_condition_t;
  68. typedef uint64_t mbedtls_ct_uint_t;
  69. typedef int64_t mbedtls_ct_int_t;
  70. #define MBEDTLS_CT_SIZE_64
  71. #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX))
  72. #else
  73. /* Pointer size <= 32-bit, and no 64-bit MPIs */
  74. typedef uint32_t mbedtls_ct_condition_t;
  75. typedef uint32_t mbedtls_ct_uint_t;
  76. typedef int32_t mbedtls_ct_int_t;
  77. #define MBEDTLS_CT_SIZE_32
  78. #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX))
  79. #endif
  80. #define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0))
  81. /* ============================================================================
  82. * Boolean operations
  83. */
  84. /** Convert a number into a mbedtls_ct_condition_t.
  85. *
  86. * \param x Number to convert.
  87. *
  88. * \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0
  89. *
  90. */
  91. static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x);
  92. /** Boolean "not equal" operation.
  93. *
  94. * Functionally equivalent to:
  95. *
  96. * \p x != \p y
  97. *
  98. * \param x The first value to analyze.
  99. * \param y The second value to analyze.
  100. *
  101. * \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE.
  102. */
  103. static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
  104. /** Boolean "equals" operation.
  105. *
  106. * Functionally equivalent to:
  107. *
  108. * \p x == \p y
  109. *
  110. * \param x The first value to analyze.
  111. * \param y The second value to analyze.
  112. *
  113. * \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE.
  114. */
  115. static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
  116. mbedtls_ct_uint_t y);
  117. /** Boolean "less than" operation.
  118. *
  119. * Functionally equivalent to:
  120. *
  121. * \p x < \p y
  122. *
  123. * \param x The first value to analyze.
  124. * \param y The second value to analyze.
  125. *
  126. * \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE.
  127. */
  128. static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
  129. /** Boolean "greater than" operation.
  130. *
  131. * Functionally equivalent to:
  132. *
  133. * \p x > \p y
  134. *
  135. * \param x The first value to analyze.
  136. * \param y The second value to analyze.
  137. *
  138. * \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE.
  139. */
  140. static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
  141. mbedtls_ct_uint_t y);
  142. /** Boolean "greater or equal" operation.
  143. *
  144. * Functionally equivalent to:
  145. *
  146. * \p x >= \p y
  147. *
  148. * \param x The first value to analyze.
  149. * \param y The second value to analyze.
  150. *
  151. * \return MBEDTLS_CT_TRUE if \p x >= \p y,
  152. * otherwise MBEDTLS_CT_FALSE.
  153. */
  154. static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
  155. mbedtls_ct_uint_t y);
  156. /** Boolean "less than or equal" operation.
  157. *
  158. * Functionally equivalent to:
  159. *
  160. * \p x <= \p y
  161. *
  162. * \param x The first value to analyze.
  163. * \param y The second value to analyze.
  164. *
  165. * \return MBEDTLS_CT_TRUE if \p x <= \p y,
  166. * otherwise MBEDTLS_CT_FALSE.
  167. */
  168. static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
  169. mbedtls_ct_uint_t y);
  170. /** Boolean not-equals operation.
  171. *
  172. * Functionally equivalent to:
  173. *
  174. * \p x != \p y
  175. *
  176. * \param x The first value to analyze.
  177. * \param y The second value to analyze.
  178. *
  179. * \note This is more efficient than mbedtls_ct_uint_ne if both arguments are
  180. * mbedtls_ct_condition_t.
  181. *
  182. * \return MBEDTLS_CT_TRUE if \p x != \p y,
  183. * otherwise MBEDTLS_CT_FALSE.
  184. */
  185. static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
  186. mbedtls_ct_condition_t y);
  187. /** Boolean "and" operation.
  188. *
  189. * Functionally equivalent to:
  190. *
  191. * \p x && \p y
  192. *
  193. * \param x The first value to analyze.
  194. * \param y The second value to analyze.
  195. *
  196. * \return MBEDTLS_CT_TRUE if \p x && \p y,
  197. * otherwise MBEDTLS_CT_FALSE.
  198. */
  199. static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
  200. mbedtls_ct_condition_t y);
  201. /** Boolean "or" operation.
  202. *
  203. * Functionally equivalent to:
  204. *
  205. * \p x || \p y
  206. *
  207. * \param x The first value to analyze.
  208. * \param y The second value to analyze.
  209. *
  210. * \return MBEDTLS_CT_TRUE if \p x || \p y,
  211. * otherwise MBEDTLS_CT_FALSE.
  212. */
  213. static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
  214. mbedtls_ct_condition_t y);
  215. /** Boolean "not" operation.
  216. *
  217. * Functionally equivalent to:
  218. *
  219. * ! \p x
  220. *
  221. * \param x The value to invert
  222. *
  223. * \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE.
  224. */
  225. static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x);
  226. /* ============================================================================
  227. * Data selection operations
  228. */
  229. /** Choose between two size_t values.
  230. *
  231. * Functionally equivalent to:
  232. *
  233. * condition ? if1 : if0.
  234. *
  235. * \param condition Condition to test.
  236. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  237. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
  238. *
  239. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  240. */
  241. static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
  242. size_t if1,
  243. size_t if0);
  244. /** Choose between two unsigned values.
  245. *
  246. * Functionally equivalent to:
  247. *
  248. * condition ? if1 : if0.
  249. *
  250. * \param condition Condition to test.
  251. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  252. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
  253. *
  254. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  255. */
  256. static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
  257. unsigned if1,
  258. unsigned if0);
  259. /** Choose between two mbedtls_ct_condition_t values.
  260. *
  261. * Functionally equivalent to:
  262. *
  263. * condition ? if1 : if0.
  264. *
  265. * \param condition Condition to test.
  266. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  267. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
  268. *
  269. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  270. */
  271. static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,
  272. mbedtls_ct_condition_t if1,
  273. mbedtls_ct_condition_t if0);
  274. #if defined(MBEDTLS_BIGNUM_C)
  275. /** Choose between two mbedtls_mpi_uint values.
  276. *
  277. * Functionally equivalent to:
  278. *
  279. * condition ? if1 : if0.
  280. *
  281. * \param condition Condition to test.
  282. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  283. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
  284. *
  285. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  286. */
  287. static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \
  288. mbedtls_mpi_uint if1, \
  289. mbedtls_mpi_uint if0);
  290. #endif
  291. /** Choose between an unsigned value and 0.
  292. *
  293. * Functionally equivalent to:
  294. *
  295. * condition ? if1 : 0.
  296. *
  297. * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but
  298. * results in smaller code size.
  299. *
  300. * \param condition Condition to test.
  301. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  302. *
  303. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  304. */
  305. static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1);
  306. /** Choose between an mbedtls_ct_condition_t and 0.
  307. *
  308. * Functionally equivalent to:
  309. *
  310. * condition ? if1 : 0.
  311. *
  312. * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but
  313. * results in smaller code size.
  314. *
  315. * \param condition Condition to test.
  316. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  317. *
  318. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  319. */
  320. static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,
  321. mbedtls_ct_condition_t if1);
  322. /** Choose between a size_t value and 0.
  323. *
  324. * Functionally equivalent to:
  325. *
  326. * condition ? if1 : 0.
  327. *
  328. * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but
  329. * results in smaller code size.
  330. *
  331. * \param condition Condition to test.
  332. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  333. *
  334. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  335. */
  336. static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1);
  337. #if defined(MBEDTLS_BIGNUM_C)
  338. /** Choose between an mbedtls_mpi_uint value and 0.
  339. *
  340. * Functionally equivalent to:
  341. *
  342. * condition ? if1 : 0.
  343. *
  344. * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but
  345. * results in smaller code size.
  346. *
  347. * \param condition Condition to test.
  348. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  349. *
  350. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  351. */
  352. static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
  353. mbedtls_mpi_uint if1);
  354. #endif
  355. /** Constant-flow char selection
  356. *
  357. * \param low Secret. Bottom of range
  358. * \param high Secret. Top of range
  359. * \param c Secret. Value to compare to range
  360. * \param t Secret. Value to return, if in range
  361. *
  362. * \return \p t if \p low <= \p c <= \p high, 0 otherwise.
  363. */
  364. static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
  365. unsigned char high,
  366. unsigned char c,
  367. unsigned char t);
  368. /** Choose between two error values. The values must be in the range [-32767..0].
  369. *
  370. * Functionally equivalent to:
  371. *
  372. * condition ? if1 : if0.
  373. *
  374. * \param condition Condition to test.
  375. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  376. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
  377. *
  378. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  379. */
  380. static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0);
  381. /** Choose between an error value and 0. The error value must be in the range [-32767..0].
  382. *
  383. * Functionally equivalent to:
  384. *
  385. * condition ? if1 : 0.
  386. *
  387. * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but
  388. * results in smaller code size.
  389. *
  390. * \param condition Condition to test.
  391. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
  392. *
  393. * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  394. */
  395. static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1);
  396. /* ============================================================================
  397. * Block memory operations
  398. */
  399. #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
  400. /** Conditionally set a block of memory to zero.
  401. *
  402. * Regardless of the condition, every byte will be read once and written to
  403. * once.
  404. *
  405. * \param condition Secret. Condition to test.
  406. * \param buf Secret. Pointer to the start of the buffer.
  407. * \param len Number of bytes to set to zero.
  408. *
  409. * \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees
  410. * about not being optimised away if the memory is never read again.
  411. */
  412. void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len);
  413. /** Shift some data towards the left inside a buffer.
  414. *
  415. * Functionally equivalent to:
  416. *
  417. * memmove(start, start + offset, total - offset);
  418. * memset(start + (total - offset), 0, offset);
  419. *
  420. * Timing independence comes at the expense of performance.
  421. *
  422. * \param start Secret. Pointer to the start of the buffer.
  423. * \param total Total size of the buffer.
  424. * \param offset Secret. Offset from which to copy \p total - \p offset bytes.
  425. */
  426. void mbedtls_ct_memmove_left(void *start,
  427. size_t total,
  428. size_t offset);
  429. #endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */
  430. /** Conditional memcpy.
  431. *
  432. * Functionally equivalent to:
  433. *
  434. * if (condition) {
  435. * memcpy(dest, src1, len);
  436. * } else {
  437. * if (src2 != NULL)
  438. * memcpy(dest, src2, len);
  439. * }
  440. *
  441. * It will always read len bytes from src1.
  442. * If src2 != NULL, it will always read len bytes from src2.
  443. * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest).
  444. *
  445. * \param condition The condition
  446. * \param dest Secret. Destination pointer.
  447. * \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE).
  448. * This may be equal to \p dest, but may not overlap in other ways.
  449. * \param src2 Secret (contents only - may branch to determine if this parameter is NULL).
  450. * Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL.
  451. * This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1.
  452. * \param len Number of bytes to copy.
  453. */
  454. void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
  455. unsigned char *dest,
  456. const unsigned char *src1,
  457. const unsigned char *src2,
  458. size_t len
  459. );
  460. /** Copy data from a secret position.
  461. *
  462. * Functionally equivalent to:
  463. *
  464. * memcpy(dst, src + offset, len)
  465. *
  466. * This function copies \p len bytes from \p src + \p offset to
  467. * \p dst, with a code flow and memory access pattern that does not depend on
  468. * \p offset, but only on \p offset_min, \p offset_max and \p len.
  469. *
  470. * \note This function reads from \p dest, but the value that
  471. * is read does not influence the result and this
  472. * function's behavior is well-defined regardless of the
  473. * contents of the buffers. This may result in false
  474. * positives from static or dynamic analyzers, especially
  475. * if \p dest is not initialized.
  476. *
  477. * \param dest Secret. The destination buffer. This must point to a writable
  478. * buffer of at least \p len bytes.
  479. * \param src Secret. The base of the source buffer. This must point to a
  480. * readable buffer of at least \p offset_max + \p len
  481. * bytes. Shouldn't overlap with \p dest
  482. * \param offset Secret. The offset in the source buffer from which to copy.
  483. * This must be no less than \p offset_min and no greater
  484. * than \p offset_max.
  485. * \param offset_min The minimal value of \p offset.
  486. * \param offset_max The maximal value of \p offset.
  487. * \param len The number of bytes to copy.
  488. */
  489. void mbedtls_ct_memcpy_offset(unsigned char *dest,
  490. const unsigned char *src,
  491. size_t offset,
  492. size_t offset_min,
  493. size_t offset_max,
  494. size_t len);
  495. /* Documented in include/mbedtls/constant_time.h. a and b are secret.
  496. int mbedtls_ct_memcmp(const void *a,
  497. const void *b,
  498. size_t n);
  499. */
  500. #if defined(MBEDTLS_NIST_KW_C)
  501. /** Constant-time buffer comparison without branches.
  502. *
  503. * Similar to mbedtls_ct_memcmp, except that the result only depends on part of
  504. * the input data - differences in the head or tail are ignored. Functionally equivalent to:
  505. *
  506. * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail)
  507. *
  508. * Time taken depends on \p n, but not on \p skip_head or \p skip_tail .
  509. *
  510. * Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n.
  511. *
  512. * \param a Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
  513. * \param b Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
  514. * \param n The number of bytes to examine (total size of the buffers).
  515. * \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer.
  516. * These bytes will still be read.
  517. * \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer.
  518. * These bytes will still be read.
  519. *
  520. * \return Zero if the contents of the two buffers are the same, otherwise non-zero.
  521. */
  522. int mbedtls_ct_memcmp_partial(const void *a,
  523. const void *b,
  524. size_t n,
  525. size_t skip_head,
  526. size_t skip_tail);
  527. #endif
  528. /* Include the implementation of static inline functions above. */
  529. #include "constant_time_impl.h"
  530. #endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */