]> git.cryptolib.org Git - arm-crypto-lib.git/blob - sha256/sha256.c
adding SHA-512
[arm-crypto-lib.git] / sha256 / sha256.c
1 /* sha256.c */
2 /*
3     This file is part of the ARM-Crypto-Lib.
4     Copyright (C) 2006-2010  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /**
20  * \file                sha256.c
21  * \author              Daniel Otte
22  * \date                16.05.2006
23  *
24  * \par License:
25  *      GPL
26  *
27  * \brief SHA-256 implementation.
28  *
29  *
30  */
31
32 #include <stdint.h>
33 #include <string.h> /* for memcpy, memmove, memset */
34 #include "sha256.h"
35
36 #define LITTLE_ENDIAN
37
38 #if defined LITTLE_ENDIAN
39 #elif defined BIG_ENDIAN
40 #else
41         #error specify endianess!!!
42 #endif
43
44
45 /*************************************************************************/
46
47 const
48 uint32_t sha256_init_vector[]={
49         0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
50     0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };
51
52
53 /*************************************************************************/
54
55 /**
56  * \brief \c sh256_init initialises a sha256 context for hashing.
57  * \c sh256_init c initialises the given sha256 context for hashing
58  * @param state pointer to a sha256 context
59  * @return none
60  */
61 void sha256_init(sha256_ctx_t *state){
62         state->length=0;
63         memcpy(state->h, sha256_init_vector, 8*4);
64 }
65
66 /*************************************************************************/
67
68 /**
69  * rotate x right by n positions
70  */
71 static
72 uint32_t rotr32( uint32_t x, uint8_t n){
73         return ((x>>n) | (x<<(32-n)));
74 }
75
76 static
77 uint32_t rotl32( uint32_t x, uint8_t n){
78         return ((x<<n) | (x>>(32-n)));
79 }
80
81 /*************************************************************************/
82
83 // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8))
84 static
85 uint32_t change_endian32(uint32_t x){
86         return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8));
87 }
88
89
90 /*************************************************************************/
91
92 /* sha256 functions as macros for speed and size, cause they are called only once */
93
94 #define CH(x,y,z)  (((x)&(y)) ^ ((~(x))&(z)))
95 #define MAJ(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
96
97 #define SIGMA0(x) (rotr32((x),2) ^ rotr32((x),13) ^ rotl32((x),10))
98 #define SIGMA1(x) (rotr32((x),6) ^ rotr32((x),11) ^ rotl32((x),7))
99 #define SIGMA_a(x) (rotr32((x),7)  ^ rotl32((x),14) ^ ((x)>>3))
100 #define SIGMA_b(x) (rotl32((x),15) ^ rotl32((x),13) ^ ((x)>>10))
101
102 const
103 uint32_t k[]={
104         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
105         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
106         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
107         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
108         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
109         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
110         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
111         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
112 };
113
114
115 /*************************************************************************/
116
117 /**
118  * block must be, 512, Bit = 64, Byte, long !!!
119  */
120 void sha256_nextBlock (sha256_ctx_t *state, const void* block){
121         uint32_t w[64]; /* this is 256, byte, large, */
122         uint8_t  i;
123         uint32_t a[8],t1,t2;
124
125         /* init w */
126 #if defined LITTLE_ENDIAN
127                 for (i=0; i<16; ++i){
128                         w[i]= change_endian32(((uint32_t*)block)[i]);
129                 }
130 #elif defined BIG_ENDIAN
131                 memcpy((void*)w, block, 64);
132 #endif
133                 for (i=16; i<64; ++i){
134                         w[i] = SIGMA_b(w[i-2]) + w[i-7] + SIGMA_a(w[i-15]) + w[i-16];
135                 }
136
137         /* init working variables */
138                 memcpy((void*)a,(void*)(state->h), 8*4);
139
140         /* do the, fun stuff, */
141                 for (i=0; i<64; ++i){
142                         t1 = a[7] + SIGMA1(a[4]) + CH(a[4],a[5],a[6]) + k[i] + w[i];
143                         t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]);
144                         memmove(&(a[1]), &(a[0]), 7*4);         /* a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; */
145                         a[4] += t1;
146                         a[0] = t1 + t2;
147                 }
148
149         /* update, the, state, */
150                 for (i=0; i<8; ++i){
151                         state->h[i] += a[i];
152                 }
153                 state->length += 512;
154 }
155
156
157 /*************************************************************************/
158
159 /**
160  * \brief function to process the last block being hashed
161  * @param state Pointer to the context in which this block should be processed.
162  * @param block Pointer to the message wich should be hashed.
163  * @param length is the length of only THIS block in BITS not in bytes!
164  *  bits are big endian, meaning high bits come first.
165  *      if you have a message with bits at the end, the byte must be padded with zeros
166  */
167 void sha256_lastBlock(sha256_ctx_t *state, const void* block, uint16_t length){
168         uint8_t lb[SHA256_BLOCK_BITS/8]; /* local block */
169         while(length>=SHA256_BLOCK_BITS){
170                 sha256_nextBlock(state, block);
171                 length -= SHA256_BLOCK_BITS;
172                 block = (uint8_t*)block+SHA256_BLOCK_BYTES;
173         }
174
175         state->length += length;
176         memcpy (&(lb[0]), block, length/8);
177
178         /* set the final one bit */
179         if (length & 0x7){ // if we have single bits at the end
180                 lb[length/8] = ((uint8_t*)(block))[length/8];
181         } else {
182                 lb[length/8] = 0;
183         }
184         lb[length/8] |= 0x80>>(length & 0x7);
185         length =(length >> 3) + 1; /* from now on length contains the number of BYTES in lb*/
186         /* pad with zeros */
187         if (length>64-8){ /* not enouth space for 64bit length value */
188                 memset((void*)(&(lb[length])), 0, 64-length);
189                 sha256_nextBlock(state, lb);
190                 state->length -= 512;
191                 length = 0;
192         }
193         memset((void*)(&(lb[length])), 0, 56-length);
194         /* store the 64bit length value */
195 #if defined LITTLE_ENDIAN
196                 /* this is now rolled up */
197         uint8_t i;
198         for (i=1; i<=8; ++i){
199                 lb[55+i] = (uint8_t)(state->length>>(64- 8*i));
200         }
201 #elif defined BIG_ENDIAN
202         *((uint64_t)&(lb[56])) = state->length;
203 #endif
204         sha256_nextBlock(state, lb);
205 }
206
207
208 /*************************************************************************/
209
210 /*
211  * length in bits!
212  */
213 void sha256(sha256_hash_t *dest, const void* msg, uint32_t length){ /* length could be choosen longer but this is for µC */
214         sha256_ctx_t s;
215         sha256_init(&s);
216         while(length >= SHA256_BLOCK_BITS){
217                 sha256_nextBlock(&s, msg);
218                 msg = (uint8_t*)msg + SHA256_BLOCK_BITS/8;
219                 length -= SHA256_BLOCK_BITS;
220         }
221         sha256_lastBlock(&s, msg, length);
222         sha256_ctx2hash(dest,&s);
223 }
224
225
226
227 /*************************************************************************/
228
229 void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state){
230 #if defined LITTLE_ENDIAN
231         uint8_t i;
232         for(i=0; i<8; ++i){
233                 ((uint32_t*)dest)[i] = change_endian32(state->h[i]);
234         }
235 #elif BIG_ENDIAN
236         if (dest != state->h)
237                 memcpy(dest, state->h, SHA256_HASH_BITS/8);
238 #else
239 # error unsupported endian type!
240 #endif
241 }
242
243