]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/sha.c
Update CyaSSL to latest version.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / sha.c
1 /* sha.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
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26
27 #include <cyassl/ctaocrypt/settings.h>
28
29 #if !defined(NO_SHA)
30
31 #ifdef CYASSL_PIC32MZ_HASH
32 #define InitSha   InitSha_sw
33 #define ShaUpdate ShaUpdate_sw
34 #define ShaFinal  ShaFinal_sw
35 #endif
36
37 #ifdef HAVE_FIPS
38     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
39     #define FIPS_NO_WRAPPERS
40 #endif
41
42 #include <cyassl/ctaocrypt/sha.h>
43 #include <cyassl/ctaocrypt/logging.h>
44 #include <cyassl/ctaocrypt/error-crypt.h>
45
46 #ifdef NO_INLINE
47     #include <cyassl/ctaocrypt/misc.h>
48 #else
49     #include <ctaocrypt/src/misc.c>
50 #endif
51
52 #ifdef FREESCALE_MMCAU
53     #include "cau_api.h"
54     #define XTRANSFORM(S,B)  cau_sha1_hash_n((B), 1, ((S))->digest)
55 #else
56     #define XTRANSFORM(S,B)  Transform((S))
57 #endif
58
59
60 #ifdef STM32F2_HASH
61     /*
62      * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral
63      * library. Documentation located in STM32F2xx Standard Peripheral Library
64      * document (See note in README).
65      */
66     #include "stm32f2xx.h"
67     #include "stm32f2xx_hash.h"
68
69     int InitSha(Sha* sha)
70     {
71         /* STM32F2 struct notes:
72          * sha->buffer  = first 4 bytes used to hold partial block if needed 
73          * sha->buffLen = num bytes currently stored in sha->buffer
74          * sha->loLen   = num bytes that have been written to STM32 FIFO
75          */
76         XMEMSET(sha->buffer, 0, SHA_REG_SIZE);
77         sha->buffLen = 0;
78         sha->loLen = 0;
79
80         /* initialize HASH peripheral */
81         HASH_DeInit();
82
83         /* configure algo used, algo mode, datatype */
84         HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE);
85         HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH 
86                  | HASH_DataType_8b);
87
88         /* reset HASH processor */
89         HASH->CR |= HASH_CR_INIT;
90
91         return 0;
92     }
93
94     int ShaUpdate(Sha* sha, const byte* data, word32 len)
95     {
96         word32 i = 0;
97         word32 fill = 0;
98         word32 diff = 0;
99
100         /* if saved partial block is available */
101         if (sha->buffLen) {
102             fill = 4 - sha->buffLen;
103
104             /* if enough data to fill, fill and push to FIFO */
105             if (fill <= len) {
106                 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill);
107                 HASH_DataIn(*(uint32_t*)sha->buffer);
108
109                 data += fill;
110                 len -= fill;
111                 sha->loLen += 4;
112                 sha->buffLen = 0;
113             } else {
114                 /* append partial to existing stored block */
115                 XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len);
116                 sha->buffLen += len;
117                 return;
118             }
119         }
120        
121         /* write input block in the IN FIFO */
122         for(i = 0; i < len; i += 4)
123         {
124             diff = len - i;
125             if ( diff < 4) {
126                 /* store incomplete last block, not yet in FIFO */
127                 XMEMSET(sha->buffer, 0, SHA_REG_SIZE);
128                 XMEMCPY((byte*)sha->buffer, data, diff);
129                 sha->buffLen = diff;
130             } else {
131                 HASH_DataIn(*(uint32_t*)data);
132                 data+=4;
133             }
134         }
135
136         /* keep track of total data length thus far */ 
137         sha->loLen += (len - sha->buffLen);
138
139         return 0;
140     }
141
142     int ShaFinal(Sha* sha, byte* hash)
143     {
144         __IO uint16_t nbvalidbitsdata = 0;
145         
146         /* finish reading any trailing bytes into FIFO */
147         if (sha->buffLen) {
148             HASH_DataIn(*(uint32_t*)sha->buffer);
149             sha->loLen += sha->buffLen;
150         }
151
152         /* calculate number of valid bits in last word of input data */
153         nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE);
154
155         /* configure number of valid bits in last word of the data */
156         HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
157
158         /* start HASH processor */
159         HASH_StartDigest();
160
161         /* wait until Busy flag == RESET */
162         while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {}
163
164         /* read message digest */
165         sha->digest[0] = HASH->HR[0];
166         sha->digest[1] = HASH->HR[1];
167         sha->digest[2] = HASH->HR[2];
168         sha->digest[3] = HASH->HR[3];
169         sha->digest[4] = HASH->HR[4];
170         
171         ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE);
172
173         XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE);
174
175         return InitSha(sha);  /* reset state */
176     }
177
178 #else /* CTaoCrypt software implementation */
179
180 #ifndef min
181
182     static INLINE word32 min(word32 a, word32 b)
183     {
184         return a > b ? b : a;
185     }
186
187 #endif /* min */
188
189
190 int InitSha(Sha* sha)
191 {
192     #ifdef FREESCALE_MMCAU
193         cau_sha1_initialize_output(sha->digest);
194     #else
195         sha->digest[0] = 0x67452301L;
196         sha->digest[1] = 0xEFCDAB89L;
197         sha->digest[2] = 0x98BADCFEL;
198         sha->digest[3] = 0x10325476L;
199         sha->digest[4] = 0xC3D2E1F0L;
200     #endif
201
202     sha->buffLen = 0;
203     sha->loLen   = 0;
204     sha->hiLen   = 0;
205
206     return 0;
207 }
208
209 #ifndef FREESCALE_MMCAU
210
211 #define blk0(i) (W[i] = sha->buffer[i])
212 #define blk1(i) (W[i&15] = \
213                    rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
214
215 #define f1(x,y,z) (z^(x &(y^z)))
216 #define f2(x,y,z) (x^y^z)
217 #define f3(x,y,z) ((x&y)|(z&(x|y)))
218 #define f4(x,y,z) (x^y^z)
219
220 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
221 #define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \
222                         rotlFixed(v,5); w = rotlFixed(w,30);
223 #define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \
224                         rotlFixed(v,5); w = rotlFixed(w,30);
225 #define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \
226                         rotlFixed(v,5); w = rotlFixed(w,30);
227 #define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \
228                         rotlFixed(v,5); w = rotlFixed(w,30);
229 #define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \
230                         rotlFixed(v,5); w = rotlFixed(w,30);
231
232
233 static void Transform(Sha* sha)
234 {
235     word32 W[SHA_BLOCK_SIZE / sizeof(word32)];
236
237     /* Copy context->state[] to working vars */ 
238     word32 a = sha->digest[0];
239     word32 b = sha->digest[1];
240     word32 c = sha->digest[2];
241     word32 d = sha->digest[3];
242     word32 e = sha->digest[4];
243
244 #ifdef USE_SLOW_SHA
245     word32 t, i;
246
247     for (i = 0; i < 16; i++) {
248         R0(a, b, c, d, e, i);
249         t = e; e = d; d = c; c = b; b = a; a = t;
250     }
251
252     for (; i < 20; i++) {
253         R1(a, b, c, d, e, i);
254         t = e; e = d; d = c; c = b; b = a; a = t;
255     }
256
257     for (; i < 40; i++) {
258         R2(a, b, c, d, e, i);
259         t = e; e = d; d = c; c = b; b = a; a = t;
260     }
261
262     for (; i < 60; i++) {
263         R3(a, b, c, d, e, i);
264         t = e; e = d; d = c; c = b; b = a; a = t;
265     }
266
267     for (; i < 80; i++) {
268         R4(a, b, c, d, e, i);
269         t = e; e = d; d = c; c = b; b = a; a = t;
270     }
271 #else
272     /* nearly 1 K bigger in code size but 25% faster  */
273     /* 4 rounds of 20 operations each. Loop unrolled. */
274     R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
275     R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
276     R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
277     R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
278
279     R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
280
281     R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
282     R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
283     R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
284     R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
285     R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
286
287     R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
288     R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
289     R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
290     R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
291     R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
292
293     R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
294     R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
295     R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
296     R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
297     R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
298 #endif
299
300     /* Add the working vars back into digest state[] */
301     sha->digest[0] += a;
302     sha->digest[1] += b;
303     sha->digest[2] += c;
304     sha->digest[3] += d;
305     sha->digest[4] += e;
306 }
307
308 #endif /* FREESCALE_MMCAU */
309
310
311 static INLINE void AddLength(Sha* sha, word32 len)
312 {
313     word32 tmp = sha->loLen;
314     if ( (sha->loLen += len) < tmp)
315         sha->hiLen++;                       /* carry low to high */
316 }
317
318
319 int ShaUpdate(Sha* sha, const byte* data, word32 len)
320 {
321     /* do block size increments */
322     byte* local = (byte*)sha->buffer;
323
324     while (len) {
325         word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen);
326         XMEMCPY(&local[sha->buffLen], data, add);
327
328         sha->buffLen += add;
329         data         += add;
330         len          -= add;
331
332         if (sha->buffLen == SHA_BLOCK_SIZE) {
333             #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
334                 ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE);
335             #endif
336             XTRANSFORM(sha, local);
337             AddLength(sha, SHA_BLOCK_SIZE);
338             sha->buffLen = 0;
339         }
340     }
341
342     return 0;
343 }
344
345
346 int ShaFinal(Sha* sha, byte* hash)
347 {
348     byte* local = (byte*)sha->buffer;
349
350     AddLength(sha, sha->buffLen);  /* before adding pads */
351
352     local[sha->buffLen++] = 0x80;  /* add 1 */
353
354     /* pad with zeros */
355     if (sha->buffLen > SHA_PAD_SIZE) {
356         XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen);
357         sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen;
358
359         #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
360             ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE);
361         #endif
362         XTRANSFORM(sha, local);
363         sha->buffLen = 0;
364     }
365     XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen);
366    
367     /* put lengths in bits */
368     sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + 
369                  (sha->hiLen << 3);
370     sha->loLen = sha->loLen << 3;
371
372     /* store lengths */
373     #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU)
374         ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE);
375     #endif
376     /* ! length ordering dependent on digest endian type ! */
377     XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32));
378     XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32));
379
380     #ifdef FREESCALE_MMCAU
381         /* Kinetis requires only these bytes reversed */
382         ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)],
383                          &sha->buffer[SHA_PAD_SIZE/sizeof(word32)],
384                          2 * sizeof(word32));
385     #endif
386
387     XTRANSFORM(sha, local);
388     #ifdef LITTLE_ENDIAN_ORDER
389         ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE);
390     #endif
391     XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE);
392
393     return InitSha(sha);  /* reset state */
394 }
395
396 #endif /* STM32F2_HASH */
397
398
399 int ShaHash(const byte* data, word32 len, byte* hash)
400 {
401     int ret = 0;
402 #ifdef CYASSL_SMALL_STACK
403     Sha* sha;
404 #else
405     Sha sha[1];
406 #endif
407
408 #ifdef CYASSL_SMALL_STACK
409     sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
410     if (sha == NULL)
411         return MEMORY_E;
412 #endif
413
414     if ((ret = InitSha(sha)) != 0) {
415         CYASSL_MSG("InitSha failed");
416     }
417     else {
418         ShaUpdate(sha, data, len);
419         ShaFinal(sha, hash);
420     }
421
422 #ifdef CYASSL_SMALL_STACK
423     XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
424 #endif
425
426     return ret;
427 }
428
429 #endif /* NO_SHA */