libxcks  0.1.0.1
sha1.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 "sha1.hpp"
28 //---------------------------------------------------------------------------
29 
31 using namespace std;
32 //---------------------------------------------------------------------------
33 
34 
35 namespace libxcks
36 {
37 // For doxygen
82 //---------------------------------------------------------------------------
83 
84 
85 /*
86  * Default constructor.
87  */
88 SHA1::SHA1()
89 {
90  reset();
91 }
92 //---------------------------------------------------------------------------
93 
94 
95 /*
96  * Resets the SHA1 hash to initial value.
97  */
98 void SHA1::reset()
99 {
100  h0 = 0x67452301;
101  h1 = 0xefcdab89;
102  h2 = 0x98badcfe;
103  h3 = 0x10325476;
104  h4 = 0xc3d2e1f0;
105  nblocks = 0;
106  count = 0;
107 }
108 //---------------------------------------------------------------------------
109 
110 
111 /*
112  * Process the remaining bytes in the internal buffer and the usual
113  * prolog according to the standard.
114  */
115 void SHA1::finish()
116 {
117  uint32_t t, msb, lsb;
118  uint8_t *p;
119 
120  update(nullptr, 0); // flush
121 
122  t = nblocks;
123  // multiply by 64 to make a byte count
124  lsb = t << 6;
125  msb = t >> 26;
126  // add the count
127  t = lsb;
128  if ((lsb += count) < t)
129  msb++;
130  // multiply by 8 to make a bit count
131  t = lsb;
132  lsb <<= 3;
133  msb <<= 3;
134  msb |= t >> 29;
135 
136  if (count < 56) // enough room
137  {
138  ibuffer[count++] = 0x80; // pad
139  while (count < 56)
140  ibuffer[count++] = 0; // pad
141  }
142  else // need one extra block
143  {
144  ibuffer[count++] = 0x80; // pad character
145  while (count < 64)
146  ibuffer[count++] = 0;
147  update(nullptr, 0); // flush
148  memset(ibuffer, 0, 56); // fill next block with zeroes
149  }
150  /* append the 64 bit count */
151  ibuffer[56] = msb >> 24;
152  ibuffer[57] = msb >> 16;
153  ibuffer[58] = msb >> 8;
154  ibuffer[59] = msb;
155  ibuffer[60] = lsb >> 24;
156  ibuffer[61] = lsb >> 16;
157  ibuffer[62] = lsb >> 8;
158  ibuffer[63] = lsb;
159  transform(ibuffer);
160  //_gcry_burn_stack (88+4*sizeof(void*));
161 
162  p = ibuffer;
163  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
164  #define X(a) do { *(uint32_t*)p = h##a ; p += 4; } while(0)
165  #else /* little endian */
166  #define X(a) do { *p++ = h##a >> 24; *p++ = h##a >> 16; \
167  *p++ = h##a >> 8; *p++ = h##a; } while(0)
168  #endif
169  X(0);
170  X(1);
171  X(2);
172  X(3);
173  X(4);
174  #undef X
175 }
176 //---------------------------------------------------------------------------
177 
178 
179 /*
180  * Updates the SHA1 hash with specified array of bytes.
181  */
182 void SHA1::update(const uint8_t* buf, size_t len)
183 {
184  if (count == 64) // flush the buffer
185  {
186  transform(ibuffer);
187  // _gcry_burn_stack (88+4*sizeof(void*));
188  count = 0;
189  nblocks++;
190  }
191  if (buf == nullptr)
192  return;
193 
194  if (count != 0)
195  {
196  for (; len && count < 64; len--)
197  ibuffer[count++] = *buf++;
198  update(nullptr, 0);
199  if (len == 0)
200  return;
201  }
202 
203  while (len >= 64)
204  {
205  uint8_t tmpBuf[sizeof(uint32_t) * 16];
206  memcpy(tmpBuf, buf, sizeof(uint32_t) * 16);
207  transform(tmpBuf);
208  count = 0;
209  nblocks++;
210  len -= 64;
211  buf += 64;
212  }
213  //_gcry_burn_stack (88+4*sizeof(void*));
214  for(; len && count < 64; len--)
215  ibuffer[count++] = *buf++;
216 }
217 //---------------------------------------------------------------------------
218 
219 
220 /*
221  * Transform the message X which consists of 16 32-bit-words.
222  */
223 void SHA1::transform(uint8_t* data)
224 {
225  uint32_t a, b, c, d, e, tm;
226  uint32_t x[16];
227 
228  /* Get values from the chaining vars. */
229  a = h0;
230  b = h1;
231  c = h2;
232  d = h3;
233  e = h4;
234 
235  #if (LIBXCKS_BYTE_ORDER == LIBXCKS_BIG_ENDIAN)
236  memcpy(x, data, 64);
237  #else
238  {
239  int i;
240  uint8_t *p2;
241  for (i = 0, p2 = (uint8_t*)x; i < 16; i++, p2 += 4)
242  {
243  p2[3] = *data++;
244  p2[2] = *data++;
245  p2[1] = *data++;
246  p2[0] = *data++;
247  }
248  }
249  #endif
250 
251  #define K1 0x5A827999L
252  #define K2 0x6ED9EBA1L
253  #define K3 0x8F1BBCDCL
254  #define K4 0xCA62C1D6L
255  #define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) )
256  #define F2(x,y,z) ( x ^ y ^ z )
257  #define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) )
258  #define F4(x,y,z) ( x ^ y ^ z )
259 
260  #define M(i) ( tm = x[i & 0x0f] ^ x[(i - 14) & 0x0f] \
261  ^ x[(i - 8) & 0x0f] ^ x[(i - 3) & 0x0f] \
262  , (x[i & 0x0f] = rol(tm, 1)) )
263 
264  #define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \
265  + f(b, c, d) \
266  + k \
267  + m; \
268  b = rol( b, 30 ); \
269  } while(0)
270 
271  R(a, b, c, d, e, F1, K1, x[ 0]);
272  R(e, a, b, c, d, F1, K1, x[ 1]);
273  R(d, e, a, b, c, F1, K1, x[ 2]);
274  R(c, d, e, a, b, F1, K1, x[ 3]);
275  R(b, c, d, e, a, F1, K1, x[ 4]);
276  R(a, b, c, d, e, F1, K1, x[ 5]);
277  R(e, a, b, c, d, F1, K1, x[ 6]);
278  R(d, e, a, b, c, F1, K1, x[ 7]);
279  R(c, d, e, a, b, F1, K1, x[ 8]);
280  R(b, c, d, e, a, F1, K1, x[ 9]);
281  R(a, b, c, d, e, F1, K1, x[10]);
282  R(e, a, b, c, d, F1, K1, x[11]);
283  R(d, e, a, b, c, F1, K1, x[12]);
284  R(c, d, e, a, b, F1, K1, x[13]);
285  R(b, c, d, e, a, F1, K1, x[14]);
286  R(a, b, c, d, e, F1, K1, x[15]);
287  R(e, a, b, c, d, F1, K1, M(16));
288  R(d, e, a, b, c, F1, K1, M(17));
289  R(c, d, e, a, b, F1, K1, M(18));
290  R(b, c, d, e, a, F1, K1, M(19));
291  R(a, b, c, d, e, F2, K2, M(20));
292  R(e, a, b, c, d, F2, K2, M(21));
293  R(d, e, a, b, c, F2, K2, M(22));
294  R(c, d, e, a, b, F2, K2, M(23));
295  R(b, c, d, e, a, F2, K2, M(24));
296  R(a, b, c, d, e, F2, K2, M(25));
297  R(e, a, b, c, d, F2, K2, M(26));
298  R(d, e, a, b, c, F2, K2, M(27));
299  R(c, d, e, a, b, F2, K2, M(28));
300  R(b, c, d, e, a, F2, K2, M(29));
301  R(a, b, c, d, e, F2, K2, M(30));
302  R(e, a, b, c, d, F2, K2, M(31));
303  R(d, e, a, b, c, F2, K2, M(32));
304  R(c, d, e, a, b, F2, K2, M(33));
305  R(b, c, d, e, a, F2, K2, M(34));
306  R(a, b, c, d, e, F2, K2, M(35));
307  R(e, a, b, c, d, F2, K2, M(36));
308  R(d, e, a, b, c, F2, K2, M(37));
309  R(c, d, e, a, b, F2, K2, M(38));
310  R(b, c, d, e, a, F2, K2, M(39));
311  R(a, b, c, d, e, F3, K3, M(40));
312  R(e, a, b, c, d, F3, K3, M(41));
313  R(d, e, a, b, c, F3, K3, M(42));
314  R(c, d, e, a, b, F3, K3, M(43));
315  R(b, c, d, e, a, F3, K3, M(44));
316  R(a, b, c, d, e, F3, K3, M(45));
317  R(e, a, b, c, d, F3, K3, M(46));
318  R(d, e, a, b, c, F3, K3, M(47));
319  R(c, d, e, a, b, F3, K3, M(48));
320  R(b, c, d, e, a, F3, K3, M(49));
321  R(a, b, c, d, e, F3, K3, M(50));
322  R(e, a, b, c, d, F3, K3, M(51));
323  R(d, e, a, b, c, F3, K3, M(52));
324  R(c, d, e, a, b, F3, K3, M(53));
325  R(b, c, d, e, a, F3, K3, M(54));
326  R(a, b, c, d, e, F3, K3, M(55));
327  R(e, a, b, c, d, F3, K3, M(56));
328  R(d, e, a, b, c, F3, K3, M(57));
329  R(c, d, e, a, b, F3, K3, M(58));
330  R(b, c, d, e, a, F3, K3, M(59));
331  R(a, b, c, d, e, F4, K4, M(60));
332  R(e, a, b, c, d, F4, K4, M(61));
333  R(d, e, a, b, c, F4, K4, M(62));
334  R(c, d, e, a, b, F4, K4, M(63));
335  R(b, c, d, e, a, F4, K4, M(64));
336  R(a, b, c, d, e, F4, K4, M(65));
337  R(e, a, b, c, d, F4, K4, M(66));
338  R(d, e, a, b, c, F4, K4, M(67));
339  R(c, d, e, a, b, F4, K4, M(68));
340  R(b, c, d, e, a, F4, K4, M(69));
341  R(a, b, c, d, e, F4, K4, M(70));
342  R(e, a, b, c, d, F4, K4, M(71));
343  R(d, e, a, b, c, F4, K4, M(72));
344  R(c, d, e, a, b, F4, K4, M(73));
345  R(b, c, d, e, a, F4, K4, M(74));
346  R(a, b, c, d, e, F4, K4, M(75));
347  R(e, a, b, c, d, F4, K4, M(76));
348  R(d, e, a, b, c, F4, K4, M(77));
349  R(c, d, e, a, b, F4, K4, M(78));
350  R(b, c, d, e, a, F4, K4, M(79));
351 
352  // Update chaining vars.
353  h0 += a;
354  h1 += b;
355  h2 += c;
356  h3 += d;
357  h4 += e;
358 }
359 //---------------------------------------------------------------------------
360 
361 
362 /*
363  * Returns the SHA1 hash value in the first 20 bytes of the given address.
364  */
365 uint8_t* SHA1::getValue(uint8_t* buffer) const
366 {
367  SHA1 sha1(*this);
368  sha1.finish();
369 
370  memcpy(buffer, sha1.ibuffer, getSize());
371 
372  return buffer;
373 }
374 //---------------------------------------------------------------------------
375 
376 
377 /*
378  * Returns the alternative names of the SHA1 hash algorithm.
379  */
380 ArrayString SHA1::getAlternativeNames()
381 {
382  return ArrayString{ "SHA1", "SHA160", "SHA-160" };
383 }
384 //---------------------------------------------------------------------------
385 } // namespace libxcks
386 //---------------------------------------------------------------------------
Computes the SHA1 (or SHA160) hash from a byte stream.
Definition: sha1.hpp:57
uint8_t ibuffer[64]
Input buffer.
Definition: sha1.hpp:68
void finish()
Process the remaining bytes in the internal buffer and the usual prolog according to the standard.
Definition: sha1.cpp:115
#define F1(x, y, z)
Helper value for SHA1's computing.
#define R(a, b, c, d, e, f, k, m)
Helper value for SHA1's computing.
#define F4(x, y, z)
Helper value for SHA1's computing.
#define M(i)
Helper value for SHA1's computing.
#define F3(x, y, z)
Helper value for SHA1's computing.
#define K3
Helper value for SHA1's computing.
#define K1
Helper value for SHA1's computing.
#define K4
Helper value for SHA1's computing.
#define K2
Helper value for SHA1's computing.
#define X(a)
Helper value for SHA1's computing.
#define F2(x, y, z)
Helper value for SHA1's computing.
Compute sha1 hash.
std::vector< std::string > ArrayString
Array of strings.
Definition: types.hpp:44