m5531_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file m5531_crypto_hash.c
3  * @brief M5531 hash hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "NuMicro.h"
36 #include "core/crypto.h"
39 #include "hash/hash_algorithms.h"
40 #include "xof/keccak.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (M5531_CRYPTO_HASH_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Update hash value
49  * @param[in] opmode Hash algorithm
50  * @param[in] data Pointer to the input buffer
51  * @param[in] length Length of the input buffer
52  * @param[in,out] h Intermediate hash value
53  * @param[in] hLen Length of the intermediate hash value, in words
54  **/
55 
56 void hashProcessData(uint32_t opmode, const uint8_t *data,
57  size_t length, uint32_t *h, size_t hLen)
58 {
59  uint_t i;
60 
61  //Acquire exclusive access to the CRYPTO module
63 
64  //Reset CRYPTO controller
65  SYS_ResetModule(SYS_CRYPTO0RST);
66 
67  //Select the relevant hash algorithm
68  CRYPTO->HMAC_CTL = CRYPTO_HMAC_CTL_INSWAP_Msk | CRYPTO_HMAC_CTL_OUTSWAP_Msk |
69  CRYPTO_HMAC_CTL_DMACSCAD_Msk | opmode;
70 
71  //SHA-1, SHA-224, SHA-256 or SM3 algorithm?
72  if(opmode == CRYPTO_HMAC_CTL_OPMODE_SHA1 ||
75  opmode == CRYPTO_HMAC_CTL_SM3EN_Msk)
76  {
77  //Restore initial hash value
78  for(i = 0; i < hLen; i++)
79  {
80  CRYPTO->HMAC_FDBCK[2 * i] = h[i];
81  }
82  }
83  else
84  {
85  //Restore initial hash value
86  for(i = 0; i < hLen; i++)
87  {
88  CRYPTO->HMAC_FDBCK[i] = h[i];
89  }
90  }
91 
92  //Start SHA engine
93  CRYPTO->HMAC_CTL |= CRYPTO_HMAC_CTL_START_Msk;
94 
95  //Process input data
96  for(i = 0; i < length; i += 4)
97  {
98  //Wait for the DATINREQ bit to be set
99  while((CRYPTO->HMAC_STS & CRYPTO_HMAC_STS_DATINREQ_Msk) == 0)
100  {
101  }
102 
103  //Write one word of data
104  CRYPTO->HMAC_DATIN = __UNALIGNED_UINT32_READ(data + i);
105  }
106 
107  //Wait for the processing to complete
108  while((CRYPTO->HMAC_STS & CRYPTO_HMAC_STS_DATINREQ_Msk) == 0)
109  {
110  }
111 
112  //SHA-1, SHA-224, SHA-256 or SM3 algorithm?
113  if(opmode == CRYPTO_HMAC_CTL_OPMODE_SHA1 ||
114  opmode == CRYPTO_HMAC_CTL_OPMODE_SHA224 ||
115  opmode == CRYPTO_HMAC_CTL_OPMODE_SHA256 ||
116  opmode == CRYPTO_HMAC_CTL_SM3EN_Msk)
117  {
118  //Save intermediate hash value
119  for(i = 0; i < hLen; i++)
120  {
121  h[i] = CRYPTO->HMAC_FDBCK[2 * i];
122  }
123  }
124  else
125  {
126  //Save intermediate hash value
127  for(i = 0; i < hLen; i++)
128  {
129  h[i] = CRYPTO->HMAC_FDBCK[i];
130  }
131  }
132 
133  //Stop SHA engine
134  CRYPTO->HMAC_CTL |= CRYPTO_HMAC_CTL_STOP_Msk;
135 
136  //Release exclusive access to the CRYPTO module
138 }
139 
140 
141 #if (SHA1_SUPPORT == ENABLED)
142 
143 /**
144  * @brief Update the SHA-1 context with a portion of the message being hashed
145  * @param[in] context Pointer to the SHA-1 context
146  * @param[in] data Pointer to the buffer being hashed
147  * @param[in] length Length of the buffer
148  **/
149 
150 void sha1Update(Sha1Context *context, const void *data, size_t length)
151 {
152  size_t n;
153 
154  //Process the incoming data
155  while(length > 0)
156  {
157  //Check whether some data is pending in the buffer
158  if(context->size == 0 && length >= 64)
159  {
160  //The length must be a multiple of 64 bytes
161  n = length - (length % 64);
162 
163  //Update hash value
165  SHA1_DIGEST_SIZE / 4);
166 
167  //Update the SHA-1 context
168  context->totalSize += n;
169  //Advance the data pointer
170  data = (uint8_t *) data + n;
171  //Remaining bytes to process
172  length -= n;
173  }
174  else
175  {
176  //The buffer can hold at most 64 bytes
177  n = MIN(length, 64 - context->size);
178 
179  //Copy the data to the buffer
180  osMemcpy(context->buffer + context->size, data, n);
181 
182  //Update the SHA-1 context
183  context->size += n;
184  context->totalSize += n;
185  //Advance the data pointer
186  data = (uint8_t *) data + n;
187  //Remaining bytes to process
188  length -= n;
189 
190  //Check whether the buffer is full
191  if(context->size == 64)
192  {
193  //Update hash value
195  context->size, context->h, SHA1_DIGEST_SIZE / 4);
196 
197  //Empty the buffer
198  context->size = 0;
199  }
200  }
201  }
202 }
203 
204 
205 /**
206  * @brief Process message in 16-word blocks
207  * @param[in] context Pointer to the SHA-1 context
208  **/
209 
211 {
212  //Update hash value
214  context->h, SHA1_DIGEST_SIZE / 4);
215 }
216 
217 #endif
218 #if (SHA256_SUPPORT == ENABLED)
219 
220 /**
221  * @brief Update the SHA-256 context with a portion of the message being hashed
222  * @param[in] context Pointer to the SHA-256 context
223  * @param[in] data Pointer to the buffer being hashed
224  * @param[in] length Length of the buffer
225  **/
226 
227 void sha256Update(Sha256Context *context, const void *data, size_t length)
228 {
229  size_t n;
230 
231  //Process the incoming data
232  while(length > 0)
233  {
234  //Check whether some data is pending in the buffer
235  if(context->size == 0 && length >= 64)
236  {
237  //The length must be a multiple of 64 bytes
238  n = length - (length % 64);
239 
240  //Update hash value
242  SHA256_DIGEST_SIZE / 4);
243 
244  //Update the SHA-256 context
245  context->totalSize += n;
246  //Advance the data pointer
247  data = (uint8_t *) data + n;
248  //Remaining bytes to process
249  length -= n;
250  }
251  else
252  {
253  //The buffer can hold at most 64 bytes
254  n = MIN(length, 64 - context->size);
255 
256  //Copy the data to the buffer
257  osMemcpy(context->buffer + context->size, data, n);
258 
259  //Update the SHA-256 context
260  context->size += n;
261  context->totalSize += n;
262  //Advance the data pointer
263  data = (uint8_t *) data + n;
264  //Remaining bytes to process
265  length -= n;
266 
267  //Check whether the buffer is full
268  if(context->size == 64)
269  {
270  //Update hash value
272  context->size, context->h, SHA256_DIGEST_SIZE / 4);
273 
274  //Empty the buffer
275  context->size = 0;
276  }
277  }
278  }
279 }
280 
281 
282 /**
283  * @brief Process message in 16-word blocks
284  * @param[in] context Pointer to the SHA-256 context
285  **/
286 
288 {
289  //Update hash value
291  context->h, SHA256_DIGEST_SIZE / 4);
292 }
293 
294 #endif
295 #if (SHA512_SUPPORT == ENABLED)
296 
297 /**
298  * @brief Update the SHA-512 context with a portion of the message being hashed
299  * @param[in] context Pointer to the SHA-512 context
300  * @param[in] data Pointer to the buffer being hashed
301  * @param[in] length Length of the buffer
302  **/
303 
304 void sha512Update(Sha512Context *context, const void *data, size_t length)
305 {
306  size_t n;
307 
308  //Process the incoming data
309  while(length > 0)
310  {
311  //Check whether some data is pending in the buffer
312  if(context->size == 0 && length >= 128)
313  {
314  //The length must be a multiple of 128 bytes
315  n = length - (length % 128);
316 
317  //Update hash value
319  (uint32_t *) context->h, SHA512_DIGEST_SIZE / 4);
320 
321  //Update the SHA-512 context
322  context->totalSize += n;
323  //Advance the data pointer
324  data = (uint8_t *) data + n;
325  //Remaining bytes to process
326  length -= n;
327  }
328  else
329  {
330  //The buffer can hold at most 128 bytes
331  n = MIN(length, 128 - context->size);
332 
333  //Copy the data to the buffer
334  osMemcpy(context->buffer + context->size, data, n);
335 
336  //Update the SHA-512 context
337  context->size += n;
338  context->totalSize += n;
339  //Advance the data pointer
340  data = (uint8_t *) data + n;
341  //Remaining bytes to process
342  length -= n;
343 
344  //Check whether the buffer is full
345  if(context->size == 128)
346  {
347  //Update hash value
349  context->size, (uint32_t *) context->h, SHA512_DIGEST_SIZE / 4);
350 
351  //Empty the buffer
352  context->size = 0;
353  }
354  }
355  }
356 }
357 
358 
359 /**
360  * @brief Process message in 16-word blocks
361  * @param[in] context Pointer to the SHA-512 context
362  **/
363 
365 {
366  //Update hash value
368  (uint32_t *) context->h, SHA512_DIGEST_SIZE / 4);
369 }
370 
371 #endif
372 #if (SM3_SUPPORT == ENABLED)
373 
374 /**
375  * @brief Update the SM3 context with a portion of the message being hashed
376  * @param[in] context Pointer to the SM3 context
377  * @param[in] data Pointer to the buffer being hashed
378  * @param[in] length Length of the buffer
379  **/
380 
381 void sm3Update(Sm3Context *context, const void *data, size_t length)
382 {
383  size_t n;
384 
385  //Process the incoming data
386  while(length > 0)
387  {
388  //Check whether some data is pending in the buffer
389  if(context->size == 0 && length >= 64)
390  {
391  //The length must be a multiple of 64 bytes
392  n = length - (length % 64);
393 
394  //Update hash value
395  hashProcessData(CRYPTO_HMAC_CTL_SM3EN_Msk, data, n, context->h,
396  SM3_DIGEST_SIZE / 4);
397 
398  //Update the SM3 context
399  context->totalSize += n;
400  //Advance the data pointer
401  data = (uint8_t *) data + n;
402  //Remaining bytes to process
403  length -= n;
404  }
405  else
406  {
407  //The buffer can hold at most 64 bytes
408  n = MIN(length, 64 - context->size);
409 
410  //Copy the data to the buffer
411  osMemcpy(context->buffer + context->size, data, n);
412 
413  //Update the SM3 context
414  context->size += n;
415  context->totalSize += n;
416  //Advance the data pointer
417  data = (uint8_t *) data + n;
418  //Remaining bytes to process
419  length -= n;
420 
421  //Check whether the buffer is full
422  if(context->size == 64)
423  {
424  //Update hash value
425  hashProcessData(CRYPTO_HMAC_CTL_SM3EN_Msk, context->buffer,
426  context->size, context->h, SM3_DIGEST_SIZE / 4);
427 
428  //Empty the buffer
429  context->size = 0;
430  }
431  }
432  }
433 }
434 
435 
436 /**
437  * @brief Process message in 16-word blocks
438  * @param[in] context Pointer to the SM3 context
439  **/
440 
442 {
443  //Update hash value
444  hashProcessData(CRYPTO_HMAC_CTL_SM3EN_Msk, context->buffer, 64,
445  context->h, SM3_DIGEST_SIZE / 4);
446 }
447 
448 #endif
449 #if (KECCAK_SUPPORT == ENABLED)
450 
451 /**
452  * @brief Update state array
453  * @param[in] data Pointer to the input buffer
454  * @param[in] length Length of the input buffer
455  * @param[in] blockSize Block size
456  * @param[in,out] a State array
457  **/
458 
459 void keccakProcessData(const uint8_t *data, size_t length, size_t blockSize,
460  uint32_t *a)
461 {
462  uint_t i;
463  uint32_t opmode;
464 
465  //Check block size
466  if(blockSize == 72)
467  {
469  }
470  else if(blockSize == 104)
471  {
473  }
474  else if(blockSize == 136)
475  {
477  }
478  else
479  {
481  }
482 
483  //Acquire exclusive access to the CRYPTO module
485 
486  //Reset CRYPTO controller
487  SYS_ResetModule(SYS_CRYPTO0RST);
488 
489  //Select the relevant hash algorithm
490  CRYPTO->HMAC_CTL = CRYPTO_HMAC_CTL_INSWAP_Msk | CRYPTO_HMAC_CTL_OUTSWAP_Msk |
491  CRYPTO_HMAC_CTL_SHA3EN_Msk | CRYPTO_HMAC_CTL_DMACSCAD_Msk | opmode;
492 
493  //Restore state array
494  for(i = 0; i < 16; i++)
495  {
496  CRYPTO->HMAC_FDBCK[i] = reverseInt32(a[49 - i]);
497  }
498 
499  for(i = 0; i < 34; i++)
500  {
501  CRYPTO->HMAC_FDBCK[54 + i] = reverseInt32(a[33 - i]);
502  }
503 
504  //Start SHA engine
505  CRYPTO->HMAC_CTL |= CRYPTO_HMAC_CTL_START_Msk;
506 
507  //Valid buffer?
508  if(data != NULL)
509  {
510  //Process input data
511  for(i = 0; i < length; i += 4)
512  {
513  //Wait for the DATINREQ bit to be set
514  while((CRYPTO->HMAC_STS & CRYPTO_HMAC_STS_DATINREQ_Msk) == 0)
515  {
516  }
517 
518  //Write one word of data
519  CRYPTO->HMAC_DATIN = __UNALIGNED_UINT32_READ(data + i);
520  }
521  }
522  else
523  {
524  //Process input data
525  for(i = 0; i < length; i += 4)
526  {
527  //Wait for the DATINREQ bit to be set
528  while((CRYPTO->HMAC_STS & CRYPTO_HMAC_STS_DATINREQ_Msk) == 0)
529  {
530  }
531 
532  //Write one word of data
533  CRYPTO->HMAC_DATIN = 0;
534  }
535  }
536 
537  //Wait for the processing to complete
538  while((CRYPTO->HMAC_STS & CRYPTO_HMAC_STS_DATINREQ_Msk) == 0)
539  {
540  }
541 
542  //Save state array
543  for(i = 0; i < 34; i++)
544  {
545  a[i] = reverseInt32(CRYPTO->HMAC_FDBCK[87 - i]);
546  }
547 
548  for(i = 0; i < 16; i++)
549  {
550  a[34 + i] = reverseInt32(CRYPTO->HMAC_FDBCK[15 - i]);
551  }
552 
553  //Stop SHA engine
554  CRYPTO->HMAC_CTL |= CRYPTO_HMAC_CTL_STOP_Msk;
555 
556  //Release exclusive access to the CRYPTO module
558 }
559 
560 
561 /**
562  * @brief Absorb data
563  * @param[in] context Pointer to the Keccak context
564  * @param[in] input Pointer to the buffer being hashed
565  * @param[in] length Length of the buffer
566  **/
567 
568 void keccakAbsorb(KeccakContext *context, const void *input, size_t length)
569 {
570  size_t n;
571 
572  //Process the incoming data
573  while(length > 0)
574  {
575  //Check whether some data is pending in the buffer
576  if(context->length == 0 && length >= context->blockSize)
577  {
578  //The length must be a multiple of the block size
579  n = length - (length % context->blockSize);
580 
581  //Absorb the current block
582  keccakProcessData(input, n, context->blockSize,
583  (uint32_t *) context->a);
584 
585  //Advance the data pointer
586  input = (uint8_t *) input + n;
587  //Remaining bytes to process
588  length -= n;
589  }
590  else
591  {
592  //The buffer can hold at most one block
593  n = MIN(length, context->blockSize - context->length);
594 
595  //Copy the data to the buffer
596  osMemcpy(context->buffer + context->length, input, n);
597  //Update the length of the buffer
598  context->length += n;
599 
600  //Advance the data pointer
601  input = (uint8_t *) input + n;
602  //Remaining bytes to process
603  length -= n;
604 
605  //Check whether the buffer is full
606  if(context->length == context->blockSize)
607  {
608  //Absorb the current block
609  keccakProcessData(context->buffer, context->length,
610  context->blockSize, (uint32_t *) context->a);
611 
612  //Empty the buffer
613  context->length = 0;
614  }
615  }
616  }
617 }
618 
619 
620 /**
621  * @brief Block permutation
622  * @param[in] context Pointer to the Keccak context
623  **/
624 
626 {
627  //Perform block permutation
628  keccakProcessData(NULL, context->blockSize, context->blockSize,
629  (uint32_t *) context->a);
630 }
631 
632 #endif
633 #endif
keccak_lane_t a[5][5]
Definition: keccak.h:117
void sha512ProcessBlock(Sha512Context *context)
Process message in 16-word blocks.
uint8_t a
Definition: ndp.h:411
SHA-256 algorithm context.
Definition: sha256.h:62
void sha256ProcessBlock(Sha256Context *context)
Process message in 16-word blocks.
uint8_t data[]
Definition: ethernet.h:224
#define CRYPTO_HMAC_CTL_OPMODE_SHA1
void keccakAbsorb(KeccakContext *context, const void *input, size_t length)
Absorb data.
Keccak context.
Definition: keccak.h:116
size_t size
Definition: sha256.h:69
SM3 algorithm context.
Definition: sm3.h:62
uint32_t h[8]
Definition: sha256.h:63
uint8_t buffer[64]
Definition: sm3.h:67
#define CRYPTO_HMAC_CTL_OPMODE_SHA3_384
uint64_t totalSize
Definition: sm3.h:70
M5531 hash hardware accelerator.
uint64_t totalSize
Definition: sha1.h:70
size_t size
Definition: sha512.h:69
uint8_t buffer[24 *KECCAK_W_BYTES]
Definition: keccak.h:118
void keccakPermutBlock(KeccakContext *context)
Block permutation.
uint8_t h
Definition: ndp.h:302
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
void keccakProcessData(const uint8_t *data, size_t length, size_t blockSize, uint32_t *a)
Update state array.
SHA-512 algorithm context.
Definition: sha512.h:62
uint32_t h[5]
Definition: sha1.h:63
uint32_t h[8]
Definition: sm3.h:63
General definitions for cryptographic algorithms.
uint8_t buffer[128]
Definition: sha512.h:67
uint8_t length
Definition: tcp.h:375
uint8_t buffer[64]
Definition: sha256.h:67
#define MIN(a, b)
Definition: os_port.h:63
OsMutex m5531CryptoMutex
Definition: m5531_crypto.c:42
#define CRYPTO_HMAC_CTL_OPMODE_SHA3_224
Collection of hash algorithms.
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
Keccak sponge function.
void sm3ProcessBlock(Sm3Context *context)
Process message in 16-word blocks.
uint64_t h[8]
Definition: sha512.h:63
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
uint8_t n
uint_t blockSize
Definition: keccak.h:119
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
size_t length
Definition: keccak.h:120
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
M5531 hardware cryptographic accelerator.
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.
size_t size
Definition: sha1.h:69
void sha1ProcessBlock(Sha1Context *context)
Process message in 16-word blocks.
SHA-1 algorithm context.
Definition: sha1.h:62
uint32_t reverseInt32(uint32_t value)
Reverse bit order in a 32-bit word.
Definition: cpu_endian.c:123
void sha256Update(Sha256Context *context, const void *data, size_t length)
Update the SHA-256 context with a portion of the message being hashed.
#define CRYPTO_HMAC_CTL_OPMODE_SHA512
uint8_t buffer[64]
Definition: sha1.h:67
uint64_t totalSize
Definition: sha512.h:70
#define CRYPTO_HMAC_CTL_OPMODE_SHA3_256
uint64_t totalSize
Definition: sha256.h:70
void sm3Update(Sm3Context *context, const void *data, size_t length)
Update the SM3 context with a portion of the message being hashed.
unsigned int uint_t
Definition: compiler_port.h:57
#define CRYPTO_HMAC_CTL_OPMODE_SHA224
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
void hashProcessData(uint32_t opmode, const uint8_t *data, size_t length, uint32_t *h, size_t hLen)
Update hash value.
size_t size
Definition: sm3.h:69
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
#define CRYPTO_HMAC_CTL_OPMODE_SHA3_512
Debugging facilities.
#define CRYPTO_HMAC_CTL_OPMODE_SHA256
#define SM3_DIGEST_SIZE
Definition: sm3.h:45