xref: /xnu-12377.81.4/osfmk/corecrypto/ccsha512_ltc_compress.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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