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 if (ctx->cipher_ctx->cipher_info == NULL) {
32 goto clear_ctx;
33 }
34
35 CX_CHECK(ctx->cipher_ctx->cipher_info->base->ctx_reset());
36
37clear_ctx:
38 cx_cipher_reset(ctx->cipher_ctx);
39
40end:
41 return error;
42}
43
44cx_err_t cx_aes_siv_set_key(cx_aes_siv_context_t *ctx, const uint8_t *key, size_t key_bitlen)
45{
46 // AES SIV uses two keys of either 128, 192 or 256 bits each
47 if (key_bitlen > AES_SIV_MAX_KEY_LEN * AES_SIV_KEY_NUMBER * 8) {
48 return CX_INVALID_PARAMETER_SIZE;
49 }
50
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);
54 return CX_OK;
55}
56
57cx_err_t cx_aes_siv_start(cx_aes_siv_context_t *ctx,
58 uint32_t mode,
59 const uint8_t *iv,
60 size_t iv_len)
61{
62 uint8_t iv_used[CX_AES_BLOCK_SIZE] = {0};
63 cx_err_t error;
64
65 // Set up cipher to be used for CMAC computation
66 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB));
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));
70
71 if (CX_DECRYPT == mode) {
72 // Prepare for the AES-CTR computation
73 memcpy(iv_used, iv, iv_len);
74 cx_clear_bits(iv_used);
75 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR));
76 CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT));
77 CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, iv_used, CX_AES_BLOCK_SIZE));
78 }
79 ctx->mode = mode;
80
81end:
82 return error;
83}
84
85cx_err_t cx_aes_siv_update_aad(cx_aes_siv_context_t *ctx, const uint8_t *aad, size_t aad_len)
86{
87 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
88 cx_err_t error;
89
90 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_ECB));
91 CX_CHECK(cx_cmac_start(ctx->cipher_ctx, ctx->key1, ctx->key_len));
92
93 if (NULL == aad) {
94 return CX_OK;
95 }
96
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));
102
103end:
104 return error;
105}
106
107cx_err_t cx_aes_siv_update_mac(cx_aes_siv_context_t *ctx, const uint8_t *input, size_t in_len)
108{
109 return cx_cmac_update(ctx->cipher_ctx, input, in_len);
110}
111
112cx_err_t cx_aes_siv_update(cx_aes_siv_context_t *ctx,
113 const uint8_t *input,
114 uint8_t *output,
115 size_t len)
116{
117 size_t out_len = len;
118 cx_err_t error;
119 CX_CHECK(cx_cipher_update(ctx->cipher_ctx, input, len, output, &out_len));
120
121end:
122 return error;
123}
124
125static cx_err_t cx_aes_siv_check_tag(cx_aes_siv_context_t *ctx, const uint8_t *tag)
126{
127 uint8_t diff;
128 diff = cx_constant_time_eq(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
129 return diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
130}
131
132cx_err_t cx_aes_siv_finish(cx_aes_siv_context_t *ctx,
133 const uint8_t *input,
134 size_t in_len,
135 uint8_t *tag)
136{
137 uint8_t tmp[CX_AES_BLOCK_SIZE] = {0};
138 cx_err_t error;
139
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);
144 add_one_and_zeros_padding(ctx->tag_state, CX_AES_BLOCK_SIZE, 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));
148 }
149 else {
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));
154 }
155 if (CX_DECRYPT == ctx->mode) {
156 return cx_aes_siv_check_tag(ctx, tag);
157 }
158 memcpy(tag, ctx->tag_state, CX_AES_BLOCK_SIZE);
159 // Prepare for the AES-CTR computation
160 cx_clear_bits(ctx->tag_state);
161 CX_CHECK(cx_cipher_setup(ctx->cipher_ctx, ctx->cipher_type, CX_CHAIN_CTR));
162 CX_CHECK(cx_cipher_setkey(ctx->cipher_ctx, ctx->key2, ctx->key_len, CX_ENCRYPT));
163 CX_CHECK(cx_cipher_setiv(ctx->cipher_ctx, ctx->tag_state, CX_AES_BLOCK_SIZE));
164
165end:
166 return error;
167}
168
169cx_err_t cx_aes_siv_encrypt(cx_aes_siv_context_t *ctx,
170 const uint8_t *input,
171 size_t in_len,
172 const uint8_t *aad,
173 size_t aad_len,
174 uint8_t *output,
175 uint8_t *tag)
176{
177 cx_err_t error;
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));
183end:
184 err_reset = cx_aes_siv_reset(ctx);
185 return error == CX_OK ? err_reset : error;
186}
187
188cx_err_t cx_aes_siv_decrypt(cx_aes_siv_context_t *ctx,
189 const uint8_t *input,
190 size_t in_len,
191 const uint8_t *aad,
192 size_t aad_len,
193 uint8_t *output,
194 uint8_t *tag)
195{
196 cx_err_t error;
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));
203
204end:
205 err_reset = cx_aes_siv_reset(ctx);
206 return error == CX_OK ? err_reset : error;
207}
208
209#endif // HAVE_AES && HAVE_CMAC
210#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