1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  PSA cipher driver entry points
3a8e1175bSopenharmony_ci */
4a8e1175bSopenharmony_ci/*
5a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
6a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7a8e1175bSopenharmony_ci */
8a8e1175bSopenharmony_ci
9a8e1175bSopenharmony_ci#include "common.h"
10a8e1175bSopenharmony_ci
11a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_CRYPTO_C)
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_ci#include "psa_crypto_cipher.h"
14a8e1175bSopenharmony_ci#include "psa_crypto_core.h"
15a8e1175bSopenharmony_ci#include "psa_crypto_random_impl.h"
16a8e1175bSopenharmony_ci
17a8e1175bSopenharmony_ci#include "mbedtls/cipher.h"
18a8e1175bSopenharmony_ci#include "mbedtls/error.h"
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_ci#include <string.h>
21a8e1175bSopenharmony_ci
22a8e1175bSopenharmony_ci/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
23a8e1175bSopenharmony_ci * are enabled, but it does not provide any compatibility check between them
24a8e1175bSopenharmony_ci * (i.e. if the specified key works with the specified algorithm). This helper
25a8e1175bSopenharmony_ci * function is meant to provide this support.
26a8e1175bSopenharmony_ci * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
27a8e1175bSopenharmony_ci * requires CIPHER_C to be enabled.
28a8e1175bSopenharmony_ci */
29a8e1175bSopenharmony_cistatic psa_status_t mbedtls_cipher_validate_values(
30a8e1175bSopenharmony_ci    psa_algorithm_t alg,
31a8e1175bSopenharmony_ci    psa_key_type_t key_type)
32a8e1175bSopenharmony_ci{
33a8e1175bSopenharmony_ci    /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
34a8e1175bSopenharmony_ci       eliminate bits of the logic below. */
35a8e1175bSopenharmony_ci#if !defined(PSA_WANT_KEY_TYPE_AES)
36a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
37a8e1175bSopenharmony_ci#endif
38a8e1175bSopenharmony_ci#if !defined(PSA_WANT_KEY_TYPE_ARIA)
39a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
40a8e1175bSopenharmony_ci#endif
41a8e1175bSopenharmony_ci#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
42a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
43a8e1175bSopenharmony_ci#endif
44a8e1175bSopenharmony_ci#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
45a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
46a8e1175bSopenharmony_ci#endif
47a8e1175bSopenharmony_ci#if !defined(PSA_WANT_KEY_TYPE_DES)
48a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
49a8e1175bSopenharmony_ci#endif
50a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CCM)
51a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
52a8e1175bSopenharmony_ci#endif
53a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_GCM)
54a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
55a8e1175bSopenharmony_ci#endif
56a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_STREAM_CIPHER)
57a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
58a8e1175bSopenharmony_ci#endif
59a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
60a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
61a8e1175bSopenharmony_ci#endif
62a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
63a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
64a8e1175bSopenharmony_ci#endif
65a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CTR)
66a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
67a8e1175bSopenharmony_ci#endif
68a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CFB)
69a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
70a8e1175bSopenharmony_ci#endif
71a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_OFB)
72a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
73a8e1175bSopenharmony_ci#endif
74a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_XTS)
75a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_XTS);
76a8e1175bSopenharmony_ci#endif
77a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
78a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
79a8e1175bSopenharmony_ci#endif
80a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
81a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
82a8e1175bSopenharmony_ci#endif
83a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CBC_PKCS7)
84a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
85a8e1175bSopenharmony_ci#endif
86a8e1175bSopenharmony_ci#if !defined(PSA_WANT_ALG_CMAC)
87a8e1175bSopenharmony_ci    MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
88a8e1175bSopenharmony_ci#endif
89a8e1175bSopenharmony_ci
90a8e1175bSopenharmony_ci    if (alg == PSA_ALG_STREAM_CIPHER ||
91a8e1175bSopenharmony_ci        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
92a8e1175bSopenharmony_ci        if (key_type == PSA_KEY_TYPE_CHACHA20) {
93a8e1175bSopenharmony_ci            return PSA_SUCCESS;
94a8e1175bSopenharmony_ci        }
95a8e1175bSopenharmony_ci    }
96a8e1175bSopenharmony_ci
97a8e1175bSopenharmony_ci    if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
98a8e1175bSopenharmony_ci        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
99a8e1175bSopenharmony_ci        alg == PSA_ALG_CCM_STAR_NO_TAG) {
100a8e1175bSopenharmony_ci        if (key_type == PSA_KEY_TYPE_AES ||
101a8e1175bSopenharmony_ci            key_type == PSA_KEY_TYPE_ARIA ||
102a8e1175bSopenharmony_ci            key_type == PSA_KEY_TYPE_CAMELLIA) {
103a8e1175bSopenharmony_ci            return PSA_SUCCESS;
104a8e1175bSopenharmony_ci        }
105a8e1175bSopenharmony_ci    }
106a8e1175bSopenharmony_ci
107a8e1175bSopenharmony_ci    if (alg == PSA_ALG_CTR ||
108a8e1175bSopenharmony_ci        alg == PSA_ALG_CFB ||
109a8e1175bSopenharmony_ci        alg == PSA_ALG_OFB ||
110a8e1175bSopenharmony_ci        alg == PSA_ALG_XTS ||
111a8e1175bSopenharmony_ci        alg == PSA_ALG_ECB_NO_PADDING ||
112a8e1175bSopenharmony_ci        alg == PSA_ALG_CBC_NO_PADDING ||
113a8e1175bSopenharmony_ci        alg == PSA_ALG_CBC_PKCS7 ||
114a8e1175bSopenharmony_ci        alg == PSA_ALG_CMAC) {
115a8e1175bSopenharmony_ci        if (key_type == PSA_KEY_TYPE_AES ||
116a8e1175bSopenharmony_ci            key_type == PSA_KEY_TYPE_ARIA ||
117a8e1175bSopenharmony_ci            key_type == PSA_KEY_TYPE_DES ||
118a8e1175bSopenharmony_ci            key_type == PSA_KEY_TYPE_CAMELLIA) {
119a8e1175bSopenharmony_ci            return PSA_SUCCESS;
120a8e1175bSopenharmony_ci        }
121a8e1175bSopenharmony_ci    }
122a8e1175bSopenharmony_ci
123a8e1175bSopenharmony_ci    return PSA_ERROR_NOT_SUPPORTED;
124a8e1175bSopenharmony_ci}
125a8e1175bSopenharmony_ci
126a8e1175bSopenharmony_cipsa_status_t mbedtls_cipher_values_from_psa(
127a8e1175bSopenharmony_ci    psa_algorithm_t alg,
128a8e1175bSopenharmony_ci    psa_key_type_t key_type,
129a8e1175bSopenharmony_ci    size_t *key_bits,
130a8e1175bSopenharmony_ci    mbedtls_cipher_mode_t *mode,
131a8e1175bSopenharmony_ci    mbedtls_cipher_id_t *cipher_id)
132a8e1175bSopenharmony_ci{
133a8e1175bSopenharmony_ci    mbedtls_cipher_id_t cipher_id_tmp;
134a8e1175bSopenharmony_ci    /* Only DES modifies key_bits */
135a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
136a8e1175bSopenharmony_ci    (void) key_bits;
137a8e1175bSopenharmony_ci#endif
138a8e1175bSopenharmony_ci
139a8e1175bSopenharmony_ci    if (PSA_ALG_IS_AEAD(alg)) {
140a8e1175bSopenharmony_ci        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
141a8e1175bSopenharmony_ci    }
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci    if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
144a8e1175bSopenharmony_ci        switch (alg) {
145a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
146a8e1175bSopenharmony_ci            case PSA_ALG_STREAM_CIPHER:
147a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_STREAM;
148a8e1175bSopenharmony_ci                break;
149a8e1175bSopenharmony_ci#endif
150a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
151a8e1175bSopenharmony_ci            case PSA_ALG_CTR:
152a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CTR;
153a8e1175bSopenharmony_ci                break;
154a8e1175bSopenharmony_ci#endif
155a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
156a8e1175bSopenharmony_ci            case PSA_ALG_CFB:
157a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CFB;
158a8e1175bSopenharmony_ci                break;
159a8e1175bSopenharmony_ci#endif
160a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
161a8e1175bSopenharmony_ci            case PSA_ALG_OFB:
162a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_OFB;
163a8e1175bSopenharmony_ci                break;
164a8e1175bSopenharmony_ci#endif
165a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
166a8e1175bSopenharmony_ci            case PSA_ALG_ECB_NO_PADDING:
167a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_ECB;
168a8e1175bSopenharmony_ci                break;
169a8e1175bSopenharmony_ci#endif
170a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
171a8e1175bSopenharmony_ci            case PSA_ALG_CBC_NO_PADDING:
172a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CBC;
173a8e1175bSopenharmony_ci                break;
174a8e1175bSopenharmony_ci#endif
175a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
176a8e1175bSopenharmony_ci            case PSA_ALG_CBC_PKCS7:
177a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CBC;
178a8e1175bSopenharmony_ci                break;
179a8e1175bSopenharmony_ci#endif
180a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
181a8e1175bSopenharmony_ci            case PSA_ALG_CCM_STAR_NO_TAG:
182a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
183a8e1175bSopenharmony_ci                break;
184a8e1175bSopenharmony_ci#endif
185a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
186a8e1175bSopenharmony_ci            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
187a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CCM;
188a8e1175bSopenharmony_ci                break;
189a8e1175bSopenharmony_ci#endif
190a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
191a8e1175bSopenharmony_ci            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
192a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_GCM;
193a8e1175bSopenharmony_ci                break;
194a8e1175bSopenharmony_ci#endif
195a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
196a8e1175bSopenharmony_ci            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
197a8e1175bSopenharmony_ci                *mode = MBEDTLS_MODE_CHACHAPOLY;
198a8e1175bSopenharmony_ci                break;
199a8e1175bSopenharmony_ci#endif
200a8e1175bSopenharmony_ci            default:
201a8e1175bSopenharmony_ci                return PSA_ERROR_NOT_SUPPORTED;
202a8e1175bSopenharmony_ci        }
203a8e1175bSopenharmony_ci    } else if (alg == PSA_ALG_CMAC) {
204a8e1175bSopenharmony_ci        *mode = MBEDTLS_MODE_ECB;
205a8e1175bSopenharmony_ci    } else {
206a8e1175bSopenharmony_ci        return PSA_ERROR_NOT_SUPPORTED;
207a8e1175bSopenharmony_ci    }
208a8e1175bSopenharmony_ci
209a8e1175bSopenharmony_ci    switch (key_type) {
210a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
211a8e1175bSopenharmony_ci        case PSA_KEY_TYPE_AES:
212a8e1175bSopenharmony_ci            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
213a8e1175bSopenharmony_ci            break;
214a8e1175bSopenharmony_ci#endif
215a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
216a8e1175bSopenharmony_ci        case PSA_KEY_TYPE_ARIA:
217a8e1175bSopenharmony_ci            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
218a8e1175bSopenharmony_ci            break;
219a8e1175bSopenharmony_ci#endif
220a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
221a8e1175bSopenharmony_ci        case PSA_KEY_TYPE_DES:
222a8e1175bSopenharmony_ci            /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
223a8e1175bSopenharmony_ci             * and 192 for three-key Triple-DES. */
224a8e1175bSopenharmony_ci            if (*key_bits == 64) {
225a8e1175bSopenharmony_ci                cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
226a8e1175bSopenharmony_ci            } else {
227a8e1175bSopenharmony_ci                cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
228a8e1175bSopenharmony_ci            }
229a8e1175bSopenharmony_ci            /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
230a8e1175bSopenharmony_ci             * but two-key Triple-DES is functionally three-key Triple-DES
231a8e1175bSopenharmony_ci             * with K1=K3, so that's how we present it to mbedtls. */
232a8e1175bSopenharmony_ci            if (*key_bits == 128) {
233a8e1175bSopenharmony_ci                *key_bits = 192;
234a8e1175bSopenharmony_ci            }
235a8e1175bSopenharmony_ci            break;
236a8e1175bSopenharmony_ci#endif
237a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
238a8e1175bSopenharmony_ci        case PSA_KEY_TYPE_CAMELLIA:
239a8e1175bSopenharmony_ci            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
240a8e1175bSopenharmony_ci            break;
241a8e1175bSopenharmony_ci#endif
242a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
243a8e1175bSopenharmony_ci        case PSA_KEY_TYPE_CHACHA20:
244a8e1175bSopenharmony_ci            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
245a8e1175bSopenharmony_ci            break;
246a8e1175bSopenharmony_ci#endif
247a8e1175bSopenharmony_ci        default:
248a8e1175bSopenharmony_ci            return PSA_ERROR_NOT_SUPPORTED;
249a8e1175bSopenharmony_ci    }
250a8e1175bSopenharmony_ci    if (cipher_id != NULL) {
251a8e1175bSopenharmony_ci        *cipher_id = cipher_id_tmp;
252a8e1175bSopenharmony_ci    }
253a8e1175bSopenharmony_ci
254a8e1175bSopenharmony_ci    return mbedtls_cipher_validate_values(alg, key_type);
255a8e1175bSopenharmony_ci}
256a8e1175bSopenharmony_ci
257a8e1175bSopenharmony_ci#if defined(MBEDTLS_CIPHER_C)
258a8e1175bSopenharmony_ciconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
259a8e1175bSopenharmony_ci    psa_algorithm_t alg,
260a8e1175bSopenharmony_ci    psa_key_type_t key_type,
261a8e1175bSopenharmony_ci    size_t key_bits,
262a8e1175bSopenharmony_ci    mbedtls_cipher_id_t *cipher_id)
263a8e1175bSopenharmony_ci{
264a8e1175bSopenharmony_ci    mbedtls_cipher_mode_t mode;
265a8e1175bSopenharmony_ci    psa_status_t status;
266a8e1175bSopenharmony_ci    mbedtls_cipher_id_t cipher_id_tmp;
267a8e1175bSopenharmony_ci
268a8e1175bSopenharmony_ci    status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
269a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
270a8e1175bSopenharmony_ci        return NULL;
271a8e1175bSopenharmony_ci    }
272a8e1175bSopenharmony_ci    if (cipher_id != NULL) {
273a8e1175bSopenharmony_ci        *cipher_id = cipher_id_tmp;
274a8e1175bSopenharmony_ci    }
275a8e1175bSopenharmony_ci
276a8e1175bSopenharmony_ci    return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
277a8e1175bSopenharmony_ci}
278a8e1175bSopenharmony_ci#endif /* MBEDTLS_CIPHER_C */
279a8e1175bSopenharmony_ci
280a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
281a8e1175bSopenharmony_ci
282a8e1175bSopenharmony_cistatic psa_status_t psa_cipher_setup(
283a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
284a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
285a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
286a8e1175bSopenharmony_ci    psa_algorithm_t alg,
287a8e1175bSopenharmony_ci    mbedtls_operation_t cipher_operation)
288a8e1175bSopenharmony_ci{
289a8e1175bSopenharmony_ci    int ret = 0;
290a8e1175bSopenharmony_ci    size_t key_bits;
291a8e1175bSopenharmony_ci    const mbedtls_cipher_info_t *cipher_info = NULL;
292a8e1175bSopenharmony_ci    psa_key_type_t key_type = attributes->type;
293a8e1175bSopenharmony_ci
294a8e1175bSopenharmony_ci    (void) key_buffer_size;
295a8e1175bSopenharmony_ci
296a8e1175bSopenharmony_ci    mbedtls_cipher_init(&operation->ctx.cipher);
297a8e1175bSopenharmony_ci
298a8e1175bSopenharmony_ci    operation->alg = alg;
299a8e1175bSopenharmony_ci    key_bits = attributes->bits;
300a8e1175bSopenharmony_ci    cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
301a8e1175bSopenharmony_ci                                               key_bits, NULL);
302a8e1175bSopenharmony_ci    if (cipher_info == NULL) {
303a8e1175bSopenharmony_ci        return PSA_ERROR_NOT_SUPPORTED;
304a8e1175bSopenharmony_ci    }
305a8e1175bSopenharmony_ci
306a8e1175bSopenharmony_ci    ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
307a8e1175bSopenharmony_ci    if (ret != 0) {
308a8e1175bSopenharmony_ci        goto exit;
309a8e1175bSopenharmony_ci    }
310a8e1175bSopenharmony_ci
311a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
312a8e1175bSopenharmony_ci    if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
313a8e1175bSopenharmony_ci        /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
314a8e1175bSopenharmony_ci        uint8_t keys[24];
315a8e1175bSopenharmony_ci        memcpy(keys, key_buffer, 16);
316a8e1175bSopenharmony_ci        memcpy(keys + 16, key_buffer, 8);
317a8e1175bSopenharmony_ci        ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
318a8e1175bSopenharmony_ci                                    keys,
319a8e1175bSopenharmony_ci                                    192, cipher_operation);
320a8e1175bSopenharmony_ci    } else
321a8e1175bSopenharmony_ci#endif
322a8e1175bSopenharmony_ci    {
323a8e1175bSopenharmony_ci        ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
324a8e1175bSopenharmony_ci                                    (int) key_bits, cipher_operation);
325a8e1175bSopenharmony_ci    }
326a8e1175bSopenharmony_ci    if (ret != 0) {
327a8e1175bSopenharmony_ci        goto exit;
328a8e1175bSopenharmony_ci    }
329a8e1175bSopenharmony_ci
330a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
331a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
332a8e1175bSopenharmony_ci    switch (alg) {
333a8e1175bSopenharmony_ci        case PSA_ALG_CBC_NO_PADDING:
334a8e1175bSopenharmony_ci            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
335a8e1175bSopenharmony_ci                                                  MBEDTLS_PADDING_NONE);
336a8e1175bSopenharmony_ci            break;
337a8e1175bSopenharmony_ci        case PSA_ALG_CBC_PKCS7:
338a8e1175bSopenharmony_ci            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
339a8e1175bSopenharmony_ci                                                  MBEDTLS_PADDING_PKCS7);
340a8e1175bSopenharmony_ci            break;
341a8e1175bSopenharmony_ci        default:
342a8e1175bSopenharmony_ci            /* The algorithm doesn't involve padding. */
343a8e1175bSopenharmony_ci            ret = 0;
344a8e1175bSopenharmony_ci            break;
345a8e1175bSopenharmony_ci    }
346a8e1175bSopenharmony_ci    if (ret != 0) {
347a8e1175bSopenharmony_ci        goto exit;
348a8e1175bSopenharmony_ci    }
349a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
350a8e1175bSopenharmony_ci          MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
351a8e1175bSopenharmony_ci
352a8e1175bSopenharmony_ci    operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
353a8e1175bSopenharmony_ci                               PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
354a8e1175bSopenharmony_ci    operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
355a8e1175bSopenharmony_ci
356a8e1175bSopenharmony_ciexit:
357a8e1175bSopenharmony_ci    return mbedtls_to_psa_error(ret);
358a8e1175bSopenharmony_ci}
359a8e1175bSopenharmony_ci
360a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_encrypt_setup(
361a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
362a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
363a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
364a8e1175bSopenharmony_ci    psa_algorithm_t alg)
365a8e1175bSopenharmony_ci{
366a8e1175bSopenharmony_ci    return psa_cipher_setup(operation, attributes,
367a8e1175bSopenharmony_ci                            key_buffer, key_buffer_size,
368a8e1175bSopenharmony_ci                            alg, MBEDTLS_ENCRYPT);
369a8e1175bSopenharmony_ci}
370a8e1175bSopenharmony_ci
371a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_decrypt_setup(
372a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
373a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
374a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
375a8e1175bSopenharmony_ci    psa_algorithm_t alg)
376a8e1175bSopenharmony_ci{
377a8e1175bSopenharmony_ci    return psa_cipher_setup(operation, attributes,
378a8e1175bSopenharmony_ci                            key_buffer, key_buffer_size,
379a8e1175bSopenharmony_ci                            alg, MBEDTLS_DECRYPT);
380a8e1175bSopenharmony_ci}
381a8e1175bSopenharmony_ci
382a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_set_iv(
383a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
384a8e1175bSopenharmony_ci    const uint8_t *iv, size_t iv_length)
385a8e1175bSopenharmony_ci{
386a8e1175bSopenharmony_ci    if (iv_length != operation->iv_length) {
387a8e1175bSopenharmony_ci        return PSA_ERROR_INVALID_ARGUMENT;
388a8e1175bSopenharmony_ci    }
389a8e1175bSopenharmony_ci
390a8e1175bSopenharmony_ci    return mbedtls_to_psa_error(
391a8e1175bSopenharmony_ci        mbedtls_cipher_set_iv(&operation->ctx.cipher,
392a8e1175bSopenharmony_ci                              iv, iv_length));
393a8e1175bSopenharmony_ci}
394a8e1175bSopenharmony_ci
395a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
396a8e1175bSopenharmony_ci/** Process input for which the algorithm is set to ECB mode.
397a8e1175bSopenharmony_ci *
398a8e1175bSopenharmony_ci * This requires manual processing, since the PSA API is defined as being
399a8e1175bSopenharmony_ci * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
400a8e1175bSopenharmony_ci * but the underlying mbedtls_cipher_update only takes full blocks.
401a8e1175bSopenharmony_ci *
402a8e1175bSopenharmony_ci * \param ctx           The mbedtls cipher context to use. It must have been
403a8e1175bSopenharmony_ci *                      set up for ECB.
404a8e1175bSopenharmony_ci * \param[in] input     The input plaintext or ciphertext to process.
405a8e1175bSopenharmony_ci * \param input_length  The number of bytes to process from \p input.
406a8e1175bSopenharmony_ci *                      This does not need to be aligned to a block boundary.
407a8e1175bSopenharmony_ci *                      If there is a partial block at the end of the input,
408a8e1175bSopenharmony_ci *                      it is stored in \p ctx for future processing.
409a8e1175bSopenharmony_ci * \param output        The buffer where the output is written. It must be
410a8e1175bSopenharmony_ci *                      at least `BS * floor((p + input_length) / BS)` bytes
411a8e1175bSopenharmony_ci *                      long, where `p` is the number of bytes in the
412a8e1175bSopenharmony_ci *                      unprocessed partial block in \p ctx (with
413a8e1175bSopenharmony_ci *                      `0 <= p <= BS - 1`) and `BS` is the block size.
414a8e1175bSopenharmony_ci * \param output_length On success, the number of bytes written to \p output.
415a8e1175bSopenharmony_ci *                      \c 0 on error.
416a8e1175bSopenharmony_ci *
417a8e1175bSopenharmony_ci * \return #PSA_SUCCESS or an error from a hardware accelerator
418a8e1175bSopenharmony_ci */
419a8e1175bSopenharmony_cistatic psa_status_t psa_cipher_update_ecb(
420a8e1175bSopenharmony_ci    mbedtls_cipher_context_t *ctx,
421a8e1175bSopenharmony_ci    const uint8_t *input,
422a8e1175bSopenharmony_ci    size_t input_length,
423a8e1175bSopenharmony_ci    uint8_t *output,
424a8e1175bSopenharmony_ci    size_t *output_length)
425a8e1175bSopenharmony_ci{
426a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
427a8e1175bSopenharmony_ci    size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
428a8e1175bSopenharmony_ci    size_t internal_output_length = 0;
429a8e1175bSopenharmony_ci    *output_length = 0;
430a8e1175bSopenharmony_ci
431a8e1175bSopenharmony_ci    if (input_length == 0) {
432a8e1175bSopenharmony_ci        status = PSA_SUCCESS;
433a8e1175bSopenharmony_ci        goto exit;
434a8e1175bSopenharmony_ci    }
435a8e1175bSopenharmony_ci
436a8e1175bSopenharmony_ci    if (ctx->unprocessed_len > 0) {
437a8e1175bSopenharmony_ci        /* Fill up to block size, and run the block if there's a full one. */
438a8e1175bSopenharmony_ci        size_t bytes_to_copy = block_size - ctx->unprocessed_len;
439a8e1175bSopenharmony_ci
440a8e1175bSopenharmony_ci        if (input_length < bytes_to_copy) {
441a8e1175bSopenharmony_ci            bytes_to_copy = input_length;
442a8e1175bSopenharmony_ci        }
443a8e1175bSopenharmony_ci
444a8e1175bSopenharmony_ci        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
445a8e1175bSopenharmony_ci               input, bytes_to_copy);
446a8e1175bSopenharmony_ci        input_length -= bytes_to_copy;
447a8e1175bSopenharmony_ci        input += bytes_to_copy;
448a8e1175bSopenharmony_ci        ctx->unprocessed_len += bytes_to_copy;
449a8e1175bSopenharmony_ci
450a8e1175bSopenharmony_ci        if (ctx->unprocessed_len == block_size) {
451a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
452a8e1175bSopenharmony_ci                mbedtls_cipher_update(ctx,
453a8e1175bSopenharmony_ci                                      ctx->unprocessed_data,
454a8e1175bSopenharmony_ci                                      block_size,
455a8e1175bSopenharmony_ci                                      output, &internal_output_length));
456a8e1175bSopenharmony_ci
457a8e1175bSopenharmony_ci            if (status != PSA_SUCCESS) {
458a8e1175bSopenharmony_ci                goto exit;
459a8e1175bSopenharmony_ci            }
460a8e1175bSopenharmony_ci
461a8e1175bSopenharmony_ci            output += internal_output_length;
462a8e1175bSopenharmony_ci            *output_length += internal_output_length;
463a8e1175bSopenharmony_ci            ctx->unprocessed_len = 0;
464a8e1175bSopenharmony_ci        }
465a8e1175bSopenharmony_ci    }
466a8e1175bSopenharmony_ci
467a8e1175bSopenharmony_ci    while (input_length >= block_size) {
468a8e1175bSopenharmony_ci        /* Run all full blocks we have, one by one */
469a8e1175bSopenharmony_ci        status = mbedtls_to_psa_error(
470a8e1175bSopenharmony_ci            mbedtls_cipher_update(ctx, input,
471a8e1175bSopenharmony_ci                                  block_size,
472a8e1175bSopenharmony_ci                                  output, &internal_output_length));
473a8e1175bSopenharmony_ci
474a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
475a8e1175bSopenharmony_ci            goto exit;
476a8e1175bSopenharmony_ci        }
477a8e1175bSopenharmony_ci
478a8e1175bSopenharmony_ci        input_length -= block_size;
479a8e1175bSopenharmony_ci        input += block_size;
480a8e1175bSopenharmony_ci
481a8e1175bSopenharmony_ci        output += internal_output_length;
482a8e1175bSopenharmony_ci        *output_length += internal_output_length;
483a8e1175bSopenharmony_ci    }
484a8e1175bSopenharmony_ci
485a8e1175bSopenharmony_ci    if (input_length > 0) {
486a8e1175bSopenharmony_ci        /* Save unprocessed bytes for later processing */
487a8e1175bSopenharmony_ci        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
488a8e1175bSopenharmony_ci               input, input_length);
489a8e1175bSopenharmony_ci        ctx->unprocessed_len += input_length;
490a8e1175bSopenharmony_ci    }
491a8e1175bSopenharmony_ci
492a8e1175bSopenharmony_ci    status = PSA_SUCCESS;
493a8e1175bSopenharmony_ci
494a8e1175bSopenharmony_ciexit:
495a8e1175bSopenharmony_ci    return status;
496a8e1175bSopenharmony_ci}
497a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
498a8e1175bSopenharmony_ci
499a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_update(
500a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
501a8e1175bSopenharmony_ci    const uint8_t *input, size_t input_length,
502a8e1175bSopenharmony_ci    uint8_t *output, size_t output_size, size_t *output_length)
503a8e1175bSopenharmony_ci{
504a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
505a8e1175bSopenharmony_ci    size_t expected_output_size;
506a8e1175bSopenharmony_ci
507a8e1175bSopenharmony_ci    if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
508a8e1175bSopenharmony_ci        /* Take the unprocessed partial block left over from previous
509a8e1175bSopenharmony_ci         * update calls, if any, plus the input to this call. Remove
510a8e1175bSopenharmony_ci         * the last partial block, if any. You get the data that will be
511a8e1175bSopenharmony_ci         * output in this call. */
512a8e1175bSopenharmony_ci        expected_output_size =
513a8e1175bSopenharmony_ci            (operation->ctx.cipher.unprocessed_len + input_length)
514a8e1175bSopenharmony_ci            / operation->block_length * operation->block_length;
515a8e1175bSopenharmony_ci    } else {
516a8e1175bSopenharmony_ci        expected_output_size = input_length;
517a8e1175bSopenharmony_ci    }
518a8e1175bSopenharmony_ci
519a8e1175bSopenharmony_ci    if (output_size < expected_output_size) {
520a8e1175bSopenharmony_ci        return PSA_ERROR_BUFFER_TOO_SMALL;
521a8e1175bSopenharmony_ci    }
522a8e1175bSopenharmony_ci
523a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
524a8e1175bSopenharmony_ci    if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
525a8e1175bSopenharmony_ci        /* mbedtls_cipher_update has an API inconsistency: it will only
526a8e1175bSopenharmony_ci         * process a single block at a time in ECB mode. Abstract away that
527a8e1175bSopenharmony_ci         * inconsistency here to match the PSA API behaviour. */
528a8e1175bSopenharmony_ci        status = psa_cipher_update_ecb(&operation->ctx.cipher,
529a8e1175bSopenharmony_ci                                       input,
530a8e1175bSopenharmony_ci                                       input_length,
531a8e1175bSopenharmony_ci                                       output,
532a8e1175bSopenharmony_ci                                       output_length);
533a8e1175bSopenharmony_ci    } else
534a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
535a8e1175bSopenharmony_ci    if (input_length == 0) {
536a8e1175bSopenharmony_ci        /* There is no input, nothing to be done */
537a8e1175bSopenharmony_ci        *output_length = 0;
538a8e1175bSopenharmony_ci        status = PSA_SUCCESS;
539a8e1175bSopenharmony_ci    } else {
540a8e1175bSopenharmony_ci        status = mbedtls_to_psa_error(
541a8e1175bSopenharmony_ci            mbedtls_cipher_update(&operation->ctx.cipher, input,
542a8e1175bSopenharmony_ci                                  input_length, output, output_length));
543a8e1175bSopenharmony_ci
544a8e1175bSopenharmony_ci        if (*output_length > output_size) {
545a8e1175bSopenharmony_ci            return PSA_ERROR_CORRUPTION_DETECTED;
546a8e1175bSopenharmony_ci        }
547a8e1175bSopenharmony_ci    }
548a8e1175bSopenharmony_ci
549a8e1175bSopenharmony_ci    return status;
550a8e1175bSopenharmony_ci}
551a8e1175bSopenharmony_ci
552a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_finish(
553a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation,
554a8e1175bSopenharmony_ci    uint8_t *output, size_t output_size, size_t *output_length)
555a8e1175bSopenharmony_ci{
556a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
557a8e1175bSopenharmony_ci    uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
558a8e1175bSopenharmony_ci
559a8e1175bSopenharmony_ci    if (operation->ctx.cipher.unprocessed_len != 0) {
560a8e1175bSopenharmony_ci        if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
561a8e1175bSopenharmony_ci            operation->alg == PSA_ALG_CBC_NO_PADDING) {
562a8e1175bSopenharmony_ci            status = PSA_ERROR_INVALID_ARGUMENT;
563a8e1175bSopenharmony_ci            goto exit;
564a8e1175bSopenharmony_ci        }
565a8e1175bSopenharmony_ci    }
566a8e1175bSopenharmony_ci
567a8e1175bSopenharmony_ci    status = mbedtls_to_psa_error(
568a8e1175bSopenharmony_ci        mbedtls_cipher_finish(&operation->ctx.cipher,
569a8e1175bSopenharmony_ci                              temp_output_buffer,
570a8e1175bSopenharmony_ci                              output_length));
571a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
572a8e1175bSopenharmony_ci        goto exit;
573a8e1175bSopenharmony_ci    }
574a8e1175bSopenharmony_ci
575a8e1175bSopenharmony_ci    if (*output_length == 0) {
576a8e1175bSopenharmony_ci        ; /* Nothing to copy. Note that output may be NULL in this case. */
577a8e1175bSopenharmony_ci    } else if (output_size >= *output_length) {
578a8e1175bSopenharmony_ci        memcpy(output, temp_output_buffer, *output_length);
579a8e1175bSopenharmony_ci    } else {
580a8e1175bSopenharmony_ci        status = PSA_ERROR_BUFFER_TOO_SMALL;
581a8e1175bSopenharmony_ci    }
582a8e1175bSopenharmony_ci
583a8e1175bSopenharmony_ciexit:
584a8e1175bSopenharmony_ci    mbedtls_platform_zeroize(temp_output_buffer,
585a8e1175bSopenharmony_ci                             sizeof(temp_output_buffer));
586a8e1175bSopenharmony_ci
587a8e1175bSopenharmony_ci    return status;
588a8e1175bSopenharmony_ci}
589a8e1175bSopenharmony_ci
590a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_abort(
591a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t *operation)
592a8e1175bSopenharmony_ci{
593a8e1175bSopenharmony_ci    /* Sanity check (shouldn't happen: operation->alg should
594a8e1175bSopenharmony_ci     * always have been initialized to a valid value). */
595a8e1175bSopenharmony_ci    if (!PSA_ALG_IS_CIPHER(operation->alg)) {
596a8e1175bSopenharmony_ci        return PSA_ERROR_BAD_STATE;
597a8e1175bSopenharmony_ci    }
598a8e1175bSopenharmony_ci
599a8e1175bSopenharmony_ci    mbedtls_cipher_free(&operation->ctx.cipher);
600a8e1175bSopenharmony_ci
601a8e1175bSopenharmony_ci    return PSA_SUCCESS;
602a8e1175bSopenharmony_ci}
603a8e1175bSopenharmony_ci
604a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_encrypt(
605a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
606a8e1175bSopenharmony_ci    const uint8_t *key_buffer,
607a8e1175bSopenharmony_ci    size_t key_buffer_size,
608a8e1175bSopenharmony_ci    psa_algorithm_t alg,
609a8e1175bSopenharmony_ci    const uint8_t *iv,
610a8e1175bSopenharmony_ci    size_t iv_length,
611a8e1175bSopenharmony_ci    const uint8_t *input,
612a8e1175bSopenharmony_ci    size_t input_length,
613a8e1175bSopenharmony_ci    uint8_t *output,
614a8e1175bSopenharmony_ci    size_t output_size,
615a8e1175bSopenharmony_ci    size_t *output_length)
616a8e1175bSopenharmony_ci{
617a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
618a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
619a8e1175bSopenharmony_ci    size_t update_output_length, finish_output_length;
620a8e1175bSopenharmony_ci
621a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
622a8e1175bSopenharmony_ci                                              key_buffer, key_buffer_size,
623a8e1175bSopenharmony_ci                                              alg);
624a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
625a8e1175bSopenharmony_ci        goto exit;
626a8e1175bSopenharmony_ci    }
627a8e1175bSopenharmony_ci
628a8e1175bSopenharmony_ci    if (iv_length > 0) {
629a8e1175bSopenharmony_ci        status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
630a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
631a8e1175bSopenharmony_ci            goto exit;
632a8e1175bSopenharmony_ci        }
633a8e1175bSopenharmony_ci    }
634a8e1175bSopenharmony_ci
635a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_update(&operation, input, input_length,
636a8e1175bSopenharmony_ci                                       output, output_size,
637a8e1175bSopenharmony_ci                                       &update_output_length);
638a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
639a8e1175bSopenharmony_ci        goto exit;
640a8e1175bSopenharmony_ci    }
641a8e1175bSopenharmony_ci
642a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_finish(
643a8e1175bSopenharmony_ci        &operation,
644a8e1175bSopenharmony_ci        mbedtls_buffer_offset(output, update_output_length),
645a8e1175bSopenharmony_ci        output_size - update_output_length, &finish_output_length);
646a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
647a8e1175bSopenharmony_ci        goto exit;
648a8e1175bSopenharmony_ci    }
649a8e1175bSopenharmony_ci
650a8e1175bSopenharmony_ci    *output_length = update_output_length + finish_output_length;
651a8e1175bSopenharmony_ci
652a8e1175bSopenharmony_ciexit:
653a8e1175bSopenharmony_ci    if (status == PSA_SUCCESS) {
654a8e1175bSopenharmony_ci        status = mbedtls_psa_cipher_abort(&operation);
655a8e1175bSopenharmony_ci    } else {
656a8e1175bSopenharmony_ci        mbedtls_psa_cipher_abort(&operation);
657a8e1175bSopenharmony_ci    }
658a8e1175bSopenharmony_ci
659a8e1175bSopenharmony_ci    return status;
660a8e1175bSopenharmony_ci}
661a8e1175bSopenharmony_ci
662a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_cipher_decrypt(
663a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
664a8e1175bSopenharmony_ci    const uint8_t *key_buffer,
665a8e1175bSopenharmony_ci    size_t key_buffer_size,
666a8e1175bSopenharmony_ci    psa_algorithm_t alg,
667a8e1175bSopenharmony_ci    const uint8_t *input,
668a8e1175bSopenharmony_ci    size_t input_length,
669a8e1175bSopenharmony_ci    uint8_t *output,
670a8e1175bSopenharmony_ci    size_t output_size,
671a8e1175bSopenharmony_ci    size_t *output_length)
672a8e1175bSopenharmony_ci{
673a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
674a8e1175bSopenharmony_ci    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
675a8e1175bSopenharmony_ci    size_t olength, accumulated_length;
676a8e1175bSopenharmony_ci
677a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
678a8e1175bSopenharmony_ci                                              key_buffer, key_buffer_size,
679a8e1175bSopenharmony_ci                                              alg);
680a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
681a8e1175bSopenharmony_ci        goto exit;
682a8e1175bSopenharmony_ci    }
683a8e1175bSopenharmony_ci
684a8e1175bSopenharmony_ci    if (operation.iv_length > 0) {
685a8e1175bSopenharmony_ci        status = mbedtls_psa_cipher_set_iv(&operation,
686a8e1175bSopenharmony_ci                                           input, operation.iv_length);
687a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
688a8e1175bSopenharmony_ci            goto exit;
689a8e1175bSopenharmony_ci        }
690a8e1175bSopenharmony_ci    }
691a8e1175bSopenharmony_ci
692a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_update(
693a8e1175bSopenharmony_ci        &operation,
694a8e1175bSopenharmony_ci        mbedtls_buffer_offset_const(input, operation.iv_length),
695a8e1175bSopenharmony_ci        input_length - operation.iv_length,
696a8e1175bSopenharmony_ci        output, output_size, &olength);
697a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
698a8e1175bSopenharmony_ci        goto exit;
699a8e1175bSopenharmony_ci    }
700a8e1175bSopenharmony_ci
701a8e1175bSopenharmony_ci    accumulated_length = olength;
702a8e1175bSopenharmony_ci
703a8e1175bSopenharmony_ci    status = mbedtls_psa_cipher_finish(
704a8e1175bSopenharmony_ci        &operation,
705a8e1175bSopenharmony_ci        mbedtls_buffer_offset(output, accumulated_length),
706a8e1175bSopenharmony_ci        output_size - accumulated_length, &olength);
707a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
708a8e1175bSopenharmony_ci        goto exit;
709a8e1175bSopenharmony_ci    }
710a8e1175bSopenharmony_ci
711a8e1175bSopenharmony_ci    *output_length = accumulated_length + olength;
712a8e1175bSopenharmony_ci
713a8e1175bSopenharmony_ciexit:
714a8e1175bSopenharmony_ci    if (status == PSA_SUCCESS) {
715a8e1175bSopenharmony_ci        status = mbedtls_psa_cipher_abort(&operation);
716a8e1175bSopenharmony_ci    } else {
717a8e1175bSopenharmony_ci        mbedtls_psa_cipher_abort(&operation);
718a8e1175bSopenharmony_ci    }
719a8e1175bSopenharmony_ci
720a8e1175bSopenharmony_ci    return status;
721a8e1175bSopenharmony_ci}
722a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
723a8e1175bSopenharmony_ci
724a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_CRYPTO_C */
725