19 #if defined(HAVE_AES_GCM) && defined(HAVE_AES)
24 #if defined(HAVE_AEAD)
33 #define GF2_128_MPI_BYTES (2 * 16)
34 #define AES_BLOCK_BYTES (16)
35 #define AES_GCM_TAG_LEN (16)
37 #if defined(HAVE_AEAD)
38 static const cx_aead_base_t cx_aes_gcm_functions = {
39 (void (*)(
void *ctx)) cx_aes_gcm_init,
40 (cx_err_t(*)(
void *ctx,
const uint8_t *key,
size_t key_len)) cx_aes_gcm_set_key,
41 (cx_err_t(*)(
void *ctx, uint32_t mode, const
uint8_t *iv,
size_t iv_len)) cx_aes_gcm_start,
42 (cx_err_t(*)(
void *ctx, const
uint8_t *aad,
size_t aad_len)) cx_aes_gcm_update_aad,
43 (cx_err_t(*)(
void *ctx, const
uint8_t *input,
uint8_t *output,
size_t len)) cx_aes_gcm_update,
44 (cx_err_t(*)(
void *ctx,
uint8_t *tag,
size_t tag_len)) cx_aes_gcm_finish,
45 (cx_err_t(*)(
void *ctx,
54 size_t tag_len)) cx_aes_gcm_encrypt_and_tag,
55 (cx_err_t(*)(
void *ctx,
64 size_t tag_len)) cx_aes_gcm_decrypt_and_auth,
65 (cx_err_t(*)(
void *ctx, const
uint8_t *tag,
size_t tag_len)) cx_aes_gcm_check_tag};
67 const cx_aead_info_t cx_aes128_gcm_info = {CX_AEAD_AES128_GCM, 128, 128, &cx_aes_gcm_functions};
69 const cx_aead_info_t cx_aes192_gcm_info = {CX_AEAD_AES192_GCM, 192, 128, &cx_aes_gcm_functions};
71 const cx_aead_info_t cx_aes256_gcm_info = {CX_AEAD_AES256_GCM, 256, 128, &cx_aes_gcm_functions};
95 const uint8_t R2[4] = {0x10, 0x00, 0x01, 0x11};
101 static void cx_gcm_increment(
uint8_t *in)
105 for (i = 0; i < 4; i++) {
107 if (++(in[15 - i]) != 0) {
124 for (i = 0; i < len; i++) {
134 value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4);
135 value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
136 value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
144 static void cx_reverse_buffer(
uint8_t *r,
uint8_t *buf,
size_t buf_len)
148 for (i = 0; i < buf_len; i++) {
149 r[i] = cx_reverse_8bits(buf[buf_len - 1 - i]);
159 cx_bn_t bn_n, bn_c, bn_a, bn_b, bn_r;
162 CX_CHECK(cx_bn_lock(GF2_128_MPI_BYTES, 0));
163 CX_CHECK(cx_bn_alloc(&bn_r, GF2_128_MPI_BYTES));
164 cx_reverse_buffer(tmp, a, AES_BLOCK_BYTES);
165 CX_CHECK(cx_bn_alloc_init(&bn_a, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES));
166 cx_reverse_buffer(tmp, b, AES_BLOCK_BYTES);
167 CX_CHECK(cx_bn_alloc_init(&bn_b, GF2_128_MPI_BYTES, tmp, AES_BLOCK_BYTES));
168 CX_CHECK(cx_bn_alloc_init(&bn_n, GF2_128_MPI_BYTES, N,
sizeof(N)));
169 CX_CHECK(cx_bn_alloc_init(&bn_c, GF2_128_MPI_BYTES, R2,
sizeof(R2)));
170 CX_CHECK(cx_bn_gf2_n_mul(bn_r, bn_b, bn_a, bn_n, bn_c));
171 CX_CHECK(cx_bn_export(bn_r, tmp, AES_BLOCK_BYTES));
172 cx_reverse_buffer(r, tmp, AES_BLOCK_BYTES);
179 void cx_aes_gcm_init(cx_aes_gcm_context_t *ctx)
181 memset(ctx, 0,
sizeof(cx_aes_gcm_context_t));
184 cx_err_t cx_aes_gcm_set_key(cx_aes_gcm_context_t *ctx,
const uint8_t *raw_key,
size_t key_len)
186 return cx_aes_init_key_no_throw(raw_key, key_len, &ctx->key);
189 cx_err_t cx_aes_gcm_start(cx_aes_gcm_context_t *ctx,
194 cx_err_t error = CX_INVALID_PARAMETER;
197 if ((NULL == iv) || (iv_len < 1)) {
198 return CX_INVALID_PARAMETER;
203 memset(ctx->enc_block, 0, AES_BLOCK_BYTES);
206 CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->enc_block, ctx->hash_key));
207 memset(ctx->J0, 0, 16);
211 memcpy(ctx->J0, iv, iv_len);
218 block_len =
MIN(i, AES_BLOCK_BYTES);
219 cx_gcm_xor_block(ctx->J0, ctx->J0, iv, block_len);
220 CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0));
224 memset(ctx->enc_block, 0, 8);
225 STORE64BE(iv_len * 8, ctx->enc_block + 8);
226 cx_gcm_xor_block(ctx->J0, ctx->J0, ctx->enc_block, AES_BLOCK_BYTES);
227 CX_CHECK(cx_gcm_mul(ctx->J0, ctx->hash_key, ctx->J0));
230 CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, ctx->enc_block));
239 cx_err_t cx_aes_gcm_update_aad(cx_aes_gcm_context_t *ctx,
const uint8_t *aad,
size_t aad_len)
242 cx_err_t error = CX_OK;
245 ctx->aad_len += aad_len;
248 block_len =
MIN(i, AES_BLOCK_BYTES);
249 cx_gcm_xor_block(ctx->processed, ctx->processed, aad, block_len);
250 CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed));
258 cx_err_t cx_aes_gcm_update(cx_aes_gcm_context_t *ctx,
const uint8_t *in,
uint8_t *out,
size_t len)
260 cx_err_t error = CX_INVALID_PARAMETER;
269 block_len =
MIN(i, AES_BLOCK_BYTES);
270 cx_gcm_increment(ctx->J0);
271 CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp));
272 cx_gcm_xor_block(out, in, tmp, block_len);
273 cx_gcm_xor_block(ctx->processed, ctx->processed, out, block_len);
274 CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed));
275 if (i - block_len > 0) {
284 block_len =
MIN(i, AES_BLOCK_BYTES);
285 cx_gcm_xor_block(ctx->processed, ctx->processed, in, block_len);
286 CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed));
287 cx_gcm_increment(ctx->J0);
288 CX_CHECK(cx_aes_enc_block(&ctx->key, ctx->J0, tmp));
289 cx_gcm_xor_block(out, in, tmp, block_len);
290 if (i - block_len > 0) {
298 return CX_INVALID_PARAMETER_VALUE;
305 cx_err_t cx_aes_gcm_finish(cx_aes_gcm_context_t *ctx,
uint8_t *tag,
size_t tag_len)
311 cx_gcm_xor_block(ctx->processed, ctx->processed, ctx->J0, AES_BLOCK_BYTES);
312 CX_CHECK(cx_gcm_mul(ctx->processed, ctx->hash_key, ctx->processed));
313 cx_gcm_xor_block(tag, ctx->enc_block, ctx->processed, tag_len);
319 static cx_err_t cx_aes_gcm_process_and_tag(cx_aes_gcm_context_t *ctx,
333 CX_CHECK(cx_aes_gcm_start(ctx, mode, iv, iv_len));
334 CX_CHECK(cx_aes_gcm_update_aad(ctx, aad, aad_len));
335 CX_CHECK(cx_aes_gcm_update(ctx, in, out, len));
336 CX_CHECK(cx_aes_gcm_finish(ctx, tag, tag_len));
342 cx_err_t cx_aes_gcm_encrypt_and_tag(cx_aes_gcm_context_t *ctx,
353 return cx_aes_gcm_process_and_tag(
354 ctx,
CX_ENCRYPT, in, len, iv, iv_len, aad, aad_len, out, tag, tag_len);
357 cx_err_t cx_aes_gcm_decrypt_and_auth(cx_aes_gcm_context_t *ctx,
369 uint8_t check_tag[AES_BLOCK_BYTES];
372 CX_CHECK(cx_aes_gcm_process_and_tag(
373 ctx,
CX_DECRYPT, in, len, iv, iv_len, aad, aad_len, out, check_tag, tag_len));
375 error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE);
386 cx_err_t cx_aes_gcm_check_tag(cx_aes_gcm_context_t *ctx,
const uint8_t *tag,
size_t tag_len)
390 uint8_t check_tag[AES_GCM_TAG_LEN];
392 if (tag_len > AES_GCM_TAG_LEN) {
393 return CX_INVALID_PARAMETER_SIZE;
395 CX_CHECK(cx_aes_gcm_finish(ctx, check_tag, tag_len));
398 error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len)
Authenticated Encryption with Associated Data (AEAD)
AES (Advanced Encryption Standard).
AES in Galois/Counter Mode (AES-GCM)