blob: c881d65b6bdf9f379ce1c0ecfa283ac277f1dfb2 [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
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "common.h"
22
23#if defined(MBEDTLS_PSA_CRYPTO_C)
24
Martin Man4741e0b2022-08-02 12:44:35 +020025#include "psa_crypto_cipher.h"
Ronald Crond6d28882020-12-14 14:56:02 +010026#include "psa_crypto_core.h"
Ronald Cron6d051732020-10-01 14:10:20 +020027#include "psa_crypto_random_impl.h"
28
Ronald Crond6d28882020-12-14 14:56:02 +010029#include "mbedtls/cipher.h"
Ronald Cron6d051732020-10-01 14:10:20 +020030#include "mbedtls/error.h"
Ronald Cron0ff57952021-03-08 16:46:35 +010031
Ronald Crond6d28882020-12-14 14:56:02 +010032#include <string.h>
33
Valerio Setti2c2aded2023-08-25 09:22:19 +020034#if defined(MBEDTLS_CIPHER_C)
Ronald Cron75e6ae22021-03-17 14:46:05 +010035const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
36 psa_algorithm_t alg,
37 psa_key_type_t key_type,
38 size_t key_bits,
Gilles Peskine449bd832023-01-11 14:50:10 +010039 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010040{
41 mbedtls_cipher_mode_t mode;
42 mbedtls_cipher_id_t cipher_id_tmp;
43
Gilles Peskine449bd832023-01-11 14:50:10 +010044 if (PSA_ALG_IS_AEAD(alg)) {
45 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
46 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010047
Gilles Peskine449bd832023-01-11 14:50:10 +010048 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
49 switch (alg) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +010050#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +010051 case PSA_ALG_STREAM_CIPHER:
52 mode = MBEDTLS_MODE_STREAM;
53 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010054#endif
55#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +010056 case PSA_ALG_CTR:
57 mode = MBEDTLS_MODE_CTR;
58 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010059#endif
60#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010061 case PSA_ALG_CFB:
62 mode = MBEDTLS_MODE_CFB;
63 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010064#endif
65#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010066 case PSA_ALG_OFB:
67 mode = MBEDTLS_MODE_OFB;
68 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010069#endif
70#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010071 case PSA_ALG_ECB_NO_PADDING:
72 mode = MBEDTLS_MODE_ECB;
73 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010074#endif
75#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010076 case PSA_ALG_CBC_NO_PADDING:
77 mode = MBEDTLS_MODE_CBC;
78 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010079#endif
80#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +010081 case PSA_ALG_CBC_PKCS7:
82 mode = MBEDTLS_MODE_CBC;
83 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010084#endif
85#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
Mateusz Starzyk594215b2021-10-14 12:23:06 +020086 case PSA_ALG_CCM_STAR_NO_TAG:
Mateusz Starzyk4cb97392021-10-27 10:42:31 +020087 mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
Mateusz Starzyk594215b2021-10-14 12:23:06 +020088 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010089#endif
90#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010091 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010092 mode = MBEDTLS_MODE_CCM;
93 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010094#endif
95#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010096 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010097 mode = MBEDTLS_MODE_GCM;
98 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +010099#endif
100#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +0100102 mode = MBEDTLS_MODE_CHACHAPOLY;
103 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100104#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100105 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100107 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 } else if (alg == PSA_ALG_CMAC) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100109 mode = MBEDTLS_MODE_ECB;
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 } else {
111 return NULL;
112 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 switch (key_type) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100115#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100116 case PSA_KEY_TYPE_AES:
117 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
118 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100119#endif
120#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine6c12a1e2021-09-21 11:59:39 +0200121 case PSA_KEY_TYPE_ARIA:
122 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
123 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100124#endif
125#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100126 case PSA_KEY_TYPE_DES:
127 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
128 * and 192 for three-key Triple-DES. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 if (key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100130 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100132 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100134 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
135 * but two-key Triple-DES is functionally three-key Triple-DES
136 * with K1=K3, so that's how we present it to mbedtls. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 if (key_bits == 128) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100138 key_bits = 192;
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100140 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100141#endif
142#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100143 case PSA_KEY_TYPE_CAMELLIA:
144 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
145 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100146#endif
147#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100148 case PSA_KEY_TYPE_CHACHA20:
149 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
150 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100151#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100152 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100154 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100156 *cipher_id = cipher_id_tmp;
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 return mbedtls_cipher_info_from_values(cipher_id_tmp,
160 (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100161}
Valerio Setti2c2aded2023-08-25 09:22:19 +0200162#endif /* MBEDTLS_CIPHER_C */
Ronald Cron75e6ae22021-03-17 14:46:05 +0100163
Ronald Cron0266cfe2021-03-13 18:50:11 +0100164#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100165
Ronald Cron0266cfe2021-03-13 18:50:11 +0100166static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100167 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100168 const psa_key_attributes_t *attributes,
169 const uint8_t *key_buffer, size_t key_buffer_size,
170 psa_algorithm_t alg,
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100172{
173 int ret = 0;
174 size_t key_bits;
175 const mbedtls_cipher_info_t *cipher_info = NULL;
176 psa_key_type_t key_type = attributes->core.type;
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100181
Ronald Cron6e412a72021-03-10 09:58:47 +0100182 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100183 key_bits = attributes->core.bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
185 key_bits, NULL);
186 if (cipher_info == NULL) {
187 return PSA_ERROR_NOT_SUPPORTED;
188 }
Ronald Crond6d28882020-12-14 14:56:02 +0100189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
191 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100192 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 }
Ronald Crond6d28882020-12-14 14:56:02 +0100194
Ronald Cron0266cfe2021-03-13 18:50:11 +0100195#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100197 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
198 uint8_t keys[24];
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 memcpy(keys, key_buffer, 16);
200 memcpy(keys + 16, key_buffer, 8);
201 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
202 keys,
203 192, cipher_operation);
204 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100205#endif
206 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
208 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100209 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100211 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 }
Ronald Crond6d28882020-12-14 14:56:02 +0100213
Ronald Cron0266cfe2021-03-13 18:50:11 +0100214#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
215 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100217 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
219 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100220 break;
221 case PSA_ALG_CBC_PKCS7:
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
223 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100224 break;
225 default:
226 /* The algorithm doesn't involve padding. */
227 ret = 0;
228 break;
229 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100231 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100233#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
234 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
237 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
238 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100239
240exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100242}
243
Ronald Cron0266cfe2021-03-13 18:50:11 +0100244psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100245 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100246 const psa_key_attributes_t *attributes,
247 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100249{
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 return psa_cipher_setup(operation, attributes,
251 key_buffer, key_buffer_size,
252 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100253}
254
Ronald Cron0266cfe2021-03-13 18:50:11 +0100255psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100256 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100257 const psa_key_attributes_t *attributes,
258 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100260{
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 return psa_cipher_setup(operation, attributes,
262 key_buffer, key_buffer_size,
263 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100264}
Ronald Cron6d051732020-10-01 14:10:20 +0200265
Ronald Cron0266cfe2021-03-13 18:50:11 +0100266psa_status_t mbedtls_psa_cipher_set_iv(
267 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100269{
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 if (iv_length != operation->iv_length) {
271 return PSA_ERROR_INVALID_ARGUMENT;
272 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 return mbedtls_to_psa_error(
275 mbedtls_cipher_set_iv(&operation->ctx.cipher,
276 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100277}
278
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100279#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine55dffe52021-09-13 09:33:28 +0200280/** Process input for which the algorithm is set to ECB mode.
281 *
282 * This requires manual processing, since the PSA API is defined as being
283 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
284 * but the underlying mbedtls_cipher_update only takes full blocks.
285 *
286 * \param ctx The mbedtls cipher context to use. It must have been
287 * set up for ECB.
288 * \param[in] input The input plaintext or ciphertext to process.
289 * \param input_length The number of bytes to process from \p input.
290 * This does not need to be aligned to a block boundary.
291 * If there is a partial block at the end of the input,
292 * it is stored in \p ctx for future processing.
Gilles Peskined87d8732021-09-13 12:20:51 +0200293 * \param output The buffer where the output is written. It must be
294 * at least `BS * floor((p + input_length) / BS)` bytes
295 * long, where `p` is the number of bytes in the
296 * unprocessed partial block in \p ctx (with
297 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine55dffe52021-09-13 09:33:28 +0200298 * \param output_length On success, the number of bytes written to \p output.
299 * \c 0 on error.
300 *
301 * \return #PSA_SUCCESS or an error from a hardware accelerator
302 */
Ronald Cron6d051732020-10-01 14:10:20 +0200303static psa_status_t psa_cipher_update_ecb(
304 mbedtls_cipher_context_t *ctx,
305 const uint8_t *input,
306 size_t input_length,
307 uint8_t *output,
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200309{
310 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Dave Rodgman85a88132023-06-24 11:41:50 +0100311 size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Ronald Cron6d051732020-10-01 14:10:20 +0200312 size_t internal_output_length = 0;
313 *output_length = 0;
314
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200316 status = PSA_SUCCESS;
317 goto exit;
318 }
319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200321 /* Fill up to block size, and run the block if there's a full one. */
322 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200325 bytes_to_copy = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 }
Ronald Cron6d051732020-10-01 14:10:20 +0200327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
329 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200330 input_length -= bytes_to_copy;
331 input += bytes_to_copy;
332 ctx->unprocessed_len += bytes_to_copy;
333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200335 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 mbedtls_cipher_update(ctx,
337 ctx->unprocessed_data,
338 block_size,
339 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200342 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 }
Ronald Cron6d051732020-10-01 14:10:20 +0200344
345 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200346 *output_length += internal_output_length;
347 ctx->unprocessed_len = 0;
348 }
349 }
350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200352 /* Run all full blocks we have, one by one */
353 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 mbedtls_cipher_update(ctx, input,
355 block_size,
356 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200359 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 }
Ronald Cron6d051732020-10-01 14:10:20 +0200361
362 input_length -= block_size;
363 input += block_size;
364
365 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200366 *output_length += internal_output_length;
367 }
368
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200370 /* Save unprocessed bytes for later processing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
372 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200373 ctx->unprocessed_len += input_length;
374 }
375
376 status = PSA_SUCCESS;
377
378exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200380}
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100381#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200382
Ronald Cron0266cfe2021-03-13 18:50:11 +0100383psa_status_t mbedtls_psa_cipher_update(
384 mbedtls_psa_cipher_operation_t *operation,
385 const uint8_t *input, size_t input_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200387{
388 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
389 size_t expected_output_size;
390
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200392 /* Take the unprocessed partial block left over from previous
393 * update calls, if any, plus the input to this call. Remove
394 * the last partial block, if any. You get the data that will be
395 * output in this call. */
396 expected_output_size =
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100398 / operation->block_length * operation->block_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200400 expected_output_size = input_length;
401 }
402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 if (output_size < expected_output_size) {
404 return PSA_ERROR_BUFFER_TOO_SMALL;
405 }
Ronald Cron6d051732020-10-01 14:10:20 +0200406
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100407#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200409 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 * process a single block at a time in ECB mode. Abstract away that
411 * inconsistency here to match the PSA API behaviour. */
412 status = psa_cipher_update_ecb(&operation->ctx.cipher,
413 input,
414 input_length,
415 output,
416 output_length);
417 } else
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100418#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200419 {
420 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 mbedtls_cipher_update(&operation->ctx.cipher, input,
422 input_length, output, output_length));
gabor-mezei-arm58c17272021-06-29 16:41:25 +0200423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (*output_length > output_size) {
425 return PSA_ERROR_CORRUPTION_DETECTED;
426 }
Ronald Cron6d051732020-10-01 14:10:20 +0200427 }
428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200430}
431
Ronald Cron0266cfe2021-03-13 18:50:11 +0100432psa_status_t mbedtls_psa_cipher_finish(
433 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200435{
436 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
437 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
438
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (operation->ctx.cipher.unprocessed_len != 0) {
440 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
441 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200442 status = PSA_ERROR_INVALID_ARGUMENT;
443 goto exit;
444 }
445 }
446
447 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 mbedtls_cipher_finish(&operation->ctx.cipher,
449 temp_output_buffer,
450 output_length));
451 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200452 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 }
Ronald Cron6d051732020-10-01 14:10:20 +0200454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200456 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 } else if (output_size >= *output_length) {
458 memcpy(output, temp_output_buffer, *output_length);
459 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200460 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 }
Ronald Cron6d051732020-10-01 14:10:20 +0200462
463exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 mbedtls_platform_zeroize(temp_output_buffer,
465 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200468}
469
Ronald Cron0266cfe2021-03-13 18:50:11 +0100470psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200472{
Ronald Cron937dfee2021-03-10 09:17:32 +0100473 /* Sanity check (shouldn't happen: operation->alg should
474 * always have been initialized to a valid value). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
476 return PSA_ERROR_BAD_STATE;
477 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100478
Gilles Peskine449bd832023-01-11 14:50:10 +0100479 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200480
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200482}
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100483
Ronald Cron0266cfe2021-03-13 18:50:11 +0100484psa_status_t mbedtls_psa_cipher_encrypt(
485 const psa_key_attributes_t *attributes,
486 const uint8_t *key_buffer,
487 size_t key_buffer_size,
488 psa_algorithm_t alg,
Ronald Cron9b674282021-07-09 09:19:35 +0200489 const uint8_t *iv,
490 size_t iv_length,
Ronald Cron0266cfe2021-03-13 18:50:11 +0100491 const uint8_t *input,
492 size_t input_length,
493 uint8_t *output,
494 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100496{
497 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
498 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Cron8188d192021-12-14 10:58:18 +0100499 size_t update_output_length, finish_output_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100500
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
502 key_buffer, key_buffer_size,
503 alg);
504 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100505 goto exit;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100506 }
507
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 if (iv_length > 0) {
509 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
510 if (status != PSA_SUCCESS) {
511 goto exit;
512 }
513 }
514
515 status = mbedtls_psa_cipher_update(&operation, input, input_length,
516 output, output_size,
517 &update_output_length);
518 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100519 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100521
Gilles Peskine42649d92022-11-23 14:15:57 +0100522 status = mbedtls_psa_cipher_finish(
523 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 mbedtls_buffer_offset(output, update_output_length),
525 output_size - update_output_length, &finish_output_length);
526 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100527 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100529
Ronald Cron8188d192021-12-14 10:58:18 +0100530 *output_length = update_output_length + finish_output_length;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200531
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100532exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 if (status == PSA_SUCCESS) {
534 status = mbedtls_psa_cipher_abort(&operation);
535 } else {
536 mbedtls_psa_cipher_abort(&operation);
537 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100540}
541
Ronald Cron0266cfe2021-03-13 18:50:11 +0100542psa_status_t mbedtls_psa_cipher_decrypt(
543 const psa_key_attributes_t *attributes,
544 const uint8_t *key_buffer,
545 size_t key_buffer_size,
546 psa_algorithm_t alg,
547 const uint8_t *input,
548 size_t input_length,
549 uint8_t *output,
550 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100552{
553 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
554 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200555 size_t olength, accumulated_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
558 key_buffer, key_buffer_size,
559 alg);
560 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100561 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 if (operation.iv_length > 0) {
565 status = mbedtls_psa_cipher_set_iv(&operation,
566 input, operation.iv_length);
567 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100568 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100570 }
571
Gilles Peskine42649d92022-11-23 14:15:57 +0100572 status = mbedtls_psa_cipher_update(
573 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine42649d92022-11-23 14:15:57 +0100575 input_length - operation.iv_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 output, output_size, &olength);
577 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100578 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100579 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100580
gabor-mezei-arm6158e282021-06-29 16:42:13 +0200581 accumulated_length = olength;
gabor-mezei-arm258ae072021-06-25 15:25:38 +0200582
Gilles Peskine42649d92022-11-23 14:15:57 +0100583 status = mbedtls_psa_cipher_finish(
584 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 mbedtls_buffer_offset(output, accumulated_length),
586 output_size - accumulated_length, &olength);
587 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100588 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100590
gabor-mezei-arm00e54f12021-06-29 19:06:30 +0200591 *output_length = accumulated_length + olength;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200592
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100593exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 if (status == PSA_SUCCESS) {
595 status = mbedtls_psa_cipher_abort(&operation);
596 } else {
597 mbedtls_psa_cipher_abort(&operation);
598 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100601}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100602#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100603
Ronald Cron0ff57952021-03-08 16:46:35 +0100604#endif /* MBEDTLS_PSA_CRYPTO_C */