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