blob: b195bb9fd5a8bb08ade8781410986a77ee78dd39 [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 Setti1e21f262023-10-20 16:24:07 +020034/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
35 * are enabled, but it does not provide any compatibility check between them
36 * (i.e. if the specified key works with the specified algorithm). This helper
37 * function is meant to provide this support.
38 * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
39 * requires CIPHER_C to be enabled.
40 */
41static psa_status_t mbedtls_cipher_validate_values(
42 psa_algorithm_t alg,
43 psa_key_type_t key_type)
44{
45 switch (alg) {
46 case PSA_ALG_STREAM_CIPHER:
47 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
48 if (key_type != PSA_KEY_TYPE_CHACHA20) {
49 return PSA_ERROR_NOT_SUPPORTED;
50 }
51 break;
52
53 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
54 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
55 case PSA_ALG_CCM_STAR_NO_TAG:
56 if ((key_type != PSA_KEY_TYPE_AES) &&
57 (key_type != PSA_KEY_TYPE_ARIA) &&
58 (key_type != PSA_KEY_TYPE_CAMELLIA)) {
59 return PSA_ERROR_NOT_SUPPORTED;
60 }
61 break;
62
63 case PSA_ALG_CTR:
64 case PSA_ALG_CFB:
65 case PSA_ALG_OFB:
66 case PSA_ALG_XTS:
67 case PSA_ALG_ECB_NO_PADDING:
68 case PSA_ALG_CBC_NO_PADDING:
69 case PSA_ALG_CBC_PKCS7:
70 case PSA_ALG_CMAC:
71 if ((key_type != PSA_KEY_TYPE_AES) &&
72 (key_type != PSA_KEY_TYPE_ARIA) &&
73 (key_type != PSA_KEY_TYPE_DES) &&
74 (key_type != PSA_KEY_TYPE_CAMELLIA)) {
75 return PSA_ERROR_NOT_SUPPORTED;
76 }
77 break;
78
79 default:
80 return PSA_ERROR_NOT_SUPPORTED;
81 }
82
83 return PSA_SUCCESS;
84}
85
Valerio Setti4a249822023-10-18 12:34:54 +020086psa_status_t mbedtls_cipher_values_from_psa(
Ronald Cron75e6ae22021-03-17 14:46:05 +010087 psa_algorithm_t alg,
88 psa_key_type_t key_type,
Valerio Setti4a249822023-10-18 12:34:54 +020089 size_t *key_bits,
90 mbedtls_cipher_mode_t *mode,
Gilles Peskine449bd832023-01-11 14:50:10 +010091 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010092{
Ronald Cron75e6ae22021-03-17 14:46:05 +010093 mbedtls_cipher_id_t cipher_id_tmp;
Valerio Setti4a249822023-10-18 12:34:54 +020094 (void) key_bits;
Ronald Cron75e6ae22021-03-17 14:46:05 +010095
Gilles Peskine449bd832023-01-11 14:50:10 +010096 if (PSA_ALG_IS_AEAD(alg)) {
97 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
98 }
Ronald Cron75e6ae22021-03-17 14:46:05 +010099
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
101 switch (alg) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100102#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100103 case PSA_ALG_STREAM_CIPHER:
Valerio Setti4a249822023-10-18 12:34:54 +0200104 *mode = MBEDTLS_MODE_STREAM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100105 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100106#endif
107#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100108 case PSA_ALG_CTR:
Valerio Setti4a249822023-10-18 12:34:54 +0200109 *mode = MBEDTLS_MODE_CTR;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100110 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100111#endif
112#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100113 case PSA_ALG_CFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200114 *mode = MBEDTLS_MODE_CFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100115 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100116#endif
117#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100118 case PSA_ALG_OFB:
Valerio Setti4a249822023-10-18 12:34:54 +0200119 *mode = MBEDTLS_MODE_OFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100120 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100121#endif
122#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100123 case PSA_ALG_ECB_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200124 *mode = MBEDTLS_MODE_ECB;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100125 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100126#endif
127#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100128 case PSA_ALG_CBC_NO_PADDING:
Valerio Setti4a249822023-10-18 12:34:54 +0200129 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100130 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100131#endif
132#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100133 case PSA_ALG_CBC_PKCS7:
Valerio Setti4a249822023-10-18 12:34:54 +0200134 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100135 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100136#endif
137#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200138 case PSA_ALG_CCM_STAR_NO_TAG:
Valerio Setti4a249822023-10-18 12:34:54 +0200139 *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
Mateusz Starzyk594215b2021-10-14 12:23:06 +0200140 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100141#endif
142#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200144 *mode = MBEDTLS_MODE_CCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100145 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100146#endif
147#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200149 *mode = MBEDTLS_MODE_GCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100150 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100151#endif
152#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Valerio Setti4a249822023-10-18 12:34:54 +0200154 *mode = MBEDTLS_MODE_CHACHAPOLY;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100155 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100156#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100157 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200158 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100159 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 } else if (alg == PSA_ALG_CMAC) {
Valerio Setti4a249822023-10-18 12:34:54 +0200161 *mode = MBEDTLS_MODE_ECB;
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 } else {
Valerio Setti4a249822023-10-18 12:34:54 +0200163 return PSA_ERROR_NOT_SUPPORTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 switch (key_type) {
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100167#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100168 case PSA_KEY_TYPE_AES:
169 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
170 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100171#endif
172#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
Gilles Peskine6c12a1e2021-09-21 11:59:39 +0200173 case PSA_KEY_TYPE_ARIA:
174 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
175 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100176#endif
177#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100178 case PSA_KEY_TYPE_DES:
179 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
180 * and 192 for three-key Triple-DES. */
Valerio Setti4a249822023-10-18 12:34:54 +0200181 if (*key_bits == 64) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100182 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 } else {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100184 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100186 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
187 * but two-key Triple-DES is functionally three-key Triple-DES
188 * with K1=K3, so that's how we present it to mbedtls. */
Valerio Setti4a249822023-10-18 12:34:54 +0200189 if (*key_bits == 128) {
190 *key_bits = 192;
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100192 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100193#endif
194#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100195 case PSA_KEY_TYPE_CAMELLIA:
196 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
197 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100198#endif
199#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
Ronald Cron75e6ae22021-03-17 14:46:05 +0100200 case PSA_KEY_TYPE_CHACHA20:
201 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
202 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100203#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100204 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200205 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100206 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 if (cipher_id != NULL) {
Ronald Cron75e6ae22021-03-17 14:46:05 +0100208 *cipher_id = cipher_id_tmp;
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 }
Ronald Cron75e6ae22021-03-17 14:46:05 +0100210
Valerio Setti1e21f262023-10-20 16:24:07 +0200211 return mbedtls_cipher_validate_values(alg, key_type);
Valerio Setti4a249822023-10-18 12:34:54 +0200212}
213
214#if defined(MBEDTLS_CIPHER_C)
215const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
216 psa_algorithm_t alg,
217 psa_key_type_t key_type,
218 size_t key_bits,
219 mbedtls_cipher_id_t *cipher_id)
220{
221 mbedtls_cipher_mode_t mode;
222 psa_status_t status;
223 mbedtls_cipher_id_t cipher_id_tmp;
224
225 status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
226 if (status != PSA_SUCCESS) {
227 return NULL;
228 }
229 if (cipher_id != NULL) {
230 *cipher_id = cipher_id_tmp;
231 }
232
233 return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100234}
Valerio Setti2c2aded2023-08-25 09:22:19 +0200235#endif /* MBEDTLS_CIPHER_C */
Ronald Cron75e6ae22021-03-17 14:46:05 +0100236
Ronald Cron0266cfe2021-03-13 18:50:11 +0100237#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100238
Ronald Cron0266cfe2021-03-13 18:50:11 +0100239static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100240 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100241 const psa_key_attributes_t *attributes,
242 const uint8_t *key_buffer, size_t key_buffer_size,
243 psa_algorithm_t alg,
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100245{
246 int ret = 0;
247 size_t key_bits;
248 const mbedtls_cipher_info_t *cipher_info = NULL;
249 psa_key_type_t key_type = attributes->core.type;
250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100254
Ronald Cron6e412a72021-03-10 09:58:47 +0100255 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100256 key_bits = attributes->core.bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
258 key_bits, NULL);
259 if (cipher_info == NULL) {
260 return PSA_ERROR_NOT_SUPPORTED;
261 }
Ronald Crond6d28882020-12-14 14:56:02 +0100262
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
264 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100265 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 }
Ronald Crond6d28882020-12-14 14:56:02 +0100267
Ronald Cron0266cfe2021-03-13 18:50:11 +0100268#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100270 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
271 uint8_t keys[24];
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 memcpy(keys, key_buffer, 16);
273 memcpy(keys + 16, key_buffer, 8);
274 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
275 keys,
276 192, cipher_operation);
277 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100278#endif
279 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
281 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100282 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100284 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 }
Ronald Crond6d28882020-12-14 14:56:02 +0100286
Ronald Cron0266cfe2021-03-13 18:50:11 +0100287#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
288 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100290 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
292 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100293 break;
294 case PSA_ALG_CBC_PKCS7:
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
296 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100297 break;
298 default:
299 /* The algorithm doesn't involve padding. */
300 ret = 0;
301 break;
302 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100304 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100306#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
307 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100308
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
310 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
311 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100312
313exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100315}
316
Ronald Cron0266cfe2021-03-13 18:50:11 +0100317psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100318 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100319 const psa_key_attributes_t *attributes,
320 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100322{
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 return psa_cipher_setup(operation, attributes,
324 key_buffer, key_buffer_size,
325 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100326}
327
Ronald Cron0266cfe2021-03-13 18:50:11 +0100328psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100329 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100330 const psa_key_attributes_t *attributes,
331 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100333{
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 return psa_cipher_setup(operation, attributes,
335 key_buffer, key_buffer_size,
336 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100337}
Ronald Cron6d051732020-10-01 14:10:20 +0200338
Ronald Cron0266cfe2021-03-13 18:50:11 +0100339psa_status_t mbedtls_psa_cipher_set_iv(
340 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100342{
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (iv_length != operation->iv_length) {
344 return PSA_ERROR_INVALID_ARGUMENT;
345 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100346
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 return mbedtls_to_psa_error(
348 mbedtls_cipher_set_iv(&operation->ctx.cipher,
349 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100350}
351
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100352#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine55dffe52021-09-13 09:33:28 +0200353/** Process input for which the algorithm is set to ECB mode.
354 *
355 * This requires manual processing, since the PSA API is defined as being
356 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
357 * but the underlying mbedtls_cipher_update only takes full blocks.
358 *
359 * \param ctx The mbedtls cipher context to use. It must have been
360 * set up for ECB.
361 * \param[in] input The input plaintext or ciphertext to process.
362 * \param input_length The number of bytes to process from \p input.
363 * This does not need to be aligned to a block boundary.
364 * If there is a partial block at the end of the input,
365 * it is stored in \p ctx for future processing.
Gilles Peskined87d8732021-09-13 12:20:51 +0200366 * \param output The buffer where the output is written. It must be
367 * at least `BS * floor((p + input_length) / BS)` bytes
368 * long, where `p` is the number of bytes in the
369 * unprocessed partial block in \p ctx (with
370 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine55dffe52021-09-13 09:33:28 +0200371 * \param output_length On success, the number of bytes written to \p output.
372 * \c 0 on error.
373 *
374 * \return #PSA_SUCCESS or an error from a hardware accelerator
375 */
Ronald Cron6d051732020-10-01 14:10:20 +0200376static psa_status_t psa_cipher_update_ecb(
377 mbedtls_cipher_context_t *ctx,
378 const uint8_t *input,
379 size_t input_length,
380 uint8_t *output,
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200382{
383 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Dave Rodgman85a88132023-06-24 11:41:50 +0100384 size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Ronald Cron6d051732020-10-01 14:10:20 +0200385 size_t internal_output_length = 0;
386 *output_length = 0;
387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200389 status = PSA_SUCCESS;
390 goto exit;
391 }
392
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200394 /* Fill up to block size, and run the block if there's a full one. */
395 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
396
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200398 bytes_to_copy = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 }
Ronald Cron6d051732020-10-01 14:10:20 +0200400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
402 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200403 input_length -= bytes_to_copy;
404 input += bytes_to_copy;
405 ctx->unprocessed_len += bytes_to_copy;
406
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200408 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 mbedtls_cipher_update(ctx,
410 ctx->unprocessed_data,
411 block_size,
412 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200415 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 }
Ronald Cron6d051732020-10-01 14:10:20 +0200417
418 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200419 *output_length += internal_output_length;
420 ctx->unprocessed_len = 0;
421 }
422 }
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200425 /* Run all full blocks we have, one by one */
426 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 mbedtls_cipher_update(ctx, input,
428 block_size,
429 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200432 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 }
Ronald Cron6d051732020-10-01 14:10:20 +0200434
435 input_length -= block_size;
436 input += block_size;
437
438 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200439 *output_length += internal_output_length;
440 }
441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200443 /* Save unprocessed bytes for later processing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
445 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200446 ctx->unprocessed_len += input_length;
447 }
448
449 status = PSA_SUCCESS;
450
451exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200453}
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100454#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200455
Ronald Cron0266cfe2021-03-13 18:50:11 +0100456psa_status_t mbedtls_psa_cipher_update(
457 mbedtls_psa_cipher_operation_t *operation,
458 const uint8_t *input, size_t input_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200460{
461 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
462 size_t expected_output_size;
463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200465 /* Take the unprocessed partial block left over from previous
466 * update calls, if any, plus the input to this call. Remove
467 * the last partial block, if any. You get the data that will be
468 * output in this call. */
469 expected_output_size =
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100471 / operation->block_length * operation->block_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200473 expected_output_size = input_length;
474 }
475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if (output_size < expected_output_size) {
477 return PSA_ERROR_BUFFER_TOO_SMALL;
478 }
Ronald Cron6d051732020-10-01 14:10:20 +0200479
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100480#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200482 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 * process a single block at a time in ECB mode. Abstract away that
484 * inconsistency here to match the PSA API behaviour. */
485 status = psa_cipher_update_ecb(&operation->ctx.cipher,
486 input,
487 input_length,
488 output,
489 output_length);
490 } else
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100491#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200492 {
493 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 mbedtls_cipher_update(&operation->ctx.cipher, input,
495 input_length, output, output_length));
gabor-mezei-arm58c17272021-06-29 16:41:25 +0200496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 if (*output_length > output_size) {
498 return PSA_ERROR_CORRUPTION_DETECTED;
499 }
Ronald Cron6d051732020-10-01 14:10:20 +0200500 }
501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200503}
504
Ronald Cron0266cfe2021-03-13 18:50:11 +0100505psa_status_t mbedtls_psa_cipher_finish(
506 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200508{
509 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
510 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
511
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 if (operation->ctx.cipher.unprocessed_len != 0) {
513 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
514 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200515 status = PSA_ERROR_INVALID_ARGUMENT;
516 goto exit;
517 }
518 }
519
520 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 mbedtls_cipher_finish(&operation->ctx.cipher,
522 temp_output_buffer,
523 output_length));
524 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200525 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 }
Ronald Cron6d051732020-10-01 14:10:20 +0200527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200529 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 } else if (output_size >= *output_length) {
531 memcpy(output, temp_output_buffer, *output_length);
532 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200533 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 }
Ronald Cron6d051732020-10-01 14:10:20 +0200535
536exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 mbedtls_platform_zeroize(temp_output_buffer,
538 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200539
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200541}
542
Ronald Cron0266cfe2021-03-13 18:50:11 +0100543psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200545{
Ronald Cron937dfee2021-03-10 09:17:32 +0100546 /* Sanity check (shouldn't happen: operation->alg should
547 * always have been initialized to a valid value). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
549 return PSA_ERROR_BAD_STATE;
550 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200553
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200555}
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100556
Ronald Cron0266cfe2021-03-13 18:50:11 +0100557psa_status_t mbedtls_psa_cipher_encrypt(
558 const psa_key_attributes_t *attributes,
559 const uint8_t *key_buffer,
560 size_t key_buffer_size,
561 psa_algorithm_t alg,
Ronald Cron9b674282021-07-09 09:19:35 +0200562 const uint8_t *iv,
563 size_t iv_length,
Ronald Cron0266cfe2021-03-13 18:50:11 +0100564 const uint8_t *input,
565 size_t input_length,
566 uint8_t *output,
567 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100569{
570 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
571 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Cron8188d192021-12-14 10:58:18 +0100572 size_t update_output_length, finish_output_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
575 key_buffer, key_buffer_size,
576 alg);
577 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100578 goto exit;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100579 }
580
Gilles Peskine449bd832023-01-11 14:50:10 +0100581 if (iv_length > 0) {
582 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
583 if (status != PSA_SUCCESS) {
584 goto exit;
585 }
586 }
587
588 status = mbedtls_psa_cipher_update(&operation, input, input_length,
589 output, output_size,
590 &update_output_length);
591 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100592 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100594
Gilles Peskine42649d92022-11-23 14:15:57 +0100595 status = mbedtls_psa_cipher_finish(
596 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 mbedtls_buffer_offset(output, update_output_length),
598 output_size - update_output_length, &finish_output_length);
599 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100600 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100602
Ronald Cron8188d192021-12-14 10:58:18 +0100603 *output_length = update_output_length + finish_output_length;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200604
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100605exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 if (status == PSA_SUCCESS) {
607 status = mbedtls_psa_cipher_abort(&operation);
608 } else {
609 mbedtls_psa_cipher_abort(&operation);
610 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100613}
614
Ronald Cron0266cfe2021-03-13 18:50:11 +0100615psa_status_t mbedtls_psa_cipher_decrypt(
616 const psa_key_attributes_t *attributes,
617 const uint8_t *key_buffer,
618 size_t key_buffer_size,
619 psa_algorithm_t alg,
620 const uint8_t *input,
621 size_t input_length,
622 uint8_t *output,
623 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100625{
626 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
627 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200628 size_t olength, accumulated_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100629
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
631 key_buffer, key_buffer_size,
632 alg);
633 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100634 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 if (operation.iv_length > 0) {
638 status = mbedtls_psa_cipher_set_iv(&operation,
639 input, operation.iv_length);
640 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100641 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100643 }
644
Gilles Peskine42649d92022-11-23 14:15:57 +0100645 status = mbedtls_psa_cipher_update(
646 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine42649d92022-11-23 14:15:57 +0100648 input_length - operation.iv_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 output, output_size, &olength);
650 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100651 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100652 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100653
gabor-mezei-arm6158e282021-06-29 16:42:13 +0200654 accumulated_length = olength;
gabor-mezei-arm258ae072021-06-25 15:25:38 +0200655
Gilles Peskine42649d92022-11-23 14:15:57 +0100656 status = mbedtls_psa_cipher_finish(
657 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 mbedtls_buffer_offset(output, accumulated_length),
659 output_size - accumulated_length, &olength);
660 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100661 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100663
gabor-mezei-arm00e54f12021-06-29 19:06:30 +0200664 *output_length = accumulated_length + olength;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200665
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100666exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100667 if (status == PSA_SUCCESS) {
668 status = mbedtls_psa_cipher_abort(&operation);
669 } else {
670 mbedtls_psa_cipher_abort(&operation);
671 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100672
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100674}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100675#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100676
Ronald Cron0ff57952021-03-08 16:46:35 +0100677#endif /* MBEDTLS_PSA_CRYPTO_C */