0
|
1 /* sha1.c */ |
|
2 /* |
|
3 This file is part of the AVR-Crypto-Lib. |
|
4 Copyright (C) 2008, 2009 Daniel Otte ([email protected]) |
|
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 sha1.c |
|
21 * \author Daniel Otte |
|
22 * \date 2006-10-08 |
|
23 * \license GPLv3 or later |
|
24 * \brief SHA-1 implementation. |
|
25 * |
|
26 */ |
|
27 |
|
28 #include <string.h> /* memcpy & co */ |
|
29 #include <stdint.h> |
|
30 #include "config.h" |
|
31 #include "debug.h" |
|
32 #include "sha1.h" |
|
33 |
|
34 #ifdef DEBUG |
|
35 # undef DEBUG |
|
36 #endif |
|
37 |
|
38 #include "cli.h" |
|
39 |
|
40 #define LITTLE_ENDIAN |
|
41 |
|
42 /********************************************************************************************************/ |
|
43 |
|
44 /** |
|
45 * \brief initialises given SHA-1 context |
|
46 * |
|
47 */ |
|
48 void sha1_init(sha1_ctx_t *state){ |
|
49 DEBUG_S("\r\nSHA1_INIT"); |
|
50 state->h[0] = 0x67452301; |
|
51 state->h[1] = 0xefcdab89; |
|
52 state->h[2] = 0x98badcfe; |
|
53 state->h[3] = 0x10325476; |
|
54 state->h[4] = 0xc3d2e1f0; |
|
55 state->length = 0; |
|
56 } |
|
57 |
|
58 /********************************************************************************************************/ |
|
59 /* some helping functions */ |
|
60 uint32_t rotl32(uint32_t n, uint8_t bits){ |
|
61 return ((n<<bits) | (n>>(32-bits))); |
|
62 } |
|
63 |
|
64 uint32_t change_endian32(uint32_t x){ |
|
65 return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8)); |
|
66 } |
|
67 |
|
68 |
|
69 /* three SHA-1 inner functions */ |
|
70 uint32_t ch(uint32_t x, uint32_t y, uint32_t z){ |
|
71 DEBUG_S("\r\nCH"); |
|
72 return ((x&y)^((~x)&z)); |
|
73 } |
|
74 |
|
75 uint32_t maj(uint32_t x, uint32_t y, uint32_t z){ |
|
76 DEBUG_S("\r\nMAJ"); |
|
77 return ((x&y)^(x&z)^(y&z)); |
|
78 } |
|
79 |
|
80 uint32_t parity(uint32_t x, uint32_t y, uint32_t z){ |
|
81 DEBUG_S("\r\nPARITY"); |
|
82 return ((x^y)^z); |
|
83 } |
|
84 |
|
85 /********************************************************************************************************/ |
|
86 /** |
|
87 * \brief "add" a block to the hash |
|
88 * This is the core function of the hash algorithm. To understand how it's working |
|
89 * and what thoese variables do, take a look at FIPS-182. This is an "alternativ" implementation |
|
90 */ |
|
91 |
|
92 #define MASK 0x0000000f |
|
93 |
|
94 typedef uint32_t (*pf_t)(uint32_t x, uint32_t y, uint32_t z); |
|
95 |
|
96 void sha1_nextBlock (sha1_ctx_t *state, const void* block){ |
|
97 uint32_t a[5]; |
|
98 uint32_t w[16]; |
|
99 uint32_t temp; |
|
100 uint8_t t,s,fi, fib; |
|
101 pf_t f[] = {ch,parity,maj,parity}; |
|
102 uint32_t k[4]={ 0x5a827999, |
|
103 0x6ed9eba1, |
|
104 0x8f1bbcdc, |
|
105 0xca62c1d6}; |
|
106 |
|
107 /* load the w array (changing the endian and so) */ |
|
108 for(t=0; t<16; ++t){ |
|
109 w[t] = change_endian32(((uint32_t*)block)[t]); |
|
110 } |
|
111 |
|
112 #if DEBUG |
|
113 uint8_t dbgi; |
|
114 for(dbgi=0; dbgi<16; ++dbgi){ |
|
115 /* |
|
116 DEBUG_S("\n\rBlock:"); |
|
117 DEBUG_B(dbgi); |
|
118 DEBUG_C(':'); |
|
119 */ |
|
120 cli_putstr_P(PSTR("\r\nBlock:")); |
|
121 cli_hexdump(&dbgi, 1); |
|
122 cli_putc(':'); |
|
123 cli_hexdump(&(w[dbgi]) ,4); |
|
124 } |
|
125 #endif |
|
126 |
|
127 /* load the state */ |
|
128 memcpy(a, state->h, 5*sizeof(uint32_t)); |
|
129 |
|
130 |
|
131 /* the fun stuff */ |
|
132 for(fi=0,fib=0,t=0; t<=79; ++t){ |
|
133 s = t & MASK; |
|
134 if(t>=16){ |
|
135 #if DEBUG |
|
136 DEBUG_S("\r\n ws = "); cli_hexdump(&(w[s]), 4); |
|
137 #endif |
|
138 w[s] = rotl32( w[(s+13)&MASK] ^ w[(s+8)&MASK] ^ |
|
139 w[(s+ 2)&MASK] ^ w[s] ,1); |
|
140 #ifdef DEBUG |
|
141 DEBUG_S(" --> ws = "); cli_hexdump(&(w[s]), 4); |
|
142 #endif |
|
143 } |
|
144 |
|
145 uint32_t dtemp; |
|
146 temp = rotl32(a[0],5) + (dtemp=f[fi](a[1],a[2],a[3])) + a[4] + k[fi] + w[s]; |
|
147 memmove(&(a[1]), &(a[0]), 4*sizeof(uint32_t)); /* e=d; d=c; c=b; b=a; */ |
|
148 a[0] = temp; |
|
149 a[2] = rotl32(a[2],30); /* we might also do rotr32(c,2) */ |
|
150 fib++; |
|
151 if(fib==20){ |
|
152 fib=0; |
|
153 fi = (fi+1)%4; |
|
154 } |
|
155 #if DEBUG |
|
156 /* debug dump */ |
|
157 DEBUG_S("\r\nt = "); DEBUG_B(t); |
|
158 DEBUG_S("; a[]: "); |
|
159 cli_hexdump(a, 5*4); |
|
160 DEBUG_S("; k = "); |
|
161 cli_hexdump(&(k[t/20]), 4); |
|
162 DEBUG_S("; f(b,c,d) = "); |
|
163 cli_hexdump(&dtemp, 4); |
|
164 #endif |
|
165 } |
|
166 |
|
167 /* update the state */ |
|
168 for(t=0; t<5; ++t){ |
|
169 state->h[t] += a[t]; |
|
170 } |
|
171 state->length += 512; |
|
172 } |
|
173 |
|
174 /********************************************************************************************************/ |
|
175 |
|
176 void sha1_lastBlock(sha1_ctx_t *state, const void* block, uint16_t length){ |
|
177 uint8_t lb[SHA1_BLOCK_BYTES]; /* local block */ |
|
178 while(length>=SHA1_BLOCK_BITS){ |
|
179 sha1_nextBlock(state, block); |
|
180 length -= SHA1_BLOCK_BITS; |
|
181 block = (uint8_t*)block + SHA1_BLOCK_BYTES; |
|
182 } |
|
183 state->length += length; |
|
184 memset(lb, 0, SHA1_BLOCK_BYTES); |
|
185 memcpy (lb, block, (length+7)>>3); |
|
186 |
|
187 /* set the final one bit */ |
|
188 lb[length>>3] |= 0x80>>(length & 0x07); |
|
189 |
|
190 if (length>512-64-1){ /* not enouth space for 64bit length value */ |
|
191 sha1_nextBlock(state, lb); |
|
192 state->length -= 512; |
|
193 memset(lb, 0, SHA1_BLOCK_BYTES); |
|
194 } |
|
195 /* store the 64bit length value */ |
|
196 #if defined LITTLE_ENDIAN |
|
197 /* this is now rolled up */ |
|
198 uint8_t i; |
|
199 for (i=0; i<8; ++i){ |
|
200 lb[56+i] = ((uint8_t*)&(state->length))[7-i]; |
|
201 } |
|
202 #elif defined BIG_ENDIAN |
|
203 *((uint64_t)&(lb[56])) = state->length; |
|
204 #endif |
|
205 sha1_nextBlock(state, lb); |
|
206 } |
|
207 |
|
208 /********************************************************************************************************/ |
|
209 |
|
210 void sha1_ctx2hash (void *dest, sha1_ctx_t *state){ |
|
211 #if defined LITTLE_ENDIAN |
|
212 uint8_t i; |
|
213 for(i=0; i<5; ++i){ |
|
214 ((uint32_t*)dest)[i] = change_endian32(state->h[i]); |
|
215 } |
|
216 #elif BIG_ENDIAN |
|
217 if (dest != state->h) |
|
218 memcpy(dest, state->h, SHA1_HASH_BITS/8); |
|
219 #else |
|
220 # error unsupported endian type! |
|
221 #endif |
|
222 } |
|
223 |
|
224 /********************************************************************************************************/ |
|
225 /** |
|
226 * |
|
227 * |
|
228 */ |
|
229 void sha1 (void *dest, const void* msg, uint32_t length){ |
|
230 sha1_ctx_t s; |
|
231 DEBUG_S("\r\nBLA BLUB"); |
|
232 sha1_init(&s); |
|
233 while(length & (~0x0001ff)){ /* length>=512 */ |
|
234 DEBUG_S("\r\none block"); |
|
235 sha1_nextBlock(&s, msg); |
|
236 msg = (uint8_t*)msg + SHA1_BLOCK_BITS/8; /* increment pointer to next block */ |
|
237 length -= SHA1_BLOCK_BITS; |
|
238 } |
|
239 sha1_lastBlock(&s, msg, length); |
|
240 sha1_ctx2hash(dest, &s); |
|
241 } |
|
242 |
|
243 |