sama5d3_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file sama5d3_crypto_hash.c
3  * @brief SAMA5D3 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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "sama5d3x.h"
36 #include "core/crypto.h"
39 #include "hash/hash_algorithms.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (SAMA5D3_CRYPTO_HASH_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Process data block
48  * @param[in] data Pointer to the data block
49  * @param[in] length Length of the data block, in bytes
50  **/
51 
52 void hashProcessDataBlock(const uint8_t *data, size_t length)
53 {
54  uint32_t *p;
55 
56  //Write the block to be processed to the input data registers
57  p = (uint32_t *) data;
58  SHA->SHA_IDATAR[0] = p[0];
59  SHA->SHA_IDATAR[1] = p[1];
60  SHA->SHA_IDATAR[2] = p[2];
61  SHA->SHA_IDATAR[3] = p[3];
62  SHA->SHA_IDATAR[4] = p[4];
63  SHA->SHA_IDATAR[5] = p[5];
64  SHA->SHA_IDATAR[6] = p[6];
65  SHA->SHA_IDATAR[7] = p[7];
66  SHA->SHA_IDATAR[8] = p[8];
67  SHA->SHA_IDATAR[9] = p[9];
68  SHA->SHA_IDATAR[10] = p[10];
69  SHA->SHA_IDATAR[11] = p[11];
70  SHA->SHA_IDATAR[12] = p[12];
71  SHA->SHA_IDATAR[13] = p[13];
72  SHA->SHA_IDATAR[14] = p[14];
73  SHA->SHA_IDATAR[15] = p[15];
74 
75  //128-octet data block?
76  if(length == 128)
77  {
78  SHA->SHA_IODATAR[0] = p[16];
79  SHA->SHA_IODATAR[1] = p[17];
80  SHA->SHA_IODATAR[2] = p[18];
81  SHA->SHA_IODATAR[3] = p[19];
82  SHA->SHA_IODATAR[4] = p[20];
83  SHA->SHA_IODATAR[5] = p[21];
84  SHA->SHA_IODATAR[6] = p[22];
85  SHA->SHA_IODATAR[7] = p[23];
86  SHA->SHA_IODATAR[8] = p[24];
87  SHA->SHA_IODATAR[9] = p[25];
88  SHA->SHA_IODATAR[10] = p[26];
89  SHA->SHA_IODATAR[11] = p[27];
90  SHA->SHA_IODATAR[12] = p[28];
91  SHA->SHA_IODATAR[13] = p[29];
92  SHA->SHA_IODATAR[14] = p[30];
93  SHA->SHA_IODATAR[15] = p[31];
94  }
95 
96  //Set the START bit to begin the processing
97  SHA->SHA_CR = SHA_CR_START;
98 
99  //When processing completes, the DATRDY flag is raised
100  while((SHA->SHA_ISR & SHA_ISR_DATRDY) == 0)
101  {
102  }
103 }
104 
105 
106 #if (SHA1_SUPPORT == ENABLED)
107 
108 /**
109  * @brief Digest a message using SHA-1
110  * @param[in] data Pointer to the message being hashed
111  * @param[in] length Length of the message
112  * @param[out] digest Pointer to the calculated digest
113  * @return Error code
114  **/
115 
116 error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
117 {
118  size_t n;
119  uint32_t *p;
120  uint8_t buffer[64];
121 
122  //Acquire exclusive access to the SHA module
124 
125  //Perform software reset
126  SHA->SHA_CR = SHA_CR_SWRST;
127  //Select the relevant hash algorithm
128  SHA->SHA_MR = SHA_MR_ALGO_SHA1 | SHA_MR_SMOD_MANUAL_START;
129  //For the first block of a message, the FIRST command must be set
130  SHA->SHA_CR = SHA_CR_FIRST;
131 
132  //Digest the message
133  for(n = length; n >= 64; n -= 64)
134  {
135  //Update hash value
137  //Advance the data pointer
138  data = (uint8_t *) data + 64;
139  }
140 
141  //Copy the partial block, is any
142  osMemset(buffer, 0, 64);
143  osMemcpy(buffer, data, n);
144 
145  //Append the first byte of the padding string
146  buffer[n] = 0x80;
147 
148  //Pad the message so that its length is congruent to 56 modulo 64
149  if(n >= 56)
150  {
151  hashProcessDataBlock(buffer, 64);
152  osMemset(buffer, 0, 64);
153  }
154 
155  //Append the length of the original message
156  STORE64BE(length * 8, buffer + 56);
157 
158  //Process the final block
159  hashProcessDataBlock(buffer, 64);
160 
161  //Save the resulting hash value
162  p = (uint32_t *) digest;
163  p[0] = SHA->SHA_IODATAR[0];
164  p[1] = SHA->SHA_IODATAR[1];
165  p[2] = SHA->SHA_IODATAR[2];
166  p[3] = SHA->SHA_IODATAR[3];
167  p[4] = SHA->SHA_IODATAR[4];
168 
169  //Release exclusive access to the SHA module
171 
172  //Sucessful processing
173  return NO_ERROR;
174 }
175 
176 #endif
177 #if (SHA224_SUPPORT == ENABLED)
178 
179 /**
180  * @brief Digest a message using SHA-224
181  * @param[in] data Pointer to the message being hashed
182  * @param[in] length Length of the message
183  * @param[out] digest Pointer to the calculated digest
184  * @return Error code
185  **/
186 
187 error_t sha224Compute(const void *data, size_t length, uint8_t *digest)
188 {
189  size_t n;
190  uint32_t *p;
191  uint8_t buffer[64];
192 
193  //Acquire exclusive access to the SHA module
195 
196  //Perform software reset
197  SHA->SHA_CR = SHA_CR_SWRST;
198  //Select the relevant hash algorithm
199  SHA->SHA_MR = SHA_MR_ALGO_SHA224 | SHA_MR_SMOD_MANUAL_START;
200  //For the first block of a message, the FIRST command must be set
201  SHA->SHA_CR = SHA_CR_FIRST;
202 
203  //Digest the message
204  for(n = length; n >= 64; n -= 64)
205  {
206  //Update hash value
208  //Advance the data pointer
209  data = (uint8_t *) data + 64;
210  }
211 
212  //Copy the partial block, is any
213  osMemset(buffer, 0, 64);
214  osMemcpy(buffer, data, n);
215 
216  //Append the first byte of the padding string
217  buffer[n] = 0x80;
218 
219  //Pad the message so that its length is congruent to 56 modulo 64
220  if(n >= 56)
221  {
222  hashProcessDataBlock(buffer, 64);
223  osMemset(buffer, 0, 64);
224  }
225 
226  //Append the length of the original message
227  STORE64BE(length * 8, buffer + 56);
228 
229  //Process the final block
230  hashProcessDataBlock(buffer, 64);
231 
232  //Save the resulting hash value
233  p = (uint32_t *) digest;
234  p[0] = SHA->SHA_IODATAR[0];
235  p[1] = SHA->SHA_IODATAR[1];
236  p[2] = SHA->SHA_IODATAR[2];
237  p[3] = SHA->SHA_IODATAR[3];
238  p[4] = SHA->SHA_IODATAR[4];
239  p[5] = SHA->SHA_IODATAR[5];
240  p[6] = SHA->SHA_IODATAR[6];
241 
242  //Release exclusive access to the SHA module
244 
245  //Sucessful processing
246  return NO_ERROR;
247 }
248 
249 #endif
250 #if (SHA256_SUPPORT == ENABLED)
251 
252 /**
253  * @brief Digest a message using SHA-256
254  * @param[in] data Pointer to the message being hashed
255  * @param[in] length Length of the message
256  * @param[out] digest Pointer to the calculated digest
257  * @return Error code
258  **/
259 
260 error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
261 {
262  size_t n;
263  uint32_t *p;
264  uint8_t buffer[64];
265 
266  //Acquire exclusive access to the SHA module
268 
269  //Perform software reset
270  SHA->SHA_CR = SHA_CR_SWRST;
271  //Select the relevant hash algorithm
272  SHA->SHA_MR = SHA_MR_ALGO_SHA256 | SHA_MR_SMOD_MANUAL_START;
273  //For the first block of a message, the FIRST command must be set
274  SHA->SHA_CR = SHA_CR_FIRST;
275 
276  //Digest the message
277  for(n = length; n >= 64; n -= 64)
278  {
279  //Update hash value
281  //Advance the data pointer
282  data = (uint8_t *) data + 64;
283  }
284 
285  //Copy the partial block, is any
286  osMemset(buffer, 0, 64);
287  osMemcpy(buffer, data, n);
288 
289  //Append the first byte of the padding string
290  buffer[n] = 0x80;
291 
292  //Pad the message so that its length is congruent to 56 modulo 64
293  if(n >= 56)
294  {
295  hashProcessDataBlock(buffer, 64);
296  osMemset(buffer, 0, 64);
297  }
298 
299  //Append the length of the original message
300  STORE64BE(length * 8, buffer + 56);
301 
302  //Process the final block
303  hashProcessDataBlock(buffer, 64);
304 
305  //Save the resulting hash value
306  p = (uint32_t *) digest;
307  p[0] = SHA->SHA_IODATAR[0];
308  p[1] = SHA->SHA_IODATAR[1];
309  p[2] = SHA->SHA_IODATAR[2];
310  p[3] = SHA->SHA_IODATAR[3];
311  p[4] = SHA->SHA_IODATAR[4];
312  p[5] = SHA->SHA_IODATAR[5];
313  p[6] = SHA->SHA_IODATAR[6];
314  p[7] = SHA->SHA_IODATAR[7];
315 
316  //Release exclusive access to the SHA module
318 
319  //Sucessful processing
320  return NO_ERROR;
321 }
322 
323 #endif
324 #if (SHA384_SUPPORT == ENABLED)
325 
326 /**
327  * @brief Digest a message using SHA-384
328  * @param[in] data Pointer to the message being hashed
329  * @param[in] length Length of the message
330  * @param[out] digest Pointer to the calculated digest
331  * @return Error code
332  **/
333 
334 error_t sha384Compute(const void *data, size_t length, uint8_t *digest)
335 {
336  size_t n;
337  uint32_t *p;
338  uint8_t buffer[128];
339 
340  //Acquire exclusive access to the SHA module
342 
343  //Perform software reset
344  SHA->SHA_CR = SHA_CR_SWRST;
345  //Select the relevant hash algorithm
346  SHA->SHA_MR = SHA_MR_ALGO_SHA384 | SHA_MR_SMOD_MANUAL_START;
347  //For the first block of a message, the FIRST command must be set
348  SHA->SHA_CR = SHA_CR_FIRST;
349 
350  //Digest the message
351  for(n = length; n >= 128; n -= 128)
352  {
353  //Update hash value
355  //Advance the data pointer
356  data = (uint8_t *) data + 128;
357  }
358 
359  //Copy the partial block, is any
360  osMemset(buffer, 0, 128);
361  osMemcpy(buffer, data, n);
362 
363  //Append the first byte of the padding string
364  buffer[n] = 0x80;
365 
366  //Pad the message so that its length is congruent to 112 modulo 128
367  if(n >= 112)
368  {
369  hashProcessDataBlock(buffer, 128);
370  osMemset(buffer, 0, 128);
371  }
372 
373  //Append the length of the original message
374  STORE64BE(length * 8, buffer + 120);
375 
376  //Process the final block
377  hashProcessDataBlock(buffer, 128);
378 
379  //Save the resulting hash value
380  p = (uint32_t *) digest;
381  p[0] = SHA->SHA_IODATAR[0];
382  p[1] = SHA->SHA_IODATAR[1];
383  p[2] = SHA->SHA_IODATAR[2];
384  p[3] = SHA->SHA_IODATAR[3];
385  p[4] = SHA->SHA_IODATAR[4];
386  p[5] = SHA->SHA_IODATAR[5];
387  p[6] = SHA->SHA_IODATAR[6];
388  p[7] = SHA->SHA_IODATAR[7];
389  p[8] = SHA->SHA_IODATAR[8];
390  p[9] = SHA->SHA_IODATAR[9];
391  p[10] = SHA->SHA_IODATAR[10];
392  p[11] = SHA->SHA_IODATAR[11];
393 
394  //Release exclusive access to the SHA module
396 
397  //Sucessful processing
398  return NO_ERROR;
399 }
400 
401 #endif
402 #if (SHA512_SUPPORT == ENABLED)
403 
404 /**
405  * @brief Digest a message using SHA-512
406  * @param[in] data Pointer to the message being hashed
407  * @param[in] length Length of the message
408  * @param[out] digest Pointer to the calculated digest
409  * @return Error code
410  **/
411 
412 error_t sha512Compute(const void *data, size_t length, uint8_t *digest)
413 {
414  size_t n;
415  uint32_t *p;
416  uint8_t buffer[128];
417 
418  //Acquire exclusive access to the SHA module
420 
421  //Perform software reset
422  SHA->SHA_CR = SHA_CR_SWRST;
423  //Select the relevant hash algorithm
424  SHA->SHA_MR = SHA_MR_ALGO_SHA512 | SHA_MR_SMOD_MANUAL_START;
425  //For the first block of a message, the FIRST command must be set
426  SHA->SHA_CR = SHA_CR_FIRST;
427 
428  //Digest the message
429  for(n = length; n >= 128; n -= 128)
430  {
431  //Update hash value
433  //Advance the data pointer
434  data = (uint8_t *) data + 128;
435  }
436 
437  //Copy the partial block, is any
438  osMemset(buffer, 0, 128);
439  osMemcpy(buffer, data, n);
440 
441  //Append the first byte of the padding string
442  buffer[n] = 0x80;
443 
444  //Pad the message so that its length is congruent to 112 modulo 128
445  if(n >= 112)
446  {
447  hashProcessDataBlock(buffer, 128);
448  osMemset(buffer, 0, 128);
449  }
450 
451  //Append the length of the original message
452  STORE64BE(length * 8, buffer + 120);
453 
454  //Process the final block
455  hashProcessDataBlock(buffer, 128);
456 
457  //Save the resulting hash value
458  p = (uint32_t *) digest;
459  p[0] = SHA->SHA_IODATAR[0];
460  p[1] = SHA->SHA_IODATAR[1];
461  p[2] = SHA->SHA_IODATAR[2];
462  p[3] = SHA->SHA_IODATAR[3];
463  p[4] = SHA->SHA_IODATAR[4];
464  p[5] = SHA->SHA_IODATAR[5];
465  p[6] = SHA->SHA_IODATAR[6];
466  p[7] = SHA->SHA_IODATAR[7];
467  p[8] = SHA->SHA_IODATAR[8];
468  p[9] = SHA->SHA_IODATAR[9];
469  p[10] = SHA->SHA_IODATAR[10];
470  p[11] = SHA->SHA_IODATAR[11];
471  p[12] = SHA->SHA_IODATAR[12];
472  p[13] = SHA->SHA_IODATAR[13];
473  p[14] = SHA->SHA_IODATAR[14];
474  p[15] = SHA->SHA_IODATAR[15];
475 
476  //Release exclusive access to the SHA module
478 
479  //Sucessful processing
480  return NO_ERROR;
481 }
482 
483 #endif
484 #endif
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
General definitions for cryptographic algorithms.
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t data[]
Definition: ethernet.h:222
Collection of hash algorithms.
uint8_t p
Definition: ndp.h:300
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
OsMutex sama5d3CryptoMutex
SAMA5D3 hardware cryptographic accelerator.
error_t sha224Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-224.
error_t sha512Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-512.
void hashProcessDataBlock(const uint8_t *data, size_t length)
Process data block.
error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-256.
error_t sha384Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-384.
error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-1.
SAMA5D3 hash hardware accelerator.
uint8_t length
Definition: tcp.h:368