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