Line data Source code
1 : /* fd_aes_ref.c was imported from the OpenSSL project circa 2023-Aug.
2 : Original source files: crypto/evp/e_aes.c crypto/modes/gcm128.c */
3 :
4 : #include "fd_aes_gcm.h"
5 :
6 : #include <assert.h>
7 :
8 8571387 : #define fd_gcm_init fd_gcm_init_4bit
9 4002031 : #define fd_gcm_gmult fd_gcm_gmult_4bit
10 80108067 : #define fd_gcm_ghash fd_gcm_ghash_4bit
11 :
12 : static void
13 : fd_aes_gcm_setiv( fd_aes_gcm_ref_t * gcm,
14 8571387 : uchar const iv[ 12 ] ) {
15 :
16 8571387 : uint ctr;
17 8571387 : gcm->len.u[ 0 ] = 0; /* AAD length */
18 8571387 : gcm->len.u[ 1 ] = 0; /* Message length */
19 8571387 : gcm->ares = 0;
20 8571387 : gcm->mres = 0;
21 :
22 8571387 : memcpy( gcm->Yi.c, iv, 12 );
23 8571387 : gcm->Yi.c[12] = 0;
24 8571387 : gcm->Yi.c[13] = 0;
25 8571387 : gcm->Yi.c[14] = 0;
26 8571387 : gcm->Yi.c[15] = 1;
27 8571387 : ctr = 1;
28 :
29 8571387 : gcm->Xi.u[0] = 0;
30 8571387 : gcm->Xi.u[1] = 0;
31 :
32 8571387 : fd_aes_encrypt( gcm->Yi.c, gcm->EK0.c, &gcm->key );
33 8571387 : ctr++;
34 :
35 8571387 : gcm->Yi.d[3] = fd_uint_bswap( ctr );
36 8571387 : }
37 :
38 : void
39 : fd_aes_128_gcm_init_ref( fd_aes_gcm_ref_t * gcm,
40 : uchar const key[ 16 ],
41 8571387 : uchar const iv[ 12 ] ) {
42 :
43 : /* TODO: Check key size */
44 :
45 8571387 : memset( gcm, 0, sizeof(fd_aes_gcm_t) );
46 :
47 8571387 : fd_aes_key_ref_t * ks = &gcm->key;
48 8571387 : fd_aes_set_encrypt_key( key, 128, ks );
49 :
50 8571387 : fd_aes_encrypt( gcm->H.c, gcm->H.c, ks );
51 8571387 : gcm->H.u[ 0 ] = fd_ulong_bswap( gcm->H.u[ 0 ] );
52 8571387 : gcm->H.u[ 1 ] = fd_ulong_bswap( gcm->H.u[ 1 ] );
53 :
54 8571387 : fd_gcm_init( gcm->Htable, gcm->H.u );
55 8571387 : fd_aes_gcm_setiv( gcm, iv );
56 8571387 : }
57 :
58 : static int
59 : fd_gcm128_aad( fd_aes_gcm_ref_t * aes_gcm,
60 : uchar const * aad,
61 8571387 : ulong aad_sz ) {
62 :
63 8571387 : ulong alen = aes_gcm->len.u[ 0 ];
64 :
65 8571387 : if( FD_UNLIKELY( aes_gcm->len.u[ 1 ] ) )
66 0 : return -2;
67 :
68 8571387 : alen += aad_sz;
69 8571387 : if (alen > (1UL<<61) || (sizeof(aad_sz) == 8 && alen < aad_sz))
70 0 : return -1;
71 8571387 : aes_gcm->len.u[0] = alen;
72 :
73 8571387 : uint n = aes_gcm->ares;
74 8571387 : if (n) {
75 0 : while (n && aad_sz) {
76 0 : aes_gcm->Xi.c[n] ^= *(aad++);
77 0 : --aad_sz;
78 0 : n = (n + 1) % 16;
79 0 : }
80 0 : if (n == 0)
81 0 : fd_gcm_gmult( aes_gcm->Xi.u, aes_gcm->Htable );
82 0 : else {
83 0 : aes_gcm->ares = n;
84 0 : return 0;
85 0 : }
86 0 : }
87 8571387 : ulong i;
88 8571387 : if ((i = (aad_sz & (ulong)-16))) {
89 6018761 : fd_gcm_ghash( aes_gcm->Xi.u, aes_gcm->Htable, aad, i );
90 6018761 : aad += i;
91 6018761 : aad_sz -= i;
92 6018761 : }
93 8571387 : if (aad_sz) {
94 8571383 : n = (unsigned int)aad_sz;
95 59590975 : for (i = 0; i < aad_sz; ++i)
96 51019592 : aes_gcm->Xi.c[i] ^= aad[i];
97 8571383 : }
98 :
99 8571387 : aes_gcm->ares = n;
100 8571387 : return 0;
101 8571387 : }
102 :
103 : /* TODO separate reference code and GCM128 */
104 :
105 : static int
106 : fd_gcm128_encrypt( fd_aes_gcm_ref_t * ctx,
107 : uchar const * in,
108 : uchar * out,
109 4416902 : ulong len ) {
110 :
111 4416902 : uint n, ctr, mres;
112 4416902 : ulong i;
113 4416902 : ulong mlen = ctx->len.u[1];
114 4416902 : void *key = &ctx->key;
115 :
116 4416902 : mlen += len;
117 4416902 : if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
118 0 : return -1;
119 4416902 : ctx->len.u[1] = mlen;
120 :
121 4416902 : mres = ctx->mres;
122 :
123 4416902 : if (ctx->ares) {
124 : /* First call to encrypt finalizes GHASH(AAD) */
125 4416902 : if (len == 0) {
126 2000065 : fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
127 2000065 : ctx->ares = 0;
128 2000065 : return 0;
129 2000065 : }
130 2416837 : memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
131 2416837 : ctx->Xi.u[0] = 0;
132 2416837 : ctx->Xi.u[1] = 0;
133 2416837 : mres = sizeof(ctx->Xi);
134 2416837 : ctx->ares = 0;
135 2416837 : }
136 :
137 2416837 : ctr = fd_uint_bswap( ctx->Yi.d[3] );
138 :
139 2416837 : n = mres % 16;
140 1548826860 : for (i = 0; i < len; ++i) {
141 1546410023 : if (n == 0) {
142 97558602 : fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
143 97558602 : ++ctr;
144 97558602 : ctx->Yi.d[3] = fd_uint_bswap( ctr );
145 97558602 : }
146 1546410023 : ctx->Xn[mres++] = out[i] = in[i] ^ ctx->EKi.c[n];
147 1546410023 : n = (n + 1) % 16;
148 1546410023 : if (mres == sizeof(ctx->Xn)) {
149 31693385 : fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
150 31693385 : mres = 0;
151 31693385 : }
152 1546410023 : }
153 :
154 2416837 : ctx->mres = mres;
155 2416837 : return 0;
156 4416902 : }
157 :
158 : static int
159 : fd_gcm128_decrypt( fd_aes_gcm_ref_t * ctx,
160 : uchar const * in,
161 : uchar * out,
162 4154485 : ulong len ) {
163 :
164 4154485 : uint n, ctr, mres;
165 4154485 : ulong i;
166 4154485 : ulong mlen = ctx->len.u[1];
167 4154485 : void * key = &ctx->key;
168 :
169 4154485 : mlen += len;
170 4154485 : if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
171 0 : return -1;
172 4154485 : ctx->len.u[1] = mlen;
173 :
174 4154485 : mres = ctx->mres;
175 :
176 4154485 : if (ctx->ares) {
177 : /* First call to decrypt finalizes GHASH(AAD) */
178 4154481 : if (len == 0) {
179 2001966 : fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
180 2001966 : ctx->ares = 0;
181 2001966 : return 0;
182 2001966 : }
183 2152515 : memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
184 2152515 : ctx->Xi.u[0] = 0;
185 2152515 : ctx->Xi.u[1] = 0;
186 2152515 : mres = sizeof(ctx->Xi);
187 2152515 : ctx->ares = 0;
188 2152515 : }
189 :
190 2152519 : ctr = fd_uint_bswap( ctx->Yi.d[3] );
191 :
192 2152519 : n = mres % 16;
193 1583788485 : for (i = 0; i < len; ++i) {
194 1581635966 : uchar c;
195 1581635966 : if (n == 0) {
196 99295343 : fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
197 99295343 : ++ctr;
198 99295343 : ctx->Yi.d[3] = fd_uint_bswap( ctr );
199 99295343 : }
200 1581635966 : out[i] = (ctx->Xn[mres++] = c = in[i]) ^ ctx->EKi.c[n];
201 1581635966 : n = (n + 1) % 16;
202 1581635966 : if (mres == sizeof(ctx->Xn)) {
203 32693714 : fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
204 32693714 : mres = 0;
205 32693714 : }
206 1581635966 : }
207 :
208 2152519 : ctx->mres = mres;
209 2152519 : return 0;
210 4154485 : }
211 :
212 : void
213 8571387 : fd_gcm128_finish( fd_aes_gcm_ref_t * ctx ) {
214 :
215 8571387 : ulong alen = ctx->len.u[0] << 3; // 176
216 8571387 : ulong clen = ctx->len.u[1] << 3; // 9296
217 :
218 8571387 : struct {
219 8571387 : ulong hi;
220 8571387 : ulong lo;
221 8571387 : } bitlen;
222 8571387 : uint mres = ctx->mres;
223 :
224 8571387 : if( mres ) {
225 4569158 : uint blocks = (mres + 15u) & 0xfffffff0u; // 16
226 :
227 4569158 : memset(ctx->Xn + mres, 0, blocks - mres);
228 4569158 : mres = blocks;
229 4569158 : if (mres == sizeof(ctx->Xn)) {
230 1130820 : fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
231 1130820 : mres = 0;
232 1130820 : }
233 4569158 : } else if( ctx->ares ) {
234 0 : fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
235 0 : }
236 :
237 8571387 : alen = fd_ulong_bswap( alen );
238 8571387 : clen = fd_ulong_bswap( clen );
239 :
240 8571387 : bitlen.hi = alen;
241 8571387 : bitlen.lo = clen;
242 8571387 : memcpy( ctx->Xn + mres, &bitlen, sizeof(bitlen) );
243 8571387 : mres += (uint)sizeof(bitlen);
244 8571387 : fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
245 :
246 8571387 : ctx->Xi.u[0] ^= ctx->EK0.u[0];
247 8571387 : ctx->Xi.u[1] ^= ctx->EK0.u[1];
248 8571387 : }
249 :
250 : void
251 : fd_aes_gcm_encrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
252 : uchar * c,
253 : uchar const * p,
254 : ulong sz,
255 : uchar const * aad,
256 : ulong aad_sz,
257 4416902 : uchar tag[ 16 ] ) {
258 :
259 4416902 : fd_gcm128_aad( aes_gcm, aad, aad_sz );
260 :
261 4416902 : ulong bulk = 0UL;
262 4416902 : assert( 0==fd_gcm128_encrypt( aes_gcm, p+bulk, c+bulk, sz-bulk ) );
263 :
264 : /* CRYPTO_gcm128_tag */
265 4416902 : fd_gcm128_finish( aes_gcm );
266 4416902 : fd_memcpy( tag, aes_gcm->Xi.c, 16 );
267 4416902 : }
268 :
269 : int
270 : fd_aes_gcm_decrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
271 : uchar const * c,
272 : uchar * p,
273 : ulong sz,
274 : uchar const * aad,
275 : ulong aad_sz,
276 4154485 : uchar const tag[ 16 ] ) {
277 :
278 4154485 : fd_gcm128_aad( aes_gcm, aad, aad_sz );
279 :
280 4154485 : ulong bulk = 0UL;
281 4154485 : assert( 0==fd_gcm128_decrypt( aes_gcm, c+bulk, p+bulk, sz-bulk ) );
282 :
283 : /* CRYPTO_gcm128_finish */
284 4154485 : fd_gcm128_finish( aes_gcm );
285 4154485 : return 0==memcmp( aes_gcm->Xi.c, tag, 16 ); /* TODO USE CONSTANT TIME COMPARE */
286 4154485 : }
|