1 /* Copyright (c) (2010,2011,2015-2019,2021,2022) Apple Inc. All rights reserved.
2 *
3 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4 * is contained in the License.txt file distributed with corecrypto) and only to
5 * people who accept that license. IMPORTANT: Any license rights granted to you by
6 * Apple Inc. (if any) are limited to internal use within your organization only on
7 * devices and computers you own or control, for the sole purpose of verifying the
8 * security characteristics and correct functioning of the Apple Software. You may
9 * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
10 */
11
12 /*
13 * Parts of this code adapted from LibTomCrypt
14 *
15 * LibTomCrypt, modular cryptographic library -- Tom St Denis
16 *
17 * LibTomCrypt is a library that provides various cryptographic
18 * algorithms in a highly modular and flexible manner.
19 *
20 * The library is free for all purposes without any express
21 * guarantee it works.
22 *
23 * Tom St Denis, [email protected], http://libtom.org
24 */
25
26 #include <corecrypto/ccsha2.h>
27 #include "cc_internal.h"
28 #include "ccsha2_internal.h"
29
30 #define K ccsha512_K
31
32 /* Various logical functions */
33 #define Ch(x,y,z) (z ^ (x & (y ^ z)))
34 #define Maj(x,y,z) (((x | y) & z) | (x & y))
35 #define S(x, n) CC_ROR64c(x, n)
36 #define R(x, n) (((x) & 0xFFFFFFFFFFFFFFFF )>>((uint64_t)n))
37 #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
38 #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
39 #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
40 #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
41
42 /* compress 1024-bits */
ccsha512_ltc_compress(ccdigest_state_t state,size_t nblocks,const void * in)43 void ccsha512_ltc_compress(ccdigest_state_t state, size_t nblocks, const void *in)
44 {
45 uint64_t S[8], W[80], t0, t1;
46 int i;
47 uint64_t *s = ccdigest_u64(state);
48 const uint8_t *buf = in;
49
50 while(nblocks--) {
51 /* copy state into S */
52 for (i = 0; i < 8; i++) {
53 S[i] = s[i];
54 }
55
56 /* copy the state into 1024-bits into W[0..15] */
57 for (i = 0; i < 16; i++) {
58 W[i] = cc_load64_be(buf + (8 * i));
59 }
60
61 /* fill W[16..79] */
62 for (i = 16; i < 80; i++) {
63 W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
64 }
65
66 /* Compress */
67 #if CC_SMALL_CODE
68 for (i = 0; i < 80; i++) {
69 t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
70 t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
71 S[7] = S[6];
72 S[6] = S[5];
73 S[5] = S[4];
74 S[4] = S[3] + t0;
75 S[3] = S[2];
76 S[2] = S[1];
77 S[1] = S[0];
78 S[0] = t0 + t1;
79 }
80 #else
81 #define RND(a,b,c,d,e,f,g,h,i) \
82 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
83 t1 = Sigma0(a) + Maj(a, b, c); \
84 d += t0; \
85 h = t0 + t1;
86
87 for (i = 0; i < 80; i += 8) {
88 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
89 RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
90 RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
91 RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
92 RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
93 RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
94 RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
95 RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
96 }
97 #endif
98
99
100 /* feedback */
101 for (i = 0; i < 8; i++) {
102 s[i] = s[i] + S[i];
103 }
104
105 buf+=CCSHA512_BLOCK_SIZE;
106 }
107 }
108
ccsha512_final(const struct ccdigest_info * di,ccdigest_ctx_t ctx,unsigned char * digest)109 void ccsha512_final(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned char *digest)
110 {
111 // Sanity check to recover from ctx corruptions.
112 if (ccdigest_num(di, ctx) >= di->block_size) {
113 ccdigest_num(di, ctx) = 0;
114 }
115
116 // Clone the state.
117 ccdigest_di_decl(di, tmp);
118 cc_memcpy(tmp, ctx, ccdigest_di_size(di));
119
120 ccdigest_nbits(di, tmp) += ccdigest_num(di, tmp) << 3;
121 ccdigest_data(di, tmp)[ccdigest_num(di, tmp)++] = 0x80;
122
123 /* If we don't have at least 16 bytes (for the length) left we need to add
124 a second block. */
125 if (ccdigest_num(di, tmp) > di->block_size - 16) {
126 while (ccdigest_num(di, tmp) < di->block_size) {
127 ccdigest_data(di, tmp)[ccdigest_num(di, tmp)++] = 0;
128 }
129 di->compress(ccdigest_state(di, tmp), 1, ccdigest_data(di, tmp));
130 ccdigest_num(di, tmp) = 0;
131 }
132
133 /* Pad up to block_size minus 8 with 0s */
134 while (ccdigest_num(di, tmp) < di->block_size - 8) {
135 ccdigest_data(di, tmp)[ccdigest_num(di, tmp)++] = 0;
136 }
137
138 cc_store64_be(ccdigest_nbits(di, tmp), ccdigest_data(di, tmp) + di->block_size - 8);
139 di->compress(ccdigest_state(di, tmp), 1, ccdigest_data(di, tmp));
140
141 /* Copy output */
142 for (unsigned int i = 0; i < di->output_size / 8; i++) {
143 cc_store64_be(ccdigest_state_u64(di, tmp)[i], digest + (8 * i));
144 }
145
146 ccdigest_di_clear(di, tmp);
147 }
148