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