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