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-2019 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.6
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  cryptoMemcpy(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  paddingSize = 56 - context->size;
213  else
214  paddingSize = 64 + 56 - context->size;
215 
216  //Append padding
217  sha256Update(context, padding, paddingSize);
218 
219  //Append the length of the original message
220  context->w[14] = htobe32((uint32_t) (totalSize >> 32));
221  context->w[15] = htobe32((uint32_t) totalSize);
222 
223  //Calculate the message digest
224  sha256ProcessBlock(context);
225 
226  //Convert from host byte order to big-endian byte order
227  for(i = 0; i < 8; i++)
228  {
229  context->h[i] = htobe32(context->h[i]);
230  }
231 
232  //Copy the resulting digest
233  if(digest != NULL)
234  cryptoMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
235 }
236 
237 
238 /**
239  * @brief Finish the SHA-256 message digest (no padding is added)
240  * @param[in] context Pointer to the SHA-256 context
241  * @param[out] digest Calculated digest
242  **/
243 
244 void sha256FinalRaw(Sha256Context *context, uint8_t *digest)
245 {
246  uint_t i;
247 
248  //Convert from host byte order to big-endian byte order
249  for(i = 0; i < 8; i++)
250  {
251  context->h[i] = htobe32(context->h[i]);
252  }
253 
254  //Copy the resulting digest
255  cryptoMemcpy(digest, context->digest, SHA256_DIGEST_SIZE);
256 
257  //Convert from big-endian byte order to host byte order
258  for(i = 0; i < 8; i++)
259  {
260  context->h[i] = betoh32(context->h[i]);
261  }
262 }
263 
264 
265 /**
266  * @brief Process message in 16-word blocks
267  * @param[in] context Pointer to the SHA-256 context
268  **/
269 
271 {
272  uint_t t;
273  uint32_t temp1;
274  uint32_t temp2;
275 
276  //Initialize the 8 working registers
277  uint32_t a = context->h[0];
278  uint32_t b = context->h[1];
279  uint32_t c = context->h[2];
280  uint32_t d = context->h[3];
281  uint32_t e = context->h[4];
282  uint32_t f = context->h[5];
283  uint32_t g = context->h[6];
284  uint32_t h = context->h[7];
285 
286  //Process message in 16-word blocks
287  uint32_t *w = context->w;
288 
289  //Convert from big-endian byte order to host byte order
290  for(t = 0; t < 16; t++)
291  {
292  w[t] = betoh32(w[t]);
293  }
294 
295  //SHA-256 hash computation (alternate method)
296  for(t = 0; t < 64; t++)
297  {
298  //Prepare the message schedule
299  if(t >= 16)
300  W(t) += SIGMA4(W(t + 14)) + W(t + 9) + SIGMA3(W(t + 1));
301 
302  //Calculate T1 and T2
303  temp1 = h + SIGMA2(e) + CH(e, f, g) + k[t] + W(t);
304  temp2 = SIGMA1(a) + MAJ(a, b, c);
305 
306  //Update the working registers
307  h = g;
308  g = f;
309  f = e;
310  e = d + temp1;
311  d = c;
312  c = b;
313  b = a;
314  a = temp1 + temp2;
315  }
316 
317  //Update the hash value
318  context->h[0] += a;
319  context->h[1] += b;
320  context->h[2] += c;
321  context->h[3] += d;
322  context->h[4] += e;
323  context->h[5] += f;
324  context->h[6] += g;
325  context->h[7] += h;
326 }
327 
328 #endif
#define betoh32(value)
Definition: cpu_endian.h:430
uint8_t length
Definition: dtls_misc.h:149
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1094
#define SIGMA3(x)
Definition: sha256.c:54
uint8_t a
Definition: ndp.h:410
SHA-256 algorithm context.
Definition: sha256.h:58
uint8_t b[6]
Definition: dtls_misc.h:139
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
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define W(t)
Definition: sha256.c:47
#define SIGMA2(x)
Definition: sha256.c:53
uint16_t w[3]
Definition: ethernet.h:166
#define CH(x, y, z)
Definition: sha256.c:50
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1095
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
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:1096
#define htobe32(value)
Definition: cpu_endian.h:422
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 cryptoMemcpy(dest, src, length)
Definition: crypto.h:642
#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:270
Common interface for hash algorithms.
Definition: crypto.h:1128
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:244
unsigned int uint_t
Definition: compiler_port.h:45
uint8_t data[]
Definition: dtls_misc.h:176
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1093
#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:1097
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
#define SHA256_MIN_PAD_SIZE
Definition: sha256.h:42