blob: d216339e6521446a8d8a3fca748936118438b754 [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 Man43dedd82022-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
Ronald Cron75e6ae22021-03-17 14:46:05 +010034const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
35 psa_algorithm_t alg,
36 psa_key_type_t key_type,
37 size_t key_bits,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010038 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010039{
40 mbedtls_cipher_mode_t mode;
41 mbedtls_cipher_id_t cipher_id_tmp;
42
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010043 if (PSA_ALG_IS_AEAD(alg)) {
44 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
45 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010046
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
48 switch (alg) {
Gilles Peskine449e02e2022-03-16 12:25:17 +010049#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +010050 case PSA_ALG_STREAM_CIPHER:
51 mode = MBEDTLS_MODE_STREAM;
52 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010053#endif
54#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +010055 case PSA_ALG_CTR:
56 mode = MBEDTLS_MODE_CTR;
57 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010058#endif
59#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010060 case PSA_ALG_CFB:
61 mode = MBEDTLS_MODE_CFB;
62 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010063#endif
64#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +010065 case PSA_ALG_OFB:
66 mode = MBEDTLS_MODE_OFB;
67 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010068#endif
69#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010070 case PSA_ALG_ECB_NO_PADDING:
71 mode = MBEDTLS_MODE_ECB;
72 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010073#endif
74#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +010075 case PSA_ALG_CBC_NO_PADDING:
76 mode = MBEDTLS_MODE_CBC;
77 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010078#endif
79#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +010080 case PSA_ALG_CBC_PKCS7:
81 mode = MBEDTLS_MODE_CBC;
82 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010083#endif
84#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010086 mode = MBEDTLS_MODE_CCM;
87 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010088#endif
89#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010091 mode = MBEDTLS_MODE_GCM;
92 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010093#endif
94#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010095 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Ronald Cron75e6ae22021-03-17 14:46:05 +010096 mode = MBEDTLS_MODE_CHACHAPOLY;
97 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +010098#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +010099 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100101 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100102 } else if (alg == PSA_ALG_CMAC) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100103 mode = MBEDTLS_MODE_ECB;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 } else {
105 return NULL;
106 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100107
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100108 switch (key_type) {
Gilles Peskine449e02e2022-03-16 12:25:17 +0100109#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100110 case PSA_KEY_TYPE_AES:
111 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
112 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100113#endif
114#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine8890f642021-09-21 11:59:39 +0200115 case PSA_KEY_TYPE_ARIA:
116 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
117 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100118#endif
119#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100120 case PSA_KEY_TYPE_DES:
121 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
122 * and 192 for three-key Triple-DES. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 if (key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100124 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100125 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100126 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100128 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
129 * but two-key Triple-DES is functionally three-key Triple-DES
130 * with K1=K3, so that's how we present it to mbedtls. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 if (key_bits == 128) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100132 key_bits = 192;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100134 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100135#endif
136#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100137 case PSA_KEY_TYPE_CAMELLIA:
138 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
139 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100140#endif
141#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100142 case PSA_KEY_TYPE_ARC4:
143 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
144 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100145#endif
146#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100147 case PSA_KEY_TYPE_CHACHA20:
148 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
149 break;
Gilles Peskine449e02e2022-03-16 12:25:17 +0100150#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100151 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 return NULL;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100153 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100155 *cipher_id = cipher_id_tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100156 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100157
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100158 return mbedtls_cipher_info_from_values(cipher_id_tmp,
159 (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100160}
161
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100162#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100163
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100164static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100165 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100166 const psa_key_attributes_t *attributes,
167 const uint8_t *key_buffer, size_t key_buffer_size,
168 psa_algorithm_t alg,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100169 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100170{
171 int ret = 0;
172 size_t key_bits;
173 const mbedtls_cipher_info_t *cipher_info = NULL;
174 psa_key_type_t key_type = attributes->core.type;
175
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100177
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100178 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100179
Ronald Cron6e412a72021-03-10 09:58:47 +0100180 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100181 key_bits = attributes->core.bits;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
183 key_bits, NULL);
184 if (cipher_info == NULL) {
185 return PSA_ERROR_NOT_SUPPORTED;
186 }
Ronald Crond6d28882020-12-14 14:56:02 +0100187
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100188 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
189 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100190 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100191 }
Ronald Crond6d28882020-12-14 14:56:02 +0100192
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100193#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100195 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
196 uint8_t keys[24];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100197 memcpy(keys, key_buffer, 16);
198 memcpy(keys + 16, key_buffer, 8);
199 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
200 keys,
201 192, cipher_operation);
202 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100203#endif
204 {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
206 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100207 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100209 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100210 }
Ronald Crond6d28882020-12-14 14:56:02 +0100211
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100212#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
213 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100215 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
217 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100218 break;
219 case PSA_ALG_CBC_PKCS7:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100220 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
221 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100222 break;
223 default:
224 /* The algorithm doesn't involve padding. */
225 ret = 0;
226 break;
227 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100229 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100231#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
232 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100233
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
235 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
236 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100237
238exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100239 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100240}
241
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100242psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100243 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100244 const psa_key_attributes_t *attributes,
245 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100247{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100248 return psa_cipher_setup(operation, attributes,
249 key_buffer, key_buffer_size,
250 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100251}
252
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100253psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100254 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100255 const psa_key_attributes_t *attributes,
256 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100257 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100258{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100259 return psa_cipher_setup(operation, attributes,
260 key_buffer, key_buffer_size,
261 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100262}
Ronald Cron6d051732020-10-01 14:10:20 +0200263
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100264psa_status_t mbedtls_psa_cipher_set_iv(
265 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100267{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100268 if (iv_length != operation->iv_length) {
269 return PSA_ERROR_INVALID_ARGUMENT;
270 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 return mbedtls_to_psa_error(
273 mbedtls_cipher_set_iv(&operation->ctx.cipher,
274 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100275}
276
Gilles Peskine449e02e2022-03-16 12:25:17 +0100277#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine7b1c9162021-09-13 09:33:28 +0200278/** Process input for which the algorithm is set to ECB mode.
279 *
280 * This requires manual processing, since the PSA API is defined as being
281 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
282 * but the underlying mbedtls_cipher_update only takes full blocks.
283 *
284 * \param ctx The mbedtls cipher context to use. It must have been
285 * set up for ECB.
286 * \param[in] input The input plaintext or ciphertext to process.
287 * \param input_length The number of bytes to process from \p input.
288 * This does not need to be aligned to a block boundary.
289 * If there is a partial block at the end of the input,
290 * it is stored in \p ctx for future processing.
Gilles Peskine03900162021-09-13 12:20:51 +0200291 * \param output The buffer where the output is written. It must be
292 * at least `BS * floor((p + input_length) / BS)` bytes
293 * long, where `p` is the number of bytes in the
294 * unprocessed partial block in \p ctx (with
295 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine7b1c9162021-09-13 09:33:28 +0200296 * \param output_length On success, the number of bytes written to \p output.
297 * \c 0 on error.
298 *
299 * \return #PSA_SUCCESS or an error from a hardware accelerator
300 */
Ronald Cron6d051732020-10-01 14:10:20 +0200301static psa_status_t psa_cipher_update_ecb(
302 mbedtls_cipher_context_t *ctx,
303 const uint8_t *input,
304 size_t input_length,
305 uint8_t *output,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200307{
308 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
309 size_t block_size = ctx->cipher_info->block_size;
310 size_t internal_output_length = 0;
311 *output_length = 0;
312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200314 status = PSA_SUCCESS;
315 goto exit;
316 }
317
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200319 /* Fill up to block size, and run the block if there's a full one. */
320 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
321
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100322 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200323 bytes_to_copy = input_length;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 }
Ronald Cron6d051732020-10-01 14:10:20 +0200325
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100326 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
327 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200328 input_length -= bytes_to_copy;
329 input += bytes_to_copy;
330 ctx->unprocessed_len += bytes_to_copy;
331
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200333 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334 mbedtls_cipher_update(ctx,
335 ctx->unprocessed_data,
336 block_size,
337 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200340 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 }
Ronald Cron6d051732020-10-01 14:10:20 +0200342
343 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200344 *output_length += internal_output_length;
345 ctx->unprocessed_len = 0;
346 }
347 }
348
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100349 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200350 /* Run all full blocks we have, one by one */
351 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100352 mbedtls_cipher_update(ctx, input,
353 block_size,
354 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200355
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200357 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 }
Ronald Cron6d051732020-10-01 14:10:20 +0200359
360 input_length -= block_size;
361 input += block_size;
362
363 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200364 *output_length += internal_output_length;
365 }
366
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100367 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200368 /* Save unprocessed bytes for later processing */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
370 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200371 ctx->unprocessed_len += input_length;
372 }
373
374 status = PSA_SUCCESS;
375
376exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200378}
Gilles Peskine449e02e2022-03-16 12:25:17 +0100379#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200380
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100381psa_status_t mbedtls_psa_cipher_update(
382 mbedtls_psa_cipher_operation_t *operation,
383 const uint8_t *input, size_t input_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100384 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200385{
386 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
387 size_t expected_output_size;
388
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100389 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200390 /* Take the unprocessed partial block left over from previous
391 * update calls, if any, plus the input to this call. Remove
392 * the last partial block, if any. You get the data that will be
393 * output in this call. */
394 expected_output_size =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100395 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100396 / operation->block_length * operation->block_length;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100397 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200398 expected_output_size = input_length;
399 }
400
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100401 if (output_size < expected_output_size) {
402 return PSA_ERROR_BUFFER_TOO_SMALL;
403 }
Ronald Cron6d051732020-10-01 14:10:20 +0200404
Gilles Peskine449e02e2022-03-16 12:25:17 +0100405#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100406 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200407 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100408 * process a single block at a time in ECB mode. Abstract away that
409 * inconsistency here to match the PSA API behaviour. */
410 status = psa_cipher_update_ecb(&operation->ctx.cipher,
411 input,
412 input_length,
413 output,
414 output_length);
415 } else
Gilles Peskine449e02e2022-03-16 12:25:17 +0100416#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200417 {
418 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 mbedtls_cipher_update(&operation->ctx.cipher, input,
420 input_length, output, output_length));
gabor-mezei-arm42373bd2021-06-29 16:41:25 +0200421
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 if (*output_length > output_size) {
423 return PSA_ERROR_CORRUPTION_DETECTED;
424 }
Ronald Cron6d051732020-10-01 14:10:20 +0200425 }
426
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200428}
429
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100430psa_status_t mbedtls_psa_cipher_finish(
431 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100432 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200433{
434 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
435 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
436
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 if (operation->ctx.cipher.unprocessed_len != 0) {
438 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
439 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200440 status = PSA_ERROR_INVALID_ARGUMENT;
441 goto exit;
442 }
443 }
444
445 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 mbedtls_cipher_finish(&operation->ctx.cipher,
447 temp_output_buffer,
448 output_length));
449 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200450 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 }
Ronald Cron6d051732020-10-01 14:10:20 +0200452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200454 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100455 } else if (output_size >= *output_length) {
456 memcpy(output, temp_output_buffer, *output_length);
457 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200458 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100459 }
Ronald Cron6d051732020-10-01 14:10:20 +0200460
461exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100462 mbedtls_platform_zeroize(temp_output_buffer,
463 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200464
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200466}
467
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100468psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200470{
Ronald Cron937dfee2021-03-10 09:17:32 +0100471 /* Sanity check (shouldn't happen: operation->alg should
472 * always have been initialized to a valid value). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100473 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
474 return PSA_ERROR_BAD_STATE;
475 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100476
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100477 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200478
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100479 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200480}
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100481
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100482psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,
483 const uint8_t *key_buffer,
484 size_t key_buffer_size,
485 psa_algorithm_t alg,
486 const uint8_t *iv,
487 size_t iv_length,
488 const uint8_t *input,
489 size_t input_length,
490 uint8_t *output,
491 size_t output_size,
492 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100493{
494 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
495 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Crona8331692021-07-09 09:19:35 +0200496 size_t update_output_length, finish_output_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100497
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100498 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
499 key_buffer, key_buffer_size,
500 alg);
501 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100502 goto exit;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100503 }
504
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100505 if (iv_length > 0) {
506 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
507 if (status != PSA_SUCCESS) {
508 goto exit;
509 }
510 }
511
512 status = mbedtls_psa_cipher_update(&operation, input, input_length,
513 output, output_size, &update_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
Gilles Peskine01bf6312022-11-23 14:15:57 +0100518 status = mbedtls_psa_cipher_finish(
519 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100520 mbedtls_buffer_offset(output, update_output_length),
521 output_size - update_output_length, &finish_output_length);
522 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100523 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100524 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100525
Ronald Crona8331692021-07-09 09:19:35 +0200526 *output_length = update_output_length + finish_output_length;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200527
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100528exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100529 if (status == PSA_SUCCESS) {
530 status = mbedtls_psa_cipher_abort(&operation);
531 } else {
532 mbedtls_psa_cipher_abort(&operation);
533 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100536}
537
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100538psa_status_t mbedtls_psa_cipher_decrypt(
539 const psa_key_attributes_t *attributes,
540 const uint8_t *key_buffer,
541 size_t key_buffer_size,
542 psa_algorithm_t alg,
543 const uint8_t *input,
544 size_t input_length,
545 uint8_t *output,
546 size_t output_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100547 size_t *output_length)
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100548{
549 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
550 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200551 size_t olength, accumulated_length;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100552
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100553 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
554 key_buffer, key_buffer_size,
555 alg);
556 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100557 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100559
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100560 if (operation.iv_length > 0) {
561 status = mbedtls_psa_cipher_set_iv(&operation,
562 input, operation.iv_length);
563 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100564 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100566 }
567
Gilles Peskine01bf6312022-11-23 14:15:57 +0100568 status = mbedtls_psa_cipher_update(
569 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine01bf6312022-11-23 14:15:57 +0100571 input_length - operation.iv_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100572 output, output_size, &olength);
573 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100574 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100576
gabor-mezei-arm809634d2021-06-29 16:42:13 +0200577 accumulated_length = olength;
gabor-mezei-arm3fd792d2021-06-25 15:25:38 +0200578
Gilles Peskine01bf6312022-11-23 14:15:57 +0100579 status = mbedtls_psa_cipher_finish(
580 &operation,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 mbedtls_buffer_offset(output, accumulated_length),
582 output_size - accumulated_length, &olength);
583 if (status != PSA_SUCCESS) {
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100584 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100585 }
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100586
gabor-mezei-arm25230452021-06-29 19:06:30 +0200587 *output_length = accumulated_length + olength;
gabor-mezei-arm7fbea092021-06-25 15:23:05 +0200588
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100589exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100590 if (status == PSA_SUCCESS) {
591 status = mbedtls_psa_cipher_abort(&operation);
592 } else {
593 mbedtls_psa_cipher_abort(&operation);
594 }
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100595
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100596 return status;
gabor-mezei-armfa990b52021-03-25 11:17:10 +0100597}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100598#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100599
Ronald Cron0ff57952021-03-08 16:46:35 +0100600#endif /* MBEDTLS_PSA_CRYPTO_C */