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