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