xref: /optee_os/lib/libmbedtls/mbedtls/library/cipher.c (revision 11fa71b9ddb429088f325cfda430183003ccd1db)
1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0
2817466cbSJens Wiklander /**
3817466cbSJens Wiklander  * \file cipher.c
4817466cbSJens Wiklander  *
5817466cbSJens Wiklander  * \brief Generic cipher wrapper for mbed TLS
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  * \author Adriaan de Jong <dejong@fox-it.com>
8817466cbSJens Wiklander  *
9817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
12817466cbSJens Wiklander  *  not use this file except in compliance with the License.
13817466cbSJens Wiklander  *  You may obtain a copy of the License at
14817466cbSJens Wiklander  *
15817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
16817466cbSJens Wiklander  *
17817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
18817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
21817466cbSJens Wiklander  *  limitations under the License.
22817466cbSJens Wiklander  *
23817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
24817466cbSJens Wiklander  */
25817466cbSJens Wiklander 
26817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
27817466cbSJens Wiklander #include "mbedtls/config.h"
28817466cbSJens Wiklander #else
29817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
30817466cbSJens Wiklander #endif
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_C)
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #include "mbedtls/cipher.h"
35817466cbSJens Wiklander #include "mbedtls/cipher_internal.h"
363d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
37*11fa71b9SJerome Forissier #include "mbedtls/error.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <stdlib.h>
40817466cbSJens Wiklander #include <string.h>
41817466cbSJens Wiklander 
423d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
433d3b0591SJens Wiklander #include "mbedtls/chachapoly.h"
443d3b0591SJens Wiklander #endif
453d3b0591SJens Wiklander 
46817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
47817466cbSJens Wiklander #include "mbedtls/gcm.h"
48817466cbSJens Wiklander #endif
49817466cbSJens Wiklander 
50817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
51817466cbSJens Wiklander #include "mbedtls/ccm.h"
52817466cbSJens Wiklander #endif
53817466cbSJens Wiklander 
543d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
553d3b0591SJens Wiklander #include "mbedtls/chacha20.h"
563d3b0591SJens Wiklander #endif
573d3b0591SJens Wiklander 
58817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C)
59817466cbSJens Wiklander #include "mbedtls/cmac.h"
60817466cbSJens Wiklander #endif
61817466cbSJens Wiklander 
62*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
63*11fa71b9SJerome Forissier #include "psa/crypto.h"
64*11fa71b9SJerome Forissier #include "mbedtls/psa_util.h"
65*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
66*11fa71b9SJerome Forissier 
67*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
68*11fa71b9SJerome Forissier #include "mbedtls/nist_kw.h"
69*11fa71b9SJerome Forissier #endif
70*11fa71b9SJerome Forissier 
71817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
72817466cbSJens Wiklander #include "mbedtls/platform.h"
73817466cbSJens Wiklander #else
74817466cbSJens Wiklander #define mbedtls_calloc calloc
75817466cbSJens Wiklander #define mbedtls_free   free
76817466cbSJens Wiklander #endif
77817466cbSJens Wiklander 
783d3b0591SJens Wiklander #define CIPHER_VALIDATE_RET( cond )    \
793d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
803d3b0591SJens Wiklander #define CIPHER_VALIDATE( cond )        \
813d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
82817466cbSJens Wiklander 
833d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
843d3b0591SJens Wiklander /* Compare the contents of two buffers in constant time.
853d3b0591SJens Wiklander  * Returns 0 if the contents are bitwise identical, otherwise returns
863d3b0591SJens Wiklander  * a non-zero value.
873d3b0591SJens Wiklander  * This is currently only used by GCM and ChaCha20+Poly1305.
883d3b0591SJens Wiklander  */
89*11fa71b9SJerome Forissier static int mbedtls_constant_time_memcmp( const void *v1, const void *v2,
90*11fa71b9SJerome Forissier                                          size_t len )
913d3b0591SJens Wiklander {
923d3b0591SJens Wiklander     const unsigned char *p1 = (const unsigned char*) v1;
933d3b0591SJens Wiklander     const unsigned char *p2 = (const unsigned char*) v2;
943d3b0591SJens Wiklander     size_t i;
953d3b0591SJens Wiklander     unsigned char diff;
963d3b0591SJens Wiklander 
973d3b0591SJens Wiklander     for( diff = 0, i = 0; i < len; i++ )
983d3b0591SJens Wiklander         diff |= p1[i] ^ p2[i];
993d3b0591SJens Wiklander 
1003d3b0591SJens Wiklander     return( (int)diff );
101817466cbSJens Wiklander }
1023d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
103817466cbSJens Wiklander 
104817466cbSJens Wiklander static int supported_init = 0;
105817466cbSJens Wiklander 
106817466cbSJens Wiklander const int *mbedtls_cipher_list( void )
107817466cbSJens Wiklander {
108817466cbSJens Wiklander     const mbedtls_cipher_definition_t *def;
109817466cbSJens Wiklander     int *type;
110817466cbSJens Wiklander 
111817466cbSJens Wiklander     if( ! supported_init )
112817466cbSJens Wiklander     {
113817466cbSJens Wiklander         def = mbedtls_cipher_definitions;
114817466cbSJens Wiklander         type = mbedtls_cipher_supported;
115817466cbSJens Wiklander 
116817466cbSJens Wiklander         while( def->type != 0 )
117817466cbSJens Wiklander             *type++ = (*def++).type;
118817466cbSJens Wiklander 
119817466cbSJens Wiklander         *type = 0;
120817466cbSJens Wiklander 
121817466cbSJens Wiklander         supported_init = 1;
122817466cbSJens Wiklander     }
123817466cbSJens Wiklander 
124817466cbSJens Wiklander     return( mbedtls_cipher_supported );
125817466cbSJens Wiklander }
126817466cbSJens Wiklander 
127*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
128*11fa71b9SJerome Forissier     const mbedtls_cipher_type_t cipher_type )
129817466cbSJens Wiklander {
130817466cbSJens Wiklander     const mbedtls_cipher_definition_t *def;
131817466cbSJens Wiklander 
132817466cbSJens Wiklander     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
133817466cbSJens Wiklander         if( def->type == cipher_type )
134817466cbSJens Wiklander             return( def->info );
135817466cbSJens Wiklander 
136817466cbSJens Wiklander     return( NULL );
137817466cbSJens Wiklander }
138817466cbSJens Wiklander 
139*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
140*11fa71b9SJerome Forissier     const char *cipher_name )
141817466cbSJens Wiklander {
142817466cbSJens Wiklander     const mbedtls_cipher_definition_t *def;
143817466cbSJens Wiklander 
144817466cbSJens Wiklander     if( NULL == cipher_name )
145817466cbSJens Wiklander         return( NULL );
146817466cbSJens Wiklander 
147817466cbSJens Wiklander     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
148817466cbSJens Wiklander         if( !  strcmp( def->info->name, cipher_name ) )
149817466cbSJens Wiklander             return( def->info );
150817466cbSJens Wiklander 
151817466cbSJens Wiklander     return( NULL );
152817466cbSJens Wiklander }
153817466cbSJens Wiklander 
154*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
155*11fa71b9SJerome Forissier     const mbedtls_cipher_id_t cipher_id,
156817466cbSJens Wiklander     int key_bitlen,
157817466cbSJens Wiklander     const mbedtls_cipher_mode_t mode )
158817466cbSJens Wiklander {
159817466cbSJens Wiklander     const mbedtls_cipher_definition_t *def;
160817466cbSJens Wiklander 
161817466cbSJens Wiklander     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
162817466cbSJens Wiklander         if( def->info->base->cipher == cipher_id &&
163817466cbSJens Wiklander             def->info->key_bitlen == (unsigned) key_bitlen &&
164817466cbSJens Wiklander             def->info->mode == mode )
165817466cbSJens Wiklander             return( def->info );
166817466cbSJens Wiklander 
167817466cbSJens Wiklander     return( NULL );
168817466cbSJens Wiklander }
169817466cbSJens Wiklander 
170817466cbSJens Wiklander void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
171817466cbSJens Wiklander {
1723d3b0591SJens Wiklander     CIPHER_VALIDATE( ctx != NULL );
173817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
174817466cbSJens Wiklander }
175817466cbSJens Wiklander 
176817466cbSJens Wiklander void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
177817466cbSJens Wiklander {
178817466cbSJens Wiklander     if( ctx == NULL )
179817466cbSJens Wiklander         return;
180817466cbSJens Wiklander 
181*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
182*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
183*11fa71b9SJerome Forissier     {
184*11fa71b9SJerome Forissier         if( ctx->cipher_ctx != NULL )
185*11fa71b9SJerome Forissier         {
186*11fa71b9SJerome Forissier             mbedtls_cipher_context_psa * const cipher_psa =
187*11fa71b9SJerome Forissier                 (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
188*11fa71b9SJerome Forissier 
189*11fa71b9SJerome Forissier             if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED )
190*11fa71b9SJerome Forissier             {
191*11fa71b9SJerome Forissier                 /* xxx_free() doesn't allow to return failures. */
192*11fa71b9SJerome Forissier                 (void) psa_destroy_key( cipher_psa->slot );
193*11fa71b9SJerome Forissier             }
194*11fa71b9SJerome Forissier 
195*11fa71b9SJerome Forissier             mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) );
196*11fa71b9SJerome Forissier             mbedtls_free( cipher_psa );
197*11fa71b9SJerome Forissier         }
198*11fa71b9SJerome Forissier 
199*11fa71b9SJerome Forissier         mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
200*11fa71b9SJerome Forissier         return;
201*11fa71b9SJerome Forissier     }
202*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
203*11fa71b9SJerome Forissier 
204817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C)
205817466cbSJens Wiklander     if( ctx->cmac_ctx )
206817466cbSJens Wiklander     {
2073d3b0591SJens Wiklander        mbedtls_platform_zeroize( ctx->cmac_ctx,
2083d3b0591SJens Wiklander                                  sizeof( mbedtls_cmac_context_t ) );
209817466cbSJens Wiklander        mbedtls_free( ctx->cmac_ctx );
210817466cbSJens Wiklander     }
211817466cbSJens Wiklander #endif
212817466cbSJens Wiklander 
213817466cbSJens Wiklander     if( ctx->cipher_ctx )
214817466cbSJens Wiklander         ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
215817466cbSJens Wiklander 
2163d3b0591SJens Wiklander     mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
217817466cbSJens Wiklander }
218817466cbSJens Wiklander 
21912484fc7SEdison Ai int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst,
22012484fc7SEdison Ai                           const mbedtls_cipher_context_t *src )
22112484fc7SEdison Ai {
22212484fc7SEdison Ai     if( dst == NULL || dst->cipher_info == NULL ||
22312484fc7SEdison Ai         src == NULL || src->cipher_info == NULL)
22412484fc7SEdison Ai     {
22512484fc7SEdison Ai         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
22612484fc7SEdison Ai     }
22712484fc7SEdison Ai 
22812484fc7SEdison Ai     dst->cipher_info = src->cipher_info;
22912484fc7SEdison Ai     dst->key_bitlen = src->key_bitlen;
23012484fc7SEdison Ai     dst->operation = src->operation;
23112484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
23212484fc7SEdison Ai     dst->add_padding = src->add_padding;
23312484fc7SEdison Ai     dst->get_padding = src->get_padding;
23412484fc7SEdison Ai #endif
23512484fc7SEdison Ai     memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH );
23612484fc7SEdison Ai     dst->unprocessed_len = src->unprocessed_len;
23712484fc7SEdison Ai     memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH );
23812484fc7SEdison Ai     dst->iv_size = src->iv_size;
23912484fc7SEdison Ai     if( dst->cipher_info->base->ctx_clone_func )
24012484fc7SEdison Ai         dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx );
24112484fc7SEdison Ai 
24212484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C)
24312484fc7SEdison Ai     if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL )
24412484fc7SEdison Ai         memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
24512484fc7SEdison Ai #endif
24612484fc7SEdison Ai     return( 0 );
24712484fc7SEdison Ai }
24812484fc7SEdison Ai 
249*11fa71b9SJerome Forissier int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
250*11fa71b9SJerome Forissier                           const mbedtls_cipher_info_t *cipher_info )
251817466cbSJens Wiklander {
2523d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
2533d3b0591SJens Wiklander     if( cipher_info == NULL )
254817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
255817466cbSJens Wiklander 
256817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
257817466cbSJens Wiklander 
258817466cbSJens Wiklander     if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
259817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
260817466cbSJens Wiklander 
261817466cbSJens Wiklander     ctx->cipher_info = cipher_info;
262817466cbSJens Wiklander 
263817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
264817466cbSJens Wiklander     /*
265817466cbSJens Wiklander      * Ignore possible errors caused by a cipher mode that doesn't use padding
266817466cbSJens Wiklander      */
267817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
268817466cbSJens Wiklander     (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
269817466cbSJens Wiklander #else
270817466cbSJens Wiklander     (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
271817466cbSJens Wiklander #endif
272817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
273817466cbSJens Wiklander 
274817466cbSJens Wiklander     return( 0 );
275817466cbSJens Wiklander }
276817466cbSJens Wiklander 
277*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
278*11fa71b9SJerome Forissier int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
279*11fa71b9SJerome Forissier                               const mbedtls_cipher_info_t *cipher_info,
280*11fa71b9SJerome Forissier                               size_t taglen )
281*11fa71b9SJerome Forissier {
282*11fa71b9SJerome Forissier     psa_algorithm_t alg;
283*11fa71b9SJerome Forissier     mbedtls_cipher_context_psa *cipher_psa;
284*11fa71b9SJerome Forissier 
285*11fa71b9SJerome Forissier     if( NULL == cipher_info || NULL == ctx )
286*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
287*11fa71b9SJerome Forissier 
288*11fa71b9SJerome Forissier     /* Check that the underlying cipher mode and cipher type are
289*11fa71b9SJerome Forissier      * supported by the underlying PSA Crypto implementation. */
290*11fa71b9SJerome Forissier     alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen );
291*11fa71b9SJerome Forissier     if( alg == 0 )
292*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
293*11fa71b9SJerome Forissier     if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 )
294*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
295*11fa71b9SJerome Forissier 
296*11fa71b9SJerome Forissier     memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
297*11fa71b9SJerome Forissier 
298*11fa71b9SJerome Forissier     cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) );
299*11fa71b9SJerome Forissier     if( cipher_psa == NULL )
300*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
301*11fa71b9SJerome Forissier     cipher_psa->alg  = alg;
302*11fa71b9SJerome Forissier     ctx->cipher_ctx  = cipher_psa;
303*11fa71b9SJerome Forissier     ctx->cipher_info = cipher_info;
304*11fa71b9SJerome Forissier     ctx->psa_enabled = 1;
305*11fa71b9SJerome Forissier     return( 0 );
306*11fa71b9SJerome Forissier }
307*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
308*11fa71b9SJerome Forissier 
30912484fc7SEdison Ai int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
31012484fc7SEdison Ai {
31112484fc7SEdison Ai     if( NULL == cipher_info || NULL == ctx )
31212484fc7SEdison Ai         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
31312484fc7SEdison Ai 
31412484fc7SEdison Ai     ctx->cipher_info = cipher_info;
31512484fc7SEdison Ai     return( 0 );
31612484fc7SEdison Ai }
31712484fc7SEdison Ai 
3183d3b0591SJens Wiklander int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
3193d3b0591SJens Wiklander                            const unsigned char *key,
3203d3b0591SJens Wiklander                            int key_bitlen,
3213d3b0591SJens Wiklander                            const mbedtls_operation_t operation )
322817466cbSJens Wiklander {
3233d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
3243d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( key != NULL );
3253d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
3263d3b0591SJens Wiklander                          operation == MBEDTLS_DECRYPT );
3273d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
328817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
329817466cbSJens Wiklander 
330*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
331*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
332*11fa71b9SJerome Forissier     {
333*11fa71b9SJerome Forissier         mbedtls_cipher_context_psa * const cipher_psa =
334*11fa71b9SJerome Forissier             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
335*11fa71b9SJerome Forissier 
336*11fa71b9SJerome Forissier         size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8;
337*11fa71b9SJerome Forissier 
338*11fa71b9SJerome Forissier         psa_status_t status;
339*11fa71b9SJerome Forissier         psa_key_type_t key_type;
340*11fa71b9SJerome Forissier         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
341*11fa71b9SJerome Forissier 
342*11fa71b9SJerome Forissier         /* PSA Crypto API only accepts byte-aligned keys. */
343*11fa71b9SJerome Forissier         if( key_bitlen % 8 != 0 )
344*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
345*11fa71b9SJerome Forissier 
346*11fa71b9SJerome Forissier         /* Don't allow keys to be set multiple times. */
347*11fa71b9SJerome Forissier         if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET )
348*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
349*11fa71b9SJerome Forissier 
350*11fa71b9SJerome Forissier         key_type = mbedtls_psa_translate_cipher_type(
351*11fa71b9SJerome Forissier             ctx->cipher_info->type );
352*11fa71b9SJerome Forissier         if( key_type == 0 )
353*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
354*11fa71b9SJerome Forissier         psa_set_key_type( &attributes, key_type );
355*11fa71b9SJerome Forissier 
356*11fa71b9SJerome Forissier         /* Mbed TLS' cipher layer doesn't enforce the mode of operation
357*11fa71b9SJerome Forissier          * (encrypt vs. decrypt): it is possible to setup a key for encryption
358*11fa71b9SJerome Forissier          * and use it for AEAD decryption. Until tests relying on this
359*11fa71b9SJerome Forissier          * are changed, allow any usage in PSA. */
360*11fa71b9SJerome Forissier         psa_set_key_usage_flags( &attributes,
361*11fa71b9SJerome Forissier                                  /* mbedtls_psa_translate_cipher_operation( operation ); */
362*11fa71b9SJerome Forissier                                  PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
363*11fa71b9SJerome Forissier         psa_set_key_algorithm( &attributes, cipher_psa->alg );
364*11fa71b9SJerome Forissier 
365*11fa71b9SJerome Forissier         status = psa_import_key( &attributes, key, key_bytelen,
366*11fa71b9SJerome Forissier                                  &cipher_psa->slot );
367*11fa71b9SJerome Forissier         switch( status )
368*11fa71b9SJerome Forissier         {
369*11fa71b9SJerome Forissier             case PSA_SUCCESS:
370*11fa71b9SJerome Forissier                 break;
371*11fa71b9SJerome Forissier             case PSA_ERROR_INSUFFICIENT_MEMORY:
372*11fa71b9SJerome Forissier                 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
373*11fa71b9SJerome Forissier             case PSA_ERROR_NOT_SUPPORTED:
374*11fa71b9SJerome Forissier                 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
375*11fa71b9SJerome Forissier             default:
376*11fa71b9SJerome Forissier                 return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
377*11fa71b9SJerome Forissier         }
378*11fa71b9SJerome Forissier         /* Indicate that we own the key slot and need to
379*11fa71b9SJerome Forissier          * destroy it in mbedtls_cipher_free(). */
380*11fa71b9SJerome Forissier         cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED;
381*11fa71b9SJerome Forissier 
382*11fa71b9SJerome Forissier         ctx->key_bitlen = key_bitlen;
383*11fa71b9SJerome Forissier         ctx->operation = operation;
384*11fa71b9SJerome Forissier         return( 0 );
385*11fa71b9SJerome Forissier     }
386*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
387*11fa71b9SJerome Forissier 
388817466cbSJens Wiklander     if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
389817466cbSJens Wiklander         (int) ctx->cipher_info->key_bitlen != key_bitlen )
390817466cbSJens Wiklander     {
391817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
392817466cbSJens Wiklander     }
393817466cbSJens Wiklander 
394817466cbSJens Wiklander     ctx->key_bitlen = key_bitlen;
395817466cbSJens Wiklander     ctx->operation = operation;
396817466cbSJens Wiklander 
397817466cbSJens Wiklander     /*
3983d3b0591SJens Wiklander      * For OFB, CFB and CTR mode always use the encryption key schedule
399817466cbSJens Wiklander      */
400817466cbSJens Wiklander     if( MBEDTLS_ENCRYPT == operation ||
401817466cbSJens Wiklander         MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
4023d3b0591SJens Wiklander         MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
403817466cbSJens Wiklander         MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
404817466cbSJens Wiklander     {
4053d3b0591SJens Wiklander         return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
4063d3b0591SJens Wiklander                                                          ctx->key_bitlen ) );
407817466cbSJens Wiklander     }
408817466cbSJens Wiklander 
409817466cbSJens Wiklander     if( MBEDTLS_DECRYPT == operation )
4103d3b0591SJens Wiklander         return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
4113d3b0591SJens Wiklander                                                          ctx->key_bitlen ) );
412817466cbSJens Wiklander 
413817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
414817466cbSJens Wiklander }
415817466cbSJens Wiklander 
416817466cbSJens Wiklander int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
4173d3b0591SJens Wiklander                            const unsigned char *iv,
4183d3b0591SJens Wiklander                            size_t iv_len )
419817466cbSJens Wiklander {
420817466cbSJens Wiklander     size_t actual_iv_size;
421817466cbSJens Wiklander 
4223d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
4233d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
4243d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
425817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
426*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
427*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
428*11fa71b9SJerome Forissier     {
429*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
430*11fa71b9SJerome Forissier          * operations, we currently don't make it
431*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
432*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
433*11fa71b9SJerome Forissier     }
434*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
435817466cbSJens Wiklander 
436817466cbSJens Wiklander     /* avoid buffer overflow in ctx->iv */
437817466cbSJens Wiklander     if( iv_len > MBEDTLS_MAX_IV_LENGTH )
438817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
439817466cbSJens Wiklander 
440817466cbSJens Wiklander     if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
441817466cbSJens Wiklander         actual_iv_size = iv_len;
442817466cbSJens Wiklander     else
443817466cbSJens Wiklander     {
444817466cbSJens Wiklander         actual_iv_size = ctx->cipher_info->iv_size;
445817466cbSJens Wiklander 
446817466cbSJens Wiklander         /* avoid reading past the end of input buffer */
447817466cbSJens Wiklander         if( actual_iv_size > iv_len )
448817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
449817466cbSJens Wiklander     }
450817466cbSJens Wiklander 
4513d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
4523d3b0591SJens Wiklander     if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
4533d3b0591SJens Wiklander     {
4543d3b0591SJens Wiklander         if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
4553d3b0591SJens Wiklander                                            iv,
4563d3b0591SJens Wiklander                                            0U ) ) /* Initial counter value */
4573d3b0591SJens Wiklander         {
4583d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
4593d3b0591SJens Wiklander         }
4603d3b0591SJens Wiklander     }
4613d3b0591SJens Wiklander #endif
4623d3b0591SJens Wiklander 
4633d3b0591SJens Wiklander     if ( actual_iv_size != 0 )
4643d3b0591SJens Wiklander     {
465817466cbSJens Wiklander         memcpy( ctx->iv, iv, actual_iv_size );
466817466cbSJens Wiklander         ctx->iv_size = actual_iv_size;
4673d3b0591SJens Wiklander     }
468817466cbSJens Wiklander 
469817466cbSJens Wiklander     return( 0 );
470817466cbSJens Wiklander }
471817466cbSJens Wiklander 
472817466cbSJens Wiklander int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
473817466cbSJens Wiklander {
4743d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
4753d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
476817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
477817466cbSJens Wiklander 
478*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
479*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
480*11fa71b9SJerome Forissier     {
481*11fa71b9SJerome Forissier         /* We don't support resetting PSA-based
482*11fa71b9SJerome Forissier          * cipher contexts, yet. */
483*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
484*11fa71b9SJerome Forissier     }
485*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
486*11fa71b9SJerome Forissier 
487817466cbSJens Wiklander     ctx->unprocessed_len = 0;
488817466cbSJens Wiklander 
489817466cbSJens Wiklander     return( 0 );
490817466cbSJens Wiklander }
491817466cbSJens Wiklander 
4923d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
493817466cbSJens Wiklander int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
494817466cbSJens Wiklander                       const unsigned char *ad, size_t ad_len )
495817466cbSJens Wiklander {
4963d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
4973d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
4983d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
499817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
500817466cbSJens Wiklander 
501*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
502*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
503*11fa71b9SJerome Forissier     {
504*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
505*11fa71b9SJerome Forissier          * operations, we currently don't make it
506*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
507*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
508*11fa71b9SJerome Forissier     }
509*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
510*11fa71b9SJerome Forissier 
5113d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
512817466cbSJens Wiklander     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
513817466cbSJens Wiklander     {
5143d3b0591SJens Wiklander         return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
5153d3b0591SJens Wiklander                                     ctx->iv, ctx->iv_size, ad, ad_len ) );
516817466cbSJens Wiklander     }
5173d3b0591SJens Wiklander #endif
5183d3b0591SJens Wiklander 
5193d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
5203d3b0591SJens Wiklander     if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
5213d3b0591SJens Wiklander     {
5223d3b0591SJens Wiklander         int result;
5233d3b0591SJens Wiklander         mbedtls_chachapoly_mode_t mode;
5243d3b0591SJens Wiklander 
5253d3b0591SJens Wiklander         mode = ( ctx->operation == MBEDTLS_ENCRYPT )
5263d3b0591SJens Wiklander                 ? MBEDTLS_CHACHAPOLY_ENCRYPT
5273d3b0591SJens Wiklander                 : MBEDTLS_CHACHAPOLY_DECRYPT;
5283d3b0591SJens Wiklander 
5293d3b0591SJens Wiklander         result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
5303d3b0591SJens Wiklander                                                         ctx->iv,
5313d3b0591SJens Wiklander                                                         mode );
5323d3b0591SJens Wiklander         if ( result != 0 )
5333d3b0591SJens Wiklander             return( result );
5343d3b0591SJens Wiklander 
5353d3b0591SJens Wiklander         return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
5363d3b0591SJens Wiklander                                                ad, ad_len ) );
5373d3b0591SJens Wiklander     }
5383d3b0591SJens Wiklander #endif
539817466cbSJens Wiklander 
540817466cbSJens Wiklander     return( 0 );
541817466cbSJens Wiklander }
5423d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
543817466cbSJens Wiklander 
544817466cbSJens Wiklander int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
545817466cbSJens Wiklander                    size_t ilen, unsigned char *output, size_t *olen )
546817466cbSJens Wiklander {
547*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5483d3b0591SJens Wiklander     size_t block_size;
549817466cbSJens Wiklander 
5503d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
5513d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
5523d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( output != NULL );
5533d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( olen != NULL );
5543d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
555817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
556817466cbSJens Wiklander 
557*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
558*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
559*11fa71b9SJerome Forissier     {
560*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
561*11fa71b9SJerome Forissier          * operations, we currently don't make it
562*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
563*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
564*11fa71b9SJerome Forissier     }
565*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
566*11fa71b9SJerome Forissier 
567817466cbSJens Wiklander     *olen = 0;
568817466cbSJens Wiklander     block_size = mbedtls_cipher_get_block_size( ctx );
5695b25c76aSJerome Forissier     if ( 0 == block_size )
5705b25c76aSJerome Forissier     {
5715b25c76aSJerome Forissier         return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
5725b25c76aSJerome Forissier     }
573817466cbSJens Wiklander 
574817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
575817466cbSJens Wiklander     {
576817466cbSJens Wiklander         if( ilen != block_size )
577817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
578817466cbSJens Wiklander 
579817466cbSJens Wiklander         *olen = ilen;
580817466cbSJens Wiklander 
581817466cbSJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
582817466cbSJens Wiklander                     ctx->operation, input, output ) ) )
583817466cbSJens Wiklander         {
584817466cbSJens Wiklander             return( ret );
585817466cbSJens Wiklander         }
586817466cbSJens Wiklander 
587817466cbSJens Wiklander         return( 0 );
588817466cbSJens Wiklander     }
589817466cbSJens Wiklander 
590817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
591817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
592817466cbSJens Wiklander     {
593817466cbSJens Wiklander         *olen = ilen;
5943d3b0591SJens Wiklander         return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
5953d3b0591SJens Wiklander                                     output ) );
5963d3b0591SJens Wiklander     }
5973d3b0591SJens Wiklander #endif
5983d3b0591SJens Wiklander 
5993d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
6003d3b0591SJens Wiklander     if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
6013d3b0591SJens Wiklander     {
6023d3b0591SJens Wiklander         *olen = ilen;
6033d3b0591SJens Wiklander         return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
6043d3b0591SJens Wiklander                                            ilen, input, output ) );
605817466cbSJens Wiklander     }
606817466cbSJens Wiklander #endif
607817466cbSJens Wiklander 
608817466cbSJens Wiklander     if( input == output &&
609817466cbSJens Wiklander        ( ctx->unprocessed_len != 0 || ilen % block_size ) )
610817466cbSJens Wiklander     {
611817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
612817466cbSJens Wiklander     }
613817466cbSJens Wiklander 
614817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC)
615817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
616817466cbSJens Wiklander     {
617817466cbSJens Wiklander         size_t copy_len = 0;
618817466cbSJens Wiklander 
619817466cbSJens Wiklander         /*
620817466cbSJens Wiklander          * If there is not enough data for a full block, cache it.
621817466cbSJens Wiklander          */
6223d3b0591SJens Wiklander         if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
623817466cbSJens Wiklander                 ilen <= block_size - ctx->unprocessed_len ) ||
6243d3b0591SJens Wiklander             ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
6253d3b0591SJens Wiklander                 ilen < block_size - ctx->unprocessed_len ) ||
626817466cbSJens Wiklander              ( ctx->operation == MBEDTLS_ENCRYPT &&
627817466cbSJens Wiklander                 ilen < block_size - ctx->unprocessed_len ) )
628817466cbSJens Wiklander         {
629817466cbSJens Wiklander             memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
630817466cbSJens Wiklander                     ilen );
631817466cbSJens Wiklander 
632817466cbSJens Wiklander             ctx->unprocessed_len += ilen;
633817466cbSJens Wiklander             return( 0 );
634817466cbSJens Wiklander         }
635817466cbSJens Wiklander 
636817466cbSJens Wiklander         /*
637817466cbSJens Wiklander          * Process cached data first
638817466cbSJens Wiklander          */
639817466cbSJens Wiklander         if( 0 != ctx->unprocessed_len )
640817466cbSJens Wiklander         {
641817466cbSJens Wiklander             copy_len = block_size - ctx->unprocessed_len;
642817466cbSJens Wiklander 
643817466cbSJens Wiklander             memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
644817466cbSJens Wiklander                     copy_len );
645817466cbSJens Wiklander 
646817466cbSJens Wiklander             if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
647817466cbSJens Wiklander                     ctx->operation, block_size, ctx->iv,
648817466cbSJens Wiklander                     ctx->unprocessed_data, output ) ) )
649817466cbSJens Wiklander             {
650817466cbSJens Wiklander                 return( ret );
651817466cbSJens Wiklander             }
652817466cbSJens Wiklander 
653817466cbSJens Wiklander             *olen += block_size;
654817466cbSJens Wiklander             output += block_size;
655817466cbSJens Wiklander             ctx->unprocessed_len = 0;
656817466cbSJens Wiklander 
657817466cbSJens Wiklander             input += copy_len;
658817466cbSJens Wiklander             ilen -= copy_len;
659817466cbSJens Wiklander         }
660817466cbSJens Wiklander 
661817466cbSJens Wiklander         /*
662817466cbSJens Wiklander          * Cache final, incomplete block
663817466cbSJens Wiklander          */
664817466cbSJens Wiklander         if( 0 != ilen )
665817466cbSJens Wiklander         {
6663d3b0591SJens Wiklander             /* Encryption: only cache partial blocks
6673d3b0591SJens Wiklander              * Decryption w/ padding: always keep at least one whole block
6683d3b0591SJens Wiklander              * Decryption w/o padding: only cache partial blocks
6693d3b0591SJens Wiklander              */
670817466cbSJens Wiklander             copy_len = ilen % block_size;
6713d3b0591SJens Wiklander             if( copy_len == 0 &&
6723d3b0591SJens Wiklander                 ctx->operation == MBEDTLS_DECRYPT &&
6733d3b0591SJens Wiklander                 NULL != ctx->add_padding)
6743d3b0591SJens Wiklander             {
675817466cbSJens Wiklander                 copy_len = block_size;
6763d3b0591SJens Wiklander             }
677817466cbSJens Wiklander 
678817466cbSJens Wiklander             memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
679817466cbSJens Wiklander                     copy_len );
680817466cbSJens Wiklander 
681817466cbSJens Wiklander             ctx->unprocessed_len += copy_len;
682817466cbSJens Wiklander             ilen -= copy_len;
683817466cbSJens Wiklander         }
684817466cbSJens Wiklander 
685817466cbSJens Wiklander         /*
686817466cbSJens Wiklander          * Process remaining full blocks
687817466cbSJens Wiklander          */
688817466cbSJens Wiklander         if( ilen )
689817466cbSJens Wiklander         {
690817466cbSJens Wiklander             if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
691817466cbSJens Wiklander                     ctx->operation, ilen, ctx->iv, input, output ) ) )
692817466cbSJens Wiklander             {
693817466cbSJens Wiklander                 return( ret );
694817466cbSJens Wiklander             }
695817466cbSJens Wiklander 
696817466cbSJens Wiklander             *olen += ilen;
697817466cbSJens Wiklander         }
698817466cbSJens Wiklander 
699817466cbSJens Wiklander         return( 0 );
700817466cbSJens Wiklander     }
701817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */
702817466cbSJens Wiklander 
703817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB)
704817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
705817466cbSJens Wiklander     {
706817466cbSJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
707817466cbSJens Wiklander                 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
708817466cbSJens Wiklander                 input, output ) ) )
709817466cbSJens Wiklander         {
710817466cbSJens Wiklander             return( ret );
711817466cbSJens Wiklander         }
712817466cbSJens Wiklander 
713817466cbSJens Wiklander         *olen = ilen;
714817466cbSJens Wiklander 
715817466cbSJens Wiklander         return( 0 );
716817466cbSJens Wiklander     }
717817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */
718817466cbSJens Wiklander 
7193d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB)
7203d3b0591SJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
7213d3b0591SJens Wiklander     {
7223d3b0591SJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
7233d3b0591SJens Wiklander                 ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
7243d3b0591SJens Wiklander         {
7253d3b0591SJens Wiklander             return( ret );
7263d3b0591SJens Wiklander         }
7273d3b0591SJens Wiklander 
7283d3b0591SJens Wiklander         *olen = ilen;
7293d3b0591SJens Wiklander 
7303d3b0591SJens Wiklander         return( 0 );
7313d3b0591SJens Wiklander     }
7323d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */
7333d3b0591SJens Wiklander 
734817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR)
735817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
736817466cbSJens Wiklander     {
737817466cbSJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
738817466cbSJens Wiklander                 ilen, &ctx->unprocessed_len, ctx->iv,
739817466cbSJens Wiklander                 ctx->unprocessed_data, input, output ) ) )
740817466cbSJens Wiklander         {
741817466cbSJens Wiklander             return( ret );
742817466cbSJens Wiklander         }
743817466cbSJens Wiklander 
744817466cbSJens Wiklander         *olen = ilen;
745817466cbSJens Wiklander 
746817466cbSJens Wiklander         return( 0 );
747817466cbSJens Wiklander     }
748817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */
749817466cbSJens Wiklander 
7503d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS)
7513d3b0591SJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
7523d3b0591SJens Wiklander     {
7533d3b0591SJens Wiklander         if( ctx->unprocessed_len > 0 ) {
7543d3b0591SJens Wiklander             /* We can only process an entire data unit at a time. */
7553d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
7563d3b0591SJens Wiklander         }
7573d3b0591SJens Wiklander 
7583d3b0591SJens Wiklander         ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
7593d3b0591SJens Wiklander                 ctx->operation, ilen, ctx->iv, input, output );
7603d3b0591SJens Wiklander         if( ret != 0 )
7613d3b0591SJens Wiklander         {
7623d3b0591SJens Wiklander             return( ret );
7633d3b0591SJens Wiklander         }
7643d3b0591SJens Wiklander 
7653d3b0591SJens Wiklander         *olen = ilen;
7663d3b0591SJens Wiklander 
7673d3b0591SJens Wiklander         return( 0 );
7683d3b0591SJens Wiklander     }
7693d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */
7703d3b0591SJens Wiklander 
771817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM)
772817466cbSJens Wiklander     if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
773817466cbSJens Wiklander     {
774817466cbSJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
775817466cbSJens Wiklander                                                     ilen, input, output ) ) )
776817466cbSJens Wiklander         {
777817466cbSJens Wiklander             return( ret );
778817466cbSJens Wiklander         }
779817466cbSJens Wiklander 
780817466cbSJens Wiklander         *olen = ilen;
781817466cbSJens Wiklander 
782817466cbSJens Wiklander         return( 0 );
783817466cbSJens Wiklander     }
784817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */
785817466cbSJens Wiklander 
786817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
787817466cbSJens Wiklander }
788817466cbSJens Wiklander 
789817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
790817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
791817466cbSJens Wiklander /*
792817466cbSJens Wiklander  * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
793817466cbSJens Wiklander  */
794817466cbSJens Wiklander static void add_pkcs_padding( unsigned char *output, size_t output_len,
795817466cbSJens Wiklander         size_t data_len )
796817466cbSJens Wiklander {
797817466cbSJens Wiklander     size_t padding_len = output_len - data_len;
798817466cbSJens Wiklander     unsigned char i;
799817466cbSJens Wiklander 
800817466cbSJens Wiklander     for( i = 0; i < padding_len; i++ )
801817466cbSJens Wiklander         output[data_len + i] = (unsigned char) padding_len;
802817466cbSJens Wiklander }
803817466cbSJens Wiklander 
804817466cbSJens Wiklander static int get_pkcs_padding( unsigned char *input, size_t input_len,
805817466cbSJens Wiklander         size_t *data_len )
806817466cbSJens Wiklander {
807817466cbSJens Wiklander     size_t i, pad_idx;
808817466cbSJens Wiklander     unsigned char padding_len, bad = 0;
809817466cbSJens Wiklander 
810817466cbSJens Wiklander     if( NULL == input || NULL == data_len )
811817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
812817466cbSJens Wiklander 
813817466cbSJens Wiklander     padding_len = input[input_len - 1];
814817466cbSJens Wiklander     *data_len = input_len - padding_len;
815817466cbSJens Wiklander 
816817466cbSJens Wiklander     /* Avoid logical || since it results in a branch */
817817466cbSJens Wiklander     bad |= padding_len > input_len;
818817466cbSJens Wiklander     bad |= padding_len == 0;
819817466cbSJens Wiklander 
820817466cbSJens Wiklander     /* The number of bytes checked must be independent of padding_len,
821817466cbSJens Wiklander      * so pick input_len, which is usually 8 or 16 (one block) */
822817466cbSJens Wiklander     pad_idx = input_len - padding_len;
823817466cbSJens Wiklander     for( i = 0; i < input_len; i++ )
824817466cbSJens Wiklander         bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
825817466cbSJens Wiklander 
826817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
827817466cbSJens Wiklander }
828817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
829817466cbSJens Wiklander 
830817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
831817466cbSJens Wiklander /*
832817466cbSJens Wiklander  * One and zeros padding: fill with 80 00 ... 00
833817466cbSJens Wiklander  */
834817466cbSJens Wiklander static void add_one_and_zeros_padding( unsigned char *output,
835817466cbSJens Wiklander                                        size_t output_len, size_t data_len )
836817466cbSJens Wiklander {
837817466cbSJens Wiklander     size_t padding_len = output_len - data_len;
838817466cbSJens Wiklander     unsigned char i = 0;
839817466cbSJens Wiklander 
840817466cbSJens Wiklander     output[data_len] = 0x80;
841817466cbSJens Wiklander     for( i = 1; i < padding_len; i++ )
842817466cbSJens Wiklander         output[data_len + i] = 0x00;
843817466cbSJens Wiklander }
844817466cbSJens Wiklander 
845817466cbSJens Wiklander static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
846817466cbSJens Wiklander                                       size_t *data_len )
847817466cbSJens Wiklander {
848817466cbSJens Wiklander     size_t i;
849817466cbSJens Wiklander     unsigned char done = 0, prev_done, bad;
850817466cbSJens Wiklander 
851817466cbSJens Wiklander     if( NULL == input || NULL == data_len )
852817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
853817466cbSJens Wiklander 
8543d3b0591SJens Wiklander     bad = 0x80;
855817466cbSJens Wiklander     *data_len = 0;
856817466cbSJens Wiklander     for( i = input_len; i > 0; i-- )
857817466cbSJens Wiklander     {
858817466cbSJens Wiklander         prev_done = done;
859817466cbSJens Wiklander         done |= ( input[i - 1] != 0 );
860817466cbSJens Wiklander         *data_len |= ( i - 1 ) * ( done != prev_done );
8613d3b0591SJens Wiklander         bad ^= input[i - 1] * ( done != prev_done );
862817466cbSJens Wiklander     }
863817466cbSJens Wiklander 
864817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
865817466cbSJens Wiklander 
866817466cbSJens Wiklander }
867817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
868817466cbSJens Wiklander 
869817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
870817466cbSJens Wiklander /*
871817466cbSJens Wiklander  * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
872817466cbSJens Wiklander  */
873817466cbSJens Wiklander static void add_zeros_and_len_padding( unsigned char *output,
874817466cbSJens Wiklander                                        size_t output_len, size_t data_len )
875817466cbSJens Wiklander {
876817466cbSJens Wiklander     size_t padding_len = output_len - data_len;
877817466cbSJens Wiklander     unsigned char i = 0;
878817466cbSJens Wiklander 
879817466cbSJens Wiklander     for( i = 1; i < padding_len; i++ )
880817466cbSJens Wiklander         output[data_len + i - 1] = 0x00;
881817466cbSJens Wiklander     output[output_len - 1] = (unsigned char) padding_len;
882817466cbSJens Wiklander }
883817466cbSJens Wiklander 
884817466cbSJens Wiklander static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
885817466cbSJens Wiklander                                       size_t *data_len )
886817466cbSJens Wiklander {
887817466cbSJens Wiklander     size_t i, pad_idx;
888817466cbSJens Wiklander     unsigned char padding_len, bad = 0;
889817466cbSJens Wiklander 
890817466cbSJens Wiklander     if( NULL == input || NULL == data_len )
891817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
892817466cbSJens Wiklander 
893817466cbSJens Wiklander     padding_len = input[input_len - 1];
894817466cbSJens Wiklander     *data_len = input_len - padding_len;
895817466cbSJens Wiklander 
896817466cbSJens Wiklander     /* Avoid logical || since it results in a branch */
897817466cbSJens Wiklander     bad |= padding_len > input_len;
898817466cbSJens Wiklander     bad |= padding_len == 0;
899817466cbSJens Wiklander 
900817466cbSJens Wiklander     /* The number of bytes checked must be independent of padding_len */
901817466cbSJens Wiklander     pad_idx = input_len - padding_len;
902817466cbSJens Wiklander     for( i = 0; i < input_len - 1; i++ )
903817466cbSJens Wiklander         bad |= input[i] * ( i >= pad_idx );
904817466cbSJens Wiklander 
905817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
906817466cbSJens Wiklander }
907817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
908817466cbSJens Wiklander 
909817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
910817466cbSJens Wiklander /*
911817466cbSJens Wiklander  * Zero padding: fill with 00 ... 00
912817466cbSJens Wiklander  */
913817466cbSJens Wiklander static void add_zeros_padding( unsigned char *output,
914817466cbSJens Wiklander                                size_t output_len, size_t data_len )
915817466cbSJens Wiklander {
916817466cbSJens Wiklander     size_t i;
917817466cbSJens Wiklander 
918817466cbSJens Wiklander     for( i = data_len; i < output_len; i++ )
919817466cbSJens Wiklander         output[i] = 0x00;
920817466cbSJens Wiklander }
921817466cbSJens Wiklander 
922817466cbSJens Wiklander static int get_zeros_padding( unsigned char *input, size_t input_len,
923817466cbSJens Wiklander                               size_t *data_len )
924817466cbSJens Wiklander {
925817466cbSJens Wiklander     size_t i;
926817466cbSJens Wiklander     unsigned char done = 0, prev_done;
927817466cbSJens Wiklander 
928817466cbSJens Wiklander     if( NULL == input || NULL == data_len )
929817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
930817466cbSJens Wiklander 
931817466cbSJens Wiklander     *data_len = 0;
932817466cbSJens Wiklander     for( i = input_len; i > 0; i-- )
933817466cbSJens Wiklander     {
934817466cbSJens Wiklander         prev_done = done;
935817466cbSJens Wiklander         done |= ( input[i-1] != 0 );
936817466cbSJens Wiklander         *data_len |= i * ( done != prev_done );
937817466cbSJens Wiklander     }
938817466cbSJens Wiklander 
939817466cbSJens Wiklander     return( 0 );
940817466cbSJens Wiklander }
941817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
942817466cbSJens Wiklander 
943817466cbSJens Wiklander /*
944817466cbSJens Wiklander  * No padding: don't pad :)
945817466cbSJens Wiklander  *
946817466cbSJens Wiklander  * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
947817466cbSJens Wiklander  * but a trivial get_padding function
948817466cbSJens Wiklander  */
949817466cbSJens Wiklander static int get_no_padding( unsigned char *input, size_t input_len,
950817466cbSJens Wiklander                               size_t *data_len )
951817466cbSJens Wiklander {
952817466cbSJens Wiklander     if( NULL == input || NULL == data_len )
953817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
954817466cbSJens Wiklander 
955817466cbSJens Wiklander     *data_len = input_len;
956817466cbSJens Wiklander 
957817466cbSJens Wiklander     return( 0 );
958817466cbSJens Wiklander }
959817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
960817466cbSJens Wiklander 
961817466cbSJens Wiklander int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
962817466cbSJens Wiklander                    unsigned char *output, size_t *olen )
963817466cbSJens Wiklander {
9643d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
9653d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( output != NULL );
9663d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( olen != NULL );
9673d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
968817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
969817466cbSJens Wiklander 
970*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
971*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
972*11fa71b9SJerome Forissier     {
973*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
974*11fa71b9SJerome Forissier          * operations, we currently don't make it
975*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
976*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
977*11fa71b9SJerome Forissier     }
978*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
979*11fa71b9SJerome Forissier 
980817466cbSJens Wiklander     *olen = 0;
981817466cbSJens Wiklander 
982817466cbSJens Wiklander     if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
9833d3b0591SJens Wiklander         MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
984817466cbSJens Wiklander         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
985817466cbSJens Wiklander         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
9863d3b0591SJens Wiklander         MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
987817466cbSJens Wiklander         MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
988817466cbSJens Wiklander     {
989817466cbSJens Wiklander         return( 0 );
990817466cbSJens Wiklander     }
991817466cbSJens Wiklander 
9923d3b0591SJens Wiklander     if ( ( MBEDTLS_CIPHER_CHACHA20          == ctx->cipher_info->type ) ||
9933d3b0591SJens Wiklander          ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
9943d3b0591SJens Wiklander     {
9953d3b0591SJens Wiklander         return( 0 );
9963d3b0591SJens Wiklander     }
9973d3b0591SJens Wiklander 
998817466cbSJens Wiklander     if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
999817466cbSJens Wiklander     {
1000817466cbSJens Wiklander         if( ctx->unprocessed_len != 0 )
1001817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
1002817466cbSJens Wiklander 
1003817466cbSJens Wiklander         return( 0 );
1004817466cbSJens Wiklander     }
1005817466cbSJens Wiklander 
1006817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC)
1007817466cbSJens Wiklander     if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
1008817466cbSJens Wiklander     {
1009817466cbSJens Wiklander         int ret = 0;
1010817466cbSJens Wiklander 
1011817466cbSJens Wiklander         if( MBEDTLS_ENCRYPT == ctx->operation )
1012817466cbSJens Wiklander         {
1013817466cbSJens Wiklander             /* check for 'no padding' mode */
1014817466cbSJens Wiklander             if( NULL == ctx->add_padding )
1015817466cbSJens Wiklander             {
1016817466cbSJens Wiklander                 if( 0 != ctx->unprocessed_len )
1017817466cbSJens Wiklander                     return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
1018817466cbSJens Wiklander 
1019817466cbSJens Wiklander                 return( 0 );
1020817466cbSJens Wiklander             }
1021817466cbSJens Wiklander 
1022817466cbSJens Wiklander             ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
1023817466cbSJens Wiklander                     ctx->unprocessed_len );
1024817466cbSJens Wiklander         }
1025817466cbSJens Wiklander         else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
1026817466cbSJens Wiklander         {
1027817466cbSJens Wiklander             /*
1028817466cbSJens Wiklander              * For decrypt operations, expect a full block,
1029817466cbSJens Wiklander              * or an empty block if no padding
1030817466cbSJens Wiklander              */
1031817466cbSJens Wiklander             if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
1032817466cbSJens Wiklander                 return( 0 );
1033817466cbSJens Wiklander 
1034817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
1035817466cbSJens Wiklander         }
1036817466cbSJens Wiklander 
1037817466cbSJens Wiklander         /* cipher block */
1038817466cbSJens Wiklander         if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
1039817466cbSJens Wiklander                 ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
1040817466cbSJens Wiklander                 ctx->unprocessed_data, output ) ) )
1041817466cbSJens Wiklander         {
1042817466cbSJens Wiklander             return( ret );
1043817466cbSJens Wiklander         }
1044817466cbSJens Wiklander 
1045817466cbSJens Wiklander         /* Set output size for decryption */
1046817466cbSJens Wiklander         if( MBEDTLS_DECRYPT == ctx->operation )
10473d3b0591SJens Wiklander             return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
10483d3b0591SJens Wiklander                                       olen ) );
1049817466cbSJens Wiklander 
1050817466cbSJens Wiklander         /* Set output size for encryption */
1051817466cbSJens Wiklander         *olen = mbedtls_cipher_get_block_size( ctx );
1052817466cbSJens Wiklander         return( 0 );
1053817466cbSJens Wiklander     }
1054817466cbSJens Wiklander #else
1055817466cbSJens Wiklander     ((void) output);
1056817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */
1057817466cbSJens Wiklander 
1058817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1059817466cbSJens Wiklander }
1060817466cbSJens Wiklander 
1061817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
10623d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
10633d3b0591SJens Wiklander                                      mbedtls_cipher_padding_t mode )
1064817466cbSJens Wiklander {
10653d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
10663d3b0591SJens Wiklander 
10673d3b0591SJens Wiklander     if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
1068817466cbSJens Wiklander     {
1069817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1070817466cbSJens Wiklander     }
1071817466cbSJens Wiklander 
1072*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1073*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1074*11fa71b9SJerome Forissier     {
1075*11fa71b9SJerome Forissier         /* While PSA Crypto knows about CBC padding
1076*11fa71b9SJerome Forissier          * schemes, we currently don't make them
1077*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
1078*11fa71b9SJerome Forissier         if( mode != MBEDTLS_PADDING_NONE )
1079*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1080*11fa71b9SJerome Forissier 
1081*11fa71b9SJerome Forissier         return( 0 );
1082*11fa71b9SJerome Forissier     }
1083*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1084*11fa71b9SJerome Forissier 
1085817466cbSJens Wiklander     switch( mode )
1086817466cbSJens Wiklander     {
1087817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
1088817466cbSJens Wiklander     case MBEDTLS_PADDING_PKCS7:
1089817466cbSJens Wiklander         ctx->add_padding = add_pkcs_padding;
1090817466cbSJens Wiklander         ctx->get_padding = get_pkcs_padding;
1091817466cbSJens Wiklander         break;
1092817466cbSJens Wiklander #endif
1093817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
1094817466cbSJens Wiklander     case MBEDTLS_PADDING_ONE_AND_ZEROS:
1095817466cbSJens Wiklander         ctx->add_padding = add_one_and_zeros_padding;
1096817466cbSJens Wiklander         ctx->get_padding = get_one_and_zeros_padding;
1097817466cbSJens Wiklander         break;
1098817466cbSJens Wiklander #endif
1099817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
1100817466cbSJens Wiklander     case MBEDTLS_PADDING_ZEROS_AND_LEN:
1101817466cbSJens Wiklander         ctx->add_padding = add_zeros_and_len_padding;
1102817466cbSJens Wiklander         ctx->get_padding = get_zeros_and_len_padding;
1103817466cbSJens Wiklander         break;
1104817466cbSJens Wiklander #endif
1105817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
1106817466cbSJens Wiklander     case MBEDTLS_PADDING_ZEROS:
1107817466cbSJens Wiklander         ctx->add_padding = add_zeros_padding;
1108817466cbSJens Wiklander         ctx->get_padding = get_zeros_padding;
1109817466cbSJens Wiklander         break;
1110817466cbSJens Wiklander #endif
1111817466cbSJens Wiklander     case MBEDTLS_PADDING_NONE:
1112817466cbSJens Wiklander         ctx->add_padding = NULL;
1113817466cbSJens Wiklander         ctx->get_padding = get_no_padding;
1114817466cbSJens Wiklander         break;
1115817466cbSJens Wiklander 
1116817466cbSJens Wiklander     default:
1117817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1118817466cbSJens Wiklander     }
1119817466cbSJens Wiklander 
1120817466cbSJens Wiklander     return( 0 );
1121817466cbSJens Wiklander }
1122817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
1123817466cbSJens Wiklander 
11243d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
1125817466cbSJens Wiklander int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
1126817466cbSJens Wiklander                       unsigned char *tag, size_t tag_len )
1127817466cbSJens Wiklander {
11283d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
11293d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
11303d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
1131817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1132817466cbSJens Wiklander 
1133817466cbSJens Wiklander     if( MBEDTLS_ENCRYPT != ctx->operation )
1134817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1135817466cbSJens Wiklander 
1136*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1137*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1138*11fa71b9SJerome Forissier     {
1139*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
1140*11fa71b9SJerome Forissier          * operations, we currently don't make it
1141*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
1142*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1143*11fa71b9SJerome Forissier     }
1144*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1145*11fa71b9SJerome Forissier 
11463d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
1147817466cbSJens Wiklander     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
11483d3b0591SJens Wiklander         return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
11493d3b0591SJens Wiklander                                     tag, tag_len ) );
11503d3b0591SJens Wiklander #endif
11513d3b0591SJens Wiklander 
11523d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
11533d3b0591SJens Wiklander     if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
11543d3b0591SJens Wiklander     {
11553d3b0591SJens Wiklander         /* Don't allow truncated MAC for Poly1305 */
11563d3b0591SJens Wiklander         if ( tag_len != 16U )
11573d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
11583d3b0591SJens Wiklander 
1159*11fa71b9SJerome Forissier         return( mbedtls_chachapoly_finish(
1160*11fa71b9SJerome Forissier                     (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) );
11613d3b0591SJens Wiklander     }
11623d3b0591SJens Wiklander #endif
1163817466cbSJens Wiklander 
1164817466cbSJens Wiklander     return( 0 );
1165817466cbSJens Wiklander }
1166817466cbSJens Wiklander 
1167817466cbSJens Wiklander int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
1168817466cbSJens Wiklander                       const unsigned char *tag, size_t tag_len )
1169817466cbSJens Wiklander {
11703d3b0591SJens Wiklander     unsigned char check_tag[16];
1171*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1172817466cbSJens Wiklander 
11733d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
11743d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
11753d3b0591SJens Wiklander     if( ctx->cipher_info == NULL )
11763d3b0591SJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
11773d3b0591SJens Wiklander 
11783d3b0591SJens Wiklander     if( MBEDTLS_DECRYPT != ctx->operation )
1179817466cbSJens Wiklander     {
1180817466cbSJens Wiklander         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1181817466cbSJens Wiklander     }
1182817466cbSJens Wiklander 
1183*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1184*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1185*11fa71b9SJerome Forissier     {
1186*11fa71b9SJerome Forissier         /* While PSA Crypto has an API for multipart
1187*11fa71b9SJerome Forissier          * operations, we currently don't make it
1188*11fa71b9SJerome Forissier          * accessible through the cipher layer. */
1189*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1190*11fa71b9SJerome Forissier     }
1191*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1192*11fa71b9SJerome Forissier 
11933d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C)
1194817466cbSJens Wiklander     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1195817466cbSJens Wiklander     {
1196817466cbSJens Wiklander         if( tag_len > sizeof( check_tag ) )
1197817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1198817466cbSJens Wiklander 
1199*11fa71b9SJerome Forissier         if( 0 != ( ret = mbedtls_gcm_finish(
1200*11fa71b9SJerome Forissier                        (mbedtls_gcm_context *) ctx->cipher_ctx,
1201817466cbSJens Wiklander                        check_tag, tag_len ) ) )
1202817466cbSJens Wiklander         {
1203817466cbSJens Wiklander             return( ret );
1204817466cbSJens Wiklander         }
1205817466cbSJens Wiklander 
1206817466cbSJens Wiklander         /* Check the tag in "constant-time" */
12073d3b0591SJens Wiklander         if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
1208817466cbSJens Wiklander             return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1209817466cbSJens Wiklander 
1210817466cbSJens Wiklander         return( 0 );
1211817466cbSJens Wiklander     }
12123d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */
12133d3b0591SJens Wiklander 
12143d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
12153d3b0591SJens Wiklander     if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
12163d3b0591SJens Wiklander     {
12173d3b0591SJens Wiklander         /* Don't allow truncated MAC for Poly1305 */
12183d3b0591SJens Wiklander         if ( tag_len != sizeof( check_tag ) )
12193d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
12203d3b0591SJens Wiklander 
1221*11fa71b9SJerome Forissier         ret = mbedtls_chachapoly_finish(
1222*11fa71b9SJerome Forissier             (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag );
12233d3b0591SJens Wiklander         if ( ret != 0 )
12243d3b0591SJens Wiklander         {
12253d3b0591SJens Wiklander             return( ret );
12263d3b0591SJens Wiklander         }
12273d3b0591SJens Wiklander 
12283d3b0591SJens Wiklander         /* Check the tag in "constant-time" */
12293d3b0591SJens Wiklander         if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
12303d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1231817466cbSJens Wiklander 
1232817466cbSJens Wiklander         return( 0 );
1233817466cbSJens Wiklander     }
12343d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
12353d3b0591SJens Wiklander 
12363d3b0591SJens Wiklander     return( 0 );
12373d3b0591SJens Wiklander }
12383d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
1239817466cbSJens Wiklander 
1240817466cbSJens Wiklander /*
1241817466cbSJens Wiklander  * Packet-oriented wrapper for non-AEAD modes
1242817466cbSJens Wiklander  */
1243817466cbSJens Wiklander int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
1244817466cbSJens Wiklander                   const unsigned char *iv, size_t iv_len,
1245817466cbSJens Wiklander                   const unsigned char *input, size_t ilen,
1246817466cbSJens Wiklander                   unsigned char *output, size_t *olen )
1247817466cbSJens Wiklander {
1248*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1249817466cbSJens Wiklander     size_t finish_olen;
1250817466cbSJens Wiklander 
12513d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
12523d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
12533d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
12543d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( output != NULL );
12553d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( olen != NULL );
12563d3b0591SJens Wiklander 
1257*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1258*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1259*11fa71b9SJerome Forissier     {
1260*11fa71b9SJerome Forissier         /* As in the non-PSA case, we don't check that
1261*11fa71b9SJerome Forissier          * a key has been set. If not, the key slot will
1262*11fa71b9SJerome Forissier          * still be in its default state of 0, which is
1263*11fa71b9SJerome Forissier          * guaranteed to be invalid, hence the PSA-call
1264*11fa71b9SJerome Forissier          * below will gracefully fail. */
1265*11fa71b9SJerome Forissier         mbedtls_cipher_context_psa * const cipher_psa =
1266*11fa71b9SJerome Forissier             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
1267*11fa71b9SJerome Forissier 
1268*11fa71b9SJerome Forissier         psa_status_t status;
1269*11fa71b9SJerome Forissier         psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
1270*11fa71b9SJerome Forissier         size_t part_len;
1271*11fa71b9SJerome Forissier 
1272*11fa71b9SJerome Forissier         if( ctx->operation == MBEDTLS_DECRYPT )
1273*11fa71b9SJerome Forissier         {
1274*11fa71b9SJerome Forissier             status = psa_cipher_decrypt_setup( &cipher_op,
1275*11fa71b9SJerome Forissier                                                cipher_psa->slot,
1276*11fa71b9SJerome Forissier                                                cipher_psa->alg );
1277*11fa71b9SJerome Forissier         }
1278*11fa71b9SJerome Forissier         else if( ctx->operation == MBEDTLS_ENCRYPT )
1279*11fa71b9SJerome Forissier         {
1280*11fa71b9SJerome Forissier             status = psa_cipher_encrypt_setup( &cipher_op,
1281*11fa71b9SJerome Forissier                                                cipher_psa->slot,
1282*11fa71b9SJerome Forissier                                                cipher_psa->alg );
1283*11fa71b9SJerome Forissier         }
1284*11fa71b9SJerome Forissier         else
1285*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1286*11fa71b9SJerome Forissier 
1287*11fa71b9SJerome Forissier         /* In the following, we can immediately return on an error,
1288*11fa71b9SJerome Forissier          * because the PSA Crypto API guarantees that cipher operations
1289*11fa71b9SJerome Forissier          * are terminated by unsuccessful calls to psa_cipher_update(),
1290*11fa71b9SJerome Forissier          * and by any call to psa_cipher_finish(). */
1291*11fa71b9SJerome Forissier         if( status != PSA_SUCCESS )
1292*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1293*11fa71b9SJerome Forissier 
1294*11fa71b9SJerome Forissier         status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
1295*11fa71b9SJerome Forissier         if( status != PSA_SUCCESS )
1296*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1297*11fa71b9SJerome Forissier 
1298*11fa71b9SJerome Forissier         status = psa_cipher_update( &cipher_op,
1299*11fa71b9SJerome Forissier                                     input, ilen,
1300*11fa71b9SJerome Forissier                                     output, ilen, olen );
1301*11fa71b9SJerome Forissier         if( status != PSA_SUCCESS )
1302*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1303*11fa71b9SJerome Forissier 
1304*11fa71b9SJerome Forissier         status = psa_cipher_finish( &cipher_op,
1305*11fa71b9SJerome Forissier                                     output + *olen, ilen - *olen,
1306*11fa71b9SJerome Forissier                                     &part_len );
1307*11fa71b9SJerome Forissier         if( status != PSA_SUCCESS )
1308*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1309*11fa71b9SJerome Forissier 
1310*11fa71b9SJerome Forissier         *olen += part_len;
1311*11fa71b9SJerome Forissier         return( 0 );
1312*11fa71b9SJerome Forissier     }
1313*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1314*11fa71b9SJerome Forissier 
1315817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
1316817466cbSJens Wiklander         return( ret );
1317817466cbSJens Wiklander 
1318817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
1319817466cbSJens Wiklander         return( ret );
1320817466cbSJens Wiklander 
1321*11fa71b9SJerome Forissier     if( ( ret = mbedtls_cipher_update( ctx, input, ilen,
1322*11fa71b9SJerome Forissier                                        output, olen ) ) != 0 )
1323817466cbSJens Wiklander         return( ret );
1324817466cbSJens Wiklander 
1325*11fa71b9SJerome Forissier     if( ( ret = mbedtls_cipher_finish( ctx, output + *olen,
1326*11fa71b9SJerome Forissier                                        &finish_olen ) ) != 0 )
1327817466cbSJens Wiklander         return( ret );
1328817466cbSJens Wiklander 
1329817466cbSJens Wiklander     *olen += finish_olen;
1330817466cbSJens Wiklander 
1331817466cbSJens Wiklander     return( 0 );
1332817466cbSJens Wiklander }
1333817466cbSJens Wiklander 
1334817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD)
1335817466cbSJens Wiklander /*
1336817466cbSJens Wiklander  * Packet-oriented encryption for AEAD modes
1337817466cbSJens Wiklander  */
1338817466cbSJens Wiklander int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
1339817466cbSJens Wiklander                          const unsigned char *iv, size_t iv_len,
1340817466cbSJens Wiklander                          const unsigned char *ad, size_t ad_len,
1341817466cbSJens Wiklander                          const unsigned char *input, size_t ilen,
1342817466cbSJens Wiklander                          unsigned char *output, size_t *olen,
1343817466cbSJens Wiklander                          unsigned char *tag, size_t tag_len )
1344817466cbSJens Wiklander {
13453d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
13463d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( iv != NULL );
13473d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
13483d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
13493d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( output != NULL );
13503d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( olen != NULL );
13513d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
13523d3b0591SJens Wiklander 
1353*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1354*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1355*11fa71b9SJerome Forissier     {
1356*11fa71b9SJerome Forissier         /* As in the non-PSA case, we don't check that
1357*11fa71b9SJerome Forissier          * a key has been set. If not, the key slot will
1358*11fa71b9SJerome Forissier          * still be in its default state of 0, which is
1359*11fa71b9SJerome Forissier          * guaranteed to be invalid, hence the PSA-call
1360*11fa71b9SJerome Forissier          * below will gracefully fail. */
1361*11fa71b9SJerome Forissier         mbedtls_cipher_context_psa * const cipher_psa =
1362*11fa71b9SJerome Forissier             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
1363*11fa71b9SJerome Forissier 
1364*11fa71b9SJerome Forissier         psa_status_t status;
1365*11fa71b9SJerome Forissier 
1366*11fa71b9SJerome Forissier         /* PSA Crypto API always writes the authentication tag
1367*11fa71b9SJerome Forissier          * at the end of the encrypted message. */
1368*11fa71b9SJerome Forissier         if( tag != output + ilen )
1369*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1370*11fa71b9SJerome Forissier 
1371*11fa71b9SJerome Forissier         status = psa_aead_encrypt( cipher_psa->slot,
1372*11fa71b9SJerome Forissier                                    cipher_psa->alg,
1373*11fa71b9SJerome Forissier                                    iv, iv_len,
1374*11fa71b9SJerome Forissier                                    ad, ad_len,
1375*11fa71b9SJerome Forissier                                    input, ilen,
1376*11fa71b9SJerome Forissier                                    output, ilen + tag_len, olen );
1377*11fa71b9SJerome Forissier         if( status != PSA_SUCCESS )
1378*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1379*11fa71b9SJerome Forissier 
1380*11fa71b9SJerome Forissier         *olen -= tag_len;
1381*11fa71b9SJerome Forissier         return( 0 );
1382*11fa71b9SJerome Forissier     }
1383*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1384*11fa71b9SJerome Forissier 
1385817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
1386817466cbSJens Wiklander     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1387817466cbSJens Wiklander     {
1388817466cbSJens Wiklander         *olen = ilen;
1389*11fa71b9SJerome Forissier         return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
1390*11fa71b9SJerome Forissier                                            ilen, iv, iv_len, ad, ad_len,
1391*11fa71b9SJerome Forissier                                            input, output, tag_len, tag ) );
1392817466cbSJens Wiklander     }
1393817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1394817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
1395817466cbSJens Wiklander     if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1396817466cbSJens Wiklander     {
1397817466cbSJens Wiklander         *olen = ilen;
1398817466cbSJens Wiklander         return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
1399817466cbSJens Wiklander                                      iv, iv_len, ad, ad_len, input, output,
1400817466cbSJens Wiklander                                      tag, tag_len ) );
1401817466cbSJens Wiklander     }
1402817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */
14033d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
14043d3b0591SJens Wiklander     if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
14053d3b0591SJens Wiklander     {
14063d3b0591SJens Wiklander         /* ChachaPoly has fixed length nonce and MAC (tag) */
14073d3b0591SJens Wiklander         if ( ( iv_len != ctx->cipher_info->iv_size ) ||
14083d3b0591SJens Wiklander              ( tag_len != 16U ) )
14093d3b0591SJens Wiklander         {
14103d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
14113d3b0591SJens Wiklander         }
14123d3b0591SJens Wiklander 
14133d3b0591SJens Wiklander         *olen = ilen;
14143d3b0591SJens Wiklander         return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
14153d3b0591SJens Wiklander                                 ilen, iv, ad, ad_len, input, output, tag ) );
14163d3b0591SJens Wiklander     }
14173d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
1418*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
1419*11fa71b9SJerome Forissier    if( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
1420*11fa71b9SJerome Forissier        MBEDTLS_MODE_KWP == ctx->cipher_info->mode )
1421*11fa71b9SJerome Forissier     {
1422*11fa71b9SJerome Forissier         mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
1423*11fa71b9SJerome Forissier                                         MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
1424*11fa71b9SJerome Forissier 
1425*11fa71b9SJerome Forissier         /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */
1426*11fa71b9SJerome Forissier         if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
1427*11fa71b9SJerome Forissier         {
1428*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1429*11fa71b9SJerome Forissier         }
1430*11fa71b9SJerome Forissier 
1431*11fa71b9SJerome Forissier         return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) );
1432*11fa71b9SJerome Forissier     }
1433*11fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */
1434817466cbSJens Wiklander 
1435817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1436817466cbSJens Wiklander }
1437817466cbSJens Wiklander 
1438817466cbSJens Wiklander /*
1439817466cbSJens Wiklander  * Packet-oriented decryption for AEAD modes
1440817466cbSJens Wiklander  */
1441817466cbSJens Wiklander int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
1442817466cbSJens Wiklander                          const unsigned char *iv, size_t iv_len,
1443817466cbSJens Wiklander                          const unsigned char *ad, size_t ad_len,
1444817466cbSJens Wiklander                          const unsigned char *input, size_t ilen,
1445817466cbSJens Wiklander                          unsigned char *output, size_t *olen,
1446817466cbSJens Wiklander                          const unsigned char *tag, size_t tag_len )
1447817466cbSJens Wiklander {
14483d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ctx != NULL );
14493d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( iv != NULL );
14503d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
14513d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
14523d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( output != NULL );
14533d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( olen != NULL );
14543d3b0591SJens Wiklander     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
14553d3b0591SJens Wiklander 
1456*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
1457*11fa71b9SJerome Forissier     if( ctx->psa_enabled == 1 )
1458*11fa71b9SJerome Forissier     {
1459*11fa71b9SJerome Forissier         /* As in the non-PSA case, we don't check that
1460*11fa71b9SJerome Forissier          * a key has been set. If not, the key slot will
1461*11fa71b9SJerome Forissier          * still be in its default state of 0, which is
1462*11fa71b9SJerome Forissier          * guaranteed to be invalid, hence the PSA-call
1463*11fa71b9SJerome Forissier          * below will gracefully fail. */
1464*11fa71b9SJerome Forissier         mbedtls_cipher_context_psa * const cipher_psa =
1465*11fa71b9SJerome Forissier             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
1466*11fa71b9SJerome Forissier 
1467*11fa71b9SJerome Forissier         psa_status_t status;
1468*11fa71b9SJerome Forissier 
1469*11fa71b9SJerome Forissier         /* PSA Crypto API always writes the authentication tag
1470*11fa71b9SJerome Forissier          * at the end of the encrypted message. */
1471*11fa71b9SJerome Forissier         if( tag != input + ilen )
1472*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1473*11fa71b9SJerome Forissier 
1474*11fa71b9SJerome Forissier         status = psa_aead_decrypt( cipher_psa->slot,
1475*11fa71b9SJerome Forissier                                    cipher_psa->alg,
1476*11fa71b9SJerome Forissier                                    iv, iv_len,
1477*11fa71b9SJerome Forissier                                    ad, ad_len,
1478*11fa71b9SJerome Forissier                                    input, ilen + tag_len,
1479*11fa71b9SJerome Forissier                                    output, ilen, olen );
1480*11fa71b9SJerome Forissier         if( status == PSA_ERROR_INVALID_SIGNATURE )
1481*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1482*11fa71b9SJerome Forissier         else if( status != PSA_SUCCESS )
1483*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
1484*11fa71b9SJerome Forissier 
1485*11fa71b9SJerome Forissier         return( 0 );
1486*11fa71b9SJerome Forissier     }
1487*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
1488*11fa71b9SJerome Forissier 
1489817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
1490817466cbSJens Wiklander     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1491817466cbSJens Wiklander     {
1492*11fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1493817466cbSJens Wiklander 
1494817466cbSJens Wiklander         *olen = ilen;
1495817466cbSJens Wiklander         ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
1496817466cbSJens Wiklander                                 iv, iv_len, ad, ad_len,
1497817466cbSJens Wiklander                                 tag, tag_len, input, output );
1498817466cbSJens Wiklander 
1499817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
1500817466cbSJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1501817466cbSJens Wiklander 
1502817466cbSJens Wiklander         return( ret );
1503817466cbSJens Wiklander     }
1504817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1505817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C)
1506817466cbSJens Wiklander     if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1507817466cbSJens Wiklander     {
1508*11fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1509817466cbSJens Wiklander 
1510817466cbSJens Wiklander         *olen = ilen;
1511817466cbSJens Wiklander         ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
1512817466cbSJens Wiklander                                 iv, iv_len, ad, ad_len,
1513817466cbSJens Wiklander                                 input, output, tag, tag_len );
1514817466cbSJens Wiklander 
1515817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
1516817466cbSJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1517817466cbSJens Wiklander 
1518817466cbSJens Wiklander         return( ret );
1519817466cbSJens Wiklander     }
1520817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */
15213d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
15223d3b0591SJens Wiklander     if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
15233d3b0591SJens Wiklander     {
1524*11fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
15253d3b0591SJens Wiklander 
15263d3b0591SJens Wiklander         /* ChachaPoly has fixed length nonce and MAC (tag) */
15273d3b0591SJens Wiklander         if ( ( iv_len != ctx->cipher_info->iv_size ) ||
15283d3b0591SJens Wiklander              ( tag_len != 16U ) )
15293d3b0591SJens Wiklander         {
15303d3b0591SJens Wiklander             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
15313d3b0591SJens Wiklander         }
15323d3b0591SJens Wiklander 
15333d3b0591SJens Wiklander         *olen = ilen;
15343d3b0591SJens Wiklander         ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
15353d3b0591SJens Wiklander                                 iv, ad, ad_len, tag, input, output );
15363d3b0591SJens Wiklander 
15373d3b0591SJens Wiklander         if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
15383d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
15393d3b0591SJens Wiklander 
15403d3b0591SJens Wiklander         return( ret );
15413d3b0591SJens Wiklander     }
15423d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
1543*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C)
1544*11fa71b9SJerome Forissier     if( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
1545*11fa71b9SJerome Forissier         MBEDTLS_MODE_KWP == ctx->cipher_info->mode )
1546*11fa71b9SJerome Forissier     {
1547*11fa71b9SJerome Forissier         mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
1548*11fa71b9SJerome Forissier                                         MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
1549*11fa71b9SJerome Forissier 
1550*11fa71b9SJerome Forissier         /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */
1551*11fa71b9SJerome Forissier         if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
1552*11fa71b9SJerome Forissier         {
1553*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1554*11fa71b9SJerome Forissier         }
1555*11fa71b9SJerome Forissier 
1556*11fa71b9SJerome Forissier         return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) );
1557*11fa71b9SJerome Forissier     }
1558*11fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */
1559817466cbSJens Wiklander 
1560817466cbSJens Wiklander     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1561817466cbSJens Wiklander }
1562817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */
1563817466cbSJens Wiklander 
1564817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */
1565