18 #if defined(HAVE_CHACHA_POLY)
19 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
27 #define CHACHAPOLY_STATE_INIT 0
28 #define CHACHAPOLY_STATE_AAD 1
29 #define CHACHAPOLY_STATE_CIPHERTEXT 2
30 #define CHACHAPOLY_STATE_FINISHED 3
31 #define CHACHAPOLY_N_ROUNDS 20
32 #define CHACHAPOLY_TAG_LEN 16
34 #if defined(HAVE_AEAD)
35 static const cx_aead_base_t cx_chachapoly_functions = {
36 (void (*)(
void *ctx)) cx_chachapoly_init,
37 (cx_err_t(*)(
void *ctx,
const uint8_t *key,
size_t key_len)) cx_chachapoly_set_key,
38 (cx_err_t(*)(
void *ctx, uint32_t mode, const
uint8_t *iv,
size_t iv_len)) cx_chachapoly_start,
39 (cx_err_t(*)(
void *ctx, const
uint8_t *aad,
size_t aad_len)) cx_chachapoly_update_aad,
40 (cx_err_t(*)(
void *ctx, const
uint8_t *input,
uint8_t *output,
size_t len))
42 (cx_err_t(*)(
void *ctx,
uint8_t *tag,
size_t tag_len)) cx_chachapoly_finish,
43 (cx_err_t(*)(
void *ctx,
52 size_t tag_len)) cx_chachapoly_encrypt_and_tag,
53 (cx_err_t(*)(
void *ctx,
62 size_t tag_len)) cx_chachapoly_decrypt_and_auth,
63 (cx_err_t(*)(
void *ctx, const
uint8_t *tag,
size_t tag_len)) cx_chachapoly_check_tag};
65 const cx_aead_info_t cx_chacha20_poly1305_info
66 = {CX_AEAD_CHACHA20_POLY1305, 256, 512, &cx_chachapoly_functions};
69 void cx_chachapoly_init(cx_chachapoly_context_t *ctx)
71 cx_chacha_init(&ctx->chacha20_ctx, CHACHAPOLY_N_ROUNDS);
72 cx_poly1305_init(&ctx->poly1305_ctx);
74 ctx->ciphertext_len = 0;
75 ctx->state = CHACHAPOLY_STATE_INIT;
79 cx_err_t cx_chachapoly_set_key(cx_chachapoly_context_t *ctx,
const uint8_t *key,
size_t key_len)
81 return cx_chacha_set_key(&ctx->chacha20_ctx, key, key_len);
84 cx_err_t cx_chachapoly_start(cx_chachapoly_context_t *ctx,
93 CX_CHECK(cx_chacha_start(&ctx->chacha20_ctx, iv, iv_len));
100 memset(poly1305_key, 0,
sizeof(poly1305_key));
102 cx_chacha_update(&ctx->chacha20_ctx, poly1305_key, poly1305_key,
sizeof(poly1305_key)));
104 cx_poly1305_set_key(&ctx->poly1305_ctx, poly1305_key);
106 ctx->ciphertext_len = 0;
107 ctx->state = CHACHAPOLY_STATE_AAD;
111 memset(poly1305_key, 0, 64);
115 cx_err_t cx_chachapoly_update_aad(cx_chachapoly_context_t *ctx,
const uint8_t *aad,
size_t aad_len)
117 if (ctx->state != CHACHAPOLY_STATE_AAD) {
118 return CX_INTERNAL_ERROR;
121 ctx->aad_len += aad_len;
122 return cx_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
125 static cx_err_t cx_chachapoly_pad(cx_chachapoly_context_t *ctx,
size_t in_to_pad_len)
127 uint32_t pad_len = in_to_pad_len % 16;
128 unsigned char pad_bytes[15];
134 memset(pad_bytes, 0,
sizeof(pad_bytes));
135 return cx_poly1305_update(&ctx->poly1305_ctx, pad_bytes, 16 - pad_len);
138 cx_err_t cx_chachapoly_update(cx_chachapoly_context_t *ctx,
145 if ((ctx->state != CHACHAPOLY_STATE_AAD) && (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
146 return CX_INTERNAL_ERROR;
148 if (CHACHAPOLY_STATE_AAD == ctx->state) {
149 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
150 CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len));
152 ctx->ciphertext_len += len;
154 CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len));
155 CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, output, len));
158 CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, input, len));
159 CX_CHECK(cx_chacha_update(&ctx->chacha20_ctx, input, output, len));
165 cx_err_t cx_chachapoly_finish(cx_chachapoly_context_t *ctx,
uint8_t *tag,
size_t tag_len)
170 if (tag_len != CHACHAPOLY_TAG_LEN) {
171 return CX_INVALID_PARAMETER_VALUE;
174 if (CHACHAPOLY_STATE_INIT == ctx->state) {
175 return CX_INTERNAL_ERROR;
177 if (CHACHAPOLY_STATE_AAD == ctx->state) {
178 CX_CHECK(cx_chachapoly_pad(ctx, ctx->aad_len));
180 else if (CHACHAPOLY_STATE_CIPHERTEXT == ctx->state) {
181 CX_CHECK(cx_chachapoly_pad(ctx, ctx->ciphertext_len));
183 ctx->state = CHACHAPOLY_STATE_FINISHED;
187 memset(len_block, 0, 16);
188 U4LE_ENCODE(len_block, 0, ctx->aad_len);
189 U4LE_ENCODE(len_block, 8, ctx->ciphertext_len);
190 CX_CHECK(cx_poly1305_update(&ctx->poly1305_ctx, len_block, 16));
191 CX_CHECK(cx_poly1305_finish(&ctx->poly1305_ctx, tag));
197 static cx_err_t cx_chachapoly_process_and_tag(cx_chachapoly_context_t *ctx,
210 CX_CHECK(cx_chachapoly_start(ctx, mode, iv, iv_len));
211 CX_CHECK(cx_chachapoly_update_aad(ctx, aad, aad_len));
212 CX_CHECK(cx_chachapoly_update(ctx, input, output, len));
213 CX_CHECK(cx_chachapoly_finish(ctx, tag, tag_len));
218 cx_err_t cx_chachapoly_encrypt_and_tag(cx_chachapoly_context_t *ctx,
229 return cx_chachapoly_process_and_tag(
230 ctx,
CX_ENCRYPT, input, len, iv, iv_len, aad, aad_len, output, tag, tag_len);
233 cx_err_t cx_chachapoly_decrypt_and_auth(cx_chachapoly_context_t *ctx,
244 uint8_t check_tag[CHACHAPOLY_TAG_LEN];
248 memset(check_tag, 0, CHACHAPOLY_TAG_LEN);
249 CX_CHECK(cx_chachapoly_process_and_tag(
250 ctx,
CX_DECRYPT, input, len, iv, iv_len, aad, aad_len, output, check_tag, tag_len));
253 error = ((diff == 0) ? CX_OK : CX_INVALID_PARAMETER_VALUE);
255 memset(check_tag, 0, CHACHAPOLY_TAG_LEN);
262 cx_err_t cx_chachapoly_check_tag(cx_chachapoly_context_t *ctx,
const uint8_t *tag,
size_t tag_len)
266 uint8_t check_tag[CHACHAPOLY_TAG_LEN];
268 CX_CHECK(cx_chachapoly_finish(ctx, check_tag, tag_len));
271 error = diff * CX_INVALID_PARAMETER_VALUE + (1 - diff) * CX_OK;
uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len)