Home | History | Annotate | Download | only in tools
      1 /*
      2  * sha512.c --- The sha512 algorithm
      3  *
      4  * Copyright (C) 2004 Sam Hocevar <sam (at) 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
     42 static 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 
    124 struct 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 */
    131 struct hash_state {
    132 	struct sha512_state sha512;
    133 };
    134 
    135 static 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 
    173 static 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 
    187 static 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
    226 static 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 
    254 void 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
    265 static 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 
    301 int 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 */
    324