xref: /optee_os/lib/libmbedtls/mbedtls/library/cipher.c (revision 273a583ea99627ff3b8ccbbaedbdacecd0909b2e)
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