xref: /aosp_15_r20/external/f2fs-tools/tools/sha512.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
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