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