1 /* sha512.c - TinyCrypt SHA-512 crypto hash algorithm implementation */
2
3 /*
4 * Copyright (C) 2020 by Intel Corporation, All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * - Neither the name of Intel Corporation nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <tinycrypt/sha512.h>
34 #include <tinycrypt/constants.h>
35 #include <tinycrypt/utils.h>
36
37 static void compress(uint64_t *iv, const uint8_t *data);
38
tc_sha512_init(TCSha512State_t s)39 int tc_sha512_init(TCSha512State_t s)
40 {
41 /* input sanity check: */
42 if (s == (TCSha512State_t) 0) {
43 return TC_CRYPTO_FAIL;
44 }
45
46 /*
47 * Setting the initial state values.
48 * These values correspond to the first 64 bits of the fractional parts
49 * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
50 * and 19.
51 */
52 _set((uint8_t *) s, 0x00, sizeof(*s));
53 s->iv[0] = 0x6a09e667f3bcc908;
54 s->iv[1] = 0xbb67ae8584caa73b;
55 s->iv[2] = 0x3c6ef372fe94f82b;
56 s->iv[3] = 0xa54ff53a5f1d36f1;
57 s->iv[4] = 0x510e527fade682d1;
58 s->iv[5] = 0x9b05688c2b3e6c1f;
59 s->iv[6] = 0x1f83d9abfb41bd6b;
60 s->iv[7] = 0x5be0cd19137e2179;
61
62 return TC_CRYPTO_SUCCESS;
63 }
64
tc_sha512_update(TCSha512State_t s,const uint8_t * data,size_t datalen)65 int tc_sha512_update(TCSha512State_t s, const uint8_t *data, size_t datalen)
66 {
67 /* input sanity check: */
68 if (s == (TCSha512State_t) 0 || data == (void *) 0) {
69 return TC_CRYPTO_FAIL;
70 } else if (datalen == 0) {
71 return TC_CRYPTO_SUCCESS;
72 }
73
74 while (datalen-- > 0) {
75 s->leftover[s->leftover_offset++] = *(data++);
76 if (s->leftover_offset >= TC_SHA512_BLOCK_SIZE) {
77 compress(s->iv, s->leftover);
78 s->leftover_offset = 0;
79 s->bits_hashed += (TC_SHA512_BLOCK_SIZE << 3);
80 }
81 }
82
83 return TC_CRYPTO_SUCCESS;
84 }
85
tc_sha512_final(uint8_t * digest,TCSha512State_t s)86 int tc_sha512_final(uint8_t *digest, TCSha512State_t s)
87 {
88 unsigned int i;
89
90 /* input sanity check: */
91 if (digest == (uint8_t *) 0 || s == (TCSha512State_t) 0) {
92 return TC_CRYPTO_FAIL;
93 }
94
95 s->bits_hashed += (s->leftover_offset << 3);
96
97 s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
98 if (s->leftover_offset > (sizeof(s->leftover) - 16)) {
99 /* there is not room for all the padding in this block */
100 _set(s->leftover + s->leftover_offset, 0x00,
101 sizeof(s->leftover) - s->leftover_offset);
102 compress(s->iv, s->leftover);
103 s->leftover_offset = 0;
104 }
105
106 /*
107 * add the padding and the length in big-Endian format
108 *
109 * NOTE: SHA-512 uses 128 bits for the length of the message, but the
110 * current implementation is only using 64 bits for size, leaving the
111 * 64 "upper" bits zeroed.
112 */
113 _set(s->leftover + s->leftover_offset, 0x00,
114 sizeof(s->leftover) - 8 - s->leftover_offset);
115 s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
116 s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
117 s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
118 s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
119 s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
120 s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
121 s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
122 s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
123
124 /* hash the padding and length */
125 compress(s->iv, s->leftover);
126
127 /* copy the iv out to digest */
128 for (i = 0; i < TC_SHA512_STATE_BLOCKS; ++i) {
129 uint64_t t = *((uint64_t *) &s->iv[i]);
130 *digest++ = (uint8_t)(t >> 56);
131 *digest++ = (uint8_t)(t >> 48);
132 *digest++ = (uint8_t)(t >> 40);
133 *digest++ = (uint8_t)(t >> 32);
134 *digest++ = (uint8_t)(t >> 24);
135 *digest++ = (uint8_t)(t >> 16);
136 *digest++ = (uint8_t)(t >> 8);
137 *digest++ = (uint8_t)(t);
138 }
139
140 /* destroy the current state */
141 _set(s, 0, sizeof(*s));
142
143 return TC_CRYPTO_SUCCESS;
144 }
145
146 /*
147 * Initializing SHA-512 Hash constant words K.
148 * These values correspond to the first 64 bits of the fractional parts of the
149 * cube roots of the first 80 primes between 2 and 409.
150 */
151 static const uint64_t k512[80] = {
152 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
153 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
154 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
155 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
156 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
157 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
158 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
159 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
160 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
161 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
162 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
163 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
164 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
165 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
166 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
167 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
168 };
169
ROTR(uint64_t a,uint64_t n)170 static inline uint64_t ROTR(uint64_t a, uint64_t n)
171 {
172 return (((a) >> n) | ((a) << (64 - n)));
173 }
174
175 #define Sigma0(a)(ROTR((a), 28) ^ ROTR((a), 34) ^ ROTR((a), 39))
176 #define Sigma1(a)(ROTR((a), 14) ^ ROTR((a), 18) ^ ROTR((a), 41))
177 #define sigma0(a)(ROTR((a), 1) ^ ROTR((a), 8) ^ ((a) >> 7))
178 #define sigma1(a)(ROTR((a), 19) ^ ROTR((a), 61) ^ ((a) >> 6))
179
180 #define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
181 #define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
182
BigEndian(const uint8_t ** c)183 static inline uint64_t BigEndian(const uint8_t **c)
184 {
185 uint64_t n = 0;
186
187 n = (uint64_t)(*((*c)++)) << 56;
188 n |= (uint64_t)(*((*c)++)) << 48;
189 n |= (uint64_t)(*((*c)++)) << 40;
190 n |= (uint64_t)(*((*c)++)) << 32;
191 n |= (uint64_t)(*((*c)++)) << 24;
192 n |= (uint64_t)(*((*c)++)) << 16;
193 n |= (uint64_t)(*((*c)++)) << 8;
194 n |= (uint64_t)(*((*c)++));
195 return n;
196 }
197
compress(uint64_t * iv,const uint8_t * data)198 static void compress(uint64_t *iv, const uint8_t *data)
199 {
200 uint64_t a, b, c, d, e, f, g, h;
201 uint64_t s0, s1;
202 uint64_t t1, t2;
203 uint64_t work_space[16];
204 uint64_t n;
205 unsigned int i;
206
207 a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
208 e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
209
210 for (i = 0; i < 16; ++i) {
211 n = BigEndian(&data);
212 t1 = work_space[i] = n;
213 t1 += h + Sigma1(e) + Ch(e, f, g) + k512[i];
214 t2 = Sigma0(a) + Maj(a, b, c);
215 h = g; g = f; f = e; e = d + t1;
216 d = c; c = b; b = a; a = t1 + t2;
217 }
218
219 for ( ; i < 80; ++i) {
220 s0 = work_space[(i+1)&0x0f];
221 s0 = sigma0(s0);
222 s1 = work_space[(i+14)&0x0f];
223 s1 = sigma1(s1);
224
225 t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
226 t1 += h + Sigma1(e) + Ch(e, f, g) + k512[i];
227 t2 = Sigma0(a) + Maj(a, b, c);
228 h = g; g = f; f = e; e = d + t1;
229 d = c; c = b; b = a; a = t1 + t2;
230 }
231
232 iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
233 iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
234 }
235