Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_aes_siv.c
Go to the documentation of this file.
1/* @BANNER@ */
2
3#ifdef HAVE_AES_SIV
4#if defined(HAVE_AES) && defined(HAVE_CMAC)
5#include "cx_cmac.h"
6#include "cx_utils.h"
7#include "lcx_cmac.h"
8#include "lcx_aes_siv.h"
9
10static void cx_clear_bits(uint8_t *input)
11{
12 input[8] &= 0x7f;
13 input[12] &= 0x7f;
14}
15
16cx_err_t cx_aes_siv_init(cx_aes_siv_context_t *ctx)
17{
18 cx_err_t error;
19 CX_CHECK(cx_cipher_init(ctx->cipher_ctx));
20
21end:
22 return error;
23}
24
25cx_err_t cx_aes_siv_reset(cx_aes_siv_context_t *ctx)
26{
27 cx_err_t error = CX_INVALID_PARAMETER_VALUE;
28 if (ctx->cipher_ctx == NULL) {
29 goto end;
30 }
31 CX_CHECK(ctx->cipher_ctx->cipher_info->base->ctx_reset());
32 cx_cipher_reset(ctx->cipher_ctx);
33
34end:
35 return error;
36}
37
38cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, const uint8_t *key, size_t key_bitlen)
39{
40 // AES SIV uses two keys of either 128, 192 or 256 bits each
41 if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) {
42 return CX_INVALID_PARAMETER_SIZE;
43 }
44
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);
48 return CX_OK;
49}
50
51cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx,
52 uint32_t mode,
53 const uint8_t *iv,
54 size_t iv_len)
55{
56 uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0};
57 cx_err_t error;
58
59 // Set up cipher to be used for CMAC computation
60 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB));
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));
64
65 if (CX_DECRYPT == mode) {
66 // Prepare for the AES-CTR computation
67 memcpy(iv_used, iv, iv_len);
68 cx_clear_bits(iv_used);
69 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR));
70 CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT));
71 CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE));
72 }
73 ctx->mode = mode;
74
75end:
76 return error;
77}
78
79cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, const uint8_t *aad, size_t aad_len)
80{
81 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
82 cx_err_t error;
83
84 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB));
85 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
86
87 if (NULL == aad) {
88 return CX_OK;
89 }
90
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));
96
97end:
98 return error;
99}
100
101cx_err_t cx_aes_siv_update_mac(cx_aes_siv_context_t *ctx, const uint8_t *input, size_t in_len)
102{
103 return cx_cmac_update(ctx->cipher_ctx, input, in_len);
104}
105
106cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx,
107 const uint8_t *input,
108 uint8_t *output,
109 size_t len)
110{
111 size_t out_len = len;
112 cx_err_t error;
113 CX_CHECK(cx_cipher_update(ctx->cipher_ctx, input, len, output, &out_len));
114
115end:
116 return error;
117}
118
119static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx, const uint8_t *tag)
120{
121 uint8_t diff;
122 diff = cx_constant_time_eq(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
123 return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
124}
125
126cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx,
127 const uint8_t *input,
128 size_t in_len,
129 uint8_t *tag)
130{
131 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
132 cx_err_t error;
133
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);
138 add_one_and_zeros_padding(ctx->tag_state, CX_AES_BLOCK_SIZE, 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));
142 }
143 else {
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));
148 }
149 if (CX_DECRYPT == ctx->mode) {
150 return cx_aes_siv_check_tag(ctx, tag);
151 }
152 memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
153 // Prepare for the AES-CTR computation
154 cx_clear_bits(ctx->tag_state);
155 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR));
156 CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT));
157 CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
158
159end:
160 return error;
161}
162
163cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx,
164 const uint8_t *input,
165 size_t in_len,
166 const uint8_t *aad,
167 size_t aad_len,
168 uint8_t *output,
169 uint8_t *tag)
170{
171 cx_err_t error;
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));
177end:
178 err_reset = cx_aes_siv_reset(ctx);
179 return error == CX_OK ? err_reset : error;
180}
181
182cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx,
183 const uint8_t *input,
184 size_t in_len,
185 const uint8_t *aad,
186 size_t aad_len,
187 uint8_t *output,
188 uint8_t *tag)
189{
190 cx_err_t error;
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));
197
198end:
199 err_reset = cx_aes_siv_reset(ctx);
200 return error == CX_OK ? err_reset : error;
201}
202
203#endif // HAVE_AES && HAVE_CMAC
204#endif // HAVE_AES_SIV
uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len)
Definition cx_utils.c:181
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)
Definition cx_utils.c:173
Advanced Encryption Standard with Synthetic Initialization Vector (AES-SIV).
void cx_cipher_reset(cx_cipher_context_t *ctx)
Definition cx_cipher.c:516
void add_one_and_zeros_padding(uint8_t *output, size_t out_len, size_t data_len)
Definition cx_cipher.c:79
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.
Definition cx_cipher.c:324
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.
Definition cx_cipher.c:253
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.
Definition cx_cipher.c:276
WARN_UNUSED_RESULT cx_err_t cx_cipher_init(cx_cipher_context_t *ctx)
Initialize a cipher context as NONE.
Definition cx_cipher.c:209
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.
Definition cx_cipher.c:218
CMAC (Cipher-based Message Authentication Code).
#define CX_CHAIN_CTR
Definition lcx_common.h:148
#define CX_ENCRYPT
Definition lcx_common.h:126
#define CX_DECRYPT
Definition lcx_common.h:127
#define CX_CHAIN_ECB
Definition lcx_common.h:146
unsigned char uint8_t
Definition usbd_conf.h:53