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-2020 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 1.9.8
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(t) w[(t) & 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 sha256Oid[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01};
81 
82 //Common interface for hash algorithms
84 {
85  "SHA-256",
86  sha256Oid,
87  sizeof(sha256Oid),
88  sizeof(Sha256Context),
92  TRUE,
98 };
99 
100 
101 /**
102  * @brief Digest a message using SHA-256
103  * @param[in] data Pointer to the message being hashed
104  * @param[in] length Length of the message
105  * @param[out] digest Pointer to the calculated digest
106  * @return Error code
107  **/
108 
109 error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
110 {
111  //Allocate a memory buffer to hold the SHA-256 context
112  Sha256Context *context = cryptoAllocMem(sizeof(Sha256Context));
113  //Failed to allocate memory?
114  if(context == NULL)
115  return ERROR_OUT_OF_MEMORY;
116 
117  //Initialize the SHA-256 context
118  sha256Init(context);
119  //Digest the message
120  sha256Update(context, data, length);
121  //Finalize the SHA-256 message digest
122  sha256Final(context, digest);
123 
124  //Free previously allocated memory
125  cryptoFreeMem(context);
126  //Successful processing
127  return NO_ERROR;
128 }
129 
130 
131 /**
132  * @brief Initialize SHA-256 message digest context
133  * @param[in] context Pointer to the SHA-256 context to initialize
134  **/
135 
136 void sha256Init(Sha256Context *context)
137 {
138  //Set initial hash value
139  context->h[0] = 0x6A09E667;
140  context->h[1] = 0xBB67AE85;
141  context->h[2] = 0x3C6EF372;
142  context->h[3] = 0xA54FF53A;
143  context->h[4] = 0x510E527F;
144  context->h[5] = 0x9B05688C;
145  context->h[6] = 0x1F83D9AB;
146  context->h[7] = 0x5BE0CD19;
147 
148  //Number of bytes in the buffer
149  context->size = 0;
150  //Total length of the message
151  context->totalSize = 0;
152 }
153 
154 
155 /**
156  * @brief Update the SHA-256 context with a portion of the message being hashed
157  * @param[in] context Pointer to the SHA-256 context
158  * @param[in] data Pointer to the buffer being hashed
159  * @param[in] length Length of the buffer
160  **/
161 
162 void sha256Update(Sha256Context *context, const void *data, size_t length)
163 {
164  size_t n;
165 
166  //Process the incoming data
167  while(length > 0)
168  {
169  //The buffer can hold at most 64 bytes
170  n = MIN(length, 64 - context->size);
171 
172  //Copy the data to the buffer
173  osMemcpy(context->buffer + context->size, data, n);
174 
175  //Update the SHA-256 context
176  context->size += n;
177  context->totalSize += n;
178  //Advance the data pointer
179  data = (uint8_t *) data + n;
180  //Remaining bytes to process
181  length -= n;
182 
183  //Process message in 16-word blocks
184  if(context->size == 64)
185  {
186  //Transform the 16-word block
187  sha256ProcessBlock(context);
188  //Empty the buffer
189  context->size = 0;
190  }
191  }
192 }
193 
194 
195 /**
196  * @brief Finish the SHA-256 message digest
197  * @param[in] context Pointer to the SHA-256 context
198  * @param[out] digest Calculated digest (optional parameter)
199  **/
200 
201 void sha256Final(Sha256Context *context, uint8_t *digest)
202 {
203  uint_t i;
204  size_t paddingSize;
205  uint64_t totalSize;
206 
207  //Length of the original message (before padding)
208  totalSize = context->totalSize * 8;
209 
210  //Pad the message so that its length is congruent to 56 modulo 64
211  if(context->size < 56)
212  {
213  paddingSize = 56 - context->size;
214  }
215  else
216  {
217  paddingSize = 64 + 56 - context->size;
218  }
219 
220  //Append padding
221  sha256Update(context, padding, paddingSize);
222 
223  //Append the length of the original message
224  context->w[14] = htobe32((uint32_t) (totalSize >> 32));
225  context->w[15] = htobe32((uint32_t) totalSize);
226 
227  //Calculate the message digest
228  sha256ProcessBlock(context);
229 
230  //Convert from host byte order to big-endian byte order
231  for(i = 0; i < 8; i++)
232  {
233  context->h[i] = htobe32(context->h[i]);
234  }
235 
236  //Copy the resulting digest
237  if(digest != NULL)
238  osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
239 }
240 
241 
242 /**
243  * @brief Finish the SHA-256 message digest (no padding is added)
244  * @param[in] context Pointer to the SHA-256 context
245  * @param[out] digest Calculated digest
246  **/
247 
248 void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
249 {
250  uint_t i;
251 
252  //Convert from host byte order to big-endian byte order
253  for(i = 0; i < 8; i++)
254  {
255  context->h[i] = htobe32(context->h[i]);
256  }
257 
258  //Copy the resulting digest
259  osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
260 
261  //Convert from big-endian byte order to host byte order
262  for(i = 0; i < 8; i++)
263  {
264  context->h[i] = betoh32(context->h[i]);
265  }
266 }
267 
268 
269 /**
270  * @brief Process message in 16-word blocks
271  * @param[in] context Pointer to the SHA-256 context
272  **/
273 
275 {
276  uint_t t;
277  uint32_t temp1;
278  uint32_t temp2;
279 
280  //Initialize the 8 working registers
281  uint32_t a = context->h[0];
282  uint32_t b = context->h[1];
283  uint32_t c = context->h[2];
284  uint32_t d = context->h[3];
285  uint32_t e = context->h[4];
286  uint32_t f = context->h[5];
287  uint32_t g = context->h[6];
288  uint32_t h = context->h[7];
289 
290  //Process message in 16-word blocks
291  uint32_t *w = context->w;
292 
293  //Convert from big-endian byte order to host byte order
294  for(t = 0; t < 16; t++)
295  {
296  w[t] = betoh32(w[t]);
297  }
298 
299  //SHA-256 hash computation (alternate method)
300  for(t = 0; t < 64; t++)
301  {
302  //Prepare the message schedule
303  if(t >= 16)
304  W(t) += SIGMA4(W(t + 14)) + W(t + 9) + SIGMA3(W(t + 1));
305 
306  //Calculate T1 and T2
307  temp1 = h + SIGMA2(e) + CH(e, f, g) + k[t] + W(t);
308  temp2 = SIGMA1(a) + MAJ(a, b, c);
309 
310  //Update the working registers
311  h = g;
312  g = f;
313  f = e;
314  e = d + temp1;
315  d = c;
316  c = b;
317  b = a;
318  a = temp1 + temp2;
319  }
320 
321  //Update the hash value
322  context->h[0] += a;
323  context->h[1] += b;
324  context->h[2] += c;
325  context->h[3] += d;
326  context->h[4] += e;
327  context->h[5] += f;
328  context->h[6] += g;
329  context->h[7] += h;
330 }
331 
332 #endif
uint8_t length
Definition: coap_common.h:190
#define betoh32(value)
Definition: cpu_endian.h:454
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1028
#define SIGMA3(x)
Definition: sha256.c:54
uint8_t a
Definition: ndp.h:410
uint8_t data[]
Definition: ethernet.h:209
SHA-256 algorithm context.
Definition: sha256.h:58
void sha256Final(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest.
Definition: sha256.c:201
#define TRUE
Definition: os_port.h:50
#define SIGMA4(x)
Definition: sha256.c:55
size_t size
Definition: sha256.h:70
uint32_t h[8]
Definition: sha256.h:62
#define W(t)
Definition: sha256.c:47
#define SIGMA2(x)
Definition: sha256.c:53
uint16_t w[3]
Definition: ethernet.h:180
#define CH(x, y, z)
Definition: sha256.c:50
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1029
uint8_t t
Definition: llmnr_common.h:81
#define SHA256_BLOCK_SIZE
Definition: sha256.h:38
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:162
uint8_t h
Definition: ndp.h:300
#define osMemcpy(dest, src, length)
Definition: os_port.h:134
error_t
Error codes.
Definition: error.h:42
uint32_t w[16]
Definition: sha256.h:67
const HashAlgo sha256HashAlgo
Definition: sha256.c:83
#define MAJ(x, y, z)
Definition: sha256.c:51
General definitions for cryptographic algorithms.
uint8_t buffer[64]
Definition: sha256.h:68
#define MIN(a, b)
Definition: os_port.h:62
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:1030
#define htobe32(value)
Definition: cpu_endian.h:446
uint8_t b[6]
Definition: ethernet.h:179
void sha256Init(Sha256Context *context)
Initialize SHA-256 message digest context.
Definition: sha256.c:136
uint8_t digest[32]
Definition: sha256.h:63
SHA-256 (Secure Hash Algorithm 256)
error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-256.
Definition: sha256.c:109
uint8_t n
#define cryptoFreeMem(p)
Definition: crypto.h:630
uint32_t totalSize
const uint8_t sha256Oid[9]
Definition: sha256.c:80
#define cryptoAllocMem(size)
Definition: crypto.h:625
void sha256ProcessBlock(Sha256Context *context)
Process message in 16-word blocks.
Definition: sha256.c:274
Common interface for hash algorithms.
Definition: crypto.h:1062
uint64_t totalSize
Definition: sha256.h:71
void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
Finish the SHA-256 message digest (no padding is added)
Definition: sha256.c:248
unsigned int uint_t
Definition: compiler_port.h:45
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1027
#define SIGMA1(x)
Definition: sha256.c:52
#define SHA256_DIGEST_SIZE
Definition: sha256.h:40
void(* HashAlgoFinalRaw)(void *context, uint8_t *digest)
Definition: crypto.h:1031
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
#define SHA256_MIN_PAD_SIZE
Definition: sha256.h:42