quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

constant_time_internal.h (20735B)


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