1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
13 LTC_SHA512 by Tom St Denis
18 const struct ltc_hash_descriptor sha512_desc =
26 { 2, 16, 840, 1, 101, 3, 4, 2, 3, },
37 static const ulong64 K[80] = {
38 CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
39 CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
40 CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
41 CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
42 CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
43 CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
44 CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
45 CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
46 CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
47 CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
48 CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
49 CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
50 CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
51 CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
52 CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
53 CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
54 CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
55 CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
56 CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
57 CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
58 CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
59 CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
60 CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
61 CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
62 CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
63 CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
64 CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
65 CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
66 CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
67 CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
68 CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
69 CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
70 CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
71 CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
72 CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
73 CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
74 CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
75 CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
76 CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
77 CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
80 /* Various logical functions */
81 #define Ch(x,y,z) (z ^ (x & (y ^ z)))
82 #define Maj(x,y,z) (((x | y) & z) | (x & y))
83 #define S(x, n) ROR64c(x, n)
84 #define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
85 #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
86 #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
87 #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
88 #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
90 /* compress 1024-bits */
91 #ifdef LTC_CLEAN_STACK
92 static int _sha512_compress(hash_state * md, unsigned char *buf)
94 static int sha512_compress(hash_state * md, unsigned char *buf)
97 ulong64 S[8], W[80], t0, t1;
100 /* copy state into S */
101 for (i = 0; i < 8; i++) {
102 S[i] = md->sha512.state[i];
105 /* copy the state into 1024-bits into W[0..15] */
106 for (i = 0; i < 16; i++) {
107 LOAD64H(W[i], buf + (8*i));
111 for (i = 16; i < 80; i++) {
112 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
116 #ifdef LTC_SMALL_CODE
117 for (i = 0; i < 80; i++) {
118 t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
119 t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
130 #define RND(a,b,c,d,e,f,g,h,i) \
131 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
132 t1 = Sigma0(a) + Maj(a, b, c); \
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);
150 for (i = 0; i < 8; i++) {
151 md->sha512.state[i] = md->sha512.state[i] + S[i];
157 /* compress 1024-bits */
158 #ifdef LTC_CLEAN_STACK
159 static int sha512_compress(hash_state * md, unsigned char *buf)
162 err = _sha512_compress(md, buf);
163 burn_stack(sizeof(ulong64) * 90 + sizeof(int));
169 Initialize the hash state
170 @param md The hash state you wish to initialize
171 @return CRYPT_OK if successful
173 int sha512_init(hash_state * md)
175 LTC_ARGCHK(md != NULL);
176 md->sha512.curlen = 0;
177 md->sha512.length = 0;
178 md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
179 md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
180 md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
181 md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
182 md->sha512.state[4] = CONST64(0x510e527fade682d1);
183 md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
184 md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
185 md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
190 Process a block of memory though the hash
191 @param md The hash state
192 @param in The data to hash
193 @param inlen The length of the data (octets)
194 @return CRYPT_OK if successful
196 HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
199 Terminate the hash to get the digest
200 @param md The hash state
201 @param out [out] The destination of the hash (64 bytes)
202 @return CRYPT_OK if successful
204 int sha512_done(hash_state * md, unsigned char *out)
208 LTC_ARGCHK(md != NULL);
209 LTC_ARGCHK(out != NULL);
211 if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
212 return CRYPT_INVALID_ARG;
215 /* increase the length of the message */
216 md->sha512.length += md->sha512.curlen * CONST64(8);
218 /* append the '1' bit */
219 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
221 /* if the length is currently above 112 bytes we append zeros
222 * then compress. Then we can fall back to padding zeros and length
223 * encoding like normal.
225 if (md->sha512.curlen > 112) {
226 while (md->sha512.curlen < 128) {
227 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
229 sha512_compress(md, md->sha512.buf);
230 md->sha512.curlen = 0;
233 /* pad upto 120 bytes of zeroes
234 * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
235 * > 2^64 bits of data... :-)
237 while (md->sha512.curlen < 120) {
238 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
242 STORE64H(md->sha512.length, md->sha512.buf+120);
243 sha512_compress(md, md->sha512.buf);
246 for (i = 0; i < 8; i++) {
247 STORE64H(md->sha512.state[i], out+(8*i));
249 #ifdef LTC_CLEAN_STACK
250 zeromem(md, sizeof(hash_state));
257 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
259 int sha512_test(void)
264 static const struct {
266 unsigned char hash[64];
269 { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
270 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
271 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
272 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
273 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
274 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
275 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
276 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
278 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
279 { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
280 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
281 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
282 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
283 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
284 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
285 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
286 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
291 unsigned char tmp[64];
294 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
296 sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
297 sha512_done(&md, tmp);
298 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) {
299 return CRYPT_FAIL_TESTVECTOR;
311 /* ref: $Format:%D$ */
312 /* git commit: $Format:%H$ */
313 /* commit time: $Format:%ai$ */