1 /* 2 * Copyright (c) 2019-2023, Texas Instruments Incorporated 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of Texas Instruments Incorporated nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /** ============================================================================ 33 * @file CryptoUtils.h 34 * 35 * @brief A collection of utility functions for cryptographic purposes 36 * 37 */ 38 39 #ifndef ti_drivers_cryptoutils_utils_CryptoUtils__include 40 #define ti_drivers_cryptoutils_utils_CryptoUtils__include 41 42 #include <stdint.h> 43 #include <stdbool.h> 44 #include <string.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 /*! 51 * @brief Indicates the endianess (byte order) of a multi-byte value. 52 */ 53 typedef enum 54 { 55 CryptoUtils_ENDIANESS_BIG = 0u, /*!< MSB at lowest address. */ 56 CryptoUtils_ENDIANESS_LITTLE = 1u, /*!< LSB at highest address. */ 57 } CryptoUtils_Endianess; 58 59 /*! 60 * @brief Limit value of 0 61 * 62 * This is a value provided for convenience when checking a value 63 * against a range. 64 * 65 * @sa CryptoUtils_limitOne 66 * @sa CryptoUtils_isNumberInRange 67 */ 68 extern const uint8_t *CryptoUtils_limitZero; 69 70 /*! 71 * @brief Limit value of 1 72 * 73 * This is a value provided for convenience when checking a value 74 * against a range. 75 * 76 * @sa CryptoUtils_limitZero 77 * @sa CryptoUtils_isNumberInRange 78 */ 79 extern const uint8_t *CryptoUtils_limitOne; 80 81 /** 82 * @brief Compares two buffers for equality without branching 83 * 84 * @note This is not a drop-in replacement for memcmp! 85 * 86 * Most memcmp implementations break out of their comparison loop immediately 87 * once a mismatch is detected to save execution time. For cryptographic 88 * purposes, this is a flaw. 89 * 90 * This function compares two buffers without branching thus requiring a 91 * an amount of time that does not vary with the content of @c buffer0 and 92 * @c buffer1. 93 * 94 * @param buffer0 Buffer to compare against @c buffer1. 95 * @param buffer1 Buffer tp compare against @c buffer0 96 * @param bufferByteLength Length in bytes of @c buffer0 and @c buffer1. 97 * @retval true The contents of the buffers match. 98 * @retval false The contents of the buffers do not match. 99 */ 100 bool CryptoUtils_buffersMatch(const volatile void *volatile buffer0, 101 const volatile void *volatile buffer1, 102 size_t bufferByteLength); 103 104 /** 105 * @brief Compares two buffers for equality word-by-word without branching 106 * 107 * @note This is not a drop-in replacement for memcmp! 108 * 109 * Most memcmp implementations break out of their comparison loop immediately 110 * once a mismatch is detected to save execution time. For cryptographic 111 * purposes, this is a flaw. 112 * 113 * This function compares two buffers without branching thus requiring a 114 * an amount of time that does not vary with the content of @c buffer0 and 115 * @c buffer1. 116 * 117 * Unlike #CryptoUtils_buffersMatch(), this function expects @c buffer0 and 118 * @c buffer1 to be 32-bit aligned. It will only perform 32-bit aligned 119 * accesses to memory. This is needed to access the registers of certain 120 * peripherals. 121 * 122 * @param buffer0 Buffer to compare against @c buffer1. 123 * @param buffer1 Buffer tp compare against @c buffer0 124 * @param bufferByteLength Length in bytes of @c buffer0 and @c buffer1. 125 * Must be evenly divisible by sizeof(uint32_t). 126 * This function will return false if @c 127 * bufferByteLength is not evenly divisible by 128 * sizeof(uin32_t). 129 * @retval true The contents of the buffers match. 130 * @retval false The contents of the buffers do not match. 131 */ 132 bool CryptoUtils_buffersMatchWordAligned(const volatile uint32_t *volatile buffer0, 133 const volatile uint32_t *volatile buffer1, 134 size_t bufferByteLength); 135 136 /** 137 * @brief Check whether the provided buffer only contains 0x00 bytes 138 * 139 * @param buffer Buffer to search for non-zero bytes 140 * @param bufferByteLength Length of @c buffer in bytes 141 * 142 * @retval true The buffer contained only bytes with value 0x00 143 * @retval false The buffer contained at least one non-zero byte 144 */ 145 bool CryptoUtils_isBufferAllZeros(const void *buffer, size_t bufferByteLength); 146 147 /** 148 * @brief Copies @c val into the first @c count bytes of the buffer 149 * pointed to by @c dest. 150 * 151 * @param dest Pointer to destination buffer 152 * @param destSize Size of destination buffer in bytes 153 * @param val Fill byte value 154 * @param count Number of bytes to fill 155 * 156 */ 157 void CryptoUtils_memset(void *dest, size_t destSize, uint8_t val, size_t count); 158 159 /** 160 * @brief Reverses the byte order in a buffer of a given length 161 * 162 * The left-most byte will become the right-most byte and vice versa. 163 * 164 * @param buffer Buffer containing the data to be reversed. 165 * @param bufferByteLength Length in bytes of @c buffer. 166 */ 167 void CryptoUtils_reverseBufferBytewise(void *buffer, size_t bufferByteLength); 168 169 /** 170 * @brief Copies and pads an array of words. 171 * 172 * The \c source array is copied into the \c destination 173 * array. Writes are done word-wise. If \c sourceLength is not a multiple of 4, 174 * any remaining bytes up to the next word boundary are padded with 0. 175 * 176 * The length of the destination array must be a multiple of 4, rounded up to the 177 * padded \c sourceLength if required. 178 * 179 * @param source Source array 180 * 181 * @param destination Destination array 182 * 183 * @param sourceLength Length of the source array 184 */ 185 void CryptoUtils_copyPad(const void *source, uint32_t *destination, size_t sourceLength); 186 187 /** 188 * @brief Reverses, copies, and pads an array of words. 189 * 190 * The \c source array is reversed byte-wise and copied into the \c destination 191 * array. Writes are done word-wise. If \c sourceLength is not a multiple of 4, 192 * any remaining bytes up to the next word boundary are padded with 0. 193 * 194 * The length of the destination array must be a multiple of 4, rounded up to the 195 * padded \c sourceLength if required. 196 * 197 * @param source Source array 198 * 199 * @param destination Destination array 200 * 201 * @param sourceLength Length of the source array 202 */ 203 void CryptoUtils_reverseCopyPad(const void *source, uint32_t *destination, size_t sourceLength); 204 205 /** 206 * @brief Reverses and copies an array of bytes. 207 * 208 * The \c source array is reversed byte-wise and copied into the \c destination 209 * array. 210 * 211 * @param source Source array 212 * 213 * @param destination Destination array 214 * 215 * @param sourceLength Length of the source array 216 */ 217 void CryptoUtils_reverseCopy(const void *source, void *destination, size_t sourceLength); 218 219 /** 220 * @brief Checks if number is within the range [lowerLimit, upperLimit) 221 * 222 * Checks if the specified number is at greater than or equal to 223 * the lower limit and less than the upper limit. Note that the boundary 224 * set by the upper limit is not inclusive. 225 * 226 * Note that the special values of #CryptoUtils_limitZero and 227 * #CryptoUtils_limitOne are available to pass in for the @c lowerLimit. 228 * (These values can also be used for the @c upperLimit but their use for 229 * the upperLimit has no practical use.) 230 * 231 * If @c lowerLimit is NULL then the lower limit is taken as 0. 232 * If @c upperLimit is NULL then the upper limit is taken as 233 * 2<sup>(@c bitLength + 1)</sup>. 234 * 235 * The implemented algorithm is timing-constant when the following parameters 236 * are held constant: @c lowerLimit, @c upperLimit, @c bitLength, 237 * and @c endianess. Thus, the @c number being checked may change and 238 * timing will not leak its relation to the limits. However, timing may leak 239 * the bitLength, the endianess, and the use of #CryptoUtils_limitZero, 240 * #CryptoUtils_limitOne, and NULL for the limit values. 241 * 242 * @param number Pointer to number to check 243 * @param bitLength Length in bits of @c number, @c lowerLimit, and 244 * @c upperLimit. 245 * @param endianess The endianess of @c number, @c lowerLimit, and 246 * @c upperLimit. 247 * @param lowerLimit Pointer to lower limit value. 248 * @param upperLimit Pointer to upper limit value. 249 * @retval true The randomNumber is within 250 * [@c lowerLimit, @c upperLimit). 251 * @retval false The randomNumber is not within 252 * [@c lowerLimit, @c upperLimit). 253 */ 254 bool CryptoUtils_isNumberInRange(const void *number, 255 size_t bitLength, 256 CryptoUtils_Endianess endianess, 257 const void *lowerLimit, 258 const void *upperLimit); 259 260 #ifdef __cplusplus 261 } 262 #endif 263 264 #endif /* ti_drivers_cryptoutils_utils_CryptoUtils__include */ 265