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