]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/sha512.c
40086949b54fac12136e098f6633002b2b5c77e6
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / sha512.c
1 /* sha512.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * CyaSSL 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 General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/settings.h>
27
28 #ifdef CYASSL_SHA512
29
30 #ifdef HAVE_FIPS
31     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
32     #define FIPS_NO_WRAPPERS
33 #endif
34
35 #include <cyassl/ctaocrypt/sha512.h>
36 #include <cyassl/ctaocrypt/logging.h>
37 #include <cyassl/ctaocrypt/error-crypt.h>
38
39 #ifdef NO_INLINE
40     #include <cyassl/ctaocrypt/misc.h>
41 #else
42     #include <ctaocrypt/src/misc.c>
43 #endif
44
45
46 #ifndef min
47
48     static INLINE word32 min(word32 a, word32 b)
49     {
50         return a > b ? b : a;
51     }
52
53 #endif /* min */
54
55
56 int InitSha512(Sha512* sha512)
57 {
58     sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
59     sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
60     sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
61     sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
62     sha512->digest[4] = W64LIT(0x510e527fade682d1);
63     sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
64     sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
65     sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
66
67     sha512->buffLen = 0;
68     sha512->loLen   = 0;
69     sha512->hiLen   = 0;
70
71     return 0;
72 }
73
74
75 static const word64 K512[80] = {
76         W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
77         W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
78         W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
79         W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
80         W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
81         W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
82         W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
83         W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
84         W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
85         W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
86         W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
87         W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
88         W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
89         W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
90         W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
91         W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
92         W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
93         W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
94         W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
95         W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
96         W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
97         W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
98         W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
99         W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
100         W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
101         W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
102         W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
103         W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
104         W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
105         W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
106         W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
107         W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
108         W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
109         W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
110         W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
111         W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
112         W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
113         W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
114         W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
115         W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
116 };
117
118
119 #define blk0(i) (W[i] = sha512->buffer[i])
120 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
121
122 #define Ch(x,y,z) (z^(x&(y^z)))
123 #define Maj(x,y,z) ((x&y)|(z&(x|y)))
124
125 #define a(i) T[(0-i)&7]
126 #define b(i) T[(1-i)&7]
127 #define c(i) T[(2-i)&7]
128 #define d(i) T[(3-i)&7]
129 #define e(i) T[(4-i)&7]
130 #define f(i) T[(5-i)&7]
131 #define g(i) T[(6-i)&7]
132 #define h(i) T[(7-i)&7]
133
134 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39))
135 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41))
136 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7))
137 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6))
138
139 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\
140         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
141
142 #define blk384(i) (W[i] = sha384->buffer[i])
143
144 #define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\
145         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
146
147
148 static int Transform(Sha512* sha512)
149 {
150     const word64* K = K512;
151
152     word32 j;
153     word64 T[8];
154
155 #ifdef CYASSL_SMALL_STACK
156     word64* W;
157
158     W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
159     if (W == NULL)
160         return MEMORY_E;
161 #else
162     word64 W[16];
163 #endif
164
165     /* Copy digest to working vars */
166     XMEMCPY(T, sha512->digest, sizeof(T));
167
168 #ifdef USE_SLOW_SHA2
169     /* over twice as small, but 50% slower */
170     /* 80 operations, not unrolled */
171     for (j = 0; j < 80; j += 16) {
172         int m; 
173         for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
174             R(m);
175         }
176     }
177 #else
178     /* 80 operations, partially loop unrolled */
179     for (j = 0; j < 80; j += 16) {
180         R( 0); R( 1); R( 2); R( 3);
181         R( 4); R( 5); R( 6); R( 7);
182         R( 8); R( 9); R(10); R(11);
183         R(12); R(13); R(14); R(15);
184     }
185 #endif /* USE_SLOW_SHA2 */
186
187     /* Add the working vars back into digest */
188
189     sha512->digest[0] += a(0);
190     sha512->digest[1] += b(0);
191     sha512->digest[2] += c(0);
192     sha512->digest[3] += d(0);
193     sha512->digest[4] += e(0);
194     sha512->digest[5] += f(0);
195     sha512->digest[6] += g(0);
196     sha512->digest[7] += h(0);
197
198     /* Wipe variables */
199     XMEMSET(W, 0, sizeof(word64) * 16);
200     XMEMSET(T, 0, sizeof(T));
201
202 #ifdef CYASSL_SMALL_STACK
203     XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
204 #endif
205
206     return 0;
207 }
208
209
210 static INLINE void AddLength(Sha512* sha512, word32 len)
211 {
212     word32 tmp = sha512->loLen;
213     if ( (sha512->loLen += len) < tmp)
214         sha512->hiLen++;                       /* carry low to high */
215 }
216
217
218 int Sha512Update(Sha512* sha512, const byte* data, word32 len)
219 {
220     /* do block size increments */
221     byte* local = (byte*)sha512->buffer;
222
223     while (len) {
224         word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen);
225         XMEMCPY(&local[sha512->buffLen], data, add);
226
227         sha512->buffLen += add;
228         data         += add;
229         len          -= add;
230
231         if (sha512->buffLen == SHA512_BLOCK_SIZE) {
232             int ret;
233
234             #ifdef LITTLE_ENDIAN_ORDER
235                 ByteReverseWords64(sha512->buffer, sha512->buffer,
236                                    SHA512_BLOCK_SIZE);
237             #endif
238             ret = Transform(sha512);
239             if (ret != 0)
240                 return ret;
241
242             AddLength(sha512, SHA512_BLOCK_SIZE);
243             sha512->buffLen = 0;
244         }
245     }
246     return 0;
247 }
248
249
250 int Sha512Final(Sha512* sha512, byte* hash)
251 {
252     byte* local = (byte*)sha512->buffer;
253     int ret;
254
255     AddLength(sha512, sha512->buffLen);               /* before adding pads */
256
257     local[sha512->buffLen++] = 0x80;  /* add 1 */
258
259     /* pad with zeros */
260     if (sha512->buffLen > SHA512_PAD_SIZE) {
261         XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen);
262         sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen;
263
264         #ifdef LITTLE_ENDIAN_ORDER
265             ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE);
266         #endif
267         ret = Transform(sha512);
268         if (ret != 0)
269             return ret;
270
271         sha512->buffLen = 0;
272     }
273     XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen);
274    
275     /* put lengths in bits */
276     sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + 
277                  (sha512->hiLen << 3);
278     sha512->loLen = sha512->loLen << 3;
279
280     /* store lengths */
281     #ifdef LITTLE_ENDIAN_ORDER
282         ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE);
283     #endif
284     /* ! length ordering dependent on digest endian type ! */
285     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
286     sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
287
288     ret = Transform(sha512);
289     if (ret != 0)
290         return ret;
291
292     #ifdef LITTLE_ENDIAN_ORDER
293         ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE);
294     #endif
295     XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE);
296
297     return InitSha512(sha512);  /* reset state */
298 }
299
300
301 int Sha512Hash(const byte* data, word32 len, byte* hash)
302 {
303     int ret = 0;
304 #ifdef CYASSL_SMALL_STACK
305     Sha512* sha512;
306 #else
307     Sha512 sha512[1];
308 #endif
309
310 #ifdef CYASSL_SMALL_STACK
311     sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER);
312     if (sha512 == NULL)
313         return MEMORY_E;
314 #endif
315     
316     if ((ret = InitSha512(sha512)) != 0) {
317         CYASSL_MSG("InitSha512 failed");
318     }
319     else if ((ret = Sha512Update(sha512, data, len)) != 0) {
320         CYASSL_MSG("Sha512Update failed");
321     }
322     else if ((ret = Sha512Final(sha512, hash)) != 0) {
323         CYASSL_MSG("Sha512Final failed");
324     }
325     
326 #ifdef CYASSL_SMALL_STACK
327     XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
328 #endif
329     
330     return ret;
331 }
332
333
334 #ifdef CYASSL_SHA384
335
336 int InitSha384(Sha384* sha384)
337 {
338     sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
339     sha384->digest[1] = W64LIT(0x629a292a367cd507);
340     sha384->digest[2] = W64LIT(0x9159015a3070dd17);
341     sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
342     sha384->digest[4] = W64LIT(0x67332667ffc00b31);
343     sha384->digest[5] = W64LIT(0x8eb44a8768581511);
344     sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
345     sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
346
347     sha384->buffLen = 0;
348     sha384->loLen   = 0;
349     sha384->hiLen   = 0;
350
351     return 0;
352 }
353
354
355 static int Transform384(Sha384* sha384)
356 {
357     const word64* K = K512;
358
359     word32 j;
360     word64 T[8];
361
362 #ifdef CYASSL_SMALL_STACK
363     word64* W;
364
365     W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
366     if (W == NULL)
367         return MEMORY_E;
368 #else
369     word64 W[16];
370 #endif
371
372     /* Copy digest to working vars */
373     XMEMCPY(T, sha384->digest, sizeof(T));
374
375 #ifdef USE_SLOW_SHA2
376     /* over twice as small, but 50% slower */
377     /* 80 operations, not unrolled */
378     for (j = 0; j < 80; j += 16) {
379         int m;
380         for (m = 0; m < 16; m++) {  /* braces needed for macros {} */
381             R2(m);
382         }
383     }
384 #else
385     /* 80 operations, partially loop unrolled */
386     for (j = 0; j < 80; j += 16) {
387         R2( 0); R2( 1); R2( 2); R2( 3);
388         R2( 4); R2( 5); R2( 6); R2( 7);
389         R2( 8); R2( 9); R2(10); R2(11);
390         R2(12); R2(13); R2(14); R2(15);
391     }
392 #endif /* USE_SLOW_SHA2 */
393
394     /* Add the working vars back into digest */
395
396     sha384->digest[0] += a(0);
397     sha384->digest[1] += b(0);
398     sha384->digest[2] += c(0);
399     sha384->digest[3] += d(0);
400     sha384->digest[4] += e(0);
401     sha384->digest[5] += f(0);
402     sha384->digest[6] += g(0);
403     sha384->digest[7] += h(0);
404
405     /* Wipe variables */
406     XMEMSET(W, 0, sizeof(word64) * 16);
407     XMEMSET(T, 0, sizeof(T));
408
409 #ifdef CYASSL_SMALL_STACK
410     XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
411 #endif
412
413     return 0;
414 }
415
416
417 static INLINE void AddLength384(Sha384* sha384, word32 len)
418 {
419     word32 tmp = sha384->loLen;
420     if ( (sha384->loLen += len) < tmp)
421         sha384->hiLen++;                       /* carry low to high */
422 }
423
424
425 int Sha384Update(Sha384* sha384, const byte* data, word32 len)
426 {
427     /* do block size increments */
428     byte* local = (byte*)sha384->buffer;
429
430     while (len) {
431         word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen);
432         XMEMCPY(&local[sha384->buffLen], data, add);
433
434         sha384->buffLen += add;
435         data         += add;
436         len          -= add;
437
438         if (sha384->buffLen == SHA384_BLOCK_SIZE) {
439             int ret;
440
441             #ifdef LITTLE_ENDIAN_ORDER
442                 ByteReverseWords64(sha384->buffer, sha384->buffer,
443                                    SHA384_BLOCK_SIZE);
444             #endif
445             ret = Transform384(sha384);
446             if (ret != 0)
447                 return ret;
448
449             AddLength384(sha384, SHA384_BLOCK_SIZE);
450             sha384->buffLen = 0;
451         }
452     }
453     return 0;
454 }
455
456
457 int Sha384Final(Sha384* sha384, byte* hash)
458 {
459     byte* local = (byte*)sha384->buffer;
460     int ret;
461
462     AddLength384(sha384, sha384->buffLen);              /* before adding pads */
463
464     local[sha384->buffLen++] = 0x80;  /* add 1 */
465
466     /* pad with zeros */
467     if (sha384->buffLen > SHA384_PAD_SIZE) {
468         XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen);
469         sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen;
470
471         #ifdef LITTLE_ENDIAN_ORDER
472             ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE);
473         #endif
474         ret = Transform384(sha384);
475         if (ret !=  0)
476             return ret;
477
478         sha384->buffLen = 0;
479     }
480     XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen);
481    
482     /* put lengths in bits */
483     sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + 
484                  (sha384->hiLen << 3);
485     sha384->loLen = sha384->loLen << 3;
486
487     /* store lengths */
488     #ifdef LITTLE_ENDIAN_ORDER
489         ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE);
490     #endif
491     /* ! length ordering dependent on digest endian type ! */
492     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen;
493     sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen;
494
495     ret = Transform384(sha384);
496     if (ret != 0)
497         return ret;
498
499     #ifdef LITTLE_ENDIAN_ORDER
500         ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE);
501     #endif
502     XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE);
503
504     return InitSha384(sha384);  /* reset state */
505 }
506
507
508 int Sha384Hash(const byte* data, word32 len, byte* hash)
509 {
510     int ret = 0;
511 #ifdef CYASSL_SMALL_STACK
512     Sha384* sha384;
513 #else
514     Sha384 sha384[1];
515 #endif
516
517 #ifdef CYASSL_SMALL_STACK
518     sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER);
519     if (sha384 == NULL)
520         return MEMORY_E;
521 #endif
522
523     if ((ret = InitSha384(sha384)) != 0) {
524         CYASSL_MSG("InitSha384 failed");
525     }
526     else if ((ret = Sha384Update(sha384, data, len)) != 0) {
527         CYASSL_MSG("Sha384Update failed");
528     }
529     else if ((ret = Sha384Final(sha384, hash)) != 0) {
530         CYASSL_MSG("Sha384Final failed");
531     }
532
533 #ifdef CYASSL_SMALL_STACK
534     XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
535 #endif
536
537     return ret;
538 }
539
540 #endif /* CYASSL_SHA384 */
541
542 #endif /* CYASSL_SHA512 */