blob: a1ef9475968975c9a010ad3990c38dd0eea288a6 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/**
2 * \file cmac.c
3 *
4 * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
5 *
Jerome Forissier79013242021-07-28 10:24:04 +02006 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02007 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02008 */
9
10/*
11 * References:
12 *
13 * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
14 * CMAC Mode for Authentication
15 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
16 *
17 * - RFC 4493 - The AES-CMAC Algorithm
18 * https://tools.ietf.org/html/rfc4493
19 *
20 * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
21 * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
22 * Algorithm for the Internet Key Exchange Protocol (IKE)
23 * https://tools.ietf.org/html/rfc4615
24 *
25 * Additional test vectors: ISO/IEC 9797-1
26 *
27 */
28
Jerome Forissier79013242021-07-28 10:24:04 +020029#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020030
31#if defined(MBEDTLS_CMAC_C)
32
33#include "mbedtls/cmac.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010034#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020035#include "mbedtls/error.h"
Jerome Forissier79013242021-07-28 10:24:04 +020036#include "mbedtls/platform.h"
Tom Van Eyckc1633172024-04-09 18:44:13 +020037#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020038
39#include <string.h>
40
Jens Wiklander3d3b0592019-03-20 15:30:29 +010041#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
Jens Wiklander817466c2018-05-22 13:49:31 +020042
43/*
44 * Multiplication by u in the Galois field of GF(2^n)
45 *
46 * As explained in NIST SP 800-38B, this can be computed:
47 *
48 * If MSB(p) = 0, then p = (p << 1)
49 * If MSB(p) = 1, then p = (p << 1) ^ R_n
50 * with R_64 = 0x1B and R_128 = 0x87
51 *
52 * Input and output MUST NOT point to the same buffer
53 * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
54 */
Jens Wiklander32b31802023-10-06 16:59:46 +020055static int cmac_multiply_by_u(unsigned char *output,
56 const unsigned char *input,
57 size_t blocksize)
Jens Wiklander817466c2018-05-22 13:49:31 +020058{
59 const unsigned char R_128 = 0x87;
Tom Van Eyckc1633172024-04-09 18:44:13 +020060 unsigned char R_n;
61 uint32_t overflow = 0x00;
Jens Wiklander817466c2018-05-22 13:49:31 +020062 int i;
63
Jens Wiklander32b31802023-10-06 16:59:46 +020064 if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +020065 R_n = R_128;
Tom Van Eyckc1633172024-04-09 18:44:13 +020066 }
67#if defined(MBEDTLS_DES_C)
68 else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
69 const unsigned char R_64 = 0x1B;
Jens Wiklander817466c2018-05-22 13:49:31 +020070 R_n = R_64;
Tom Van Eyckc1633172024-04-09 18:44:13 +020071 }
72#endif
73 else {
Jens Wiklander32b31802023-10-06 16:59:46 +020074 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020075 }
76
Tom Van Eyckc1633172024-04-09 18:44:13 +020077 for (i = (int) blocksize - 4; i >= 0; i -= 4) {
78 uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
79 uint32_t new_overflow = i32 >> 31;
80 i32 = (i32 << 1) | overflow;
81 MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
82 overflow = new_overflow;
Jens Wiklander817466c2018-05-22 13:49:31 +020083 }
84
Tom Van Eyckc1633172024-04-09 18:44:13 +020085 R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
86 output[blocksize - 1] ^= R_n;
Jens Wiklander817466c2018-05-22 13:49:31 +020087
Jens Wiklander32b31802023-10-06 16:59:46 +020088 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +020089}
90
91/*
92 * Generate subkeys
93 *
94 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
95 */
Jens Wiklander32b31802023-10-06 16:59:46 +020096static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
97 unsigned char *K1, unsigned char *K2)
Jens Wiklander817466c2018-05-22 13:49:31 +020098{
Jerome Forissier11fa71b2020-04-20 17:17:56 +020099 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200100 unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200101 size_t olen, block_size;
102
Jens Wiklander32b31802023-10-06 16:59:46 +0200103 mbedtls_platform_zeroize(L, sizeof(L));
Jens Wiklander817466c2018-05-22 13:49:31 +0200104
Tom Van Eyckc1633172024-04-09 18:44:13 +0200105 block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200106
107 /* Calculate Ek(0) */
Jens Wiklander32b31802023-10-06 16:59:46 +0200108 if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200109 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200110 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200111
112 /*
113 * Generate K1 and K2
114 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200115 if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200116 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200117 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200118
Jens Wiklander32b31802023-10-06 16:59:46 +0200119 if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200120 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200121 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200122
123exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200124 mbedtls_platform_zeroize(L, sizeof(L));
Jens Wiklander817466c2018-05-22 13:49:31 +0200125
Jens Wiklander32b31802023-10-06 16:59:46 +0200126 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200127}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100128#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
Jens Wiklander817466c2018-05-22 13:49:31 +0200129
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100130#if !defined(MBEDTLS_CMAC_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200131
132/*
133 * Create padded last block from (partial) last block.
134 *
135 * We can't use the padding option from the cipher layer, as it only works for
136 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
137 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200138static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
Jens Wiklander32b31802023-10-06 16:59:46 +0200139 size_t padded_block_len,
140 const unsigned char *last_block,
141 size_t last_block_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200142{
143 size_t j;
144
Jens Wiklander32b31802023-10-06 16:59:46 +0200145 for (j = 0; j < padded_block_len; j++) {
146 if (j < last_block_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200147 padded_block[j] = last_block[j];
Jens Wiklander32b31802023-10-06 16:59:46 +0200148 } else if (j == last_block_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200149 padded_block[j] = 0x80;
Jens Wiklander32b31802023-10-06 16:59:46 +0200150 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +0200151 padded_block[j] = 0x00;
Jens Wiklander32b31802023-10-06 16:59:46 +0200152 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200153 }
154}
155
Edison Aiab0eb552018-12-19 15:36:28 +0800156int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx)
157{
158 mbedtls_cmac_context_t *cmac_ctx;
159
160 /* Allocated and initialise in the cipher context memory for the CMAC
161 * context */
162 cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));
163 if (cmac_ctx == NULL)
164 return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
165
166 ctx->cmac_ctx = cmac_ctx;
167
168 mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
169 return 0;
170}
171
Jens Wiklander32b31802023-10-06 16:59:46 +0200172int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
173 const unsigned char *key, size_t keybits)
Jens Wiklander817466c2018-05-22 13:49:31 +0200174{
175 mbedtls_cipher_type_t type;
Jens Wiklander817466c2018-05-22 13:49:31 +0200176 int retval;
177
Jens Wiklander32b31802023-10-06 16:59:46 +0200178 if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) {
179 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
180 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200181
Jens Wiklander32b31802023-10-06 16:59:46 +0200182 if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits,
183 MBEDTLS_ENCRYPT)) != 0) {
184 return retval;
185 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200186
Tom Van Eyckc1633172024-04-09 18:44:13 +0200187 type = mbedtls_cipher_info_get_type(ctx->cipher_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200188
Jens Wiklander32b31802023-10-06 16:59:46 +0200189 switch (type) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200190 case MBEDTLS_CIPHER_AES_128_ECB:
191 case MBEDTLS_CIPHER_AES_192_ECB:
192 case MBEDTLS_CIPHER_AES_256_ECB:
193 case MBEDTLS_CIPHER_DES_EDE3_ECB:
194 break;
195 default:
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200197 }
198
Edison Aiab0eb552018-12-19 15:36:28 +0800199 /* Check if cmac ctx had been allocated by mbedtls_cipher_cmac_setup() */
200 if( ctx->cmac_ctx != NULL )
201 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200202
Edison Aiab0eb552018-12-19 15:36:28 +0800203 return mbedtls_cipher_cmac_setup( ctx );
Jens Wiklander817466c2018-05-22 13:49:31 +0200204}
205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
207 const unsigned char *input, size_t ilen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200208{
Jens Wiklander32b31802023-10-06 16:59:46 +0200209 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200210 unsigned char *state;
211 int ret = 0;
212 size_t n, j, olen, block_size;
213
Jens Wiklander32b31802023-10-06 16:59:46 +0200214 if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
215 ctx->cmac_ctx == NULL) {
216 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
217 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200218
219 cmac_ctx = ctx->cmac_ctx;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200220 block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200221 state = ctx->cmac_ctx->state;
222
Tom Van Eyckc1633172024-04-09 18:44:13 +0200223 /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
224 * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
225 MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);
226
Jens Wiklander817466c2018-05-22 13:49:31 +0200227 /* Is there data still to process from the last call, that's greater in
228 * size than a block? */
Jens Wiklander32b31802023-10-06 16:59:46 +0200229 if (cmac_ctx->unprocessed_len > 0 &&
230 ilen > block_size - cmac_ctx->unprocessed_len) {
231 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
232 input,
233 block_size - cmac_ctx->unprocessed_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200234
Tom Van Eyckc1633172024-04-09 18:44:13 +0200235 mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200236
Jens Wiklander32b31802023-10-06 16:59:46 +0200237 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
238 &olen)) != 0) {
239 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200240 }
241
242 input += block_size - cmac_ctx->unprocessed_len;
243 ilen -= block_size - cmac_ctx->unprocessed_len;
244 cmac_ctx->unprocessed_len = 0;
245 }
246
247 /* n is the number of blocks including any final partial block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200248 n = (ilen + block_size - 1) / block_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200249
250 /* Iterate across the input data in block sized chunks, excluding any
251 * final partial or complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200252 for (j = 1; j < n; j++) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200253 mbedtls_xor_no_simd(state, input, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200254
Jens Wiklander32b31802023-10-06 16:59:46 +0200255 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
256 &olen)) != 0) {
257 goto exit;
258 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200259
260 ilen -= block_size;
261 input += block_size;
262 }
263
264 /* If there is data left over that wasn't aligned to a block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200265 if (ilen > 0) {
266 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
267 input,
268 ilen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200269 cmac_ctx->unprocessed_len += ilen;
270 }
271
272exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200273 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200274}
275
Jens Wiklander32b31802023-10-06 16:59:46 +0200276int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
277 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200278{
Jens Wiklander32b31802023-10-06 16:59:46 +0200279 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200280 unsigned char *state, *last_block;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200281 unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
282 unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
283 unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200284 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200285 size_t olen, block_size;
286
Jens Wiklander32b31802023-10-06 16:59:46 +0200287 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
288 output == NULL) {
289 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
290 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200291
292 cmac_ctx = ctx->cmac_ctx;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200293 block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
294 MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning
Jens Wiklander817466c2018-05-22 13:49:31 +0200295 state = cmac_ctx->state;
296
Jens Wiklander32b31802023-10-06 16:59:46 +0200297 mbedtls_platform_zeroize(K1, sizeof(K1));
298 mbedtls_platform_zeroize(K2, sizeof(K2));
299 cmac_generate_subkeys(ctx, K1, K2);
Jens Wiklander817466c2018-05-22 13:49:31 +0200300
301 last_block = cmac_ctx->unprocessed_block;
302
303 /* Calculate last block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200304 if (cmac_ctx->unprocessed_len < block_size) {
305 cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);
306 mbedtls_xor(M_last, M_last, K2, block_size);
307 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +0200308 /* Last block is complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200309 mbedtls_xor(M_last, last_block, K1, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200310 }
311
312
Jens Wiklander32b31802023-10-06 16:59:46 +0200313 mbedtls_xor(state, M_last, state, block_size);
314 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
315 &olen)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200316 goto exit;
317 }
318
Jens Wiklander32b31802023-10-06 16:59:46 +0200319 memcpy(output, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200320
321exit:
322 /* Wipe the generated keys on the stack, and any other transients to avoid
323 * side channel leakage */
Jens Wiklander32b31802023-10-06 16:59:46 +0200324 mbedtls_platform_zeroize(K1, sizeof(K1));
325 mbedtls_platform_zeroize(K2, sizeof(K2));
Jens Wiklander817466c2018-05-22 13:49:31 +0200326
327 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200328 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
329 sizeof(cmac_ctx->unprocessed_block));
Jens Wiklander817466c2018-05-22 13:49:31 +0200330
Tom Van Eyckc1633172024-04-09 18:44:13 +0200331 mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE);
Jens Wiklander32b31802023-10-06 16:59:46 +0200332 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200333}
334
Jens Wiklander32b31802023-10-06 16:59:46 +0200335int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200336{
Jens Wiklander32b31802023-10-06 16:59:46 +0200337 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
Jens Wiklander32b31802023-10-06 16:59:46 +0200339 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) {
340 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
341 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200342
343 cmac_ctx = ctx->cmac_ctx;
344
345 /* Reset the internal state */
346 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200347 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
348 sizeof(cmac_ctx->unprocessed_block));
349 mbedtls_platform_zeroize(cmac_ctx->state,
350 sizeof(cmac_ctx->state));
Jens Wiklander817466c2018-05-22 13:49:31 +0200351
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200353}
354
Jens Wiklander32b31802023-10-06 16:59:46 +0200355int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
356 const unsigned char *key, size_t keylen,
357 const unsigned char *input, size_t ilen,
358 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200359{
360 mbedtls_cipher_context_t ctx;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200361 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200362
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) {
364 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
365 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200366
Jens Wiklander32b31802023-10-06 16:59:46 +0200367 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200368
Jens Wiklander32b31802023-10-06 16:59:46 +0200369 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200370 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200371 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200372
Jens Wiklander32b31802023-10-06 16:59:46 +0200373 ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);
374 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200375 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200376 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200377
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);
379 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200380 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200381 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200382
Jens Wiklander32b31802023-10-06 16:59:46 +0200383 ret = mbedtls_cipher_cmac_finish(&ctx, output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200384
385exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200386 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200387
Jens Wiklander32b31802023-10-06 16:59:46 +0200388 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200389}
390
391#if defined(MBEDTLS_AES_C)
392/*
393 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
394 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200395int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
396 const unsigned char *input, size_t in_len,
397 unsigned char output[16])
Jens Wiklander817466c2018-05-22 13:49:31 +0200398{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200399 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200400 const mbedtls_cipher_info_t *cipher_info;
401 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
402 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
403
Jens Wiklander32b31802023-10-06 16:59:46 +0200404 if (key == NULL || input == NULL || output == NULL) {
405 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
406 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200407
Jens Wiklander32b31802023-10-06 16:59:46 +0200408 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
409 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200410 /* Failing at this point must be due to a build issue */
411 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
412 goto exit;
413 }
414
Jens Wiklander32b31802023-10-06 16:59:46 +0200415 if (key_length == MBEDTLS_AES_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200416 /* Use key as is */
Jens Wiklander32b31802023-10-06 16:59:46 +0200417 memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);
418 } else {
419 memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200420
Jens Wiklander32b31802023-10-06 16:59:46 +0200421 ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
422 key_length, int_key);
423 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200424 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200425 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200426 }
427
Jens Wiklander32b31802023-10-06 16:59:46 +0200428 ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
429 output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200430
431exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200432 mbedtls_platform_zeroize(int_key, sizeof(int_key));
Jens Wiklander817466c2018-05-22 13:49:31 +0200433
Jens Wiklander32b31802023-10-06 16:59:46 +0200434 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200435}
436#endif /* MBEDTLS_AES_C */
437
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100438#endif /* !MBEDTLS_CMAC_ALT */
439
Jens Wiklander817466c2018-05-22 13:49:31 +0200440#if defined(MBEDTLS_SELF_TEST)
441/*
442 * CMAC test data for SP800-38B
443 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
444 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
445 *
446 * AES-CMAC-PRF-128 test data from RFC 4615
447 * https://tools.ietf.org/html/rfc4615#page-4
448 */
449
450#define NB_CMAC_TESTS_PER_KEY 4
451#define NB_PRF_TESTS 3
452
453#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
454/* All CMAC test inputs are truncated from the same 64 byte buffer. */
455static const unsigned char test_message[] = {
456 /* PT */
457 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
458 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
459 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
460 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
461 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
462 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
463 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
464 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
465};
466#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
467
468#if defined(MBEDTLS_AES_C)
469/* Truncation point of message for AES CMAC tests */
470static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
471 /* Mlen */
472 0,
473 16,
474 20,
475 64
476};
477
478/* CMAC-AES128 Test Data */
479static const unsigned char aes_128_key[16] = {
480 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
481 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
482};
483static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
484 {
485 /* K1 */
486 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
487 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
488 },
489 {
490 /* K2 */
491 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
492 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
493 }
494};
Jens Wiklander32b31802023-10-06 16:59:46 +0200495static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
496{
Jens Wiklander817466c2018-05-22 13:49:31 +0200497 {
498 /* Example #1 */
499 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
500 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
501 },
502 {
503 /* Example #2 */
504 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
505 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
506 },
507 {
508 /* Example #3 */
509 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
510 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
511 },
512 {
513 /* Example #4 */
514 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
515 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
516 }
517};
518
519/* CMAC-AES192 Test Data */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200520#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200521static const unsigned char aes_192_key[24] = {
522 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
523 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
524 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
525};
526static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
527 {
528 /* K1 */
529 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
530 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
531 },
532 {
533 /* K2 */
534 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
535 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
536 }
537};
Jens Wiklander32b31802023-10-06 16:59:46 +0200538static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
539{
Jens Wiklander817466c2018-05-22 13:49:31 +0200540 {
541 /* Example #1 */
542 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
543 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
544 },
545 {
546 /* Example #2 */
547 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
548 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
549 },
550 {
551 /* Example #3 */
552 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04,
553 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8
554 },
555 {
556 /* Example #4 */
557 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
558 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
559 }
560};
Tom Van Eyckc1633172024-04-09 18:44:13 +0200561#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200562
563/* CMAC-AES256 Test Data */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200564#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200565static const unsigned char aes_256_key[32] = {
566 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
567 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
568 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
569 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
570};
571static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
572 {
573 /* K1 */
574 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
575 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
576 },
577 {
578 /* K2 */
579 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
580 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
581 }
582};
Jens Wiklander32b31802023-10-06 16:59:46 +0200583static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
584{
Jens Wiklander817466c2018-05-22 13:49:31 +0200585 {
586 /* Example #1 */
587 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
588 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
589 },
590 {
591 /* Example #2 */
592 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
593 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
594 },
595 {
596 /* Example #3 */
597 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a,
598 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93
599 },
600 {
601 /* Example #4 */
602 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
603 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
604 }
605};
Tom Van Eyckc1633172024-04-09 18:44:13 +0200606#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200607#endif /* MBEDTLS_AES_C */
608
609#if defined(MBEDTLS_DES_C)
610/* Truncation point of message for 3DES CMAC tests */
611static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
612 0,
613 16,
614 20,
615 32
616};
617
618/* CMAC-TDES (Generation) - 2 Key Test Data */
619static const unsigned char des3_2key_key[24] = {
620 /* Key1 */
621 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
622 /* Key2 */
623 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
624 /* Key3 */
625 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
626};
627static const unsigned char des3_2key_subkeys[2][8] = {
628 {
629 /* K1 */
630 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9
631 },
632 {
633 /* K2 */
634 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2
635 }
636};
Jens Wiklander32b31802023-10-06 16:59:46 +0200637static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
638 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200639 {
640 /* Sample #1 */
641 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60
642 },
643 {
644 /* Sample #2 */
645 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b
646 },
647 {
648 /* Sample #3 */
649 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69
650 },
651 {
652 /* Sample #4 */
653 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb
654 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200655 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200656
657/* CMAC-TDES (Generation) - 3 Key Test Data */
658static const unsigned char des3_3key_key[24] = {
659 /* Key1 */
660 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
661 /* Key2 */
662 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
663 /* Key3 */
664 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
665};
666static const unsigned char des3_3key_subkeys[2][8] = {
667 {
668 /* K1 */
669 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0
670 },
671 {
672 /* K2 */
673 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b
674 }
675};
Jens Wiklander32b31802023-10-06 16:59:46 +0200676static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
677 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200678 {
679 /* Sample #1 */
680 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50
681 },
682 {
683 /* Sample #2 */
684 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09
685 },
686 {
687 /* Sample #3 */
688 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2
689 },
690 {
691 /* Sample #4 */
692 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5
693 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200694 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200695
696#endif /* MBEDTLS_DES_C */
697
698#if defined(MBEDTLS_AES_C)
699/* AES AES-CMAC-PRF-128 Test Data */
700static const unsigned char PRFK[] = {
701 /* Key */
702 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
703 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
704 0xed, 0xcb
705};
706
707/* Sizes in bytes */
708static const size_t PRFKlen[NB_PRF_TESTS] = {
709 18,
710 16,
711 10
712};
713
714/* Message */
715static const unsigned char PRFM[] = {
716 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
717 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
718 0x10, 0x11, 0x12, 0x13
719};
720
721static const unsigned char PRFT[NB_PRF_TESTS][16] = {
722 {
723 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
724 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
725 },
726 {
727 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
728 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
729 },
730 {
731 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
732 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
733 }
734};
735#endif /* MBEDTLS_AES_C */
736
Jens Wiklander32b31802023-10-06 16:59:46 +0200737static int cmac_test_subkeys(int verbose,
738 const char *testname,
739 const unsigned char *key,
740 int keybits,
741 const unsigned char *subkeys,
742 mbedtls_cipher_type_t cipher_type,
743 int block_size,
744 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200745{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100746 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200747 mbedtls_cipher_context_t ctx;
748 const mbedtls_cipher_info_t *cipher_info;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200749 unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
750 unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200751
Jens Wiklander32b31802023-10-06 16:59:46 +0200752 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
753 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200754 /* Failing at this point must be due to a build issue */
Jens Wiklander32b31802023-10-06 16:59:46 +0200755 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +0200756 }
757
Jens Wiklander32b31802023-10-06 16:59:46 +0200758 for (i = 0; i < num_tests; i++) {
759 if (verbose != 0) {
760 mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1);
761 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200762
Jens Wiklander32b31802023-10-06 16:59:46 +0200763 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200764
Jens Wiklander32b31802023-10-06 16:59:46 +0200765 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
766 if (verbose != 0) {
767 mbedtls_printf("test execution failed\n");
768 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200769
770 goto cleanup;
771 }
772
Jens Wiklander32b31802023-10-06 16:59:46 +0200773 if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,
774 MBEDTLS_ENCRYPT)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200775 /* When CMAC is implemented by an alternative implementation, or
776 * the underlying primitive itself is implemented alternatively,
777 * AES-192 may be unavailable. This should not cause the selftest
778 * function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200779 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
780 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
781 cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {
782 if (verbose != 0) {
783 mbedtls_printf("skipped\n");
784 }
Jerome Forissier79013242021-07-28 10:24:04 +0200785 goto next_test;
786 }
787
Jens Wiklander32b31802023-10-06 16:59:46 +0200788 if (verbose != 0) {
789 mbedtls_printf("test execution failed\n");
790 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200791
792 goto cleanup;
793 }
794
Jens Wiklander32b31802023-10-06 16:59:46 +0200795 ret = cmac_generate_subkeys(&ctx, K1, K2);
796 if (ret != 0) {
797 if (verbose != 0) {
798 mbedtls_printf("failed\n");
799 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200800
801 goto cleanup;
802 }
803
Jens Wiklander32b31802023-10-06 16:59:46 +0200804 if ((ret = memcmp(K1, subkeys, block_size)) != 0 ||
805 (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {
806 if (verbose != 0) {
807 mbedtls_printf("failed\n");
808 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200809
810 goto cleanup;
811 }
812
Jens Wiklander32b31802023-10-06 16:59:46 +0200813 if (verbose != 0) {
814 mbedtls_printf("passed\n");
815 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200816
Jerome Forissier79013242021-07-28 10:24:04 +0200817next_test:
Jens Wiklander32b31802023-10-06 16:59:46 +0200818 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200819 }
820
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100821 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200822 goto exit;
823
824cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200825 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200826
827exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200828 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200829}
830
Jens Wiklander32b31802023-10-06 16:59:46 +0200831static int cmac_test_wth_cipher(int verbose,
832 const char *testname,
833 const unsigned char *key,
834 int keybits,
835 const unsigned char *messages,
836 const unsigned int message_lengths[4],
837 const unsigned char *expected_result,
838 mbedtls_cipher_type_t cipher_type,
839 int block_size,
840 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200841{
842 const mbedtls_cipher_info_t *cipher_info;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100843 int i, ret = 0;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200844 unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200845
Jens Wiklander32b31802023-10-06 16:59:46 +0200846 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
847 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200848 /* Failing at this point must be due to a build issue */
849 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
850 goto exit;
851 }
852
Jens Wiklander32b31802023-10-06 16:59:46 +0200853 for (i = 0; i < num_tests; i++) {
854 if (verbose != 0) {
855 mbedtls_printf(" %s CMAC #%d: ", testname, i + 1);
856 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200857
Jens Wiklander32b31802023-10-06 16:59:46 +0200858 if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
859 message_lengths[i], output)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200860 /* When CMAC is implemented by an alternative implementation, or
861 * the underlying primitive itself is implemented alternatively,
862 * AES-192 and/or 3DES may be unavailable. This should not cause
863 * the selftest function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200864 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
865 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
866 (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
867 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {
868 if (verbose != 0) {
869 mbedtls_printf("skipped\n");
870 }
Jerome Forissier79013242021-07-28 10:24:04 +0200871 continue;
872 }
873
Jens Wiklander32b31802023-10-06 16:59:46 +0200874 if (verbose != 0) {
875 mbedtls_printf("failed\n");
876 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200877 goto exit;
878 }
879
Jens Wiklander32b31802023-10-06 16:59:46 +0200880 if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) {
881 if (verbose != 0) {
882 mbedtls_printf("failed\n");
883 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200884 goto exit;
885 }
886
Jens Wiklander32b31802023-10-06 16:59:46 +0200887 if (verbose != 0) {
888 mbedtls_printf("passed\n");
889 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200890 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100891 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200892
893exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200894 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200895}
896
897#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200898static int test_aes128_cmac_prf(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200899{
900 int i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200901 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200902 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
903
Jens Wiklander32b31802023-10-06 16:59:46 +0200904 for (i = 0; i < NB_PRF_TESTS; i++) {
905 mbedtls_printf(" AES CMAC 128 PRF #%d: ", i);
906 ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);
907 if (ret != 0 ||
908 memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200909
Jens Wiklander32b31802023-10-06 16:59:46 +0200910 if (verbose != 0) {
911 mbedtls_printf("failed\n");
912 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200913
Jens Wiklander32b31802023-10-06 16:59:46 +0200914 return ret;
915 } else if (verbose != 0) {
916 mbedtls_printf("passed\n");
Jens Wiklander817466c2018-05-22 13:49:31 +0200917 }
918 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200919 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200920}
921#endif /* MBEDTLS_AES_C */
922
Jens Wiklander32b31802023-10-06 16:59:46 +0200923int mbedtls_cmac_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200924{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200925 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200926
927#if defined(MBEDTLS_AES_C)
928 /* AES-128 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200929 if ((ret = cmac_test_subkeys(verbose,
930 "AES 128",
931 aes_128_key,
932 128,
933 (const unsigned char *) aes_128_subkeys,
934 MBEDTLS_CIPHER_AES_128_ECB,
935 MBEDTLS_AES_BLOCK_SIZE,
936 NB_CMAC_TESTS_PER_KEY)) != 0) {
937 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200938 }
939
Jens Wiklander32b31802023-10-06 16:59:46 +0200940 if ((ret = cmac_test_wth_cipher(verbose,
941 "AES 128",
942 aes_128_key,
943 128,
944 test_message,
945 aes_message_lengths,
946 (const unsigned char *) aes_128_expected_result,
947 MBEDTLS_CIPHER_AES_128_ECB,
948 MBEDTLS_AES_BLOCK_SIZE,
949 NB_CMAC_TESTS_PER_KEY)) != 0) {
950 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200951 }
952
953 /* AES-192 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200954#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander32b31802023-10-06 16:59:46 +0200955 if ((ret = cmac_test_subkeys(verbose,
956 "AES 192",
957 aes_192_key,
958 192,
959 (const unsigned char *) aes_192_subkeys,
960 MBEDTLS_CIPHER_AES_192_ECB,
961 MBEDTLS_AES_BLOCK_SIZE,
962 NB_CMAC_TESTS_PER_KEY)) != 0) {
963 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200964 }
965
Jens Wiklander32b31802023-10-06 16:59:46 +0200966 if ((ret = cmac_test_wth_cipher(verbose,
967 "AES 192",
968 aes_192_key,
969 192,
970 test_message,
971 aes_message_lengths,
972 (const unsigned char *) aes_192_expected_result,
973 MBEDTLS_CIPHER_AES_192_ECB,
974 MBEDTLS_AES_BLOCK_SIZE,
975 NB_CMAC_TESTS_PER_KEY)) != 0) {
976 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200977 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200978#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200979
980 /* AES-256 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200981#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander32b31802023-10-06 16:59:46 +0200982 if ((ret = cmac_test_subkeys(verbose,
983 "AES 256",
984 aes_256_key,
985 256,
986 (const unsigned char *) aes_256_subkeys,
987 MBEDTLS_CIPHER_AES_256_ECB,
988 MBEDTLS_AES_BLOCK_SIZE,
989 NB_CMAC_TESTS_PER_KEY)) != 0) {
990 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200991 }
992
Jens Wiklander32b31802023-10-06 16:59:46 +0200993 if ((ret = cmac_test_wth_cipher(verbose,
994 "AES 256",
995 aes_256_key,
996 256,
997 test_message,
998 aes_message_lengths,
999 (const unsigned char *) aes_256_expected_result,
1000 MBEDTLS_CIPHER_AES_256_ECB,
1001 MBEDTLS_AES_BLOCK_SIZE,
1002 NB_CMAC_TESTS_PER_KEY)) != 0) {
1003 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001004 }
Tom Van Eyckc1633172024-04-09 18:44:13 +02001005#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +02001006#endif /* MBEDTLS_AES_C */
1007
1008#if defined(MBEDTLS_DES_C)
1009 /* 3DES 2 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001010 if ((ret = cmac_test_subkeys(verbose,
1011 "3DES 2 key",
1012 des3_2key_key,
1013 192,
1014 (const unsigned char *) des3_2key_subkeys,
1015 MBEDTLS_CIPHER_DES_EDE3_ECB,
1016 MBEDTLS_DES3_BLOCK_SIZE,
1017 NB_CMAC_TESTS_PER_KEY)) != 0) {
1018 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001019 }
1020
Jens Wiklander32b31802023-10-06 16:59:46 +02001021 if ((ret = cmac_test_wth_cipher(verbose,
1022 "3DES 2 key",
1023 des3_2key_key,
1024 192,
1025 test_message,
1026 des3_message_lengths,
1027 (const unsigned char *) des3_2key_expected_result,
1028 MBEDTLS_CIPHER_DES_EDE3_ECB,
1029 MBEDTLS_DES3_BLOCK_SIZE,
1030 NB_CMAC_TESTS_PER_KEY)) != 0) {
1031 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001032 }
1033
1034 /* 3DES 3 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001035 if ((ret = cmac_test_subkeys(verbose,
1036 "3DES 3 key",
1037 des3_3key_key,
1038 192,
1039 (const unsigned char *) des3_3key_subkeys,
1040 MBEDTLS_CIPHER_DES_EDE3_ECB,
1041 MBEDTLS_DES3_BLOCK_SIZE,
1042 NB_CMAC_TESTS_PER_KEY)) != 0) {
1043 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001044 }
1045
Jens Wiklander32b31802023-10-06 16:59:46 +02001046 if ((ret = cmac_test_wth_cipher(verbose,
1047 "3DES 3 key",
1048 des3_3key_key,
1049 192,
1050 test_message,
1051 des3_message_lengths,
1052 (const unsigned char *) des3_3key_expected_result,
1053 MBEDTLS_CIPHER_DES_EDE3_ECB,
1054 MBEDTLS_DES3_BLOCK_SIZE,
1055 NB_CMAC_TESTS_PER_KEY)) != 0) {
1056 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001057 }
1058#endif /* MBEDTLS_DES_C */
1059
1060#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +02001061 if ((ret = test_aes128_cmac_prf(verbose)) != 0) {
1062 return ret;
1063 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001064#endif /* MBEDTLS_AES_C */
1065
Jens Wiklander32b31802023-10-06 16:59:46 +02001066 if (verbose != 0) {
1067 mbedtls_printf("\n");
1068 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001069
Jens Wiklander32b31802023-10-06 16:59:46 +02001070 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001071}
1072
1073#endif /* MBEDTLS_SELF_TEST */
1074
1075#endif /* MBEDTLS_CMAC_C */