sam9x7_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file sam9x7_crypto_hash.c
3  * @brief SAM9X70/72/75 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 "sam.h"
36 #include "core/crypto.h"
39 #include "hash/hash_algorithms.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (SAM9X7_CRYPTO_HASH_SUPPORT == ENABLED)
44 
45 //Padding string
46 static const uint8_t padding[128] =
47 {
48  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
56 };
57 
58 
59 /**
60  * @brief Update hash value
61  * @param[in] algo Hash algorithm
62  * @param[in] data Pointer to the input buffer
63  * @param[in] length Length of the input buffer
64  * @param[in,out] h Hash value
65  **/
66 
67 void hashProcessData(uint32_t algo, const uint8_t *data, size_t length,
68  uint32_t *h)
69 {
70  size_t blockSize;
71 
72  //Get block size
73  blockSize = (algo == SHA_MR_ALGO_SHA512) ? 128 : 64;
74 
75  //Acquire exclusive access to the SHA module
77 
78  //Perform software reset
79  SHA_REGS->SHA_CR = SHA_CR_SWRST_Msk;
80 
81  //Select the relevant hash algorithm
82  SHA_REGS->SHA_MR = SHA_MR_UIHV_Msk | SHA_MR_SMOD_MANUAL_START | algo;
83 
84  //Set the WUIHV bit before loading the initial hash value
85  SHA_REGS->SHA_CR = SHA_CR_WUIHV_Msk;
86 
87  //Restore initial hash value
88  SHA_REGS->SHA_IDATAR[0] = h[0];
89  SHA_REGS->SHA_IDATAR[1] = h[1];
90  SHA_REGS->SHA_IDATAR[2] = h[2];
91  SHA_REGS->SHA_IDATAR[3] = h[3];
92  SHA_REGS->SHA_IDATAR[4] = h[4];
93 
94  //SHA-256 or SHA-512 algorithm?
95  if(algo == SHA_MR_ALGO_SHA256 || algo == SHA_MR_ALGO_SHA512)
96  {
97  SHA_REGS->SHA_IDATAR[5] = h[5];
98  SHA_REGS->SHA_IDATAR[6] = h[6];
99  SHA_REGS->SHA_IDATAR[7] = h[7];
100  }
101 
102  //SHA-512 algorithm?
103  if(algo == SHA_MR_ALGO_SHA512)
104  {
105  SHA_REGS->SHA_IDATAR[8] = h[8];
106  SHA_REGS->SHA_IDATAR[9] = h[9];
107  SHA_REGS->SHA_IDATAR[10] = h[10];
108  SHA_REGS->SHA_IDATAR[11] = h[11];
109  SHA_REGS->SHA_IDATAR[12] = h[12];
110  SHA_REGS->SHA_IDATAR[13] = h[13];
111  SHA_REGS->SHA_IDATAR[14] = h[14];
112  SHA_REGS->SHA_IDATAR[15] = h[15];
113  }
114 
115  //The FIRST bit indicates that the next block to process is the first one
116  //of the message
117  SHA_REGS->SHA_CR = SHA_CR_FIRST_Msk;
118 
119  //Input data are processed in a block-by-block fashion
120  while(length >= blockSize)
121  {
122  //Write the block to be processed to the input data registers
123  SHA_REGS->SHA_IDATAR[0] = LOAD32LE(data);
124  SHA_REGS->SHA_IDATAR[1] = LOAD32LE(data + 4);
125  SHA_REGS->SHA_IDATAR[2] = LOAD32LE(data + 8);
126  SHA_REGS->SHA_IDATAR[3] = LOAD32LE(data + 12);
127  SHA_REGS->SHA_IDATAR[4] = LOAD32LE(data + 16);
128  SHA_REGS->SHA_IDATAR[5] = LOAD32LE(data + 20);
129  SHA_REGS->SHA_IDATAR[6] = LOAD32LE(data + 24);
130  SHA_REGS->SHA_IDATAR[7] = LOAD32LE(data + 28);
131  SHA_REGS->SHA_IDATAR[8] = LOAD32LE(data + 32);
132  SHA_REGS->SHA_IDATAR[9] = LOAD32LE(data + 36);
133  SHA_REGS->SHA_IDATAR[10] = LOAD32LE(data + 40);
134  SHA_REGS->SHA_IDATAR[11] = LOAD32LE(data + 44);
135  SHA_REGS->SHA_IDATAR[12] = LOAD32LE(data + 48);
136  SHA_REGS->SHA_IDATAR[13] = LOAD32LE(data + 52);
137  SHA_REGS->SHA_IDATAR[14] = LOAD32LE(data + 56);
138  SHA_REGS->SHA_IDATAR[15] = LOAD32LE(data + 60);
139 
140  //SHA-512 algorithm?
141  if(algo == SHA_MR_ALGO_SHA512)
142  {
143  SHA_REGS->SHA_IODATAR[0] = LOAD32LE(data + 64);
144  SHA_REGS->SHA_IODATAR[1] = LOAD32LE(data + 68);
145  SHA_REGS->SHA_IODATAR[2] = LOAD32LE(data + 72);
146  SHA_REGS->SHA_IODATAR[3] = LOAD32LE(data + 76);
147  SHA_REGS->SHA_IODATAR[4] = LOAD32LE(data + 80);
148  SHA_REGS->SHA_IODATAR[5] = LOAD32LE(data + 84);
149  SHA_REGS->SHA_IODATAR[6] = LOAD32LE(data + 88);
150  SHA_REGS->SHA_IODATAR[7] = LOAD32LE(data + 92);
151  SHA_REGS->SHA_IODATAR[8] = LOAD32LE(data + 96);
152  SHA_REGS->SHA_IODATAR[9] = LOAD32LE(data + 100);
153  SHA_REGS->SHA_IODATAR[10] = LOAD32LE(data + 104);
154  SHA_REGS->SHA_IODATAR[11] = LOAD32LE(data + 108);
155  SHA_REGS->SHA_IODATAR[12] = LOAD32LE(data + 112);
156  SHA_REGS->SHA_IODATAR[13] = LOAD32LE(data + 116);
157  SHA_REGS->SHA_IODATAR[14] = LOAD32LE(data + 120);
158  SHA_REGS->SHA_IODATAR[15] = LOAD32LE(data + 124);
159  }
160 
161  //Set the START bit to begin the processing
162  SHA_REGS->SHA_CR = SHA_CR_START_Msk;
163 
164  //When processing completes, the DATRDY flag is raised
165  while((SHA_REGS->SHA_ISR & SHA_ISR_DATRDY_Msk) == 0)
166  {
167  }
168 
169  //Advance data pointer
170  data += blockSize;
171  length -= blockSize;
172  }
173 
174  //Save intermediate hash value
175  h[0] = SHA_REGS->SHA_IODATAR[0];
176  h[1] = SHA_REGS->SHA_IODATAR[1];
177  h[2] = SHA_REGS->SHA_IODATAR[2];
178  h[3] = SHA_REGS->SHA_IODATAR[3];
179  h[4] = SHA_REGS->SHA_IODATAR[4];
180 
181  //SHA-256 or SHA-512 algorithm?
182  if(algo == SHA_MR_ALGO_SHA256 || algo == SHA_MR_ALGO_SHA512)
183  {
184  h[5] = SHA_REGS->SHA_IODATAR[5];
185  h[6] = SHA_REGS->SHA_IODATAR[6];
186  h[7] = SHA_REGS->SHA_IODATAR[7];
187  }
188 
189  //SHA-512 algorithm?
190  if(algo == SHA_MR_ALGO_SHA512)
191  {
192  h[8] = SHA_REGS->SHA_IODATAR[8];
193  h[9] = SHA_REGS->SHA_IODATAR[9];
194  h[10] = SHA_REGS->SHA_IODATAR[10];
195  h[11] = SHA_REGS->SHA_IODATAR[11];
196  h[12] = SHA_REGS->SHA_IODATAR[12];
197  h[13] = SHA_REGS->SHA_IODATAR[13];
198  h[14] = SHA_REGS->SHA_IODATAR[14];
199  h[15] = SHA_REGS->SHA_IODATAR[15];
200  }
201 
202  //Release exclusive access to the SHA module
204 }
205 
206 
207 #if (SHA1_SUPPORT == ENABLED)
208 
209 /**
210  * @brief Initialize SHA-1 message digest context
211  * @param[in] context Pointer to the SHA-1 context to initialize
212  **/
213 
214 void sha1Init(Sha1Context *context)
215 {
216  //Set initial hash value
217  context->h[0] = BETOH32(0x67452301);
218  context->h[1] = BETOH32(0xEFCDAB89);
219  context->h[2] = BETOH32(0x98BADCFE);
220  context->h[3] = BETOH32(0x10325476);
221  context->h[4] = BETOH32(0xC3D2E1F0);
222 
223  //Number of bytes in the buffer
224  context->size = 0;
225  //Total length of the message
226  context->totalSize = 0;
227 }
228 
229 
230 /**
231  * @brief Update the SHA-1 context with a portion of the message being hashed
232  * @param[in] context Pointer to the SHA-1 context
233  * @param[in] data Pointer to the buffer being hashed
234  * @param[in] length Length of the buffer
235  **/
236 
237 void sha1Update(Sha1Context *context, const void *data, size_t length)
238 {
239  size_t n;
240 
241  //Process the incoming data
242  while(length > 0)
243  {
244  //Check whether some data is pending in the buffer
245  if(context->size == 0 && length >= 64)
246  {
247  //The length must be a multiple of 64 bytes
248  n = length - (length % 64);
249 
250  //Update hash value
251  hashProcessData(SHA_MR_ALGO_SHA1, data, n, context->h);
252 
253  //Update the SHA-1 context
254  context->totalSize += n;
255  //Advance the data pointer
256  data = (uint8_t *) data + n;
257  //Remaining bytes to process
258  length -= n;
259  }
260  else
261  {
262  //The buffer can hold at most 64 bytes
263  n = MIN(length, 64 - context->size);
264 
265  //Copy the data to the buffer
266  osMemcpy(context->buffer + context->size, data, n);
267 
268  //Update the SHA-1 context
269  context->size += n;
270  context->totalSize += n;
271  //Advance the data pointer
272  data = (uint8_t *) data + n;
273  //Remaining bytes to process
274  length -= n;
275 
276  //Check whether the buffer is full
277  if(context->size == 64)
278  {
279  //Update hash value
280  hashProcessData(SHA_MR_ALGO_SHA1, context->buffer, context->size,
281  context->h);
282 
283  //Empty the buffer
284  context->size = 0;
285  }
286  }
287  }
288 }
289 
290 
291 /**
292  * @brief Finish the SHA-1 message digest
293  * @param[in] context Pointer to the SHA-1 context
294  * @param[out] digest Calculated digest
295  **/
296 
297 void sha1Final(Sha1Context *context, uint8_t *digest)
298 {
299  uint_t i;
300  size_t paddingSize;
301  uint64_t totalSize;
302 
303  //Length of the original message (before padding)
304  totalSize = context->totalSize * 8;
305 
306  //Pad the message so that its length is congruent to 56 modulo 64
307  if(context->size < 56)
308  {
309  paddingSize = 56 - context->size;
310  }
311  else
312  {
313  paddingSize = 64 + 56 - context->size;
314  }
315 
316  //Append padding
317  sha1Update(context, padding, paddingSize);
318 
319  //Append the length of the original message
320  for(i = 0; i < 8; i++)
321  {
322  context->buffer[63 - i] = totalSize & 0xFF;
323  totalSize >>= 8;
324  }
325 
326  //Calculate the message digest
327  hashProcessData(SHA_MR_ALGO_SHA1, context->buffer, 64, context->h);
328 
329  //Copy the resulting digest
330  for(i = 0; i < (SHA1_DIGEST_SIZE / 4); i++)
331  {
332  STORE32LE(context->h[i], digest + i * 4);
333  }
334 }
335 
336 
337 /**
338  * @brief Finish the SHA-1 message digest (no padding added)
339  * @param[in] context Pointer to the SHA-1 context
340  * @param[out] digest Calculated digest
341  **/
342 
343 void sha1FinalRaw(Sha1Context *context, uint8_t *digest)
344 {
345  uint_t i;
346 
347  //Copy the resulting digest
348  for(i = 0; i < (SHA1_DIGEST_SIZE / 4); i++)
349  {
350  STORE32LE(context->h[i], digest + i * 4);
351  }
352 }
353 
354 #endif
355 #if (SHA224_SUPPORT == ENABLED)
356 
357 /**
358  * @brief Initialize SHA-224 message digest context
359  * @param[in] context Pointer to the SHA-224 context to initialize
360  **/
361 
362 void sha224Init(Sha224Context *context)
363 {
364  //Set initial hash value
365  context->h[0] = BETOH32(0xC1059ED8);
366  context->h[1] = BETOH32(0x367CD507);
367  context->h[2] = BETOH32(0x3070DD17);
368  context->h[3] = BETOH32(0xF70E5939);
369  context->h[4] = BETOH32(0xFFC00B31);
370  context->h[5] = BETOH32(0x68581511);
371  context->h[6] = BETOH32(0x64F98FA7);
372  context->h[7] = BETOH32(0xBEFA4FA4);
373 
374  //Number of bytes in the buffer
375  context->size = 0;
376  //Total length of the message
377  context->totalSize = 0;
378 }
379 
380 #endif
381 #if (SHA256_SUPPORT == ENABLED)
382 
383 /**
384  * @brief Initialize SHA-256 message digest context
385  * @param[in] context Pointer to the SHA-256 context to initialize
386  **/
387 
388 void sha256Init(Sha256Context *context)
389 {
390  //Set initial hash value
391  context->h[0] = BETOH32(0x6A09E667);
392  context->h[1] = BETOH32(0xBB67AE85);
393  context->h[2] = BETOH32(0x3C6EF372);
394  context->h[3] = BETOH32(0xA54FF53A);
395  context->h[4] = BETOH32(0x510E527F);
396  context->h[5] = BETOH32(0x9B05688C);
397  context->h[6] = BETOH32(0x1F83D9AB);
398  context->h[7] = BETOH32(0x5BE0CD19);
399 
400  //Number of bytes in the buffer
401  context->size = 0;
402  //Total length of the message
403  context->totalSize = 0;
404 }
405 
406 
407 /**
408  * @brief Update the SHA-256 context with a portion of the message being hashed
409  * @param[in] context Pointer to the SHA-256 context
410  * @param[in] data Pointer to the buffer being hashed
411  * @param[in] length Length of the buffer
412  **/
413 
414 void sha256Update(Sha256Context *context, const void *data, size_t length)
415 {
416  size_t n;
417 
418  //Process the incoming data
419  while(length > 0)
420  {
421  //Check whether some data is pending in the buffer
422  if(context->size == 0 && length >= 64)
423  {
424  //The length must be a multiple of 64 bytes
425  n = length - (length % 64);
426 
427  //Update hash value
428  hashProcessData(SHA_MR_ALGO_SHA256, data, n, context->h);
429 
430  //Update the SHA-256 context
431  context->totalSize += n;
432  //Advance the data pointer
433  data = (uint8_t *) data + n;
434  //Remaining bytes to process
435  length -= n;
436  }
437  else
438  {
439  //The buffer can hold at most 64 bytes
440  n = MIN(length, 64 - context->size);
441 
442  //Copy the data to the buffer
443  osMemcpy(context->buffer + context->size, data, n);
444 
445  //Update the SHA-256 context
446  context->size += n;
447  context->totalSize += n;
448  //Advance the data pointer
449  data = (uint8_t *) data + n;
450  //Remaining bytes to process
451  length -= n;
452 
453  //Check whether the buffer is full
454  if(context->size == 64)
455  {
456  //Update hash value
457  hashProcessData(SHA_MR_ALGO_SHA256, context->buffer, context->size,
458  context->h);
459 
460  //Empty the buffer
461  context->size = 0;
462  }
463  }
464  }
465 }
466 
467 
468 /**
469  * @brief Finish the SHA-256 message digest
470  * @param[in] context Pointer to the SHA-256 context
471  * @param[out] digest Calculated digest
472  **/
473 
474 void sha256Final(Sha256Context *context, uint8_t *digest)
475 {
476  uint_t i;
477  size_t paddingSize;
478  uint64_t totalSize;
479 
480  //Length of the original message (before padding)
481  totalSize = context->totalSize * 8;
482 
483  //Pad the message so that its length is congruent to 56 modulo 64
484  if(context->size < 56)
485  {
486  paddingSize = 56 - context->size;
487  }
488  else
489  {
490  paddingSize = 64 + 56 - context->size;
491  }
492 
493  //Append padding
494  sha256Update(context, padding, paddingSize);
495 
496  //Append the length of the original message
497  for(i = 0; i < 8; i++)
498  {
499  context->buffer[63 - i] = totalSize & 0xFF;
500  totalSize >>= 8;
501  }
502 
503  //Calculate the message digest
504  hashProcessData(SHA_MR_ALGO_SHA256, context->buffer, 64, context->h);
505 
506  //Copy the resulting digest
507  for(i = 0; i < (SHA256_DIGEST_SIZE / 4); i++)
508  {
509  STORE32LE(context->h[i], digest + i * 4);
510  }
511 }
512 
513 
514 /**
515  * @brief Finish the SHA-256 message digest (no padding added)
516  * @param[in] context Pointer to the SHA-256 context
517  * @param[out] digest Calculated digest
518  **/
519 
520 void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
521 {
522  uint_t i;
523 
524  //Copy the resulting digest
525  for(i = 0; i < (SHA256_DIGEST_SIZE / 4); i++)
526  {
527  STORE32LE(context->h[i], digest + i * 4);
528  }
529 }
530 
531 #endif
532 #if (SHA384_SUPPORT == ENABLED)
533 
534 /**
535  * @brief Initialize SHA-384 message digest context
536  * @param[in] context Pointer to the SHA-384 context to initialize
537  **/
538 
539 void sha384Init(Sha384Context *context)
540 {
541  //Set initial hash value
542  context->h[0] = BETOH64(0xCBBB9D5DC1059ED8);
543  context->h[1] = BETOH64(0x629A292A367CD507);
544  context->h[2] = BETOH64(0x9159015A3070DD17);
545  context->h[3] = BETOH64(0x152FECD8F70E5939);
546  context->h[4] = BETOH64(0x67332667FFC00B31);
547  context->h[5] = BETOH64(0x8EB44A8768581511);
548  context->h[6] = BETOH64(0xDB0C2E0D64F98FA7);
549  context->h[7] = BETOH64(0x47B5481DBEFA4FA4);
550 
551  //Number of bytes in the buffer
552  context->size = 0;
553  //Total length of the message
554  context->totalSize = 0;
555 }
556 
557 
558 /**
559  * @brief Finish the SHA-384 message digest (no padding added)
560  * @param[in] context Pointer to the SHA-384 context
561  * @param[out] digest Calculated digest
562  **/
563 
564 void sha384FinalRaw(Sha384Context *context, uint8_t *digest)
565 {
566  uint_t i;
567 
568  //Copy the resulting digest
569  for(i = 0; i < (SHA384_DIGEST_SIZE / 8); i++)
570  {
571  STORE64LE(context->h[i], digest + i * 8);
572  }
573 }
574 
575 #endif
576 #if (SHA512_SUPPORT == ENABLED)
577 
578 /**
579  * @brief Initialize SHA-512 message digest context
580  * @param[in] context Pointer to the SHA-512 context to initialize
581  **/
582 
583 void sha512Init(Sha512Context *context)
584 {
585  //Set initial hash value
586  context->h[0] = BETOH64(0x6A09E667F3BCC908);
587  context->h[1] = BETOH64(0xBB67AE8584CAA73B);
588  context->h[2] = BETOH64(0x3C6EF372FE94F82B);
589  context->h[3] = BETOH64(0xA54FF53A5F1D36F1);
590  context->h[4] = BETOH64(0x510E527FADE682D1);
591  context->h[5] = BETOH64(0x9B05688C2B3E6C1F);
592  context->h[6] = BETOH64(0x1F83D9ABFB41BD6B);
593  context->h[7] = BETOH64(0x5BE0CD19137E2179);
594 
595  //Number of bytes in the buffer
596  context->size = 0;
597  //Total length of the message
598  context->totalSize = 0;
599 }
600 
601 
602 /**
603  * @brief Update the SHA-512 context with a portion of the message being hashed
604  * @param[in] context Pointer to the SHA-512 context
605  * @param[in] data Pointer to the buffer being hashed
606  * @param[in] length Length of the buffer
607  **/
608 
609 void sha512Update(Sha512Context *context, const void *data, size_t length)
610 {
611  size_t n;
612 
613  //Process the incoming data
614  while(length > 0)
615  {
616  //Check whether some data is pending in the buffer
617  if(context->size == 0 && length >= 128)
618  {
619  //The length must be a multiple of 128 bytes
620  n = length - (length % 128);
621 
622  //Update hash value
623  hashProcessData(SHA_MR_ALGO_SHA512, data, n, (uint32_t *) context->h);
624 
625  //Update the SHA-512 context
626  context->totalSize += n;
627  //Advance the data pointer
628  data = (uint8_t *) data + n;
629  //Remaining bytes to process
630  length -= n;
631  }
632  else
633  {
634  //The buffer can hold at most 128 bytes
635  n = MIN(length, 128 - context->size);
636 
637  //Copy the data to the buffer
638  osMemcpy(context->buffer + context->size, data, n);
639 
640  //Update the SHA-512 context
641  context->size += n;
642  context->totalSize += n;
643  //Advance the data pointer
644  data = (uint8_t *) data + n;
645  //Remaining bytes to process
646  length -= n;
647 
648  //Check whether the buffer is full
649  if(context->size == 128)
650  {
651  //Update hash value
652  hashProcessData(SHA_MR_ALGO_SHA512, context->buffer, context->size,
653  (uint32_t *) context->h);
654 
655  //Empty the buffer
656  context->size = 0;
657  }
658  }
659  }
660 }
661 
662 
663 /**
664  * @brief Finish the SHA-512 message digest
665  * @param[in] context Pointer to the SHA-512 context
666  * @param[out] digest Calculated digest
667  **/
668 
669 void sha512Final(Sha512Context *context, uint8_t *digest)
670 {
671  uint_t i;
672  size_t paddingSize;
673  uint64_t totalSize;
674 
675  //Length of the original message (before padding)
676  totalSize = context->totalSize * 8;
677 
678  //Pad the message so that its length is congruent to 112 modulo 128
679  if(context->size < 112)
680  {
681  paddingSize = 112 - context->size;
682  }
683  else
684  {
685  paddingSize = 128 + 112 - context->size;
686  }
687 
688  //Append padding
689  sha512Update(context, padding, paddingSize);
690 
691  //Append the length of the original message
692  for(i = 0; i < 16; i++)
693  {
694  context->buffer[127 - i] = totalSize & 0xFF;
695  totalSize >>= 8;
696  }
697 
698  //Calculate the message digest
699  hashProcessData(SHA_MR_ALGO_SHA512, context->buffer, 128,
700  (uint32_t *) context->h);
701 
702  //Copy the resulting digest
703  for(i = 0; i < (SHA512_DIGEST_SIZE / 8); i++)
704  {
705  STORE64LE(context->h[i], digest + i * 8);
706  }
707 }
708 
709 #endif
710 #if (SHA512_224_SUPPORT == ENABLED)
711 
712 /**
713  * @brief Initialize SHA-512/224 message digest context
714  * @param[in] context Pointer to the SHA-512/224 context to initialize
715  **/
716 
718 {
719  //Set initial hash value
720  context->h[0] = BETOH64(0x8C3D37C819544DA2);
721  context->h[1] = BETOH64(0x73E1996689DCD4D6);
722  context->h[2] = BETOH64(0x1DFAB7AE32FF9C82);
723  context->h[3] = BETOH64(0x679DD514582F9FCF);
724  context->h[4] = BETOH64(0x0F6D2B697BD44DA8);
725  context->h[5] = BETOH64(0x77E36F7304C48942);
726  context->h[6] = BETOH64(0x3F9D85A86A1D36C8);
727  context->h[7] = BETOH64(0x1112E6AD91D692A1);
728 
729  //Number of bytes in the buffer
730  context->size = 0;
731  //Total length of the message
732  context->totalSize = 0;
733 }
734 
735 #endif
736 #if (SHA512_256_SUPPORT == ENABLED)
737 
738 /**
739  * @brief Initialize SHA-512/256 message digest context
740  * @param[in] context Pointer to the SHA-512/256 context to initialize
741  **/
742 
744 {
745  //Set initial hash value
746  context->h[0] = BETOH64(0x22312194FC2BF72C);
747  context->h[1] = BETOH64(0x9F555FA3C84C64C2);
748  context->h[2] = BETOH64(0x2393B86B6F53B151);
749  context->h[3] = BETOH64(0x963877195940EABD);
750  context->h[4] = BETOH64(0x96283EE2A88EFFE3);
751  context->h[5] = BETOH64(0xBE5E1E2553863992);
752  context->h[6] = BETOH64(0x2B0199FC2C85B8AA);
753  context->h[7] = BETOH64(0x0EB72DDC81C52CA2);
754 
755  //Number of bytes in the buffer
756  context->size = 0;
757  //Total length of the message
758  context->totalSize = 0;
759 }
760 
761 #endif
762 #endif
void sha384FinalRaw(Sha384Context *context, uint8_t *digest)
Finish the SHA-384 message digest (no padding added)
SHA-256 algorithm context.
Definition: sha256.h:62
void sha512Final(Sha512Context *context, uint8_t *digest)
Finish the SHA-512 message digest.
void sha224Init(Sha224Context *context)
Initialize SHA-224 message digest context.
SAM9X70/72/75 hash hardware accelerator.
uint8_t data[]
Definition: ethernet.h:222
#define STORE32LE(a, p)
Definition: cpu_endian.h:279
size_t size
Definition: sha256.h:69
void sha256Init(Sha256Context *context)
Initialize SHA-256 message digest context.
uint32_t h[8]
Definition: sha256.h:63
#define BETOH32(value)
Definition: cpu_endian.h:451
uint64_t totalSize
Definition: sha1.h:70
size_t size
Definition: sha512.h:69
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
uint8_t h
Definition: ndp.h:302
void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest (no padding added)
void sha256Update(Sha256Context *context, const void *data, size_t length)
Update the SHA-256 context with a portion of the message being hashed.
void sha512_224Init(Sha512_224Context *context)
Initialize SHA-512/224 message digest context.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
void sha384Init(Sha384Context *context)
Initialize SHA-384 message digest context.
void sha1FinalRaw(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest (no padding added)
OsMutex sam9x7CryptoMutex
Definition: sam9x7_crypto.c:44
SHA-512 algorithm context.
Definition: sha512.h:62
uint32_t h[5]
Definition: sha1.h:63
General definitions for cryptographic algorithms.
uint8_t buffer[128]
Definition: sha512.h:67
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 length
Definition: tcp.h:375
uint8_t buffer[64]
Definition: sha256.h:67
void hashProcessData(uint32_t algo, const uint8_t *data, size_t length, uint32_t *h)
Update hash value.
#define MIN(a, b)
Definition: os_port.h:63
#define SHA384_DIGEST_SIZE
Definition: sha384.h:41
Collection of hash algorithms.
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
void sha256Final(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest.
uint64_t h[8]
Definition: sha512.h:63
uint8_t n
#define STORE64LE(a, p)
Definition: cpu_endian.h:311
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:69
#define BETOH64(value)
Definition: cpu_endian.h:452
SHA-1 algorithm context.
Definition: sha1.h:62
uint8_t buffer[64]
Definition: sha1.h:67
void sha512_256Init(Sha512_256Context *context)
Initialize SHA-512/256 message digest context.
uint64_t totalSize
Definition: sha512.h:70
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
#define LOAD32LE(p)
Definition: cpu_endian.h:203
uint64_t totalSize
Definition: sha256.h:70
unsigned int uint_t
Definition: compiler_port.h:57
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
SAM9X7 hardware cryptographic accelerator.
Debugging facilities.
void sha512Init(Sha512Context *context)
Initialize SHA-512 message digest context.