blob: 545bb50cc8797ae4704ddc1365f5282667a223c1 [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 */
Ronald Cron6d051732020-10-01 14:10:20 +0200405 {
406 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 mbedtls_cipher_update(&operation->ctx.cipher, input,
408 input_length, output, output_length));
gabor-mezei-arm42373bd2021-06-29 16:41:25 +0200409
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410 if (*output_length > output_size) {
411 return PSA_ERROR_CORRUPTION_DETECTED;
412 }
Ronald Cron6d051732020-10-01 14:10:20 +0200413 }
414
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200416}
417
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100418psa_status_t mbedtls_psa_cipher_finish(
419 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100420 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200421{
422 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
423 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
424
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100425 if (operation->ctx.cipher.unprocessed_len != 0) {
426 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
427 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200428 status = PSA_ERROR_INVALID_ARGUMENT;
429 goto exit;
430 }
431 }
432
433 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100434 mbedtls_cipher_finish(&operation->ctx.cipher,
435 temp_output_buffer,
436 output_length));
437 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200438 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 }
Ronald Cron6d051732020-10-01 14:10:20 +0200440
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100441 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200442 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100443 } else if (output_size >= *output_length) {
444 memcpy(output, temp_output_buffer, *output_length);
445 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200446 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 }
Ronald Cron6d051732020-10-01 14:10:20 +0200448
449exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100450 mbedtls_platform_zeroize(temp_output_buffer,
451 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200454}
455
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100456psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200458{
Ronald Cron937dfee2021-03-10 09:17:32 +0100459 /* Sanity check (shouldn't happen: operation->alg should
460 * always have been initialized to a valid value). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
462 return PSA_ERROR_BAD_STATE;
463 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100464
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200466
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100467 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200468}
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100469
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100470psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,
471 const uint8_t *key_buffer,
472 size_t key_buffer_size,
473 psa_algorithm_t alg,
474 const uint8_t *iv,
475 size_t iv_length,
476 const uint8_t *input,
477 size_t input_length,
478 uint8_t *output,
479 size_t output_size,
480 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100481{
482 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
483 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Crona8331692021-07-09 09:19:35 +0200484 size_t update_output_length, finish_output_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100485
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100486 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
487 key_buffer, key_buffer_size,
488 alg);
489 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100490 goto exit;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100491 }
492
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100493 if (iv_length > 0) {
494 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
495 if (status != PSA_SUCCESS) {
496 goto exit;
497 }
498 }
499
500 status = mbedtls_psa_cipher_update(&operation, input, input_length,
501 output, output_size, &update_output_length);
502 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100503 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100505
Gilles Peskine01bf6312022-11-23 14:15:57 +0100506 status = mbedtls_psa_cipher_finish(
507 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100508 mbedtls_buffer_offset(output, update_output_length),
509 output_size - update_output_length, &finish_output_length);
510 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100511 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100512 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100513
Ronald Crona8331692021-07-09 09:19:35 +0200514 *output_length = update_output_length + finish_output_length;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200515
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100516exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100517 if (status == PSA_SUCCESS) {
518 status = mbedtls_psa_cipher_abort(&operation);
519 } else {
520 mbedtls_psa_cipher_abort(&operation);
521 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100522
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100523 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100524}
525
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100526psa_status_t mbedtls_psa_cipher_decrypt(
527 const psa_key_attributes_t *attributes,
528 const uint8_t *key_buffer,
529 size_t key_buffer_size,
530 psa_algorithm_t alg,
531 const uint8_t *input,
532 size_t input_length,
533 uint8_t *output,
534 size_t output_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100536{
537 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
538 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200539 size_t olength, accumulated_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100540
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
542 key_buffer, key_buffer_size,
543 alg);
544 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100545 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100547
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100548 if (operation.iv_length > 0) {
549 status = mbedtls_psa_cipher_set_iv(&operation,
550 input, operation.iv_length);
551 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100552 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100553 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100554 }
555
Gilles Peskine01bf6312022-11-23 14:15:57 +0100556 status = mbedtls_psa_cipher_update(
557 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine01bf6312022-11-23 14:15:57 +0100559 input_length - operation.iv_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100560 output, output_size, &olength);
561 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100562 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100563 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100564
gabor-mezei-arm809634d2021-06-29 16:42:13 +0200565 accumulated_length = olength;
gabor-mezei-arm3fd792d2021-06-25 15:25:38 +0200566
Gilles Peskine01bf6312022-11-23 14:15:57 +0100567 status = mbedtls_psa_cipher_finish(
568 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100569 mbedtls_buffer_offset(output, accumulated_length),
570 output_size - accumulated_length, &olength);
571 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100572 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100573 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100574
gabor-mezei-arm25230452021-06-29 19:06:30 +0200575 *output_length = accumulated_length + olength;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200576
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100577exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100578 if (status == PSA_SUCCESS) {
579 status = mbedtls_psa_cipher_abort(&operation);
580 } else {
581 mbedtls_psa_cipher_abort(&operation);
582 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100583
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100584 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100585}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100586#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100587
Ronald Cron0ff57952021-03-08 16:46:35 +0100588#endif /* MBEDTLS_PSA_CRYPTO_C */