• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
_sha512_compress(hash_state * md,unsigned char * buf)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
sha512_compress(hash_state * md,unsigned char * buf)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 */
sha512_init(hash_state * md)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 */
sha512_done(hash_state * md,unsigned char * out)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 */
sha512_test(void)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