blob: b7ddbf5ba167668ef82bbcd9ae153a3d5d512ce4 [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 Rodgmane3c05852023-11-03 12:21:36 +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;
34 size_t key_bits;
Ronald Cronecbc0682021-03-26 13:25:17 +010035 const mbedtls_cipher_info_t *cipher_info;
Ronald Cron46f91782021-03-17 08:16:34 +010036 mbedtls_cipher_id_t cipher_id;
37
Gilles Peskine449bd832023-01-11 14:50:10 +010038 (void) key_buffer_size;
Paul Elliottcc358592021-05-12 12:22:28 +010039
Ronald Cron46f91782021-03-17 08:16:34 +010040 key_bits = attributes->core.bits;
41
Gilles Peskine449bd832023-01-11 14:50:10 +010042 cipher_info = mbedtls_cipher_info_from_psa(alg,
43 attributes->core.type, key_bits,
44 &cipher_id);
45 if (cipher_info == NULL) {
46 return PSA_ERROR_NOT_SUPPORTED;
47 }
Ronald Cron46f91782021-03-17 08:16:34 +010048
Gilles Peskine449bd832023-01-11 14:50:10 +010049 switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
Ronald Cron46f91782021-03-17 08:16:34 +010050#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010051 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010052 operation->alg = PSA_ALG_CCM;
Ronald Cron46f91782021-03-17 08:16:34 +010053 /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
54 * The call to mbedtls_ccm_encrypt_and_tag or
55 * mbedtls_ccm_auth_decrypt will validate the tag length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010056 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
57 return PSA_ERROR_INVALID_ARGUMENT;
58 }
Ronald Cron46f91782021-03-17 08:16:34 +010059
Gilles Peskine449bd832023-01-11 14:50:10 +010060 mbedtls_ccm_init(&operation->ctx.ccm);
Ronald Cron46f91782021-03-17 08:16:34 +010061 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +010062 mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
63 key_buffer, (unsigned int) key_bits));
64 if (status != PSA_SUCCESS) {
65 return status;
66 }
Ronald Cron46f91782021-03-17 08:16:34 +010067 break;
68#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
69
70#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +010071 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010072 operation->alg = PSA_ALG_GCM;
Ronald Cron46f91782021-03-17 08:16:34 +010073 /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
74 * The call to mbedtls_gcm_crypt_and_tag or
75 * mbedtls_gcm_auth_decrypt will validate the tag length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010076 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
77 return PSA_ERROR_INVALID_ARGUMENT;
78 }
Ronald Cron46f91782021-03-17 08:16:34 +010079
Gilles Peskine449bd832023-01-11 14:50:10 +010080 mbedtls_gcm_init(&operation->ctx.gcm);
Ronald Cron46f91782021-03-17 08:16:34 +010081 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +010082 mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
83 key_buffer, (unsigned int) key_bits));
84 if (status != PSA_SUCCESS) {
85 return status;
86 }
Ronald Cron46f91782021-03-17 08:16:34 +010087 break;
88#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
89
90#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +010091 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
Paul Elliott07a30c42021-04-20 14:13:23 +010092 operation->alg = PSA_ALG_CHACHA20_POLY1305;
Ronald Cron46f91782021-03-17 08:16:34 +010093 /* We only support the default tag length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010094 if (alg != PSA_ALG_CHACHA20_POLY1305) {
95 return PSA_ERROR_NOT_SUPPORTED;
96 }
Ronald Cron46f91782021-03-17 08:16:34 +010097
Gilles Peskine449bd832023-01-11 14:50:10 +010098 mbedtls_chachapoly_init(&operation->ctx.chachapoly);
Ronald Cron46f91782021-03-17 08:16:34 +010099 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
101 key_buffer));
102 if (status != PSA_SUCCESS) {
103 return status;
104 }
Ronald Cron46f91782021-03-17 08:16:34 +0100105 break;
106#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
107
108 default:
Ronald Cron7a55deb2021-04-28 14:29:00 +0200109 (void) status;
110 (void) key_buffer;
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100112 }
113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 operation->key_type = psa_get_key_type(attributes);
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
Ronald Cron46f91782021-03-17 08:16:34 +0100117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 return PSA_SUCCESS;
Ronald Cron46f91782021-03-17 08:16:34 +0100119}
120
121psa_status_t mbedtls_psa_aead_encrypt(
122 const psa_key_attributes_t *attributes,
123 const uint8_t *key_buffer, size_t key_buffer_size,
124 psa_algorithm_t alg,
125 const uint8_t *nonce, size_t nonce_length,
126 const uint8_t *additional_data, size_t additional_data_length,
127 const uint8_t *plaintext, size_t plaintext_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
Ronald Cron46f91782021-03-17 08:16:34 +0100129{
130 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100131 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100132 uint8_t *tag;
Ronald Cron46f91782021-03-17 08:16:34 +0100133
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 status = psa_aead_setup(&operation, attributes, key_buffer,
135 key_buffer_size, alg);
Paul Elliottcc358592021-05-12 12:22:28 +0100136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100138 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 }
Ronald Cron46f91782021-03-17 08:16:34 +0100140
141 /* For all currently supported modes, the tag is at the end of the
142 * ciphertext. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 if (ciphertext_size < (plaintext_length + operation.tag_length)) {
Ronald Cron46f91782021-03-17 08:16:34 +0100144 status = PSA_ERROR_BUFFER_TOO_SMALL;
145 goto exit;
146 }
147 tag = ciphertext + plaintext_length;
148
Ronald Cron46f91782021-03-17 08:16:34 +0100149#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if (operation.alg == PSA_ALG_CCM) {
Ronald Cron46f91782021-03-17 08:16:34 +0100151 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
153 plaintext_length,
154 nonce, nonce_length,
155 additional_data,
156 additional_data_length,
157 plaintext, ciphertext,
158 tag, operation.tag_length));
159 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100160#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200161#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 if (operation.alg == PSA_ALG_GCM) {
Ronald Cron810eb162021-04-06 09:01:39 +0200163 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
165 MBEDTLS_GCM_ENCRYPT,
166 plaintext_length,
167 nonce, nonce_length,
168 additional_data, additional_data_length,
169 plaintext, ciphertext,
170 operation.tag_length, tag));
171 } else
Ronald Cron810eb162021-04-06 09:01:39 +0200172#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100173#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
175 if (operation.tag_length != 16) {
Ronald Cron46f91782021-03-17 08:16:34 +0100176 status = PSA_ERROR_NOT_SUPPORTED;
177 goto exit;
178 }
179 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
181 plaintext_length,
182 nonce,
183 additional_data,
184 additional_data_length,
185 plaintext,
186 ciphertext,
187 tag));
188 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100189#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
190 {
191 (void) tag;
Ronald Cron7a55deb2021-04-28 14:29:00 +0200192 (void) nonce;
193 (void) nonce_length;
194 (void) additional_data;
195 (void) additional_data_length;
196 (void) plaintext;
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100198 }
199
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100201 *ciphertext_length = plaintext_length + operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 }
Ronald Cron46f91782021-03-17 08:16:34 +0100203
204exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 mbedtls_psa_aead_abort(&operation);
Ronald Cron46f91782021-03-17 08:16:34 +0100206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 return status;
Ronald Cron46f91782021-03-17 08:16:34 +0100208}
209
210/* Locate the tag in a ciphertext buffer containing the encrypted data
211 * followed by the tag. Return the length of the part preceding the tag in
212 * *plaintext_length. This is the size of the plaintext in modes where
213 * the encrypted data has the same size as the plaintext, such as
214 * CCM and GCM. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100215static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
216 const uint8_t *ciphertext,
217 size_t ciphertext_length,
218 size_t plaintext_size,
219 const uint8_t **p_tag)
Ronald Cron46f91782021-03-17 08:16:34 +0100220{
221 size_t payload_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if (tag_length > ciphertext_length) {
223 return PSA_ERROR_INVALID_ARGUMENT;
224 }
Ronald Cron46f91782021-03-17 08:16:34 +0100225 payload_length = ciphertext_length - tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 if (payload_length > plaintext_size) {
227 return PSA_ERROR_BUFFER_TOO_SMALL;
228 }
Ronald Cron46f91782021-03-17 08:16:34 +0100229 *p_tag = ciphertext + payload_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 return PSA_SUCCESS;
Ronald Cron46f91782021-03-17 08:16:34 +0100231}
232
233psa_status_t mbedtls_psa_aead_decrypt(
234 const psa_key_attributes_t *attributes,
235 const uint8_t *key_buffer, size_t key_buffer_size,
236 psa_algorithm_t alg,
237 const uint8_t *nonce, size_t nonce_length,
238 const uint8_t *additional_data, size_t additional_data_length,
239 const uint8_t *ciphertext, size_t ciphertext_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
Ronald Cron46f91782021-03-17 08:16:34 +0100241{
242 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100243 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100244 const uint8_t *tag = NULL;
Ronald Cron46f91782021-03-17 08:16:34 +0100245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 status = psa_aead_setup(&operation, attributes, key_buffer,
247 key_buffer_size, alg);
Paul Elliottcc358592021-05-12 12:22:28 +0100248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100250 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 }
Ronald Cron46f91782021-03-17 08:16:34 +0100252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 status = psa_aead_unpadded_locate_tag(operation.tag_length,
254 ciphertext, ciphertext_length,
255 plaintext_size, &tag);
256 if (status != PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100257 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 }
Ronald Cron46f91782021-03-17 08:16:34 +0100259
Ronald Cron46f91782021-03-17 08:16:34 +0100260#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if (operation.alg == PSA_ALG_CCM) {
Ronald Cron46f91782021-03-17 08:16:34 +0100262 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
264 ciphertext_length - operation.tag_length,
265 nonce, nonce_length,
266 additional_data,
267 additional_data_length,
268 ciphertext, plaintext,
269 tag, operation.tag_length));
270 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100271#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200272#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 if (operation.alg == PSA_ALG_GCM) {
Ronald Cron810eb162021-04-06 09:01:39 +0200274 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
276 ciphertext_length - operation.tag_length,
277 nonce, nonce_length,
278 additional_data,
279 additional_data_length,
280 tag, operation.tag_length,
281 ciphertext, plaintext));
282 } else
Ronald Cron810eb162021-04-06 09:01:39 +0200283#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100284#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
286 if (operation.tag_length != 16) {
Ronald Cron46f91782021-03-17 08:16:34 +0100287 status = PSA_ERROR_NOT_SUPPORTED;
288 goto exit;
289 }
290 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
292 ciphertext_length - operation.tag_length,
293 nonce,
294 additional_data,
295 additional_data_length,
296 tag,
297 ciphertext,
298 plaintext));
299 } else
Ronald Cron46f91782021-03-17 08:16:34 +0100300#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
301 {
Ronald Cron7a55deb2021-04-28 14:29:00 +0200302 (void) nonce;
303 (void) nonce_length;
304 (void) additional_data;
305 (void) additional_data_length;
306 (void) plaintext;
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 return PSA_ERROR_NOT_SUPPORTED;
Ronald Cron46f91782021-03-17 08:16:34 +0100308 }
309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100311 *plaintext_length = ciphertext_length - operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 }
Ronald Cron46f91782021-03-17 08:16:34 +0100313
314exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 mbedtls_psa_aead_abort(&operation);
Ronald Cron46f91782021-03-17 08:16:34 +0100316
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 if (status == PSA_SUCCESS) {
Ronald Cron46f91782021-03-17 08:16:34 +0100318 *plaintext_length = ciphertext_length - operation.tag_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 }
320 return status;
Ronald Cron46f91782021-03-17 08:16:34 +0100321}
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100322
Paul Elliottadb8b162021-04-20 16:06:57 +0100323/* Set the key and algorithm for a multipart authenticated encryption
324 * operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100325psa_status_t mbedtls_psa_aead_encrypt_setup(
326 mbedtls_psa_aead_operation_t *operation,
327 const psa_key_attributes_t *attributes,
328 const uint8_t *key_buffer,
329 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 psa_algorithm_t alg)
Paul Elliottadb8b162021-04-20 16:06:57 +0100331{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100332 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 status = psa_aead_setup(operation, attributes, key_buffer,
335 key_buffer_size, alg);
Paul Elliottadb8b162021-04-20 16:06:57 +0100336
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 if (status == PSA_SUCCESS) {
Paul Elliottadb8b162021-04-20 16:06:57 +0100338 operation->is_encrypt = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100342}
343
344/* Set the key and algorithm for a multipart authenticated decryption
345 * operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100346psa_status_t mbedtls_psa_aead_decrypt_setup(
347 mbedtls_psa_aead_operation_t *operation,
348 const psa_key_attributes_t *attributes,
349 const uint8_t *key_buffer,
350 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 psa_algorithm_t alg)
Paul Elliottadb8b162021-04-20 16:06:57 +0100352{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100353 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100354
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 status = psa_aead_setup(operation, attributes, key_buffer,
356 key_buffer_size, alg);
Paul Elliottadb8b162021-04-20 16:06:57 +0100357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 if (status == PSA_SUCCESS) {
Paul Elliottadb8b162021-04-20 16:06:57 +0100359 operation->is_encrypt = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100363}
364
Paul Elliottadb8b162021-04-20 16:06:57 +0100365/* Set a nonce for the multipart AEAD operation*/
Paul Elliottbb8bf662021-05-19 17:29:42 +0100366psa_status_t mbedtls_psa_aead_set_nonce(
367 mbedtls_psa_aead_operation_t *operation,
368 const uint8_t *nonce,
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 size_t nonce_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100370{
Paul Elliott9e8ccd72021-05-13 14:30:53 +0100371 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100372
Paul Elliottbc949782021-06-03 15:29:00 +0100373#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100375 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 mbedtls_gcm_starts(&operation->ctx.gcm,
377 operation->is_encrypt ?
378 MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
379 nonce,
380 nonce_length));
381 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100382#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100383#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100385 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 mbedtls_ccm_starts(&operation->ctx.ccm,
387 operation->is_encrypt ?
388 MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
389 nonce,
390 nonce_length));
391 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100392#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100393#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliott946c9202021-09-28 14:32:55 +0100395 /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
396 * allocate a buffer in the operation, copy the nonce to it and pad
397 * it, so for now check the nonce is 12 bytes, as
398 * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
399 * passed in buffer. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 if (nonce_length != 12) {
401 return PSA_ERROR_INVALID_ARGUMENT;
Paul Elliott946c9202021-09-28 14:32:55 +0100402 }
403
Paul Elliott2df40052021-05-07 17:52:18 +0100404 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100406 nonce,
407 operation->is_encrypt ?
408 MBEDTLS_CHACHAPOLY_ENCRYPT :
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 MBEDTLS_CHACHAPOLY_DECRYPT));
410 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100411#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
412 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 (void) operation;
414 (void) nonce;
415 (void) nonce_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100418 }
419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100421}
Paul Elliottefda3402021-08-25 17:16:52 +0100422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423/* Declare the lengths of the message and additional data for AEAD. */
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100424psa_status_t mbedtls_psa_aead_set_lengths(
425 mbedtls_psa_aead_operation_t *operation,
426 size_t ad_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 size_t plaintext_length)
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100428{
Paul Elliotte193ea82021-10-01 13:00:16 +0100429#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 if (operation->alg == PSA_ALG_CCM) {
431 return mbedtls_to_psa_error(
432 mbedtls_ccm_set_lengths(&operation->ctx.ccm,
433 ad_length,
434 plaintext_length,
435 operation->tag_length));
Paul Elliotte193ea82021-10-01 13:00:16 +0100436
437 }
438#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 (void) operation;
440 (void) ad_length;
441 (void) plaintext_length;
Paul Elliotte193ea82021-10-01 13:00:16 +0100442#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 return PSA_SUCCESS;
Paul Elliottdff6c5d2021-09-28 11:00:20 +0100445}
446
Paul Elliottadb8b162021-04-20 16:06:57 +0100447/* Pass additional data to an active multipart AEAD operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100448psa_status_t mbedtls_psa_aead_update_ad(
449 mbedtls_psa_aead_operation_t *operation,
450 const uint8_t *input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 size_t input_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100452{
453 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
454
Paul Elliottadb8b162021-04-20 16:06:57 +0100455#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott2df40052021-05-07 17:52:18 +0100457 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
459 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100460#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100461#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100463 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
465 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100466#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100467#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliott2df40052021-05-07 17:52:18 +0100469 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100471 input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 input_length));
473 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100474#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
475 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 (void) operation;
477 (void) input;
478 (void) input_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100481 }
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100484}
485
486/* Encrypt or decrypt a message fragment in an active multipart AEAD
487 * operation.*/
Paul Elliottbb8bf662021-05-19 17:29:42 +0100488psa_status_t mbedtls_psa_aead_update(
489 mbedtls_psa_aead_operation_t *operation,
490 const uint8_t *input,
491 size_t input_length,
492 uint8_t *output,
493 size_t output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 size_t *output_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100495{
Paul Elliotte2c788d2021-05-13 17:16:01 +0100496 size_t update_output_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100497 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
498
Paul Elliotte2c788d2021-05-13 17:16:01 +0100499 update_output_length = input_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100500
Paul Elliottadb8b162021-04-20 16:06:57 +0100501#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100503 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 mbedtls_gcm_update(&operation->ctx.gcm,
Paul Elliotte193ea82021-10-01 13:00:16 +0100505 input, input_length,
506 output, output_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 &update_output_length));
508 } else
509#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
510#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
511 if (operation->alg == PSA_ALG_CCM) {
512 if (output_size < input_length) {
513 return PSA_ERROR_BUFFER_TOO_SMALL;
514 }
Paul Elliottecce9012021-07-23 15:44:11 +0100515
Paul Elliott2df40052021-05-07 17:52:18 +0100516 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 mbedtls_ccm_update(&operation->ctx.ccm,
518 input, input_length,
519 output, output_size,
520 &update_output_length));
521 } else
522#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
523#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
524 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
525 if (output_size < input_length) {
526 return PSA_ERROR_BUFFER_TOO_SMALL;
527 }
528
529 status = mbedtls_to_psa_error(
530 mbedtls_chachapoly_update(&operation->ctx.chachapoly,
Paul Elliott2df40052021-05-07 17:52:18 +0100531 input_length,
532 input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 output));
534 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100535#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
536 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 (void) operation;
538 (void) input;
539 (void) output;
540 (void) output_size;
Paul Elliottadb8b162021-04-20 16:06:57 +0100541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100543 }
544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 if (status == PSA_SUCCESS) {
Paul Elliotte2c788d2021-05-13 17:16:01 +0100546 *output_length = update_output_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100548
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100550}
551
Paul Elliottadb8b162021-04-20 16:06:57 +0100552/* Finish encrypting a message in a multipart AEAD operation. */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100553psa_status_t mbedtls_psa_aead_finish(
554 mbedtls_psa_aead_operation_t *operation,
555 uint8_t *ciphertext,
556 size_t ciphertext_size,
557 size_t *ciphertext_length,
558 uint8_t *tag,
559 size_t tag_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 size_t *tag_length)
Paul Elliottadb8b162021-04-20 16:06:57 +0100561{
562 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliottfd3ca242021-04-25 18:10:42 +0100563 size_t finish_output_size = 0;
Paul Elliottadb8b162021-04-20 16:06:57 +0100564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 if (tag_size < operation->tag_length) {
566 return PSA_ERROR_BUFFER_TOO_SMALL;
567 }
Paul Elliottadb8b162021-04-20 16:06:57 +0100568
569#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if (operation->alg == PSA_ALG_GCM) {
Paul Elliott83f09ef2021-05-21 19:28:26 +0100571 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 mbedtls_gcm_finish(&operation->ctx.gcm,
573 ciphertext, ciphertext_size, ciphertext_length,
574 tag, operation->tag_length));
575 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100576#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Paul Elliotte193ea82021-10-01 13:00:16 +0100577#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Gilles Peskine449bd832023-01-11 14:50:10 +0100578 if (operation->alg == PSA_ALG_CCM) {
Paul Elliotte193ea82021-10-01 13:00:16 +0100579 /* tag must be big enough to store a tag of size passed into set
580 * lengths. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100581 if (tag_size < operation->tag_length) {
582 return PSA_ERROR_BUFFER_TOO_SMALL;
583 }
Paul Elliotte193ea82021-10-01 13:00:16 +0100584
585 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 mbedtls_ccm_finish(&operation->ctx.ccm,
587 tag, operation->tag_length));
588 } else
Paul Elliotte193ea82021-10-01 13:00:16 +0100589#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Paul Elliottadb8b162021-04-20 16:06:57 +0100590#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
Paul Elliotted08cf82021-07-22 18:48:24 +0100592 /* Belt and braces. Although the above tag_size check should have
593 * already done this, if we later start supporting smaller tag sizes
594 * for chachapoly, then passing a tag buffer smaller than 16 into here
595 * could cause a buffer overflow, so better safe than sorry. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 if (tag_size < 16) {
597 return PSA_ERROR_BUFFER_TOO_SMALL;
598 }
Paul Elliotted08cf82021-07-22 18:48:24 +0100599
Paul Elliott2df40052021-05-07 17:52:18 +0100600 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
602 tag));
603 } else
Paul Elliottadb8b162021-04-20 16:06:57 +0100604#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
605 {
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 (void) ciphertext;
607 (void) ciphertext_size;
608 (void) ciphertext_length;
609 (void) tag;
610 (void) tag_size;
611 (void) tag_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100612
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 return PSA_ERROR_NOT_SUPPORTED;
Paul Elliottadb8b162021-04-20 16:06:57 +0100614 }
615
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 if (status == PSA_SUCCESS) {
Paul Elliott8ff74212021-09-19 18:39:23 +0100617 /* This will be zero for all supported algorithms currently, but left
618 * here for future support. */
Paul Elliottadb8b162021-04-20 16:06:57 +0100619 *ciphertext_length = finish_output_size;
Paul Elliottfd3ca242021-04-25 18:10:42 +0100620 *tag_length = operation->tag_length;
Paul Elliottadb8b162021-04-20 16:06:57 +0100621 }
622
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 return status;
Paul Elliottadb8b162021-04-20 16:06:57 +0100624}
625
Paul Elliottadb8b162021-04-20 16:06:57 +0100626/* Abort an AEAD operation */
Paul Elliottbb8bf662021-05-19 17:29:42 +0100627psa_status_t mbedtls_psa_aead_abort(
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 mbedtls_psa_aead_operation_t *operation)
Paul Elliottadb8b162021-04-20 16:06:57 +0100629{
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 switch (operation->alg) {
Paul Elliott811d8d42021-04-22 11:31:14 +0100631#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
632 case PSA_ALG_CCM:
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 mbedtls_ccm_free(&operation->ctx.ccm);
Paul Elliottadb8b162021-04-20 16:06:57 +0100634 break;
635#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
636#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
637 case PSA_ALG_GCM:
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 mbedtls_gcm_free(&operation->ctx.gcm);
Paul Elliottadb8b162021-04-20 16:06:57 +0100639 break;
640#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
641#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott811d8d42021-04-22 11:31:14 +0100642 case PSA_ALG_CHACHA20_POLY1305:
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 mbedtls_chachapoly_free(&operation->ctx.chachapoly);
Paul Elliott811d8d42021-04-22 11:31:14 +0100644 break;
Paul Elliottadb8b162021-04-20 16:06:57 +0100645#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
646 }
647
Paul Elliottcbbde5f2021-05-10 18:19:46 +0100648 operation->is_encrypt = 0;
Paul Elliott1a98aca2021-05-20 18:24:07 +0100649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 return PSA_SUCCESS;
Paul Elliottadb8b162021-04-20 16:06:57 +0100651}
652
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100653#endif /* MBEDTLS_PSA_CRYPTO_C */