max32690_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file max32690_crypto_hash.c
3  * @brief MAX32690 hash hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "mxc_device.h"
36 #include "mxc_sys.h"
37 #include "ctb.h"
38 #include "core/crypto.h"
41 #include "hash/hash_algorithms.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (MAX32690_CRYPTO_HASH_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Update hash value
50  * @param[in] algo Hash algorithm
51  * @param[in] data Pointer to the input buffer
52  * @param[in] length Length of the input buffer
53  * @param[in,out] h Intermediate hash value
54  * @param[in] hLen Length of the intermediate hash value, in words
55  **/
56 
57 void hashProcessData(mxc_ctb_hash_func_t algo, const uint8_t *data,
58  size_t length, uint32_t *h, size_t hLen)
59 {
60  uint_t i;
61  uint32_t temp;
62  size_t blockSize;
63 
64  //Get block size
65  if(algo == MXC_CTB_HASH_SHA1 || algo == MXC_CTB_HASH_SHA224 ||
66  algo == MXC_CTB_HASH_SHA256)
67  {
68  blockSize = 64;
69  }
70  else
71  {
72  blockSize = 128;
73  }
74 
75  //Acquire exclusive access to the CTB module
77 
78  //Reset the engine by setting CTB_CTRL.rst
79  MXC_CTB->ctrl = MXC_F_CTB_CTRL_RST;
80 
81  //Software must poll the CTB_CTRL.rst bit until it is set to 1 by hardware,
82  //indicating the cryptographic accelerator is ready for use
83  while((MXC_CTB->ctrl & MXC_F_CTB_CTRL_RDY) == 0)
84  {
85  }
86 
87  //Legacy support for the access behavior of the done flags
88  MXC_CTB->ctrl |= MXC_F_CTB_CTRL_FLAG_MODE;
89  //Clear done flag
90  MXC_CTB->ctrl |= MXC_F_CTB_CTRL_HSH_DONE;
91 
92  //Select the desired hash function
93  MXC_CTB->hash_ctrl = (algo << MXC_F_CTB_HASH_CTRL_HASH_POS) &
94  MXC_F_CTB_HASH_CTRL_HASH;
95 
96  //Set the length of the message in bytes
97  MXC_CTB->hash_msg_sz[0] = length;
98  MXC_CTB->hash_msg_sz[1] = 0;
99  MXC_CTB->hash_msg_sz[2] = 0;
100  MXC_CTB->hash_msg_sz[3] = 0;
101 
102  //Select hash function input source
103  temp = MXC_CTB->ctrl & ~MXC_F_CTB_CTRL_SRC;
104  temp |= MXC_CTB_HASH_SOURCE_INFIFO << MXC_F_CTB_CTRL_SRC_POS;
105  MXC_CTB->ctrl = temp;
106 
107  //Initialize hash calculation
108  MXC_CTB->hash_ctrl |= MXC_F_CTB_HASH_CTRL_INIT;
109 
110  //Wait for the initialization to complete
111  while((MXC_CTB->hash_ctrl & MXC_F_CTB_HASH_CTRL_INIT) != 0)
112  {
113  }
114 
115  //SHA-1, SHA-224 or SHA-256 algorithm?
116  if(blockSize == 64)
117  {
118  //Restore initial hash value
119  for(i = 0; i < hLen; i++)
120  {
121  MXC_CTB->hash_digest[i] = htobe32(h[i]);
122  }
123  }
124  else
125  {
126  //Restore initial hash value
127  for(i = 0; i < hLen; i += 2)
128  {
129  MXC_CTB->hash_digest[i] = htobe32(h[i + 1]);
130  MXC_CTB->hash_digest[i + 1] = htobe32(h[i]);
131  }
132  }
133 
134  //Input data are processed in a block-by-block fashion
135  while(length >= blockSize)
136  {
137  //Write the block to be processed to the DIN registers
138  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data);
139  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 4);
140  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 8);
141  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 12);
142  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 16);
143  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 20);
144  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 24);
145  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 28);
146  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 32);
147  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 36);
148  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 40);
149  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 44);
150  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 48);
151  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 52);
152  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 56);
153  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 60);
154 
155  //128-octet data block?
156  if(blockSize == 128)
157  {
158  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 64);
159  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 68);
160  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 72);
161  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 76);
162  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 80);
163  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 84);
164  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 88);
165  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 92);
166  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 96);
167  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 100);
168  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 104);
169  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 108);
170  MXC_CTB->din[0] = __UNALIGNED_UINT32_READ(data + 112);
171  MXC_CTB->din[1] = __UNALIGNED_UINT32_READ(data + 116);
172  MXC_CTB->din[2] = __UNALIGNED_UINT32_READ(data + 120);
173  MXC_CTB->din[3] = __UNALIGNED_UINT32_READ(data + 124);
174  }
175 
176  //Wait until the operation is complete
177  while((MXC_CTB->ctrl & MXC_F_CTB_CTRL_HSH_DONE) == 0)
178  {
179  }
180 
181  //Clear CTB_CTRL.hsh_done flag before starting the next hash operation
182  MXC_CTB->ctrl |= MXC_F_CTB_CTRL_HSH_DONE;
183 
184  //Advance data pointer
185  data += blockSize;
186  length -= blockSize;
187  }
188 
189  //SHA-1, SHA-224 or SHA-256 algorithm?
190  if(blockSize == 64)
191  {
192  //Save intermediate hash value
193  for(i = 0; i < hLen; i++)
194  {
195  h[i] = betoh32(MXC_CTB->hash_digest[i]);
196  }
197  }
198  else
199  {
200  //Save intermediate hash value
201  for(i = 0; i < hLen; i += 2)
202  {
203  h[i] = betoh32(MXC_CTB->hash_digest[i + 1]);
204  h[i + 1] = betoh32(MXC_CTB->hash_digest[i]);
205  }
206  }
207 
208  //Disable hash engine
209  MXC_CTB->hash_ctrl = (MXC_CTB_HASH_DIS << MXC_F_CTB_HASH_CTRL_HASH_POS) &
210  MXC_F_CTB_HASH_CTRL_HASH;
211 
212  //Release exclusive access to the CTB module
214 }
215 
216 
217 #if (SHA1_SUPPORT == ENABLED)
218 
219 /**
220  * @brief Update the SHA-1 context with a portion of the message being hashed
221  * @param[in] context Pointer to the SHA-1 context
222  * @param[in] data Pointer to the buffer being hashed
223  * @param[in] length Length of the buffer
224  **/
225 
226 void sha1Update(Sha1Context *context, const void *data, size_t length)
227 {
228  size_t n;
229 
230  //Process the incoming data
231  while(length > 0)
232  {
233  //Check whether some data is pending in the buffer
234  if(context->size == 0 && length >= 64)
235  {
236  //The length must be a multiple of 64 bytes
237  n = length - (length % 64);
238 
239  //Update hash value
240  hashProcessData(MXC_CTB_HASH_SHA1, data, n, context->h,
241  SHA1_DIGEST_SIZE / 4);
242 
243  //Update the SHA-1 context
244  context->totalSize += n;
245  //Advance the data pointer
246  data = (uint8_t *) data + n;
247  //Remaining bytes to process
248  length -= n;
249  }
250  else
251  {
252  //The buffer can hold at most 64 bytes
253  n = MIN(length, 64 - context->size);
254 
255  //Copy the data to the buffer
256  osMemcpy(context->buffer + context->size, data, n);
257 
258  //Update the SHA-1 context
259  context->size += n;
260  context->totalSize += n;
261  //Advance the data pointer
262  data = (uint8_t *) data + n;
263  //Remaining bytes to process
264  length -= n;
265 
266  //Check whether the buffer is full
267  if(context->size == 64)
268  {
269  //Update hash value
270  hashProcessData(MXC_CTB_HASH_SHA1, context->buffer, context->size,
271  context->h, SHA1_DIGEST_SIZE / 4);
272 
273  //Empty the buffer
274  context->size = 0;
275  }
276  }
277  }
278 }
279 
280 
281 /**
282  * @brief Process message in 16-word blocks
283  * @param[in] context Pointer to the SHA-1 context
284  **/
285 
287 {
288  //Update hash value
289  hashProcessData(MXC_CTB_HASH_SHA1, context->buffer, 64, context->h,
290  SHA1_DIGEST_SIZE / 4);
291 }
292 
293 #endif
294 #if (SHA256_SUPPORT == ENABLED)
295 
296 /**
297  * @brief Update the SHA-256 context with a portion of the message being hashed
298  * @param[in] context Pointer to the SHA-256 context
299  * @param[in] data Pointer to the buffer being hashed
300  * @param[in] length Length of the buffer
301  **/
302 
303 void sha256Update(Sha256Context *context, const void *data, size_t length)
304 {
305  size_t n;
306 
307  //Process the incoming data
308  while(length > 0)
309  {
310  //Check whether some data is pending in the buffer
311  if(context->size == 0 && length >= 64)
312  {
313  //The length must be a multiple of 64 bytes
314  n = length - (length % 64);
315 
316  //Update hash value
317  hashProcessData(MXC_CTB_HASH_SHA256, data, n, context->h,
318  SHA256_DIGEST_SIZE / 4);
319 
320  //Update the SHA-256 context
321  context->totalSize += n;
322  //Advance the data pointer
323  data = (uint8_t *) data + n;
324  //Remaining bytes to process
325  length -= n;
326  }
327  else
328  {
329  //The buffer can hold at most 64 bytes
330  n = MIN(length, 64 - context->size);
331 
332  //Copy the data to the buffer
333  osMemcpy(context->buffer + context->size, data, n);
334 
335  //Update the SHA-256 context
336  context->size += n;
337  context->totalSize += n;
338  //Advance the data pointer
339  data = (uint8_t *) data + n;
340  //Remaining bytes to process
341  length -= n;
342 
343  //Check whether the buffer is full
344  if(context->size == 64)
345  {
346  //Update hash value
347  hashProcessData(MXC_CTB_HASH_SHA256, context->buffer, context->size,
348  context->h, SHA256_DIGEST_SIZE / 4);
349 
350  //Empty the buffer
351  context->size = 0;
352  }
353  }
354  }
355 }
356 
357 
358 /**
359  * @brief Process message in 16-word blocks
360  * @param[in] context Pointer to the SHA-256 context
361  **/
362 
364 {
365  //Update hash value
366  hashProcessData(MXC_CTB_HASH_SHA256, context->buffer, 64, context->h,
367  SHA256_DIGEST_SIZE / 4);
368 }
369 
370 #endif
371 #if (SHA512_SUPPORT == ENABLED)
372 
373 /**
374  * @brief Update the SHA-512 context with a portion of the message being hashed
375  * @param[in] context Pointer to the SHA-512 context
376  * @param[in] data Pointer to the buffer being hashed
377  * @param[in] length Length of the buffer
378  **/
379 
380 void sha512Update(Sha512Context *context, const void *data, size_t length)
381 {
382  size_t n;
383 
384  //Process the incoming data
385  while(length > 0)
386  {
387  //Check whether some data is pending in the buffer
388  if(context->size == 0 && length >= 128)
389  {
390  //The length must be a multiple of 128 bytes
391  n = length - (length % 128);
392 
393  //Update hash value
394  hashProcessData(MXC_CTB_HASH_SHA512, data, n, (uint32_t *) context->h,
395  SHA512_DIGEST_SIZE / 4);
396 
397  //Update the SHA-512 context
398  context->totalSize += n;
399  //Advance the data pointer
400  data = (uint8_t *) data + n;
401  //Remaining bytes to process
402  length -= n;
403  }
404  else
405  {
406  //The buffer can hold at most 128 bytes
407  n = MIN(length, 128 - context->size);
408 
409  //Copy the data to the buffer
410  osMemcpy(context->buffer + context->size, data, n);
411 
412  //Update the SHA-512 context
413  context->size += n;
414  context->totalSize += n;
415  //Advance the data pointer
416  data = (uint8_t *) data + n;
417  //Remaining bytes to process
418  length -= n;
419 
420  //Check whether the buffer is full
421  if(context->size == 128)
422  {
423  //Update hash value
424  hashProcessData(MXC_CTB_HASH_SHA512, context->buffer, context->size,
425  (uint32_t *) context->h, SHA512_DIGEST_SIZE / 4);
426 
427  //Empty the buffer
428  context->size = 0;
429  }
430  }
431  }
432 }
433 
434 
435 /**
436  * @brief Process message in 16-word blocks
437  * @param[in] context Pointer to the SHA-512 context
438  **/
439 
441 {
442  //Update hash value
443  hashProcessData(MXC_CTB_HASH_SHA512, context->buffer, 128,
444  (uint32_t *) context->h, SHA512_DIGEST_SIZE / 4);
445 }
446 
447 #endif
448 #endif
#define betoh32(value)
Definition: cpu_endian.h:454
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
MAX32690 hardware cryptographic accelerator.
SHA-256 algorithm context.
Definition: sha256.h:62
uint8_t data[]
Definition: ethernet.h:222
size_t size
Definition: sha256.h:73
uint32_t h[8]
Definition: sha256.h:65
uint64_t totalSize
Definition: sha1.h:74
size_t size
Definition: sha512.h:73
uint8_t h
Definition: ndp.h:302
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
void sha1ProcessBlock(Sha1Context *context)
Process message in 16-word blocks.
SHA-512 algorithm context.
Definition: sha512.h:62
uint32_t h[5]
Definition: sha1.h:65
void hashProcessData(mxc_ctb_hash_func_t algo, const uint8_t *data, size_t length, uint32_t *h, size_t hLen)
Update hash value.
General definitions for cryptographic algorithms.
uint8_t buffer[128]
Definition: sha512.h:71
uint8_t length
Definition: tcp.h:368
uint8_t buffer[64]
Definition: sha256.h:71
#define MIN(a, b)
Definition: os_port.h:63
Collection of hash algorithms.
#define htobe32(value)
Definition: cpu_endian.h:446
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
uint64_t h[8]
Definition: sha512.h:65
uint8_t n
MAX32690 hash hardware accelerator.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
size_t size
Definition: sha1.h:73
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.
SHA-1 algorithm context.
Definition: sha1.h:62
OsMutex max32690CryptoMutex
uint8_t buffer[64]
Definition: sha1.h:71
uint64_t totalSize
Definition: sha512.h:74
uint64_t totalSize
Definition: sha256.h:74
void sha512ProcessBlock(Sha512Context *context)
Process message in 16-word blocks.
unsigned int uint_t
Definition: compiler_port.h:50
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
void sha256ProcessBlock(Sha256Context *context)
Process message in 16-word blocks.
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
Debugging facilities.
void sha256Update(Sha256Context *context, const void *data, size_t length)
Update the SHA-256 context with a portion of the message being hashed.