1 /******************************************************************************
2  *  Copyright (c) 2022-2023 Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are met:
6  *
7  *  1) Redistributions of source code must retain the above copyright notice,
8  *     this list of conditions and the following disclaimer.
9  *
10  *  2) Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *
14  *  3) Neither the name of the copyright holder nor the names of its
15  *     contributors may be used to endorse or promote products derived from this
16  *     software without specific prior written permission.
17  *
18  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  *  POSSIBILITY OF SUCH DAMAGE.
29  *
30  ******************************************************************************/
31 #ifndef SHA256SW_H_
32 #define SHA256SW_H_
33 
34 /** ============================================================================
35  *  @file       sha256sw.h
36  */
37 /*!
38  *  @addtogroup sw_libraries_group
39  *  @{
40  *
41  *  @addtogroup sha2sw_api
42  *  @{
43  *  @brief      SHA2 256/224 SW APIs.
44  *
45  *
46  *  @anchor ti_SHA256_SW_LIBRARY_Overview
47  *  # Overview #
48  *  Provides top-level general purpose SHA2 256/224 APIs. SHA2 algorithm is
49  *  implemented in SW with no HW acceleration. The implementation is highly
50  *  optimized for speed and code size. These functions reside in ROM, and are
51  *  exposed through HAPI, and also through the function prototypes and macros below.
52  *
53  *
54  *  Availability of SHA2 224 depends on build configuration.
55  *  See file @ref sha2sw_config.h.
56  *
57  *  ## Limitations ##
58  *  @li A maximum of 512MiB may be hashed by this implementation. (SHA2
59  *      standard supports 2 million Terabytes for 224/256)
60  *  @li Input data may be 8-bit aligned. However, output digest must be
61  *      32-bit aligned.
62  *  @li Intermediate values, input data, and final digest value may be
63  *      left behind on the stack.
64  *
65  *  <hr>
66  *  @anchor ti_SHA256_SW_LIBRARY_Usage
67  *  # Usage #
68  *
69  *  There are two general ways to execute a SHA2 operation:
70  *
71  *  - one-step, using #SHA256SWHashData()
72  *  - multi-step, using #SHA256SWStart(), #SHA256SWAddData(), and
73  *    #SHA256SWFinalize()
74  *
75  *  The multi-step approach allows the hash to be extended by adding
76  *  more data.
77  *
78  *  All input data is to be in little-endian (LE) format and the resulting
79  *  hash values produced by these APIs are in LE format.
80  *
81  *  @anchor ti_SHA256_SW_LIBRARY_Synopsis
82  *  ## Synopsis
83  *
84  *  The following is a quick overview of one-step hashing.
85  *
86  *  @anchor ti_SHA256_SW_LIBRARY_Synopsis_Code
87  *  @code
88  *  // Import SHA2 SW Driver definitions
89  *  #include <sha256sw.h>
90  *
91  *  // Create an object and handle
92  *  SHA256SW_Object sha256SWObject;
93  *  SHA256SW_Handle sha256SWHandle = &sha256SWObject;
94  *
95  *  // Allocate space for digest output
96  *  uint32_t actualDigest[8];
97  *
98  *  result = SHA256SWHashData(sha256SWHandle, SHA2SW_HASH_TYPE_256,
99  *                             message, strlen(message), actualDigest);
100  *  @endcode
101  *
102  *  <hr>
103  *  @anchor ti_SHA256_SW_LIBRARY_Examples
104  *  # Examples
105  *  @li @ref ti_SHA256_SW_LIBRARY_Example_hashData "Hashing data in one call"
106  *  @li @ref ti_SHA256_SW_LIBRARY_Example_addData "Hashing data in multiple calls"
107  *
108  *  @anchor ti_SHA256_SW_LIBRARY_Example_hashData
109  *  ## Hashing data in one call
110  *
111  *  @code
112  *  SHA256SW_Object sha256SWObject;
113  *  SHA256SW_Handle sha256SWHandle = &sha256SWObject;
114  *  int_fast16_t sha2SWresult;
115  *  uint32_t finalDigest[8];
116  *  int notsame;
117  *
118  *  char message[] =
119  *          "abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn1234";
120  *  uint8_t expectedDigest[] =
121  *          { 0x60, 0x06, 0x00, 0x24, 0x13, 0xe4, 0x27, 0x0d,
122  *            0x4d, 0xdb, 0x66, 0x93, 0x42, 0xa9, 0xe2, 0xdb,
123  *            0x66, 0x5e, 0xc8, 0x70, 0x73, 0xc4, 0x2e, 0xb5,
124  *            0x44, 0x99, 0x62, 0xf1, 0x2a, 0xb2, 0xe8, 0x60 };
125  *
126  *  sha2SWresult = SHA256SWHashData(sha256SWHandle, SHA2SW_HASH_TYPE_256,
127  *                                   message, strlen(message), finalDigest);
128  *
129  *  if (sha2SWresult != SHA2SW_STATUS_SUCCESS)
130  *  {
131  *      while(1);
132  *  }
133  *
134  *  // NOTE: If expectedDigest is a secret value, a timing constant comparison
135  *  // routine shall be used instead of memcmp.
136  *  notsame = memcmp(finalDigest, expectedDigest, sizeof(finalDigest));
137  *
138  *  if (notsame)
139  *  {
140  *      while(1);
141  *  }
142  *  @endcode
143  *
144  *
145  *  @anchor ti_SHA256_SW_LIBRARY_Example_addData
146  *  ## Hashing data in multiple calls
147  *
148  *  @code
149  *  SHA256SW_Object sha256SWObject;
150  *  SHA256SW_Handle sha256SWHandle = &sha256SWObject;
151  *  int_fast16_t sha2SWresult;
152  *  uint32_t finalDigest[8];
153  *  int notsame;
154  *
155  *  char message[] =
156  *          "abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn1234";
157  *  uint8_t expectedDigest[] =
158  *          { 0x60, 0x06, 0x00, 0x24, 0x13, 0xe4, 0x27, 0x0d,
159  *            0x4d, 0xdb, 0x66, 0x93, 0x42, 0xa9, 0xe2, 0xdb,
160  *            0x66, 0x5e, 0xc8, 0x70, 0x73, 0xc4, 0x2e, 0xb5,
161  *            0x44, 0x99, 0x62, 0xf1, 0x2a, 0xb2, 0xe8, 0x60, };
162  *
163  *
164  *  sha2SWresult = SHA256SWStart(sha256SWHandle, SHA2SW_HASH_TYPE_256);
165  *
166  *  if (sha2SWresult == SHA2SW_STATUS_SUCCESS) {
167  *      sha2SWresult = SHA256SWAddData(sha256SWHandle, message, 20);
168  *  }
169  *
170  *  if (sha2SWresult == SHA2SW_STATUS_SUCCESS) {
171  *      sha2SWresult = SHA256SWAddData(sha256SWHandle, &message[20], strlen(message) - 20);
172  *  }
173  *
174  *  if (sha2SWresult == SHA2SW_STATUS_SUCCESS) {
175  *      sha2SWresult = SHA256SWFinalize(sha256SWHandle, finalDigest);
176  *  }
177  *
178  *  if (sha2SWresult != SHA2SW_STATUS_SUCCESS)
179  *  {
180  *      while(1);
181  *  }
182  *
183  *  // NOTE: If expectedDigest is a secret value, a timing constant comparison
184  *  // routine shall be used instead of memcmp.
185  *  notsame = memcmp(finalDigest, expectedDigest, sizeof(finalDigest));
186  *
187  *  if (notsame)
188  *  {
189  *      while(1);
190  *  }
191  *  @endcode
192  *
193  *
194  *  <hr>
195  *  @anchor ti_SHA256_SW_LIBRARY_configuration
196  *  # Configuration
197  *
198  *  See file @ref sha2sw_config.h for full configuration information.
199  *
200  *  If #SHA2SW_VALIDATE_INPUTS is not defined then:
201  *  @li the caller is responsible for ensuring all inputs are valid, and
202  *  @li the module's functions will only return #SHA2SW_STATUS_SUCCESS
203  *
204  */
205 
206 #include <stddef.h>
207 #include <stdint.h>
208 
209 #include "sha2sw_common.h"
210 #include "sha2sw_config.h"
211 
212 /*!
213  *  @brief SHA256SW Object
214  *
215  *  The application must not access any member variables of this structure!
216  */
217 typedef struct
218 {
219     uint32_t bitsProcessed; // Only 2^32 bits (512 MiBytes) are supported
220     int8_t offsetWb;        // Byte offset into Ws, used to load message
221     uint8_t reserved1;
222     uint8_t reserved2;
223     uint8_t reserved3;
224     uint32_t digest32[8]; // Holds intermediate/final digest
225     uint32_t Ws32[16];    // Message schedule, indexed by (s & 0xF),
226                           // where s = 63 - t, and t is NIST 180-4's
227                           // message schedule index
228 } SHA256SW_Object;
229 
230 /*!
231  *  @brief  A handle to a SHA256SW_Object.
232  */
233 typedef SHA256SW_Object *SHA256SW_Handle;
234 
235 /* Include this file after the type definitions above, to break cyclic dependency between hapi.h and sha256sw.h */
236 #include "hapi.h"
237 
238 /*!
239  *  @brief  Performs a complete hash operation, producing a final digest
240  *          for the data.
241  *
242  *  This function wraps #SHA256SWStart(), #SHA256SWAddData(), and
243  *  #SHA256SWFinalize().
244  *
245  *  There is no need to call #SHA256SWStart() prior to calling this function.
246  *
247  *  The total length of data that can be hashed by this implementation
248  *  is 512MiB (0x20000000 bytes.)
249  *
250  *  @param[in]  handle A #SHA256SW_Handle.
251  *
252  *  @param[in]  hashType The type of hash (256 or 224) to perform.
253  *
254  *  @param[in]  data data (message) to hash. May point to zero.
255  *
256  *  @param[in]  length the number of bytes (pointed to by @c data parameter)
257  *              to add to the hash.
258  *
259  *  @param[out]  digest Output location for the final digest. Must be
260  *               able to hold 32 bytes of output and be 32-bit aligned.
261  *
262  *  @retval #SHA2SW_STATUS_SUCCESS             The hash operation succeeded.
263  *  @retval #SHA2SW_STATUS_ERROR               The hash operation failed.
264  *  @retval #SHA2SW_STATUS_UNSUPPORTED         Requested Hash Type is unsupported.
265  *  @retval #SHA2SW_STATUS_LENGTH_TOO_LARGE    The requested length of data to hash
266  *                                             is more than the implementation
267  *                                             supports.
268  *  @retval #SHA2SW_STATUS_NULL_INPUT          One or more of the pointer inputs is
269  *                                             NULL.
270  *
271  */
272 extern int_fast16_t SHA256SWHashData(SHA256SW_Handle handle,
273                                      SHA2SW_HashType hashType,
274                                      const void *data,
275                                      size_t length,
276                                      uint32_t digest[8]);
277 
278 #define SHA256SWHashData HAPI_TABLE_POINTER->sha256SwHashData
279 
280 /*!
281  *  @brief  Initialize a SHA256SW_Handle, preparing for hashing data.
282  *
283  *  @param[in] handle A #SHA256SW_Handle.
284  *
285  *  @param[in] hashType The type of hash (256 or 224) to perform.
286  *
287  *  @retval #SHA2SW_STATUS_SUCCESS             The hash operation succeeded.
288  *  @retval #SHA2SW_STATUS_UNSUPPORTED         Requested Hash Type is unsupported.
289  *  @retval #SHA2SW_STATUS_NULL_INPUT          One or more of the pointer inputs is
290  *                                             NULL.
291  *
292  *  @sa     #SHA256SWAddData()
293  *  @sa     #SHA256SWFinalize()
294  */
295 extern int_fast16_t SHA256SWStart(SHA256SW_Handle handle, SHA2SW_HashType hashType);
296 
297 #define SHA256SWStart HAPI_TABLE_POINTER->sha256SwStart
298 
299 /*!
300  *  @brief  Add data to a SHA256/224 operation.
301  *
302  *  Adds data to a hash operation. The @c handle must have been
303  *  initialized by a call to SHA256SWStart first.
304  *
305  *  The total length of data that can be hashed by this implementation
306  *  is 512MiB (0x20000000 bytes.)
307  *
308  *  After passing in all data to be hashed, call #SHA256SWFinalize()
309  *  to obtain the final digest.
310  *
311  *  @pre    handle was previously passed to #SHA256SWStart().
312  *
313  *  @param[in]  handle A #SHA256SW_Handle.
314  *
315  *  @param[in]  data data (message) to add to the hash. May point to zero.
316  *
317  *  @param[in]  length the number of bytes (pointed to by @c data parameter)
318  *              to add to the hash.
319  *
320  *  @retval #SHA2SW_STATUS_SUCCESS             The hash operation succeeded.
321  *  @retval #SHA2SW_STATUS_LENGTH_TOO_LARGE    The requested length of data to hash
322  *                                             is more than the implementation
323  *                                             supports.
324  *  @retval #SHA2SW_STATUS_NULL_INPUT          One or more of the pointer inputs is
325  *                                             NULL.
326  *
327  *  @sa     #SHA256SWStart()
328  *  @sa     #SHA256SWFinalize()
329  */
330 extern int_fast16_t SHA256SWAddData(SHA256SW_Handle handle, const void *data, size_t length);
331 
332 #define SHA256SWAddData HAPI_TABLE_POINTER->sha256SwAddData
333 
334 /*!
335  *  @brief  Finalize a SHA256/224 operation, creating the final digest.
336  *
337  *  After calling this function, @c handle should not be used again
338  *  until it has been reinitialized via a call to #SHA256SWStart().
339  *
340  *  @pre    handle was previously passed to #SHA256SWStart() and data to
341  *          be hashed was passed to #SHA256SWAddData()
342  *
343  *  @param[in]  handle A #SHA256SW_Handle.
344  *
345  *  @param[out]  digest Output location for the final digest. Must be
346  *               able to hold 32 bytes of output and be 32-bit aligned.
347  *
348  *  @retval #SHA2SW_STATUS_SUCCESS             The hash operation succeeded.
349  *  @retval #SHA2SW_STATUS_NULL_INPUT          One or more of the pointer inputs is
350  *                                             NULL.
351  *
352  *  @sa     #SHA256SWStart()
353  *  @sa     #SHA256SWAddData()
354  */
355 extern int_fast16_t SHA256SWFinalize(SHA256SW_Handle handle, uint32_t digest[8]);
356 
357 #define SHA256SWFinalize HAPI_TABLE_POINTER->sha256SwFinalize
358 
359 /*! @}*/
360 /*! @}*/
361 
362 #endif /* SHA256SW_H_ */
363