blob: 93a6b93f1cba22fa5b4497457eaf3b4398435e44 [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 Rodgman7ff79652023-11-03 12:04:52 +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 Man43dedd82022-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
Ronald Cron75e6ae22021-03-17 14:46:05 +010022const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
23 psa_algorithm_t alg,
24 psa_key_type_t key_type,
25 size_t key_bits,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010026 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010027{
28 mbedtls_cipher_mode_t mode;
29 mbedtls_cipher_id_t cipher_id_tmp;
30
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010031 if (PSA_ALG_IS_AEAD(alg)) {
32 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
33 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010034
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010035 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
36 switch (alg) {
Gilles Peskine449e02e2022-03-16 12:25:17 +010037#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +010038 case PSA_ALG_STREAM_CIPHER:
39 mode = MBEDTLS_MODE_STREAM;
40 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010041#endif
42#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +010043 case PSA_ALG_CTR:
44 mode = MBEDTLS_MODE_CTR;
45 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010046#endif
47#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010048 case PSA_ALG_CFB:
49 mode = MBEDTLS_MODE_CFB;
50 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010051#endif
52#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010053 case PSA_ALG_OFB:
54 mode = MBEDTLS_MODE_OFB;
55 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010056#endif
57#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010058 case PSA_ALG_ECB_NO_PADDING:
59 mode = MBEDTLS_MODE_ECB;
60 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010061#endif
62#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010063 case PSA_ALG_CBC_NO_PADDING:
64 mode = MBEDTLS_MODE_CBC;
65 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010066#endif
67#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +010068 case PSA_ALG_CBC_PKCS7:
69 mode = MBEDTLS_MODE_CBC;
70 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010071#endif
72#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010073 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010074 mode = MBEDTLS_MODE_CCM;
75 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010076#endif
77#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010079 mode = MBEDTLS_MODE_GCM;
80 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010081#endif
82#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010083 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010084 mode = MBEDTLS_MODE_CHACHAPOLY;
85 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010086#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +010087 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +010089 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 } else if (alg == PSA_ALG_CMAC) {
Ronald Cron75e6ae22021-03-17 14:46:05 +010091 mode = MBEDTLS_MODE_ECB;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 } else {
93 return NULL;
94 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096 switch (key_type) {
Gilles Peskine449e02e2022-03-16 12:25:17 +010097#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +010098 case PSA_KEY_TYPE_AES:
99 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
100 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100101#endif
102#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine8890f642021-09-21 11:59:39 +0200103 case PSA_KEY_TYPE_ARIA:
104 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
105 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100106#endif
107#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100108 case PSA_KEY_TYPE_DES:
109 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
110 * and 192 for three-key Triple-DES. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 if (key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100112 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100113 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100114 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100116 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
117 * but two-key Triple-DES is functionally three-key Triple-DES
118 * with K1=K3, so that's how we present it to mbedtls. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100119 if (key_bits == 128) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100120 key_bits = 192;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100122 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100123#endif
124#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100125 case PSA_KEY_TYPE_CAMELLIA:
126 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
127 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100128#endif
129#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100130 case PSA_KEY_TYPE_ARC4:
131 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
132 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100133#endif
134#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100135 case PSA_KEY_TYPE_CHACHA20:
136 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
137 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100138#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100139 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100141 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100142 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100143 *cipher_id = cipher_id_tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100145
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 return mbedtls_cipher_info_from_values(cipher_id_tmp,
147 (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100148}
149
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100150#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100151
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100152static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100153 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100154 const psa_key_attributes_t *attributes,
155 const uint8_t *key_buffer, size_t key_buffer_size,
156 psa_algorithm_t alg,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100158{
159 int ret = 0;
160 size_t key_bits;
161 const mbedtls_cipher_info_t *cipher_info = NULL;
162 psa_key_type_t key_type = attributes->core.type;
163
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100164 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100167
Ronald Cron6e412a72021-03-10 09:58:47 +0100168 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100169 key_bits = attributes->core.bits;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100170 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
171 key_bits, NULL);
172 if (cipher_info == NULL) {
173 return PSA_ERROR_NOT_SUPPORTED;
174 }
Ronald Crond6d28882020-12-14 14:56:02 +0100175
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
177 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100178 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 }
Ronald Crond6d28882020-12-14 14:56:02 +0100180
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100181#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100183 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
184 uint8_t keys[24];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100185 memcpy(keys, key_buffer, 16);
186 memcpy(keys + 16, key_buffer, 8);
187 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
188 keys,
189 192, cipher_operation);
190 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100191#endif
192 {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
194 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100195 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100197 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100198 }
Ronald Crond6d28882020-12-14 14:56:02 +0100199
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100200#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
201 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100202 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100203 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
205 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100206 break;
207 case PSA_ALG_CBC_PKCS7:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
209 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100210 break;
211 default:
212 /* The algorithm doesn't involve padding. */
213 ret = 0;
214 break;
215 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100217 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100218 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100219#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
220 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100221
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
223 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
224 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100225
226exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100228}
229
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100230psa_status_t mbedtls_psa_cipher_encrypt_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,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100235{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236 return psa_cipher_setup(operation, attributes,
237 key_buffer, key_buffer_size,
238 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100239}
240
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100241psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100242 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100243 const psa_key_attributes_t *attributes,
244 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100246{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100247 return psa_cipher_setup(operation, attributes,
248 key_buffer, key_buffer_size,
249 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100250}
Ronald Cron6d051732020-10-01 14:10:20 +0200251
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100252psa_status_t mbedtls_psa_cipher_set_iv(
253 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100255{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100256 if (iv_length != operation->iv_length) {
257 return PSA_ERROR_INVALID_ARGUMENT;
258 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100259
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 return mbedtls_to_psa_error(
261 mbedtls_cipher_set_iv(&operation->ctx.cipher,
262 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100263}
264
Gilles Peskine449e02e2022-03-16 12:25:17 +0100265#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine7b1c9162021-09-13 09:33:28 +0200266/** Process input for which the algorithm is set to ECB mode.
267 *
268 * This requires manual processing, since the PSA API is defined as being
269 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
270 * but the underlying mbedtls_cipher_update only takes full blocks.
271 *
272 * \param ctx The mbedtls cipher context to use. It must have been
273 * set up for ECB.
274 * \param[in] input The input plaintext or ciphertext to process.
275 * \param input_length The number of bytes to process from \p input.
276 * This does not need to be aligned to a block boundary.
277 * If there is a partial block at the end of the input,
278 * it is stored in \p ctx for future processing.
Gilles Peskine03900162021-09-13 12:20:51 +0200279 * \param output The buffer where the output is written. It must be
280 * at least `BS * floor((p + input_length) / BS)` bytes
281 * long, where `p` is the number of bytes in the
282 * unprocessed partial block in \p ctx (with
283 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine7b1c9162021-09-13 09:33:28 +0200284 * \param output_length On success, the number of bytes written to \p output.
285 * \c 0 on error.
286 *
287 * \return #PSA_SUCCESS or an error from a hardware accelerator
288 */
Ronald Cron6d051732020-10-01 14:10:20 +0200289static psa_status_t psa_cipher_update_ecb(
290 mbedtls_cipher_context_t *ctx,
291 const uint8_t *input,
292 size_t input_length,
293 uint8_t *output,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100294 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200295{
296 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
297 size_t block_size = ctx->cipher_info->block_size;
298 size_t internal_output_length = 0;
299 *output_length = 0;
300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200302 status = PSA_SUCCESS;
303 goto exit;
304 }
305
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200307 /* Fill up to block size, and run the block if there's a full one. */
308 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
309
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100310 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200311 bytes_to_copy = input_length;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100312 }
Ronald Cron6d051732020-10-01 14:10:20 +0200313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
315 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200316 input_length -= bytes_to_copy;
317 input += bytes_to_copy;
318 ctx->unprocessed_len += bytes_to_copy;
319
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100320 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200321 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100322 mbedtls_cipher_update(ctx,
323 ctx->unprocessed_data,
324 block_size,
325 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200326
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200328 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100329 }
Ronald Cron6d051732020-10-01 14:10:20 +0200330
331 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200332 *output_length += internal_output_length;
333 ctx->unprocessed_len = 0;
334 }
335 }
336
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100337 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200338 /* Run all full blocks we have, one by one */
339 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100340 mbedtls_cipher_update(ctx, input,
341 block_size,
342 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200343
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200345 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100346 }
Ronald Cron6d051732020-10-01 14:10:20 +0200347
348 input_length -= block_size;
349 input += block_size;
350
351 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200352 *output_length += internal_output_length;
353 }
354
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200356 /* Save unprocessed bytes for later processing */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
358 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200359 ctx->unprocessed_len += input_length;
360 }
361
362 status = PSA_SUCCESS;
363
364exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200366}
Gilles Peskine449e02e2022-03-16 12:25:17 +0100367#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200368
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100369psa_status_t mbedtls_psa_cipher_update(
370 mbedtls_psa_cipher_operation_t *operation,
371 const uint8_t *input, size_t input_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200373{
374 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
375 size_t expected_output_size;
376
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200378 /* Take the unprocessed partial block left over from previous
379 * update calls, if any, plus the input to this call. Remove
380 * the last partial block, if any. You get the data that will be
381 * output in this call. */
382 expected_output_size =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100384 / operation->block_length * operation->block_length;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100385 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200386 expected_output_size = input_length;
387 }
388
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100389 if (output_size < expected_output_size) {
390 return PSA_ERROR_BUFFER_TOO_SMALL;
391 }
Ronald Cron6d051732020-10-01 14:10:20 +0200392
Gilles Peskine449e02e2022-03-16 12:25:17 +0100393#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200395 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100396 * process a single block at a time in ECB mode. Abstract away that
397 * inconsistency here to match the PSA API behaviour. */
398 status = psa_cipher_update_ecb(&operation->ctx.cipher,
399 input,
400 input_length,
401 output,
402 output_length);
403 } else
Gilles Peskine449e02e2022-03-16 12:25:17 +0100404#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Gabor Mezei92905be2024-01-29 13:33:58 +0100405 if (input_length == 0) {
406 /* There is no input, nothing to be done */
407 *output_length = 0;
408 status = PSA_SUCCESS;
409 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200410 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100411 mbedtls_cipher_update(&operation->ctx.cipher, input,
412 input_length, output, output_length));
gabor-mezei-arm42373bd2021-06-29 16:41:25 +0200413
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100414 if (*output_length > output_size) {
415 return PSA_ERROR_CORRUPTION_DETECTED;
416 }
Ronald Cron6d051732020-10-01 14:10:20 +0200417 }
418
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200420}
421
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100422psa_status_t mbedtls_psa_cipher_finish(
423 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100424 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200425{
426 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
427 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
428
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100429 if (operation->ctx.cipher.unprocessed_len != 0) {
430 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
431 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200432 status = PSA_ERROR_INVALID_ARGUMENT;
433 goto exit;
434 }
435 }
436
437 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100438 mbedtls_cipher_finish(&operation->ctx.cipher,
439 temp_output_buffer,
440 output_length));
441 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200442 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100443 }
Ronald Cron6d051732020-10-01 14:10:20 +0200444
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100445 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200446 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 } else if (output_size >= *output_length) {
448 memcpy(output, temp_output_buffer, *output_length);
449 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200450 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 }
Ronald Cron6d051732020-10-01 14:10:20 +0200452
453exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 mbedtls_platform_zeroize(temp_output_buffer,
455 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200458}
459
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100460psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200462{
Ronald Cron937dfee2021-03-10 09:17:32 +0100463 /* Sanity check (shouldn't happen: operation->alg should
464 * always have been initialized to a valid value). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
466 return PSA_ERROR_BAD_STATE;
467 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100468
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200470
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100471 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200472}
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100473
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100474psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,
475 const uint8_t *key_buffer,
476 size_t key_buffer_size,
477 psa_algorithm_t alg,
478 const uint8_t *iv,
479 size_t iv_length,
480 const uint8_t *input,
481 size_t input_length,
482 uint8_t *output,
483 size_t output_size,
484 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100485{
486 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
487 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Crona8331692021-07-09 09:19:35 +0200488 size_t update_output_length, finish_output_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100489
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100490 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
491 key_buffer, key_buffer_size,
492 alg);
493 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100494 goto exit;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100495 }
496
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100497 if (iv_length > 0) {
498 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
499 if (status != PSA_SUCCESS) {
500 goto exit;
501 }
502 }
503
504 status = mbedtls_psa_cipher_update(&operation, input, input_length,
505 output, output_size, &update_output_length);
506 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100507 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100508 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100509
Gilles Peskine01bf6312022-11-23 14:15:57 +0100510 status = mbedtls_psa_cipher_finish(
511 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100512 mbedtls_buffer_offset(output, update_output_length),
513 output_size - update_output_length, &finish_output_length);
514 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100515 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100517
Ronald Crona8331692021-07-09 09:19:35 +0200518 *output_length = update_output_length + finish_output_length;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200519
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100520exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100521 if (status == PSA_SUCCESS) {
522 status = mbedtls_psa_cipher_abort(&operation);
523 } else {
524 mbedtls_psa_cipher_abort(&operation);
525 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100526
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100527 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100528}
529
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100530psa_status_t mbedtls_psa_cipher_decrypt(
531 const psa_key_attributes_t *attributes,
532 const uint8_t *key_buffer,
533 size_t key_buffer_size,
534 psa_algorithm_t alg,
535 const uint8_t *input,
536 size_t input_length,
537 uint8_t *output,
538 size_t output_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100539 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100540{
541 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
542 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200543 size_t olength, accumulated_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100544
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100545 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
546 key_buffer, key_buffer_size,
547 alg);
548 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100549 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100550 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100551
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100552 if (operation.iv_length > 0) {
553 status = mbedtls_psa_cipher_set_iv(&operation,
554 input, operation.iv_length);
555 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100556 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100557 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100558 }
559
Gilles Peskine01bf6312022-11-23 14:15:57 +0100560 status = mbedtls_psa_cipher_update(
561 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100562 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine01bf6312022-11-23 14:15:57 +0100563 input_length - operation.iv_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100564 output, output_size, &olength);
565 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100566 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100567 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100568
gabor-mezei-arm809634d2021-06-29 16:42:13 +0200569 accumulated_length = olength;
gabor-mezei-arm3fd792d2021-06-25 15:25:38 +0200570
Gilles Peskine01bf6312022-11-23 14:15:57 +0100571 status = mbedtls_psa_cipher_finish(
572 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100573 mbedtls_buffer_offset(output, accumulated_length),
574 output_size - accumulated_length, &olength);
575 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100576 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100577 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100578
gabor-mezei-arm25230452021-06-29 19:06:30 +0200579 *output_length = accumulated_length + olength;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200580
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100581exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100582 if (status == PSA_SUCCESS) {
583 status = mbedtls_psa_cipher_abort(&operation);
584 } else {
585 mbedtls_psa_cipher_abort(&operation);
586 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100587
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100588 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100589}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100590#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100591
Ronald Cron0ff57952021-03-08 16:46:35 +0100592#endif /* MBEDTLS_PSA_CRYPTO_C */