blob: a201985b4f0678ba881f4689222106421fa9789c [file] [log] [blame]
Ronald Cron7ceee8d2021-03-17 16:55:43 +01001/*
2 * PSA AEAD entry points
3 */
4/*
5 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Ronald Cron7ceee8d2021-03-17 16:55:43 +01007 */
8
9#include "common.h"
10
11#if defined(MBEDTLS_PSA_CRYPTO_C)
12
13#include "psa_crypto_aead.h"
Ronald Cron46f91782021-03-17 08:16:34 +010014#include "psa_crypto_core.h"
Dave Rodgman16304472022-11-02 09:25:38 +000015#include "psa_crypto_cipher.h"
Ronald Cron46f91782021-03-17 08:16:34 +010016
Paul Elliottadb8b162021-04-20 16:06:57 +010017#include <string.h>
18#include "mbedtls/platform.h"
Paul Elliottadb8b162021-04-20 16:06:57 +010019
Ronald Cron46f91782021-03-17 08:16:34 +010020#include "mbedtls/ccm.h"
21#include "mbedtls/chachapoly.h"
22#include "mbedtls/cipher.h"
23#include "mbedtls/gcm.h"
Paul Elliottadb8b162021-04-20 16:06:57 +010024#include "mbedtls/error.h"
Ronald Cron46f91782021-03-17 08:16:34 +010025
Ronald Cron46f91782021-03-17 08:16:34 +010026static psa_status_t psa_aead_setup(
Paul Elliottcbbde5f2021-05-10 18:19:46 +010027 mbedtls_psa_aead_operation_t *operation,
Ronald Cron46f91782021-03-17 08:16:34 +010028 const psa_key_attributes_t *attributes,
29 const uint8_t *key_buffer,
Paul Elliottcc358592021-05-12 12:22:28 +010030 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +010031 psa_algorithm_t alg)
Ronald Cron46f91782021-03-17 08:16:34 +010032{
33 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Valerio Setti4a249822023-10-18 12:34:54 +020034 mbedtls_cipher_id_t cipher_id;
35 mbedtls_cipher_mode_t mode;
Gilles Peskine2f107ae2024-02-28 01:26:46 +010036 size_t key_bits = attributes->bits;
Gilles Peskine449bd832023-01-11 14:50:10 +010037 (void) key_buffer_size;
Paul Elliottcc358592021-05-12 12:22:28 +010038
Gilles Peskine2f107ae2024-02-28 01:26:46 +010039 status = mbedtls_cipher_values_from_psa(alg, attributes->type,
Valerio Setti4a249822023-10-18 12:34:54 +020040 &key_bits, &mode, &cipher_id);
41 if (status != PSA_SUCCESS) {
42 return status;
Gilles Peskine449bd832023-01-11 14:50:10 +010043 }
Ronald Cron46f91782021-03-17 08:16:34 +010044
Gilles Peskine449bd832023-01-11 14:50:10 +010045 switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
Ronald Cron46f91782021-03-17 08:16:34 +010046#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010047 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010048 operation->alg = PSA_ALG_CCM;
Ronald Cron46f91782021-03-17 08:16:34 +010049 /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
50 * The call to mbedtls_ccm_encrypt_and_tag or
51 * mbedtls_ccm_auth_decrypt will validate the tag length. */
Gilles Peskine2f107ae2024-02-28 01:26:46 +010052 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010053 return PSA_ERROR_INVALID_ARGUMENT;
54 }
Ronald Cron46f91782021-03-17 08:16:34 +010055
Gilles Peskine449bd832023-01-11 14:50:10 +010056 mbedtls_ccm_init(&operation->ctx.ccm);
Ronald Cron46f91782021-03-17 08:16:34 +010057 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +010058 mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
59 key_buffer, (unsigned int) key_bits));
60 if (status != PSA_SUCCESS) {
61 return status;
62 }
Ronald Cron46f91782021-03-17 08:16:34 +010063 break;
64#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
65
66#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010067 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010068 operation->alg = PSA_ALG_GCM;
Ronald Cron46f91782021-03-17 08:16:34 +010069 /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
70 * The call to mbedtls_gcm_crypt_and_tag or
71 * mbedtls_gcm_auth_decrypt will validate the tag length. */
Gilles Peskine2f107ae2024-02-28 01:26:46 +010072 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010073 return PSA_ERROR_INVALID_ARGUMENT;
74 }
Ronald Cron46f91782021-03-17 08:16:34 +010075
Gilles Peskine449bd832023-01-11 14:50:10 +010076 mbedtls_gcm_init(&operation->ctx.gcm);
Ronald Cron46f91782021-03-17 08:16:34 +010077 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +010078 mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
79 key_buffer, (unsigned int) key_bits));
80 if (status != PSA_SUCCESS) {
81 return status;
82 }
Ronald Cron46f91782021-03-17 08:16:34 +010083 break;
84#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
85
86#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +010087 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010088 operation->alg = PSA_ALG_CHACHA20_POLY1305;
Ronald Cron46f91782021-03-17 08:16:34 +010089 /* We only support the default tag length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010090 if (alg != PSA_ALG_CHACHA20_POLY1305) {
91 return PSA_ERROR_NOT_SUPPORTED;
92 }
Ronald Cron46f91782021-03-17 08:16:34 +010093
Gilles Peskine449bd832023-01-11 14:50:10 +010094 mbedtls_chachapoly_init(&operation->ctx.chachapoly);
Ronald Cron46f91782021-03-17 08:16:34 +010095 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +010096 mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
97 key_buffer));
98 if (status != PSA_SUCCESS) {
99 return status;
100 }
Ronald Cron46f91782021-03-17 08:16:34 +0100101 break;
102#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
103
104 default:
Ronald Cron7a55deb2021-04-28 14:29:00 +0200105 (void) status;
106 (void) key_buffer;
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100108 }
109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 operation->key_type = psa_get_key_type(attributes);
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100111
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
Ronald Cron46f91782021-03-17 08:16:34 +0100113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 return PSA_SUCCESS;
Ronald Cron46f91782021-03-17 08:16:34 +0100115}
116
117psa_status_t mbedtls_psa_aead_encrypt(
118 const psa_key_attributes_t *attributes,
119 const uint8_t *key_buffer, size_t key_buffer_size,
120 psa_algorithm_t alg,
121 const uint8_t *nonce, size_t nonce_length,
122 const uint8_t *additional_data, size_t additional_data_length,
123 const uint8_t *plaintext, size_t plaintext_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100124 uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
Ronald Cron46f91782021-03-17 08:16:34 +0100125{
126 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100127 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100128 uint8_t *tag;
Ronald Cron46f91782021-03-17 08:16:34 +0100129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 status = psa_aead_setup(&operation, attributes, key_buffer,
131 key_buffer_size, alg);
Paul Elliottcc358592021-05-12 12:22:28 +0100132
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100134 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 }
Ronald Cron46f91782021-03-17 08:16:34 +0100136
137 /* For all currently supported modes, the tag is at the end of the
138 * ciphertext. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 if (ciphertext_size < (plaintext_length + operation.tag_length)) {
Ronald Cron46f91782021-03-17 08:16:34 +0100140 status = PSA_ERROR_BUFFER_TOO_SMALL;
141 goto exit;
142 }
143 tag = ciphertext + plaintext_length;
144
Ronald Cron46f91782021-03-17 08:16:34 +0100145#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 if (operation.alg == PSA_ALG_CCM) {
Ronald Cron46f91782021-03-17 08:16:34 +0100147 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
149 plaintext_length,
150 nonce, nonce_length,
151 additional_data,
152 additional_data_length,
153 plaintext, ciphertext,
154 tag, operation.tag_length));
155 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100156#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200157#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 if (operation.alg == PSA_ALG_GCM) {
Ronald Cron810eb162021-04-06 09:01:39 +0200159 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
161 MBEDTLS_GCM_ENCRYPT,
162 plaintext_length,
163 nonce, nonce_length,
164 additional_data, additional_data_length,
165 plaintext, ciphertext,
166 operation.tag_length, tag));
167 } else
Ronald Cron810eb162021-04-06 09:01:39 +0200168#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100169#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
171 if (operation.tag_length != 16) {
Ronald Cron46f91782021-03-17 08:16:34 +0100172 status = PSA_ERROR_NOT_SUPPORTED;
173 goto exit;
174 }
175 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
177 plaintext_length,
178 nonce,
179 additional_data,
180 additional_data_length,
181 plaintext,
182 ciphertext,
183 tag));
184 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100185#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
186 {
187 (void) tag;
Ronald Cron7a55deb2021-04-28 14:29:00 +0200188 (void) nonce;
189 (void) nonce_length;
190 (void) additional_data;
191 (void) additional_data_length;
192 (void) plaintext;
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100194 }
195
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100197 *ciphertext_length = plaintext_length + operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 }
Ronald Cron46f91782021-03-17 08:16:34 +0100199
200exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 mbedtls_psa_aead_abort(&operation);
Ronald Cron46f91782021-03-17 08:16:34 +0100202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 return status;
Ronald Cron46f91782021-03-17 08:16:34 +0100204}
205
206/* Locate the tag in a ciphertext buffer containing the encrypted data
207 * followed by the tag. Return the length of the part preceding the tag in
208 * *plaintext_length. This is the size of the plaintext in modes where
209 * the encrypted data has the same size as the plaintext, such as
210 * CCM and GCM. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100211static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
212 const uint8_t *ciphertext,
213 size_t ciphertext_length,
214 size_t plaintext_size,
215 const uint8_t **p_tag)
Ronald Cron46f91782021-03-17 08:16:34 +0100216{
217 size_t payload_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 if (tag_length > ciphertext_length) {
219 return PSA_ERROR_INVALID_ARGUMENT;
220 }
Ronald Cron46f91782021-03-17 08:16:34 +0100221 payload_length = ciphertext_length - tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if (payload_length > plaintext_size) {
223 return PSA_ERROR_BUFFER_TOO_SMALL;
224 }
Ronald Cron46f91782021-03-17 08:16:34 +0100225 *p_tag = ciphertext + payload_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 return PSA_SUCCESS;
Ronald Cron46f91782021-03-17 08:16:34 +0100227}
228
229psa_status_t mbedtls_psa_aead_decrypt(
230 const psa_key_attributes_t *attributes,
231 const uint8_t *key_buffer, size_t key_buffer_size,
232 psa_algorithm_t alg,
233 const uint8_t *nonce, size_t nonce_length,
234 const uint8_t *additional_data, size_t additional_data_length,
235 const uint8_t *ciphertext, size_t ciphertext_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
Ronald Cron46f91782021-03-17 08:16:34 +0100237{
238 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100239 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100240 const uint8_t *tag = NULL;
Ronald Cron46f91782021-03-17 08:16:34 +0100241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 status = psa_aead_setup(&operation, attributes, key_buffer,
243 key_buffer_size, alg);
Paul Elliottcc358592021-05-12 12:22:28 +0100244
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100246 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 }
Ronald Cron46f91782021-03-17 08:16:34 +0100248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 status = psa_aead_unpadded_locate_tag(operation.tag_length,
250 ciphertext, ciphertext_length,
251 plaintext_size, &tag);
252 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100253 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 }
Ronald Cron46f91782021-03-17 08:16:34 +0100255
Ronald Cron46f91782021-03-17 08:16:34 +0100256#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 if (operation.alg == PSA_ALG_CCM) {
Ronald Cron46f91782021-03-17 08:16:34 +0100258 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
260 ciphertext_length - operation.tag_length,
261 nonce, nonce_length,
262 additional_data,
263 additional_data_length,
264 ciphertext, plaintext,
265 tag, operation.tag_length));
266 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100267#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200268#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 if (operation.alg == PSA_ALG_GCM) {
Ronald Cron810eb162021-04-06 09:01:39 +0200270 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
272 ciphertext_length - operation.tag_length,
273 nonce, nonce_length,
274 additional_data,
275 additional_data_length,
276 tag, operation.tag_length,
277 ciphertext, plaintext));
278 } else
Ronald Cron810eb162021-04-06 09:01:39 +0200279#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100280#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
282 if (operation.tag_length != 16) {
Ronald Cron46f91782021-03-17 08:16:34 +0100283 status = PSA_ERROR_NOT_SUPPORTED;
284 goto exit;
285 }
286 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
288 ciphertext_length - operation.tag_length,
289 nonce,
290 additional_data,
291 additional_data_length,
292 tag,
293 ciphertext,
294 plaintext));
295 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100296#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
297 {
Ronald Cron7a55deb2021-04-28 14:29:00 +0200298 (void) nonce;
299 (void) nonce_length;
300 (void) additional_data;
301 (void) additional_data_length;
302 (void) plaintext;
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100304 }
305
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100307 *plaintext_length = ciphertext_length - operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 }
Ronald Cron46f91782021-03-17 08:16:34 +0100309
310exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 mbedtls_psa_aead_abort(&operation);
Ronald Cron46f91782021-03-17 08:16:34 +0100312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100314 *plaintext_length = ciphertext_length - operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 }
316 return status;
Ronald Cron46f91782021-03-17 08:16:34 +0100317}
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100318
Paul Elliottadb8b162021-04-20 16:06:57 +0100319/* Set the key and algorithm for a multipart authenticated encryption
320 * operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100321psa_status_t mbedtls_psa_aead_encrypt_setup(
322 mbedtls_psa_aead_operation_t *operation,
323 const psa_key_attributes_t *attributes,
324 const uint8_t *key_buffer,
325 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 psa_algorithm_t alg)
Paul Elliottadb8b162021-04-20 16:06:57 +0100327{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100328 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 status = psa_aead_setup(operation, attributes, key_buffer,
331 key_buffer_size, alg);
Paul Elliottadb8b162021-04-20 16:06:57 +0100332
Gilles Peskine449bd832023-01-11 14:50:10 +0100333 if (status == PSA_SUCCESS) {
Paul Elliottadb8b162021-04-20 16:06:57 +0100334 operation->is_encrypt = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100336
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100338}
339
340/* Set the key and algorithm for a multipart authenticated decryption
341 * operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100342psa_status_t mbedtls_psa_aead_decrypt_setup(
343 mbedtls_psa_aead_operation_t *operation,
344 const psa_key_attributes_t *attributes,
345 const uint8_t *key_buffer,
346 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 psa_algorithm_t alg)
Paul Elliottadb8b162021-04-20 16:06:57 +0100348{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100349 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 status = psa_aead_setup(operation, attributes, key_buffer,
352 key_buffer_size, alg);
Paul Elliottadb8b162021-04-20 16:06:57 +0100353
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 if (status == PSA_SUCCESS) {
Paul Elliottadb8b162021-04-20 16:06:57 +0100355 operation->is_encrypt = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100359}
360
Paul Elliottadb8b162021-04-20 16:06:57 +0100361/* Set a nonce for the multipart AEAD operation*/
Paul Elliottbb8bf662021-05-19 17:29:42 +0100362psa_status_t mbedtls_psa_aead_set_nonce(
363 mbedtls_psa_aead_operation_t *operation,
364 const uint8_t *nonce,
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 size_t nonce_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100366{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100367 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100368
Paul Elliottbc949782021-06-03 15:29:00 +0100369#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100371 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 mbedtls_gcm_starts(&operation->ctx.gcm,
373 operation->is_encrypt ?
374 MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
375 nonce,
376 nonce_length));
377 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100378#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100379#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100381 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 mbedtls_ccm_starts(&operation->ctx.ccm,
383 operation->is_encrypt ?
384 MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
385 nonce,
386 nonce_length));
387 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100388#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100389#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliott946c9202021-09-28 14:32:55 +0100391 /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
392 * allocate a buffer in the operation, copy the nonce to it and pad
393 * it, so for now check the nonce is 12 bytes, as
394 * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
395 * passed in buffer. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 if (nonce_length != 12) {
397 return PSA_ERROR_INVALID_ARGUMENT;
Paul Elliott946c9202021-09-28 14:32:55 +0100398 }
399
Paul Elliott2df40052021-05-07 17:52:18 +0100400 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100402 nonce,
403 operation->is_encrypt ?
404 MBEDTLS_CHACHAPOLY_ENCRYPT :
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 MBEDTLS_CHACHAPOLY_DECRYPT));
406 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100407#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
408 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 (void) operation;
410 (void) nonce;
411 (void) nonce_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100412
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100414 }
415
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100417}
Paul Elliottefda3402021-08-25 17:16:52 +0100418
Gilles Peskine449bd832023-01-11 14:50:10 +0100419/* Declare the lengths of the message and additional data for AEAD. */
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100420psa_status_t mbedtls_psa_aead_set_lengths(
421 mbedtls_psa_aead_operation_t *operation,
422 size_t ad_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 size_t plaintext_length)
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100424{
Paul Elliotte193ea82021-10-01 13:00:16 +0100425#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 if (operation->alg == PSA_ALG_CCM) {
427 return mbedtls_to_psa_error(
428 mbedtls_ccm_set_lengths(&operation->ctx.ccm,
429 ad_length,
430 plaintext_length,
431 operation->tag_length));
Paul Elliotte193ea82021-10-01 13:00:16 +0100432
433 }
434#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 (void) operation;
436 (void) ad_length;
437 (void) plaintext_length;
Paul Elliotte193ea82021-10-01 13:00:16 +0100438#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 return PSA_SUCCESS;
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100441}
442
Paul Elliottadb8b162021-04-20 16:06:57 +0100443/* Pass additional data to an active multipart AEAD operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100444psa_status_t mbedtls_psa_aead_update_ad(
445 mbedtls_psa_aead_operation_t *operation,
446 const uint8_t *input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 size_t input_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100448{
449 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
450
Paul Elliottadb8b162021-04-20 16:06:57 +0100451#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott2df40052021-05-07 17:52:18 +0100453 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
455 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100456#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100457#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100459 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
461 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100462#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100463#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliott2df40052021-05-07 17:52:18 +0100465 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100467 input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 input_length));
469 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100470#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
471 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 (void) operation;
473 (void) input;
474 (void) input_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100477 }
478
Gilles Peskine449bd832023-01-11 14:50:10 +0100479 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100480}
481
482/* Encrypt or decrypt a message fragment in an active multipart AEAD
483 * operation.*/
Paul Elliottbb8bf662021-05-19 17:29:42 +0100484psa_status_t mbedtls_psa_aead_update(
485 mbedtls_psa_aead_operation_t *operation,
486 const uint8_t *input,
487 size_t input_length,
488 uint8_t *output,
489 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 size_t *output_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100491{
Paul Elliotte2c788d2021-05-13 17:16:01 +0100492 size_t update_output_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100493 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
494
Paul Elliotte2c788d2021-05-13 17:16:01 +0100495 update_output_length = input_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100496
Paul Elliottadb8b162021-04-20 16:06:57 +0100497#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100499 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 mbedtls_gcm_update(&operation->ctx.gcm,
Paul Elliotte193ea82021-10-01 13:00:16 +0100501 input, input_length,
502 output, output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 &update_output_length));
504 } else
505#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
506#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
507 if (operation->alg == PSA_ALG_CCM) {
508 if (output_size < input_length) {
509 return PSA_ERROR_BUFFER_TOO_SMALL;
510 }
Paul Elliottecce9012021-07-23 15:44:11 +0100511
Paul Elliott2df40052021-05-07 17:52:18 +0100512 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 mbedtls_ccm_update(&operation->ctx.ccm,
514 input, input_length,
515 output, output_size,
516 &update_output_length));
517 } else
518#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
519#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
520 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
521 if (output_size < input_length) {
522 return PSA_ERROR_BUFFER_TOO_SMALL;
523 }
524
525 status = mbedtls_to_psa_error(
526 mbedtls_chachapoly_update(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100527 input_length,
528 input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 output));
530 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100531#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
532 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 (void) operation;
534 (void) input;
535 (void) output;
536 (void) output_size;
Paul Elliottadb8b162021-04-20 16:06:57 +0100537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100539 }
540
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 if (status == PSA_SUCCESS) {
Paul Elliotte2c788d2021-05-13 17:16:01 +0100542 *output_length = update_output_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100546}
547
Paul Elliottadb8b162021-04-20 16:06:57 +0100548/* Finish encrypting a message in a multipart AEAD operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100549psa_status_t mbedtls_psa_aead_finish(
550 mbedtls_psa_aead_operation_t *operation,
551 uint8_t *ciphertext,
552 size_t ciphertext_size,
553 size_t *ciphertext_length,
554 uint8_t *tag,
555 size_t tag_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 size_t *tag_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100557{
558 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottfd3ca242021-04-25 18:10:42 +0100559 size_t finish_output_size = 0;
Paul Elliottadb8b162021-04-20 16:06:57 +0100560
Gilles Peskine449bd832023-01-11 14:50:10 +0100561 if (tag_size < operation->tag_length) {
562 return PSA_ERROR_BUFFER_TOO_SMALL;
563 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100564
565#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100567 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 mbedtls_gcm_finish(&operation->ctx.gcm,
569 ciphertext, ciphertext_size, ciphertext_length,
570 tag, operation->tag_length));
571 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100572#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100573#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100575 /* tag must be big enough to store a tag of size passed into set
576 * lengths. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 if (tag_size < operation->tag_length) {
578 return PSA_ERROR_BUFFER_TOO_SMALL;
579 }
Paul Elliotte193ea82021-10-01 13:00:16 +0100580
581 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 mbedtls_ccm_finish(&operation->ctx.ccm,
583 tag, operation->tag_length));
584 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100585#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100586#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliotted08cf82021-07-22 18:48:24 +0100588 /* Belt and braces. Although the above tag_size check should have
589 * already done this, if we later start supporting smaller tag sizes
590 * for chachapoly, then passing a tag buffer smaller than 16 into here
591 * could cause a buffer overflow, so better safe than sorry. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 if (tag_size < 16) {
593 return PSA_ERROR_BUFFER_TOO_SMALL;
594 }
Paul Elliotted08cf82021-07-22 18:48:24 +0100595
Paul Elliott2df40052021-05-07 17:52:18 +0100596 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
598 tag));
599 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100600#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
601 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 (void) ciphertext;
603 (void) ciphertext_size;
604 (void) ciphertext_length;
605 (void) tag;
606 (void) tag_size;
607 (void) tag_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100608
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100610 }
611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 if (status == PSA_SUCCESS) {
Paul Elliott8ff74212021-09-19 18:39:23 +0100613 /* This will be zero for all supported algorithms currently, but left
614 * here for future support. */
Paul Elliottadb8b162021-04-20 16:06:57 +0100615 *ciphertext_length = finish_output_size;
Paul Elliottfd3ca242021-04-25 18:10:42 +0100616 *tag_length = operation->tag_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100617 }
618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100620}
621
Paul Elliottadb8b162021-04-20 16:06:57 +0100622/* Abort an AEAD operation */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100623psa_status_t mbedtls_psa_aead_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 mbedtls_psa_aead_operation_t *operation)
Paul Elliottadb8b162021-04-20 16:06:57 +0100625{
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 switch (operation->alg) {
Paul Elliott811d8d42021-04-22 11:31:14 +0100627#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
628 case PSA_ALG_CCM:
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 mbedtls_ccm_free(&operation->ctx.ccm);
Paul Elliottadb8b162021-04-20 16:06:57 +0100630 break;
631#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
632#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
633 case PSA_ALG_GCM:
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 mbedtls_gcm_free(&operation->ctx.gcm);
Paul Elliottadb8b162021-04-20 16:06:57 +0100635 break;
636#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
637#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott811d8d42021-04-22 11:31:14 +0100638 case PSA_ALG_CHACHA20_POLY1305:
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 mbedtls_chachapoly_free(&operation->ctx.chachapoly);
Paul Elliott811d8d42021-04-22 11:31:14 +0100640 break;
Paul Elliottadb8b162021-04-20 16:06:57 +0100641#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
642 }
643
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100644 operation->is_encrypt = 0;
Paul Elliott1a98aca2021-05-20 18:24:07 +0100645
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 return PSA_SUCCESS;
Paul Elliottadb8b162021-04-20 16:06:57 +0100647}
648
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100649#endif /* MBEDTLS_PSA_CRYPTO_C */