Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_sha512.c
Go to the documentation of this file.
1
2/*******************************************************************************
3 * Ledger Nano S - Secure firmware
4 * (c) 2022 Ledger
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 ********************************************************************************/
18
19#if defined(HAVE_SHA512) || defined(HAVE_SHA384)
20
21#include "cx_ram.h"
22#include "cx_sha512.h"
23#include "cx_utils.h"
24
25#include <string.h>
26
27#ifdef HAVE_SHA384
28const cx_hash_info_t cx_sha384_info
29 = {CX_SHA384,
30 CX_SHA384_SIZE,
31 SHA512_BLOCK_SIZE,
32 sizeof(cx_sha512_t),
33 (cx_err_t(*)(cx_hash_t * ctx)) cx_sha384_init_no_throw,
34 (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha512_update,
35 (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha512_final,
36 NULL,
37 NULL};
38#endif // HAVE_SHA384
39
40#ifdef HAVE_SHA512
41const cx_hash_info_t cx_sha512_info
42 = {CX_SHA512,
43 CX_SHA512_SIZE,
44 SHA512_BLOCK_SIZE,
45 sizeof(cx_sha512_t),
46 (cx_err_t(*)(cx_hash_t * ctx)) cx_sha512_init_no_throw,
47 (cx_err_t(*)(cx_hash_t * ctx, const uint8_t *data, size_t len)) cx_sha512_update,
48 (cx_err_t(*)(cx_hash_t * ctx, uint8_t *digest)) cx_sha512_final,
49 NULL,
50 NULL};
51#endif // HAVE_SHA512
52
53#ifndef HAVE_SHA512_WITH_INIT_ALT_METHOD
54
55#if defined(HAVE_SHA384)
56static const uint64bits_t hzero_384[] = {_64BITS(0xcbbb9d5d, 0xc1059ed8),
57 _64BITS(0x629a292a, 0x367cd507),
58 _64BITS(0x9159015a, 0x3070dd17),
59 _64BITS(0x152fecd8, 0xf70e5939),
60 _64BITS(0x67332667, 0xffc00b31),
61 _64BITS(0x8eb44a87, 0x68581511),
62 _64BITS(0xdb0c2e0d, 0x64f98fa7),
63 _64BITS(0x47b5481d, 0xbefa4fa4)};
64#endif
65#if defined(HAVE_SHA512)
66static const uint64bits_t hzero[] = {_64BITS(0x6a09e667, 0xf3bcc908),
67 _64BITS(0xbb67ae85, 0x84caa73b),
68 _64BITS(0x3c6ef372, 0xfe94f82b),
69 _64BITS(0xa54ff53a, 0x5f1d36f1),
70 _64BITS(0x510e527f, 0xade682d1),
71 _64BITS(0x9b05688c, 0x2b3e6c1f),
72 _64BITS(0x1f83d9ab, 0xfb41bd6b),
73 _64BITS(0x5be0cd19, 0x137e2179)};
74#endif
75
76#if defined(HAVE_SHA384)
77cx_err_t cx_sha384_init_no_throw(cx_sha512_t *hash)
78{
79 memset(hash, 0, sizeof(cx_sha512_t));
80 hash->header.info = &cx_sha384_info;
81 memmove(hash->acc, hzero_384, sizeof(hzero_384));
82 return CX_OK;
83}
84#endif
85
86#if defined(HAVE_SHA512)
87cx_err_t cx_sha512_init_no_throw(cx_sha512_t *hash)
88{
89 memset(hash, 0, sizeof(cx_sha512_t));
90 hash->header.info = &cx_sha512_info;
91 memmove(hash->acc, hzero, sizeof(hzero));
92 return CX_OK;
93}
94#endif
95#endif // HAVE_SHA512_WITH_INIT_ALT_METHOD
96
97#ifndef HAVE_SHA512_WITH_BLOCK_ALT_METHOD
98
99#ifndef NATIVE_64BITS // NO 64BITS natively supported by the compiler
100
101#define rotR64(x, n) cx_rotr64(&x, n)
102#define shR64(x, n) cx_shr64(&x, n)
103
104static void sig512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c)
105{
106 uint64bits_t x1, x2, x3;
107
108 ASSIGN64(x1, *x);
109 ASSIGN64(x2, *x);
110 ASSIGN64(x3, *x);
111 rotR64(x1, a);
112 rotR64(x2, b);
113 shR64(x3, c);
114 x->l = x1.l ^ x2.l ^ x3.l;
115 x->h = x1.h ^ x2.h ^ x3.h;
116}
117
118static void sum512(uint64bits_t *x, uint8_t a, uint8_t b, uint8_t c)
119{
120 uint64bits_t x1, x2, x3;
121
122 ASSIGN64(x1, *x);
123 ASSIGN64(x2, *x);
124 ASSIGN64(x3, *x);
125 rotR64((x1), a);
126 rotR64((x2), b);
127 rotR64((x3), c);
128 x->l = x1.l ^ x2.l ^ x3.l;
129 x->h = x1.h ^ x2.h ^ x3.h;
130}
131#define sigma0(x) sig512(&x, 1, 8, 7)
132#define sigma1(x) sig512(&x, 19, 61, 6)
133#define sum0(x) sum512(&x, 28, 34, 39)
134#define sum1(x) sum512(&x, 14, 18, 41)
135
136// ( ((x) & (y)) ^ (~(x) & (z)) )
137#define ch(r, x, y, z) \
138 r.l = ((x.l) & (y.l)) ^ (~(x.l) & (z.l)); \
139 r.h = ((x.h) & (y.h)) ^ (~(x.h) & (z.h))
140
141//( ((x) & (y)) ^ ( (x) & (z)) ^ ((y) & (z)) )
142#define maj(r, x, y, z) \
143 r.l = ((x.l) & (y.l)) ^ ((x.l) & (z.l)) ^ ((y.l) & (z.l)); \
144 r.h = ((x.h) & (y.h)) ^ ((x.h) & (z.h)) ^ ((y.h) & (z.h))
145
146#else // NATIVE_64BITS
147
148#define rotR64(x, n) cx_rotr64(x, n)
149#define shR64(x, n) cx_shr64(x, n)
150
151#define sig512(x, a, b, c) (rotR64((x), a) ^ rotR64((x), b) ^ shR64((x), c))
152
153#define sum512(x, a, b, c) (rotR64((x), a) ^ rotR64((x), b) ^ rotR64((x), c))
154
155#define sigma0(x) sig512(x, 1, 8, 7)
156#define sigma1(x) sig512(x, 19, 61, 6)
157#define sum0(x) sum512(x, 28, 34, 39)
158#define sum1(x) sum512(x, 14, 18, 41)
159
160#define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
161#define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
162
163#endif // NATIVE_64BITS?
164
165static const uint64bits_t primeSqrt[] = {
166
167 _64BITS(0x428a2f98, 0xd728ae22), _64BITS(0x71374491, 0x23ef65cd),
168 _64BITS(0xb5c0fbcf, 0xec4d3b2f), _64BITS(0xe9b5dba5, 0x8189dbbc),
169 _64BITS(0x3956c25b, 0xf348b538), _64BITS(0x59f111f1, 0xb605d019),
170 _64BITS(0x923f82a4, 0xaf194f9b), _64BITS(0xab1c5ed5, 0xda6d8118),
171 _64BITS(0xd807aa98, 0xa3030242), _64BITS(0x12835b01, 0x45706fbe),
172 _64BITS(0x243185be, 0x4ee4b28c), _64BITS(0x550c7dc3, 0xd5ffb4e2),
173 _64BITS(0x72be5d74, 0xf27b896f), _64BITS(0x80deb1fe, 0x3b1696b1),
174 _64BITS(0x9bdc06a7, 0x25c71235), _64BITS(0xc19bf174, 0xcf692694),
175 _64BITS(0xe49b69c1, 0x9ef14ad2), _64BITS(0xefbe4786, 0x384f25e3),
176 _64BITS(0x0fc19dc6, 0x8b8cd5b5), _64BITS(0x240ca1cc, 0x77ac9c65),
177 _64BITS(0x2de92c6f, 0x592b0275), _64BITS(0x4a7484aa, 0x6ea6e483),
178 _64BITS(0x5cb0a9dc, 0xbd41fbd4), _64BITS(0x76f988da, 0x831153b5),
179 _64BITS(0x983e5152, 0xee66dfab), _64BITS(0xa831c66d, 0x2db43210),
180 _64BITS(0xb00327c8, 0x98fb213f), _64BITS(0xbf597fc7, 0xbeef0ee4),
181 _64BITS(0xc6e00bf3, 0x3da88fc2), _64BITS(0xd5a79147, 0x930aa725),
182 _64BITS(0x06ca6351, 0xe003826f), _64BITS(0x14292967, 0x0a0e6e70),
183 _64BITS(0x27b70a85, 0x46d22ffc), _64BITS(0x2e1b2138, 0x5c26c926),
184 _64BITS(0x4d2c6dfc, 0x5ac42aed), _64BITS(0x53380d13, 0x9d95b3df),
185 _64BITS(0x650a7354, 0x8baf63de), _64BITS(0x766a0abb, 0x3c77b2a8),
186 _64BITS(0x81c2c92e, 0x47edaee6), _64BITS(0x92722c85, 0x1482353b),
187 _64BITS(0xa2bfe8a1, 0x4cf10364), _64BITS(0xa81a664b, 0xbc423001),
188 _64BITS(0xc24b8b70, 0xd0f89791), _64BITS(0xc76c51a3, 0x0654be30),
189 _64BITS(0xd192e819, 0xd6ef5218), _64BITS(0xd6990624, 0x5565a910),
190 _64BITS(0xf40e3585, 0x5771202a), _64BITS(0x106aa070, 0x32bbd1b8),
191 _64BITS(0x19a4c116, 0xb8d2d0c8), _64BITS(0x1e376c08, 0x5141ab53),
192 _64BITS(0x2748774c, 0xdf8eeb99), _64BITS(0x34b0bcb5, 0xe19b48a8),
193 _64BITS(0x391c0cb3, 0xc5c95a63), _64BITS(0x4ed8aa4a, 0xe3418acb),
194 _64BITS(0x5b9cca4f, 0x7763e373), _64BITS(0x682e6ff3, 0xd6b2b8a3),
195 _64BITS(0x748f82ee, 0x5defb2fc), _64BITS(0x78a5636f, 0x43172f60),
196 _64BITS(0x84c87814, 0xa1f0ab72), _64BITS(0x8cc70208, 0x1a6439ec),
197 _64BITS(0x90befffa, 0x23631e28), _64BITS(0xa4506ceb, 0xde82bde9),
198 _64BITS(0xbef9a3f7, 0xb2c67915), _64BITS(0xc67178f2, 0xe372532b),
199 _64BITS(0xca273ece, 0xea26619c), _64BITS(0xd186b8c7, 0x21c0c207),
200 _64BITS(0xeada7dd6, 0xcde0eb1e), _64BITS(0xf57d4f7f, 0xee6ed178),
201 _64BITS(0x06f067aa, 0x72176fba), _64BITS(0x0a637dc5, 0xa2c898a6),
202 _64BITS(0x113f9804, 0xbef90dae), _64BITS(0x1b710b35, 0x131c471b),
203 _64BITS(0x28db77f5, 0x23047d84), _64BITS(0x32caab7b, 0x40c72493),
204 _64BITS(0x3c9ebe0a, 0x15c9bebc), _64BITS(0x431d67c4, 0x9c100d4c),
205 _64BITS(0x4cc5d4be, 0xcb3e42b6), _64BITS(0x597f299c, 0xfc657e2a),
206 _64BITS(0x5fcb6fab, 0x3ad6faec), _64BITS(0x6c44198c, 0x4a475817)};
207
208void cx_sha512_block(cx_sha512_t *hash)
209{
210 uint8_t j;
211 uint64bits_t t1, t2;
212
213 uint64bits_t *accumulator;
214 uint64bits_t *X;
215 struct {
216 uint64bits_t a, b, c, d, e, f, g, h;
217 } ACC;
218#define A ACC.a
219#define B ACC.b
220#define C ACC.c
221#define D ACC.d
222#define E ACC.e
223#define F ACC.f
224#define G ACC.g
225#define H ACC.h
226
227 X = (uint64bits_t *) (&hash->block[0]);
228 accumulator = (uint64bits_t *) (&hash->acc[0]); // only work because of indexing zero!
229 A = accumulator[0];
230 B = accumulator[1];
231 C = accumulator[2];
232 D = accumulator[3];
233 E = accumulator[4];
234 F = accumulator[5];
235 G = accumulator[6];
236 H = accumulator[7];
237
238#ifdef ARCH_LITTLE_ENDIAN
239 cx_swap_buffer64(X, 16);
240#endif
241
242 // init
243 /*
244 * T1 = Sum_1_512(e) + Chg(e,f,g) + K_t_512 + Wt
245 * T2 = Sum_0_512(a) + Maj(abc)
246 * h = g ;
247 * g = f;
248 * f = e;
249 * e = d + T1;
250 * d = c;
251 * c = b;
252 * b = a;
253 * a = T1 + T2;
254 */
255 for (j = 0; j < 80; j++) {
256#ifndef NATIVE_64BITS
257 uint64bits_t r;
258
259 /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15)
260 * + Xj-16 ). */
261 if (j >= 16) {
262 // sigma1(X[(j-2) & 0xF])
263 ASSIGN64(t2, X[(j - 2) & 0xF]);
264 sigma1(t2);
265 //+ X[(j-7) & 0xF]
266 ADD64(t2, X[(j - 7) & 0xF]);
267 //+ sigma0(X[(j-15) & 0xF]
268 ASSIGN64(t1, X[(j - 15) & 0xF]);
269 sigma0(t1);
270 ADD64(t2, t1);
271 //+ X[(j-16) & 0xF])
272 ADD64(t2, X[(j - 16) & 0xF]);
273 // assign
274 ASSIGN64(X[j & 0xF], t2);
275 }
276
278 // H
279 ASSIGN64(t1, H);
280 //+sum1(E)
281 ASSIGN64(r, E);
282 sum1(r);
283 ADD64(t1, r);
284 //+ch(E,F,G)
285 ch(r, E, F, G);
286 ADD64(t1, r);
287 //+primeSqrt[j]
288 ASSIGN64(r, primeSqrt[j]);
289 ADD64(t1, r); // ADD64(t1,primeSqrt[j]);
290 //+X[j&0xF]
291 ADD64(t1, X[j & 0xF]);
292
294 // sum0(A)
295 ASSIGN64(t2, A);
296 sum0(t2);
297 //+maj(A,B,C);
298 maj(r, A, B, C);
299 ADD64(t2, r);
300
301 /*
302 H = G ;
303 G = F;
304 F = E;
305 E = D+t1;
306 D = C;
307 C = B;
308 B = A;
309 A = t1+t2;
310 */
311 memmove(&ACC[1], &ACC[0], sizeof(ACC) - sizeof(uint64bits_t));
312 // E += t1;
313 ADD64(E, t1);
314 // A = t1+t2;
315 ASSIGN64(A, t1);
316 ADD64(A, t2);
317#else // no NATIVE_64BITS
318 /* for j in 16 to 63, Xj <- (Sigma_1_512( Xj-2) + Xj-7 + Sigma_0_512(Xj-15)
319 * + Xj-16 ). */
320 if (j >= 16) {
321 uint64bits_t xj2, xj15;
322 xj2 = X[(j - 2) & 0xF];
323 xj15 = X[(j - 15) & 0xF];
324 X[j & 0xF] = (sigma1(xj2) + X[(j - 7) & 0xF] + sigma0(xj15) + X[(j - 16) & 0xF]);
325 }
326 t1 = H + sum1(E) + ch(E, F, G) + primeSqrt[j] + X[j & 0xF];
327 t2 = sum0(A) + maj(A, B, C);
328
329 /*
330 H = G ;
331 G = F;
332 F = E;
333 E = D+t1;
334 D = C;
335 C = B;
336 B = A;
337 A = t1+t2;
338 */
339 H = G;
340 G = F;
341 F = E;
342 E = D;
343 D = C;
344 C = B;
345 B = A;
346 E += t1;
347 A = t1 + t2;
348
349#endif // NATIVE_64BITS?
350 }
351
352 //(update chaining values) (H1 , H2 , H3 , H4 ) <- (H1 + A, H2 + B, H3 + C, H4
353 //+ D...)
354
355#ifndef NATIVE_64BITS
356 ADD64(accumulator[0], A);
357 ADD64(accumulator[1], B);
358 ADD64(accumulator[2], C);
359 ADD64(accumulator[3], D);
360 ADD64(accumulator[4], E);
361 ADD64(accumulator[5], F);
362 ADD64(accumulator[6], G);
363 ADD64(accumulator[7], H);
364#else
365 accumulator[0] += A;
366 accumulator[1] += B;
367 accumulator[2] += C;
368 accumulator[3] += D;
369 accumulator[4] += E;
370 accumulator[5] += F;
371 accumulator[6] += G;
372 accumulator[7] += H;
373
374#endif
375}
376#else
377void cx_sha512_block(cx_sha512_t *ctx);
378#endif
379
380cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len)
381{
382 size_t r;
383 uint8_t block_size;
384 uint8_t *block;
385 size_t blen;
386
387 if (ctx == NULL) {
388 return CX_INVALID_PARAMETER;
389 }
390
391 if (data == NULL) {
392 if (len == 0) {
393 return CX_OK;
394 }
395 else {
396 return CX_INVALID_PARAMETER;
397 }
398 }
399
400 block_size = 128;
401 block = ctx->block;
402 blen = ctx->blen;
403 ctx->blen = 0;
404
405 // --- append input data and process all blocks ---
406 if ((blen + len) >= block_size) {
407 r = block_size - blen;
408 do {
409 if (ctx->header.counter == CX_HASH_MAX_BLOCK_COUNT) {
410 return CX_INVALID_PARAMETER;
411 }
412 memcpy(block + blen, data, r);
413 cx_sha512_block(ctx);
414 blen = 0;
415 ctx->header.counter++;
416 data += r;
417 len -= r;
418 r = block_size;
419 } while (len >= block_size);
420 }
421
422 // --- remind rest data---
423 memcpy(block + blen, data, len);
424 blen += len;
425 ctx->blen = blen;
426 return CX_OK;
427}
428
429cx_err_t cx_sha512_final(cx_sha512_t *ctx, uint8_t *digest)
430{
431 uint64_t bitlen;
432 size_t len;
433
434 uint8_t *block = ctx->block;
435 unsigned int blen = ctx->blen;
436 uint8_t *acc = ctx->acc;
437
438 // one more block?
439 block[blen] = 0x80;
440 blen++;
441
442 bitlen = (((uint64_t) ctx->header.counter) * 128UL + (uint64_t) blen - 1UL) * 8UL;
443 // one more block?
444 if ((128 - blen) < 16) {
445 memset(block + blen, 0, 128 - blen);
446 cx_sha512_block(ctx);
447 blen = 0;
448 }
449 // last block!
450 memset(block + blen, 0, 128 - blen);
451#ifdef ARCH_LITTLE_ENDIAN
452 (*(uint64_t *) (&block[128 - 8])) = cx_swap_uint64(bitlen);
453#else
454 (*(uint64_t *) (&block[128 - 8])) = bitlen;
455#endif
456 cx_sha512_block(ctx);
457 // provide result
458 len = (ctx->header.info->md_type == CX_SHA512) ? 512 >> 3 : 384 >> 3;
459#ifdef ARCH_LITTLE_ENDIAN
460 cx_swap_buffer64((uint64bits_t *) acc, 8);
461#endif
462 memcpy(digest, acc, len);
463 return CX_OK;
464}
465
466#if defined(HAVE_SHA512)
467size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len)
468{
469 if (out_len < CX_SHA512_SIZE) {
470 return 0;
471 }
472 cx_sha512_init_no_throw(&G_cx.sha512);
473 if (cx_sha512_update(&G_cx.sha512, in, in_len) != CX_OK) {
474 return 0;
475 }
476 cx_sha512_final(&G_cx.sha512, out);
477 explicit_bzero(&G_cx.sha512, sizeof(cx_sha512_t));
478 return CX_SHA512_SIZE;
479}
480#endif
481
482#endif // defined (HAVE_SHA512) || defined(HAVE_SHA384)
union cx_u G_cx
Definition cx_ram.c:21
void cx_swap_buffer64(uint64bits_t *v, int len)
Definition cx_utils.c:140
void cx_swap_uint64(uint64bits_t *v)
Definition cx_utils.c:118
#define ADD64(x, y)
Definition cx_utils.h:62
#define ASSIGN64(r, x)
Definition cx_utils.h:63
#define _64BITS(h, l)
Definition cx_utils.h:53
64-bit types, native or by-hands, depending on target and/or compiler support.
Definition lcx_common.h:49
uint32_t l
32 least significant bits
Definition lcx_common.h:51
uint32_t h
32 most significant bits
Definition lcx_common.h:52
unsigned char uint8_t
Definition usbd_conf.h:53