[core] allow scilab to use more secure hash functions
[scilab.git] / scilab / modules / core / src / cpp / hash / sha256.cpp
1 // //////////////////////////////////////////////////////////
2 // sha256.cpp
3 // Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
4 // see http://create.stephan-brumme.com/disclaimer.html
5 //
6
7 #include "sha256.hxx"
8
9 /// same as reset()
10 SHA256::SHA256()
11 {
12   reset();
13 }
14
15
16 /// restart
17 void SHA256::reset()
18 {
19   m_numBytes   = 0;
20   m_bufferSize = 0;
21
22   // according to RFC 1321
23   m_hash[0] = 0x6a09e667;
24   m_hash[1] = 0xbb67ae85;
25   m_hash[2] = 0x3c6ef372;
26   m_hash[3] = 0xa54ff53a;
27   m_hash[4] = 0x510e527f;
28   m_hash[5] = 0x9b05688c;
29   m_hash[6] = 0x1f83d9ab;
30   m_hash[7] = 0x5be0cd19;
31 }
32
33
34 namespace
35 {
36   inline uint32_t rotate(uint32_t a, uint32_t c)
37   {
38     return (a >> c) | (a << (32 - c));
39   }
40
41   inline uint32_t swap(uint32_t x)
42   {
43 #if defined(__GNUC__) || defined(__clang__)
44     return __builtin_bswap32(x);
45 #endif
46 #ifdef MSC_VER
47     return _byteswap_ulong(x);
48 #endif
49
50     return (x >> 24) |
51           ((x >>  8) & 0x0000FF00) |
52           ((x <<  8) & 0x00FF0000) |
53            (x << 24);
54   }
55
56   // mix functions for processBlock()
57   inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
58   {
59     uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
60     uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
61     return term1 + term2;
62   }
63
64   inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
65   {
66     uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
67     uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
68     return term1 + term2;
69   }
70 }
71
72
73 /// process 64 bytes
74 void SHA256::processBlock(const void* data)
75 {
76   // get last hash
77   uint32_t a = m_hash[0];
78   uint32_t b = m_hash[1];
79   uint32_t c = m_hash[2];
80   uint32_t d = m_hash[3];
81   uint32_t e = m_hash[4];
82   uint32_t f = m_hash[5];
83   uint32_t g = m_hash[6];
84   uint32_t h = m_hash[7];
85
86   // data represented as 16x 32-bit words
87   const uint32_t* input = (uint32_t*) data;
88   // convert to big endian
89   uint32_t words[64];
90   int i;
91   for (i = 0; i < 16; i++)
92 #if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
93     words[i] =      input[i];
94 #else
95     words[i] = swap(input[i]);
96 #endif
97
98   uint32_t x,y; // temporaries
99
100   // first round
101   x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
102   x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
103   x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
104   x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
105   x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
106   x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
107   x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
108   x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
109
110   // secound round
111   x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
112   x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
113   x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
114   x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
115   x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
116   x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
117   x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
118   x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
119
120   // extend to 24 words
121   for (; i < 24; i++)
122     words[i] = words[i-16] +
123                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
124                words[i-7] +
125                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
126
127   // third round
128   x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
129   x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
130   x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
131   x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
132   x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
133   x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
134   x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
135   x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
136
137   // extend to 32 words
138   for (; i < 32; i++)
139     words[i] = words[i-16] +
140                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
141                words[i-7] +
142                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
143
144   // fourth round
145   x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
146   x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
147   x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
148   x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
149   x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
150   x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
151   x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
152   x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
153
154   // extend to 40 words
155   for (; i < 40; i++)
156     words[i] = words[i-16] +
157                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
158                words[i-7] +
159                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
160
161   // fifth round
162   x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
163   x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
164   x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
165   x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
166   x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
167   x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
168   x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
169   x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
170
171   // extend to 48 words
172   for (; i < 48; i++)
173     words[i] = words[i-16] +
174                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
175                words[i-7] +
176                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
177
178   // sixth round
179   x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
180   x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
181   x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
182   x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
183   x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
184   x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
185   x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
186   x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
187
188   // extend to 56 words
189   for (; i < 56; i++)
190     words[i] = words[i-16] +
191                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
192                words[i-7] +
193                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
194
195   // seventh round
196   x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
197   x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
198   x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
199   x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
200   x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
201   x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
202   x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
203   x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
204
205   // extend to 64 words
206   for (; i < 64; i++)
207     words[i] = words[i-16] +
208                (rotate(words[i-15],  7) ^ rotate(words[i-15], 18) ^ (words[i-15] >>  3)) +
209                words[i-7] +
210                (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
211
212   // eigth round
213   x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
214   x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
215   x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
216   x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
217   x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
218   x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
219   x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
220   x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
221
222   // update hash
223   m_hash[0] += a;
224   m_hash[1] += b;
225   m_hash[2] += c;
226   m_hash[3] += d;
227   m_hash[4] += e;
228   m_hash[5] += f;
229   m_hash[6] += g;
230   m_hash[7] += h;
231 }
232
233
234 /// add arbitrary number of bytes
235 void SHA256::add(const void* data, size_t numBytes)
236 {
237   const uint8_t* current = (const uint8_t*) data;
238
239   if (m_bufferSize > 0)
240   {
241     while (numBytes > 0 && m_bufferSize < BlockSize)
242     {
243       m_buffer[m_bufferSize++] = *current++;
244       numBytes--;
245     }
246   }
247
248   // full buffer
249   if (m_bufferSize == BlockSize)
250   {
251     processBlock(m_buffer);
252     m_numBytes  += BlockSize;
253     m_bufferSize = 0;
254   }
255
256   // no more data ?
257   if (numBytes == 0)
258     return;
259
260   // process full blocks
261   while (numBytes >= BlockSize)
262   {
263     processBlock(current);
264     current    += BlockSize;
265     m_numBytes += BlockSize;
266     numBytes   -= BlockSize;
267   }
268
269   // keep remaining bytes in buffer
270   while (numBytes > 0)
271   {
272     m_buffer[m_bufferSize++] = *current++;
273     numBytes--;
274   }
275 }
276
277
278 /// process final block, less than 64 bytes
279 void SHA256::processBuffer()
280 {
281   // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
282
283   // - append "1" bit to message
284   // - append "0" bits until message length in bit mod 512 is 448
285   // - append length as 64 bit integer
286
287   // number of bits
288   size_t paddedLength = m_bufferSize * 8;
289
290   // plus one bit set to 1 (always appended)
291   paddedLength++;
292
293   // number of bits must be (numBits % 512) = 448
294   size_t lower11Bits = paddedLength & 511;
295   if (lower11Bits <= 448)
296     paddedLength +=       448 - lower11Bits;
297   else
298     paddedLength += 512 + 448 - lower11Bits;
299   // convert from bits to bytes
300   paddedLength /= 8;
301
302   // only needed if additional data flows over into a second block
303   unsigned char extra[BlockSize];
304
305   // append a "1" bit, 128 => binary 10000000
306   if (m_bufferSize < BlockSize)
307     m_buffer[m_bufferSize] = 128;
308   else
309     extra[0] = 128;
310
311   size_t i;
312   for (i = m_bufferSize + 1; i < BlockSize; i++)
313     m_buffer[i] = 0;
314   for (; i < paddedLength; i++)
315     extra[i - BlockSize] = 0;
316
317   // add message length in bits as 64 bit number
318   uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
319   // find right position
320   unsigned char* addLength;
321   if (paddedLength < BlockSize)
322     addLength = m_buffer + paddedLength;
323   else
324     addLength = extra + paddedLength - BlockSize;
325
326   // must be big endian
327   *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
328   *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
329   *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
330   *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
331   *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
332   *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
333   *addLength++ = (unsigned char)((msgBits >>  8) & 0xFF);
334   *addLength   = (unsigned char)( msgBits        & 0xFF);
335
336   // process blocks
337   processBlock(m_buffer);
338   // flowed over into a second block ?
339   if (paddedLength > BlockSize)
340     processBlock(extra);
341 }
342
343
344 /// return latest hash as 64 hex characters
345 std::string SHA256::getHash()
346 {
347   // compute hash (as raw bytes)
348   unsigned char rawHash[HashBytes];
349   getHash(rawHash);
350
351   // convert to hex string
352   std::string result;
353   result.reserve(2 * HashBytes);
354   for (int i = 0; i < HashBytes; i++)
355   {
356     static const char dec2hex[16+1] = "0123456789abcdef";
357     result += dec2hex[(rawHash[i] >> 4) & 15];
358     result += dec2hex[ rawHash[i]       & 15];
359   }
360
361   return result;
362 }
363
364
365 /// return latest hash as bytes
366 void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
367 {
368   // save old hash if buffer is partially filled
369   uint32_t oldHash[HashValues];
370   for (int i = 0; i < HashValues; i++)
371     oldHash[i] = m_hash[i];
372
373   // process remaining bytes
374   processBuffer();
375
376   unsigned char* current = buffer;
377   for (int i = 0; i < HashValues; i++)
378   {
379     *current++ = (m_hash[i] >> 24) & 0xFF;
380     *current++ = (m_hash[i] >> 16) & 0xFF;
381     *current++ = (m_hash[i] >>  8) & 0xFF;
382     *current++ =  m_hash[i]        & 0xFF;
383
384     // restore old hash
385     m_hash[i] = oldHash[i];
386   }
387 }
388
389
390 /// compute SHA256 of a memory block
391 std::string SHA256::operator()(const void* data, size_t numBytes)
392 {
393   reset();
394   add(data, numBytes);
395   return getHash();
396 }
397
398
399 /// compute SHA256 of a string, excluding final zero
400 std::string SHA256::operator()(const std::string& text)
401 {
402   reset();
403   add(text.c_str(), text.size());
404   return getHash();
405 }