1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 #include "tomcrypt.h" 12 13 /** 14 @param sha512.c 15 SHA512 by Tom St Denis 16 */ 17 18 #ifdef SHA512 19 20 const struct ltc_hash_descriptor sha512_desc = 21 { 22 "sha512", 23 5, 24 64, 25 128, 26 27 /* OID */ 28 { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, 29 9, 30 31 &sha512_init, 32 &sha512_process, 33 &sha512_done, 34 &sha512_test, 35 NULL 36 }; 37 38 /* the K array */ 39 static const ulong64 K[80] = { 40 CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), 41 CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), 42 CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), 43 CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), 44 CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), 45 CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), 46 CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), 47 CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), 48 CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), 49 CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), 50 CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), 51 CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), 52 CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), 53 CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), 54 CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), 55 CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), 56 CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), 57 CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), 58 CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), 59 CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), 60 CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), 61 CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), 62 CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), 63 CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), 64 CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), 65 CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), 66 CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), 67 CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), 68 CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), 69 CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), 70 CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), 71 CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), 72 CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), 73 CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), 74 CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), 75 CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), 76 CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), 77 CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), 78 CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), 79 CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) 80 }; 81 82 /* Various logical functions */ 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))>>((ulong64)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 92 /* compress 1024-bits */ 93 #ifdef LTC_CLEAN_STACK 94 static int _sha512_compress(hash_state * md, unsigned char *buf) 95 #else 96 static int sha512_compress(hash_state * md, unsigned char *buf) 97 #endif 98 { 99 ulong64 S[8], W[80], t0, t1; 100 int i; 101 102 /* copy state into S */ 103 for (i = 0; i < 8; i++) { 104 S[i] = md->sha512.state[i]; 105 } 106 107 /* copy the state into 1024-bits into W[0..15] */ 108 for (i = 0; i < 16; i++) { 109 LOAD64H(W[i], buf + (8*i)); 110 } 111 112 /* fill W[16..79] */ 113 for (i = 16; i < 80; i++) { 114 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; 115 } 116 117 /* Compress */ 118 #ifdef LTC_SMALL_CODE 119 for (i = 0; i < 80; i++) { 120 t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; 121 t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); 122 S[7] = S[6]; 123 S[6] = S[5]; 124 S[5] = S[4]; 125 S[4] = S[3] + t0; 126 S[3] = S[2]; 127 S[2] = S[1]; 128 S[1] = S[0]; 129 S[0] = t0 + t1; 130 } 131 #else 132 #define RND(a,b,c,d,e,f,g,h,i) \ 133 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ 134 t1 = Sigma0(a) + Maj(a, b, c); \ 135 d += t0; \ 136 h = t0 + t1; 137 138 for (i = 0; i < 80; i += 8) { 139 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); 140 RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); 141 RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); 142 RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); 143 RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); 144 RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); 145 RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); 146 RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); 147 } 148 #endif 149 150 151 /* feedback */ 152 for (i = 0; i < 8; i++) { 153 md->sha512.state[i] = md->sha512.state[i] + S[i]; 154 } 155 156 return CRYPT_OK; 157 } 158 159 /* compress 1024-bits */ 160 #ifdef LTC_CLEAN_STACK 161 static int sha512_compress(hash_state * md, unsigned char *buf) 162 { 163 int err; 164 err = _sha512_compress(md, buf); 165 burn_stack(sizeof(ulong64) * 90 + sizeof(int)); 166 return err; 167 } 168 #endif 169 170 /** 171 Initialize the hash state 172 @param md The hash state you wish to initialize 173 @return CRYPT_OK if successful 174 */ 175 int sha512_init(hash_state * md) 176 { 177 LTC_ARGCHK(md != NULL); 178 md->sha512.curlen = 0; 179 md->sha512.length = 0; 180 md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); 181 md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); 182 md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); 183 md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); 184 md->sha512.state[4] = CONST64(0x510e527fade682d1); 185 md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); 186 md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); 187 md->sha512.state[7] = CONST64(0x5be0cd19137e2179); 188 return CRYPT_OK; 189 } 190 191 /** 192 Process a block of memory though the hash 193 @param md The hash state 194 @param in The data to hash 195 @param inlen The length of the data (octets) 196 @return CRYPT_OK if successful 197 */ 198 HASH_PROCESS(sha512_process, sha512_compress, sha512, 128) 199 200 /** 201 Terminate the hash to get the digest 202 @param md The hash state 203 @param out [out] The destination of the hash (64 bytes) 204 @return CRYPT_OK if successful 205 */ 206 int sha512_done(hash_state * md, unsigned char *out) 207 { 208 int i; 209 210 LTC_ARGCHK(md != NULL); 211 LTC_ARGCHK(out != NULL); 212 213 if (md->sha512.curlen >= sizeof(md->sha512.buf)) { 214 return CRYPT_INVALID_ARG; 215 } 216 217 /* increase the length of the message */ 218 md->sha512.length += md->sha512.curlen * CONST64(8); 219 220 /* append the '1' bit */ 221 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; 222 223 /* if the length is currently above 112 bytes we append zeros 224 * then compress. Then we can fall back to padding zeros and length 225 * encoding like normal. 226 */ 227 if (md->sha512.curlen > 112) { 228 while (md->sha512.curlen < 128) { 229 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; 230 } 231 sha512_compress(md, md->sha512.buf); 232 md->sha512.curlen = 0; 233 } 234 235 /* pad upto 120 bytes of zeroes 236 * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash 237 * > 2^64 bits of data... :-) 238 */ 239 while (md->sha512.curlen < 120) { 240 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; 241 } 242 243 /* store length */ 244 STORE64H(md->sha512.length, md->sha512.buf+120); 245 sha512_compress(md, md->sha512.buf); 246 247 /* copy output */ 248 for (i = 0; i < 8; i++) { 249 STORE64H(md->sha512.state[i], out+(8*i)); 250 } 251 #ifdef LTC_CLEAN_STACK 252 zeromem(md, sizeof(hash_state)); 253 #endif 254 return CRYPT_OK; 255 } 256 257 /** 258 Self-test the hash 259 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 260 */ 261 int sha512_test(void) 262 { 263 #ifndef LTC_TEST 264 return CRYPT_NOP; 265 #else 266 static const struct { 267 char *msg; 268 unsigned char hash[64]; 269 } tests[] = { 270 { "abc", 271 { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 272 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 273 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 274 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 275 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 276 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 277 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 278 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } 279 }, 280 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 281 { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 282 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 283 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 284 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 285 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 286 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 287 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 288 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } 289 }, 290 }; 291 292 int i; 293 unsigned char tmp[64]; 294 hash_state md; 295 296 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { 297 sha512_init(&md); 298 sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 299 sha512_done(&md, tmp); 300 if (XMEMCMP(tmp, tests[i].hash, 64) != 0) { 301 return CRYPT_FAIL_TESTVECTOR; 302 } 303 } 304 return CRYPT_OK; 305 #endif 306 } 307 308 #ifdef SHA384 309 #include "sha384.c" 310 #endif 311 312 #endif 313 314 315 316 317 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha512.c,v $ */ 318 /* $Revision: 1.8 $ */ 319 /* $Date: 2006/11/01 09:28:17 $ */ 320