libxcks  0.1.0.1
sha384_512.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 "sha384_512.hpp"
28 //---------------------------------------------------------------------------
29 
31 using namespace std;
32 //---------------------------------------------------------------------------
33 
34 
35 namespace libxcks
36 {
37 // For doxygen
70 //---------------------------------------------------------------------------
71 
72 
73 //###########################################################################
74 // Implementation of AbstractSHA512Impl
75 //###########################################################################
76 
77 /*
78  * Process the remaining bytes in the internal buffer and the usual
79  * prolog according to the standard.
80  */
81 void AbstractSHA512Impl::finish()
82 {
83  uint64_t t, msb, lsb;
84  uint8_t *p;
85 
86  update(nullptr, 0); // flush
87 
88  t = nblocks;
89  // multiply by 128 to make a byte count
90  lsb = t << 7;
91  msb = t >> 57;
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 >> 61;
101 
102  if (count < 112)
103  { // enough room
104  ibuffer[count++] = 0x80; // pad
105  while (count < 112)
106  ibuffer[count++] = 0; // pad
107  }
108  else
109  { // need one extra block
110  ibuffer[count++] = 0x80; // pad character
111  while (count < 128)
112  ibuffer[count++] = 0;
113  update(nullptr, 0); // flush
114  memset(ibuffer, 0, 112); // fill next block with zeroes
115  }
116  /* append the 128 bit count */
117  ibuffer[112] = msb >> 56;
118  ibuffer[113] = msb >> 48;
119  ibuffer[114] = msb >> 40;
120  ibuffer[115] = msb >> 32;
121  ibuffer[116] = msb >> 24;
122  ibuffer[117] = msb >> 16;
123  ibuffer[118] = msb >> 8;
124  ibuffer[119] = msb;
125 
126  ibuffer[120] = lsb >> 56;
127  ibuffer[121] = lsb >> 48;
128  ibuffer[122] = lsb >> 40;
129  ibuffer[123] = lsb >> 32;
130  ibuffer[124] = lsb >> 24;
131  ibuffer[125] = lsb >> 16;
132  ibuffer[126] = lsb >> 8;
133  ibuffer[127] = lsb;
134  transform(ibuffer);
135  //_gcry_burn_stack (768);
136 
137  p = ibuffer;
138  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
139  #define X(a) do { *(uint64_t*)p = h##a ; p += 8; } while (0)
140  #else // little endian
141  #define X(a) do { *p++ = h##a >> 56; *p++ = h##a >> 48; \
142  *p++ = h##a >> 40; *p++ = h##a >> 32; \
143  *p++ = h##a >> 24; *p++ = h##a >> 16; \
144  *p++ = h##a >> 8; *p++ = h##a; } while (0)
145  #endif
146  X(0);
147  X(1);
148  X(2);
149  X(3);
150  X(4);
151  X(5);
152  // Note that these last two chunks are included even for SHA384.
153  // We just ignore them.
154  X(6);
155  X(7);
156  #undef X
157 }
158 //---------------------------------------------------------------------------
159 
160 
161 /*
162  * Updates the SHA512 hash with specified array of bytes.
163  */
164 void AbstractSHA512Impl::update(const uint8_t* buf, size_t len)
165 {
166  if (count == 128)
167  { // flush the buffer
168  transform(ibuffer);
169  //_gcry_burn_stack (768);
170  count = 0;
171  nblocks++;
172  }
173  if (buf == nullptr)
174  return;
175 
176  if (count != 0)
177  {
178  for (; len && count < 128; len--)
179  ibuffer[count++] = *buf++;
180  update(nullptr, 0);
181  if (len == 0)
182  return;
183  }
184 
185  while (len >= 128)
186  {
187  uint8_t tmpBuf[sizeof(uint64_t) * 16];
188  memcpy(tmpBuf, buf, sizeof(uint64_t) * 16);
189  transform(tmpBuf);
190  count = 0;
191  nblocks++;
192  len -= 128;
193  buf += 128;
194  }
195  //_gcry_burn_stack (768);
196  for (; len && count < 128; len--)
197  ibuffer[count++] = *buf++;
198 }
199 //---------------------------------------------------------------------------
200 
201 
202 /*
203  * Transform the message X which consists of 64 bytes.
204  */
205 void AbstractSHA512Impl::transform(uint8_t* data)
206 {
207  uint64_t a, b, c, d, e, f, g, h;
208  uint64_t w[80];
209  int t;
210  static const uint64_t k[] =
211  {
212  UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
213  UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
214  UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
215  UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
216  UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
217  UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
218  UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
219  UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
220  UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
221  UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
222  UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
223  UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
224  UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
225  UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
226  UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
227  UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
228  UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
229  UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
230  UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
231  UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
232  UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
233  UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
234  UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
235  UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
236  UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
237  UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
238  UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
239  UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
240  UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
241  UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
242  UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
243  UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
244  UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
245  UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
246  UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
247  UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
248  UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
249  UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
250  UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
251  UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
252  };
253 
254  // get values from the chaining vars
255  a = h0;
256  b = h1;
257  c = h2;
258  d = h3;
259  e = h4;
260  f = h5;
261  g = h6;
262  h = h7;
263 
264  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
265  memcpy(w, data, 128);
266  #else
267  {
268  int i;
269  uint8_t *p2;
270 
271  for (i = 0, p2 = (uint8_t*)w; i < 16; i++, p2 += 8)
272  {
273  p2[7] = *data++;
274  p2[6] = *data++;
275  p2[5] = *data++;
276  p2[4] = *data++;
277  p2[3] = *data++;
278  p2[2] = *data++;
279  p2[1] = *data++;
280  p2[0] = *data++;
281  }
282  }
283  #endif
284 
285  #define ROTR(x,n) (((x)>>(n)) | ((x)<<(64-(n))))
286  #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
287  #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
288  #define Sum0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
289  #define Sum1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
290  #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
291  #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
292 
293  for (t = 16; t < 80; t++)
294  w[t] = S1(w[t - 2]) + w[t - 7] + S0(w[t - 15]) + w[t - 16];
295 
296  for (t = 0; t < 80; t++)
297  {
298  uint64_t t1, t2;
299 
300  t1 = h + Sum1(e) + Ch(e, f, g) + k[t] + w[t];
301  t2 = Sum0(a) + Maj(a, b, c);
302  h = g;
303  g = f;
304  f = e;
305  e = d + t1;
306  d = c;
307  c = b;
308  b = a;
309  a = t1 + t2;
310  }
311 
312  // update chaining vars
313  h0 += a;
314  h1 += b;
315  h2 += c;
316  h3 += d;
317  h4 += e;
318  h5 += f;
319  h6 += g;
320  h7 += h;
321 }
322 //---------------------------------------------------------------------------
323 
324 
325 //###########################################################################
326 // Implementation of SHA384
327 //###########################################################################
328 
329 /*
330  * Default constructor.
331  */
332 SHA384::SHA384()
333 {
334  reset();
335 }
336 //---------------------------------------------------------------------------
337 
338 
339 /*
340  * Resets the SHA384 hash to initial value.
341  */
342 void SHA384::reset()
343 {
344  h0 = UINT64_C(0xcbbb9d5dc1059ed8);
345  h1 = UINT64_C(0x629a292a367cd507);
346  h2 = UINT64_C(0x9159015a3070dd17);
347  h3 = UINT64_C(0x152fecd8f70e5939);
348  h4 = UINT64_C(0x67332667ffc00b31);
349  h5 = UINT64_C(0x8eb44a8768581511);
350  h6 = UINT64_C(0xdb0c2e0d64f98fa7);
351  h7 = UINT64_C(0x47b5481dbefa4fa4);
352 
353  nblocks = UINT64_C(0);
354  count = 0;
355 }
356 //---------------------------------------------------------------------------
357 
358 
359 /*
360  * Returns the SHA384 hash value in the first 48 bytes of the given address.
361  */
362 uint8_t* SHA384::getValue(uint8_t* buffer) const
363 {
364  SHA384 sha384(*this);
365  sha384.finish();
366 
367  memcpy(buffer, sha384.ibuffer, getSize());
368 
369  return buffer;
370 }
371 //---------------------------------------------------------------------------
372 
373 
374 /*
375  * Returns the alternative names of the SHA384 hash algorithm.
376  */
377 ArrayString SHA384::getAlternativeNames()
378 {
379  return ArrayString{ "SHA384", "SHA-384" };
380 }
381 //---------------------------------------------------------------------------
382 
383 
384 
385 
386 //###########################################################################
387 // Implementation of SHA512
388 //###########################################################################
389 
390 /*
391  * Default constructor.
392  */
393 SHA512::SHA512()
394 {
395  reset();
396 }
397 //---------------------------------------------------------------------------
398 
399 
400 /*
401  * Resets the SHA512 hash to initial value.
402  */
403 void SHA512::reset()
404 {
405  h0 = UINT64_C(0x6a09e667f3bcc908);
406  h1 = UINT64_C(0xbb67ae8584caa73b);
407  h2 = UINT64_C(0x3c6ef372fe94f82b);
408  h3 = UINT64_C(0xa54ff53a5f1d36f1);
409  h4 = UINT64_C(0x510e527fade682d1);
410  h5 = UINT64_C(0x9b05688c2b3e6c1f);
411  h6 = UINT64_C(0x1f83d9abfb41bd6b);
412  h7 = UINT64_C(0x5be0cd19137e2179);
413 
414  nblocks = UINT64_C(0);
415  count = 0;
416 }
417 //---------------------------------------------------------------------------
418 
419 
420 /*
421  * Returns the SHA512 hash value in the first 64 bytes of the given address.
422  */
423 uint8_t* SHA512::getValue(uint8_t* buffer) const
424 {
425  SHA512 sha512(*this);
426  sha512.finish();
427 
428  memcpy(buffer, sha512.ibuffer, getSize());
429 
430  return buffer;
431 }
432 //---------------------------------------------------------------------------
433 
434 
435 /*
436  * Returns the alternative names of the SHA512 hash algorithm.
437  */
438 ArrayString SHA512::getAlternativeNames()
439 {
440  return ArrayString{ "SHA512", "SHA-512" };
441 }
442 //---------------------------------------------------------------------------
443 } // namespace libxcks
444 //---------------------------------------------------------------------------
void finish()
Process the remaining bytes in the internal buffer and the usual prolog according to the standard.
Definition: sha384_512.cpp:81
uint8_t ibuffer[128]
Input buffer.
Definition: sha384_512.hpp:59
Computes the SHA384 hash from a byte stream.
Definition: sha384_512.hpp:117
Computes the SHA512 hash from a byte stream.
Definition: sha384_512.hpp:252
#define Sum0(x)
Helper function for SHA512's computing.
#define Maj(x, y, z)
Helper function for SHA512's computing.
#define S0(x)
Helper function for SHA512's computing.
#define Sum1(x)
Helper function for SHA512's computing.
#define S1(x)
Helper function for SHA512's computing.
#define Ch(x, y, z)
Helper function for SHA512's computing.
#define X(a)
Helper function for SHA512's computing.
Compute sha384 hash and sha512 hash.
std::vector< std::string > ArrayString
Array of strings.
Definition: types.hpp:44