]> git.cryptolib.org Git - avr-crypto-lib.git/blob - sha256/sha256.c
adjusting test system debug uart reference
[avr-crypto-lib.git] / sha256 / sha256.c
1 /* sha256.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2008  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 <avr/pgmspace.h>
35 #include "sha256.h"
36
37 #define LITTLE_ENDIAN
38
39 #if defined LITTLE_ENDIAN
40 #elif defined BIG_ENDIAN
41 #else
42         #error specify endianess!!!
43 #endif
44
45
46 /*************************************************************************/
47
48 static const uint32_t sha256_init_vector[] PROGMEM = {
49         0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
50     0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL };
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_P(state->h, sha256_init_vector, 8 * 4);
64 }
65
66 /*************************************************************************/
67
68 /**
69  * rotate x right by n positions
70  */
71 uint32_t rotr32( uint32_t x, uint8_t n){
72         return ((x >> n) | (x << (32 - n)));
73 }
74
75
76 /*************************************************************************/
77
78 // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8))
79
80 uint32_t change_endian32(uint32_t x){
81         return (  ((x) << 24)
82                 | ((x) >> 24)
83                 | (((x) & 0x0000ff00UL) << 8)
84                 | (((x) & 0x00ff0000UL) >> 8) );
85 }
86
87
88 /*************************************************************************/
89
90 /* sha256 functions as macros for speed and size, cause they are called only once */
91
92 #define CH(x,y,z)  (((x) & (y)) ^ ((~(x)) & (z)))
93 #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
94
95 #define SIGMA0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
96 #define SIGMA1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
97 #define SIGMA_a(x) (rotr32((x), 7)  ^ rotr32((x), 18) ^ ((x) >> 3))
98 #define SIGMA_b(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
99
100
101 static const uint32_t k[] PROGMEM = {
102         0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
103         0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
104         0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
105         0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
106         0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
107         0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
108         0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
109         0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
110 };
111
112
113 /*************************************************************************/
114
115 /**
116  * block must be 512 Bit = 64 Byte long !!!
117  */
118 void sha256_nextBlock (sha256_ctx_t *state, const void *block){
119         uint32_t w[16]; /* this is 64 Byte large, */
120         uint8_t  i;
121         uint32_t a[8], t1, t2;
122
123     /* init working variables */
124     memcpy((void*)a,(void*)(state->h), 8 * 4);
125
126     /* init w */
127 #if defined LITTLE_ENDIAN
128     for (i = 0; i < 16; ++i) {
129         w[i] = change_endian32(((uint32_t*)block)[i]);
130     }
131 #elif defined BIG_ENDIAN
132                 memcpy((void*)w, block, 64);
133 #endif
134 /*
135     for (i = 16; i < 64; ++i) {
136         w[i] = SIGMA_b(w[i - 2]) + w[i - 7] + SIGMA_a(w[i - 15]) + w[i - 16];
137     }
138 */
139         /* do the, fun stuff, */
140     for (i=0; i<64; ++i) {
141         if (i > 15) {
142             w[i % 16] =   SIGMA_b(w[(i + 14) % 16])
143                         + w[(i + 9) % 16]
144                         + SIGMA_a(w[(i + 1) % 16])
145                         + w[i % 16];
146         }
147         t1 = a[7] + SIGMA1(a[4]) + CH(a[4], a[5], a[6]) + pgm_read_dword(&k[i]) + w[i % 16];
148         t2 = SIGMA0(a[0]) + MAJ(a[0], a[1], a[2]);
149         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]; */
150         a[4] += t1;
151         a[0] = t1 + t2;
152     }
153
154         /* update, the, state, */
155     for (i = 0; i < 8; ++i){
156         state->h[i] += a[i];
157     }
158     state->length += 1;
159 }
160
161
162 /*************************************************************************/
163
164 /**
165  * \brief function to process the last block being hashed
166  * @param state Pointer to the context in which this block should be processed.
167  * @param block Pointer to the message wich should be hashed.
168  * @param length is the length of only THIS block in BITS not in bytes!
169  *  bits are big endian, meaning high bits come first.
170  *      if you have a message with bits at the end, the byte must be padded with zeros
171  */
172 void sha256_lastBlock(sha256_ctx_t *state, const void *block, uint16_t length){
173         uint8_t lb[SHA256_BLOCK_BITS / 8]; /* local block */
174         uint64_t msg_len;
175         while(length>=SHA256_BLOCK_BITS){
176                 sha256_nextBlock(state, block);
177                 length -= SHA256_BLOCK_BITS;
178                 block = (uint8_t*)block + SHA256_BLOCK_BYTES;
179         }
180
181         msg_len = state->length;
182         msg_len *= 512;
183         msg_len += length;
184         memcpy (&(lb[0]), block, length / 8);
185
186         /* set the final one bit */
187         if (length & 7){ // if we have single bits at the end
188                 lb[length / 8] = ((uint8_t*)(block))[length / 8];
189         } else {
190                 lb[length / 8] = 0;
191         }
192         lb[length / 8] |= 0x80 >> (length & 7);
193         length = (length / 8) + 1; /* from now on length contains the number of BYTES in lb*/
194         /* pad with zeros */
195         if (length > 64 - 8){ /* not enouth space for 64bit length value */
196                 memset((void*)(&(lb[length])), 0, 64 - length);
197                 sha256_nextBlock(state, lb);
198                 length = 0;
199         }
200         memset((void*)(&(lb[length])), 0, 56 - length);
201         /* store the 64bit length value */
202 #if defined LITTLE_ENDIAN
203     /* this is now rolled up */
204         uint8_t i = 7;
205         do {
206             lb[56 + i] = msg_len & 0xff;
207             msg_len >>= 8;
208         } while (i--);
209 #elif defined BIG_ENDIAN
210         *((uint64_t)&(lb[56])) = state->length;
211 #endif
212         sha256_nextBlock(state, lb);
213 }
214
215
216 /*************************************************************************/
217
218 /*
219  * length in bits!
220  */
221 void sha256(sha256_hash_t *dest, const void *msg, uint32_t length){ /* length could be choosen longer but this is for µC */
222         sha256_ctx_t s;
223         sha256_init(&s);
224         while(length >= SHA256_BLOCK_BITS){
225                 sha256_nextBlock(&s, msg);
226                 msg = (uint8_t*)msg + SHA256_BLOCK_BITS/8;
227                 length -= SHA256_BLOCK_BITS;
228         }
229         sha256_lastBlock(&s, msg, length);
230         sha256_ctx2hash(dest,&s);
231 }
232
233
234
235 /*************************************************************************/
236
237 void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state){
238 #if defined LITTLE_ENDIAN
239         uint8_t i;
240         for(i = 0; i < 8; ++i){
241                 ((uint32_t*)dest)[i] = change_endian32(state->h[i]);
242         }
243 #elif BIG_ENDIAN
244         if (dest != state->h)
245                 memcpy(dest, state->h, SHA256_HASH_BITS/8);
246 #else
247 # error unsupported endian type!
248 #endif
249 }
250
251