• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * sha512.c --- The sha512 algorithm
3  *
4  * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
5  * (copied from libtomcrypt and then relicensed under GPLv2)
6  *
7  * %Begin-Header%
8  * This file may be redistributed under the terms of the GNU Library
9  * General Public License, version 2.
10  * %End-Header%
11  */
12 
13 
14 #include "config.h"
15 #if HAVE_SYS_TYPES_H
16 #include <sys/types.h>
17 #endif
18 #include "ext2fs.h"
19 
20 /* the K array */
21 #define CONST64(n) n
22 static const __u64 K[80] = {
23 	CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
24 	CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
25 	CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
26 	CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
27 	CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
28 	CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
29 	CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
30 	CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
31 	CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
32 	CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
33 	CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
34 	CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
35 	CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
36 	CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
37 	CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
38 	CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
39 	CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
40 	CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
41 	CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
42 	CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
43 	CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
44 	CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
45 	CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
46 	CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
47 	CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
48 	CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
49 	CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
50 	CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
51 	CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
52 	CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
53 	CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
54 	CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
55 	CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
56 	CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
57 	CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
58 	CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
59 	CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
60 	CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
61 	CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
62 	CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
63 };
64 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
65 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
66 #define S(x, n)         ROR64c(x, n)
67 #define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)n))
68 #define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
69 #define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
70 #define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
71 #define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
72 #define RND(a,b,c,d,e,f,g,h,i)\
73 		t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];\
74 		t1 = Sigma0(a) + Maj(a, b, c);\
75 		d += t0;\
76 		h  = t0 + t1;
77 #define STORE64H(x, y) \
78 	do { \
79 		(y)[0] = (unsigned char)(((x)>>56)&255);\
80 		(y)[1] = (unsigned char)(((x)>>48)&255);\
81 		(y)[2] = (unsigned char)(((x)>>40)&255);\
82 		(y)[3] = (unsigned char)(((x)>>32)&255);\
83 		(y)[4] = (unsigned char)(((x)>>24)&255);\
84 		(y)[5] = (unsigned char)(((x)>>16)&255);\
85 		(y)[6] = (unsigned char)(((x)>>8)&255);\
86 		(y)[7] = (unsigned char)((x)&255); } while(0)
87 
88 #define LOAD64H(x, y)\
89 	do {x = \
90 		(((__u64)((y)[0] & 255)) << 56) |\
91 		(((__u64)((y)[1] & 255)) << 48) |\
92 		(((__u64)((y)[2] & 255)) << 40) |\
93 		(((__u64)((y)[3] & 255)) << 32) |\
94 		(((__u64)((y)[4] & 255)) << 24) |\
95 		(((__u64)((y)[5] & 255)) << 16) |\
96 		(((__u64)((y)[6] & 255)) << 8) |\
97 		(((__u64)((y)[7] & 255)));\
98 	} while(0)
99 
100 #define ROR64c(x, y) \
101     ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)(y)&CONST64(63))) | \
102       ((x)<<((__u64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
103 
104 struct sha512_state {
105 	__u64  length, state[8];
106 	unsigned long curlen;
107 	unsigned char buf[128];
108 };
109 
110 /* This is a highly simplified version from libtomcrypt */
111 struct hash_state {
112 	struct sha512_state sha512;
113 };
114 
sha512_compress(struct hash_state * md,const unsigned char * buf)115 static void sha512_compress(struct hash_state * md, const unsigned char *buf)
116 {
117 	__u64 S[8], W[80], t0, t1;
118 	int i;
119 
120 	/* copy state into S */
121 	for (i = 0; i < 8; i++) {
122 		S[i] = md->sha512.state[i];
123 	}
124 
125 	/* copy the state into 1024-bits into W[0..15] */
126 	for (i = 0; i < 16; i++) {
127 		LOAD64H(W[i], buf + (8*i));
128 	}
129 
130 	/* fill W[16..79] */
131 	for (i = 16; i < 80; i++) {
132 		W[i] = Gamma1(W[i - 2]) + W[i - 7] +
133 			Gamma0(W[i - 15]) + W[i - 16];
134 	}
135 
136 	for (i = 0; i < 80; i += 8) {
137 		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
138 		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
139 		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
140 		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
141 		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
142 		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
143 		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
144 		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
145 	}
146 
147 	 /* feedback */
148 	for (i = 0; i < 8; i++) {
149 		md->sha512.state[i] = md->sha512.state[i] + S[i];
150 	}
151 }
152 
sha512_init(struct hash_state * md)153 static void sha512_init(struct hash_state * md)
154 {
155 	md->sha512.curlen = 0;
156 	md->sha512.length = 0;
157 	md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
158 	md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
159 	md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
160 	md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
161 	md->sha512.state[4] = CONST64(0x510e527fade682d1);
162 	md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
163 	md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
164 	md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
165 }
166 
sha512_done(struct hash_state * md,unsigned char * out)167 static void sha512_done(struct hash_state * md, unsigned char *out)
168 {
169 	int i;
170 
171 	/* increase the length of the message */
172 	md->sha512.length += md->sha512.curlen * CONST64(8);
173 
174 	/* append the '1' bit */
175 	md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
176 
177 	/* if the length is currently above 112 bytes we append zeros then
178 	 * compress. Then we can fall back to padding zeros and length encoding
179 	 * like normal. */
180 	if (md->sha512.curlen > 112) {
181 		while (md->sha512.curlen < 128) {
182 			md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
183 		}
184 		sha512_compress(md, md->sha512.buf);
185 		md->sha512.curlen = 0;
186 	}
187 
188 	/* pad upto 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB
189 	 * of the length. We assume that you won't hash > 2^64 bits of data. */
190 	while (md->sha512.curlen < 120) {
191 		md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
192 	}
193 
194 	/* store length */
195 	STORE64H(md->sha512.length, md->sha512.buf + 120);
196 	sha512_compress(md, md->sha512.buf);
197 
198 	/* copy output */
199 	for (i = 0; i < 8; i++) {
200 		STORE64H(md->sha512.state[i], out+(8 * i));
201 	}
202 }
203 
204 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
205 #define SHA512_BLOCKSIZE 128
sha512_process(struct hash_state * md,const unsigned char * in,unsigned long inlen)206 static void sha512_process(struct hash_state * md,
207 			   const unsigned char *in,
208 			   unsigned long inlen)
209 {
210 	unsigned long n;
211 
212 	while (inlen > 0) {
213 		if (md->sha512.curlen == 0 && inlen >= SHA512_BLOCKSIZE) {
214 			sha512_compress(md, in);
215 			md->sha512.length += SHA512_BLOCKSIZE * 8;
216 			in += SHA512_BLOCKSIZE;
217 			inlen -= SHA512_BLOCKSIZE;
218 		} else {
219 			n = MIN(inlen, (SHA512_BLOCKSIZE - md->sha512.curlen));
220 			memcpy(md->sha512.buf + md->sha512.curlen,
221 			       in, (size_t)n);
222 			md->sha512.curlen += n;
223 			in += n;
224 			inlen -= n;
225 			if (md->sha512.curlen == SHA512_BLOCKSIZE) {
226 				sha512_compress(md, md->sha512.buf);
227 				md->sha512.length += SHA512_BLOCKSIZE * 8;
228 				md->sha512.curlen = 0;
229 			}
230 		}
231 	}
232 }
233 
ext2fs_sha512(const unsigned char * in,unsigned long in_size,unsigned char out[EXT2FS_SHA512_LENGTH])234 void ext2fs_sha512(const unsigned char *in, unsigned long in_size,
235 		   unsigned char out[EXT2FS_SHA512_LENGTH])
236 {
237 	struct hash_state md;
238 
239 	sha512_init(&md);
240 	sha512_process(&md, in, in_size);
241 	sha512_done(&md, out);
242 }
243 
244 #ifdef UNITTEST
245 static const struct {
246 	char *msg;
247 	unsigned char hash[64];
248 } tests[] = {
249 	{ "",
250 	  { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
251 	    0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
252 	    0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
253 	    0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
254 	    0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
255 	    0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
256 	    0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
257 	    0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e }
258 	},
259 	{ "abc",
260 	  { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
261 	    0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
262 	    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
263 	    0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
264 	    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
265 	    0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
266 	    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
267 	    0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
268 	},
269 	{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
270 	  { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
271 	    0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
272 	    0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
273 	    0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
274 	    0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
275 	    0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
276 	    0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
277 	    0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
278 	},
279 };
280 
main(int argc,char ** argv)281 int main(int argc, char **argv)
282 {
283 	int i;
284 	int errors = 0;
285 	unsigned char tmp[64];
286 
287 	for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
288 		unsigned char *msg = (unsigned char *) tests[i].msg;
289 		int len = strlen(tests[i].msg);
290 
291 		ext2fs_sha512(msg, len, tmp);
292 		printf("SHA512 test message %d: ", i);
293 		if (memcmp(tmp, tests[i].hash, 64) != 0) {
294 			printf("FAILED\n");
295 			errors++;
296 		} else
297 			printf("OK\n");
298 	}
299 	return errors;
300 }
301 
302 #endif /* UNITTEST */
303