blob: 7e81dfee79dc0212c8d64c44914ea9a0dc9ce8f0 [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 Setti4a249822023-10-18 12:34:54 +020034psa_status_t mbedtls_cipher_values_from_psa(
Ronald Cron75e6ae22021-03-17 14:46:05 +010035 psa_algorithm_t alg,
36 psa_key_type_t key_type,
Valerio Setti4a249822023-10-18 12:34:54 +020037 size_t *key_bits,
38 mbedtls_cipher_mode_t *mode,
Gilles Peskine449bd832023-01-11 14:50:10 +010039 mbedtls_cipher_id_t *cipher_id)
Ronald Cron75e6ae22021-03-17 14:46:05 +010040{
Ronald Cron75e6ae22021-03-17 14:46:05 +010041 mbedtls_cipher_id_t cipher_id_tmp;
Valerio Setti4a249822023-10-18 12:34:54 +020042 (void) key_bits;
Ronald Cron75e6ae22021-03-17 14:46:05 +010043
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:
Valerio Setti4a249822023-10-18 12:34:54 +020052 *mode = MBEDTLS_MODE_STREAM;
Ronald Cron75e6ae22021-03-17 14:46:05 +010053 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:
Valerio Setti4a249822023-10-18 12:34:54 +020057 *mode = MBEDTLS_MODE_CTR;
Ronald Cron75e6ae22021-03-17 14:46:05 +010058 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:
Valerio Setti4a249822023-10-18 12:34:54 +020062 *mode = MBEDTLS_MODE_CFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +010063 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:
Valerio Setti4a249822023-10-18 12:34:54 +020067 *mode = MBEDTLS_MODE_OFB;
Ronald Cron75e6ae22021-03-17 14:46:05 +010068 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:
Valerio Setti4a249822023-10-18 12:34:54 +020072 *mode = MBEDTLS_MODE_ECB;
Ronald Cron75e6ae22021-03-17 14:46:05 +010073 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:
Valerio Setti4a249822023-10-18 12:34:54 +020077 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +010078 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:
Valerio Setti4a249822023-10-18 12:34:54 +020082 *mode = MBEDTLS_MODE_CBC;
Ronald Cron75e6ae22021-03-17 14:46:05 +010083 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:
Valerio Setti4a249822023-10-18 12:34:54 +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):
Valerio Setti4a249822023-10-18 12:34:54 +020092 *mode = MBEDTLS_MODE_CCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +010093 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):
Valerio Setti4a249822023-10-18 12:34:54 +020097 *mode = MBEDTLS_MODE_GCM;
Ronald Cron75e6ae22021-03-17 14:46:05 +010098 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):
Valerio Setti4a249822023-10-18 12:34:54 +0200102 *mode = MBEDTLS_MODE_CHACHAPOLY;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100103 break;
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100104#endif
Ronald Cron75e6ae22021-03-17 14:46:05 +0100105 default:
Valerio Setti4a249822023-10-18 12:34:54 +0200106 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron75e6ae22021-03-17 14:46:05 +0100107 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 } else if (alg == PSA_ALG_CMAC) {
Valerio Setti4a249822023-10-18 12:34:54 +0200109 *mode = MBEDTLS_MODE_ECB;
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 } else {
Valerio Setti4a249822023-10-18 12:34:54 +0200111 return PSA_ERROR_NOT_SUPPORTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 }
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. */
Valerio Setti4a249822023-10-18 12:34:54 +0200129 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. */
Valerio Setti4a249822023-10-18 12:34:54 +0200137 if (*key_bits == 128) {
138 *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:
Valerio Setti4a249822023-10-18 12:34:54 +0200153 return PSA_ERROR_NOT_SUPPORTED;
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
Valerio Setti4a249822023-10-18 12:34:54 +0200159 return PSA_SUCCESS;
160}
161
162#if defined(MBEDTLS_CIPHER_C)
163const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
164 psa_algorithm_t alg,
165 psa_key_type_t key_type,
166 size_t key_bits,
167 mbedtls_cipher_id_t *cipher_id)
168{
169 mbedtls_cipher_mode_t mode;
170 psa_status_t status;
171 mbedtls_cipher_id_t cipher_id_tmp;
172
173 status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
174 if (status != PSA_SUCCESS) {
175 return NULL;
176 }
177 if (cipher_id != NULL) {
178 *cipher_id = cipher_id_tmp;
179 }
180
181 return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
Ronald Cron75e6ae22021-03-17 14:46:05 +0100182}
Valerio Setti2c2aded2023-08-25 09:22:19 +0200183#endif /* MBEDTLS_CIPHER_C */
Ronald Cron75e6ae22021-03-17 14:46:05 +0100184
Ronald Cron0266cfe2021-03-13 18:50:11 +0100185#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100186
Ronald Cron0266cfe2021-03-13 18:50:11 +0100187static psa_status_t psa_cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100188 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100189 const psa_key_attributes_t *attributes,
190 const uint8_t *key_buffer, size_t key_buffer_size,
191 psa_algorithm_t alg,
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 mbedtls_operation_t cipher_operation)
Ronald Crond6d28882020-12-14 14:56:02 +0100193{
194 int ret = 0;
195 size_t key_bits;
196 const mbedtls_cipher_info_t *cipher_info = NULL;
197 psa_key_type_t key_type = attributes->core.type;
198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 (void) key_buffer_size;
Ronald Crond6d28882020-12-14 14:56:02 +0100200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 mbedtls_cipher_init(&operation->ctx.cipher);
Ronald Crond6d28882020-12-14 14:56:02 +0100202
Ronald Cron6e412a72021-03-10 09:58:47 +0100203 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +0100204 key_bits = attributes->core.bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
206 key_bits, NULL);
207 if (cipher_info == NULL) {
208 return PSA_ERROR_NOT_SUPPORTED;
209 }
Ronald Crond6d28882020-12-14 14:56:02 +0100210
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
212 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100213 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 }
Ronald Crond6d28882020-12-14 14:56:02 +0100215
Ronald Cron0266cfe2021-03-13 18:50:11 +0100216#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
Ronald Crond6d28882020-12-14 14:56:02 +0100218 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
219 uint8_t keys[24];
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 memcpy(keys, key_buffer, 16);
221 memcpy(keys + 16, key_buffer, 8);
222 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
223 keys,
224 192, cipher_operation);
225 } else
Ronald Crond6d28882020-12-14 14:56:02 +0100226#endif
227 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
229 (int) key_bits, cipher_operation);
Ronald Crond6d28882020-12-14 14:56:02 +0100230 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100232 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 }
Ronald Crond6d28882020-12-14 14:56:02 +0100234
Ronald Cron0266cfe2021-03-13 18:50:11 +0100235#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
236 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 switch (alg) {
Ronald Crond6d28882020-12-14 14:56:02 +0100238 case PSA_ALG_CBC_NO_PADDING:
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
240 MBEDTLS_PADDING_NONE);
Ronald Crond6d28882020-12-14 14:56:02 +0100241 break;
242 case PSA_ALG_CBC_PKCS7:
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
244 MBEDTLS_PADDING_PKCS7);
Ronald Crond6d28882020-12-14 14:56:02 +0100245 break;
246 default:
247 /* The algorithm doesn't involve padding. */
248 ret = 0;
249 break;
250 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 if (ret != 0) {
Ronald Crond6d28882020-12-14 14:56:02 +0100252 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100254#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
255 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
Ronald Crond6d28882020-12-14 14:56:02 +0100256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
258 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
259 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
Ronald Crond6d28882020-12-14 14:56:02 +0100260
261exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 return mbedtls_to_psa_error(ret);
Ronald Crond6d28882020-12-14 14:56:02 +0100263}
264
Ronald Cron0266cfe2021-03-13 18:50:11 +0100265psa_status_t mbedtls_psa_cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100266 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100267 const psa_key_attributes_t *attributes,
268 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100270{
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 return psa_cipher_setup(operation, attributes,
272 key_buffer, key_buffer_size,
273 alg, MBEDTLS_ENCRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100274}
275
Ronald Cron0266cfe2021-03-13 18:50:11 +0100276psa_status_t mbedtls_psa_cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100277 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100278 const psa_key_attributes_t *attributes,
279 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 psa_algorithm_t alg)
Ronald Crond6d28882020-12-14 14:56:02 +0100281{
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 return psa_cipher_setup(operation, attributes,
283 key_buffer, key_buffer_size,
284 alg, MBEDTLS_DECRYPT);
Ronald Crond6d28882020-12-14 14:56:02 +0100285}
Ronald Cron6d051732020-10-01 14:10:20 +0200286
Ronald Cron0266cfe2021-03-13 18:50:11 +0100287psa_status_t mbedtls_psa_cipher_set_iv(
288 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 const uint8_t *iv, size_t iv_length)
Ronald Cron8287e6b2021-03-12 10:35:18 +0100290{
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if (iv_length != operation->iv_length) {
292 return PSA_ERROR_INVALID_ARGUMENT;
293 }
Ronald Cron8287e6b2021-03-12 10:35:18 +0100294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 return mbedtls_to_psa_error(
296 mbedtls_cipher_set_iv(&operation->ctx.cipher,
297 iv, iv_length));
Ronald Cron8287e6b2021-03-12 10:35:18 +0100298}
299
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100300#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine55dffe52021-09-13 09:33:28 +0200301/** Process input for which the algorithm is set to ECB mode.
302 *
303 * This requires manual processing, since the PSA API is defined as being
304 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
305 * but the underlying mbedtls_cipher_update only takes full blocks.
306 *
307 * \param ctx The mbedtls cipher context to use. It must have been
308 * set up for ECB.
309 * \param[in] input The input plaintext or ciphertext to process.
310 * \param input_length The number of bytes to process from \p input.
311 * This does not need to be aligned to a block boundary.
312 * If there is a partial block at the end of the input,
313 * it is stored in \p ctx for future processing.
Gilles Peskined87d8732021-09-13 12:20:51 +0200314 * \param output The buffer where the output is written. It must be
315 * at least `BS * floor((p + input_length) / BS)` bytes
316 * long, where `p` is the number of bytes in the
317 * unprocessed partial block in \p ctx (with
318 * `0 <= p <= BS - 1`) and `BS` is the block size.
Gilles Peskine55dffe52021-09-13 09:33:28 +0200319 * \param output_length On success, the number of bytes written to \p output.
320 * \c 0 on error.
321 *
322 * \return #PSA_SUCCESS or an error from a hardware accelerator
323 */
Ronald Cron6d051732020-10-01 14:10:20 +0200324static psa_status_t psa_cipher_update_ecb(
325 mbedtls_cipher_context_t *ctx,
326 const uint8_t *input,
327 size_t input_length,
328 uint8_t *output,
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200330{
331 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Dave Rodgman85a88132023-06-24 11:41:50 +0100332 size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Ronald Cron6d051732020-10-01 14:10:20 +0200333 size_t internal_output_length = 0;
334 *output_length = 0;
335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 if (input_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200337 status = PSA_SUCCESS;
338 goto exit;
339 }
340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (ctx->unprocessed_len > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200342 /* Fill up to block size, and run the block if there's a full one. */
343 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 if (input_length < bytes_to_copy) {
Ronald Cron6d051732020-10-01 14:10:20 +0200346 bytes_to_copy = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 }
Ronald Cron6d051732020-10-01 14:10:20 +0200348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
350 input, bytes_to_copy);
Ronald Cron6d051732020-10-01 14:10:20 +0200351 input_length -= bytes_to_copy;
352 input += bytes_to_copy;
353 ctx->unprocessed_len += bytes_to_copy;
354
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 if (ctx->unprocessed_len == block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200356 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 mbedtls_cipher_update(ctx,
358 ctx->unprocessed_data,
359 block_size,
360 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200363 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 }
Ronald Cron6d051732020-10-01 14:10:20 +0200365
366 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200367 *output_length += internal_output_length;
368 ctx->unprocessed_len = 0;
369 }
370 }
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 while (input_length >= block_size) {
Ronald Cron6d051732020-10-01 14:10:20 +0200373 /* Run all full blocks we have, one by one */
374 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 mbedtls_cipher_update(ctx, input,
376 block_size,
377 output, &internal_output_length));
Ronald Cron6d051732020-10-01 14:10:20 +0200378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200380 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 }
Ronald Cron6d051732020-10-01 14:10:20 +0200382
383 input_length -= block_size;
384 input += block_size;
385
386 output += internal_output_length;
Ronald Cron6d051732020-10-01 14:10:20 +0200387 *output_length += internal_output_length;
388 }
389
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 if (input_length > 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200391 /* Save unprocessed bytes for later processing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
393 input, input_length);
Ronald Cron6d051732020-10-01 14:10:20 +0200394 ctx->unprocessed_len += input_length;
395 }
396
397 status = PSA_SUCCESS;
398
399exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200401}
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100402#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200403
Ronald Cron0266cfe2021-03-13 18:50:11 +0100404psa_status_t mbedtls_psa_cipher_update(
405 mbedtls_psa_cipher_operation_t *operation,
406 const uint8_t *input, size_t input_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200408{
409 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
410 size_t expected_output_size;
411
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
Ronald Cron6d051732020-10-01 14:10:20 +0200413 /* Take the unprocessed partial block left over from previous
414 * update calls, if any, plus the input to this call. Remove
415 * the last partial block, if any. You get the data that will be
416 * output in this call. */
417 expected_output_size =
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 (operation->ctx.cipher.unprocessed_len + input_length)
Ronald Cron6ad554c2021-03-26 09:29:09 +0100419 / operation->block_length * operation->block_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200421 expected_output_size = input_length;
422 }
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (output_size < expected_output_size) {
425 return PSA_ERROR_BUFFER_TOO_SMALL;
426 }
Ronald Cron6d051732020-10-01 14:10:20 +0200427
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100428#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200430 /* mbedtls_cipher_update has an API inconsistency: it will only
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 * process a single block at a time in ECB mode. Abstract away that
432 * inconsistency here to match the PSA API behaviour. */
433 status = psa_cipher_update_ecb(&operation->ctx.cipher,
434 input,
435 input_length,
436 output,
437 output_length);
438 } else
Gilles Peskine695c4cb2022-03-16 12:25:17 +0100439#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
Ronald Cron6d051732020-10-01 14:10:20 +0200440 {
441 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 mbedtls_cipher_update(&operation->ctx.cipher, input,
443 input_length, output, output_length));
gabor-mezei-arm58c17272021-06-29 16:41:25 +0200444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 if (*output_length > output_size) {
446 return PSA_ERROR_CORRUPTION_DETECTED;
447 }
Ronald Cron6d051732020-10-01 14:10:20 +0200448 }
449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200451}
452
Ronald Cron0266cfe2021-03-13 18:50:11 +0100453psa_status_t mbedtls_psa_cipher_finish(
454 mbedtls_psa_cipher_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 uint8_t *output, size_t output_size, size_t *output_length)
Ronald Cron6d051732020-10-01 14:10:20 +0200456{
457 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
458 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
459
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 if (operation->ctx.cipher.unprocessed_len != 0) {
461 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
462 operation->alg == PSA_ALG_CBC_NO_PADDING) {
Ronald Cron6d051732020-10-01 14:10:20 +0200463 status = PSA_ERROR_INVALID_ARGUMENT;
464 goto exit;
465 }
466 }
467
468 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 mbedtls_cipher_finish(&operation->ctx.cipher,
470 temp_output_buffer,
471 output_length));
472 if (status != PSA_SUCCESS) {
Ronald Cron6d051732020-10-01 14:10:20 +0200473 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 }
Ronald Cron6d051732020-10-01 14:10:20 +0200475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if (*output_length == 0) {
Ronald Cron6d051732020-10-01 14:10:20 +0200477 ; /* Nothing to copy. Note that output may be NULL in this case. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 } else if (output_size >= *output_length) {
479 memcpy(output, temp_output_buffer, *output_length);
480 } else {
Ronald Cron6d051732020-10-01 14:10:20 +0200481 status = PSA_ERROR_BUFFER_TOO_SMALL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 }
Ronald Cron6d051732020-10-01 14:10:20 +0200483
484exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 mbedtls_platform_zeroize(temp_output_buffer,
486 sizeof(temp_output_buffer));
Ronald Cron6d051732020-10-01 14:10:20 +0200487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 return status;
Ronald Cron6d051732020-10-01 14:10:20 +0200489}
490
Ronald Cron0266cfe2021-03-13 18:50:11 +0100491psa_status_t mbedtls_psa_cipher_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 mbedtls_psa_cipher_operation_t *operation)
Ronald Cron6d051732020-10-01 14:10:20 +0200493{
Ronald Cron937dfee2021-03-10 09:17:32 +0100494 /* Sanity check (shouldn't happen: operation->alg should
495 * always have been initialized to a valid value). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
497 return PSA_ERROR_BAD_STATE;
498 }
Ronald Cron937dfee2021-03-10 09:17:32 +0100499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 mbedtls_cipher_free(&operation->ctx.cipher);
Ronald Cron6d051732020-10-01 14:10:20 +0200501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 return PSA_SUCCESS;
Ronald Cron6d051732020-10-01 14:10:20 +0200503}
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100504
Ronald Cron0266cfe2021-03-13 18:50:11 +0100505psa_status_t mbedtls_psa_cipher_encrypt(
506 const psa_key_attributes_t *attributes,
507 const uint8_t *key_buffer,
508 size_t key_buffer_size,
509 psa_algorithm_t alg,
Ronald Cron9b674282021-07-09 09:19:35 +0200510 const uint8_t *iv,
511 size_t iv_length,
Ronald Cron0266cfe2021-03-13 18:50:11 +0100512 const uint8_t *input,
513 size_t input_length,
514 uint8_t *output,
515 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100517{
518 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
519 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
Ronald Cron8188d192021-12-14 10:58:18 +0100520 size_t update_output_length, finish_output_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100521
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
523 key_buffer, key_buffer_size,
524 alg);
525 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100526 goto exit;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100527 }
528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 if (iv_length > 0) {
530 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
531 if (status != PSA_SUCCESS) {
532 goto exit;
533 }
534 }
535
536 status = mbedtls_psa_cipher_update(&operation, input, input_length,
537 output, output_size,
538 &update_output_length);
539 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100540 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100542
Gilles Peskine42649d92022-11-23 14:15:57 +0100543 status = mbedtls_psa_cipher_finish(
544 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 mbedtls_buffer_offset(output, update_output_length),
546 output_size - update_output_length, &finish_output_length);
547 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100548 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100550
Ronald Cron8188d192021-12-14 10:58:18 +0100551 *output_length = update_output_length + finish_output_length;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200552
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100553exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 if (status == PSA_SUCCESS) {
555 status = mbedtls_psa_cipher_abort(&operation);
556 } else {
557 mbedtls_psa_cipher_abort(&operation);
558 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100561}
562
Ronald Cron0266cfe2021-03-13 18:50:11 +0100563psa_status_t mbedtls_psa_cipher_decrypt(
564 const psa_key_attributes_t *attributes,
565 const uint8_t *key_buffer,
566 size_t key_buffer_size,
567 psa_algorithm_t alg,
568 const uint8_t *input,
569 size_t input_length,
570 uint8_t *output,
571 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 size_t *output_length)
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100573{
574 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
575 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200576 size_t olength, accumulated_length;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100577
Gilles Peskine449bd832023-01-11 14:50:10 +0100578 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
579 key_buffer, key_buffer_size,
580 alg);
581 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100582 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100584
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 if (operation.iv_length > 0) {
586 status = mbedtls_psa_cipher_set_iv(&operation,
587 input, operation.iv_length);
588 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100589 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100590 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100591 }
592
Gilles Peskine42649d92022-11-23 14:15:57 +0100593 status = mbedtls_psa_cipher_update(
594 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100595 mbedtls_buffer_offset_const(input, operation.iv_length),
Gilles Peskine42649d92022-11-23 14:15:57 +0100596 input_length - operation.iv_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 output, output_size, &olength);
598 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100599 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100601
gabor-mezei-arm6158e282021-06-29 16:42:13 +0200602 accumulated_length = olength;
gabor-mezei-arm258ae072021-06-25 15:25:38 +0200603
Gilles Peskine42649d92022-11-23 14:15:57 +0100604 status = mbedtls_psa_cipher_finish(
605 &operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 mbedtls_buffer_offset(output, accumulated_length),
607 output_size - accumulated_length, &olength);
608 if (status != PSA_SUCCESS) {
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100609 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 }
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100611
gabor-mezei-arm00e54f12021-06-29 19:06:30 +0200612 *output_length = accumulated_length + olength;
gabor-mezei-arme5ff8f42021-06-25 15:23:05 +0200613
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100614exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (status == PSA_SUCCESS) {
616 status = mbedtls_psa_cipher_abort(&operation);
617 } else {
618 mbedtls_psa_cipher_abort(&operation);
619 }
Ronald Cron0266cfe2021-03-13 18:50:11 +0100620
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 return status;
gabor-mezei-arma9449a02021-03-25 11:17:10 +0100622}
Ronald Cron5d9b00d2021-03-10 14:43:20 +0100623#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
Ronald Cron8287e6b2021-03-12 10:35:18 +0100624
Ronald Cron0ff57952021-03-08 16:46:35 +0100625#endif /* MBEDTLS_PSA_CRYPTO_C */