Embedded SDK
Embedded SDK
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
28 const 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
41 const 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)
56 static 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)
66 static 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)
77 cx_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)
87 cx_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 
104 static 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 
118 static 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 
165 static 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 
208 void 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
377 void cx_sha512_block(cx_sha512_t *ctx);
378 #endif
379 
380 cx_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 
429 cx_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)
467 size_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