blob: 7f625c549dd4da091dfbe72c3d786fbd1c457961 [file] [log] [blame]
Steven Cooremand13a70f2021-03-19 15:24:23 +01001/*
2 * PSA MAC layer on top of Mbed TLS software crypto
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
Steven Cooremand13a70f2021-03-19 15:24:23 +01007 */
8
9#include "common.h"
10
11#if defined(MBEDTLS_PSA_CRYPTO_C)
12
13#include <psa/crypto.h>
14#include "psa_crypto_core.h"
Dave Rodgman16304472022-11-02 09:25:38 +000015#include "psa_crypto_cipher.h"
Steven Cooremand13a70f2021-03-19 15:24:23 +010016#include "psa_crypto_mac.h"
Steven Cooreman82c66b62021-03-19 17:39:17 +010017#include <mbedtls/md.h>
Steven Cooremand13a70f2021-03-19 15:24:23 +010018
19#include <mbedtls/error.h>
Dave Rodgman78701152023-08-29 14:20:18 +010020#include "mbedtls/constant_time.h"
Steven Cooremand13a70f2021-03-19 15:24:23 +010021#include <string.h>
22
Ronald Cron0266cfe2021-03-13 18:50:11 +010023#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Steven Cooremana6df6042021-04-29 19:32:25 +020024static psa_status_t psa_hmac_abort_internal(
Gilles Peskine449bd832023-01-11 14:50:10 +010025 mbedtls_psa_hmac_operation_t *hmac)
Steven Cooreman82c66b62021-03-19 17:39:17 +010026{
Gilles Peskine449bd832023-01-11 14:50:10 +010027 mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad));
28 return psa_hash_abort(&hmac->hash_ctx);
Steven Cooreman82c66b62021-03-19 17:39:17 +010029}
30
Steven Cooremana6df6042021-04-29 19:32:25 +020031static psa_status_t psa_hmac_setup_internal(
32 mbedtls_psa_hmac_operation_t *hmac,
33 const uint8_t *key,
34 size_t key_length,
Gilles Peskine449bd832023-01-11 14:50:10 +010035 psa_algorithm_t hash_alg)
Steven Cooreman82c66b62021-03-19 17:39:17 +010036{
37 uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
38 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +010039 size_t hash_size = PSA_HASH_LENGTH(hash_alg);
40 size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
Steven Cooreman82c66b62021-03-19 17:39:17 +010041 psa_status_t status;
42
43 hmac->alg = hash_alg;
44
45 /* Sanity checks on block_size, to guarantee that there won't be a buffer
46 * overflow below. This should never trigger if the hash algorithm
47 * is implemented correctly. */
48 /* The size checks against the ipad and opad buffers cannot be written
49 * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
50 * because that triggers -Wlogical-op on GCC 7.3. */
Gilles Peskine449bd832023-01-11 14:50:10 +010051 if (block_size > sizeof(ipad)) {
52 return PSA_ERROR_NOT_SUPPORTED;
53 }
54 if (block_size > sizeof(hmac->opad)) {
55 return PSA_ERROR_NOT_SUPPORTED;
56 }
57 if (block_size < hash_size) {
58 return PSA_ERROR_NOT_SUPPORTED;
59 }
Steven Cooreman82c66b62021-03-19 17:39:17 +010060
Gilles Peskine449bd832023-01-11 14:50:10 +010061 if (key_length > block_size) {
62 status = psa_hash_compute(hash_alg, key, key_length,
63 ipad, sizeof(ipad), &key_length);
64 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +010065 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +010066 }
Steven Cooreman82c66b62021-03-19 17:39:17 +010067 }
68 /* A 0-length key is not commonly used in HMAC when used as a MAC,
69 * but it is permitted. It is common when HMAC is used in HKDF, for
70 * example. Don't call `memcpy` in the 0-length because `key` could be
71 * an invalid pointer which would make the behavior undefined. */
Gilles Peskine449bd832023-01-11 14:50:10 +010072 else if (key_length != 0) {
73 memcpy(ipad, key, key_length);
74 }
Steven Cooreman82c66b62021-03-19 17:39:17 +010075
76 /* ipad contains the key followed by garbage. Xor and fill with 0x36
77 * to create the ipad value. */
Gilles Peskine449bd832023-01-11 14:50:10 +010078 for (i = 0; i < key_length; i++) {
Steven Cooreman82c66b62021-03-19 17:39:17 +010079 ipad[i] ^= 0x36;
Gilles Peskine449bd832023-01-11 14:50:10 +010080 }
81 memset(ipad + key_length, 0x36, block_size - key_length);
Steven Cooreman82c66b62021-03-19 17:39:17 +010082
83 /* Copy the key material from ipad to opad, flipping the requisite bits,
84 * and filling the rest of opad with the requisite constant. */
Gilles Peskine449bd832023-01-11 14:50:10 +010085 for (i = 0; i < key_length; i++) {
Steven Cooreman82c66b62021-03-19 17:39:17 +010086 hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
Gilles Peskine449bd832023-01-11 14:50:10 +010087 }
88 memset(hmac->opad + key_length, 0x5C, block_size - key_length);
Steven Cooreman82c66b62021-03-19 17:39:17 +010089
Gilles Peskine449bd832023-01-11 14:50:10 +010090 status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
91 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +010092 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +010093 }
Steven Cooreman82c66b62021-03-19 17:39:17 +010094
Gilles Peskine449bd832023-01-11 14:50:10 +010095 status = psa_hash_update(&hmac->hash_ctx, ipad, block_size);
Steven Cooreman82c66b62021-03-19 17:39:17 +010096
97cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +010098 mbedtls_platform_zeroize(ipad, sizeof(ipad));
Steven Cooreman82c66b62021-03-19 17:39:17 +010099
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 return status;
Steven Cooreman82c66b62021-03-19 17:39:17 +0100101}
102
Steven Cooremana6df6042021-04-29 19:32:25 +0200103static psa_status_t psa_hmac_update_internal(
104 mbedtls_psa_hmac_operation_t *hmac,
105 const uint8_t *data,
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 size_t data_length)
Steven Cooreman4fdf0602021-03-22 12:21:10 +0100107{
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 return psa_hash_update(&hmac->hash_ctx, data, data_length);
Steven Cooreman4fdf0602021-03-22 12:21:10 +0100109}
110
Steven Cooremana6df6042021-04-29 19:32:25 +0200111static psa_status_t psa_hmac_finish_internal(
112 mbedtls_psa_hmac_operation_t *hmac,
113 uint8_t *mac,
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 size_t mac_size)
Steven Cooreman82c66b62021-03-19 17:39:17 +0100115{
Ronald Cron69a63422021-10-18 09:47:58 +0200116 uint8_t tmp[PSA_HASH_MAX_SIZE];
Steven Cooreman82c66b62021-03-19 17:39:17 +0100117 psa_algorithm_t hash_alg = hmac->alg;
118 size_t hash_size = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
Steven Cooreman82c66b62021-03-19 17:39:17 +0100120 psa_status_t status;
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
123 if (status != PSA_SUCCESS) {
124 return status;
125 }
Steven Cooreman82c66b62021-03-19 17:39:17 +0100126 /* From here on, tmp needs to be wiped. */
127
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
129 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +0100130 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 }
Steven Cooreman82c66b62021-03-19 17:39:17 +0100132
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size);
134 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +0100135 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 }
Steven Cooreman82c66b62021-03-19 17:39:17 +0100137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size);
139 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +0100140 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 }
Steven Cooreman82c66b62021-03-19 17:39:17 +0100142
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
144 if (status != PSA_SUCCESS) {
Steven Cooreman82c66b62021-03-19 17:39:17 +0100145 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 }
Steven Cooreman82c66b62021-03-19 17:39:17 +0100147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 memcpy(mac, tmp, mac_size);
Steven Cooreman82c66b62021-03-19 17:39:17 +0100149
150exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 mbedtls_platform_zeroize(tmp, hash_size);
152 return status;
Steven Cooreman82c66b62021-03-19 17:39:17 +0100153}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100154#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooremane6804192021-03-19 18:28:56 +0100155
Ronald Cron0266cfe2021-03-13 18:50:11 +0100156#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100157static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
158 const psa_key_attributes_t *attributes,
159 const uint8_t *key_buffer)
Steven Cooremane6804192021-03-19 18:28:56 +0100160{
161 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Steven Cooreman0c239652021-05-07 17:27:27 +0200162
163#if defined(PSA_WANT_KEY_TYPE_DES)
164 /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
165 * to do CMAC with pure DES, so return NOT_SUPPORTED here. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
167 (psa_get_key_bits(attributes) == 64 ||
168 psa_get_key_bits(attributes) == 128)) {
169 return PSA_ERROR_NOT_SUPPORTED;
170 }
Steven Cooreman0c239652021-05-07 17:27:27 +0200171#endif
172
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 const mbedtls_cipher_info_t *cipher_info =
Steven Cooremane6804192021-03-19 18:28:56 +0100174 mbedtls_cipher_info_from_psa(
175 PSA_ALG_CMAC,
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 psa_get_key_type(attributes),
177 psa_get_key_bits(attributes),
178 NULL);
Steven Cooremane6804192021-03-19 18:28:56 +0100179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 if (cipher_info == NULL) {
181 return PSA_ERROR_NOT_SUPPORTED;
182 }
Steven Cooremane6804192021-03-19 18:28:56 +0100183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);
185 if (ret != 0) {
Steven Cooremane6804192021-03-19 18:28:56 +0100186 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 }
Steven Cooremane6804192021-03-19 18:28:56 +0100188
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,
190 key_buffer,
191 psa_get_key_bits(attributes));
Steven Cooremane6804192021-03-19 18:28:56 +0100192exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 return mbedtls_to_psa_error(ret);
Steven Cooremane6804192021-03-19 18:28:56 +0100194}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100195#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
Steven Cooremane6804192021-03-19 18:28:56 +0100196
Ronald Cron0266cfe2021-03-13 18:50:11 +0100197#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \
198 defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Steven Cooreman02865f52021-05-07 15:55:27 +0200199
Steven Cooremane6804192021-03-19 18:28:56 +0100200/* Initialize this driver's MAC operation structure. Once this function has been
201 * called, mbedtls_psa_mac_abort can run and will do the right thing. */
202static psa_status_t mac_init(
203 mbedtls_psa_mac_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 psa_algorithm_t alg)
Steven Cooremane6804192021-03-19 18:28:56 +0100205{
Steven Cooremanba9a5bf2021-04-29 16:21:24 +0200206 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Steven Cooremane6804192021-03-19 18:28:56 +0100207
Steven Cooreman72f736a2021-05-07 14:14:37 +0200208 operation->alg = alg;
Steven Cooremane6804192021-03-19 18:28:56 +0100209
Ronald Cron0266cfe2021-03-13 18:50:11 +0100210#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
212 mbedtls_cipher_init(&operation->ctx.cmac);
Steven Cooremane6804192021-03-19 18:28:56 +0100213 status = PSA_SUCCESS;
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100215#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
216#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 if (PSA_ALG_IS_HMAC(operation->alg)) {
Steven Cooremane6804192021-03-19 18:28:56 +0100218 /* We'll set up the hash operation later in psa_hmac_setup_internal. */
219 operation->ctx.hmac.alg = 0;
220 status = PSA_SUCCESS;
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100222#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooremane6804192021-03-19 18:28:56 +0100223 {
Ronald Cron7a55deb2021-04-28 14:29:00 +0200224 (void) operation;
Steven Cooremanba9a5bf2021-04-29 16:21:24 +0200225 status = PSA_ERROR_NOT_SUPPORTED;
Steven Cooremane6804192021-03-19 18:28:56 +0100226 }
227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 if (status != PSA_SUCCESS) {
229 memset(operation, 0, sizeof(*operation));
230 }
231 return status;
Steven Cooremane6804192021-03-19 18:28:56 +0100232}
233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)
Steven Cooremane6804192021-03-19 18:28:56 +0100235{
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 if (operation->alg == 0) {
Steven Cooremane6804192021-03-19 18:28:56 +0100237 /* The object has (apparently) been initialized but it is not
238 * in use. It's ok to call abort on such an object, and there's
239 * nothing to do. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 return PSA_SUCCESS;
241 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100242#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
244 mbedtls_cipher_free(&operation->ctx.cmac);
245 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100246#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
247#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 if (PSA_ALG_IS_HMAC(operation->alg)) {
249 psa_hmac_abort_internal(&operation->ctx.hmac);
250 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100251#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooremane6804192021-03-19 18:28:56 +0100252 {
253 /* Sanity check (shouldn't happen: operation->alg should
254 * always have been initialized to a valid value). */
255 goto bad_state;
256 }
257
258 operation->alg = 0;
Steven Cooremane6804192021-03-19 18:28:56 +0100259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 return PSA_SUCCESS;
Steven Cooremane6804192021-03-19 18:28:56 +0100261
262bad_state:
263 /* If abort is called on an uninitialized object, we can't trust
264 * anything. Wipe the object in case it contains confidential data.
265 * This may result in a memory leak if a pointer gets overwritten,
266 * but it's too late to do anything about this. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 memset(operation, 0, sizeof(*operation));
268 return PSA_ERROR_BAD_STATE;
Steven Cooremane6804192021-03-19 18:28:56 +0100269}
270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,
272 const psa_key_attributes_t *attributes,
273 const uint8_t *key_buffer,
274 size_t key_buffer_size,
275 psa_algorithm_t alg)
Steven Cooremane6804192021-03-19 18:28:56 +0100276{
277 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
278
279 /* A context must be freshly initialized before it can be set up. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if (operation->alg != 0) {
281 return PSA_ERROR_BAD_STATE;
282 }
Steven Cooremane6804192021-03-19 18:28:56 +0100283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 status = mac_init(operation, alg);
285 if (status != PSA_SUCCESS) {
286 return status;
287 }
Steven Cooremane6804192021-03-19 18:28:56 +0100288
Ronald Cron0266cfe2021-03-13 18:50:11 +0100289#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
Steven Cooremandcd08112021-05-06 18:00:37 +0200291 /* Key buffer size for CMAC is dictated by the key bits set on the
292 * attributes, and previously validated by the core on key import. */
293 (void) key_buffer_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 status = cmac_setup(operation, attributes, key_buffer);
295 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100296#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
297#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 if (PSA_ALG_IS_HMAC(alg)) {
299 status = psa_hmac_setup_internal(&operation->ctx.hmac,
300 key_buffer,
301 key_buffer_size,
302 PSA_ALG_HMAC_GET_HASH(alg));
303 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100304#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooremane6804192021-03-19 18:28:56 +0100305 {
Steven Cooremanb29902a2021-05-10 09:47:05 +0200306 (void) attributes;
307 (void) key_buffer;
308 (void) key_buffer_size;
Steven Cooremane6804192021-03-19 18:28:56 +0100309 status = PSA_ERROR_NOT_SUPPORTED;
310 }
311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 if (status != PSA_SUCCESS) {
313 mbedtls_psa_mac_abort(operation);
314 }
Steven Cooremane6804192021-03-19 18:28:56 +0100315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 return status;
Steven Cooremane6804192021-03-19 18:28:56 +0100317}
318
Ronald Cron0266cfe2021-03-13 18:50:11 +0100319psa_status_t mbedtls_psa_mac_sign_setup(
320 mbedtls_psa_mac_operation_t *operation,
321 const psa_key_attributes_t *attributes,
322 const uint8_t *key_buffer,
323 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 psa_algorithm_t alg)
Ronald Cron0266cfe2021-03-13 18:50:11 +0100325{
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 return psa_mac_setup(operation, attributes,
327 key_buffer, key_buffer_size, alg);
Ronald Cron0266cfe2021-03-13 18:50:11 +0100328}
329
330psa_status_t mbedtls_psa_mac_verify_setup(
331 mbedtls_psa_mac_operation_t *operation,
332 const psa_key_attributes_t *attributes,
333 const uint8_t *key_buffer,
334 size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 psa_algorithm_t alg)
Ronald Cron0266cfe2021-03-13 18:50:11 +0100336{
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 return psa_mac_setup(operation, attributes,
338 key_buffer, key_buffer_size, alg);
Ronald Cron0266cfe2021-03-13 18:50:11 +0100339}
340
341psa_status_t mbedtls_psa_mac_update(
Steven Cooremand13a70f2021-03-19 15:24:23 +0100342 mbedtls_psa_mac_operation_t *operation,
343 const uint8_t *input,
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 size_t input_length)
Steven Cooremand13a70f2021-03-19 15:24:23 +0100345{
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 if (operation->alg == 0) {
347 return PSA_ERROR_BAD_STATE;
348 }
Steven Cooreman6e7f2912021-03-19 18:38:46 +0100349
Ronald Cron0266cfe2021-03-13 18:50:11 +0100350#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
352 return mbedtls_to_psa_error(
353 mbedtls_cipher_cmac_update(&operation->ctx.cmac,
354 input, input_length));
355 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100356#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
357#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 if (PSA_ALG_IS_HMAC(operation->alg)) {
359 return psa_hmac_update_internal(&operation->ctx.hmac,
360 input, input_length);
361 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100362#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooreman6e7f2912021-03-19 18:38:46 +0100363 {
364 /* This shouldn't happen if `operation` was initialized by
365 * a setup function. */
Steven Cooremanb29902a2021-05-10 09:47:05 +0200366 (void) input;
367 (void) input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 return PSA_ERROR_BAD_STATE;
Steven Cooreman6e7f2912021-03-19 18:38:46 +0100369 }
Steven Cooremand13a70f2021-03-19 15:24:23 +0100370}
371
Ronald Cron0266cfe2021-03-13 18:50:11 +0100372static psa_status_t psa_mac_finish_internal(
373 mbedtls_psa_mac_operation_t *operation,
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 uint8_t *mac, size_t mac_size)
Steven Cooremana5b860a2021-03-19 19:04:39 +0100375{
Ronald Cron0266cfe2021-03-13 18:50:11 +0100376#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
Steven Cooremana5b860a2021-03-19 19:04:39 +0100378 uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);
380 if (ret == 0) {
381 memcpy(mac, tmp, mac_size);
382 }
383 mbedtls_platform_zeroize(tmp, sizeof(tmp));
384 return mbedtls_to_psa_error(ret);
385 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100386#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
387#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (PSA_ALG_IS_HMAC(operation->alg)) {
389 return psa_hmac_finish_internal(&operation->ctx.hmac,
390 mac, mac_size);
391 } else
Ronald Cron0266cfe2021-03-13 18:50:11 +0100392#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
Steven Cooremana5b860a2021-03-19 19:04:39 +0100393 {
394 /* This shouldn't happen if `operation` was initialized by
395 * a setup function. */
Steven Cooreman72f736a2021-05-07 14:14:37 +0200396 (void) operation;
397 (void) mac;
398 (void) mac_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 return PSA_ERROR_BAD_STATE;
Steven Cooremana5b860a2021-03-19 19:04:39 +0100400 }
401}
402
Ronald Cron0266cfe2021-03-13 18:50:11 +0100403psa_status_t mbedtls_psa_mac_sign_finish(
Steven Cooremand13a70f2021-03-19 15:24:23 +0100404 mbedtls_psa_mac_operation_t *operation,
405 uint8_t *mac,
406 size_t mac_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 size_t *mac_length)
Steven Cooremand13a70f2021-03-19 15:24:23 +0100408{
Steven Cooreman094a77e2021-05-06 17:58:36 +0200409 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Steven Cooremana5b860a2021-03-19 19:04:39 +0100410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 if (operation->alg == 0) {
412 return PSA_ERROR_BAD_STATE;
413 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 status = psa_mac_finish_internal(operation, mac, mac_size);
416 if (status == PSA_SUCCESS) {
Steven Cooreman72f736a2021-05-07 14:14:37 +0200417 *mac_length = mac_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 return status;
Steven Cooremana5b860a2021-03-19 19:04:39 +0100421}
422
Ronald Cron0266cfe2021-03-13 18:50:11 +0100423psa_status_t mbedtls_psa_mac_verify_finish(
Steven Cooremand13a70f2021-03-19 15:24:23 +0100424 mbedtls_psa_mac_operation_t *operation,
425 const uint8_t *mac,
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 size_t mac_length)
Steven Cooremand13a70f2021-03-19 15:24:23 +0100427{
Steven Cooremana5b860a2021-03-19 19:04:39 +0100428 uint8_t actual_mac[PSA_MAC_MAX_SIZE];
Steven Cooreman094a77e2021-05-06 17:58:36 +0200429 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Steven Cooremana5b860a2021-03-19 19:04:39 +0100430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (operation->alg == 0) {
432 return PSA_ERROR_BAD_STATE;
433 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100434
Steven Cooreman72f736a2021-05-07 14:14:37 +0200435 /* Consistency check: requested MAC length fits our local buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 if (mac_length > sizeof(actual_mac)) {
437 return PSA_ERROR_INVALID_ARGUMENT;
438 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 status = psa_mac_finish_internal(operation, actual_mac, mac_length);
441 if (status != PSA_SUCCESS) {
Steven Cooremana5b860a2021-03-19 19:04:39 +0100442 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100444
Dave Rodgman78701152023-08-29 14:20:18 +0100445 if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {
Steven Cooremana5b860a2021-03-19 19:04:39 +0100446 status = PSA_ERROR_INVALID_SIGNATURE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 }
Steven Cooremana5b860a2021-03-19 19:04:39 +0100448
449cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
Steven Cooremana5b860a2021-03-19 19:04:39 +0100451
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 return status;
Steven Cooremand13a70f2021-03-19 15:24:23 +0100453}
Ronald Cron76be3e02021-06-17 17:34:43 +0200454
Ronald Cron0266cfe2021-03-13 18:50:11 +0100455psa_status_t mbedtls_psa_mac_compute(
Ronald Cron76be3e02021-06-17 17:34:43 +0200456 const psa_key_attributes_t *attributes,
457 const uint8_t *key_buffer,
458 size_t key_buffer_size,
459 psa_algorithm_t alg,
460 const uint8_t *input,
461 size_t input_length,
462 uint8_t *mac,
463 size_t mac_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 size_t *mac_length)
Ronald Cron76be3e02021-06-17 17:34:43 +0200465{
466 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
467 mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;
Gilles Peskine0e4907d2025-02-05 19:53:54 +0100468 /* Make sure the whole the operation is zeroed.
469 * PSA_MAC_OPERATION_INIT does not necessarily do it fully,
470 * since one field is a union and initializing a union does not
471 * necessarily initialize all of its members.
472 * In multipart operations, this is done in the API functions,
473 * before driver dispatch, since it needs to be done before calling
474 * the driver entry point. Here, we bypass the multipart API,
475 * so it's our job. */
476 memset(&operation, 0, sizeof(operation));
Ronald Cron76be3e02021-06-17 17:34:43 +0200477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 status = psa_mac_setup(&operation,
479 attributes, key_buffer, key_buffer_size,
480 alg);
481 if (status != PSA_SUCCESS) {
Ronald Cron76be3e02021-06-17 17:34:43 +0200482 goto exit;
Ronald Cron76be3e02021-06-17 17:34:43 +0200483 }
484
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 if (input_length > 0) {
486 status = mbedtls_psa_mac_update(&operation, input, input_length);
487 if (status != PSA_SUCCESS) {
488 goto exit;
489 }
490 }
491
492 status = psa_mac_finish_internal(&operation, mac, mac_size);
493 if (status == PSA_SUCCESS) {
Ronald Cron76be3e02021-06-17 17:34:43 +0200494 *mac_length = mac_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 }
Ronald Cron76be3e02021-06-17 17:34:43 +0200496
497exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 mbedtls_psa_mac_abort(&operation);
Ronald Cron76be3e02021-06-17 17:34:43 +0200499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 return status;
Ronald Cron76be3e02021-06-17 17:34:43 +0200501}
502
Ronald Cron0266cfe2021-03-13 18:50:11 +0100503#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */
Steven Cooremand13a70f2021-03-19 15:24:23 +0100504
505#endif /* MBEDTLS_PSA_CRYPTO_C */