blob: f0bb3aa55007cca02758fed06869191ab9b6e295 [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"
16
Ronald Crond6d28882020-12-14 14:56:02 +010017#include "mbedtls/cipher.h"
Ronald Cron6d051732020-10-01 14:10:20 +020018#include "mbedtls/error.h"
Ronald Cron0ff57952021-03-08 16:46:35 +010019
Ronald Crond6d28882020-12-14 14:56:02 +010020#include <string.h>
21
Valerio Setti1e21f262023-10-20 16:24:07 +020022/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
23 * are enabled, but it does not provide any compatibility check between them
24 * (i.e. if the specified key works with the specified algorithm). This helper
25 * function is meant to provide this support.
26 * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
27 * requires CIPHER_C to be enabled.
28 */
29static psa_status_t mbedtls_cipher_validate_values(
30 psa_algorithm_t alg,
31 psa_key_type_t key_type)
32{
33 switch (alg) {
34 case PSA_ALG_STREAM_CIPHER:
35 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
36 if (key_type != PSA_KEY_TYPE_CHACHA20) {
37 return PSA_ERROR_NOT_SUPPORTED;
38 }
39 break;
40
41 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
42 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
43 case PSA_ALG_CCM_STAR_NO_TAG:
44 if ((key_type != PSA_KEY_TYPE_AES) &&
45 (key_type != PSA_KEY_TYPE_ARIA) &&
46 (key_type != PSA_KEY_TYPE_CAMELLIA)) {
47 return PSA_ERROR_NOT_SUPPORTED;
48 }
49 break;
50
51 case PSA_ALG_CTR:
52 case PSA_ALG_CFB:
53 case PSA_ALG_OFB:
54 case PSA_ALG_XTS:
55 case PSA_ALG_ECB_NO_PADDING:
56 case PSA_ALG_CBC_NO_PADDING:
57 case PSA_ALG_CBC_PKCS7:
58 case PSA_ALG_CMAC:
59 if ((key_type != PSA_KEY_TYPE_AES) &&
60 (key_type != PSA_KEY_TYPE_ARIA) &&
61 (key_type != PSA_KEY_TYPE_DES) &&
62 (key_type != PSA_KEY_TYPE_CAMELLIA)) {
63 return PSA_ERROR_NOT_SUPPORTED;
64 }
65 break;
66
67 default:
68 return PSA_ERROR_NOT_SUPPORTED;
69 }
70
71 return PSA_SUCCESS;
72}
73
Valerio Setti4a249822023-10-18 12:34:54 +020074psa_status_t mbedtls_cipher_values_from_psa(
Ronald Cron75e6ae22021-03-17 14:46:05 +010075 psa_algorithm_t alg,
76 psa_key_type_t key_type,
Valerio Setti4a249822023-10-18 12:34:54 +020077 size_t *key_bits,
78 mbedtls_cipher_mode_t *mode,
Gilles Peskine449bd832023-01-11 14:50:10 +010079 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010080{
Ronald Cron75e6ae22021-03-17 14:46:05 +010081 mbedtls_cipher_id_t cipher_id_tmp;
Valerio Setti36fe8b92023-10-23 14:12:23 +020082 /* Only DES modifies key_bits */
83#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Valerio Setti4a249822023-10-18 12:34:54 +020084 (void) key_bits;
Valerio Setti36fe8b92023-10-23 14:12:23 +020085#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +010086
Gilles Peskine449bd832023-01-11 14:50:10 +010087 if (PSA_ALG_IS_AEAD(alg)) {
88 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
89 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010090
Gilles Peskine449bd832023-01-11 14:50:10 +010091 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
92 switch (alg) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +010093#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +010094 case PSA_ALG_STREAM_CIPHER:
Valerio Setti4a249822023-10-18 12:34:54 +020095 *mode = MBEDTLS_MODE_STREAM;
Ronald Cron75e6ae22021-03-17 14:46:05 +010096 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010097#endif
98#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +010099 case PSA_ALG_CTR:
Valerio Setti4a249822023-10-18 12:34:54 +0200100 *mode = MBEDTLS_MODE_CTR;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100101 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100102#endif
103#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100104 case PSA_ALG_CFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200105 *mode = MBEDTLS_MODE_CFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100106 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100107#endif
108#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100109 case PSA_ALG_OFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200110 *mode = MBEDTLS_MODE_OFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100111 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100112#endif
113#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100114 case PSA_ALG_ECB_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200115 *mode = MBEDTLS_MODE_ECB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100116 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100117#endif
118#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100119 case PSA_ALG_CBC_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200120 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100121 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100122#endif
123#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100124 case PSA_ALG_CBC_PKCS7:
Valerio Setti4a249822023-10-18 12:34:54 +0200125 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100126 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100127#endif
128#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200129 case PSA_ALG_CCM_STAR_NO_TAG:
Valerio Setti4a249822023-10-18 12:34:54 +0200130 *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200131 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100132#endif
133#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200135 *mode = MBEDTLS_MODE_CCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100136 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100137#endif
138#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200140 *mode = MBEDTLS_MODE_GCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100141 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100142#endif
143#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200145 *mode = MBEDTLS_MODE_CHACHAPOLY;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100146 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100147#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100148 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200149 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100150 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 } else if (alg == PSA_ALG_CMAC) {
Valerio Setti4a249822023-10-18 12:34:54 +0200152 *mode = MBEDTLS_MODE_ECB;
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 } else {
Valerio Setti4a249822023-10-18 12:34:54 +0200154 return PSA_ERROR_NOT_SUPPORTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 switch (key_type) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100158#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100159 case PSA_KEY_TYPE_AES:
160 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
161 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100162#endif
163#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine6c12a1e2021-09-21 11:59:39 +0200164 case PSA_KEY_TYPE_ARIA:
165 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
166 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100167#endif
168#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100169 case PSA_KEY_TYPE_DES:
170 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
171 * and 192 for three-key Triple-DES. */
Valerio Setti4a249822023-10-18 12:34:54 +0200172 if (*key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100173 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100175 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100177 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
178 * but two-key Triple-DES is functionally three-key Triple-DES
179 * with K1=K3, so that's how we present it to mbedtls. */
Valerio Setti4a249822023-10-18 12:34:54 +0200180 if (*key_bits == 128) {
181 *key_bits = 192;
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100183 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100184#endif
185#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100186 case PSA_KEY_TYPE_CAMELLIA:
187 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
188 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100189#endif
190#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100191 case PSA_KEY_TYPE_CHACHA20:
192 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
193 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100194#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100195 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200196 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100197 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100199 *cipher_id = cipher_id_tmp;
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100201
Valerio Setti1e21f262023-10-20 16:24:07 +0200202 return mbedtls_cipher_validate_values(alg, key_type);
Valerio Setti4a249822023-10-18 12:34:54 +0200203}
204
205#if defined(MBEDTLS_CIPHER_C)
206const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
207 psa_algorithm_t alg,
208 psa_key_type_t key_type,
209 size_t key_bits,
210 mbedtls_cipher_id_t *cipher_id)
211{
212 mbedtls_cipher_mode_t mode;
213 psa_status_t status;
214 mbedtls_cipher_id_t cipher_id_tmp;
215
216 status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
217 if (status != PSA_SUCCESS) {
218 return NULL;
219 }
220 if (cipher_id != NULL) {
221 *cipher_id = cipher_id_tmp;
222 }
223
224 return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100225}
Valerio Setti2c2aded2023-08-25 09:22:19 +0200226#endif /* MBEDTLS_CIPHER_C */
Ronald Cron75e6ae22021-03-17 14:46:05 +0100227
Ronald Cron0266cfe2021-03-13 18:50:11 +0100228#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100229
Ronald Cron0266cfe2021-03-13 18:50:11 +0100230static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100231 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100232 const psa_key_attributes_t *attributes,
233 const uint8_t *key_buffer, size_t key_buffer_size,
234 psa_algorithm_t alg,
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100236{
237 int ret = 0;
238 size_t key_bits;
239 const mbedtls_cipher_info_t *cipher_info = NULL;
240 psa_key_type_t key_type = attributes->core.type;
241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100243
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100245
Ronald Cron6e412a72021-03-10 09:58:47 +0100246 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100247 key_bits = attributes->core.bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
249 key_bits, NULL);
250 if (cipher_info == NULL) {
251 return PSA_ERROR_NOT_SUPPORTED;
252 }
Ronald Crond6d28882020-12-14 14:56:02 +0100253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
255 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100256 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 }
Ronald Crond6d28882020-12-14 14:56:02 +0100258
Ronald Cron0266cfe2021-03-13 18:50:11 +0100259#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100261 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
262 uint8_t keys[24];
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 memcpy(keys, key_buffer, 16);
264 memcpy(keys + 16, key_buffer, 8);
265 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
266 keys,
267 192, cipher_operation);
268 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100269#endif
270 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
272 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100273 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100275 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 }
Ronald Crond6d28882020-12-14 14:56:02 +0100277
Ronald Cron0266cfe2021-03-13 18:50:11 +0100278#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
279 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100281 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
283 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100284 break;
285 case PSA_ALG_CBC_PKCS7:
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
287 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100288 break;
289 default:
290 /* The algorithm doesn't involve padding. */
291 ret = 0;
292 break;
293 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100295 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100297#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
298 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
301 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
302 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100303
304exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100306}
307
Ronald Cron0266cfe2021-03-13 18:50:11 +0100308psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100309 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100310 const psa_key_attributes_t *attributes,
311 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100313{
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 return psa_cipher_setup(operation, attributes,
315 key_buffer, key_buffer_size,
316 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100317}
318
Ronald Cron0266cfe2021-03-13 18:50:11 +0100319psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100320 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100321 const psa_key_attributes_t *attributes,
322 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100324{
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 return psa_cipher_setup(operation, attributes,
326 key_buffer, key_buffer_size,
327 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100328}
Ronald Cron6d051732020-10-01 14:10:20 +0200329
Ronald Cron0266cfe2021-03-13 18:50:11 +0100330psa_status_t mbedtls_psa_cipher_set_iv(
331 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100333{
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (iv_length != operation->iv_length) {
335 return PSA_ERROR_INVALID_ARGUMENT;
336 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100337
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 return mbedtls_to_psa_error(
339 mbedtls_cipher_set_iv(&operation->ctx.cipher,
340 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100341}
342
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100343#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine55dffe52021-09-13 09:33:28 +0200344/** Process input for which the algorithm is set to ECB mode.
345 *
346 * This requires manual processing, since the PSA API is defined as being
347 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
348 * but the underlying mbedtls_cipher_update only takes full blocks.
349 *
350 * \param ctx The mbedtls cipher context to use. It must have been
351 * set up for ECB.
352 * \param[in] input The input plaintext or ciphertext to process.
353 * \param input_length The number of bytes to process from \p input.
354 * This does not need to be aligned to a block boundary.
355 * If there is a partial block at the end of the input,
356 * it is stored in \p ctx for future processing.
Gilles Peskined87d8732021-09-13 12:20:51 +0200357 * \param output The buffer where the output is written. It must be
358 * at least `BS * floor((p + input_length) / BS)` bytes
359 * long, where `p` is the number of bytes in the
360 * unprocessed partial block in \p ctx (with
361 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine55dffe52021-09-13 09:33:28 +0200362 * \param output_length On success, the number of bytes written to \p output.
363 * \c 0 on error.
364 *
365 * \return #PSA_SUCCESS or an error from a hardware accelerator
366 */
Ronald Cron6d051732020-10-01 14:10:20 +0200367static psa_status_t psa_cipher_update_ecb(
368 mbedtls_cipher_context_t *ctx,
369 const uint8_t *input,
370 size_t input_length,
371 uint8_t *output,
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200373{
374 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Dave Rodgman85a88132023-06-24 11:41:50 +0100375 size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Ronald Cron6d051732020-10-01 14:10:20 +0200376 size_t internal_output_length = 0;
377 *output_length = 0;
378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200380 status = PSA_SUCCESS;
381 goto exit;
382 }
383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200385 /* Fill up to block size, and run the block if there's a full one. */
386 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200389 bytes_to_copy = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 }
Ronald Cron6d051732020-10-01 14:10:20 +0200391
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
393 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200394 input_length -= bytes_to_copy;
395 input += bytes_to_copy;
396 ctx->unprocessed_len += bytes_to_copy;
397
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200399 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 mbedtls_cipher_update(ctx,
401 ctx->unprocessed_data,
402 block_size,
403 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200406 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 }
Ronald Cron6d051732020-10-01 14:10:20 +0200408
409 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200410 *output_length += internal_output_length;
411 ctx->unprocessed_len = 0;
412 }
413 }
414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200416 /* Run all full blocks we have, one by one */
417 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 mbedtls_cipher_update(ctx, input,
419 block_size,
420 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200423 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 }
Ronald Cron6d051732020-10-01 14:10:20 +0200425
426 input_length -= block_size;
427 input += block_size;
428
429 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200430 *output_length += internal_output_length;
431 }
432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200434 /* Save unprocessed bytes for later processing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
436 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200437 ctx->unprocessed_len += input_length;
438 }
439
440 status = PSA_SUCCESS;
441
442exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200444}
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100445#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200446
Ronald Cron0266cfe2021-03-13 18:50:11 +0100447psa_status_t mbedtls_psa_cipher_update(
448 mbedtls_psa_cipher_operation_t *operation,
449 const uint8_t *input, size_t input_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200451{
452 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
453 size_t expected_output_size;
454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200456 /* Take the unprocessed partial block left over from previous
457 * update calls, if any, plus the input to this call. Remove
458 * the last partial block, if any. You get the data that will be
459 * output in this call. */
460 expected_output_size =
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100462 / operation->block_length * operation->block_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200464 expected_output_size = input_length;
465 }
466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 if (output_size < expected_output_size) {
468 return PSA_ERROR_BUFFER_TOO_SMALL;
469 }
Ronald Cron6d051732020-10-01 14:10:20 +0200470
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100471#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200473 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 * process a single block at a time in ECB mode. Abstract away that
475 * inconsistency here to match the PSA API behaviour. */
476 status = psa_cipher_update_ecb(&operation->ctx.cipher,
477 input,
478 input_length,
479 output,
480 output_length);
481 } else
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100482#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200483 {
484 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 mbedtls_cipher_update(&operation->ctx.cipher, input,
486 input_length, output, output_length));
gabor-mezei-arm58c17272021-06-29 16:41:25 +0200487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 if (*output_length > output_size) {
489 return PSA_ERROR_CORRUPTION_DETECTED;
490 }
Ronald Cron6d051732020-10-01 14:10:20 +0200491 }
492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200494}
495
Ronald Cron0266cfe2021-03-13 18:50:11 +0100496psa_status_t mbedtls_psa_cipher_finish(
497 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200499{
500 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
501 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 if (operation->ctx.cipher.unprocessed_len != 0) {
504 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
505 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200506 status = PSA_ERROR_INVALID_ARGUMENT;
507 goto exit;
508 }
509 }
510
511 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 mbedtls_cipher_finish(&operation->ctx.cipher,
513 temp_output_buffer,
514 output_length));
515 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200516 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 }
Ronald Cron6d051732020-10-01 14:10:20 +0200518
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200520 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 } else if (output_size >= *output_length) {
522 memcpy(output, temp_output_buffer, *output_length);
523 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200524 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 }
Ronald Cron6d051732020-10-01 14:10:20 +0200526
527exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 mbedtls_platform_zeroize(temp_output_buffer,
529 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200530
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200532}
533
Ronald Cron0266cfe2021-03-13 18:50:11 +0100534psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200536{
Ronald Cron937dfee2021-03-10 09:17:32 +0100537 /* Sanity check (shouldn't happen: operation->alg should
538 * always have been initialized to a valid value). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
540 return PSA_ERROR_BAD_STATE;
541 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100542
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200546}
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100547
Ronald Cron0266cfe2021-03-13 18:50:11 +0100548psa_status_t mbedtls_psa_cipher_encrypt(
549 const psa_key_attributes_t *attributes,
550 const uint8_t *key_buffer,
551 size_t key_buffer_size,
552 psa_algorithm_t alg,
Ronald Cron9b674282021-07-09 09:19:35 +0200553 const uint8_t *iv,
554 size_t iv_length,
Ronald Cron0266cfe2021-03-13 18:50:11 +0100555 const uint8_t *input,
556 size_t input_length,
557 uint8_t *output,
558 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100559 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100560{
561 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
562 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Cron8188d192021-12-14 10:58:18 +0100563 size_t update_output_length, finish_output_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
566 key_buffer, key_buffer_size,
567 alg);
568 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100569 goto exit;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100570 }
571
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 if (iv_length > 0) {
573 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
574 if (status != PSA_SUCCESS) {
575 goto exit;
576 }
577 }
578
579 status = mbedtls_psa_cipher_update(&operation, input, input_length,
580 output, output_size,
581 &update_output_length);
582 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100583 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100585
Gilles Peskine42649d92022-11-23 14:15:57 +0100586 status = mbedtls_psa_cipher_finish(
587 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 mbedtls_buffer_offset(output, update_output_length),
589 output_size - update_output_length, &finish_output_length);
590 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100591 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100593
Ronald Cron8188d192021-12-14 10:58:18 +0100594 *output_length = update_output_length + finish_output_length;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200595
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100596exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 if (status == PSA_SUCCESS) {
598 status = mbedtls_psa_cipher_abort(&operation);
599 } else {
600 mbedtls_psa_cipher_abort(&operation);
601 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100604}
605
Ronald Cron0266cfe2021-03-13 18:50:11 +0100606psa_status_t mbedtls_psa_cipher_decrypt(
607 const psa_key_attributes_t *attributes,
608 const uint8_t *key_buffer,
609 size_t key_buffer_size,
610 psa_algorithm_t alg,
611 const uint8_t *input,
612 size_t input_length,
613 uint8_t *output,
614 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100616{
617 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
618 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200619 size_t olength, accumulated_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100620
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
622 key_buffer, key_buffer_size,
623 alg);
624 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100625 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100627
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 if (operation.iv_length > 0) {
629 status = mbedtls_psa_cipher_set_iv(&operation,
630 input, operation.iv_length);
631 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100632 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100634 }
635
Gilles Peskine42649d92022-11-23 14:15:57 +0100636 status = mbedtls_psa_cipher_update(
637 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine42649d92022-11-23 14:15:57 +0100639 input_length - operation.iv_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 output, output_size, &olength);
641 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100642 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100644
gabor-mezei-arm6158e282021-06-29 16:42:13 +0200645 accumulated_length = olength;
gabor-mezei-arm258ae072021-06-25 15:25:38 +0200646
Gilles Peskine42649d92022-11-23 14:15:57 +0100647 status = mbedtls_psa_cipher_finish(
648 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 mbedtls_buffer_offset(output, accumulated_length),
650 output_size - accumulated_length, &olength);
651 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100652 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100654
gabor-mezei-arm00e54f12021-06-29 19:06:30 +0200655 *output_length = accumulated_length + olength;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200656
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100657exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 if (status == PSA_SUCCESS) {
659 status = mbedtls_psa_cipher_abort(&operation);
660 } else {
661 mbedtls_psa_cipher_abort(&operation);
662 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100663
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100665}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100666#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100667
Ronald Cron0ff57952021-03-08 16:46:35 +0100668#endif /* MBEDTLS_PSA_CRYPTO_C */