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