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