2 * sha512.c --- The sha512 algorithm
4 * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
5 * (copied from libtomcrypt and then relicensed under GPLv2)
8 * This file may be redistributed under the terms of the GNU Library
9 * General Public License, version 2.
16 #include <sys/types.h>
22 static const __u64 K[80] = {
23 CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
24 CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
25 CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
26 CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
27 CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
28 CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
29 CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
30 CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
31 CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
32 CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
33 CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
34 CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
35 CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
36 CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
37 CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
38 CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
39 CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
40 CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
41 CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
42 CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
43 CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
44 CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
45 CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
46 CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
47 CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
48 CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
49 CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
50 CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
51 CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
52 CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
53 CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
54 CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
55 CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
56 CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
57 CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
58 CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
59 CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
60 CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
61 CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
62 CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
64 #define Ch(x,y,z) (z ^ (x & (y ^ z)))
65 #define Maj(x,y,z) (((x | y) & z) | (x & y))
66 #define S(x, n) ROR64c(x, n)
67 #define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)n))
68 #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
69 #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
70 #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
71 #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
72 #define RND(a,b,c,d,e,f,g,h,i)\
73 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];\
74 t1 = Sigma0(a) + Maj(a, b, c);\
77 #define STORE64H(x, y) \
79 (y)[0] = (unsigned char)(((x)>>56)&255);\
80 (y)[1] = (unsigned char)(((x)>>48)&255);\
81 (y)[2] = (unsigned char)(((x)>>40)&255);\
82 (y)[3] = (unsigned char)(((x)>>32)&255);\
83 (y)[4] = (unsigned char)(((x)>>24)&255);\
84 (y)[5] = (unsigned char)(((x)>>16)&255);\
85 (y)[6] = (unsigned char)(((x)>>8)&255);\
86 (y)[7] = (unsigned char)((x)&255); } while(0)
88 #define LOAD64H(x, y)\
90 (((__u64)((y)[0] & 255)) << 56) |\
91 (((__u64)((y)[1] & 255)) << 48) |\
92 (((__u64)((y)[2] & 255)) << 40) |\
93 (((__u64)((y)[3] & 255)) << 32) |\
94 (((__u64)((y)[4] & 255)) << 24) |\
95 (((__u64)((y)[5] & 255)) << 16) |\
96 (((__u64)((y)[6] & 255)) << 8) |\
97 (((__u64)((y)[7] & 255)));\
100 #define ROR64c(x, y) \
101 ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)(y)&CONST64(63))) | \
102 ((x)<<((__u64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
104 struct sha512_state {
105 __u64 length, state[8];
106 unsigned long curlen;
107 unsigned char buf[128];
110 /* This is a highly simplified version from libtomcrypt */
112 struct sha512_state sha512;
115 static void sha512_compress(struct hash_state * md, const unsigned char *buf)
117 __u64 S[8], W[80], t0, t1;
120 /* copy state into S */
121 for (i = 0; i < 8; i++) {
122 S[i] = md->sha512.state[i];
125 /* copy the state into 1024-bits into W[0..15] */
126 for (i = 0; i < 16; i++) {
127 LOAD64H(W[i], buf + (8*i));
131 for (i = 16; i < 80; i++) {
132 W[i] = Gamma1(W[i - 2]) + W[i - 7] +
133 Gamma0(W[i - 15]) + W[i - 16];
136 for (i = 0; i < 80; i += 8) {
137 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
138 RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
139 RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
140 RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
141 RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
142 RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
143 RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
144 RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
148 for (i = 0; i < 8; i++) {
149 md->sha512.state[i] = md->sha512.state[i] + S[i];
153 static void sha512_init(struct hash_state * md)
155 md->sha512.curlen = 0;
156 md->sha512.length = 0;
157 md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
158 md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
159 md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
160 md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
161 md->sha512.state[4] = CONST64(0x510e527fade682d1);
162 md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
163 md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
164 md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
167 static void sha512_done(struct hash_state * md, unsigned char *out)
171 /* increase the length of the message */
172 md->sha512.length += md->sha512.curlen * CONST64(8);
174 /* append the '1' bit */
175 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
177 /* if the length is currently above 112 bytes we append zeros then
178 * compress. Then we can fall back to padding zeros and length encoding
180 if (md->sha512.curlen > 112) {
181 while (md->sha512.curlen < 128) {
182 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
184 sha512_compress(md, md->sha512.buf);
185 md->sha512.curlen = 0;
188 /* pad upto 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB
189 * of the length. We assume that you won't hash > 2^64 bits of data. */
190 while (md->sha512.curlen < 120) {
191 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
195 STORE64H(md->sha512.length, md->sha512.buf + 120);
196 sha512_compress(md, md->sha512.buf);
199 for (i = 0; i < 8; i++) {
200 STORE64H(md->sha512.state[i], out+(8 * i));
204 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
205 #define SHA512_BLOCKSIZE 512
206 static void sha512_process(struct hash_state * md,
213 if (md->sha512.curlen == 0 && inlen >= SHA512_BLOCKSIZE) {
214 sha512_compress(md, in);
215 md->sha512.length += SHA512_BLOCKSIZE * 8;
216 in += SHA512_BLOCKSIZE;
217 inlen -= SHA512_BLOCKSIZE;
219 n = MIN(inlen, (SHA512_BLOCKSIZE - md->sha512.curlen));
220 memcpy(md->sha512.buf + md->sha512.curlen,
222 md->sha512.curlen += n;
225 if (md->sha512.curlen == SHA512_BLOCKSIZE) {
226 sha512_compress(md, md->sha512.buf);
227 md->sha512.length += SHA512_BLOCKSIZE * 8;
228 md->sha512.curlen = 0;
234 void ext2fs_sha512(unsigned char *in, unsigned long in_size,
235 unsigned char out[EXT2FS_SHA512_LENGTH])
237 struct hash_state md;
240 sha512_process(&md, in, in_size);
241 sha512_done(&md, out);
245 static const struct {
247 unsigned char hash[64];
250 { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
251 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
252 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
253 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
254 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
255 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
256 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
257 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e }
260 { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
261 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
262 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
263 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
264 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
265 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
266 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
267 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
269 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
270 { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
271 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
272 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
273 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
274 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
275 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
276 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
277 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
281 int main(int argc, char **argv)
285 unsigned char tmp[64];
286 struct hash_state md;
288 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
289 unsigned char *msg = (unsigned char *) tests[i].msg;
290 int len = strlen(tests[i].msg);
292 ext2fs_sha512(msg, len, tmp);
293 printf("SHA512 test message %d: ", i);
294 if (memcmp(tmp, tests[i].hash, 64) != 0) {
303 #endif /* UNITTEST */