1817466cbSJens Wiklander /**
2817466cbSJens Wiklander * \file cipher.c
3817466cbSJens Wiklander *
4b0563631STom Van Eyck * \brief Generic cipher wrapper for Mbed TLS
5817466cbSJens Wiklander *
6817466cbSJens Wiklander * \author Adriaan de Jong <dejong@fox-it.com>
7817466cbSJens Wiklander *
87901324dSJerome Forissier * Copyright The Mbed TLS Contributors
9b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
10817466cbSJens Wiklander */
11817466cbSJens Wiklander
127901324dSJerome Forissier #include "common.h"
13817466cbSJens Wiklander
14817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_C)
15817466cbSJens Wiklander
16817466cbSJens Wiklander #include "mbedtls/cipher.h"
17*273a583eSThomas Bourgoin #include "cipher_invasive.h"
1832b31808SJens Wiklander #include "cipher_wrap.h"
193d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2011fa71b9SJerome Forissier #include "mbedtls/error.h"
21039e02dfSJerome Forissier #include "mbedtls/constant_time.h"
22b0563631STom Van Eyck #include "constant_time_internal.h"
23817466cbSJens Wiklander
24817466cbSJens Wiklander #include <stdlib.h>
25817466cbSJens Wiklander #include <string.h>
26817466cbSJens Wiklander
273d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
283d3b0591SJens Wiklander #include "mbedtls/chachapoly.h"
293d3b0591SJens Wiklander #endif
303d3b0591SJens Wiklander
31817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
32817466cbSJens Wiklander #include "mbedtls/gcm.h"
33817466cbSJens Wiklander #endif
34817466cbSJens Wiklander
35817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
36817466cbSJens Wiklander #include "mbedtls/ccm.h"
37817466cbSJens Wiklander #endif
38817466cbSJens Wiklander
393d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
403d3b0591SJens Wiklander #include "mbedtls/chacha20.h"
413d3b0591SJens Wiklander #endif
423d3b0591SJens Wiklander
43817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C)
44817466cbSJens Wiklander #include "mbedtls/cmac.h"
45817466cbSJens Wiklander #endif
46817466cbSJens Wiklander
47b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
4811fa71b9SJerome Forissier #include "psa/crypto.h"
49b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
5011fa71b9SJerome Forissier
5111fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
5211fa71b9SJerome Forissier #include "mbedtls/nist_kw.h"
5311fa71b9SJerome Forissier #endif
5411fa71b9SJerome Forissier
55817466cbSJens Wiklander #include "mbedtls/platform.h"
56817466cbSJens Wiklander
57817466cbSJens Wiklander static int supported_init = 0;
58817466cbSJens Wiklander
mbedtls_cipher_get_base(const mbedtls_cipher_info_t * info)59b0563631STom Van Eyck static inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base(
60b0563631STom Van Eyck const mbedtls_cipher_info_t *info)
61b0563631STom Van Eyck {
62b0563631STom Van Eyck return mbedtls_cipher_base_lookup_table[info->base_idx];
63b0563631STom Van Eyck }
64b0563631STom Van Eyck
mbedtls_cipher_list(void)65817466cbSJens Wiklander const int *mbedtls_cipher_list(void)
66817466cbSJens Wiklander {
67817466cbSJens Wiklander const mbedtls_cipher_definition_t *def;
68817466cbSJens Wiklander int *type;
69817466cbSJens Wiklander
7032b31808SJens Wiklander if (!supported_init) {
71817466cbSJens Wiklander def = mbedtls_cipher_definitions;
72817466cbSJens Wiklander type = mbedtls_cipher_supported;
73817466cbSJens Wiklander
7432b31808SJens Wiklander while (def->type != 0) {
75817466cbSJens Wiklander *type++ = (*def++).type;
7632b31808SJens Wiklander }
77817466cbSJens Wiklander
78817466cbSJens Wiklander *type = 0;
79817466cbSJens Wiklander
80817466cbSJens Wiklander supported_init = 1;
81817466cbSJens Wiklander }
82817466cbSJens Wiklander
8332b31808SJens Wiklander return mbedtls_cipher_supported;
84817466cbSJens Wiklander }
85817466cbSJens Wiklander
mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type)8611fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
8711fa71b9SJerome Forissier const mbedtls_cipher_type_t cipher_type)
88817466cbSJens Wiklander {
89817466cbSJens Wiklander const mbedtls_cipher_definition_t *def;
90817466cbSJens Wiklander
9132b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
9232b31808SJens Wiklander if (def->type == cipher_type) {
9332b31808SJens Wiklander return def->info;
9432b31808SJens Wiklander }
9532b31808SJens Wiklander }
96817466cbSJens Wiklander
9732b31808SJens Wiklander return NULL;
98817466cbSJens Wiklander }
99817466cbSJens Wiklander
mbedtls_cipher_info_from_string(const char * cipher_name)10011fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
10111fa71b9SJerome Forissier const char *cipher_name)
102817466cbSJens Wiklander {
103817466cbSJens Wiklander const mbedtls_cipher_definition_t *def;
104817466cbSJens Wiklander
10532b31808SJens Wiklander if (NULL == cipher_name) {
10632b31808SJens Wiklander return NULL;
10732b31808SJens Wiklander }
108817466cbSJens Wiklander
10932b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
11032b31808SJens Wiklander if (!strcmp(def->info->name, cipher_name)) {
11132b31808SJens Wiklander return def->info;
11232b31808SJens Wiklander }
11332b31808SJens Wiklander }
114817466cbSJens Wiklander
11532b31808SJens Wiklander return NULL;
116817466cbSJens Wiklander }
117817466cbSJens Wiklander
mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id,int key_bitlen,const mbedtls_cipher_mode_t mode)11811fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
11911fa71b9SJerome Forissier const mbedtls_cipher_id_t cipher_id,
120817466cbSJens Wiklander int key_bitlen,
121817466cbSJens Wiklander const mbedtls_cipher_mode_t mode)
122817466cbSJens Wiklander {
123817466cbSJens Wiklander const mbedtls_cipher_definition_t *def;
124817466cbSJens Wiklander
12532b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
126b0563631STom Van Eyck if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id &&
127b0563631STom Van Eyck mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen &&
12832b31808SJens Wiklander def->info->mode == mode) {
12932b31808SJens Wiklander return def->info;
13032b31808SJens Wiklander }
13132b31808SJens Wiklander }
132817466cbSJens Wiklander
13332b31808SJens Wiklander return NULL;
134817466cbSJens Wiklander }
135817466cbSJens Wiklander
136b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_psa_translate_cipher_type(mbedtls_cipher_type_t cipher)137b0563631STom Van Eyck static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
138b0563631STom Van Eyck mbedtls_cipher_type_t cipher)
139b0563631STom Van Eyck {
140b0563631STom Van Eyck switch (cipher) {
141b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_128_CCM:
142b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_192_CCM:
143b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_256_CCM:
144b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG:
145b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG:
146b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG:
147b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_128_GCM:
148b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_192_GCM:
149b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_256_GCM:
150b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_128_CBC:
151b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_192_CBC:
152b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_256_CBC:
153b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_128_ECB:
154b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_192_ECB:
155b0563631STom Van Eyck case MBEDTLS_CIPHER_AES_256_ECB:
156b0563631STom Van Eyck return PSA_KEY_TYPE_AES;
157b0563631STom Van Eyck
158b0563631STom Van Eyck /* ARIA not yet supported in PSA. */
159b0563631STom Van Eyck /* case MBEDTLS_CIPHER_ARIA_128_CCM:
160b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_192_CCM:
161b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_256_CCM:
162b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG:
163b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG:
164b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG:
165b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_128_GCM:
166b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_192_GCM:
167b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_256_GCM:
168b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_128_CBC:
169b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_192_CBC:
170b0563631STom Van Eyck case MBEDTLS_CIPHER_ARIA_256_CBC:
171b0563631STom Van Eyck return( PSA_KEY_TYPE_ARIA ); */
172b0563631STom Van Eyck
173b0563631STom Van Eyck default:
174b0563631STom Van Eyck return 0;
175b0563631STom Van Eyck }
176b0563631STom Van Eyck }
177b0563631STom Van Eyck
mbedtls_psa_translate_cipher_mode(mbedtls_cipher_mode_t mode,size_t taglen)178b0563631STom Van Eyck static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
179b0563631STom Van Eyck mbedtls_cipher_mode_t mode, size_t taglen)
180b0563631STom Van Eyck {
181b0563631STom Van Eyck switch (mode) {
182b0563631STom Van Eyck case MBEDTLS_MODE_ECB:
183b0563631STom Van Eyck return PSA_ALG_ECB_NO_PADDING;
184b0563631STom Van Eyck case MBEDTLS_MODE_GCM:
185b0563631STom Van Eyck return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen);
186b0563631STom Van Eyck case MBEDTLS_MODE_CCM:
187b0563631STom Van Eyck return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen);
188b0563631STom Van Eyck case MBEDTLS_MODE_CCM_STAR_NO_TAG:
189b0563631STom Van Eyck return PSA_ALG_CCM_STAR_NO_TAG;
190b0563631STom Van Eyck case MBEDTLS_MODE_CBC:
191b0563631STom Van Eyck if (taglen == 0) {
192b0563631STom Van Eyck return PSA_ALG_CBC_NO_PADDING;
193b0563631STom Van Eyck } else {
194b0563631STom Van Eyck return 0;
195b0563631STom Van Eyck }
196b0563631STom Van Eyck default:
197b0563631STom Van Eyck return 0;
198b0563631STom Van Eyck }
199b0563631STom Van Eyck }
200b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
201b0563631STom Van Eyck
mbedtls_cipher_init(mbedtls_cipher_context_t * ctx)202817466cbSJens Wiklander void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx)
203817466cbSJens Wiklander {
204817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
205817466cbSJens Wiklander }
206817466cbSJens Wiklander
mbedtls_cipher_free(mbedtls_cipher_context_t * ctx)207817466cbSJens Wiklander void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx)
208817466cbSJens Wiklander {
20932b31808SJens Wiklander if (ctx == NULL) {
210817466cbSJens Wiklander return;
21132b31808SJens Wiklander }
212817466cbSJens Wiklander
213b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
21432b31808SJens Wiklander if (ctx->psa_enabled == 1) {
21532b31808SJens Wiklander if (ctx->cipher_ctx != NULL) {
21611fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa =
21711fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
21811fa71b9SJerome Forissier
21932b31808SJens Wiklander if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) {
22011fa71b9SJerome Forissier /* xxx_free() doesn't allow to return failures. */
22111fa71b9SJerome Forissier (void) psa_destroy_key(cipher_psa->slot);
22211fa71b9SJerome Forissier }
22311fa71b9SJerome Forissier
224b0563631STom Van Eyck mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa));
22511fa71b9SJerome Forissier }
22611fa71b9SJerome Forissier
22711fa71b9SJerome Forissier mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
22811fa71b9SJerome Forissier return;
22911fa71b9SJerome Forissier }
230b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
23111fa71b9SJerome Forissier
232817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C)
23332b31808SJens Wiklander if (ctx->cmac_ctx) {
234b0563631STom Van Eyck mbedtls_zeroize_and_free(ctx->cmac_ctx,
2353d3b0591SJens Wiklander sizeof(mbedtls_cmac_context_t));
236817466cbSJens Wiklander }
237817466cbSJens Wiklander #endif
238817466cbSJens Wiklander
23932b31808SJens Wiklander if (ctx->cipher_ctx) {
240b0563631STom Van Eyck mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx);
24132b31808SJens Wiklander }
242817466cbSJens Wiklander
2433d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
244817466cbSJens Wiklander }
245817466cbSJens Wiklander
mbedtls_cipher_clone(mbedtls_cipher_context_t * dst,const mbedtls_cipher_context_t * src)24612484fc7SEdison Ai int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst,
24712484fc7SEdison Ai const mbedtls_cipher_context_t *src)
24812484fc7SEdison Ai {
24912484fc7SEdison Ai if (dst == NULL || dst->cipher_info == NULL ||
25032b31808SJens Wiklander src == NULL || src->cipher_info == NULL) {
25132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
25212484fc7SEdison Ai }
25312484fc7SEdison Ai
25412484fc7SEdison Ai dst->cipher_info = src->cipher_info;
25512484fc7SEdison Ai dst->key_bitlen = src->key_bitlen;
25612484fc7SEdison Ai dst->operation = src->operation;
25712484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
25812484fc7SEdison Ai dst->add_padding = src->add_padding;
25912484fc7SEdison Ai dst->get_padding = src->get_padding;
26012484fc7SEdison Ai #endif
26112484fc7SEdison Ai memcpy(dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH);
26212484fc7SEdison Ai dst->unprocessed_len = src->unprocessed_len;
26312484fc7SEdison Ai memcpy(dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH);
26412484fc7SEdison Ai dst->iv_size = src->iv_size;
265b0563631STom Van Eyck if (mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func)
266b0563631STom Van Eyck mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx);
26712484fc7SEdison Ai
26812484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C)
26912484fc7SEdison Ai if (dst->cmac_ctx != NULL && src->cmac_ctx != NULL)
27012484fc7SEdison Ai memcpy(dst->cmac_ctx, src->cmac_ctx, sizeof(mbedtls_cmac_context_t));
27112484fc7SEdison Ai #endif
27232b31808SJens Wiklander return 0;
27312484fc7SEdison Ai }
27412484fc7SEdison Ai
mbedtls_cipher_setup(mbedtls_cipher_context_t * ctx,const mbedtls_cipher_info_t * cipher_info)27511fa71b9SJerome Forissier int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,
27611fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info)
277817466cbSJens Wiklander {
27832b31808SJens Wiklander if (cipher_info == NULL) {
27932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
28032b31808SJens Wiklander }
281817466cbSJens Wiklander
282817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
283817466cbSJens Wiklander
284b0563631STom Van Eyck if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) {
285b0563631STom Van Eyck ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func();
286b0563631STom Van Eyck if (ctx->cipher_ctx == NULL) {
28732b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
28832b31808SJens Wiklander }
289b0563631STom Van Eyck }
290817466cbSJens Wiklander
291817466cbSJens Wiklander ctx->cipher_info = cipher_info;
292817466cbSJens Wiklander
29332b31808SJens Wiklander return 0;
294817466cbSJens Wiklander }
295817466cbSJens Wiklander
296b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_cipher_setup_psa(mbedtls_cipher_context_t * ctx,const mbedtls_cipher_info_t * cipher_info,size_t taglen)29711fa71b9SJerome Forissier int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,
29811fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info,
29911fa71b9SJerome Forissier size_t taglen)
30011fa71b9SJerome Forissier {
30111fa71b9SJerome Forissier psa_algorithm_t alg;
30211fa71b9SJerome Forissier mbedtls_cipher_context_psa *cipher_psa;
30311fa71b9SJerome Forissier
30432b31808SJens Wiklander if (NULL == cipher_info || NULL == ctx) {
30532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
30632b31808SJens Wiklander }
30711fa71b9SJerome Forissier
30811fa71b9SJerome Forissier /* Check that the underlying cipher mode and cipher type are
30911fa71b9SJerome Forissier * supported by the underlying PSA Crypto implementation. */
310b0563631STom Van Eyck alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen);
31132b31808SJens Wiklander if (alg == 0) {
31232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
31332b31808SJens Wiklander }
314b0563631STom Van Eyck if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) {
31532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
31632b31808SJens Wiklander }
31711fa71b9SJerome Forissier
31811fa71b9SJerome Forissier memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
31911fa71b9SJerome Forissier
32011fa71b9SJerome Forissier cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa));
32132b31808SJens Wiklander if (cipher_psa == NULL) {
32232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
32332b31808SJens Wiklander }
32411fa71b9SJerome Forissier cipher_psa->alg = alg;
32511fa71b9SJerome Forissier ctx->cipher_ctx = cipher_psa;
32611fa71b9SJerome Forissier ctx->cipher_info = cipher_info;
32711fa71b9SJerome Forissier ctx->psa_enabled = 1;
32832b31808SJens Wiklander return 0;
32911fa71b9SJerome Forissier }
330b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
33111fa71b9SJerome Forissier
mbedtls_cipher_setup_info(mbedtls_cipher_context_t * ctx,const mbedtls_cipher_info_t * cipher_info)33232b31808SJens Wiklander int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx,
33332b31808SJens Wiklander const mbedtls_cipher_info_t *cipher_info )
33412484fc7SEdison Ai {
33512484fc7SEdison Ai if (NULL == cipher_info || NULL == ctx)
33632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
33712484fc7SEdison Ai
33812484fc7SEdison Ai ctx->cipher_info = cipher_info;
33932b31808SJens Wiklander return 0;
34012484fc7SEdison Ai }
34112484fc7SEdison Ai
mbedtls_cipher_setkey(mbedtls_cipher_context_t * ctx,const unsigned char * key,int key_bitlen,const mbedtls_operation_t operation)3423d3b0591SJens Wiklander int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
3433d3b0591SJens Wiklander const unsigned char *key,
3443d3b0591SJens Wiklander int key_bitlen,
3453d3b0591SJens Wiklander const mbedtls_operation_t operation)
346817466cbSJens Wiklander {
34732b31808SJens Wiklander if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) {
34832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
34932b31808SJens Wiklander }
35032b31808SJens Wiklander if (ctx->cipher_info == NULL) {
35132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
35232b31808SJens Wiklander }
353b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
354b0563631STom Van Eyck if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) &&
355b0563631STom Van Eyck MBEDTLS_DECRYPT == operation) {
356b0563631STom Van Eyck return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
357b0563631STom Van Eyck }
358b0563631STom Van Eyck #endif
359817466cbSJens Wiklander
360b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
36132b31808SJens Wiklander if (ctx->psa_enabled == 1) {
36211fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa =
36311fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
36411fa71b9SJerome Forissier
36511fa71b9SJerome Forissier size_t const key_bytelen = ((size_t) key_bitlen + 7) / 8;
36611fa71b9SJerome Forissier
36711fa71b9SJerome Forissier psa_status_t status;
36811fa71b9SJerome Forissier psa_key_type_t key_type;
36911fa71b9SJerome Forissier psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
37011fa71b9SJerome Forissier
37111fa71b9SJerome Forissier /* PSA Crypto API only accepts byte-aligned keys. */
37232b31808SJens Wiklander if (key_bitlen % 8 != 0) {
37332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
37432b31808SJens Wiklander }
37511fa71b9SJerome Forissier
37611fa71b9SJerome Forissier /* Don't allow keys to be set multiple times. */
37732b31808SJens Wiklander if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) {
37832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
37932b31808SJens Wiklander }
38011fa71b9SJerome Forissier
38111fa71b9SJerome Forissier key_type = mbedtls_psa_translate_cipher_type(
382b0563631STom Van Eyck ((mbedtls_cipher_type_t) ctx->cipher_info->type));
38332b31808SJens Wiklander if (key_type == 0) {
38432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
38532b31808SJens Wiklander }
38611fa71b9SJerome Forissier psa_set_key_type(&attributes, key_type);
38711fa71b9SJerome Forissier
38811fa71b9SJerome Forissier /* Mbed TLS' cipher layer doesn't enforce the mode of operation
38911fa71b9SJerome Forissier * (encrypt vs. decrypt): it is possible to setup a key for encryption
39011fa71b9SJerome Forissier * and use it for AEAD decryption. Until tests relying on this
39111fa71b9SJerome Forissier * are changed, allow any usage in PSA. */
39211fa71b9SJerome Forissier psa_set_key_usage_flags(&attributes,
39311fa71b9SJerome Forissier PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
39411fa71b9SJerome Forissier psa_set_key_algorithm(&attributes, cipher_psa->alg);
39511fa71b9SJerome Forissier
39611fa71b9SJerome Forissier status = psa_import_key(&attributes, key, key_bytelen,
39711fa71b9SJerome Forissier &cipher_psa->slot);
39832b31808SJens Wiklander switch (status) {
39911fa71b9SJerome Forissier case PSA_SUCCESS:
40011fa71b9SJerome Forissier break;
40111fa71b9SJerome Forissier case PSA_ERROR_INSUFFICIENT_MEMORY:
40232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
40311fa71b9SJerome Forissier case PSA_ERROR_NOT_SUPPORTED:
40432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
40511fa71b9SJerome Forissier default:
40632b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
40711fa71b9SJerome Forissier }
40811fa71b9SJerome Forissier /* Indicate that we own the key slot and need to
40911fa71b9SJerome Forissier * destroy it in mbedtls_cipher_free(). */
41011fa71b9SJerome Forissier cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED;
41111fa71b9SJerome Forissier
41211fa71b9SJerome Forissier ctx->key_bitlen = key_bitlen;
41311fa71b9SJerome Forissier ctx->operation = operation;
41432b31808SJens Wiklander return 0;
41511fa71b9SJerome Forissier }
416b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
41711fa71b9SJerome Forissier
418817466cbSJens Wiklander if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 &&
419b0563631STom Van Eyck (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) {
42032b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
421817466cbSJens Wiklander }
422817466cbSJens Wiklander
423817466cbSJens Wiklander ctx->key_bitlen = key_bitlen;
424817466cbSJens Wiklander ctx->operation = operation;
425817466cbSJens Wiklander
426b0563631STom Van Eyck #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
427817466cbSJens Wiklander /*
4283d3b0591SJens Wiklander * For OFB, CFB and CTR mode always use the encryption key schedule
429817466cbSJens Wiklander */
430817466cbSJens Wiklander if (MBEDTLS_ENCRYPT == operation ||
431b0563631STom Van Eyck MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
432b0563631STom Van Eyck MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
433b0563631STom Van Eyck MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
434b0563631STom Van Eyck return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,
43532b31808SJens Wiklander ctx->key_bitlen);
436817466cbSJens Wiklander }
437817466cbSJens Wiklander
43832b31808SJens Wiklander if (MBEDTLS_DECRYPT == operation) {
439b0563631STom Van Eyck return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key,
44032b31808SJens Wiklander ctx->key_bitlen);
44132b31808SJens Wiklander }
442b0563631STom Van Eyck #else
443b0563631STom Van Eyck if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) {
444b0563631STom Van Eyck return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,
445b0563631STom Van Eyck ctx->key_bitlen);
446b0563631STom Van Eyck }
447b0563631STom Van Eyck #endif
448817466cbSJens Wiklander
44932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
450817466cbSJens Wiklander }
451817466cbSJens Wiklander
mbedtls_cipher_set_iv(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len)452817466cbSJens Wiklander int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
4533d3b0591SJens Wiklander const unsigned char *iv,
4543d3b0591SJens Wiklander size_t iv_len)
455817466cbSJens Wiklander {
456817466cbSJens Wiklander size_t actual_iv_size;
457817466cbSJens Wiklander
45832b31808SJens Wiklander if (ctx->cipher_info == NULL) {
45932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
46032b31808SJens Wiklander }
461b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
46232b31808SJens Wiklander if (ctx->psa_enabled == 1) {
46311fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
46411fa71b9SJerome Forissier * operations, we currently don't make it
46511fa71b9SJerome Forissier * accessible through the cipher layer. */
46632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
46711fa71b9SJerome Forissier }
468b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
469817466cbSJens Wiklander
470817466cbSJens Wiklander /* avoid buffer overflow in ctx->iv */
47132b31808SJens Wiklander if (iv_len > MBEDTLS_MAX_IV_LENGTH) {
47232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
47332b31808SJens Wiklander }
474817466cbSJens Wiklander
47532b31808SJens Wiklander if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) {
476817466cbSJens Wiklander actual_iv_size = iv_len;
47732b31808SJens Wiklander } else {
478b0563631STom Van Eyck actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info);
479817466cbSJens Wiklander
480817466cbSJens Wiklander /* avoid reading past the end of input buffer */
48132b31808SJens Wiklander if (actual_iv_size > iv_len) {
48232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
48332b31808SJens Wiklander }
484817466cbSJens Wiklander }
485817466cbSJens Wiklander
4863d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
487b0563631STom Van Eyck if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) {
488039e02dfSJerome Forissier /* Even though the actual_iv_size is overwritten with a correct value
489039e02dfSJerome Forissier * of 12 from the cipher info, return an error to indicate that
490039e02dfSJerome Forissier * the input iv_len is wrong. */
49132b31808SJens Wiklander if (iv_len != 12) {
49232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
49332b31808SJens Wiklander }
494039e02dfSJerome Forissier
4953d3b0591SJens Wiklander if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx,
4963d3b0591SJens Wiklander iv,
49732b31808SJens Wiklander 0U)) { /* Initial counter value */
49832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
4993d3b0591SJens Wiklander }
5003d3b0591SJens Wiklander }
501039e02dfSJerome Forissier #if defined(MBEDTLS_CHACHAPOLY_C)
502b0563631STom Van Eyck if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
50332b31808SJens Wiklander iv_len != 12) {
50432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
50532b31808SJens Wiklander }
506039e02dfSJerome Forissier #endif
5073d3b0591SJens Wiklander #endif
5083d3b0591SJens Wiklander
50932b31808SJens Wiklander #if defined(MBEDTLS_GCM_C)
510b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
51132b31808SJens Wiklander return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx,
51232b31808SJens Wiklander ctx->operation,
51332b31808SJens Wiklander iv, iv_len);
51432b31808SJens Wiklander }
51532b31808SJens Wiklander #endif
51632b31808SJens Wiklander
51732b31808SJens Wiklander #if defined(MBEDTLS_CCM_C)
518b0563631STom Van Eyck if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
51932b31808SJens Wiklander int set_lengths_result;
52032b31808SJens Wiklander int ccm_star_mode;
52132b31808SJens Wiklander
52232b31808SJens Wiklander set_lengths_result = mbedtls_ccm_set_lengths(
52332b31808SJens Wiklander (mbedtls_ccm_context *) ctx->cipher_ctx,
52432b31808SJens Wiklander 0, 0, 0);
52532b31808SJens Wiklander if (set_lengths_result != 0) {
52632b31808SJens Wiklander return set_lengths_result;
52732b31808SJens Wiklander }
52832b31808SJens Wiklander
52932b31808SJens Wiklander if (ctx->operation == MBEDTLS_DECRYPT) {
53032b31808SJens Wiklander ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT;
53132b31808SJens Wiklander } else if (ctx->operation == MBEDTLS_ENCRYPT) {
53232b31808SJens Wiklander ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT;
53332b31808SJens Wiklander } else {
53432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
53532b31808SJens Wiklander }
53632b31808SJens Wiklander
53732b31808SJens Wiklander return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx,
53832b31808SJens Wiklander ccm_star_mode,
53932b31808SJens Wiklander iv, iv_len);
54032b31808SJens Wiklander }
54132b31808SJens Wiklander #endif
54232b31808SJens Wiklander
54332b31808SJens Wiklander if (actual_iv_size != 0) {
544817466cbSJens Wiklander memcpy(ctx->iv, iv, actual_iv_size);
545817466cbSJens Wiklander ctx->iv_size = actual_iv_size;
5463d3b0591SJens Wiklander }
547817466cbSJens Wiklander
54832b31808SJens Wiklander return 0;
549817466cbSJens Wiklander }
550817466cbSJens Wiklander
mbedtls_cipher_reset(mbedtls_cipher_context_t * ctx)551817466cbSJens Wiklander int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx)
552817466cbSJens Wiklander {
55332b31808SJens Wiklander if (ctx->cipher_info == NULL) {
55432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
55532b31808SJens Wiklander }
556817466cbSJens Wiklander
557b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
55832b31808SJens Wiklander if (ctx->psa_enabled == 1) {
55911fa71b9SJerome Forissier /* We don't support resetting PSA-based
56011fa71b9SJerome Forissier * cipher contexts, yet. */
56132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
56211fa71b9SJerome Forissier }
563b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
56411fa71b9SJerome Forissier
565817466cbSJens Wiklander ctx->unprocessed_len = 0;
566817466cbSJens Wiklander
56732b31808SJens Wiklander return 0;
568817466cbSJens Wiklander }
569817466cbSJens Wiklander
5703d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
mbedtls_cipher_update_ad(mbedtls_cipher_context_t * ctx,const unsigned char * ad,size_t ad_len)571817466cbSJens Wiklander int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,
572817466cbSJens Wiklander const unsigned char *ad, size_t ad_len)
573817466cbSJens Wiklander {
57432b31808SJens Wiklander if (ctx->cipher_info == NULL) {
57532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
57632b31808SJens Wiklander }
577817466cbSJens Wiklander
578b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
57932b31808SJens Wiklander if (ctx->psa_enabled == 1) {
58011fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
58111fa71b9SJerome Forissier * operations, we currently don't make it
58211fa71b9SJerome Forissier * accessible through the cipher layer. */
58332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
58411fa71b9SJerome Forissier }
585b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
58611fa71b9SJerome Forissier
5873d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
588b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
58932b31808SJens Wiklander return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx,
59032b31808SJens Wiklander ad, ad_len);
591817466cbSJens Wiklander }
5923d3b0591SJens Wiklander #endif
5933d3b0591SJens Wiklander
5943d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
595b0563631STom Van Eyck if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
5963d3b0591SJens Wiklander int result;
5973d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode;
5983d3b0591SJens Wiklander
5993d3b0591SJens Wiklander mode = (ctx->operation == MBEDTLS_ENCRYPT)
6003d3b0591SJens Wiklander ? MBEDTLS_CHACHAPOLY_ENCRYPT
6013d3b0591SJens Wiklander : MBEDTLS_CHACHAPOLY_DECRYPT;
6023d3b0591SJens Wiklander
6033d3b0591SJens Wiklander result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx,
6043d3b0591SJens Wiklander ctx->iv,
6053d3b0591SJens Wiklander mode);
60632b31808SJens Wiklander if (result != 0) {
60732b31808SJens Wiklander return result;
60832b31808SJens Wiklander }
6093d3b0591SJens Wiklander
61032b31808SJens Wiklander return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx,
61132b31808SJens Wiklander ad, ad_len);
6123d3b0591SJens Wiklander }
6133d3b0591SJens Wiklander #endif
614817466cbSJens Wiklander
61532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
616817466cbSJens Wiklander }
6173d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
618817466cbSJens Wiklander
mbedtls_cipher_update(mbedtls_cipher_context_t * ctx,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen)619817466cbSJens Wiklander int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input,
620817466cbSJens Wiklander size_t ilen, unsigned char *output, size_t *olen)
621817466cbSJens Wiklander {
62211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6233d3b0591SJens Wiklander size_t block_size;
624817466cbSJens Wiklander
62532b31808SJens Wiklander if (ctx->cipher_info == NULL) {
62632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
62732b31808SJens Wiklander }
628817466cbSJens Wiklander
629b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
63032b31808SJens Wiklander if (ctx->psa_enabled == 1) {
63111fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
63211fa71b9SJerome Forissier * operations, we currently don't make it
63311fa71b9SJerome Forissier * accessible through the cipher layer. */
63432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
63511fa71b9SJerome Forissier }
636b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
63711fa71b9SJerome Forissier
638817466cbSJens Wiklander *olen = 0;
639817466cbSJens Wiklander block_size = mbedtls_cipher_get_block_size(ctx);
64032b31808SJens Wiklander if (0 == block_size) {
64132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
6425b25c76aSJerome Forissier }
643817466cbSJens Wiklander
644b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) {
64532b31808SJens Wiklander if (ilen != block_size) {
64632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
64732b31808SJens Wiklander }
648817466cbSJens Wiklander
649817466cbSJens Wiklander *olen = ilen;
650817466cbSJens Wiklander
651b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx,
652b0563631STom Van Eyck ctx->operation, input,
653b0563631STom Van Eyck output))) {
65432b31808SJens Wiklander return ret;
655817466cbSJens Wiklander }
656817466cbSJens Wiklander
65732b31808SJens Wiklander return 0;
658817466cbSJens Wiklander }
659817466cbSJens Wiklander
660817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
661b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) {
66232b31808SJens Wiklander return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx,
66332b31808SJens Wiklander input, ilen,
66432b31808SJens Wiklander output, ilen, olen);
66532b31808SJens Wiklander }
66632b31808SJens Wiklander #endif
66732b31808SJens Wiklander
66832b31808SJens Wiklander #if defined(MBEDTLS_CCM_C)
669b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) {
67032b31808SJens Wiklander return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx,
67132b31808SJens Wiklander input, ilen,
67232b31808SJens Wiklander output, ilen, olen);
6733d3b0591SJens Wiklander }
6743d3b0591SJens Wiklander #endif
6753d3b0591SJens Wiklander
6763d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
677b0563631STom Van Eyck if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) {
6783d3b0591SJens Wiklander *olen = ilen;
67932b31808SJens Wiklander return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx,
68032b31808SJens Wiklander ilen, input, output);
681817466cbSJens Wiklander }
682817466cbSJens Wiklander #endif
683817466cbSJens Wiklander
684817466cbSJens Wiklander if (input == output &&
68532b31808SJens Wiklander (ctx->unprocessed_len != 0 || ilen % block_size)) {
68632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
687817466cbSJens Wiklander }
688817466cbSJens Wiklander
689817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC)
690b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) {
691817466cbSJens Wiklander size_t copy_len = 0;
692817466cbSJens Wiklander
693817466cbSJens Wiklander /*
694817466cbSJens Wiklander * If there is not enough data for a full block, cache it.
695817466cbSJens Wiklander */
6963d3b0591SJens Wiklander if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
697817466cbSJens Wiklander ilen <= block_size - ctx->unprocessed_len) ||
6983d3b0591SJens Wiklander (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
6993d3b0591SJens Wiklander ilen < block_size - ctx->unprocessed_len) ||
700817466cbSJens Wiklander (ctx->operation == MBEDTLS_ENCRYPT &&
70132b31808SJens Wiklander ilen < block_size - ctx->unprocessed_len)) {
702817466cbSJens Wiklander memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,
703817466cbSJens Wiklander ilen);
704817466cbSJens Wiklander
705817466cbSJens Wiklander ctx->unprocessed_len += ilen;
70632b31808SJens Wiklander return 0;
707817466cbSJens Wiklander }
708817466cbSJens Wiklander
709817466cbSJens Wiklander /*
710817466cbSJens Wiklander * Process cached data first
711817466cbSJens Wiklander */
71232b31808SJens Wiklander if (0 != ctx->unprocessed_len) {
713817466cbSJens Wiklander copy_len = block_size - ctx->unprocessed_len;
714817466cbSJens Wiklander
715817466cbSJens Wiklander memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,
716817466cbSJens Wiklander copy_len);
717817466cbSJens Wiklander
718b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
719b0563631STom Van Eyck ctx->operation,
720b0563631STom Van Eyck block_size, ctx->iv,
721b0563631STom Van Eyck ctx->
722b0563631STom Van Eyck unprocessed_data,
723b0563631STom Van Eyck output))) {
72432b31808SJens Wiklander return ret;
725817466cbSJens Wiklander }
726817466cbSJens Wiklander
727817466cbSJens Wiklander *olen += block_size;
728817466cbSJens Wiklander output += block_size;
729817466cbSJens Wiklander ctx->unprocessed_len = 0;
730817466cbSJens Wiklander
731817466cbSJens Wiklander input += copy_len;
732817466cbSJens Wiklander ilen -= copy_len;
733817466cbSJens Wiklander }
734817466cbSJens Wiklander
735817466cbSJens Wiklander /*
736817466cbSJens Wiklander * Cache final, incomplete block
737817466cbSJens Wiklander */
73832b31808SJens Wiklander if (0 != ilen) {
7393d3b0591SJens Wiklander /* Encryption: only cache partial blocks
7403d3b0591SJens Wiklander * Decryption w/ padding: always keep at least one whole block
7413d3b0591SJens Wiklander * Decryption w/o padding: only cache partial blocks
7423d3b0591SJens Wiklander */
743817466cbSJens Wiklander copy_len = ilen % block_size;
7443d3b0591SJens Wiklander if (copy_len == 0 &&
7453d3b0591SJens Wiklander ctx->operation == MBEDTLS_DECRYPT &&
74632b31808SJens Wiklander NULL != ctx->add_padding) {
747817466cbSJens Wiklander copy_len = block_size;
7483d3b0591SJens Wiklander }
749817466cbSJens Wiklander
750817466cbSJens Wiklander memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]),
751817466cbSJens Wiklander copy_len);
752817466cbSJens Wiklander
753817466cbSJens Wiklander ctx->unprocessed_len += copy_len;
754817466cbSJens Wiklander ilen -= copy_len;
755817466cbSJens Wiklander }
756817466cbSJens Wiklander
757817466cbSJens Wiklander /*
758817466cbSJens Wiklander * Process remaining full blocks
759817466cbSJens Wiklander */
76032b31808SJens Wiklander if (ilen) {
761b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
762b0563631STom Van Eyck ctx->operation,
763b0563631STom Van Eyck ilen, ctx->iv,
764b0563631STom Van Eyck input,
76532b31808SJens Wiklander output))) {
76632b31808SJens Wiklander return ret;
767817466cbSJens Wiklander }
768817466cbSJens Wiklander
769817466cbSJens Wiklander *olen += ilen;
770817466cbSJens Wiklander }
771817466cbSJens Wiklander
77232b31808SJens Wiklander return 0;
773817466cbSJens Wiklander }
774817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */
775817466cbSJens Wiklander
776817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB)
777b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) {
778b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx,
77932b31808SJens Wiklander ctx->operation, ilen,
780b0563631STom Van Eyck &ctx->unprocessed_len,
781b0563631STom Van Eyck ctx->iv,
78232b31808SJens Wiklander input, output))) {
78332b31808SJens Wiklander return ret;
784817466cbSJens Wiklander }
785817466cbSJens Wiklander
786817466cbSJens Wiklander *olen = ilen;
787817466cbSJens Wiklander
78832b31808SJens Wiklander return 0;
789817466cbSJens Wiklander }
790817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */
791817466cbSJens Wiklander
7923d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB)
793b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) {
794b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx,
795b0563631STom Van Eyck ilen,
796b0563631STom Van Eyck &ctx->unprocessed_len,
797b0563631STom Van Eyck ctx->iv,
79832b31808SJens Wiklander input, output))) {
79932b31808SJens Wiklander return ret;
8003d3b0591SJens Wiklander }
8013d3b0591SJens Wiklander
8023d3b0591SJens Wiklander *olen = ilen;
8033d3b0591SJens Wiklander
80432b31808SJens Wiklander return 0;
8053d3b0591SJens Wiklander }
8063d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */
8073d3b0591SJens Wiklander
808817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR)
809b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) {
810b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx,
811b0563631STom Van Eyck ilen,
812b0563631STom Van Eyck &ctx->unprocessed_len,
813b0563631STom Van Eyck ctx->iv,
814b0563631STom Van Eyck ctx->unprocessed_data,
815b0563631STom Van Eyck input, output))) {
81632b31808SJens Wiklander return ret;
817817466cbSJens Wiklander }
818817466cbSJens Wiklander
819817466cbSJens Wiklander *olen = ilen;
820817466cbSJens Wiklander
82132b31808SJens Wiklander return 0;
822817466cbSJens Wiklander }
823817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */
824817466cbSJens Wiklander
8253d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS)
826b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) {
8273d3b0591SJens Wiklander if (ctx->unprocessed_len > 0) {
8283d3b0591SJens Wiklander /* We can only process an entire data unit at a time. */
82932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
8303d3b0591SJens Wiklander }
8313d3b0591SJens Wiklander
832b0563631STom Van Eyck ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx,
833b0563631STom Van Eyck ctx->operation,
834b0563631STom Van Eyck ilen,
835b0563631STom Van Eyck ctx->iv,
836b0563631STom Van Eyck input,
837b0563631STom Van Eyck output);
83832b31808SJens Wiklander if (ret != 0) {
83932b31808SJens Wiklander return ret;
8403d3b0591SJens Wiklander }
8413d3b0591SJens Wiklander
8423d3b0591SJens Wiklander *olen = ilen;
8433d3b0591SJens Wiklander
84432b31808SJens Wiklander return 0;
8453d3b0591SJens Wiklander }
8463d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */
8473d3b0591SJens Wiklander
848817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM)
849b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) {
850b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx,
851b0563631STom Van Eyck ilen, input,
852b0563631STom Van Eyck output))) {
85332b31808SJens Wiklander return ret;
854817466cbSJens Wiklander }
855817466cbSJens Wiklander
856817466cbSJens Wiklander *olen = ilen;
857817466cbSJens Wiklander
85832b31808SJens Wiklander return 0;
859817466cbSJens Wiklander }
860817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */
861817466cbSJens Wiklander
86232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
863817466cbSJens Wiklander }
864817466cbSJens Wiklander
865817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
866817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
867817466cbSJens Wiklander /*
868817466cbSJens Wiklander * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
869817466cbSJens Wiklander */
add_pkcs_padding(unsigned char * output,size_t output_len,size_t data_len)870817466cbSJens Wiklander static void add_pkcs_padding(unsigned char *output, size_t output_len,
871817466cbSJens Wiklander size_t data_len)
872817466cbSJens Wiklander {
873817466cbSJens Wiklander size_t padding_len = output_len - data_len;
874817466cbSJens Wiklander unsigned char i;
875817466cbSJens Wiklander
87632b31808SJens Wiklander for (i = 0; i < padding_len; i++) {
877817466cbSJens Wiklander output[data_len + i] = (unsigned char) padding_len;
878817466cbSJens Wiklander }
87932b31808SJens Wiklander }
880817466cbSJens Wiklander
881*273a583eSThomas Bourgoin /*
882*273a583eSThomas Bourgoin * Get the length of the PKCS7 padding.
883*273a583eSThomas Bourgoin *
884*273a583eSThomas Bourgoin * Note: input_len must be the block size of the cipher.
885*273a583eSThomas Bourgoin */
mbedtls_get_pkcs_padding(unsigned char * input,size_t input_len,size_t * data_len)886*273a583eSThomas Bourgoin MBEDTLS_STATIC_TESTABLE int mbedtls_get_pkcs_padding(unsigned char *input,
887*273a583eSThomas Bourgoin size_t input_len,
888817466cbSJens Wiklander size_t *data_len)
889817466cbSJens Wiklander {
890817466cbSJens Wiklander size_t i, pad_idx;
891b0563631STom Van Eyck unsigned char padding_len;
892817466cbSJens Wiklander
89332b31808SJens Wiklander if (NULL == input || NULL == data_len) {
89432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
89532b31808SJens Wiklander }
896817466cbSJens Wiklander
897817466cbSJens Wiklander padding_len = input[input_len - 1];
898817466cbSJens Wiklander
899b0563631STom Van Eyck mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
900b0563631STom Van Eyck bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
901817466cbSJens Wiklander
902817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len,
903817466cbSJens Wiklander * so pick input_len, which is usually 8 or 16 (one block) */
904817466cbSJens Wiklander pad_idx = input_len - padding_len;
90532b31808SJens Wiklander for (i = 0; i < input_len; i++) {
906b0563631STom Van Eyck mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx);
907b0563631STom Van Eyck mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len);
908b0563631STom Van Eyck bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));
90932b31808SJens Wiklander }
910817466cbSJens Wiklander
911*273a583eSThomas Bourgoin /* If the padding is invalid, set the output length to 0 */
912*273a583eSThomas Bourgoin *data_len = mbedtls_ct_if(bad, 0, input_len - padding_len);
913*273a583eSThomas Bourgoin
914b0563631STom Van Eyck return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
915817466cbSJens Wiklander }
916817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
917817466cbSJens Wiklander
918817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
919817466cbSJens Wiklander /*
920817466cbSJens Wiklander * One and zeros padding: fill with 80 00 ... 00
921817466cbSJens Wiklander */
add_one_and_zeros_padding(unsigned char * output,size_t output_len,size_t data_len)922817466cbSJens Wiklander static void add_one_and_zeros_padding(unsigned char *output,
923817466cbSJens Wiklander size_t output_len, size_t data_len)
924817466cbSJens Wiklander {
925817466cbSJens Wiklander size_t padding_len = output_len - data_len;
926817466cbSJens Wiklander unsigned char i = 0;
927817466cbSJens Wiklander
928817466cbSJens Wiklander output[data_len] = 0x80;
92932b31808SJens Wiklander for (i = 1; i < padding_len; i++) {
930817466cbSJens Wiklander output[data_len + i] = 0x00;
931817466cbSJens Wiklander }
93232b31808SJens Wiklander }
933817466cbSJens Wiklander
get_one_and_zeros_padding(unsigned char * input,size_t input_len,size_t * data_len)934817466cbSJens Wiklander static int get_one_and_zeros_padding(unsigned char *input, size_t input_len,
935817466cbSJens Wiklander size_t *data_len)
936817466cbSJens Wiklander {
93732b31808SJens Wiklander if (NULL == input || NULL == data_len) {
93832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
93932b31808SJens Wiklander }
940817466cbSJens Wiklander
941b0563631STom Van Eyck mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE;
942b0563631STom Van Eyck mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE;
943b0563631STom Van Eyck
944817466cbSJens Wiklander *data_len = 0;
945b0563631STom Van Eyck
946b0563631STom Van Eyck for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) {
947b0563631STom Van Eyck mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]);
948b0563631STom Van Eyck
949b0563631STom Van Eyck mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding);
950b0563631STom Van Eyck
951b0563631STom Van Eyck *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len);
952b0563631STom Van Eyck
953b0563631STom Van Eyck bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad);
954b0563631STom Van Eyck
955b0563631STom Van Eyck in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero));
956817466cbSJens Wiklander }
957817466cbSJens Wiklander
958b0563631STom Van Eyck return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
959817466cbSJens Wiklander }
960817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
961817466cbSJens Wiklander
962817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
963817466cbSJens Wiklander /*
964817466cbSJens Wiklander * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
965817466cbSJens Wiklander */
add_zeros_and_len_padding(unsigned char * output,size_t output_len,size_t data_len)966817466cbSJens Wiklander static void add_zeros_and_len_padding(unsigned char *output,
967817466cbSJens Wiklander size_t output_len, size_t data_len)
968817466cbSJens Wiklander {
969817466cbSJens Wiklander size_t padding_len = output_len - data_len;
970817466cbSJens Wiklander unsigned char i = 0;
971817466cbSJens Wiklander
97232b31808SJens Wiklander for (i = 1; i < padding_len; i++) {
973817466cbSJens Wiklander output[data_len + i - 1] = 0x00;
97432b31808SJens Wiklander }
975817466cbSJens Wiklander output[output_len - 1] = (unsigned char) padding_len;
976817466cbSJens Wiklander }
977817466cbSJens Wiklander
get_zeros_and_len_padding(unsigned char * input,size_t input_len,size_t * data_len)978817466cbSJens Wiklander static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
979817466cbSJens Wiklander size_t *data_len)
980817466cbSJens Wiklander {
981817466cbSJens Wiklander size_t i, pad_idx;
982b0563631STom Van Eyck unsigned char padding_len;
983b0563631STom Van Eyck mbedtls_ct_condition_t bad;
984817466cbSJens Wiklander
98532b31808SJens Wiklander if (NULL == input || NULL == data_len) {
98632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
98732b31808SJens Wiklander }
988817466cbSJens Wiklander
989817466cbSJens Wiklander padding_len = input[input_len - 1];
990817466cbSJens Wiklander *data_len = input_len - padding_len;
991817466cbSJens Wiklander
992817466cbSJens Wiklander /* Avoid logical || since it results in a branch */
993b0563631STom Van Eyck bad = mbedtls_ct_uint_gt(padding_len, input_len);
994b0563631STom Van Eyck bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
995817466cbSJens Wiklander
996817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len */
997817466cbSJens Wiklander pad_idx = input_len - padding_len;
99832b31808SJens Wiklander for (i = 0; i < input_len - 1; i++) {
999b0563631STom Van Eyck mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx);
1000b0563631STom Van Eyck mbedtls_ct_condition_t nonzero_pad_byte;
1001b0563631STom Van Eyck nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i]));
1002b0563631STom Van Eyck bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte);
100332b31808SJens Wiklander }
1004817466cbSJens Wiklander
1005b0563631STom Van Eyck return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
1006817466cbSJens Wiklander }
1007817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
1008817466cbSJens Wiklander
1009817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
1010817466cbSJens Wiklander /*
1011817466cbSJens Wiklander * Zero padding: fill with 00 ... 00
1012817466cbSJens Wiklander */
add_zeros_padding(unsigned char * output,size_t output_len,size_t data_len)1013817466cbSJens Wiklander static void add_zeros_padding(unsigned char *output,
1014817466cbSJens Wiklander size_t output_len, size_t data_len)
1015817466cbSJens Wiklander {
1016b0563631STom Van Eyck memset(output + data_len, 0, output_len - data_len);
101732b31808SJens Wiklander }
1018817466cbSJens Wiklander
get_zeros_padding(unsigned char * input,size_t input_len,size_t * data_len)1019817466cbSJens Wiklander static int get_zeros_padding(unsigned char *input, size_t input_len,
1020817466cbSJens Wiklander size_t *data_len)
1021817466cbSJens Wiklander {
1022817466cbSJens Wiklander size_t i;
1023b0563631STom Van Eyck mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done;
1024817466cbSJens Wiklander
102532b31808SJens Wiklander if (NULL == input || NULL == data_len) {
102632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
102732b31808SJens Wiklander }
1028817466cbSJens Wiklander
1029817466cbSJens Wiklander *data_len = 0;
103032b31808SJens Wiklander for (i = input_len; i > 0; i--) {
1031817466cbSJens Wiklander prev_done = done;
1032b0563631STom Van Eyck done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0));
1033b0563631STom Van Eyck *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len);
1034817466cbSJens Wiklander }
1035817466cbSJens Wiklander
103632b31808SJens Wiklander return 0;
1037817466cbSJens Wiklander }
1038817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
1039817466cbSJens Wiklander
1040817466cbSJens Wiklander /*
1041817466cbSJens Wiklander * No padding: don't pad :)
1042817466cbSJens Wiklander *
1043817466cbSJens Wiklander * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
1044817466cbSJens Wiklander * but a trivial get_padding function
1045817466cbSJens Wiklander */
get_no_padding(unsigned char * input,size_t input_len,size_t * data_len)1046817466cbSJens Wiklander static int get_no_padding(unsigned char *input, size_t input_len,
1047817466cbSJens Wiklander size_t *data_len)
1048817466cbSJens Wiklander {
104932b31808SJens Wiklander if (NULL == input || NULL == data_len) {
105032b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
105132b31808SJens Wiklander }
1052817466cbSJens Wiklander
1053817466cbSJens Wiklander *data_len = input_len;
1054817466cbSJens Wiklander
105532b31808SJens Wiklander return 0;
1056817466cbSJens Wiklander }
1057817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
1058817466cbSJens Wiklander
mbedtls_cipher_finish(mbedtls_cipher_context_t * ctx,unsigned char * output,size_t * olen)1059817466cbSJens Wiklander int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
1060817466cbSJens Wiklander unsigned char *output, size_t *olen)
1061817466cbSJens Wiklander {
106232b31808SJens Wiklander if (ctx->cipher_info == NULL) {
106332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
106432b31808SJens Wiklander }
1065817466cbSJens Wiklander
1066b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
106732b31808SJens Wiklander if (ctx->psa_enabled == 1) {
106811fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
106911fa71b9SJerome Forissier * operations, we currently don't make it
107011fa71b9SJerome Forissier * accessible through the cipher layer. */
107132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
107211fa71b9SJerome Forissier }
1073b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
107411fa71b9SJerome Forissier
1075817466cbSJens Wiklander *olen = 0;
1076817466cbSJens Wiklander
1077b0563631STom Van Eyck #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
1078b0563631STom Van Eyck /* CBC mode requires padding so we make sure a call to
1079b0563631STom Van Eyck * mbedtls_cipher_set_padding_mode has been done successfully. */
1080b0563631STom Van Eyck if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
1081b0563631STom Van Eyck if (ctx->get_padding == NULL) {
1082b0563631STom Van Eyck return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1083b0563631STom Van Eyck }
1084b0563631STom Van Eyck }
1085b0563631STom Van Eyck #endif
1086b0563631STom Van Eyck
1087b0563631STom Van Eyck if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1088b0563631STom Van Eyck MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1089b0563631STom Van Eyck MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1090b0563631STom Van Eyck MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1091b0563631STom Van Eyck MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1092b0563631STom Van Eyck MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1093b0563631STom Van Eyck MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
109432b31808SJens Wiklander return 0;
1095817466cbSJens Wiklander }
1096817466cbSJens Wiklander
1097b0563631STom Van Eyck if ((MBEDTLS_CIPHER_CHACHA20 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) ||
1098b0563631STom Van Eyck (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) {
109932b31808SJens Wiklander return 0;
11003d3b0591SJens Wiklander }
11013d3b0591SJens Wiklander
1102b0563631STom Van Eyck if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
110332b31808SJens Wiklander if (ctx->unprocessed_len != 0) {
110432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
110532b31808SJens Wiklander }
1106817466cbSJens Wiklander
110732b31808SJens Wiklander return 0;
1108817466cbSJens Wiklander }
1109817466cbSJens Wiklander
1110817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC)
1111b0563631STom Van Eyck if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
1112817466cbSJens Wiklander int ret = 0;
1113817466cbSJens Wiklander
111432b31808SJens Wiklander if (MBEDTLS_ENCRYPT == ctx->operation) {
1115817466cbSJens Wiklander /* check for 'no padding' mode */
111632b31808SJens Wiklander if (NULL == ctx->add_padding) {
111732b31808SJens Wiklander if (0 != ctx->unprocessed_len) {
111832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
111932b31808SJens Wiklander }
1120817466cbSJens Wiklander
112132b31808SJens Wiklander return 0;
1122817466cbSJens Wiklander }
1123817466cbSJens Wiklander
1124817466cbSJens Wiklander ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx),
1125817466cbSJens Wiklander ctx->unprocessed_len);
112632b31808SJens Wiklander } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) {
1127817466cbSJens Wiklander /*
1128817466cbSJens Wiklander * For decrypt operations, expect a full block,
1129817466cbSJens Wiklander * or an empty block if no padding
1130817466cbSJens Wiklander */
113132b31808SJens Wiklander if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) {
113232b31808SJens Wiklander return 0;
113332b31808SJens Wiklander }
1134817466cbSJens Wiklander
113532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
1136817466cbSJens Wiklander }
1137817466cbSJens Wiklander
1138817466cbSJens Wiklander /* cipher block */
1139b0563631STom Van Eyck if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
114032b31808SJens Wiklander ctx->operation,
1141b0563631STom Van Eyck mbedtls_cipher_get_block_size(
1142b0563631STom Van Eyck ctx),
114332b31808SJens Wiklander ctx->iv,
1144b0563631STom Van Eyck ctx->unprocessed_data,
1145b0563631STom Van Eyck output))) {
114632b31808SJens Wiklander return ret;
1147817466cbSJens Wiklander }
1148817466cbSJens Wiklander
1149817466cbSJens Wiklander /* Set output size for decryption */
115032b31808SJens Wiklander if (MBEDTLS_DECRYPT == ctx->operation) {
115132b31808SJens Wiklander return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx),
115232b31808SJens Wiklander olen);
115332b31808SJens Wiklander }
1154817466cbSJens Wiklander
1155817466cbSJens Wiklander /* Set output size for encryption */
1156817466cbSJens Wiklander *olen = mbedtls_cipher_get_block_size(ctx);
115732b31808SJens Wiklander return 0;
1158817466cbSJens Wiklander }
1159817466cbSJens Wiklander #else
1160817466cbSJens Wiklander ((void) output);
1161817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */
1162817466cbSJens Wiklander
116332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1164817466cbSJens Wiklander }
1165817466cbSJens Wiklander
1166817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t * ctx,mbedtls_cipher_padding_t mode)11673d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,
11683d3b0591SJens Wiklander mbedtls_cipher_padding_t mode)
1169817466cbSJens Wiklander {
1170b0563631STom Van Eyck if (NULL == ctx->cipher_info ||
1171b0563631STom Van Eyck MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
117232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1173817466cbSJens Wiklander }
1174817466cbSJens Wiklander
1175b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
117632b31808SJens Wiklander if (ctx->psa_enabled == 1) {
117711fa71b9SJerome Forissier /* While PSA Crypto knows about CBC padding
117811fa71b9SJerome Forissier * schemes, we currently don't make them
117911fa71b9SJerome Forissier * accessible through the cipher layer. */
118032b31808SJens Wiklander if (mode != MBEDTLS_PADDING_NONE) {
118132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
118232b31808SJens Wiklander }
118311fa71b9SJerome Forissier
118432b31808SJens Wiklander return 0;
118511fa71b9SJerome Forissier }
1186b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
118711fa71b9SJerome Forissier
118832b31808SJens Wiklander switch (mode) {
1189817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
1190817466cbSJens Wiklander case MBEDTLS_PADDING_PKCS7:
1191817466cbSJens Wiklander ctx->add_padding = add_pkcs_padding;
1192*273a583eSThomas Bourgoin ctx->get_padding = mbedtls_get_pkcs_padding;
1193817466cbSJens Wiklander break;
1194817466cbSJens Wiklander #endif
1195817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
1196817466cbSJens Wiklander case MBEDTLS_PADDING_ONE_AND_ZEROS:
1197817466cbSJens Wiklander ctx->add_padding = add_one_and_zeros_padding;
1198817466cbSJens Wiklander ctx->get_padding = get_one_and_zeros_padding;
1199817466cbSJens Wiklander break;
1200817466cbSJens Wiklander #endif
1201817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
1202817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS_AND_LEN:
1203817466cbSJens Wiklander ctx->add_padding = add_zeros_and_len_padding;
1204817466cbSJens Wiklander ctx->get_padding = get_zeros_and_len_padding;
1205817466cbSJens Wiklander break;
1206817466cbSJens Wiklander #endif
1207817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
1208817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS:
1209817466cbSJens Wiklander ctx->add_padding = add_zeros_padding;
1210817466cbSJens Wiklander ctx->get_padding = get_zeros_padding;
1211817466cbSJens Wiklander break;
1212817466cbSJens Wiklander #endif
1213817466cbSJens Wiklander case MBEDTLS_PADDING_NONE:
1214817466cbSJens Wiklander ctx->add_padding = NULL;
1215817466cbSJens Wiklander ctx->get_padding = get_no_padding;
1216817466cbSJens Wiklander break;
1217817466cbSJens Wiklander
1218817466cbSJens Wiklander default:
121932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1220817466cbSJens Wiklander }
1221817466cbSJens Wiklander
122232b31808SJens Wiklander return 0;
1223817466cbSJens Wiklander }
1224817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
1225817466cbSJens Wiklander
12263d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
mbedtls_cipher_write_tag(mbedtls_cipher_context_t * ctx,unsigned char * tag,size_t tag_len)1227817466cbSJens Wiklander int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,
1228817466cbSJens Wiklander unsigned char *tag, size_t tag_len)
1229817466cbSJens Wiklander {
123032b31808SJens Wiklander if (ctx->cipher_info == NULL) {
123132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
123232b31808SJens Wiklander }
1233817466cbSJens Wiklander
123432b31808SJens Wiklander if (MBEDTLS_ENCRYPT != ctx->operation) {
123532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
123632b31808SJens Wiklander }
1237817466cbSJens Wiklander
1238b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
123932b31808SJens Wiklander if (ctx->psa_enabled == 1) {
124011fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
124111fa71b9SJerome Forissier * operations, we currently don't make it
124211fa71b9SJerome Forissier * accessible through the cipher layer. */
124332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
124411fa71b9SJerome Forissier }
1245b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
124611fa71b9SJerome Forissier
12473d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
1248b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
124932b31808SJens Wiklander size_t output_length;
125032b31808SJens Wiklander /* The code here doesn't yet support alternative implementations
125132b31808SJens Wiklander * that can delay up to a block of output. */
125232b31808SJens Wiklander return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx,
125332b31808SJens Wiklander NULL, 0, &output_length,
125432b31808SJens Wiklander tag, tag_len);
12553d3b0591SJens Wiklander }
12563d3b0591SJens Wiklander #endif
1257817466cbSJens Wiklander
125832b31808SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
1259b0563631STom Van Eyck if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
126032b31808SJens Wiklander /* Don't allow truncated MAC for Poly1305 */
126132b31808SJens Wiklander if (tag_len != 16U) {
126232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
126332b31808SJens Wiklander }
126432b31808SJens Wiklander
126532b31808SJens Wiklander return mbedtls_chachapoly_finish(
126632b31808SJens Wiklander (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag);
126732b31808SJens Wiklander }
126832b31808SJens Wiklander #endif
126932b31808SJens Wiklander
127032b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1271817466cbSJens Wiklander }
1272817466cbSJens Wiklander
mbedtls_cipher_check_tag(mbedtls_cipher_context_t * ctx,const unsigned char * tag,size_t tag_len)1273817466cbSJens Wiklander int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,
1274817466cbSJens Wiklander const unsigned char *tag, size_t tag_len)
1275817466cbSJens Wiklander {
12763d3b0591SJens Wiklander unsigned char check_tag[16];
127711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1278817466cbSJens Wiklander
127932b31808SJens Wiklander if (ctx->cipher_info == NULL) {
128032b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
128132b31808SJens Wiklander }
12823d3b0591SJens Wiklander
128332b31808SJens Wiklander if (MBEDTLS_DECRYPT != ctx->operation) {
128432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1285817466cbSJens Wiklander }
1286817466cbSJens Wiklander
1287b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
128832b31808SJens Wiklander if (ctx->psa_enabled == 1) {
128911fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart
129011fa71b9SJerome Forissier * operations, we currently don't make it
129111fa71b9SJerome Forissier * accessible through the cipher layer. */
129232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
129311fa71b9SJerome Forissier }
1294b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
129511fa71b9SJerome Forissier
129632b31808SJens Wiklander /* Status to return on a non-authenticated algorithm. */
129732b31808SJens Wiklander ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1298039e02dfSJerome Forissier
12993d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
1300b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
130132b31808SJens Wiklander size_t output_length;
130232b31808SJens Wiklander /* The code here doesn't yet support alternative implementations
130332b31808SJens Wiklander * that can delay up to a block of output. */
130432b31808SJens Wiklander
130532b31808SJens Wiklander if (tag_len > sizeof(check_tag)) {
130632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
130732b31808SJens Wiklander }
1308817466cbSJens Wiklander
130911fa71b9SJerome Forissier if (0 != (ret = mbedtls_gcm_finish(
131011fa71b9SJerome Forissier (mbedtls_gcm_context *) ctx->cipher_ctx,
131132b31808SJens Wiklander NULL, 0, &output_length,
131232b31808SJens Wiklander check_tag, tag_len))) {
131332b31808SJens Wiklander return ret;
1314817466cbSJens Wiklander }
1315817466cbSJens Wiklander
1316817466cbSJens Wiklander /* Check the tag in "constant-time" */
131732b31808SJens Wiklander if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {
1318039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1319039e02dfSJerome Forissier goto exit;
1320039e02dfSJerome Forissier }
1321817466cbSJens Wiklander }
13223d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */
13233d3b0591SJens Wiklander
13243d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
1325b0563631STom Van Eyck if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
13263d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */
132732b31808SJens Wiklander if (tag_len != sizeof(check_tag)) {
132832b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
132932b31808SJens Wiklander }
13303d3b0591SJens Wiklander
133111fa71b9SJerome Forissier ret = mbedtls_chachapoly_finish(
133211fa71b9SJerome Forissier (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag);
133332b31808SJens Wiklander if (ret != 0) {
133432b31808SJens Wiklander return ret;
13353d3b0591SJens Wiklander }
13363d3b0591SJens Wiklander
13373d3b0591SJens Wiklander /* Check the tag in "constant-time" */
133832b31808SJens Wiklander if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {
1339039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1340039e02dfSJerome Forissier goto exit;
1341039e02dfSJerome Forissier }
1342817466cbSJens Wiklander }
13433d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
13443d3b0591SJens Wiklander
1345039e02dfSJerome Forissier exit:
1346039e02dfSJerome Forissier mbedtls_platform_zeroize(check_tag, tag_len);
134732b31808SJens Wiklander return ret;
13483d3b0591SJens Wiklander }
13493d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
1350817466cbSJens Wiklander
1351817466cbSJens Wiklander /*
1352817466cbSJens Wiklander * Packet-oriented wrapper for non-AEAD modes
1353817466cbSJens Wiklander */
mbedtls_cipher_crypt(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen)1354817466cbSJens Wiklander int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,
1355817466cbSJens Wiklander const unsigned char *iv, size_t iv_len,
1356817466cbSJens Wiklander const unsigned char *input, size_t ilen,
1357817466cbSJens Wiklander unsigned char *output, size_t *olen)
1358817466cbSJens Wiklander {
135911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1360817466cbSJens Wiklander size_t finish_olen;
1361817466cbSJens Wiklander
1362b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
136332b31808SJens Wiklander if (ctx->psa_enabled == 1) {
136411fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that
136511fa71b9SJerome Forissier * a key has been set. If not, the key slot will
136611fa71b9SJerome Forissier * still be in its default state of 0, which is
136711fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call
136811fa71b9SJerome Forissier * below will gracefully fail. */
136911fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa =
137011fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
137111fa71b9SJerome Forissier
137211fa71b9SJerome Forissier psa_status_t status;
137311fa71b9SJerome Forissier psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
137411fa71b9SJerome Forissier size_t part_len;
137511fa71b9SJerome Forissier
137632b31808SJens Wiklander if (ctx->operation == MBEDTLS_DECRYPT) {
137711fa71b9SJerome Forissier status = psa_cipher_decrypt_setup(&cipher_op,
137811fa71b9SJerome Forissier cipher_psa->slot,
137911fa71b9SJerome Forissier cipher_psa->alg);
138032b31808SJens Wiklander } else if (ctx->operation == MBEDTLS_ENCRYPT) {
138111fa71b9SJerome Forissier status = psa_cipher_encrypt_setup(&cipher_op,
138211fa71b9SJerome Forissier cipher_psa->slot,
138311fa71b9SJerome Forissier cipher_psa->alg);
138432b31808SJens Wiklander } else {
138532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
138611fa71b9SJerome Forissier }
138711fa71b9SJerome Forissier
138811fa71b9SJerome Forissier /* In the following, we can immediately return on an error,
138911fa71b9SJerome Forissier * because the PSA Crypto API guarantees that cipher operations
139011fa71b9SJerome Forissier * are terminated by unsuccessful calls to psa_cipher_update(),
139111fa71b9SJerome Forissier * and by any call to psa_cipher_finish(). */
139232b31808SJens Wiklander if (status != PSA_SUCCESS) {
139332b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
139432b31808SJens Wiklander }
139511fa71b9SJerome Forissier
1396b0563631STom Van Eyck if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) {
139711fa71b9SJerome Forissier status = psa_cipher_set_iv(&cipher_op, iv, iv_len);
139832b31808SJens Wiklander if (status != PSA_SUCCESS) {
139932b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
140032b31808SJens Wiklander }
1401039e02dfSJerome Forissier }
140211fa71b9SJerome Forissier
140311fa71b9SJerome Forissier status = psa_cipher_update(&cipher_op,
140411fa71b9SJerome Forissier input, ilen,
140511fa71b9SJerome Forissier output, ilen, olen);
140632b31808SJens Wiklander if (status != PSA_SUCCESS) {
140732b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
140832b31808SJens Wiklander }
140911fa71b9SJerome Forissier
141011fa71b9SJerome Forissier status = psa_cipher_finish(&cipher_op,
141111fa71b9SJerome Forissier output + *olen, ilen - *olen,
141211fa71b9SJerome Forissier &part_len);
141332b31808SJens Wiklander if (status != PSA_SUCCESS) {
141432b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
141532b31808SJens Wiklander }
141611fa71b9SJerome Forissier
141711fa71b9SJerome Forissier *olen += part_len;
141832b31808SJens Wiklander return 0;
141911fa71b9SJerome Forissier }
1420b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
142111fa71b9SJerome Forissier
142232b31808SJens Wiklander if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) {
142332b31808SJens Wiklander return ret;
142432b31808SJens Wiklander }
1425817466cbSJens Wiklander
142632b31808SJens Wiklander if ((ret = mbedtls_cipher_reset(ctx)) != 0) {
142732b31808SJens Wiklander return ret;
142832b31808SJens Wiklander }
1429817466cbSJens Wiklander
143011fa71b9SJerome Forissier if ((ret = mbedtls_cipher_update(ctx, input, ilen,
143132b31808SJens Wiklander output, olen)) != 0) {
143232b31808SJens Wiklander return ret;
143332b31808SJens Wiklander }
1434817466cbSJens Wiklander
143511fa71b9SJerome Forissier if ((ret = mbedtls_cipher_finish(ctx, output + *olen,
143632b31808SJens Wiklander &finish_olen)) != 0) {
143732b31808SJens Wiklander return ret;
143832b31808SJens Wiklander }
1439817466cbSJens Wiklander
1440817466cbSJens Wiklander *olen += finish_olen;
1441817466cbSJens Wiklander
144232b31808SJens Wiklander return 0;
1443817466cbSJens Wiklander }
1444817466cbSJens Wiklander
1445817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD)
1446817466cbSJens Wiklander /*
144732b31808SJens Wiklander * Packet-oriented encryption for AEAD modes: internal function used by
144832b31808SJens Wiklander * mbedtls_cipher_auth_encrypt_ext().
1449817466cbSJens Wiklander */
mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len,const unsigned char * ad,size_t ad_len,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen,unsigned char * tag,size_t tag_len)14507901324dSJerome Forissier static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
1451817466cbSJens Wiklander const unsigned char *iv, size_t iv_len,
1452817466cbSJens Wiklander const unsigned char *ad, size_t ad_len,
1453817466cbSJens Wiklander const unsigned char *input, size_t ilen,
1454817466cbSJens Wiklander unsigned char *output, size_t *olen,
1455817466cbSJens Wiklander unsigned char *tag, size_t tag_len)
1456817466cbSJens Wiklander {
1457b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
145832b31808SJens Wiklander if (ctx->psa_enabled == 1) {
145911fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that
146011fa71b9SJerome Forissier * a key has been set. If not, the key slot will
146111fa71b9SJerome Forissier * still be in its default state of 0, which is
146211fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call
146311fa71b9SJerome Forissier * below will gracefully fail. */
146411fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa =
146511fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
146611fa71b9SJerome Forissier
146711fa71b9SJerome Forissier psa_status_t status;
146811fa71b9SJerome Forissier
146911fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag
147011fa71b9SJerome Forissier * at the end of the encrypted message. */
147132b31808SJens Wiklander if (output == NULL || tag != output + ilen) {
147232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
147332b31808SJens Wiklander }
147411fa71b9SJerome Forissier
147511fa71b9SJerome Forissier status = psa_aead_encrypt(cipher_psa->slot,
147611fa71b9SJerome Forissier cipher_psa->alg,
147711fa71b9SJerome Forissier iv, iv_len,
147811fa71b9SJerome Forissier ad, ad_len,
147911fa71b9SJerome Forissier input, ilen,
148011fa71b9SJerome Forissier output, ilen + tag_len, olen);
148132b31808SJens Wiklander if (status != PSA_SUCCESS) {
148232b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
148332b31808SJens Wiklander }
148411fa71b9SJerome Forissier
148511fa71b9SJerome Forissier *olen -= tag_len;
148632b31808SJens Wiklander return 0;
148711fa71b9SJerome Forissier }
1488b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
148911fa71b9SJerome Forissier
1490817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
1491b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
1492817466cbSJens Wiklander *olen = ilen;
149332b31808SJens Wiklander return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
149411fa71b9SJerome Forissier ilen, iv, iv_len, ad, ad_len,
149532b31808SJens Wiklander input, output, tag_len, tag);
1496817466cbSJens Wiklander }
1497817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1498817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
1499b0563631STom Van Eyck if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
1500817466cbSJens Wiklander *olen = ilen;
150132b31808SJens Wiklander return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen,
1502817466cbSJens Wiklander iv, iv_len, ad, ad_len, input, output,
150332b31808SJens Wiklander tag, tag_len);
1504817466cbSJens Wiklander }
1505817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */
15063d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
1507b0563631STom Van Eyck if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
15083d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */
1509b0563631STom Van Eyck if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||
151032b31808SJens Wiklander (tag_len != 16U)) {
151132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
15123d3b0591SJens Wiklander }
15133d3b0591SJens Wiklander
15143d3b0591SJens Wiklander *olen = ilen;
151532b31808SJens Wiklander return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx,
151632b31808SJens Wiklander ilen, iv, ad, ad_len, input, output, tag);
15173d3b0591SJens Wiklander }
15183d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
1519817466cbSJens Wiklander
152032b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1521817466cbSJens Wiklander }
1522817466cbSJens Wiklander
1523817466cbSJens Wiklander /*
152432b31808SJens Wiklander * Packet-oriented encryption for AEAD modes: internal function used by
152532b31808SJens Wiklander * mbedtls_cipher_auth_encrypt_ext().
1526817466cbSJens Wiklander */
mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len,const unsigned char * ad,size_t ad_len,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen,const unsigned char * tag,size_t tag_len)15277901324dSJerome Forissier static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
1528817466cbSJens Wiklander const unsigned char *iv, size_t iv_len,
1529817466cbSJens Wiklander const unsigned char *ad, size_t ad_len,
1530817466cbSJens Wiklander const unsigned char *input, size_t ilen,
1531817466cbSJens Wiklander unsigned char *output, size_t *olen,
1532817466cbSJens Wiklander const unsigned char *tag, size_t tag_len)
1533817466cbSJens Wiklander {
1534b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
153532b31808SJens Wiklander if (ctx->psa_enabled == 1) {
153611fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that
153711fa71b9SJerome Forissier * a key has been set. If not, the key slot will
153811fa71b9SJerome Forissier * still be in its default state of 0, which is
153911fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call
154011fa71b9SJerome Forissier * below will gracefully fail. */
154111fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa =
154211fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
154311fa71b9SJerome Forissier
154411fa71b9SJerome Forissier psa_status_t status;
154511fa71b9SJerome Forissier
154611fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag
154711fa71b9SJerome Forissier * at the end of the encrypted message. */
154832b31808SJens Wiklander if (input == NULL || tag != input + ilen) {
154932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
155032b31808SJens Wiklander }
155111fa71b9SJerome Forissier
155211fa71b9SJerome Forissier status = psa_aead_decrypt(cipher_psa->slot,
155311fa71b9SJerome Forissier cipher_psa->alg,
155411fa71b9SJerome Forissier iv, iv_len,
155511fa71b9SJerome Forissier ad, ad_len,
155611fa71b9SJerome Forissier input, ilen + tag_len,
155711fa71b9SJerome Forissier output, ilen, olen);
155832b31808SJens Wiklander if (status == PSA_ERROR_INVALID_SIGNATURE) {
155932b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_AUTH_FAILED;
156032b31808SJens Wiklander } else if (status != PSA_SUCCESS) {
156132b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
156232b31808SJens Wiklander }
156311fa71b9SJerome Forissier
156432b31808SJens Wiklander return 0;
156511fa71b9SJerome Forissier }
1566b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
156711fa71b9SJerome Forissier
1568817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
1569b0563631STom Van Eyck if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
157011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1571817466cbSJens Wiklander
1572817466cbSJens Wiklander *olen = ilen;
1573817466cbSJens Wiklander ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen,
1574817466cbSJens Wiklander iv, iv_len, ad, ad_len,
1575817466cbSJens Wiklander tag, tag_len, input, output);
1576817466cbSJens Wiklander
157732b31808SJens Wiklander if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) {
1578817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
157932b31808SJens Wiklander }
1580817466cbSJens Wiklander
158132b31808SJens Wiklander return ret;
1582817466cbSJens Wiklander }
1583817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1584817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
1585b0563631STom Van Eyck if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
158611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1587817466cbSJens Wiklander
1588817466cbSJens Wiklander *olen = ilen;
1589817466cbSJens Wiklander ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen,
1590817466cbSJens Wiklander iv, iv_len, ad, ad_len,
1591817466cbSJens Wiklander input, output, tag, tag_len);
1592817466cbSJens Wiklander
159332b31808SJens Wiklander if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) {
1594817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
159532b31808SJens Wiklander }
1596817466cbSJens Wiklander
159732b31808SJens Wiklander return ret;
1598817466cbSJens Wiklander }
1599817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */
16003d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
1601b0563631STom Van Eyck if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
160211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
16033d3b0591SJens Wiklander
16043d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */
1605b0563631STom Van Eyck if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||
160632b31808SJens Wiklander (tag_len != 16U)) {
160732b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
16083d3b0591SJens Wiklander }
16093d3b0591SJens Wiklander
16103d3b0591SJens Wiklander *olen = ilen;
16113d3b0591SJens Wiklander ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen,
16123d3b0591SJens Wiklander iv, ad, ad_len, tag, input, output);
16133d3b0591SJens Wiklander
161432b31808SJens Wiklander if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) {
16153d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
161632b31808SJens Wiklander }
16173d3b0591SJens Wiklander
161832b31808SJens Wiklander return ret;
16193d3b0591SJens Wiklander }
16203d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
16217901324dSJerome Forissier
162232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
16237901324dSJerome Forissier }
16247901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */
16257901324dSJerome Forissier
16267901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)
16277901324dSJerome Forissier /*
16287901324dSJerome Forissier * Packet-oriented encryption for AEAD/NIST_KW: public function.
16297901324dSJerome Forissier */
mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len,const unsigned char * ad,size_t ad_len,const unsigned char * input,size_t ilen,unsigned char * output,size_t output_len,size_t * olen,size_t tag_len)16307901324dSJerome Forissier int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx,
16317901324dSJerome Forissier const unsigned char *iv, size_t iv_len,
16327901324dSJerome Forissier const unsigned char *ad, size_t ad_len,
16337901324dSJerome Forissier const unsigned char *input, size_t ilen,
16347901324dSJerome Forissier unsigned char *output, size_t output_len,
16357901324dSJerome Forissier size_t *olen, size_t tag_len)
16367901324dSJerome Forissier {
163711fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
16387901324dSJerome Forissier if (
1639b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
16407901324dSJerome Forissier ctx->psa_enabled == 0 &&
16417901324dSJerome Forissier #endif
1642b0563631STom Van Eyck (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1643b0563631STom Van Eyck MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {
1644b0563631STom Van Eyck mbedtls_nist_kw_mode_t mode =
1645b0563631STom Van Eyck (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?
164611fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
164711fa71b9SJerome Forissier
16487901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP,
16497901324dSJerome Forissier * so these length should be 0 as documented. */
165032b31808SJens Wiklander if (iv_len != 0 || tag_len != 0 || ad_len != 0) {
165132b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
165232b31808SJens Wiklander }
165311fa71b9SJerome Forissier
16547901324dSJerome Forissier (void) iv;
16557901324dSJerome Forissier (void) ad;
16567901324dSJerome Forissier
165732b31808SJens Wiklander return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen,
165832b31808SJens Wiklander output, olen, output_len);
165911fa71b9SJerome Forissier }
166011fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */
1661817466cbSJens Wiklander
16627901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD)
16637901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */
166432b31808SJens Wiklander if (output_len < ilen + tag_len) {
166532b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
166632b31808SJens Wiklander }
16677901324dSJerome Forissier
16687901324dSJerome Forissier int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len,
16697901324dSJerome Forissier input, ilen, output, olen,
16707901324dSJerome Forissier output + ilen, tag_len);
16717901324dSJerome Forissier *olen += tag_len;
167232b31808SJens Wiklander return ret;
16737901324dSJerome Forissier #else
167432b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
1675817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */
16767901324dSJerome Forissier }
16777901324dSJerome Forissier
16787901324dSJerome Forissier /*
16797901324dSJerome Forissier * Packet-oriented decryption for AEAD/NIST_KW: public function.
16807901324dSJerome Forissier */
mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t * ctx,const unsigned char * iv,size_t iv_len,const unsigned char * ad,size_t ad_len,const unsigned char * input,size_t ilen,unsigned char * output,size_t output_len,size_t * olen,size_t tag_len)16817901324dSJerome Forissier int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx,
16827901324dSJerome Forissier const unsigned char *iv, size_t iv_len,
16837901324dSJerome Forissier const unsigned char *ad, size_t ad_len,
16847901324dSJerome Forissier const unsigned char *input, size_t ilen,
16857901324dSJerome Forissier unsigned char *output, size_t output_len,
16867901324dSJerome Forissier size_t *olen, size_t tag_len)
16877901324dSJerome Forissier {
16887901324dSJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
16897901324dSJerome Forissier if (
1690b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
16917901324dSJerome Forissier ctx->psa_enabled == 0 &&
16927901324dSJerome Forissier #endif
1693b0563631STom Van Eyck (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
1694b0563631STom Van Eyck MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {
1695b0563631STom Van Eyck mbedtls_nist_kw_mode_t mode =
1696b0563631STom Van Eyck (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?
16977901324dSJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
16987901324dSJerome Forissier
16997901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP,
17007901324dSJerome Forissier * so these length should be 0 as documented. */
170132b31808SJens Wiklander if (iv_len != 0 || tag_len != 0 || ad_len != 0) {
170232b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
170332b31808SJens Wiklander }
17047901324dSJerome Forissier
17057901324dSJerome Forissier (void) iv;
17067901324dSJerome Forissier (void) ad;
17077901324dSJerome Forissier
170832b31808SJens Wiklander return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen,
170932b31808SJens Wiklander output, olen, output_len);
17107901324dSJerome Forissier }
17117901324dSJerome Forissier #endif /* MBEDTLS_NIST_KW_C */
17127901324dSJerome Forissier
17137901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD)
17147901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */
171532b31808SJens Wiklander if (ilen < tag_len || output_len < ilen - tag_len) {
171632b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
171732b31808SJens Wiklander }
17187901324dSJerome Forissier
171932b31808SJens Wiklander return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len,
17207901324dSJerome Forissier input, ilen - tag_len, output, olen,
172132b31808SJens Wiklander input + ilen - tag_len, tag_len);
17227901324dSJerome Forissier #else
172332b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
17247901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */
17257901324dSJerome Forissier }
17267901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */
1727817466cbSJens Wiklander
1728817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */
1729