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_set_key(cx_aes_siv_context_t *ctx,
const uint8_t *key,
size_t key_bitlen)
28 if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) {
29 return CX_INVALID_PARAMETER_SIZE;
32 ctx->key_len = key_bitlen / 2;
33 memcpy(ctx->key1, key, ctx->key_len / 8);
34 memcpy(ctx->key2, key + ctx->key_len / 8, ctx->key_len / 8);
38 cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx,
43 uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0};
48 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
49 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE));
50 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
54 memcpy(iv_used, iv, iv_len);
55 cx_clear_bits(iv_used);
66 cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx,
const uint8_t *aad,
size_t aad_len)
68 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
72 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
78 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
79 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, aad, aad_len));
80 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
81 cx_memxor(ctx->tag_state, tmp, CX_AES_BLOCK_SIZE);
82 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
88 cx_err_t cx_aes_siv_update_mac(cx_aes_siv_context_t *ctx,
const uint8_t *input,
size_t in_len)
90 return cx_cmac_update(ctx->cipher_ctx, input, in_len);
93 cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx,
106 static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx,
const uint8_t *tag)
110 return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
113 cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx,
118 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
121 if (in_len < CX_AES_BLOCK_SIZE) {
122 CX_CHECK(cx_cmac_shift_and_xor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE));
123 memset(ctx->tag_state, 0, CX_AES_BLOCK_SIZE);
124 memcpy(ctx->tag_state, input, in_len);
126 cx_memxor(tmp, ctx->tag_state, CX_AES_BLOCK_SIZE);
127 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, tmp, CX_AES_BLOCK_SIZE));
128 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
131 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, input, in_len - CX_AES_BLOCK_SIZE));
132 cx_memxor(ctx->tag_state, input + in_len - CX_AES_BLOCK_SIZE, CX_AES_BLOCK_SIZE);
133 CX_CHECK(cx_cmac_update(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
134 CX_CHECK(cx_cmac_finish(ctx->cipher_ctx, ctx->tag_state));
137 return cx_aes_siv_check_tag(ctx, tag);
139 memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
141 cx_clear_bits(ctx->tag_state);
144 CX_CHECK(
cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
150 cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx,
159 CX_CHECK(cx_aes_siv_start(ctx,
CX_ENCRYPT, NULL, 0));
160 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
161 CX_CHECK(cx_aes_siv_finish(ctx, input, in_len, tag));
162 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
167 cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx,
176 CX_CHECK(cx_aes_siv_start(ctx,
CX_DECRYPT, tag, CX_AES_BLOCK_SIZE));
177 CX_CHECK(cx_aes_siv_update(ctx, input, output, in_len));
179 CX_CHECK(cx_aes_siv_update_aad(ctx, aad, aad_len));
180 CX_CHECK(cx_aes_siv_finish(ctx, output, in_len, tag));
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).