m480_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file m480_crypto_hash.c
3  * @brief M480 hash hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "m480.h"
36 #include "core/crypto.h"
39 #include "hash/hash_algorithms.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (M480_CRYPTO_HASH_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Update hash value
48  * @param[in] data Pointer to the input buffer
49  * @param[in] length Length of the input buffer
50  **/
51 
52 void hashProcessData(const uint8_t *data, size_t length)
53 {
54  size_t i;
55 
56  //Process input data
57  for(i = 0; i < length; i += 4)
58  {
59  //Wait for the DATINREQ bit to be set
60  while((CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk) == 0)
61  {
62  }
63 
64  //Write one word of data
65  CRPT->HMAC_DATIN = __UNALIGNED_UINT32_READ(data + i);
66  }
67 
68  //Wait for the processing to complete
69  while((CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk) == 0)
70  {
71  }
72 }
73 
74 
75 #if (SHA1_SUPPORT == ENABLED)
76 
77 /**
78  * @brief Digest a message using SHA-1
79  * @param[in] data Pointer to the message being hashed
80  * @param[in] length Length of the message
81  * @param[out] digest Pointer to the calculated digest
82  * @return Error code
83  **/
84 
85 error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
86 {
87  size_t n;
88  uint32_t temp;
89  uint8_t buffer[64];
90 
91  //Acquire exclusive access to the CRYPTO module
93 
94  //Reset CRYPTO controller
95  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
96  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
97 
98  //Select the relevant hash algorithm
99  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
101 
102  //Start SHA engine
103  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
104 
105  //Digest the message
106  for(n = length; n >= 64; n -= 64)
107  {
108  //Update hash value
109  hashProcessData(data, 64);
110  //Advance the data pointer
111  data = (uint8_t *) data + 64;
112  }
113 
114  //Copy the partial block, is any
115  osMemset(buffer, 0, 64);
116  osMemcpy(buffer, data, n);
117 
118  //Append the first byte of the padding string
119  buffer[n] = 0x80;
120 
121  //Pad the message so that its length is congruent to 56 modulo 64
122  if(n >= 56)
123  {
124  hashProcessData(buffer, 64);
125  osMemset(buffer, 0, 64);
126  }
127 
128  //Append the length of the original message
129  STORE64BE(length * 8, buffer + 56);
130 
131  //Process the final block
132  hashProcessData(buffer, 64);
133 
134  //Save the resulting hash value
135  temp = CRPT->HMAC_DGST[0];
136  __UNALIGNED_UINT32_WRITE(digest, temp);
137  temp = CRPT->HMAC_DGST[1];
138  __UNALIGNED_UINT32_WRITE(digest + 4, temp);
139  temp = CRPT->HMAC_DGST[2];
140  __UNALIGNED_UINT32_WRITE(digest + 8, temp);
141  temp = CRPT->HMAC_DGST[3];
142  __UNALIGNED_UINT32_WRITE(digest + 12, temp);
143  temp = CRPT->HMAC_DGST[4];
144  __UNALIGNED_UINT32_WRITE(digest + 16, temp);
145 
146  //Stop SHA engine
147  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
148 
149  //Release exclusive access to the CRYPTO module
151 
152  //Sucessful processing
153  return NO_ERROR;
154 }
155 
156 #endif
157 #if (SHA224_SUPPORT == ENABLED)
158 
159 /**
160  * @brief Digest a message using SHA-224
161  * @param[in] data Pointer to the message being hashed
162  * @param[in] length Length of the message
163  * @param[out] digest Pointer to the calculated digest
164  * @return Error code
165  **/
166 
167 error_t sha224Compute(const void *data, size_t length, uint8_t *digest)
168 {
169  size_t n;
170  uint32_t temp;
171  uint8_t buffer[64];
172 
173  //Acquire exclusive access to the CRYPTO module
175 
176  //Reset CRYPTO controller
177  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
178  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
179 
180  //Select the relevant hash algorithm
181  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
183 
184  //Start SHA engine
185  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
186 
187  //Digest the message
188  for(n = length; n >= 64; n -= 64)
189  {
190  //Update hash value
191  hashProcessData(data, 64);
192  //Advance the data pointer
193  data = (uint8_t *) data + 64;
194  }
195 
196  //Copy the partial block, is any
197  osMemset(buffer, 0, 64);
198  osMemcpy(buffer, data, n);
199 
200  //Append the first byte of the padding string
201  buffer[n] = 0x80;
202 
203  //Pad the message so that its length is congruent to 56 modulo 64
204  if(n >= 56)
205  {
206  hashProcessData(buffer, 64);
207  osMemset(buffer, 0, 64);
208  }
209 
210  //Append the length of the original message
211  STORE64BE(length * 8, buffer + 56);
212 
213  //Process the final block
214  hashProcessData(buffer, 64);
215 
216  //Save the resulting hash value
217  temp = CRPT->HMAC_DGST[0];
218  __UNALIGNED_UINT32_WRITE(digest, temp);
219  temp = CRPT->HMAC_DGST[1];
220  __UNALIGNED_UINT32_WRITE(digest + 4, temp);
221  temp = CRPT->HMAC_DGST[2];
222  __UNALIGNED_UINT32_WRITE(digest + 8, temp);
223  temp = CRPT->HMAC_DGST[3];
224  __UNALIGNED_UINT32_WRITE(digest + 12, temp);
225  temp = CRPT->HMAC_DGST[4];
226  __UNALIGNED_UINT32_WRITE(digest + 16, temp);
227  temp = CRPT->HMAC_DGST[5];
228  __UNALIGNED_UINT32_WRITE(digest + 20, temp);
229  temp = CRPT->HMAC_DGST[6];
230  __UNALIGNED_UINT32_WRITE(digest + 24, temp);
231 
232  //Stop SHA engine
233  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
234 
235  //Release exclusive access to the CRYPTO module
237 
238  //Sucessful processing
239  return NO_ERROR;
240 }
241 
242 #endif
243 #if (SHA256_SUPPORT == ENABLED)
244 
245 /**
246  * @brief Digest a message using SHA-256
247  * @param[in] data Pointer to the message being hashed
248  * @param[in] length Length of the message
249  * @param[out] digest Pointer to the calculated digest
250  * @return Error code
251  **/
252 
253 error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
254 {
255  size_t n;
256  uint32_t temp;
257  uint8_t buffer[64];
258 
259  //Acquire exclusive access to the CRYPTO module
261 
262  //Reset CRYPTO controller
263  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
264  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
265 
266  //Select the relevant hash algorithm
267  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
269 
270  //Start SHA engine
271  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
272 
273  //Digest the message
274  for(n = length; n >= 64; n -= 64)
275  {
276  //Update hash value
277  hashProcessData(data, 64);
278  //Advance the data pointer
279  data = (uint8_t *) data + 64;
280  }
281 
282  //Copy the partial block, is any
283  osMemset(buffer, 0, 64);
284  osMemcpy(buffer, data, n);
285 
286  //Append the first byte of the padding string
287  buffer[n] = 0x80;
288 
289  //Pad the message so that its length is congruent to 56 modulo 64
290  if(n >= 56)
291  {
292  hashProcessData(buffer, 64);
293  osMemset(buffer, 0, 64);
294  }
295 
296  //Append the length of the original message
297  STORE64BE(length * 8, buffer + 56);
298 
299  //Process the final block
300  hashProcessData(buffer, 64);
301 
302  //Save the resulting hash value
303  temp = CRPT->HMAC_DGST[0];
304  __UNALIGNED_UINT32_WRITE(digest, temp);
305  temp = CRPT->HMAC_DGST[1];
306  __UNALIGNED_UINT32_WRITE(digest + 4, temp);
307  temp = CRPT->HMAC_DGST[2];
308  __UNALIGNED_UINT32_WRITE(digest + 8, temp);
309  temp = CRPT->HMAC_DGST[3];
310  __UNALIGNED_UINT32_WRITE(digest + 12, temp);
311  temp = CRPT->HMAC_DGST[4];
312  __UNALIGNED_UINT32_WRITE(digest + 16, temp);
313  temp = CRPT->HMAC_DGST[5];
314  __UNALIGNED_UINT32_WRITE(digest + 20, temp);
315  temp = CRPT->HMAC_DGST[6];
316  __UNALIGNED_UINT32_WRITE(digest + 24, temp);
317  temp = CRPT->HMAC_DGST[7];
318  __UNALIGNED_UINT32_WRITE(digest + 28, temp);
319 
320  //Stop SHA engine
321  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
322 
323  //Release exclusive access to the CRYPTO module
325 
326  //Sucessful processing
327  return NO_ERROR;
328 }
329 
330 #endif
331 #if (SHA384_SUPPORT == ENABLED)
332 
333 /**
334  * @brief Digest a message using SHA-384
335  * @param[in] data Pointer to the message being hashed
336  * @param[in] length Length of the message
337  * @param[out] digest Pointer to the calculated digest
338  * @return Error code
339  **/
340 
341 error_t sha384Compute(const void *data, size_t length, uint8_t *digest)
342 {
343  size_t n;
344  uint32_t temp;
345  uint8_t buffer[128];
346 
347  //Acquire exclusive access to the CRYPTO module
349 
350  //Reset CRYPTO controller
351  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
352  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
353 
354  //Select the relevant hash algorithm
355  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
357 
358  //Start SHA engine
359  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
360 
361  //Digest the message
362  for(n = length; n >= 128; n -= 128)
363  {
364  //Update hash value
365  hashProcessData(data, 128);
366  //Advance the data pointer
367  data = (uint8_t *) data + 128;
368  }
369 
370  //Copy the partial block, is any
371  osMemset(buffer, 0, 128);
372  osMemcpy(buffer, data, n);
373 
374  //Append the first byte of the padding string
375  buffer[n] = 0x80;
376 
377  //Pad the message so that its length is congruent to 112 modulo 128
378  if(n >= 112)
379  {
380  hashProcessData(buffer, 128);
381  osMemset(buffer, 0, 128);
382  }
383 
384  //Append the length of the original message
385  STORE64BE(length * 8, buffer + 120);
386 
387  //Process the final block
388  hashProcessData(buffer, 128);
389 
390  //Save the resulting hash value
391  temp = CRPT->HMAC_DGST[0];
392  __UNALIGNED_UINT32_WRITE(digest, temp);
393  temp = CRPT->HMAC_DGST[1];
394  __UNALIGNED_UINT32_WRITE(digest + 4, temp);
395  temp = CRPT->HMAC_DGST[2];
396  __UNALIGNED_UINT32_WRITE(digest + 8, temp);
397  temp = CRPT->HMAC_DGST[3];
398  __UNALIGNED_UINT32_WRITE(digest + 12, temp);
399  temp = CRPT->HMAC_DGST[4];
400  __UNALIGNED_UINT32_WRITE(digest + 16, temp);
401  temp = CRPT->HMAC_DGST[5];
402  __UNALIGNED_UINT32_WRITE(digest + 20, temp);
403  temp = CRPT->HMAC_DGST[6];
404  __UNALIGNED_UINT32_WRITE(digest + 24, temp);
405  temp = CRPT->HMAC_DGST[7];
406  __UNALIGNED_UINT32_WRITE(digest + 28, temp);
407  temp = CRPT->HMAC_DGST[8];
408  __UNALIGNED_UINT32_WRITE(digest + 32, temp);
409  temp = CRPT->HMAC_DGST[9];
410  __UNALIGNED_UINT32_WRITE(digest + 36, temp);
411  temp = CRPT->HMAC_DGST[10];
412  __UNALIGNED_UINT32_WRITE(digest + 40, temp);
413  temp = CRPT->HMAC_DGST[11];
414  __UNALIGNED_UINT32_WRITE(digest + 44, temp);
415 
416  //Stop SHA engine
417  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
418 
419  //Release exclusive access to the CRYPTO module
421 
422  //Sucessful processing
423  return NO_ERROR;
424 }
425 
426 #endif
427 #if (SHA512_SUPPORT == ENABLED)
428 
429 /**
430  * @brief Digest a message using SHA-512
431  * @param[in] data Pointer to the message being hashed
432  * @param[in] length Length of the message
433  * @param[out] digest Pointer to the calculated digest
434  * @return Error code
435  **/
436 
437 error_t sha512Compute(const void *data, size_t length, uint8_t *digest)
438 {
439  size_t n;
440  uint32_t temp;
441  uint8_t buffer[128];
442 
443  //Acquire exclusive access to the CRYPTO module
445 
446  //Reset CRYPTO controller
447  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
448  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
449 
450  //Select the relevant hash algorithm
451  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
453 
454  //Start SHA engine
455  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
456 
457  //Digest the message
458  for(n = length; n >= 128; n -= 128)
459  {
460  //Update hash value
461  hashProcessData(data, 128);
462  //Advance the data pointer
463  data = (uint8_t *) data + 128;
464  }
465 
466  //Copy the partial block, is any
467  osMemset(buffer, 0, 128);
468  osMemcpy(buffer, data, n);
469 
470  //Append the first byte of the padding string
471  buffer[n] = 0x80;
472 
473  //Pad the message so that its length is congruent to 112 modulo 128
474  if(n >= 112)
475  {
476  hashProcessData(buffer, 128);
477  osMemset(buffer, 0, 128);
478  }
479 
480  //Append the length of the original message
481  STORE64BE(length * 8, buffer + 120);
482 
483  //Process the final block
484  hashProcessData(buffer, 128);
485 
486  //Save the resulting hash value
487  temp = CRPT->HMAC_DGST[0];
488  __UNALIGNED_UINT32_WRITE(digest, temp);
489  temp = CRPT->HMAC_DGST[1];
490  __UNALIGNED_UINT32_WRITE(digest + 4, temp);
491  temp = CRPT->HMAC_DGST[2];
492  __UNALIGNED_UINT32_WRITE(digest + 8, temp);
493  temp = CRPT->HMAC_DGST[3];
494  __UNALIGNED_UINT32_WRITE(digest + 12, temp);
495  temp = CRPT->HMAC_DGST[4];
496  __UNALIGNED_UINT32_WRITE(digest + 16, temp);
497  temp = CRPT->HMAC_DGST[5];
498  __UNALIGNED_UINT32_WRITE(digest + 20, temp);
499  temp = CRPT->HMAC_DGST[6];
500  __UNALIGNED_UINT32_WRITE(digest + 24, temp);
501  temp = CRPT->HMAC_DGST[7];
502  __UNALIGNED_UINT32_WRITE(digest + 28, temp);
503  temp = CRPT->HMAC_DGST[8];
504  __UNALIGNED_UINT32_WRITE(digest + 32, temp);
505  temp = CRPT->HMAC_DGST[9];
506  __UNALIGNED_UINT32_WRITE(digest + 36, temp);
507  temp = CRPT->HMAC_DGST[10];
508  __UNALIGNED_UINT32_WRITE(digest + 40, temp);
509  temp = CRPT->HMAC_DGST[11];
510  __UNALIGNED_UINT32_WRITE(digest + 44, temp);
511  temp = CRPT->HMAC_DGST[12];
512  __UNALIGNED_UINT32_WRITE(digest + 48, temp);
513  temp = CRPT->HMAC_DGST[13];
514  __UNALIGNED_UINT32_WRITE(digest + 52, temp);
515  temp = CRPT->HMAC_DGST[14];
516  __UNALIGNED_UINT32_WRITE(digest + 56, temp);
517  temp = CRPT->HMAC_DGST[15];
518  __UNALIGNED_UINT32_WRITE(digest + 60, temp);
519 
520  //Stop SHA engine
521  CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
522 
523  //Release exclusive access to the CRYPTO module
525 
526  //Sucessful processing
527  return NO_ERROR;
528 }
529 
530 #endif
531 #endif
#define CRPT_HMAC_CTL_OPMODE_SHA256
error_t sha384Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-384.
uint8_t data[]
Definition: ethernet.h:222
error_t sha512Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-512.
OsMutex m480CryptoMutex
Definition: m480_crypto.c:41
M480 hardware cryptographic accelerator.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
#define CRPT_HMAC_CTL_OPMODE_SHA384
General definitions for cryptographic algorithms.
uint8_t length
Definition: tcp.h:375
Collection of hash algorithms.
#define CRPT_HMAC_CTL_OPMODE_SHA512
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
error_t sha224Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-224.
error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-256.
uint8_t n
#define CRPT_HMAC_CTL_OPMODE_SHA1
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
#define CRPT_HMAC_CTL_OPMODE_SHA224
M480 hash hardware accelerator.
error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-1.
void hashProcessData(const uint8_t *data, size_t length)
Update hash value.
#define osMemset(p, value, length)
Definition: os_port.h:138
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.