libxcks  0.1.0.1
sha224_256.cpp
Go to the documentation of this file.
1 /*
2  * libxcks
3  * Copyright (C) 2022 Julien Couot
4  *
5  * This program is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
24 //---------------------------------------------------------------------------
25 #include <cstring>
26 
27 #include "sha224_256.hpp"
28 //---------------------------------------------------------------------------
29 
31 using namespace std;
32 //---------------------------------------------------------------------------
33 
34 
35 namespace libxcks
36 {
37 // For doxygen
70 //---------------------------------------------------------------------------
71 
72 
73 //###########################################################################
74 // Implementation of AbstractSHA256Impl
75 //###########################################################################
76 
77 /*
78  * Process the remaining bytes in the internal buffer and the usual
79  * prolog according to the standard.
80  */
81 void AbstractSHA256Impl::finish()
82 {
83  uint32_t t, msb, lsb;
84  uint8_t *p;
85 
86  update(nullptr, 0); // flush
87 
88  t = nblocks;
89  // multiply by 64 to make a byte count
90  lsb = t << 6;
91  msb = t >> 26;
92  // add the count
93  t = lsb;
94  if ((lsb += count) < t)
95  msb++;
96  // multiply by 8 to make a bit count
97  t = lsb;
98  lsb <<= 3;
99  msb <<= 3;
100  msb |= t >> 29;
101 
102  if (count < 56)
103  { // enough room
104  ibuffer[count++] = 0x80; // pad
105  while (count < 56)
106  ibuffer[count++] = 0; // pad
107  }
108  else
109  { // need one extra block
110  ibuffer[count++] = 0x80; // pad character
111  while (count < 64)
112  ibuffer[count++] = 0;
113  update(nullptr, 0); // flush
114  memset(ibuffer, 0, 56); // fill next block with zeroes
115  }
116  // append the 64 bit count
117  ibuffer[56] = msb >> 24;
118  ibuffer[57] = msb >> 16;
119  ibuffer[58] = msb >> 8;
120  ibuffer[59] = msb;
121  ibuffer[60] = lsb >> 24;
122  ibuffer[61] = lsb >> 16;
123  ibuffer[62] = lsb >> 8;
124  ibuffer[63] = lsb;
125  transform(ibuffer);
126  //_gcry_burn_stack (74*4+32);
127 
128  p = ibuffer;
129  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
130  #define X(a) do { *(uint32_t*)p = h##a ; p += 4; } while(0)
131  #else // little endian
132  #define X(a) do { *p++ = h##a >> 24; *p++ = h##a >> 16; \
133  *p++ = h##a >> 8; *p++ = h##a; } while(0)
134  #endif
135  X(0);
136  X(1);
137  X(2);
138  X(3);
139  X(4);
140  X(5);
141  X(6);
142  X(7);
143  #undef X
144 }
145 //---------------------------------------------------------------------------
146 
147 
148 /*
149  * Updates the SHA256 hash with specified array of bytes.
150  */
151 void AbstractSHA256Impl::update(const uint8_t* buf, size_t len)
152 {
153  if (count == 64)
154  { // flush the buffer
155  transform(ibuffer);
156  // _gcry_burn_stack (74*4+32);
157  count = 0;
158  nblocks++;
159  }
160  if (buf == nullptr)
161  return;
162 
163  if (count != 0)
164  {
165  for (; len && count < 64; len--)
166  ibuffer[count++] = *buf++;
167  update(nullptr, 0);
168  if (len == 0)
169  return;
170  }
171 
172  while (len >= 64)
173  {
174  uint8_t tmpBuf[sizeof(uint32_t) * 16];
175  memcpy(tmpBuf, buf, sizeof(uint32_t) * 16);
176  transform(tmpBuf);
177  count = 0;
178  nblocks++;
179  len -= 64;
180  buf += 64;
181  }
182  // _gcry_burn_stack (74*4+32);
183  for (; len && count < 64; len--)
184  ibuffer[count++] = *buf++;
185 }
186 //---------------------------------------------------------------------------
187 
188 
189 #define Cho(x,y,z) (z ^ (x & (y ^ z))) /* (4.2) same as SHA-1's F1 */
190 #define Maj(x,y,z) ((x & y) | (z & (x|y))) /* (4.3) same as SHA-1's F3 */
191 #define Sum0(x) (ror ((x), 2) ^ ror ((x), 13) ^ ror ((x), 22)) /* (4.4) */
192 #define Sum1(x) (ror ((x), 6) ^ ror ((x), 11) ^ ror ((x), 25)) /* (4.5) */
193 #define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */
194 #define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */
195 #define R(a,b,c,d,e,f,g,h,k,w) do \
196  { \
197  t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \
198  t2 = Sum0((a)) + Maj((a),(b),(c)); \
199  h = g; \
200  g = f; \
201  f = e; \
202  e = d + t1; \
203  d = c; \
204  c = b; \
205  b = a; \
206  a = t1 + t2; \
207  } while (0)
208 /*
209  * Transform the message X which consists of 16 32-bit-words.
210  */
211 void AbstractSHA256Impl::transform(uint8_t* data)
212 {
213  static const uint32_t K[64] = {
214  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
215  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
216  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
217  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
218  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
219  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
220  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
221  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
222  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
223  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
224  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
225  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
226  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
227  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
228  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
229  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
230  };
231 
232  uint32_t a,b,c,d,e,f,g,h,t1,t2;
233  uint32_t x[16];
234  uint32_t w[64];
235  int i;
236 
237  a = h0;
238  b = h1;
239  c = h2;
240  d = h3;
241  e = h4;
242  f = h5;
243  g = h6;
244  h = h7;
245 
246  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
247  memcpy(x, data, 64);
248  #else
249  {
250  uint8_t *p2;
251 
252  for (i = 0, p2 = (uint8_t*)x; i < 16; i++, p2 += 4)
253  {
254  p2[3] = *data++;
255  p2[2] = *data++;
256  p2[1] = *data++;
257  p2[0] = *data++;
258  }
259  }
260  #endif
261 
262  for (i = 0; i < 16; i++)
263  w[i] = x[i];
264  for (; i < 64; i++)
265  w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16];
266 
267  for (i = 0; i < 64; i++)
268  R(a, b, c, d, e, f, g, h, K[i], w[i]);
269 
270  h0 += a;
271  h1 += b;
272  h2 += c;
273  h3 += d;
274  h4 += e;
275  h5 += f;
276  h6 += g;
277  h7 += h;
278 }
279 #undef Cho
280 #undef Maj
281 #undef Sum0
282 #undef Sum1
283 #undef S0
284 #undef S1
285 #undef R
286 //---------------------------------------------------------------------------
287 
288 
289 //###########################################################################
290 // Implementation of SHA224
291 //###########################################################################
292 
293 
294 /*
295  * Default constructor.
296  */
297 SHA224::SHA224()
298 {
299  reset();
300 }
301 //---------------------------------------------------------------------------
302 
303 
304 /*
305  * Resets the SHA224 hash to initial value.
306  */
307 void SHA224::reset()
308 {
309  h0 = 0xc1059ed8;
310  h1 = 0x367cd507;
311  h2 = 0x3070dd17;
312  h3 = 0xf70e5939;
313  h4 = 0xffc00b31;
314  h5 = 0x68581511;
315  h6 = 0x64f98fa7;
316  h7 = 0xbefa4fa4;
317  nblocks = 0;
318  count = 0;
319 }
320 //---------------------------------------------------------------------------
321 
322 
323 /*
324  * Returns the SHA224 hash value in the first 28 bytes of the given address.
325  */
326 uint8_t* SHA224::getValue(uint8_t* buffer) const
327 {
328  SHA224 sha224(*this);
329  sha224.finish();
330 
331  memcpy(buffer, sha224.ibuffer, getSize());
332 
333  return buffer;
334 }
335 //---------------------------------------------------------------------------
336 
337 
338 /*
339  * Returns the alternative names of the SHA224 hash algorithm.
340  */
341 ArrayString SHA224::getAlternativeNames()
342 {
343  return ArrayString{ "SHA224", "SHA-224" };
344 }
345 //---------------------------------------------------------------------------
346 
347 
348 //###########################################################################
349 // Implementation of SHA256
350 //###########################################################################
351 
352 
353 /*
354  * Default constructor.
355  */
356 SHA256::SHA256()
357 {
358  reset();
359 }
360 //---------------------------------------------------------------------------
361 
362 
363 /*
364  * Resets the SHA256 hash to initial value.
365  */
366 void SHA256::reset()
367 {
368  h0 = 0x6a09e667;
369  h1 = 0xbb67ae85;
370  h2 = 0x3c6ef372;
371  h3 = 0xa54ff53a;
372  h4 = 0x510e527f;
373  h5 = 0x9b05688c;
374  h6 = 0x1f83d9ab;
375  h7 = 0x5be0cd19;
376  nblocks = 0;
377  count = 0;
378 }
379 //---------------------------------------------------------------------------
380 
381 
382 /*
383  * Returns the SHA256 hash value in the first 32 bytes of the given address.
384  */
385 uint8_t* SHA256::getValue(uint8_t* buffer) const
386 {
387  SHA256 sha256(*this);
388  sha256.finish();
389 
390  memcpy(buffer, sha256.ibuffer, getSize());
391 
392  return buffer;
393 }
394 //---------------------------------------------------------------------------
395 
396 
397 /*
398  * Returns the alternative names of the SHA256 hash algorithm.
399  */
400 ArrayString SHA256::getAlternativeNames()
401 {
402  return ArrayString{ "SHA256", "SHA-256" };
403 }
404 //---------------------------------------------------------------------------
405 } // namespace libxcks
406 //---------------------------------------------------------------------------
void finish()
Process the remaining bytes in the internal buffer and the usual prolog according to the standard.
Definition: sha224_256.cpp:81
uint8_t ibuffer[64]
Input buffer.
Definition: sha224_256.hpp:59
Computes the SHA224 hash from a byte stream.
Definition: sha224_256.hpp:117
Computes the SHA256 hash from a byte stream.
Definition: sha224_256.hpp:252
#define S0(x)
Helper function for SHA256's computing.
Definition: sha224_256.cpp:193
#define S1(x)
Helper function for SHA256's computing.
Definition: sha224_256.cpp:194
#define R(a, b, c, d, e, f, g, h, k, w)
Helper function for SHA256's computing.
Definition: sha224_256.cpp:195
#define X(a)
Helper function for SHA256's computing.
Compute sha224 hash and sha256 hash.
std::vector< std::string > ArrayString
Array of strings.
Definition: types.hpp:44