4 #if defined(HAVE_AES) && defined(HAVE_CMAC)
10 static void cx_clear_bits(
uint8_t *input)
16 cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx)
25 cx_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 CX_CHECK(ctx->cipher_ctx->cipher_info->base->ctx_reset());
38 cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx,
const uint8_t *key,
size_t key_bitlen)
41 if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) {
42 return CX_INVALID_PARAMETER_SIZE;
45 ctx->key_len = key_bitlen / 2;
46 memcpy(ctx->key1, key, ctx->key_len / 8);
47 memcpy(ctx->key2, key + ctx->key_len / 8, ctx->key_len / 8);
51 cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx,
56 uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0};
61 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
62 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE));
63 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
67 memcpy(iv_used, iv, iv_len);
68 cx_clear_bits(iv_used);
79 cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx,
const uint8_t *aad,
size_t aad_len)
81 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
85 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
91 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
92 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, aad, aad_len));
93 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
94 cx_memxor(ctx->tag_state, tmp, CX_AES_BLOCK_SIZE);
95 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
101 cx_err_t cx_aes_siv_update_mac(cx_aes_siv_context_t *ctx,
const uint8_t *input,
size_t in_len)
103 return cx_cmac_update(ctx->cipher_ctx, input, in_len);
106 cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx,
111 size_t out_len = len;
119 static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx,
const uint8_t *tag)
123 return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
126 cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx,
131 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
134 if (in_len < CX_AES_BLOCK_SIZE) {
135 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
136 memset(ctx->tag_state, 0, CX_AES_BLOCK_SIZE);
137 memcpy(ctx->tag_state, input, in_len);
139 cx_memxor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE);
140 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, tmp, CX_AES_BLOCK_SIZE));
141 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
144 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, input, in_len - CX_AES_BLOCK_SIZE));
145 cx_memxor(ctx->tag_state, input + in_len - CX_AES_BLOCK_SIZE, CX_AES_BLOCK_SIZE);
146 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
147 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
150 return cx_aes_siv_check_tag(ctx, tag);
152 memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
154 cx_clear_bits(ctx->tag_state);
157 CX_CHECK(
cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
163 cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx,
172 cx_err_t err_reset = CX_INTERNAL_ERROR;
173 CX_CHECK(cx_aes_siv_start(ctx,
CX_ENCRYPT, NULL, 0));
174 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
175 CX_CHECK(cx_aes_siv_finish(ctx, input, in_len, tag));
176 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
178 err_reset = cx_aes_siv_reset(ctx);
179 return error == CX_OK ? err_reset : error;
182 cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx,
191 cx_err_t err_reset = CX_INTERNAL_ERROR;
192 CX_CHECK(cx_aes_siv_start(ctx,
CX_DECRYPT, tag, CX_AES_BLOCK_SIZE));
193 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
194 CX_CHECK(cx_aes_siv_reset(ctx));
195 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
196 CX_CHECK(cx_aes_siv_finish(ctx, output, in_len, tag));
199 err_reset = cx_aes_siv_reset(ctx);
200 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).