m2354_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file m2354_crypto_hash.c
3  * @brief M2354 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 "m2354.h"
36 #include "core/crypto.h"
39 #include "hash/hash_algorithms.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (M2354_CRYPTO_HASH_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Update hash value
48  * @param[in] opmode Hash algorithm
49  * @param[in] data Pointer to the input buffer
50  * @param[in] length Length of the input buffer
51  * @param[in,out] h Intermediate hash value
52  * @param[in] hLen Length of the intermediate hash value, in words
53  **/
54 
55 void hashProcessData(uint32_t opmode, const uint8_t *data,
56  size_t length, uint32_t *h, size_t hLen)
57 {
58  uint_t i;
59 
60  //Acquire exclusive access to the CRYPTO module
62 
63  //Reset CRYPTO controller
64  SYS->IPRST0 |= SYS_IPRST0_CRPTRST_Msk;
65  SYS->IPRST0 &= ~SYS_IPRST0_CRPTRST_Msk;
66 
67  //Select the relevant hash algorithm
68  CRPT->HMAC_CTL = CRPT_HMAC_CTL_INSWAP_Msk | CRPT_HMAC_CTL_OUTSWAP_Msk |
69  CRPT_HMAC_CTL_DMACSCAD_Msk | opmode;
70 
71  //SHA-1, SHA-224, SHA-256 or SM3 algorithm?
72  if(opmode == CRPT_HMAC_CTL_OPMODE_SHA1 ||
73  opmode == CRPT_HMAC_CTL_OPMODE_SHA224 ||
74  opmode == CRPT_HMAC_CTL_OPMODE_SHA256 ||
75  opmode == CRPT_HMAC_CTL_SM3EN_Msk)
76  {
77  //Restore initial hash value
78  for(i = 0; i < hLen; i++)
79  {
80  CRPT->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  CRPT->HMAC_FDBCK[i] = h[i];
89  }
90  }
91 
92  //Start SHA engine
93  CRPT->HMAC_CTL |= CRPT_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((CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk) == 0)
100  {
101  }
102 
103  //Write one word of data
104  CRPT->HMAC_DATIN = __UNALIGNED_UINT32_READ(data + i);
105  }
106 
107  //Wait for the processing to complete
108  while((CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk) == 0)
109  {
110  }
111 
112  //SHA-1, SHA-224, SHA-256 or SM3 algorithm?
113  if(opmode == CRPT_HMAC_CTL_OPMODE_SHA1 ||
114  opmode == CRPT_HMAC_CTL_OPMODE_SHA224 ||
115  opmode == CRPT_HMAC_CTL_OPMODE_SHA256 ||
116  opmode == CRPT_HMAC_CTL_SM3EN_Msk)
117  {
118  //Save intermediate hash value
119  for(i = 0; i < hLen; i++)
120  {
121  h[i] = CRPT->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] = CRPT->HMAC_FDBCK[i];
130  }
131  }
132 
133  //Stop SHA engine
134  CRPT->HMAC_CTL |= CRPT_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(CRPT_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(CRPT_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(CRPT_HMAC_CTL_SM3EN_Msk, context->buffer, 64,
445  context->h, SM3_DIGEST_SIZE / 4);
446 }
447 
448 #endif
449 #endif
void sha512ProcessBlock(Sha512Context *context)
Process message in 16-word blocks.
M2354 hash hardware accelerator.
SHA-256 algorithm context.
Definition: sha256.h:62
#define CRPT_HMAC_CTL_OPMODE_SHA256
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
void sha1ProcessBlock(Sha1Context *context)
Process message in 16-word blocks.
uint8_t data[]
Definition: ethernet.h:224
size_t size
Definition: sha256.h:69
SM3 algorithm context.
Definition: sm3.h:62
uint32_t h[8]
Definition: sha256.h:63
void hashProcessData(uint32_t opmode, const uint8_t *data, size_t length, uint32_t *h, size_t hLen)
Update hash value.
uint8_t buffer[64]
Definition: sm3.h:67
void sm3Update(Sm3Context *context, const void *data, size_t length)
Update the SM3 context with a portion of the message being hashed.
void sha256ProcessBlock(Sha256Context *context)
Process message in 16-word blocks.
uint64_t totalSize
Definition: sm3.h:70
uint64_t totalSize
Definition: sha1.h:70
size_t size
Definition: sha512.h:69
uint8_t h
Definition: ndp.h:302
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
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
void sha256Update(Sha256Context *context, const void *data, size_t length)
Update the SHA-256 context with a portion of the message being hashed.
uint8_t length
Definition: tcp.h:375
uint8_t buffer[64]
Definition: sha256.h:67
void sm3ProcessBlock(Sm3Context *context)
Process message in 16-word blocks.
#define MIN(a, b)
Definition: os_port.h:63
Collection of hash algorithms.
#define CRPT_HMAC_CTL_OPMODE_SHA512
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.
uint64_t h[8]
Definition: sha512.h:63
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.
OsMutex m2354CryptoMutex
Definition: m2354_crypto.c:42
size_t size
Definition: sha1.h:69
#define CRPT_HMAC_CTL_OPMODE_SHA224
SHA-1 algorithm context.
Definition: sha1.h:62
M2354 hardware cryptographic accelerator.
uint8_t buffer[64]
Definition: sha1.h:67
uint64_t totalSize
Definition: sha512.h:70
uint64_t totalSize
Definition: sha256.h:70
unsigned int uint_t
Definition: compiler_port.h:57
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
size_t size
Definition: sm3.h:69
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
Debugging facilities.
#define SM3_DIGEST_SIZE
Definition: sm3.h:45