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