3 This file is part of the AVR-Crypto-Lib.
4 Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
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.
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.
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/>.
27 * \brief SHA-256 implementation.
33 #include <string.h> /* for memcpy, memmove, memset */
34 #include <avr/pgmspace.h>
39 #if defined LITTLE_ENDIAN
40 #elif defined BIG_ENDIAN
42 #error specify endianess!!!
46 /*************************************************************************/
48 static const uint32_t sha256_init_vector[] PROGMEM = {
49 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
50 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL };
53 /*************************************************************************/
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
61 void sha256_init(sha256_ctx_t *state){
63 memcpy_P(state->h, sha256_init_vector, 8 * 4);
66 /*************************************************************************/
69 * rotate x right by n positions
71 uint32_t rotr32( uint32_t x, uint8_t n){
72 return ((x >> n) | (x << (32 - n)));
76 /*************************************************************************/
78 // #define CHANGE_ENDIAN32(x) (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8))
80 uint32_t change_endian32(uint32_t x){
83 | (((x) & 0x0000ff00UL) << 8)
84 | (((x) & 0x00ff0000UL) >> 8) );
88 /*************************************************************************/
90 /* sha256 functions as macros for speed and size, cause they are called only once */
92 #define CH(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
93 #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
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))
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
113 /*************************************************************************/
116 * block must be 512 Bit = 64 Byte long !!!
118 void sha256_nextBlock (sha256_ctx_t *state, const void *block){
119 uint32_t w[16]; /* this is 64 Byte large, */
121 uint32_t a[8], t1, t2;
123 /* init working variables */
124 memcpy((void*)a,(void*)(state->h), 8 * 4);
127 #if defined LITTLE_ENDIAN
128 for (i = 0; i < 16; ++i) {
129 w[i] = change_endian32(((uint32_t*)block)[i]);
131 #elif defined BIG_ENDIAN
132 memcpy((void*)w, block, 64);
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];
139 /* do the, fun stuff, */
140 for (i=0; i<64; ++i) {
142 w[i % 16] = SIGMA_b(w[(i + 14) % 16])
144 + SIGMA_a(w[(i + 1) % 16])
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]; */
154 /* update, the, state, */
155 for (i = 0; i < 8; ++i){
162 /*************************************************************************/
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
172 void sha256_lastBlock(sha256_ctx_t *state, const void *block, uint16_t length){
173 uint8_t lb[SHA256_BLOCK_BITS / 8]; /* local block */
175 while(length>=SHA256_BLOCK_BITS){
176 sha256_nextBlock(state, block);
177 length -= SHA256_BLOCK_BITS;
178 block = (uint8_t*)block + SHA256_BLOCK_BYTES;
181 msg_len = state->length;
184 memcpy (&(lb[0]), block, length / 8);
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];
192 lb[length / 8] |= 0x80 >> (length & 7);
193 length = (length / 8) + 1; /* from now on length contains the number of BYTES in lb*/
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);
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 */
206 lb[56 + i] = msg_len & 0xff;
209 #elif defined BIG_ENDIAN
210 *((uint64_t)&(lb[56])) = state->length;
212 sha256_nextBlock(state, lb);
216 /*************************************************************************/
221 void sha256(sha256_hash_t *dest, const void *msg, uint32_t length){ /* length could be choosen longer but this is for µC */
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;
229 sha256_lastBlock(&s, msg, length);
230 sha256_ctx2hash(dest,&s);
235 /*************************************************************************/
237 void sha256_ctx2hash(sha256_hash_t *dest, const sha256_ctx_t *state){
238 #if defined LITTLE_ENDIAN
240 for(i = 0; i < 8; ++i){
241 ((uint32_t*)dest)[i] = change_endian32(state->h[i]);
244 if (dest != state->h)
245 memcpy(dest, state->h, SHA256_HASH_BITS/8);
247 # error unsupported endian type!