blob: 83069c78522041a54c2c52ab64efc840848bdabf [file] [log] [blame]
Ronald Cron0ff57952021-03-08 16:46:35 +01001/*
2 * PSA cipher driver entry points
3 */
4/*
5 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Ronald Cron0ff57952021-03-08 16:46:35 +01007 */
8
9#include "common.h"
10
11#if defined(MBEDTLS_PSA_CRYPTO_C)
12
Martin Man4741e0b2022-08-02 12:44:35 +020013#include "psa_crypto_cipher.h"
Ronald Crond6d28882020-12-14 14:56:02 +010014#include "psa_crypto_core.h"
Ronald Cron6d051732020-10-01 14:10:20 +020015#include "psa_crypto_random_impl.h"
Gilles Peskinee74b4282025-07-27 21:29:40 +020016#include "constant_time_internal.h"
Ronald Cron6d051732020-10-01 14:10:20 +020017
Ronald Crond6d28882020-12-14 14:56:02 +010018#include "mbedtls/cipher.h"
Ronald Cron6d051732020-10-01 14:10:20 +020019#include "mbedtls/error.h"
Ronald Cron0ff57952021-03-08 16:46:35 +010020
Ronald Crond6d28882020-12-14 14:56:02 +010021#include <string.h>
22
Valerio Setti1e21f262023-10-20 16:24:07 +020023/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
24 * are enabled, but it does not provide any compatibility check between them
25 * (i.e. if the specified key works with the specified algorithm). This helper
26 * function is meant to provide this support.
27 * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
28 * requires CIPHER_C to be enabled.
29 */
30static psa_status_t mbedtls_cipher_validate_values(
31 psa_algorithm_t alg,
32 psa_key_type_t key_type)
33{
Dave Rodgman3e5cc172023-10-31 17:54:58 +000034 /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
35 eliminate bits of the logic below. */
36#if !defined(PSA_WANT_KEY_TYPE_AES)
37 MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
38#endif
39#if !defined(PSA_WANT_KEY_TYPE_ARIA)
40 MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
41#endif
42#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
43 MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
44#endif
45#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
46 MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
47#endif
48#if !defined(PSA_WANT_KEY_TYPE_DES)
49 MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
50#endif
51#if !defined(PSA_WANT_ALG_CCM)
52 MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
53#endif
54#if !defined(PSA_WANT_ALG_GCM)
55 MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
56#endif
57#if !defined(PSA_WANT_ALG_STREAM_CIPHER)
58 MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
59#endif
60#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
61 MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
62#endif
63#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
64 MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
65#endif
66#if !defined(PSA_WANT_ALG_CTR)
67 MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
68#endif
69#if !defined(PSA_WANT_ALG_CFB)
70 MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
71#endif
72#if !defined(PSA_WANT_ALG_OFB)
73 MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
74#endif
Dave Rodgman3e5cc172023-10-31 17:54:58 +000075#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
76 MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
77#endif
78#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
79 MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
80#endif
81#if !defined(PSA_WANT_ALG_CBC_PKCS7)
82 MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
83#endif
84#if !defined(PSA_WANT_ALG_CMAC)
85 MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
86#endif
Valerio Setti1e21f262023-10-20 16:24:07 +020087
Dave Rodgman6d2c1b32023-10-31 17:54:42 +000088 if (alg == PSA_ALG_STREAM_CIPHER ||
89 alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
90 if (key_type == PSA_KEY_TYPE_CHACHA20) {
91 return PSA_SUCCESS;
92 }
Valerio Setti1e21f262023-10-20 16:24:07 +020093 }
94
Dave Rodgman6d2c1b32023-10-31 17:54:42 +000095 if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
96 alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
97 alg == PSA_ALG_CCM_STAR_NO_TAG) {
98 if (key_type == PSA_KEY_TYPE_AES ||
99 key_type == PSA_KEY_TYPE_ARIA ||
100 key_type == PSA_KEY_TYPE_CAMELLIA) {
101 return PSA_SUCCESS;
102 }
103 }
104
105 if (alg == PSA_ALG_CTR ||
106 alg == PSA_ALG_CFB ||
107 alg == PSA_ALG_OFB ||
108 alg == PSA_ALG_XTS ||
109 alg == PSA_ALG_ECB_NO_PADDING ||
110 alg == PSA_ALG_CBC_NO_PADDING ||
111 alg == PSA_ALG_CBC_PKCS7 ||
112 alg == PSA_ALG_CMAC) {
113 if (key_type == PSA_KEY_TYPE_AES ||
114 key_type == PSA_KEY_TYPE_ARIA ||
115 key_type == PSA_KEY_TYPE_DES ||
116 key_type == PSA_KEY_TYPE_CAMELLIA) {
117 return PSA_SUCCESS;
118 }
119 }
120
121 return PSA_ERROR_NOT_SUPPORTED;
Valerio Setti1e21f262023-10-20 16:24:07 +0200122}
123
Valerio Setti4a249822023-10-18 12:34:54 +0200124psa_status_t mbedtls_cipher_values_from_psa(
Ronald Cron75e6ae22021-03-17 14:46:05 +0100125 psa_algorithm_t alg,
126 psa_key_type_t key_type,
Valerio Setti4a249822023-10-18 12:34:54 +0200127 size_t *key_bits,
128 mbedtls_cipher_mode_t *mode,
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100130{
Ronald Cron75e6ae22021-03-17 14:46:05 +0100131 mbedtls_cipher_id_t cipher_id_tmp;
Valerio Setti36fe8b92023-10-23 14:12:23 +0200132 /* Only DES modifies key_bits */
133#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Valerio Setti4a249822023-10-18 12:34:54 +0200134 (void) key_bits;
Valerio Setti36fe8b92023-10-23 14:12:23 +0200135#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 if (PSA_ALG_IS_AEAD(alg)) {
138 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
139 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
142 switch (alg) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100143#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100144 case PSA_ALG_STREAM_CIPHER:
Valerio Setti4a249822023-10-18 12:34:54 +0200145 *mode = MBEDTLS_MODE_STREAM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100146 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100147#endif
148#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100149 case PSA_ALG_CTR:
Valerio Setti4a249822023-10-18 12:34:54 +0200150 *mode = MBEDTLS_MODE_CTR;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100151 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100152#endif
153#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100154 case PSA_ALG_CFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200155 *mode = MBEDTLS_MODE_CFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100156 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100157#endif
158#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100159 case PSA_ALG_OFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200160 *mode = MBEDTLS_MODE_OFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100161 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100162#endif
163#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100164 case PSA_ALG_ECB_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200165 *mode = MBEDTLS_MODE_ECB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100166 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100167#endif
168#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100169 case PSA_ALG_CBC_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200170 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100171 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100172#endif
173#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100174 case PSA_ALG_CBC_PKCS7:
Valerio Setti4a249822023-10-18 12:34:54 +0200175 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100176 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100177#endif
178#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200179 case PSA_ALG_CCM_STAR_NO_TAG:
Valerio Setti4a249822023-10-18 12:34:54 +0200180 *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200181 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100182#endif
183#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200185 *mode = MBEDTLS_MODE_CCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100186 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100187#endif
188#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200190 *mode = MBEDTLS_MODE_GCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100191 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100192#endif
193#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200195 *mode = MBEDTLS_MODE_CHACHAPOLY;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100196 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100197#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100198 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200199 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100200 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 } else if (alg == PSA_ALG_CMAC) {
Valerio Setti4a249822023-10-18 12:34:54 +0200202 *mode = MBEDTLS_MODE_ECB;
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 } else {
Valerio Setti4a249822023-10-18 12:34:54 +0200204 return PSA_ERROR_NOT_SUPPORTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 switch (key_type) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100208#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100209 case PSA_KEY_TYPE_AES:
210 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
211 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100212#endif
213#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine6c12a1e2021-09-21 11:59:39 +0200214 case PSA_KEY_TYPE_ARIA:
215 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
216 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100217#endif
218#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100219 case PSA_KEY_TYPE_DES:
220 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
221 * and 192 for three-key Triple-DES. */
Valerio Setti4a249822023-10-18 12:34:54 +0200222 if (*key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100223 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100225 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100227 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
228 * but two-key Triple-DES is functionally three-key Triple-DES
229 * with K1=K3, so that's how we present it to mbedtls. */
Valerio Setti4a249822023-10-18 12:34:54 +0200230 if (*key_bits == 128) {
231 *key_bits = 192;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100233 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100234#endif
235#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100236 case PSA_KEY_TYPE_CAMELLIA:
237 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
238 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100239#endif
240#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100241 case PSA_KEY_TYPE_CHACHA20:
242 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
243 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100244#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100245 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200246 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100247 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100249 *cipher_id = cipher_id_tmp;
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100251
Valerio Setti1e21f262023-10-20 16:24:07 +0200252 return mbedtls_cipher_validate_values(alg, key_type);
Valerio Setti4a249822023-10-18 12:34:54 +0200253}
254
255#if defined(MBEDTLS_CIPHER_C)
256const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
257 psa_algorithm_t alg,
258 psa_key_type_t key_type,
259 size_t key_bits,
260 mbedtls_cipher_id_t *cipher_id)
261{
262 mbedtls_cipher_mode_t mode;
263 psa_status_t status;
Patrick Wildt38bc9602024-05-15 18:22:17 +0000264 mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;
Valerio Setti4a249822023-10-18 12:34:54 +0200265
266 status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
267 if (status != PSA_SUCCESS) {
268 return NULL;
269 }
270 if (cipher_id != NULL) {
271 *cipher_id = cipher_id_tmp;
272 }
273
274 return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100275}
Valerio Setti2c2aded2023-08-25 09:22:19 +0200276#endif /* MBEDTLS_CIPHER_C */
Ronald Cron75e6ae22021-03-17 14:46:05 +0100277
Ronald Cron0266cfe2021-03-13 18:50:11 +0100278#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100279
Ronald Cron0266cfe2021-03-13 18:50:11 +0100280static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100281 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100282 const psa_key_attributes_t *attributes,
283 const uint8_t *key_buffer, size_t key_buffer_size,
284 psa_algorithm_t alg,
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100286{
287 int ret = 0;
288 size_t key_bits;
289 const mbedtls_cipher_info_t *cipher_info = NULL;
Gilles Peskine2f107ae2024-02-28 01:26:46 +0100290 psa_key_type_t key_type = attributes->type;
Ronald Crond6d28882020-12-14 14:56:02 +0100291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100295
Ronald Cron6e412a72021-03-10 09:58:47 +0100296 operation->alg = alg;
Gilles Peskine2f107ae2024-02-28 01:26:46 +0100297 key_bits = attributes->bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
299 key_bits, NULL);
300 if (cipher_info == NULL) {
301 return PSA_ERROR_NOT_SUPPORTED;
302 }
Ronald Crond6d28882020-12-14 14:56:02 +0100303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
305 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100306 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 }
Ronald Crond6d28882020-12-14 14:56:02 +0100308
Ronald Cron0266cfe2021-03-13 18:50:11 +0100309#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100311 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
312 uint8_t keys[24];
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 memcpy(keys, key_buffer, 16);
314 memcpy(keys + 16, key_buffer, 8);
315 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
316 keys,
317 192, cipher_operation);
318 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100319#endif
320 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
322 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100323 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100325 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 }
Ronald Crond6d28882020-12-14 14:56:02 +0100327
Ronald Cron0266cfe2021-03-13 18:50:11 +0100328#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
329 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100331 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
333 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100334 break;
335 case PSA_ALG_CBC_PKCS7:
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
337 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100338 break;
339 default:
340 /* The algorithm doesn't involve padding. */
341 ret = 0;
342 break;
343 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100345 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100347#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
348 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
351 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
352 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100353
354exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100356}
357
Ronald Cron0266cfe2021-03-13 18:50:11 +0100358psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100359 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100360 const psa_key_attributes_t *attributes,
361 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100363{
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 return psa_cipher_setup(operation, attributes,
365 key_buffer, key_buffer_size,
366 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100367}
368
Ronald Cron0266cfe2021-03-13 18:50:11 +0100369psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100370 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100371 const psa_key_attributes_t *attributes,
372 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100374{
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 return psa_cipher_setup(operation, attributes,
376 key_buffer, key_buffer_size,
377 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100378}
Ronald Cron6d051732020-10-01 14:10:20 +0200379
Ronald Cron0266cfe2021-03-13 18:50:11 +0100380psa_status_t mbedtls_psa_cipher_set_iv(
381 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100383{
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (iv_length != operation->iv_length) {
385 return PSA_ERROR_INVALID_ARGUMENT;
386 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 return mbedtls_to_psa_error(
389 mbedtls_cipher_set_iv(&operation->ctx.cipher,
390 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100391}
392
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100393#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine55dffe52021-09-13 09:33:28 +0200394/** Process input for which the algorithm is set to ECB mode.
395 *
396 * This requires manual processing, since the PSA API is defined as being
397 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
398 * but the underlying mbedtls_cipher_update only takes full blocks.
399 *
400 * \param ctx The mbedtls cipher context to use. It must have been
401 * set up for ECB.
402 * \param[in] input The input plaintext or ciphertext to process.
403 * \param input_length The number of bytes to process from \p input.
404 * This does not need to be aligned to a block boundary.
405 * If there is a partial block at the end of the input,
406 * it is stored in \p ctx for future processing.
Gilles Peskined87d8732021-09-13 12:20:51 +0200407 * \param output The buffer where the output is written. It must be
408 * at least `BS * floor((p + input_length) / BS)` bytes
409 * long, where `p` is the number of bytes in the
410 * unprocessed partial block in \p ctx (with
411 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine55dffe52021-09-13 09:33:28 +0200412 * \param output_length On success, the number of bytes written to \p output.
413 * \c 0 on error.
414 *
415 * \return #PSA_SUCCESS or an error from a hardware accelerator
416 */
Ronald Cron6d051732020-10-01 14:10:20 +0200417static psa_status_t psa_cipher_update_ecb(
418 mbedtls_cipher_context_t *ctx,
419 const uint8_t *input,
420 size_t input_length,
421 uint8_t *output,
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200423{
424 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Dave Rodgman85a88132023-06-24 11:41:50 +0100425 size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Ronald Cron6d051732020-10-01 14:10:20 +0200426 size_t internal_output_length = 0;
427 *output_length = 0;
428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200430 status = PSA_SUCCESS;
431 goto exit;
432 }
433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200435 /* Fill up to block size, and run the block if there's a full one. */
436 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200439 bytes_to_copy = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 }
Ronald Cron6d051732020-10-01 14:10:20 +0200441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
443 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200444 input_length -= bytes_to_copy;
445 input += bytes_to_copy;
446 ctx->unprocessed_len += bytes_to_copy;
447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200449 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 mbedtls_cipher_update(ctx,
451 ctx->unprocessed_data,
452 block_size,
453 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200456 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 }
Ronald Cron6d051732020-10-01 14:10:20 +0200458
459 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200460 *output_length += internal_output_length;
461 ctx->unprocessed_len = 0;
462 }
463 }
464
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200466 /* Run all full blocks we have, one by one */
467 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 mbedtls_cipher_update(ctx, input,
469 block_size,
470 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200471
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200473 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 }
Ronald Cron6d051732020-10-01 14:10:20 +0200475
476 input_length -= block_size;
477 input += block_size;
478
479 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200480 *output_length += internal_output_length;
481 }
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200484 /* Save unprocessed bytes for later processing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
486 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200487 ctx->unprocessed_len += input_length;
488 }
489
490 status = PSA_SUCCESS;
491
492exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200494}
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100495#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200496
Ronald Cron0266cfe2021-03-13 18:50:11 +0100497psa_status_t mbedtls_psa_cipher_update(
498 mbedtls_psa_cipher_operation_t *operation,
499 const uint8_t *input, size_t input_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200501{
502 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
503 size_t expected_output_size;
504
Gilles Peskine449bd832023-01-11 14:50:10 +0100505 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200506 /* Take the unprocessed partial block left over from previous
507 * update calls, if any, plus the input to this call. Remove
508 * the last partial block, if any. You get the data that will be
509 * output in this call. */
510 expected_output_size =
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100512 / operation->block_length * operation->block_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200514 expected_output_size = input_length;
515 }
516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if (output_size < expected_output_size) {
518 return PSA_ERROR_BUFFER_TOO_SMALL;
519 }
Ronald Cron6d051732020-10-01 14:10:20 +0200520
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100521#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200523 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 * process a single block at a time in ECB mode. Abstract away that
525 * inconsistency here to match the PSA API behaviour. */
526 status = psa_cipher_update_ecb(&operation->ctx.cipher,
527 input,
528 input_length,
529 output,
530 output_length);
531 } else
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100532#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Gabor Mezeic25fbd22024-01-29 13:33:58 +0100533 if (input_length == 0) {
534 /* There is no input, nothing to be done */
535 *output_length = 0;
536 status = PSA_SUCCESS;
537 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200538 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 mbedtls_cipher_update(&operation->ctx.cipher, input,
540 input_length, output, output_length));
gabor-mezei-arm58c17272021-06-29 16:41:25 +0200541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 if (*output_length > output_size) {
543 return PSA_ERROR_CORRUPTION_DETECTED;
544 }
Ronald Cron6d051732020-10-01 14:10:20 +0200545 }
546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200548}
549
Ronald Cron0266cfe2021-03-13 18:50:11 +0100550psa_status_t mbedtls_psa_cipher_finish(
551 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200553{
554 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
Gilles Peskined179dc82025-07-27 18:57:04 +0200555 size_t invalid_padding = 0;
Ronald Cron6d051732020-10-01 14:10:20 +0200556
Gilles Peskine3b380da2025-08-07 21:59:07 +0200557 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH] = { 0 };
558 if (output_size > sizeof(temp_output_buffer)) {
559 output_size = sizeof(temp_output_buffer);
560 }
561 /* We will copy output_size bytes from temp_output_buffer to the
562 * output buffer. We can't use *output_length to determine how
563 * much to copy because we must not leak that value through timing
564 * when doing decryption with unpadding. But the underlying function
565 * is not guaranteed to write beyond *output_length. To ensure we don't
566 * leak the former content of the stack to the caller, wipe that
567 * former content. */
568 memset(temp_output_buffer, 0, output_size);
569
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if (operation->ctx.cipher.unprocessed_len != 0) {
571 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
572 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200573 status = PSA_ERROR_INVALID_ARGUMENT;
574 goto exit;
575 }
576 }
577
578 status = mbedtls_to_psa_error(
Gilles Peskined179dc82025-07-27 18:57:04 +0200579 mbedtls_cipher_finish_padded(&operation->ctx.cipher,
580 temp_output_buffer,
581 output_length,
582 &invalid_padding));
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200584 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 }
Ronald Cron6d051732020-10-01 14:10:20 +0200586
Gilles Peskine3b380da2025-08-07 21:59:07 +0200587 if (output_size == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200588 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 } else {
Gilles Peskine3b380da2025-08-07 21:59:07 +0200590 /* Do not use the value of *output_length to determine how much
591 * to copy. When decrypting a padded cipher, the output length is
592 * sensitive, and leaking it could allow a padding oracle attack. */
593 memcpy(output, temp_output_buffer, output_size);
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 }
Ronald Cron6d051732020-10-01 14:10:20 +0200595
Gilles Peskine3b380da2025-08-07 21:59:07 +0200596 status = mbedtls_ct_error_if_else_0(invalid_padding,
597 PSA_ERROR_INVALID_PADDING);
598 mbedtls_ct_condition_t buffer_too_small =
599 mbedtls_ct_uint_lt(output_size, *output_length);
600 status = mbedtls_ct_error_if(buffer_too_small,
601 PSA_ERROR_BUFFER_TOO_SMALL,
602 status);
603
Ronald Cron6d051732020-10-01 14:10:20 +0200604exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 mbedtls_platform_zeroize(temp_output_buffer,
606 sizeof(temp_output_buffer));
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200608}
609
Ronald Cron0266cfe2021-03-13 18:50:11 +0100610psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200612{
Ronald Cron937dfee2021-03-10 09:17:32 +0100613 /* Sanity check (shouldn't happen: operation->alg should
614 * always have been initialized to a valid value). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
616 return PSA_ERROR_BAD_STATE;
617 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200620
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200622}
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100623
Ronald Cron0266cfe2021-03-13 18:50:11 +0100624psa_status_t mbedtls_psa_cipher_encrypt(
625 const psa_key_attributes_t *attributes,
626 const uint8_t *key_buffer,
627 size_t key_buffer_size,
628 psa_algorithm_t alg,
Ronald Cron9b674282021-07-09 09:19:35 +0200629 const uint8_t *iv,
630 size_t iv_length,
Ronald Cron0266cfe2021-03-13 18:50:11 +0100631 const uint8_t *input,
632 size_t input_length,
633 uint8_t *output,
634 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100636{
637 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
638 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Cron8188d192021-12-14 10:58:18 +0100639 size_t update_output_length, finish_output_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100640
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
642 key_buffer, key_buffer_size,
643 alg);
644 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100645 goto exit;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100646 }
647
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 if (iv_length > 0) {
649 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
650 if (status != PSA_SUCCESS) {
651 goto exit;
652 }
653 }
654
655 status = mbedtls_psa_cipher_update(&operation, input, input_length,
656 output, output_size,
657 &update_output_length);
658 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100659 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100661
Gilles Peskine42649d92022-11-23 14:15:57 +0100662 status = mbedtls_psa_cipher_finish(
663 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 mbedtls_buffer_offset(output, update_output_length),
665 output_size - update_output_length, &finish_output_length);
666 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100667 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100669
Ronald Cron8188d192021-12-14 10:58:18 +0100670 *output_length = update_output_length + finish_output_length;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200671
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100672exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 if (status == PSA_SUCCESS) {
674 status = mbedtls_psa_cipher_abort(&operation);
675 } else {
676 mbedtls_psa_cipher_abort(&operation);
677 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100680}
681
Ronald Cron0266cfe2021-03-13 18:50:11 +0100682psa_status_t mbedtls_psa_cipher_decrypt(
683 const psa_key_attributes_t *attributes,
684 const uint8_t *key_buffer,
685 size_t key_buffer_size,
686 psa_algorithm_t alg,
687 const uint8_t *input,
688 size_t input_length,
689 uint8_t *output,
690 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100691 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100692{
693 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
694 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200695 size_t olength, accumulated_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
698 key_buffer, key_buffer_size,
699 alg);
700 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100701 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100703
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 if (operation.iv_length > 0) {
705 status = mbedtls_psa_cipher_set_iv(&operation,
706 input, operation.iv_length);
707 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100708 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100710 }
711
Gilles Peskine42649d92022-11-23 14:15:57 +0100712 status = mbedtls_psa_cipher_update(
713 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine42649d92022-11-23 14:15:57 +0100715 input_length - operation.iv_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 output, output_size, &olength);
717 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100718 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100720
gabor-mezei-arm6158e282021-06-29 16:42:13 +0200721 accumulated_length = olength;
gabor-mezei-arm258ae072021-06-25 15:25:38 +0200722
Gilles Peskine42649d92022-11-23 14:15:57 +0100723 status = mbedtls_psa_cipher_finish(
724 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 mbedtls_buffer_offset(output, accumulated_length),
726 output_size - accumulated_length, &olength);
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100727
gabor-mezei-arm00e54f12021-06-29 19:06:30 +0200728 *output_length = accumulated_length + olength;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200729
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100730exit:
Gilles Peskine04dfd702025-08-07 22:27:26 +0200731 /* C99 doesn't allow a declaration to follow a label */;
732 psa_status_t abort_status = mbedtls_psa_cipher_abort(&operation);
733 /* Normally abort shouldn't fail unless the operation is in a bad
734 * state, in which case we'd expect finish to fail with the same error.
735 * So it doesn't matter much which call's error code we pick when both
736 * fail. However, in unauthenticated decryption specifically, the
737 * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is
738 * security-sensitive (risk of a padding oracle attack), so here we
739 * must not have a code path that depends on the value of status. */
740 if (abort_status != PSA_SUCCESS) {
741 status = abort_status;
Gilles Peskine449bd832023-01-11 14:50:10 +0100742 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100743
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100745}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100746#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100747
Ronald Cron0ff57952021-03-08 16:46:35 +0100748#endif /* MBEDTLS_PSA_CRYPTO_C */