blob: 5b628c87745a3b34b80675cc5f2c12f23d76be4f [file] [log] [blame]
Damjan Marionb47376f2023-03-15 11:42:06 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2023 Cisco Systems, Inc.
3 */
4
5#ifndef __crypto_aes_gcm_h__
6#define __crypto_aes_gcm_h__
7
8#include <vppinfra/clib.h>
9#include <vppinfra/vector.h>
10#include <vppinfra/cache.h>
11#include <vppinfra/string.h>
12#include <vppinfra/crypto/aes.h>
13#include <vppinfra/crypto/ghash.h>
14
15#define NUM_HI 36
Damjan Marion9caef2a2024-01-08 19:05:40 +000016#if N_AES_LANES == 4
Damjan Marionb47376f2023-03-15 11:42:06 +000017typedef u8x64u aes_ghash_t;
Damjan Marionb47376f2023-03-15 11:42:06 +000018#define aes_gcm_splat(v) u8x64_splat (v)
Damjan Marionb47376f2023-03-15 11:42:06 +000019#define aes_gcm_ghash_reduce(c) ghash4_reduce (&(c)->gd)
20#define aes_gcm_ghash_reduce2(c) ghash4_reduce2 (&(c)->gd)
21#define aes_gcm_ghash_final(c) (c)->T = ghash4_final (&(c)->gd)
Damjan Marion9caef2a2024-01-08 19:05:40 +000022#elif N_AES_LANES == 2
Damjan Marionb47376f2023-03-15 11:42:06 +000023typedef u8x32u aes_ghash_t;
Damjan Marionb47376f2023-03-15 11:42:06 +000024#define aes_gcm_splat(v) u8x32_splat (v)
Damjan Marionb47376f2023-03-15 11:42:06 +000025#define aes_gcm_ghash_reduce(c) ghash2_reduce (&(c)->gd)
26#define aes_gcm_ghash_reduce2(c) ghash2_reduce2 (&(c)->gd)
27#define aes_gcm_ghash_final(c) (c)->T = ghash2_final (&(c)->gd)
28#else
Damjan Marionb47376f2023-03-15 11:42:06 +000029typedef u8x16 aes_ghash_t;
Damjan Marionb47376f2023-03-15 11:42:06 +000030#define aes_gcm_splat(v) u8x16_splat (v)
Damjan Marionb47376f2023-03-15 11:42:06 +000031#define aes_gcm_ghash_reduce(c) ghash_reduce (&(c)->gd)
32#define aes_gcm_ghash_reduce2(c) ghash_reduce2 (&(c)->gd)
33#define aes_gcm_ghash_final(c) (c)->T = ghash_final (&(c)->gd)
34#endif
Damjan Marionb47376f2023-03-15 11:42:06 +000035
36typedef enum
37{
38 AES_GCM_OP_UNKNONW = 0,
39 AES_GCM_OP_ENCRYPT,
40 AES_GCM_OP_DECRYPT,
41 AES_GCM_OP_GMAC
42} aes_gcm_op_t;
43
Damjan Marionb47376f2023-03-15 11:42:06 +000044typedef struct
45{
46 /* pre-calculated hash key values */
47 const u8x16 Hi[NUM_HI];
48 /* extracted AES key */
Damjan Marion9caef2a2024-01-08 19:05:40 +000049 const aes_expaned_key_t Ke[AES_KEY_ROUNDS (AES_KEY_256) + 1];
Damjan Marionb47376f2023-03-15 11:42:06 +000050} aes_gcm_key_data_t;
51
52typedef struct
53{
54 aes_gcm_op_t operation;
55 int last;
56 u8 rounds;
57 uword data_bytes;
58 uword aad_bytes;
59
60 u8x16 T;
61
62 /* hash */
63 const u8x16 *Hi;
64 const aes_ghash_t *next_Hi;
65
66 /* expaded keys */
Damjan Marion9caef2a2024-01-08 19:05:40 +000067 const aes_expaned_key_t *Ke;
Damjan Marionb47376f2023-03-15 11:42:06 +000068
69 /* counter */
70 u32 counter;
71 u8x16 EY0;
Damjan Marion9caef2a2024-01-08 19:05:40 +000072 aes_counter_t Y;
Damjan Marionb47376f2023-03-15 11:42:06 +000073
74 /* ghash */
Damjan Marion41724482023-03-23 13:44:01 +000075 ghash_ctx_t gd;
Damjan Marionb47376f2023-03-15 11:42:06 +000076} aes_gcm_ctx_t;
77
Damjan Marion41724482023-03-23 13:44:01 +000078static_always_inline u8x16
79aes_gcm_final_block (aes_gcm_ctx_t *ctx)
80{
81 return (u8x16) ((u64x2){ ctx->data_bytes, ctx->aad_bytes } << 3);
82}
83
Damjan Marionb47376f2023-03-15 11:42:06 +000084static_always_inline void
85aes_gcm_ghash_mul_first (aes_gcm_ctx_t *ctx, aes_data_t data, u32 n_lanes)
86{
87 uword hash_offset = NUM_HI - n_lanes;
88 ctx->next_Hi = (aes_ghash_t *) (ctx->Hi + hash_offset);
Damjan Marion9caef2a2024-01-08 19:05:40 +000089#if N_AES_LANES == 4
Damjan Marionb47376f2023-03-15 11:42:06 +000090 u8x64 tag4 = {};
91 tag4 = u8x64_insert_u8x16 (tag4, ctx->T, 0);
Damjan Marion9caef2a2024-01-08 19:05:40 +000092 ghash4_mul_first (&ctx->gd, aes_reflect (data) ^ tag4, *ctx->next_Hi++);
93#elif N_AES_LANES == 2
Damjan Marionb47376f2023-03-15 11:42:06 +000094 u8x32 tag2 = {};
95 tag2 = u8x32_insert_lo (tag2, ctx->T);
Damjan Marion9caef2a2024-01-08 19:05:40 +000096 ghash2_mul_first (&ctx->gd, aes_reflect (data) ^ tag2, *ctx->next_Hi++);
Damjan Marionb47376f2023-03-15 11:42:06 +000097#else
Damjan Marion9caef2a2024-01-08 19:05:40 +000098 ghash_mul_first (&ctx->gd, aes_reflect (data) ^ ctx->T, *ctx->next_Hi++);
Damjan Marionb47376f2023-03-15 11:42:06 +000099#endif
100}
101
102static_always_inline void
103aes_gcm_ghash_mul_next (aes_gcm_ctx_t *ctx, aes_data_t data)
104{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000105#if N_AES_LANES == 4
106 ghash4_mul_next (&ctx->gd, aes_reflect (data), *ctx->next_Hi++);
107#elif N_AES_LANES == 2
108 ghash2_mul_next (&ctx->gd, aes_reflect (data), *ctx->next_Hi++);
Damjan Marionb47376f2023-03-15 11:42:06 +0000109#else
Damjan Marion9caef2a2024-01-08 19:05:40 +0000110 ghash_mul_next (&ctx->gd, aes_reflect (data), *ctx->next_Hi++);
Damjan Marionb47376f2023-03-15 11:42:06 +0000111#endif
112}
113
114static_always_inline void
Damjan Marion41724482023-03-23 13:44:01 +0000115aes_gcm_ghash_mul_final_block (aes_gcm_ctx_t *ctx)
Damjan Marionb47376f2023-03-15 11:42:06 +0000116{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000117#if N_AES_LANES == 4
Damjan Marionb47376f2023-03-15 11:42:06 +0000118 u8x64 h = u8x64_insert_u8x16 (u8x64_zero (), ctx->Hi[NUM_HI - 1], 0);
Damjan Marion41724482023-03-23 13:44:01 +0000119 u8x64 r4 = u8x64_insert_u8x16 (u8x64_zero (), aes_gcm_final_block (ctx), 0);
Damjan Marionb47376f2023-03-15 11:42:06 +0000120 ghash4_mul_next (&ctx->gd, r4, h);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000121#elif N_AES_LANES == 2
Damjan Marionb47376f2023-03-15 11:42:06 +0000122 u8x32 h = u8x32_insert_lo (u8x32_zero (), ctx->Hi[NUM_HI - 1]);
Damjan Marion41724482023-03-23 13:44:01 +0000123 u8x32 r2 = u8x32_insert_lo (u8x32_zero (), aes_gcm_final_block (ctx));
Damjan Marionb47376f2023-03-15 11:42:06 +0000124 ghash2_mul_next (&ctx->gd, r2, h);
125#else
Damjan Marion41724482023-03-23 13:44:01 +0000126 ghash_mul_next (&ctx->gd, aes_gcm_final_block (ctx), ctx->Hi[NUM_HI - 1]);
Damjan Marionb47376f2023-03-15 11:42:06 +0000127#endif
128}
129
130static_always_inline void
131aes_gcm_enc_ctr0_round (aes_gcm_ctx_t *ctx, int aes_round)
132{
133 if (aes_round == 0)
134 ctx->EY0 ^= ctx->Ke[0].x1;
135 else if (aes_round == ctx->rounds)
Damjan Marion9caef2a2024-01-08 19:05:40 +0000136 ctx->EY0 = aes_enc_last_round_x1 (ctx->EY0, ctx->Ke[aes_round].x1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000137 else
Damjan Marion9caef2a2024-01-08 19:05:40 +0000138 ctx->EY0 = aes_enc_round_x1 (ctx->EY0, ctx->Ke[aes_round].x1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000139}
140
141static_always_inline void
142aes_gcm_ghash (aes_gcm_ctx_t *ctx, u8 *data, u32 n_left)
143{
144 uword i;
145 aes_data_t r = {};
146 const aes_mem_t *d = (aes_mem_t *) data;
147
Damjan Marion9caef2a2024-01-08 19:05:40 +0000148 for (int n = 8 * N_AES_BYTES; n_left >= n; n_left -= n, d += 8)
Damjan Marionb47376f2023-03-15 11:42:06 +0000149 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000150 if (ctx->operation == AES_GCM_OP_GMAC && n_left == n)
Damjan Marionb47376f2023-03-15 11:42:06 +0000151 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000152 aes_gcm_ghash_mul_first (ctx, d[0], 8 * N_AES_LANES + 1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000153 for (i = 1; i < 8; i++)
154 aes_gcm_ghash_mul_next (ctx, d[i]);
Damjan Marion41724482023-03-23 13:44:01 +0000155 aes_gcm_ghash_mul_final_block (ctx);
Damjan Marionb47376f2023-03-15 11:42:06 +0000156 aes_gcm_ghash_reduce (ctx);
157 aes_gcm_ghash_reduce2 (ctx);
158 aes_gcm_ghash_final (ctx);
159 goto done;
160 }
161
Damjan Marion9caef2a2024-01-08 19:05:40 +0000162 aes_gcm_ghash_mul_first (ctx, d[0], 8 * N_AES_LANES);
Damjan Marionb47376f2023-03-15 11:42:06 +0000163 for (i = 1; i < 8; i++)
164 aes_gcm_ghash_mul_next (ctx, d[i]);
165 aes_gcm_ghash_reduce (ctx);
166 aes_gcm_ghash_reduce2 (ctx);
167 aes_gcm_ghash_final (ctx);
168 }
169
170 if (n_left > 0)
171 {
172 int n_lanes = (n_left + 15) / 16;
173
174 if (ctx->operation == AES_GCM_OP_GMAC)
175 n_lanes++;
176
Damjan Marion9caef2a2024-01-08 19:05:40 +0000177 if (n_left < N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000178 {
179 clib_memcpy_fast (&r, d, n_left);
180 aes_gcm_ghash_mul_first (ctx, r, n_lanes);
181 }
182 else
183 {
184 aes_gcm_ghash_mul_first (ctx, d[0], n_lanes);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000185 n_left -= N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000186 i = 1;
187
Damjan Marion9caef2a2024-01-08 19:05:40 +0000188 if (n_left >= 4 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000189 {
190 aes_gcm_ghash_mul_next (ctx, d[i]);
191 aes_gcm_ghash_mul_next (ctx, d[i + 1]);
192 aes_gcm_ghash_mul_next (ctx, d[i + 2]);
193 aes_gcm_ghash_mul_next (ctx, d[i + 3]);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000194 n_left -= 4 * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000195 i += 4;
196 }
Damjan Marion9caef2a2024-01-08 19:05:40 +0000197 if (n_left >= 2 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000198 {
199 aes_gcm_ghash_mul_next (ctx, d[i]);
200 aes_gcm_ghash_mul_next (ctx, d[i + 1]);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000201 n_left -= 2 * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000202 i += 2;
203 }
204
Damjan Marion9caef2a2024-01-08 19:05:40 +0000205 if (n_left >= N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000206 {
207 aes_gcm_ghash_mul_next (ctx, d[i]);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000208 n_left -= N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000209 i += 1;
210 }
211
212 if (n_left)
213 {
214 clib_memcpy_fast (&r, d + i, n_left);
215 aes_gcm_ghash_mul_next (ctx, r);
216 }
217 }
218
219 if (ctx->operation == AES_GCM_OP_GMAC)
Damjan Marion41724482023-03-23 13:44:01 +0000220 aes_gcm_ghash_mul_final_block (ctx);
Damjan Marionb47376f2023-03-15 11:42:06 +0000221 aes_gcm_ghash_reduce (ctx);
222 aes_gcm_ghash_reduce2 (ctx);
223 aes_gcm_ghash_final (ctx);
224 }
225 else if (ctx->operation == AES_GCM_OP_GMAC)
Damjan Marion41724482023-03-23 13:44:01 +0000226 ctx->T =
227 ghash_mul (aes_gcm_final_block (ctx) ^ ctx->T, ctx->Hi[NUM_HI - 1]);
Damjan Marionb47376f2023-03-15 11:42:06 +0000228
229done:
230 /* encrypt counter 0 E(Y0, k) */
231 if (ctx->operation == AES_GCM_OP_GMAC)
232 for (int i = 0; i < ctx->rounds + 1; i += 1)
233 aes_gcm_enc_ctr0_round (ctx, i);
234}
235
236static_always_inline void
237aes_gcm_enc_first_round (aes_gcm_ctx_t *ctx, aes_data_t *r, uword n_blocks)
238{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000239 const aes_expaned_key_t Ke0 = ctx->Ke[0];
Damjan Marionb47376f2023-03-15 11:42:06 +0000240 uword i = 0;
241
Damjan Marion41724482023-03-23 13:44:01 +0000242 /* As counter is stored in network byte order for performance reasons we
243 are incrementing least significant byte only except in case where we
244 overlow. As we are processing four 128, 256 or 512-blocks in parallel
245 except the last round, overflow can happen only when n_blocks == 4 */
246
Damjan Marion9caef2a2024-01-08 19:05:40 +0000247#if N_AES_LANES == 4
Damjan Marionb47376f2023-03-15 11:42:06 +0000248 const u32x16 ctr_inv_4444 = { 0, 0, 0, 4 << 24, 0, 0, 0, 4 << 24,
249 0, 0, 0, 4 << 24, 0, 0, 0, 4 << 24 };
250
251 const u32x16 ctr_4444 = {
252 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0,
253 };
254
Damjan Marionb47376f2023-03-15 11:42:06 +0000255 if (n_blocks == 4)
256 for (; i < 2; i++)
257 {
Damjan Marion41724482023-03-23 13:44:01 +0000258 r[i] = Ke0.x4 ^ (u8x64) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000259 ctx->Y += ctr_inv_4444;
260 }
261
262 if (n_blocks == 4 && PREDICT_FALSE ((u8) ctx->counter == 242))
263 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000264 u32x16 Yr = (u32x16) aes_reflect ((u8x64) ctx->Y);
Damjan Marionb47376f2023-03-15 11:42:06 +0000265
266 for (; i < n_blocks; i++)
267 {
Damjan Marion41724482023-03-23 13:44:01 +0000268 r[i] = Ke0.x4 ^ (u8x64) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000269 Yr += ctr_4444;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000270 ctx->Y = (u32x16) aes_reflect ((u8x64) Yr);
Damjan Marionb47376f2023-03-15 11:42:06 +0000271 }
272 }
273 else
274 {
275 for (; i < n_blocks; i++)
276 {
Damjan Marion41724482023-03-23 13:44:01 +0000277 r[i] = Ke0.x4 ^ (u8x64) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000278 ctx->Y += ctr_inv_4444;
279 }
280 }
281 ctx->counter += n_blocks * 4;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000282#elif N_AES_LANES == 2
Damjan Marionb47376f2023-03-15 11:42:06 +0000283 const u32x8 ctr_inv_22 = { 0, 0, 0, 2 << 24, 0, 0, 0, 2 << 24 };
284 const u32x8 ctr_22 = { 2, 0, 0, 0, 2, 0, 0, 0 };
285
Damjan Marionb47376f2023-03-15 11:42:06 +0000286 if (n_blocks == 4)
287 for (; i < 2; i++)
288 {
Damjan Marion41724482023-03-23 13:44:01 +0000289 r[i] = Ke0.x2 ^ (u8x32) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000290 ctx->Y += ctr_inv_22;
291 }
292
293 if (n_blocks == 4 && PREDICT_FALSE ((u8) ctx->counter == 250))
294 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000295 u32x8 Yr = (u32x8) aes_reflect ((u8x32) ctx->Y);
Damjan Marionb47376f2023-03-15 11:42:06 +0000296
297 for (; i < n_blocks; i++)
298 {
Damjan Marion41724482023-03-23 13:44:01 +0000299 r[i] = Ke0.x2 ^ (u8x32) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000300 Yr += ctr_22;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000301 ctx->Y = (u32x8) aes_reflect ((u8x32) Yr);
Damjan Marionb47376f2023-03-15 11:42:06 +0000302 }
303 }
304 else
305 {
306 for (; i < n_blocks; i++)
307 {
Damjan Marion41724482023-03-23 13:44:01 +0000308 r[i] = Ke0.x2 ^ (u8x32) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000309 ctx->Y += ctr_inv_22;
310 }
311 }
312 ctx->counter += n_blocks * 2;
313#else
314 const u32x4 ctr_inv_1 = { 0, 0, 0, 1 << 24 };
315
316 if (PREDICT_TRUE ((u8) ctx->counter < 0xfe) || n_blocks < 3)
317 {
318 for (; i < n_blocks; i++)
319 {
Damjan Marion41724482023-03-23 13:44:01 +0000320 r[i] = Ke0.x1 ^ (u8x16) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000321 ctx->Y += ctr_inv_1;
322 }
323 ctx->counter += n_blocks;
324 }
325 else
326 {
Damjan Marion41724482023-03-23 13:44:01 +0000327 r[i++] = Ke0.x1 ^ (u8x16) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000328 ctx->Y += ctr_inv_1;
329 ctx->counter += 1;
330
331 for (; i < n_blocks; i++)
332 {
Damjan Marion41724482023-03-23 13:44:01 +0000333 r[i] = Ke0.x1 ^ (u8x16) ctx->Y; /* Initial AES round */
Damjan Marionb47376f2023-03-15 11:42:06 +0000334 ctx->counter++;
335 ctx->Y[3] = clib_host_to_net_u32 (ctx->counter);
336 }
337 }
338#endif
339}
340
341static_always_inline void
Damjan Marionb47376f2023-03-15 11:42:06 +0000342aes_gcm_enc_last_round (aes_gcm_ctx_t *ctx, aes_data_t *r, aes_data_t *d,
Damjan Marion9caef2a2024-01-08 19:05:40 +0000343 const aes_expaned_key_t *Ke, uword n_blocks)
Damjan Marionb47376f2023-03-15 11:42:06 +0000344{
345 /* additional ronuds for AES-192 and AES-256 */
346 for (int i = 10; i < ctx->rounds; i++)
Damjan Marion9caef2a2024-01-08 19:05:40 +0000347 aes_enc_round (r, Ke + i, n_blocks);
Damjan Marionb47376f2023-03-15 11:42:06 +0000348
Damjan Marion9caef2a2024-01-08 19:05:40 +0000349 aes_enc_last_round (r, d, Ke + ctx->rounds, n_blocks);
Damjan Marionb47376f2023-03-15 11:42:06 +0000350}
351
352static_always_inline void
353aes_gcm_calc (aes_gcm_ctx_t *ctx, aes_data_t *d, const u8 *src, u8 *dst, u32 n,
354 u32 n_bytes, int with_ghash)
355{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000356 const aes_expaned_key_t *k = ctx->Ke;
Damjan Marionb47376f2023-03-15 11:42:06 +0000357 const aes_mem_t *sv = (aes_mem_t *) src;
358 aes_mem_t *dv = (aes_mem_t *) dst;
359 uword ghash_blocks, gc = 1;
360 aes_data_t r[4];
361 u32 i, n_lanes;
362
363 if (ctx->operation == AES_GCM_OP_ENCRYPT)
364 {
365 ghash_blocks = 4;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000366 n_lanes = N_AES_LANES * 4;
Damjan Marionb47376f2023-03-15 11:42:06 +0000367 }
368 else
369 {
370 ghash_blocks = n;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000371 n_lanes = n * N_AES_LANES;
372#if N_AES_LANES != 1
Damjan Marionb47376f2023-03-15 11:42:06 +0000373 if (ctx->last)
374 n_lanes = (n_bytes + 15) / 16;
375#endif
376 }
377
Damjan Marion9caef2a2024-01-08 19:05:40 +0000378 n_bytes -= (n - 1) * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000379
380 /* AES rounds 0 and 1 */
381 aes_gcm_enc_first_round (ctx, r, n);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000382 aes_enc_round (r, k + 1, n);
Damjan Marionb47376f2023-03-15 11:42:06 +0000383
384 /* load data - decrypt round */
385 if (ctx->operation == AES_GCM_OP_DECRYPT)
386 {
387 for (i = 0; i < n - ctx->last; i++)
388 d[i] = sv[i];
389
390 if (ctx->last)
Damjan Marion9caef2a2024-01-08 19:05:40 +0000391 d[n - 1] = aes_load_partial ((u8 *) (sv + n - 1), n_bytes);
Damjan Marionb47376f2023-03-15 11:42:06 +0000392 }
393
394 /* GHASH multiply block 0 */
395 if (with_ghash)
396 aes_gcm_ghash_mul_first (ctx, d[0], n_lanes);
397
398 /* AES rounds 2 and 3 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000399 aes_enc_round (r, k + 2, n);
400 aes_enc_round (r, k + 3, n);
Damjan Marionb47376f2023-03-15 11:42:06 +0000401
402 /* GHASH multiply block 1 */
403 if (with_ghash && gc++ < ghash_blocks)
404 aes_gcm_ghash_mul_next (ctx, (d[1]));
405
406 /* AES rounds 4 and 5 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000407 aes_enc_round (r, k + 4, n);
408 aes_enc_round (r, k + 5, n);
Damjan Marionb47376f2023-03-15 11:42:06 +0000409
410 /* GHASH multiply block 2 */
411 if (with_ghash && gc++ < ghash_blocks)
412 aes_gcm_ghash_mul_next (ctx, (d[2]));
413
414 /* AES rounds 6 and 7 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000415 aes_enc_round (r, k + 6, n);
416 aes_enc_round (r, k + 7, n);
Damjan Marionb47376f2023-03-15 11:42:06 +0000417
418 /* GHASH multiply block 3 */
419 if (with_ghash && gc++ < ghash_blocks)
420 aes_gcm_ghash_mul_next (ctx, (d[3]));
421
422 /* load 4 blocks of data - decrypt round */
423 if (ctx->operation == AES_GCM_OP_ENCRYPT)
424 {
425 for (i = 0; i < n - ctx->last; i++)
426 d[i] = sv[i];
427
428 if (ctx->last)
Damjan Marion9caef2a2024-01-08 19:05:40 +0000429 d[n - 1] = aes_load_partial (sv + n - 1, n_bytes);
Damjan Marionb47376f2023-03-15 11:42:06 +0000430 }
431
432 /* AES rounds 8 and 9 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000433 aes_enc_round (r, k + 8, n);
434 aes_enc_round (r, k + 9, n);
Damjan Marionb47376f2023-03-15 11:42:06 +0000435
436 /* AES last round(s) */
437 aes_gcm_enc_last_round (ctx, r, d, k, n);
438
439 /* store data */
440 for (i = 0; i < n - ctx->last; i++)
441 dv[i] = d[i];
442
443 if (ctx->last)
Damjan Marion9caef2a2024-01-08 19:05:40 +0000444 aes_store_partial (d[n - 1], dv + n - 1, n_bytes);
Damjan Marionb47376f2023-03-15 11:42:06 +0000445
446 /* GHASH reduce 1st step */
447 aes_gcm_ghash_reduce (ctx);
448
449 /* GHASH reduce 2nd step */
450 if (with_ghash)
451 aes_gcm_ghash_reduce2 (ctx);
452
453 /* GHASH final step */
454 if (with_ghash)
455 aes_gcm_ghash_final (ctx);
456}
457
458static_always_inline void
Damjan Marion41724482023-03-23 13:44:01 +0000459aes_gcm_calc_double (aes_gcm_ctx_t *ctx, aes_data_t *d, const u8 *src, u8 *dst)
Damjan Marionb47376f2023-03-15 11:42:06 +0000460{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000461 const aes_expaned_key_t *k = ctx->Ke;
Damjan Marionb47376f2023-03-15 11:42:06 +0000462 const aes_mem_t *sv = (aes_mem_t *) src;
463 aes_mem_t *dv = (aes_mem_t *) dst;
464 aes_data_t r[4];
465
466 /* AES rounds 0 and 1 */
467 aes_gcm_enc_first_round (ctx, r, 4);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000468 aes_enc_round (r, k + 1, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000469
470 /* load 4 blocks of data - decrypt round */
471 if (ctx->operation == AES_GCM_OP_DECRYPT)
472 for (int i = 0; i < 4; i++)
473 d[i] = sv[i];
474
475 /* GHASH multiply block 0 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000476 aes_gcm_ghash_mul_first (ctx, d[0], N_AES_LANES * 8);
Damjan Marionb47376f2023-03-15 11:42:06 +0000477
478 /* AES rounds 2 and 3 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000479 aes_enc_round (r, k + 2, 4);
480 aes_enc_round (r, k + 3, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000481
482 /* GHASH multiply block 1 */
483 aes_gcm_ghash_mul_next (ctx, (d[1]));
484
485 /* AES rounds 4 and 5 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000486 aes_enc_round (r, k + 4, 4);
487 aes_enc_round (r, k + 5, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000488
489 /* GHASH multiply block 2 */
490 aes_gcm_ghash_mul_next (ctx, (d[2]));
491
492 /* AES rounds 6 and 7 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000493 aes_enc_round (r, k + 6, 4);
494 aes_enc_round (r, k + 7, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000495
496 /* GHASH multiply block 3 */
497 aes_gcm_ghash_mul_next (ctx, (d[3]));
498
499 /* AES rounds 8 and 9 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000500 aes_enc_round (r, k + 8, 4);
501 aes_enc_round (r, k + 9, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000502
503 /* load 4 blocks of data - encrypt round */
504 if (ctx->operation == AES_GCM_OP_ENCRYPT)
505 for (int i = 0; i < 4; i++)
506 d[i] = sv[i];
507
508 /* AES last round(s) */
509 aes_gcm_enc_last_round (ctx, r, d, k, 4);
510
511 /* store 4 blocks of data */
512 for (int i = 0; i < 4; i++)
513 dv[i] = d[i];
514
515 /* load next 4 blocks of data data - decrypt round */
516 if (ctx->operation == AES_GCM_OP_DECRYPT)
517 for (int i = 0; i < 4; i++)
518 d[i] = sv[i + 4];
519
520 /* GHASH multiply block 4 */
521 aes_gcm_ghash_mul_next (ctx, (d[0]));
522
523 /* AES rounds 0 and 1 */
524 aes_gcm_enc_first_round (ctx, r, 4);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000525 aes_enc_round (r, k + 1, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000526
527 /* GHASH multiply block 5 */
528 aes_gcm_ghash_mul_next (ctx, (d[1]));
529
530 /* AES rounds 2 and 3 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000531 aes_enc_round (r, k + 2, 4);
532 aes_enc_round (r, k + 3, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000533
534 /* GHASH multiply block 6 */
535 aes_gcm_ghash_mul_next (ctx, (d[2]));
536
537 /* AES rounds 4 and 5 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000538 aes_enc_round (r, k + 4, 4);
539 aes_enc_round (r, k + 5, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000540
541 /* GHASH multiply block 7 */
542 aes_gcm_ghash_mul_next (ctx, (d[3]));
543
544 /* AES rounds 6 and 7 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000545 aes_enc_round (r, k + 6, 4);
546 aes_enc_round (r, k + 7, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000547
548 /* GHASH reduce 1st step */
549 aes_gcm_ghash_reduce (ctx);
550
551 /* AES rounds 8 and 9 */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000552 aes_enc_round (r, k + 8, 4);
553 aes_enc_round (r, k + 9, 4);
Damjan Marionb47376f2023-03-15 11:42:06 +0000554
555 /* GHASH reduce 2nd step */
556 aes_gcm_ghash_reduce2 (ctx);
557
558 /* load 4 blocks of data - encrypt round */
559 if (ctx->operation == AES_GCM_OP_ENCRYPT)
560 for (int i = 0; i < 4; i++)
561 d[i] = sv[i + 4];
562
563 /* AES last round(s) */
564 aes_gcm_enc_last_round (ctx, r, d, k, 4);
565
566 /* store data */
567 for (int i = 0; i < 4; i++)
568 dv[i + 4] = d[i];
569
570 /* GHASH final step */
571 aes_gcm_ghash_final (ctx);
572}
573
574static_always_inline void
575aes_gcm_mask_bytes (aes_data_t *d, uword n_bytes)
576{
577 const union
578 {
579 u8 b[64];
580 aes_data_t r;
581 } scale = {
582 .b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
583 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
584 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
585 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 },
586 };
587
588 d[0] &= (aes_gcm_splat (n_bytes) > scale.r);
589}
590
591static_always_inline void
592aes_gcm_calc_last (aes_gcm_ctx_t *ctx, aes_data_t *d, int n_blocks,
593 u32 n_bytes)
594{
Damjan Marion9caef2a2024-01-08 19:05:40 +0000595 int n_lanes = (N_AES_LANES == 1 ? n_blocks : (n_bytes + 15) / 16) + 1;
596 n_bytes -= (n_blocks - 1) * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000597 int i;
598
599 aes_gcm_enc_ctr0_round (ctx, 0);
600 aes_gcm_enc_ctr0_round (ctx, 1);
601
Damjan Marion9caef2a2024-01-08 19:05:40 +0000602 if (n_bytes != N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000603 aes_gcm_mask_bytes (d + n_blocks - 1, n_bytes);
604
605 aes_gcm_ghash_mul_first (ctx, d[0], n_lanes);
606
607 aes_gcm_enc_ctr0_round (ctx, 2);
608 aes_gcm_enc_ctr0_round (ctx, 3);
609
610 if (n_blocks > 1)
611 aes_gcm_ghash_mul_next (ctx, d[1]);
612
613 aes_gcm_enc_ctr0_round (ctx, 4);
614 aes_gcm_enc_ctr0_round (ctx, 5);
615
616 if (n_blocks > 2)
617 aes_gcm_ghash_mul_next (ctx, d[2]);
618
619 aes_gcm_enc_ctr0_round (ctx, 6);
620 aes_gcm_enc_ctr0_round (ctx, 7);
621
622 if (n_blocks > 3)
623 aes_gcm_ghash_mul_next (ctx, d[3]);
624
625 aes_gcm_enc_ctr0_round (ctx, 8);
626 aes_gcm_enc_ctr0_round (ctx, 9);
627
Damjan Marion41724482023-03-23 13:44:01 +0000628 aes_gcm_ghash_mul_final_block (ctx);
Damjan Marionb47376f2023-03-15 11:42:06 +0000629 aes_gcm_ghash_reduce (ctx);
630
631 for (i = 10; i < ctx->rounds; i++)
632 aes_gcm_enc_ctr0_round (ctx, i);
633
634 aes_gcm_ghash_reduce2 (ctx);
635
636 aes_gcm_ghash_final (ctx);
637
638 aes_gcm_enc_ctr0_round (ctx, i);
639}
640
641static_always_inline void
642aes_gcm_enc (aes_gcm_ctx_t *ctx, const u8 *src, u8 *dst, u32 n_left)
643{
644 aes_data_t d[4];
645
646 if (PREDICT_FALSE (n_left == 0))
647 {
648 int i;
649 for (i = 0; i < ctx->rounds + 1; i++)
650 aes_gcm_enc_ctr0_round (ctx, i);
651 return;
652 }
653
Damjan Marion9caef2a2024-01-08 19:05:40 +0000654 if (n_left < 4 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000655 {
656 ctx->last = 1;
Damjan Marion9caef2a2024-01-08 19:05:40 +0000657 if (n_left > 3 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000658 {
659 aes_gcm_calc (ctx, d, src, dst, 4, n_left, /* with_ghash */ 0);
660 aes_gcm_calc_last (ctx, d, 4, n_left);
661 }
Damjan Marion9caef2a2024-01-08 19:05:40 +0000662 else if (n_left > 2 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000663 {
664 aes_gcm_calc (ctx, d, src, dst, 3, n_left, /* with_ghash */ 0);
665 aes_gcm_calc_last (ctx, d, 3, n_left);
666 }
Damjan Marion9caef2a2024-01-08 19:05:40 +0000667 else if (n_left > N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000668 {
669 aes_gcm_calc (ctx, d, src, dst, 2, n_left, /* with_ghash */ 0);
670 aes_gcm_calc_last (ctx, d, 2, n_left);
671 }
672 else
673 {
674 aes_gcm_calc (ctx, d, src, dst, 1, n_left, /* with_ghash */ 0);
675 aes_gcm_calc_last (ctx, d, 1, n_left);
676 }
677 return;
678 }
Damjan Marion41724482023-03-23 13:44:01 +0000679
Damjan Marion9caef2a2024-01-08 19:05:40 +0000680 aes_gcm_calc (ctx, d, src, dst, 4, 4 * N_AES_BYTES, /* with_ghash */ 0);
Damjan Marionb47376f2023-03-15 11:42:06 +0000681
682 /* next */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000683 n_left -= 4 * N_AES_BYTES;
684 dst += 4 * N_AES_BYTES;
685 src += 4 * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000686
Damjan Marion9caef2a2024-01-08 19:05:40 +0000687 for (int n = 8 * N_AES_BYTES; n_left >= n; n_left -= n, src += n, dst += n)
Damjan Marion41724482023-03-23 13:44:01 +0000688 aes_gcm_calc_double (ctx, d, src, dst);
Damjan Marionb47376f2023-03-15 11:42:06 +0000689
Damjan Marion9caef2a2024-01-08 19:05:40 +0000690 if (n_left >= 4 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000691 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000692 aes_gcm_calc (ctx, d, src, dst, 4, 4 * N_AES_BYTES, /* with_ghash */ 1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000693
694 /* next */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000695 n_left -= 4 * N_AES_BYTES;
696 dst += 4 * N_AES_BYTES;
697 src += 4 * N_AES_BYTES;
Damjan Marionb47376f2023-03-15 11:42:06 +0000698 }
699
700 if (n_left == 0)
701 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000702 aes_gcm_calc_last (ctx, d, 4, 4 * N_AES_BYTES);
Damjan Marionb47376f2023-03-15 11:42:06 +0000703 return;
704 }
705
706 ctx->last = 1;
707
Damjan Marion9caef2a2024-01-08 19:05:40 +0000708 if (n_left > 3 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000709 {
710 aes_gcm_calc (ctx, d, src, dst, 4, n_left, /* with_ghash */ 1);
711 aes_gcm_calc_last (ctx, d, 4, n_left);
712 }
Damjan Marion9caef2a2024-01-08 19:05:40 +0000713 else if (n_left > 2 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000714 {
715 aes_gcm_calc (ctx, d, src, dst, 3, n_left, /* with_ghash */ 1);
716 aes_gcm_calc_last (ctx, d, 3, n_left);
717 }
Damjan Marion9caef2a2024-01-08 19:05:40 +0000718 else if (n_left > N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000719 {
720 aes_gcm_calc (ctx, d, src, dst, 2, n_left, /* with_ghash */ 1);
721 aes_gcm_calc_last (ctx, d, 2, n_left);
722 }
723 else
724 {
725 aes_gcm_calc (ctx, d, src, dst, 1, n_left, /* with_ghash */ 1);
726 aes_gcm_calc_last (ctx, d, 1, n_left);
727 }
728}
729
730static_always_inline void
731aes_gcm_dec (aes_gcm_ctx_t *ctx, const u8 *src, u8 *dst, uword n_left)
732{
733 aes_data_t d[4] = {};
Damjan Marion41724482023-03-23 13:44:01 +0000734 ghash_ctx_t gd;
735
736 /* main encryption loop */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000737 for (int n = 8 * N_AES_BYTES; n_left >= n; n_left -= n, dst += n, src += n)
Damjan Marion41724482023-03-23 13:44:01 +0000738 aes_gcm_calc_double (ctx, d, src, dst);
Damjan Marionb47376f2023-03-15 11:42:06 +0000739
Damjan Marion9caef2a2024-01-08 19:05:40 +0000740 if (n_left >= 4 * N_AES_BYTES)
Damjan Marionb47376f2023-03-15 11:42:06 +0000741 {
Damjan Marion9caef2a2024-01-08 19:05:40 +0000742 aes_gcm_calc (ctx, d, src, dst, 4, 4 * N_AES_BYTES, /* with_ghash */ 1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000743
744 /* next */
Damjan Marion9caef2a2024-01-08 19:05:40 +0000745 n_left -= 4 * N_AES_BYTES;
746 dst += N_AES_BYTES * 4;
747 src += N_AES_BYTES * 4;
Damjan Marionb47376f2023-03-15 11:42:06 +0000748 }
749
Damjan Marion41724482023-03-23 13:44:01 +0000750 if (n_left)
751 {
752 ctx->last = 1;
Damjan Marionb47376f2023-03-15 11:42:06 +0000753
Damjan Marion9caef2a2024-01-08 19:05:40 +0000754 if (n_left > 3 * N_AES_BYTES)
Damjan Marion41724482023-03-23 13:44:01 +0000755 aes_gcm_calc (ctx, d, src, dst, 4, n_left, /* with_ghash */ 1);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000756 else if (n_left > 2 * N_AES_BYTES)
Damjan Marion41724482023-03-23 13:44:01 +0000757 aes_gcm_calc (ctx, d, src, dst, 3, n_left, /* with_ghash */ 1);
Damjan Marion9caef2a2024-01-08 19:05:40 +0000758 else if (n_left > N_AES_BYTES)
Damjan Marion41724482023-03-23 13:44:01 +0000759 aes_gcm_calc (ctx, d, src, dst, 2, n_left, /* with_ghash */ 1);
760 else
761 aes_gcm_calc (ctx, d, src, dst, 1, n_left, /* with_ghash */ 1);
762 }
Damjan Marionb47376f2023-03-15 11:42:06 +0000763
Damjan Marion41724482023-03-23 13:44:01 +0000764 /* interleaved counter 0 encryption E(Y0, k) and ghash of final GCM
765 * (bit length) block */
Damjan Marionb47376f2023-03-15 11:42:06 +0000766
Damjan Marion41724482023-03-23 13:44:01 +0000767 aes_gcm_enc_ctr0_round (ctx, 0);
768 aes_gcm_enc_ctr0_round (ctx, 1);
Damjan Marionb47376f2023-03-15 11:42:06 +0000769
Damjan Marion41724482023-03-23 13:44:01 +0000770 ghash_mul_first (&gd, aes_gcm_final_block (ctx) ^ ctx->T,
771 ctx->Hi[NUM_HI - 1]);
772
773 aes_gcm_enc_ctr0_round (ctx, 2);
774 aes_gcm_enc_ctr0_round (ctx, 3);
775
776 ghash_reduce (&gd);
777
778 aes_gcm_enc_ctr0_round (ctx, 4);
779 aes_gcm_enc_ctr0_round (ctx, 5);
780
781 ghash_reduce2 (&gd);
782
783 aes_gcm_enc_ctr0_round (ctx, 6);
784 aes_gcm_enc_ctr0_round (ctx, 7);
785
786 ctx->T = ghash_final (&gd);
787
788 aes_gcm_enc_ctr0_round (ctx, 8);
789 aes_gcm_enc_ctr0_round (ctx, 9);
790
791 for (int i = 10; i < ctx->rounds + 1; i += 1)
Damjan Marionb47376f2023-03-15 11:42:06 +0000792 aes_gcm_enc_ctr0_round (ctx, i);
793}
794
795static_always_inline int
796aes_gcm (const u8 *src, u8 *dst, const u8 *aad, u8 *ivp, u8 *tag,
797 u32 data_bytes, u32 aad_bytes, u8 tag_len,
798 const aes_gcm_key_data_t *kd, int aes_rounds, aes_gcm_op_t op)
799{
800 u8 *addt = (u8 *) aad;
801 u32x4 Y0;
802
803 aes_gcm_ctx_t _ctx = { .counter = 2,
804 .rounds = aes_rounds,
805 .operation = op,
806 .data_bytes = data_bytes,
807 .aad_bytes = aad_bytes,
Damjan Marion41724482023-03-23 13:44:01 +0000808 .Ke = kd->Ke,
Damjan Marionb47376f2023-03-15 11:42:06 +0000809 .Hi = kd->Hi },
810 *ctx = &_ctx;
811
812 /* initalize counter */
813 Y0 = (u32x4) (u64x2){ *(u64u *) ivp, 0 };
814 Y0[2] = *(u32u *) (ivp + 8);
815 Y0[3] = 1 << 24;
816 ctx->EY0 = (u8x16) Y0;
Damjan Marion41724482023-03-23 13:44:01 +0000817
Damjan Marion9caef2a2024-01-08 19:05:40 +0000818#if N_AES_LANES == 4
Damjan Marionb47376f2023-03-15 11:42:06 +0000819 ctx->Y = u32x16_splat_u32x4 (Y0) + (u32x16){
820 0, 0, 0, 1 << 24, 0, 0, 0, 2 << 24, 0, 0, 0, 3 << 24, 0, 0, 0, 4 << 24,
821 };
Damjan Marion9caef2a2024-01-08 19:05:40 +0000822#elif N_AES_LANES == 2
Damjan Marionb47376f2023-03-15 11:42:06 +0000823 ctx->Y =
824 u32x8_splat_u32x4 (Y0) + (u32x8){ 0, 0, 0, 1 << 24, 0, 0, 0, 2 << 24 };
825#else
826 ctx->Y = Y0 + (u32x4){ 0, 0, 0, 1 << 24 };
827#endif
828
829 /* calculate ghash for AAD */
830 aes_gcm_ghash (ctx, addt, aad_bytes);
831
Damjan Marionb47376f2023-03-15 11:42:06 +0000832 /* ghash and encrypt/edcrypt */
833 if (op == AES_GCM_OP_ENCRYPT)
834 aes_gcm_enc (ctx, src, dst, data_bytes);
835 else if (op == AES_GCM_OP_DECRYPT)
836 aes_gcm_dec (ctx, src, dst, data_bytes);
837
838 /* final tag is */
839 ctx->T = u8x16_reflect (ctx->T) ^ ctx->EY0;
840
841 /* tag_len 16 -> 0 */
842 tag_len &= 0xf;
843
844 if (op == AES_GCM_OP_ENCRYPT || op == AES_GCM_OP_GMAC)
845 {
846 /* store tag */
847 if (tag_len)
848 u8x16_store_partial (ctx->T, tag, tag_len);
849 else
850 ((u8x16u *) tag)[0] = ctx->T;
851 }
852 else
853 {
854 /* check tag */
855 if (tag_len)
856 {
857 u16 mask = pow2_mask (tag_len);
858 u8x16 expected = u8x16_load_partial (tag, tag_len);
859 if ((u8x16_msb_mask (expected == ctx->T) & mask) == mask)
860 return 1;
861 }
862 else
863 {
864 if (u8x16_is_equal (ctx->T, *(u8x16u *) tag))
865 return 1;
866 }
867 }
868 return 0;
869}
870
871static_always_inline void
872clib_aes_gcm_key_expand (aes_gcm_key_data_t *kd, const u8 *key,
873 aes_key_size_t ks)
874{
875 u8x16 H;
876 u8x16 ek[AES_KEY_ROUNDS (AES_KEY_256) + 1];
Damjan Marion9caef2a2024-01-08 19:05:40 +0000877 aes_expaned_key_t *Ke = (aes_expaned_key_t *) kd->Ke;
Damjan Marionb47376f2023-03-15 11:42:06 +0000878
879 /* expand AES key */
880 aes_key_expand (ek, key, ks);
881 for (int i = 0; i < AES_KEY_ROUNDS (ks) + 1; i++)
882 Ke[i].lanes[0] = Ke[i].lanes[1] = Ke[i].lanes[2] = Ke[i].lanes[3] = ek[i];
883
884 /* pre-calculate H */
885 H = aes_encrypt_block (u8x16_zero (), ek, ks);
886 H = u8x16_reflect (H);
887 ghash_precompute (H, (u8x16 *) kd->Hi, ARRAY_LEN (kd->Hi));
888}
889
890static_always_inline void
891clib_aes128_gcm_enc (const aes_gcm_key_data_t *kd, const u8 *plaintext,
892 u32 data_bytes, const u8 *aad, u32 aad_bytes,
893 const u8 *iv, u32 tag_bytes, u8 *cyphertext, u8 *tag)
894{
895 aes_gcm (plaintext, cyphertext, aad, (u8 *) iv, tag, data_bytes, aad_bytes,
896 tag_bytes, kd, AES_KEY_ROUNDS (AES_KEY_128), AES_GCM_OP_ENCRYPT);
897}
898
899static_always_inline void
900clib_aes256_gcm_enc (const aes_gcm_key_data_t *kd, const u8 *plaintext,
901 u32 data_bytes, const u8 *aad, u32 aad_bytes,
902 const u8 *iv, u32 tag_bytes, u8 *cyphertext, u8 *tag)
903{
904 aes_gcm (plaintext, cyphertext, aad, (u8 *) iv, tag, data_bytes, aad_bytes,
905 tag_bytes, kd, AES_KEY_ROUNDS (AES_KEY_256), AES_GCM_OP_ENCRYPT);
906}
907
908static_always_inline int
909clib_aes128_gcm_dec (const aes_gcm_key_data_t *kd, const u8 *cyphertext,
910 u32 data_bytes, const u8 *aad, u32 aad_bytes,
911 const u8 *iv, const u8 *tag, u32 tag_bytes, u8 *plaintext)
912{
913 return aes_gcm (cyphertext, plaintext, aad, (u8 *) iv, (u8 *) tag,
914 data_bytes, aad_bytes, tag_bytes, kd,
915 AES_KEY_ROUNDS (AES_KEY_128), AES_GCM_OP_DECRYPT);
916}
917
918static_always_inline int
919clib_aes256_gcm_dec (const aes_gcm_key_data_t *kd, const u8 *cyphertext,
920 u32 data_bytes, const u8 *aad, u32 aad_bytes,
921 const u8 *iv, const u8 *tag, u32 tag_bytes, u8 *plaintext)
922{
923 return aes_gcm (cyphertext, plaintext, aad, (u8 *) iv, (u8 *) tag,
924 data_bytes, aad_bytes, tag_bytes, kd,
925 AES_KEY_ROUNDS (AES_KEY_256), AES_GCM_OP_DECRYPT);
926}
927
928static_always_inline void
929clib_aes128_gmac (const aes_gcm_key_data_t *kd, const u8 *data, u32 data_bytes,
930 const u8 *iv, u32 tag_bytes, u8 *tag)
931{
932 aes_gcm (0, 0, data, (u8 *) iv, tag, 0, data_bytes, tag_bytes, kd,
933 AES_KEY_ROUNDS (AES_KEY_128), AES_GCM_OP_GMAC);
934}
935
936static_always_inline void
937clib_aes256_gmac (const aes_gcm_key_data_t *kd, const u8 *data, u32 data_bytes,
938 const u8 *iv, u32 tag_bytes, u8 *tag)
939{
940 aes_gcm (0, 0, data, (u8 *) iv, tag, 0, data_bytes, tag_bytes, kd,
941 AES_KEY_ROUNDS (AES_KEY_256), AES_GCM_OP_GMAC);
942}
943
944#endif /* __crypto_aes_gcm_h__ */