1+ /*********************************************************************
2+ * Filename: sha256.c
3+ * Author: Brad Conte (brad AT bradconte.com)
4+ * Copyright:
5+ * Disclaimer: This code is presented "as is" without any guarantees.
6+ * Details: Implementation of the SHA-256 hashing algorithm.
7+ SHA-256 is one of the three algorithms in the SHA2
8+ specification. The others, SHA-384 and SHA-512, are not
9+ offered in this implementation.
10+ Algorithm specification can be found here:
11+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
12+ This implementation uses little endian byte order.
13+ *********************************************************************/
14+
15+ /*************************** HEADER FILES ***************************/
16+ #include "sha256.h"
17+
18+ /****************************** MACROS ******************************/
19+ #define ROTLEFT (a , b ) (((a) << (b)) | ((a) >> (32 - (b))))
20+ #define ROTRIGHT (a , b ) (((a) >> (b)) | ((a) << (32 - (b))))
21+
22+ #define CH (x , y , z ) (((x) & (y)) ^ (~(x) & (z)))
23+ #define MAJ (x , y , z ) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
24+ #define EP0 (x ) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
25+ #define EP1 (x ) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
26+ #define SIG0 (x ) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
27+ #define SIG1 (x ) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
28+
29+ /**************************** VARIABLES *****************************/
30+ static const WORD k [64 ] = { 0x428a2f98 , 0x71374491 , 0xb5c0fbcf , 0xe9b5dba5 , 0x3956c25b , 0x59f111f1 , 0x923f82a4 ,
31+ 0xab1c5ed5 , 0xd807aa98 , 0x12835b01 , 0x243185be , 0x550c7dc3 , 0x72be5d74 , 0x80deb1fe ,
32+ 0x9bdc06a7 , 0xc19bf174 , 0xe49b69c1 , 0xefbe4786 , 0x0fc19dc6 , 0x240ca1cc , 0x2de92c6f ,
33+ 0x4a7484aa , 0x5cb0a9dc , 0x76f988da , 0x983e5152 , 0xa831c66d , 0xb00327c8 , 0xbf597fc7 ,
34+ 0xc6e00bf3 , 0xd5a79147 , 0x06ca6351 , 0x14292967 , 0x27b70a85 , 0x2e1b2138 , 0x4d2c6dfc ,
35+ 0x53380d13 , 0x650a7354 , 0x766a0abb , 0x81c2c92e , 0x92722c85 , 0xa2bfe8a1 , 0xa81a664b ,
36+ 0xc24b8b70 , 0xc76c51a3 , 0xd192e819 , 0xd6990624 , 0xf40e3585 , 0x106aa070 , 0x19a4c116 ,
37+ 0x1e376c08 , 0x2748774c , 0x34b0bcb5 , 0x391c0cb3 , 0x4ed8aa4a , 0x5b9cca4f , 0x682e6ff3 ,
38+ 0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 , 0x90befffa , 0xa4506ceb , 0xbef9a3f7 ,
39+ 0xc67178f2 };
40+
41+ /*********************** FUNCTION DEFINITIONS ***********************/
42+ void sha256_transform (SHA256_CTX * ctx , const BYTE data [])
43+ {
44+ WORD a , b , c , d , e , f , g , h , i , j , t1 , t2 , m [64 ];
45+
46+ for (i = 0 , j = 0 ; i < 16 ; ++ i , j += 4 )
47+ m [i ] = (data [j ] << 24 ) | (data [j + 1 ] << 16 ) | (data [j + 2 ] << 8 ) | (data [j + 3 ]);
48+ for (; i < 64 ; ++ i )
49+ m [i ] = SIG1 (m [i - 2 ]) + m [i - 7 ] + SIG0 (m [i - 15 ]) + m [i - 16 ];
50+
51+ a = ctx -> state [0 ];
52+ b = ctx -> state [1 ];
53+ c = ctx -> state [2 ];
54+ d = ctx -> state [3 ];
55+ e = ctx -> state [4 ];
56+ f = ctx -> state [5 ];
57+ g = ctx -> state [6 ];
58+ h = ctx -> state [7 ];
59+
60+ for (i = 0 ; i < 64 ; ++ i ) {
61+ t1 = h + EP1 (e ) + CH (e , f , g ) + k [i ] + m [i ];
62+ t2 = EP0 (a ) + MAJ (a , b , c );
63+ h = g ;
64+ g = f ;
65+ f = e ;
66+ e = d + t1 ;
67+ d = c ;
68+ c = b ;
69+ b = a ;
70+ a = t1 + t2 ;
71+ }
72+
73+ ctx -> state [0 ] += a ;
74+ ctx -> state [1 ] += b ;
75+ ctx -> state [2 ] += c ;
76+ ctx -> state [3 ] += d ;
77+ ctx -> state [4 ] += e ;
78+ ctx -> state [5 ] += f ;
79+ ctx -> state [6 ] += g ;
80+ ctx -> state [7 ] += h ;
81+ }
82+
83+ void sha256_init (SHA256_CTX * ctx )
84+ {
85+ ctx -> datalen = 0 ;
86+ ctx -> bitlen = 0 ;
87+ ctx -> state [0 ] = 0x6a09e667 ;
88+ ctx -> state [1 ] = 0xbb67ae85 ;
89+ ctx -> state [2 ] = 0x3c6ef372 ;
90+ ctx -> state [3 ] = 0xa54ff53a ;
91+ ctx -> state [4 ] = 0x510e527f ;
92+ ctx -> state [5 ] = 0x9b05688c ;
93+ ctx -> state [6 ] = 0x1f83d9ab ;
94+ ctx -> state [7 ] = 0x5be0cd19 ;
95+ }
96+
97+ void sha256_update (SHA256_CTX * ctx , const BYTE data [], size_t len )
98+ {
99+ WORD i ;
100+
101+ for (i = 0 ; i < len ; ++ i ) {
102+ ctx -> data [ctx -> datalen ] = data [i ];
103+ ctx -> datalen ++ ;
104+ if (ctx -> datalen == 64 ) {
105+ sha256_transform (ctx , ctx -> data );
106+ ctx -> bitlen += 512 ;
107+ ctx -> datalen = 0 ;
108+ }
109+ }
110+ }
111+
112+ void sha256_final (SHA256_CTX * ctx , BYTE hash [])
113+ {
114+ WORD i ;
115+
116+ i = ctx -> datalen ;
117+
118+ // Pad whatever data is left in the buffer.
119+ if (ctx -> datalen < 56 ) {
120+ ctx -> data [i ++ ] = 0x80 ;
121+ while (i < 56 )
122+ ctx -> data [i ++ ] = 0x00 ;
123+ } else {
124+ ctx -> data [i ++ ] = 0x80 ;
125+ while (i < 64 )
126+ ctx -> data [i ++ ] = 0x00 ;
127+ sha256_transform (ctx , ctx -> data );
128+ for (int i = 0 ; i < 56 ; i ++ )
129+ ctx -> data [i ] = 0 ;
130+ }
131+
132+ // Append to the padding the total message's length in bits and transform.
133+ ctx -> bitlen += ctx -> datalen * 8 ;
134+ ctx -> data [63 ] = ctx -> bitlen ;
135+ ctx -> data [62 ] = ctx -> bitlen >> 8 ;
136+ ctx -> data [61 ] = ctx -> bitlen >> 16 ;
137+ ctx -> data [60 ] = ctx -> bitlen >> 24 ;
138+ ctx -> data [59 ] = ctx -> bitlen >> 32 ;
139+ ctx -> data [58 ] = ctx -> bitlen >> 40 ;
140+ ctx -> data [57 ] = ctx -> bitlen >> 48 ;
141+ ctx -> data [56 ] = ctx -> bitlen >> 56 ;
142+ sha256_transform (ctx , ctx -> data );
143+
144+ // Since this implementation uses little endian byte ordering and SHA uses big endian,
145+ // reverse all the bytes when copying the final state to the output hash.
146+ for (i = 0 ; i < 4 ; ++ i ) {
147+ hash [i ] = (ctx -> state [0 ] >> (24 - i * 8 )) & 0x000000ff ;
148+ hash [i + 4 ] = (ctx -> state [1 ] >> (24 - i * 8 )) & 0x000000ff ;
149+ hash [i + 8 ] = (ctx -> state [2 ] >> (24 - i * 8 )) & 0x000000ff ;
150+ hash [i + 12 ] = (ctx -> state [3 ] >> (24 - i * 8 )) & 0x000000ff ;
151+ hash [i + 16 ] = (ctx -> state [4 ] >> (24 - i * 8 )) & 0x000000ff ;
152+ hash [i + 20 ] = (ctx -> state [5 ] >> (24 - i * 8 )) & 0x000000ff ;
153+ hash [i + 24 ] = (ctx -> state [6 ] >> (24 - i * 8 )) & 0x000000ff ;
154+ hash [i + 28 ] = (ctx -> state [7 ] >> (24 - i * 8 )) & 0x000000ff ;
155+ }
156+ }
0 commit comments