]> git.cryptolib.org Git - arm-crypto-lib.git/blob - sha256/sha256.c
adding PRF TLSv1.2
[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
77 /*************************************************************************/
78
79 // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8))
80 static
81 uint32_t change_endian32(uint32_t x){
82         return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8));
83 }
84
85
86 /*************************************************************************/
87
88 /* sha256 functions as macros for speed and size, cause they are called only once */
89
90 #define CH(x,y,z)  (((x)&(y)) ^ ((~(x))&(z)))
91 #define MAJ(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
92
93 #define SIGMA0(x) (rotr32((x),2) ^ rotr32((x),13) ^ rotr32((x),22))
94 #define SIGMA1(x) (rotr32((x),6) ^ rotr32((x),11) ^ rotr32((x),25))
95 #define SIGMA_a(x) (rotr32((x),7)  ^ rotr32((x),18) ^ ((x)>>3))
96 #define SIGMA_b(x) (rotr32((x),17) ^ rotr32((x),19) ^ ((x)>>10))
97
98 const
99 uint32_t k[]={
100         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
101         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
102         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
103         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
104         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
105         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
106         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
107         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
108 };
109
110
111 /*************************************************************************/
112
113 /**
114  * block must be, 512, Bit = 64, Byte, long !!!
115  */
116 void sha256_nextBlock (sha256_ctx_t *state, const void* block){
117         uint32_t w[64]; /* this is 256, byte, large, */
118         uint8_t  i;
119         uint32_t a[8],t1,t2;
120
121         /* init w */
122 #if defined LITTLE_ENDIAN
123                 for (i=0; i<16; ++i){
124                         w[i]= change_endian32(((uint32_t*)block)[i]);
125                 }
126 #elif defined BIG_ENDIAN
127                 memcpy((void*)w, block, 64);
128 #endif
129                 for (i=16; i<64; ++i){
130                         w[i] = SIGMA_b(w[i-2]) + w[i-7] + SIGMA_a(w[i-15]) + w[i-16];
131                 }
132
133         /* init working variables */
134                 memcpy((void*)a,(void*)(state->h), 8*4);
135
136         /* do the, fun stuff, */
137                 for (i=0; i<64; ++i){
138                         t1 = a[7] + SIGMA1(a[4]) + CH(a[4],a[5],a[6]) + k[i] + w[i];
139                         t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]);
140                         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]; */
141                         a[4] += t1;
142                         a[0] = t1 + t2;
143                 }
144
145         /* update, the, state, */
146                 for (i=0; i<8; ++i){
147                         state->h[i] += a[i];
148                 }
149                 state->length += 512;
150 }
151
152
153 /*************************************************************************/
154
155 /**
156  * \brief function to process the last block being hashed
157  * @param state Pointer to the context in which this block should be processed.
158  * @param block Pointer to the message wich should be hashed.
159  * @param length is the length of only THIS block in BITS not in bytes!
160  *  bits are big endian, meaning high bits come first.
161  *      if you have a message with bits at the end, the byte must be padded with zeros
162  */
163 void sha256_lastBlock(sha256_ctx_t *state, const void* block, uint16_t length){
164         uint8_t lb[SHA256_BLOCK_BITS/8]; /* local block */
165         while(length>=SHA256_BLOCK_BITS){
166                 sha256_nextBlock(state, block);
167                 length -= SHA256_BLOCK_BITS;
168                 block = (uint8_t*)block+SHA256_BLOCK_BYTES;
169         }
170
171         state->length += length;
172         memcpy (&(lb[0]), block, length/8);
173
174         /* set the final one bit */
175         if (length & 0x7){ // if we have single bits at the end
176                 lb[length/8] = ((uint8_t*)(block))[length/8];
177         } else {
178                 lb[length/8] = 0;
179         }
180         lb[length/8] |= 0x80>>(length & 0x7);
181         length =(length >> 3) + 1; /* from now on length contains the number of BYTES in lb*/
182         /* pad with zeros */
183         if (length>64-8){ /* not enouth space for 64bit length value */
184                 memset((void*)(&(lb[length])), 0, 64-length);
185                 sha256_nextBlock(state, lb);
186                 state->length -= 512;
187                 length = 0;
188         }
189         memset((void*)(&(lb[length])), 0, 56-length);
190         /* store the 64bit length value */
191 #if defined LITTLE_ENDIAN
192                 /* this is now rolled up */
193         uint8_t i;
194         for (i=1; i<=8; ++i){
195                 lb[55+i] = (uint8_t)(state->length>>(64- 8*i));
196         }
197 #elif defined BIG_ENDIAN
198         *((uint64_t)&(lb[56])) = state->length;
199 #endif
200         sha256_nextBlock(state, lb);
201 }
202
203
204 /*************************************************************************/
205
206 /*
207  * length in bits!
208  */
209 void sha256(sha256_hash_t *dest, const void* msg, uint32_t length){ /* length could be choosen longer but this is for µC */
210         sha256_ctx_t s;
211         sha256_init(&s);
212         while(length >= SHA256_BLOCK_BITS){
213                 sha256_nextBlock(&s, msg);
214                 msg = (uint8_t*)msg + SHA256_BLOCK_BITS/8;
215                 length -= SHA256_BLOCK_BITS;
216         }
217         sha256_lastBlock(&s, msg, length);
218         sha256_ctx2hash(dest,&s);
219 }
220
221
222
223 /*************************************************************************/
224
225 void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state){
226 #if defined LITTLE_ENDIAN
227         uint8_t i;
228         for(i=0; i<8; ++i){
229                 ((uint32_t*)dest)[i] = change_endian32(state->h[i]);
230         }
231 #elif BIG_ENDIAN
232         if (dest != state->h)
233                 memcpy(dest, state->h, SHA256_HASH_BITS/8);
234 #else
235 # error unsupported endian type!
236 #endif
237 }
238
239