MPHELL  5.0.0
mphell-sha256.c
Go to the documentation of this file.
1 /*
2  MPHELL-5.0
3  Author(s): The MPHELL team
4 
5  (C) Copyright 2015-2021 - Institut Fourier / Univ. Grenoble Alpes (France)
6 
7  This file is part of the MPHELL Library.
8  MPHELL is free software: you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation, version 3 of the License.
11 
12  MPHELL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with MPHELL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
26 #include "mphell-sha256.h"
27 
28 static uint32_t sha1_init_state[64] = {
29  0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
30  0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
31  0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
32  0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
33  0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
34  0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
35  0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
36  0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
37 };
38 
45 void sha256_transform(sha256_state * s, unsigned char data[])
46 {
47  uint32_t a,b,c,d,e,f,g,h,i,j,t1,t2,m[64];
48 
49  for (i=0,j=0; i < 16; ++i, j += 4)
50  m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | (data[j+3]);
51  for ( ; i < 64; ++i)
52  m[i] = SIG1(m[i-2]) + m[i-7] + SIG0(m[i-15]) + m[i-16];
53 
54  a = s->state[0];
55  b = s->state[1];
56  c = s->state[2];
57  d = s->state[3];
58  e = s->state[4];
59  f = s->state[5];
60  g = s->state[6];
61  h = s->state[7];
62 
63  for (i = 0; i < 64; ++i) {
64  t1 = h + EP1(e) + CH(e,f,g) + sha1_init_state[i] + m[i];
65  t2 = EP0(a) + MAJ(a,b,c);
66  h = g;
67  g = f;
68  f = e;
69  e = d + t1;
70  d = c;
71  c = b;
72  b = a;
73  a = t1 + t2;
74  }
75 
76  s->state[0] += a;
77  s->state[1] += b;
78  s->state[2] += c;
79  s->state[3] += d;
80  s->state[4] += e;
81  s->state[5] += f;
82  s->state[6] += g;
83  s->state[7] += h;
84 }
85 
92 {
93  s->datalen = 0;
94  s->bitlen[0] = 0;
95  s->bitlen[1] = 0;
96  s->state[0] = 0x6a09e667;
97  s->state[1] = 0xbb67ae85;
98  s->state[2] = 0x3c6ef372;
99  s->state[3] = 0xa54ff53a;
100  s->state[4] = 0x510e527f;
101  s->state[5] = 0x9b05688c;
102  s->state[6] = 0x1f83d9ab;
103  s->state[7] = 0x5be0cd19;
104 }
105 
113 void sha256_write(sha256_state * s, const uint8_t * data, uint64_t len)
114 {
115  uint32_t i;
116 
117  for (i=0; i < len; ++i) {
118  s->data[s->datalen] = data[i];
119  s->datalen++;
120  if (s->datalen == 64) {
121  sha256_transform(s,s->data);
122  DBL_INT_ADD(s->bitlen[0],s->bitlen[1],512);
123  s->datalen = 0;
124  }
125  }
126 }
127 
134 void sha256_result(sha256_state * s, uint8_t * hash)
135 {
136  uint32_t i;
137 
138  i = s->datalen;
139 
140  /* Pad whatever data is left in the buffer. */
141  if (s->datalen < 56) {
142  s->data[i++] = 0x80;
143  while (i < 56)
144  s->data[i++] = 0x00;
145  }
146  else {
147  s->data[i++] = 0x80;
148  while (i < 64)
149  s->data[i++] = 0x00;
150  sha256_transform(s,s->data);
151  memset(s->data,0,56);
152  }
153 
154  /* Append to the padding the total message's length in bits and transform. */
155  DBL_INT_ADD(s->bitlen[0],s->bitlen[1],s->datalen * 8);
156  s->data[63] = s->bitlen[0];
157  s->data[62] = s->bitlen[0] >> 8;
158  s->data[61] = s->bitlen[0] >> 16;
159  s->data[60] = s->bitlen[0] >> 24;
160  s->data[59] = s->bitlen[1];
161  s->data[58] = s->bitlen[1] >> 8;
162  s->data[57] = s->bitlen[1] >> 16;
163  s->data[56] = s->bitlen[1] >> 24;
164  sha256_transform(s,s->data);
165 
166  /* Since this implementation uses little endian byte ordering and SHA uses big endian,
167  reverse all the bytes when copying the final state to the output hash. */
168  for (i=0; i < 4; ++i) {
169  hash[i] = (s->state[0] >> (24-i*8)) & 0x000000ff;
170  hash[i+4] = (s->state[1] >> (24-i*8)) & 0x000000ff;
171  hash[i+8] = (s->state[2] >> (24-i*8)) & 0x000000ff;
172  hash[i+12] = (s->state[3] >> (24-i*8)) & 0x000000ff;
173  hash[i+16] = (s->state[4] >> (24-i*8)) & 0x000000ff;
174  hash[i+20] = (s->state[5] >> (24-i*8)) & 0x000000ff;
175  hash[i+24] = (s->state[6] >> (24-i*8)) & 0x000000ff;
176  hash[i+28] = (s->state[7] >> (24-i*8)) & 0x000000ff;
177  }
178 }
179 
180 void sha256(uint8_t * hashvalue, const uint8_t * data, const uint64_t data_len)
181 {
182  unsigned char hash[32];
183 
184  sha256_state s;
185  sha256_init(&s);
186  sha256_write(&s, data, data_len/8);
187  sha256_result(&s,hash);
188  memcpy(hashvalue, hash, 32);
189 }
void sha256_transform(sha256_state *s, unsigned char data[])
Called each time 64 bytes are written, modify the state structure.
Definition: mphell-sha256.c:45
void sha256(uint8_t *hashvalue, const uint8_t *data, const uint64_t data_len)
Compute the Sha256 hash of "data".
void sha256_init(sha256_state *s)
Initialise a sha256_state structure.
Definition: mphell-sha256.c:91
void sha256_result(sha256_state *s, uint8_t *hash)
Add padding, and perform a last computation on the sha256 states.
void sha256_write(sha256_state *s, const uint8_t *data, uint64_t len)
Write user data (message) into the sha256 state structure.
Declaration of sha256 functions.
All the sha256 computations are done on this structure.
Definition: mphell-sha256.h:49
uint32_t bitlen[2]
Definition: mphell-sha256.h:52
uint32_t state[8]
Definition: mphell-sha256.h:53
unsigned char data[64]
Definition: mphell-sha256.h:50