1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
9 * License: public domain -or- http://www.wtfpl.net/txt/copying/
14 LTC_SHA256 by Tom St Denis
22 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
26 #define hash_state SHA256_CTX
27 #define sha256_init SHA256_Init
28 #define sha256_process SHA256_Update
29 #define sha256_done SHA256_Final
31 #define STORE32H(x, y) \
32 do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
33 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
35 #define LOAD32H(x, y) \
36 do { x = ((uint32_t)((y)[0] & 255)<<24) | \
37 ((uint32_t)((y)[1] & 255)<<16) | \
38 ((uint32_t)((y)[2] & 255)<<8) | \
39 ((uint32_t)((y)[3] & 255)); } while(0)
41 #define STORE64H(x, y) \
42 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
43 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
44 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
45 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
49 #define LTC_ROx_BUILTIN
51 /* instrinsic rotate */
53 #pragma intrinsic(_rotr,_rotl)
54 #define ROR(x,n) _rotr(x,n)
55 #define RORc(x,n) ROR(x,n)
57 #elif defined(LTC_HAVE_ROTATE_BUILTIN)
58 #define LTC_ROx_BUILTIN
60 #define ROR(x,n) __builtin_rotateright32(x,n)
61 #define RORc(x,n) ROR(x,n)
63 #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
66 static inline uint32_t ROR(uint32_t word
, int i
)
76 #define RORc(word,i) ({ \
77 uint32_t __RORc_tmp = (word); \
78 __asm__ ("rorl %2, %0" : \
91 #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
94 static inline uint32_t ROR(uint32_t word
, int i
)
98 :"0" (word
),"r" (32-i
));
104 static inline uint32_t RORc(uint32_t word
, const int i
)
106 asm ("rotrwi %0,%0,%2"
108 :"0" (word
),"I" (i
));
120 /* rotates the hard way */
121 #define ROR(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
122 #define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
126 /* a simple macro for making hash "process" functions */
127 #define HASH_PROCESS(func_name, compress_name, block_size) \
128 int func_name(hash_state *md, const void *_in, size_t inlen) \
130 const unsigned char *in = (const unsigned char *)_in; \
133 if (!md || !in) return 0; \
134 if (md->curlen > sizeof(md->buf)) { \
137 if ((md->length + inlen) < md->length) { \
140 while (inlen > 0) { \
141 if (md->curlen == 0 && inlen >= block_size) { \
142 if ((err = compress_name(md, in)) != CRYPT_OK) { \
145 md->length += block_size * 8; \
147 inlen -= block_size; \
149 n = MIN(inlen, (block_size - md->curlen)); \
150 memcpy(md->buf + md->curlen, in, (size_t)n); \
154 if (md->curlen == block_size) { \
155 if ((err = compress_name(md, md->buf)) != CRYPT_OK) { \
158 md->length += 8*block_size; \
166 #ifdef LTC_SMALL_CODE
168 static const uint32_t K
[64] = {
169 0x428a2f98UL
, 0x71374491UL
, 0xb5c0fbcfUL
, 0xe9b5dba5UL
, 0x3956c25bUL
,
170 0x59f111f1UL
, 0x923f82a4UL
, 0xab1c5ed5UL
, 0xd807aa98UL
, 0x12835b01UL
,
171 0x243185beUL
, 0x550c7dc3UL
, 0x72be5d74UL
, 0x80deb1feUL
, 0x9bdc06a7UL
,
172 0xc19bf174UL
, 0xe49b69c1UL
, 0xefbe4786UL
, 0x0fc19dc6UL
, 0x240ca1ccUL
,
173 0x2de92c6fUL
, 0x4a7484aaUL
, 0x5cb0a9dcUL
, 0x76f988daUL
, 0x983e5152UL
,
174 0xa831c66dUL
, 0xb00327c8UL
, 0xbf597fc7UL
, 0xc6e00bf3UL
, 0xd5a79147UL
,
175 0x06ca6351UL
, 0x14292967UL
, 0x27b70a85UL
, 0x2e1b2138UL
, 0x4d2c6dfcUL
,
176 0x53380d13UL
, 0x650a7354UL
, 0x766a0abbUL
, 0x81c2c92eUL
, 0x92722c85UL
,
177 0xa2bfe8a1UL
, 0xa81a664bUL
, 0xc24b8b70UL
, 0xc76c51a3UL
, 0xd192e819UL
,
178 0xd6990624UL
, 0xf40e3585UL
, 0x106aa070UL
, 0x19a4c116UL
, 0x1e376c08UL
,
179 0x2748774cUL
, 0x34b0bcb5UL
, 0x391c0cb3UL
, 0x4ed8aa4aUL
, 0x5b9cca4fUL
,
180 0x682e6ff3UL
, 0x748f82eeUL
, 0x78a5636fUL
, 0x84c87814UL
, 0x8cc70208UL
,
181 0x90befffaUL
, 0xa4506cebUL
, 0xbef9a3f7UL
, 0xc67178f2UL
185 /* Various logical functions */
186 #define Ch(x,y,z) (z ^ (x & (y ^ z)))
187 #define Maj(x,y,z) (((x | y) & z) | (x & y))
188 #define S(x, n) RORc((x),(n))
189 #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
190 #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
191 #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
192 #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
193 #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
195 /* compress 512-bits */
196 static int sha256_compress(hash_state
*md
, const unsigned char *buf
)
198 uint32_t S
[8], W
[64], t0
, t1
;
199 #ifdef LTC_SMALL_CODE
204 /* copy state into S */
205 for (i
= 0; i
< 8; i
++) {
209 /* copy the state into 512-bits into W[0..15] */
210 for (i
= 0; i
< 16; i
++) {
211 LOAD32H(W
[i
], buf
+ (4*i
));
215 for (i
= 16; i
< 64; i
++) {
216 W
[i
] = Gamma1(W
[i
- 2]) + W
[i
- 7] + Gamma0(W
[i
- 15]) + W
[i
- 16];
220 #ifdef LTC_SMALL_CODE
221 #define RND(a,b,c,d,e,f,g,h,i) \
222 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
223 t1 = Sigma0(a) + Maj(a, b, c); \
227 for (i
= 0; i
< 64; ++i
) {
228 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],i
);
229 t
= S
[7]; S
[7] = S
[6]; S
[6] = S
[5]; S
[5] = S
[4];
230 S
[4] = S
[3]; S
[3] = S
[2]; S
[2] = S
[1]; S
[1] = S
[0]; S
[0] = t
;
233 #define RND(a,b,c,d,e,f,g,h,i,ki) \
234 t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
235 t1 = Sigma0(a) + Maj(a, b, c); \
239 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],0,0x428a2f98);
240 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],1,0x71374491);
241 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],2,0xb5c0fbcf);
242 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],3,0xe9b5dba5);
243 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],4,0x3956c25b);
244 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],5,0x59f111f1);
245 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],6,0x923f82a4);
246 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],7,0xab1c5ed5);
247 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],8,0xd807aa98);
248 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],9,0x12835b01);
249 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],10,0x243185be);
250 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],11,0x550c7dc3);
251 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],12,0x72be5d74);
252 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],13,0x80deb1fe);
253 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],14,0x9bdc06a7);
254 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],15,0xc19bf174);
255 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],16,0xe49b69c1);
256 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],17,0xefbe4786);
257 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],18,0x0fc19dc6);
258 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],19,0x240ca1cc);
259 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],20,0x2de92c6f);
260 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],21,0x4a7484aa);
261 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],22,0x5cb0a9dc);
262 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],23,0x76f988da);
263 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],24,0x983e5152);
264 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],25,0xa831c66d);
265 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],26,0xb00327c8);
266 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],27,0xbf597fc7);
267 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],28,0xc6e00bf3);
268 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],29,0xd5a79147);
269 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],30,0x06ca6351);
270 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],31,0x14292967);
271 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],32,0x27b70a85);
272 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],33,0x2e1b2138);
273 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],34,0x4d2c6dfc);
274 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],35,0x53380d13);
275 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],36,0x650a7354);
276 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],37,0x766a0abb);
277 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],38,0x81c2c92e);
278 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],39,0x92722c85);
279 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],40,0xa2bfe8a1);
280 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],41,0xa81a664b);
281 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],42,0xc24b8b70);
282 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],43,0xc76c51a3);
283 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],44,0xd192e819);
284 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],45,0xd6990624);
285 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],46,0xf40e3585);
286 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],47,0x106aa070);
287 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],48,0x19a4c116);
288 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],49,0x1e376c08);
289 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],50,0x2748774c);
290 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],51,0x34b0bcb5);
291 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],52,0x391c0cb3);
292 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],53,0x4ed8aa4a);
293 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],54,0x5b9cca4f);
294 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],55,0x682e6ff3);
295 RND(S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],56,0x748f82ee);
296 RND(S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],57,0x78a5636f);
297 RND(S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],S
[5],58,0x84c87814);
298 RND(S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],S
[4],59,0x8cc70208);
299 RND(S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],S
[3],60,0x90befffa);
300 RND(S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],S
[2],61,0xa4506ceb);
301 RND(S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],S
[1],62,0xbef9a3f7);
302 RND(S
[1],S
[2],S
[3],S
[4],S
[5],S
[6],S
[7],S
[0],63,0xc67178f2);
309 for (i
= 0; i
< 8; i
++) {
310 md
->state
[i
] = md
->state
[i
] + S
[i
];
316 Initialize the hash state
317 @param md The hash state you wish to initialize
318 @return CRYPT_OK if successful
320 int sha256_init(hash_state
*md
)
326 md
->state
[0] = 0x6A09E667UL
;
327 md
->state
[1] = 0xBB67AE85UL
;
328 md
->state
[2] = 0x3C6EF372UL
;
329 md
->state
[3] = 0xA54FF53AUL
;
330 md
->state
[4] = 0x510E527FUL
;
331 md
->state
[5] = 0x9B05688CUL
;
332 md
->state
[6] = 0x1F83D9ABUL
;
333 md
->state
[7] = 0x5BE0CD19UL
;
338 Process a block of memory though the hash
339 @param md The hash state
340 @param in The data to hash
341 @param inlen The length of the data (octets)
342 @return CRYPT_OK if successful
344 HASH_PROCESS(sha256_process
, sha256_compress
, 64)
347 Terminate the hash to get the digest
348 @param md The hash state
349 @param out [out] The destination of the hash (32 bytes)
350 @return CRYPT_OK if successful
352 int sha256_done(unsigned char *out
, hash_state
*md
)
356 if (!md
|| !out
) return 0;
358 if (md
->curlen
>= sizeof(md
->buf
)) {
363 /* increase the length of the message */
364 md
->length
+= md
->curlen
* 8;
366 /* append the '1' bit */
367 md
->buf
[md
->curlen
++] = (unsigned char)0x80;
369 /* if the length is currently above 56 bytes we append zeros
370 * then compress. Then we can fall back to padding zeros and length
371 * encoding like normal.
373 if (md
->curlen
> 56) {
374 while (md
->curlen
< 64) {
375 md
->buf
[md
->curlen
++] = (unsigned char)0;
377 sha256_compress(md
, md
->buf
);
381 /* pad upto 56 bytes of zeroes */
382 while (md
->curlen
< 56) {
383 md
->buf
[md
->curlen
++] = (unsigned char)0;
387 STORE64H(md
->length
, md
->buf
+56);
388 sha256_compress(md
, md
->buf
);
391 for (i
= 0; i
< 8; i
++) {
392 STORE32H(md
->state
[i
], out
+(4*i
));
397 unsigned char *SHA256(const void *data
, size_t len
, unsigned char *md
)
401 if (!SHA256_Init(&c
)) return NULL
;
402 if (!SHA256_Update(&c
, data
, len
)) return NULL
;
403 if (!SHA256_Final(md
, &c
)) return NULL
;