sha256.c
Go to the documentation of this file.
1 /**
2  * @file sha256.c
3  * @brief SHA-256 (Secure Hash Algorithm 256)
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  * @section Description
28  *
29  * SHA-256 is a secure hash algorithm for computing a condensed representation
30  * of an electronic message. Refer to FIPS 180-4 for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.0
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "hash/sha256.h"
42 
43 //Check crypto library configuration
44 #if (SHA224_SUPPORT == ENABLED || SHA256_SUPPORT == ENABLED)
45 
46 //Macro to access the workspace as a circular buffer
47 #define W(n) w[(n) & 0x0F]
48 
49 //SHA-256 auxiliary functions
50 #define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
51 #define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
52 #define SIGMA1(x) (ROR32(x, 2) ^ ROR32(x, 13) ^ ROR32(x, 22))
53 #define SIGMA2(x) (ROR32(x, 6) ^ ROR32(x, 11) ^ ROR32(x, 25))
54 #define SIGMA3(x) (ROR32(x, 7) ^ ROR32(x, 18) ^ SHR32(x, 3))
55 #define SIGMA4(x) (ROR32(x, 17) ^ ROR32(x, 19) ^ SHR32(x, 10))
56 
57 //SHA-256 padding
58 static const uint8_t padding[64] =
59 {
60  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
64 };
65 
66 //SHA-256 constants
67 static const uint32_t k[64] =
68 {
69  0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
70  0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
71  0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
72  0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
73  0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
74  0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
75  0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
76  0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
77 };
78 
79 //SHA-256 object identifier (2.16.840.1.101.3.4.2.1)
80 const uint8_t SHA256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01};
81 
82 //Common interface for hash algorithms
84 {
85  "SHA-256",
86  SHA256_OID,
87  sizeof(SHA256_OID),
88  sizeof(Sha256Context),
92  TRUE,
97 #if ((defined(MIMXRT1050_CRYPTO_HASH_SUPPORT) && MIMXRT1050_CRYPTO_HASH_SUPPORT == ENABLED) || \
98  (defined(MIMXRT1060_CRYPTO_HASH_SUPPORT) && MIMXRT1060_CRYPTO_HASH_SUPPORT == ENABLED) || \
99  (defined(MIMXRT1160_CRYPTO_HASH_SUPPORT) && MIMXRT1160_CRYPTO_HASH_SUPPORT == ENABLED) || \
100  (defined(MIMXRT1170_CRYPTO_HASH_SUPPORT) && MIMXRT1170_CRYPTO_HASH_SUPPORT == ENABLED))
101  NULL,
102 #else
104 #endif
105 };
106 
107 
108 /**
109  * @brief Digest a message using SHA-256
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 __weak_func error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
117 {
118 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
119  Sha256Context *context;
120 #else
121  Sha256Context context[1];
122 #endif
123 
124  //Check parameters
125  if(data == NULL && length != 0)
127 
128  if(digest == NULL)
130 
131 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
132  //Allocate a memory buffer to hold the SHA-256 context
133  context = cryptoAllocMem(sizeof(Sha256Context));
134  //Failed to allocate memory?
135  if(context == NULL)
136  return ERROR_OUT_OF_MEMORY;
137 #endif
138 
139  //Initialize the SHA-256 context
140  sha256Init(context);
141  //Digest the message
142  sha256Update(context, data, length);
143  //Finalize the SHA-256 message digest
144  sha256Final(context, digest);
145 
146 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
147  //Free previously allocated memory
148  cryptoFreeMem(context);
149 #endif
150 
151  //Successful processing
152  return NO_ERROR;
153 }
154 
155 
156 /**
157  * @brief Initialize SHA-256 message digest context
158  * @param[in] context Pointer to the SHA-256 context to initialize
159  **/
160 
161 __weak_func void sha256Init(Sha256Context *context)
162 {
163  //Set initial hash value
164  context->h[0] = 0x6A09E667;
165  context->h[1] = 0xBB67AE85;
166  context->h[2] = 0x3C6EF372;
167  context->h[3] = 0xA54FF53A;
168  context->h[4] = 0x510E527F;
169  context->h[5] = 0x9B05688C;
170  context->h[6] = 0x1F83D9AB;
171  context->h[7] = 0x5BE0CD19;
172 
173  //Number of bytes in the buffer
174  context->size = 0;
175  //Total length of the message
176  context->totalSize = 0;
177 }
178 
179 
180 /**
181  * @brief Update the SHA-256 context with a portion of the message being hashed
182  * @param[in] context Pointer to the SHA-256 context
183  * @param[in] data Pointer to the buffer being hashed
184  * @param[in] length Length of the buffer
185  **/
186 
187 __weak_func void sha256Update(Sha256Context *context, const void *data, size_t length)
188 {
189  size_t n;
190 
191  //Process the incoming data
192  while(length > 0)
193  {
194  //The buffer can hold at most 64 bytes
195  n = MIN(length, 64 - context->size);
196 
197  //Copy the data to the buffer
198  osMemcpy(context->buffer + context->size, data, n);
199 
200  //Update the SHA-256 context
201  context->size += n;
202  context->totalSize += n;
203  //Advance the data pointer
204  data = (uint8_t *) data + n;
205  //Remaining bytes to process
206  length -= n;
207 
208  //Process message in 16-word blocks
209  if(context->size == 64)
210  {
211  //Transform the 16-word block
212  sha256ProcessBlock(context);
213  //Empty the buffer
214  context->size = 0;
215  }
216  }
217 }
218 
219 
220 /**
221  * @brief Finish the SHA-256 message digest
222  * @param[in] context Pointer to the SHA-256 context
223  * @param[out] digest Calculated digest (optional parameter)
224  **/
225 
226 __weak_func void sha256Final(Sha256Context *context, uint8_t *digest)
227 {
228  uint_t i;
229  size_t paddingSize;
230  uint64_t totalSize;
231 
232  //Length of the original message (before padding)
233  totalSize = context->totalSize * 8;
234 
235  //Pad the message so that its length is congruent to 56 modulo 64
236  if(context->size < 56)
237  {
238  paddingSize = 56 - context->size;
239  }
240  else
241  {
242  paddingSize = 64 + 56 - context->size;
243  }
244 
245  //Append padding
246  sha256Update(context, padding, paddingSize);
247 
248  //Append the length of the original message
249  context->w[14] = htobe32((uint32_t) (totalSize >> 32));
250  context->w[15] = htobe32((uint32_t) totalSize);
251 
252  //Calculate the message digest
253  sha256ProcessBlock(context);
254 
255  //Convert from host byte order to big-endian byte order
256  for(i = 0; i < 8; i++)
257  {
258  context->h[i] = htobe32(context->h[i]);
259  }
260 
261  //Copy the resulting digest
262  if(digest != NULL)
263  {
264  osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
265  }
266 }
267 
268 
269 /**
270  * @brief Finish the SHA-256 message digest (no padding added)
271  * @param[in] context Pointer to the SHA-256 context
272  * @param[out] digest Calculated digest
273  **/
274 
275 __weak_func void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
276 {
277  uint_t i;
278 
279  //Convert from host byte order to big-endian byte order
280  for(i = 0; i < 8; i++)
281  {
282  context->h[i] = htobe32(context->h[i]);
283  }
284 
285  //Copy the resulting digest
286  osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
287 
288  //Convert from big-endian byte order to host byte order
289  for(i = 0; i < 8; i++)
290  {
291  context->h[i] = betoh32(context->h[i]);
292  }
293 }
294 
295 
296 /**
297  * @brief Process message in 16-word blocks
298  * @param[in] context Pointer to the SHA-256 context
299  **/
300 
301 __weak_func void sha256ProcessBlock(Sha256Context *context)
302 {
303  uint_t i;
304  uint32_t temp1;
305  uint32_t temp2;
306 
307  //Initialize the 8 working registers
308  uint32_t a = context->h[0];
309  uint32_t b = context->h[1];
310  uint32_t c = context->h[2];
311  uint32_t d = context->h[3];
312  uint32_t e = context->h[4];
313  uint32_t f = context->h[5];
314  uint32_t g = context->h[6];
315  uint32_t h = context->h[7];
316 
317  //Process message in 16-word blocks
318  uint32_t *w = context->w;
319 
320  //Convert from big-endian byte order to host byte order
321  for(i = 0; i < 16; i++)
322  {
323  w[i] = betoh32(w[i]);
324  }
325 
326  //SHA-256 hash computation (alternate method)
327  for(i = 0; i < 64; i++)
328  {
329  //Prepare the message schedule
330  if(i >= 16)
331  {
332  W(i) += SIGMA4(W(i + 14)) + W(i + 9) + SIGMA3(W(i + 1));
333  }
334 
335  //Calculate T1 and T2
336  temp1 = h + SIGMA2(e) + CH(e, f, g) + k[i] + W(i);
337  temp2 = SIGMA1(a) + MAJ(a, b, c);
338 
339  //Update working registers
340  h = g;
341  g = f;
342  f = e;
343  e = d + temp1;
344  d = c;
345  c = b;
346  b = a;
347  a = temp1 + temp2;
348  }
349 
350  //Update the hash value
351  context->h[0] += a;
352  context->h[1] += b;
353  context->h[2] += c;
354  context->h[3] += d;
355  context->h[4] += e;
356  context->h[5] += f;
357  context->h[6] += g;
358  context->h[7] += h;
359 }
360 
361 #endif
unsigned int uint_t
Definition: compiler_port.h:50
#define betoh32(value)
Definition: cpu_endian.h:454
#define htobe32(value)
Definition: cpu_endian.h:446
General definitions for cryptographic algorithms.
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:956
void(* HashAlgoFinalRaw)(void *context, uint8_t *digest)
Definition: crypto.h:965
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:963
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:961
#define cryptoAllocMem(size)
Definition: crypto.h:765
#define cryptoFreeMem(p)
Definition: crypto.h:770
void(* HashAlgoInit)(void *context)
Definition: crypto.h:959
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t data[]
Definition: ethernet.h:222
uint8_t b
Definition: nbns_common.h:104
uint8_t h
Definition: ndp.h:302
uint8_t c
Definition: ndp.h:514
uint8_t a
Definition: ndp.h:411
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define CH(x, y, z)
Definition: sha256.c:50
#define SIGMA3(x)
Definition: sha256.c:54
__weak_func void sha256ProcessBlock(Sha256Context *context)
Process message in 16-word blocks.
Definition: sha256.c:301
const uint8_t SHA256_OID[9]
Definition: sha256.c:80
__weak_func void sha256Update(Sha256Context *context, const void *data, size_t length)
Update the SHA-256 context with a portion of the message being hashed.
Definition: sha256.c:187
__weak_func void sha256Final(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest.
Definition: sha256.c:226
#define SIGMA2(x)
Definition: sha256.c:53
#define W(n)
Definition: sha256.c:47
const HashAlgo sha256HashAlgo
Definition: sha256.c:83
__weak_func void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest (no padding added)
Definition: sha256.c:275
__weak_func error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-256.
Definition: sha256.c:116
#define SIGMA1(x)
Definition: sha256.c:52
#define MAJ(x, y, z)
Definition: sha256.c:51
__weak_func void sha256Init(Sha256Context *context)
Initialize SHA-256 message digest context.
Definition: sha256.c:161
#define SIGMA4(x)
Definition: sha256.c:55
SHA-256 (Secure Hash Algorithm 256)
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
#define SHA256_BLOCK_SIZE
Definition: sha256.h:43
#define SHA256_MIN_PAD_SIZE
Definition: sha256.h:47
Common interface for hash algorithms.
Definition: crypto.h:1014
SHA-256 algorithm context.
Definition: sha256.h:62
uint8_t digest[32]
Definition: sha256.h:66
uint64_t totalSize
Definition: sha256.h:74
size_t size
Definition: sha256.h:73
uint8_t buffer[64]
Definition: sha256.h:71
uint32_t h[8]
Definition: sha256.h:65
uint32_t w[16]
Definition: sha256.h:70
uint8_t length
Definition: tcp.h:368