4#if defined(HAVE_AES) && defined(HAVE_CMAC)
10static void cx_clear_bits(uint8_t *input)
16cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx)
25cx_err_t cx_aes_siv_reset(cx_aes_siv_context_t *ctx)
27 cx_err_t error = CX_INVALID_PARAMETER_VALUE;
28 if (ctx->cipher_ctx == NULL) {
31 if (ctx->cipher_ctx->cipher_info == NULL) {
35 CX_CHECK(ctx->cipher_ctx->cipher_info->base->ctx_reset());
44cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx,
const uint8_t *key,
size_t key_bitlen)
47 if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) {
48 return CX_INVALID_PARAMETER_SIZE;
51 ctx->key_len = key_bitlen / 2;
52 memcpy(ctx->key1, key, ctx->key_len / 8);
53 memcpy(ctx->key2, key + ctx->key_len / 8, ctx->key_len / 8);
57cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx,
62 uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0};
67 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
68 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE));
69 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
73 memcpy(iv_used, iv, iv_len);
74 cx_clear_bits(iv_used);
85cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx,
const uint8_t *aad,
size_t aad_len)
87 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
91 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
97 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
98 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, aad, aad_len));
99 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
100 cx_memxor(ctx->tag_state, tmp, CX_AES_BLOCK_SIZE);
101 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
107cx_err_t cx_aes_siv_update_mac(cx_aes_siv_context_t *ctx,
const uint8_t *input,
size_t in_len)
109 return cx_cmac_update(ctx->cipher_ctx, input, in_len);
112cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx,
113 const uint8_t *input,
117 size_t out_len = len;
125static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx,
const uint8_t *tag)
129 return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
132cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx,
133 const uint8_t *input,
137 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
140 if (in_len < CX_AES_BLOCK_SIZE) {
141 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
142 memset(ctx->tag_state, 0, CX_AES_BLOCK_SIZE);
143 memcpy(ctx->tag_state, input, in_len);
145 cx_memxor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE);
146 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, tmp, CX_AES_BLOCK_SIZE));
147 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
150 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, input, in_len - CX_AES_BLOCK_SIZE));
151 cx_memxor(ctx->tag_state, input + in_len - CX_AES_BLOCK_SIZE, CX_AES_BLOCK_SIZE);
152 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
153 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
156 return cx_aes_siv_check_tag(ctx, tag);
158 memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
160 cx_clear_bits(ctx->tag_state);
163 CX_CHECK(
cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
169cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx,
170 const uint8_t *input,
178 cx_err_t err_reset = CX_INTERNAL_ERROR;
179 CX_CHECK(cx_aes_siv_start(ctx,
CX_ENCRYPT, NULL, 0));
180 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
181 CX_CHECK(cx_aes_siv_finish(ctx, input, in_len, tag));
182 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
184 err_reset = cx_aes_siv_reset(ctx);
185 return error == CX_OK ? err_reset : error;
188cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx,
189 const uint8_t *input,
197 cx_err_t err_reset = CX_INTERNAL_ERROR;
198 CX_CHECK(cx_aes_siv_start(ctx,
CX_DECRYPT, tag, CX_AES_BLOCK_SIZE));
199 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
200 CX_CHECK(cx_aes_siv_reset(ctx));
201 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
202 CX_CHECK(cx_aes_siv_finish(ctx, output, in_len, tag));
205 err_reset = cx_aes_siv_reset(ctx);
206 return error == CX_OK ? err_reset : error;
uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len)
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)
Advanced Encryption Standard with Synthetic Initialization Vector (AES-SIV).
void cx_cipher_reset(cx_cipher_context_t *ctx)
void add_one_and_zeros_padding(uint8_t *output, size_t out_len, size_t data_len)
WARN_UNUSED_RESULT cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len, uint8_t *output, size_t *out_len)
Encrypt or decrypt with the given context.
WARN_UNUSED_RESULT cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t key_bitlen, uint32_t operation)
Set the key to use.
WARN_UNUSED_RESULT cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len)
Set the initialization vector.
WARN_UNUSED_RESULT cx_err_t cx_cipher_init(cx_cipher_context_t *ctx)
Initialize a cipher context as NONE.
WARN_UNUSED_RESULT cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, uint32_t mode)
Initialize and fill the context structure given the cipher info.
CMAC (Cipher-based Message Authentication Code).