blob: eda10d0b3dd1bcd9cc2189a6164ca6a6324dba8b [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
Jens Wiklander32b31802023-10-06 16:59:46 +0200156int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
157 const unsigned char *key, size_t keybits)
Jens Wiklander817466c2018-05-22 13:49:31 +0200158{
159 mbedtls_cipher_type_t type;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200160 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200161 int retval;
162
Jens Wiklander32b31802023-10-06 16:59:46 +0200163 if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) {
164 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
165 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200166
Jens Wiklander32b31802023-10-06 16:59:46 +0200167 if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits,
168 MBEDTLS_ENCRYPT)) != 0) {
169 return retval;
170 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200171
Tom Van Eyckc1633172024-04-09 18:44:13 +0200172 type = mbedtls_cipher_info_get_type(ctx->cipher_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200173
Jens Wiklander32b31802023-10-06 16:59:46 +0200174 switch (type) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200175 case MBEDTLS_CIPHER_AES_128_ECB:
176 case MBEDTLS_CIPHER_AES_192_ECB:
177 case MBEDTLS_CIPHER_AES_256_ECB:
178 case MBEDTLS_CIPHER_DES_EDE3_ECB:
179 break;
180 default:
Jens Wiklander32b31802023-10-06 16:59:46 +0200181 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200182 }
183
Tom Van Eyckc1633172024-04-09 18:44:13 +0200184 /* Allocated and initialise in the cipher context memory for the CMAC
185 * context */
186 cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));
187 if (cmac_ctx == NULL) {
188 return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
189 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200190
Tom Van Eyckc1633172024-04-09 18:44:13 +0200191 ctx->cmac_ctx = cmac_ctx;
192
193 mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
194
195 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200196}
197
Jens Wiklander32b31802023-10-06 16:59:46 +0200198int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
199 const unsigned char *input, size_t ilen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200200{
Jens Wiklander32b31802023-10-06 16:59:46 +0200201 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200202 unsigned char *state;
203 int ret = 0;
204 size_t n, j, olen, block_size;
205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
207 ctx->cmac_ctx == NULL) {
208 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
209 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200210
211 cmac_ctx = ctx->cmac_ctx;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200212 block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200213 state = ctx->cmac_ctx->state;
214
Tom Van Eyckc1633172024-04-09 18:44:13 +0200215 /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
216 * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
217 MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);
218
Jens Wiklander817466c2018-05-22 13:49:31 +0200219 /* Is there data still to process from the last call, that's greater in
220 * size than a block? */
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 if (cmac_ctx->unprocessed_len > 0 &&
222 ilen > block_size - cmac_ctx->unprocessed_len) {
223 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
224 input,
225 block_size - cmac_ctx->unprocessed_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200226
Tom Van Eyckc1633172024-04-09 18:44:13 +0200227 mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200228
Jens Wiklander32b31802023-10-06 16:59:46 +0200229 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
230 &olen)) != 0) {
231 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200232 }
233
234 input += block_size - cmac_ctx->unprocessed_len;
235 ilen -= block_size - cmac_ctx->unprocessed_len;
236 cmac_ctx->unprocessed_len = 0;
237 }
238
239 /* n is the number of blocks including any final partial block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200240 n = (ilen + block_size - 1) / block_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200241
242 /* Iterate across the input data in block sized chunks, excluding any
243 * final partial or complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200244 for (j = 1; j < n; j++) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200245 mbedtls_xor_no_simd(state, input, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200246
Jens Wiklander32b31802023-10-06 16:59:46 +0200247 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
248 &olen)) != 0) {
249 goto exit;
250 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200251
252 ilen -= block_size;
253 input += block_size;
254 }
255
256 /* If there is data left over that wasn't aligned to a block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200257 if (ilen > 0) {
258 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
259 input,
260 ilen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200261 cmac_ctx->unprocessed_len += ilen;
262 }
263
264exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200265 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200266}
267
Jens Wiklander32b31802023-10-06 16:59:46 +0200268int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
269 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200270{
Jens Wiklander32b31802023-10-06 16:59:46 +0200271 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200272 unsigned char *state, *last_block;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200273 unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
274 unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
275 unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200276 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200277 size_t olen, block_size;
278
Jens Wiklander32b31802023-10-06 16:59:46 +0200279 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
280 output == NULL) {
281 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
282 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200283
284 cmac_ctx = ctx->cmac_ctx;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200285 block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
286 MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning
Jens Wiklander817466c2018-05-22 13:49:31 +0200287 state = cmac_ctx->state;
288
Jens Wiklander32b31802023-10-06 16:59:46 +0200289 mbedtls_platform_zeroize(K1, sizeof(K1));
290 mbedtls_platform_zeroize(K2, sizeof(K2));
291 cmac_generate_subkeys(ctx, K1, K2);
Jens Wiklander817466c2018-05-22 13:49:31 +0200292
293 last_block = cmac_ctx->unprocessed_block;
294
295 /* Calculate last block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200296 if (cmac_ctx->unprocessed_len < block_size) {
297 cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);
298 mbedtls_xor(M_last, M_last, K2, block_size);
299 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +0200300 /* Last block is complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200301 mbedtls_xor(M_last, last_block, K1, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200302 }
303
304
Jens Wiklander32b31802023-10-06 16:59:46 +0200305 mbedtls_xor(state, M_last, state, block_size);
306 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
307 &olen)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200308 goto exit;
309 }
310
Jens Wiklander32b31802023-10-06 16:59:46 +0200311 memcpy(output, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200312
313exit:
314 /* Wipe the generated keys on the stack, and any other transients to avoid
315 * side channel leakage */
Jens Wiklander32b31802023-10-06 16:59:46 +0200316 mbedtls_platform_zeroize(K1, sizeof(K1));
317 mbedtls_platform_zeroize(K2, sizeof(K2));
Jens Wiklander817466c2018-05-22 13:49:31 +0200318
319 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200320 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
321 sizeof(cmac_ctx->unprocessed_block));
Jens Wiklander817466c2018-05-22 13:49:31 +0200322
Tom Van Eyckc1633172024-04-09 18:44:13 +0200323 mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE);
Jens Wiklander32b31802023-10-06 16:59:46 +0200324 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200325}
326
Jens Wiklander32b31802023-10-06 16:59:46 +0200327int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200328{
Jens Wiklander32b31802023-10-06 16:59:46 +0200329 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200330
Jens Wiklander32b31802023-10-06 16:59:46 +0200331 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) {
332 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
333 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200334
335 cmac_ctx = ctx->cmac_ctx;
336
337 /* Reset the internal state */
338 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200339 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
340 sizeof(cmac_ctx->unprocessed_block));
341 mbedtls_platform_zeroize(cmac_ctx->state,
342 sizeof(cmac_ctx->state));
Jens Wiklander817466c2018-05-22 13:49:31 +0200343
Jens Wiklander32b31802023-10-06 16:59:46 +0200344 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200345}
346
Jens Wiklander32b31802023-10-06 16:59:46 +0200347int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
348 const unsigned char *key, size_t keylen,
349 const unsigned char *input, size_t ilen,
350 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200351{
352 mbedtls_cipher_context_t ctx;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200353 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200354
Jens Wiklander32b31802023-10-06 16:59:46 +0200355 if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) {
356 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
357 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200358
Jens Wiklander32b31802023-10-06 16:59:46 +0200359 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200360
Jens Wiklander32b31802023-10-06 16:59:46 +0200361 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200362 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200364
Jens Wiklander32b31802023-10-06 16:59:46 +0200365 ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);
366 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200367 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200368 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200369
Jens Wiklander32b31802023-10-06 16:59:46 +0200370 ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);
371 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200372 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200373 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200374
Jens Wiklander32b31802023-10-06 16:59:46 +0200375 ret = mbedtls_cipher_cmac_finish(&ctx, output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200376
377exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200379
Jens Wiklander32b31802023-10-06 16:59:46 +0200380 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200381}
382
383#if defined(MBEDTLS_AES_C)
384/*
385 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
386 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200387int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
388 const unsigned char *input, size_t in_len,
389 unsigned char output[16])
Jens Wiklander817466c2018-05-22 13:49:31 +0200390{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200391 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200392 const mbedtls_cipher_info_t *cipher_info;
393 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
394 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
395
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 if (key == NULL || input == NULL || output == NULL) {
397 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
398 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200399
Jens Wiklander32b31802023-10-06 16:59:46 +0200400 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
401 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200402 /* Failing at this point must be due to a build issue */
403 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
404 goto exit;
405 }
406
Jens Wiklander32b31802023-10-06 16:59:46 +0200407 if (key_length == MBEDTLS_AES_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200408 /* Use key as is */
Jens Wiklander32b31802023-10-06 16:59:46 +0200409 memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);
410 } else {
411 memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200412
Jens Wiklander32b31802023-10-06 16:59:46 +0200413 ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
414 key_length, int_key);
415 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200416 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200417 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200418 }
419
Jens Wiklander32b31802023-10-06 16:59:46 +0200420 ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
421 output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200422
423exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200424 mbedtls_platform_zeroize(int_key, sizeof(int_key));
Jens Wiklander817466c2018-05-22 13:49:31 +0200425
Jens Wiklander32b31802023-10-06 16:59:46 +0200426 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200427}
428#endif /* MBEDTLS_AES_C */
429
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100430#endif /* !MBEDTLS_CMAC_ALT */
431
Jens Wiklander817466c2018-05-22 13:49:31 +0200432#if defined(MBEDTLS_SELF_TEST)
433/*
434 * CMAC test data for SP800-38B
435 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
436 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
437 *
438 * AES-CMAC-PRF-128 test data from RFC 4615
439 * https://tools.ietf.org/html/rfc4615#page-4
440 */
441
442#define NB_CMAC_TESTS_PER_KEY 4
443#define NB_PRF_TESTS 3
444
445#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
446/* All CMAC test inputs are truncated from the same 64 byte buffer. */
447static const unsigned char test_message[] = {
448 /* PT */
449 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
450 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
451 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
452 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
453 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
454 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
455 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
456 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
457};
458#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
459
460#if defined(MBEDTLS_AES_C)
461/* Truncation point of message for AES CMAC tests */
462static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
463 /* Mlen */
464 0,
465 16,
466 20,
467 64
468};
469
470/* CMAC-AES128 Test Data */
471static const unsigned char aes_128_key[16] = {
472 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
473 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
474};
475static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
476 {
477 /* K1 */
478 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
479 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
480 },
481 {
482 /* K2 */
483 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
484 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
485 }
486};
Jens Wiklander32b31802023-10-06 16:59:46 +0200487static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
488{
Jens Wiklander817466c2018-05-22 13:49:31 +0200489 {
490 /* Example #1 */
491 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
492 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
493 },
494 {
495 /* Example #2 */
496 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
497 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
498 },
499 {
500 /* Example #3 */
501 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
502 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
503 },
504 {
505 /* Example #4 */
506 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
507 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
508 }
509};
510
511/* CMAC-AES192 Test Data */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200512#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200513static const unsigned char aes_192_key[24] = {
514 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
515 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
516 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
517};
518static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
519 {
520 /* K1 */
521 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
522 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
523 },
524 {
525 /* K2 */
526 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
527 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
528 }
529};
Jens Wiklander32b31802023-10-06 16:59:46 +0200530static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
531{
Jens Wiklander817466c2018-05-22 13:49:31 +0200532 {
533 /* Example #1 */
534 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
535 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
536 },
537 {
538 /* Example #2 */
539 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
540 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
541 },
542 {
543 /* Example #3 */
544 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04,
545 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8
546 },
547 {
548 /* Example #4 */
549 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
550 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
551 }
552};
Tom Van Eyckc1633172024-04-09 18:44:13 +0200553#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200554
555/* CMAC-AES256 Test Data */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200556#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200557static const unsigned char aes_256_key[32] = {
558 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
559 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
560 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
561 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
562};
563static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
564 {
565 /* K1 */
566 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
567 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
568 },
569 {
570 /* K2 */
571 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
572 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
573 }
574};
Jens Wiklander32b31802023-10-06 16:59:46 +0200575static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
576{
Jens Wiklander817466c2018-05-22 13:49:31 +0200577 {
578 /* Example #1 */
579 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
580 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
581 },
582 {
583 /* Example #2 */
584 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
585 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
586 },
587 {
588 /* Example #3 */
589 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a,
590 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93
591 },
592 {
593 /* Example #4 */
594 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
595 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
596 }
597};
Tom Van Eyckc1633172024-04-09 18:44:13 +0200598#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200599#endif /* MBEDTLS_AES_C */
600
601#if defined(MBEDTLS_DES_C)
602/* Truncation point of message for 3DES CMAC tests */
603static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
604 0,
605 16,
606 20,
607 32
608};
609
610/* CMAC-TDES (Generation) - 2 Key Test Data */
611static const unsigned char des3_2key_key[24] = {
612 /* Key1 */
613 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
614 /* Key2 */
615 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
616 /* Key3 */
617 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
618};
619static const unsigned char des3_2key_subkeys[2][8] = {
620 {
621 /* K1 */
622 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9
623 },
624 {
625 /* K2 */
626 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2
627 }
628};
Jens Wiklander32b31802023-10-06 16:59:46 +0200629static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
630 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200631 {
632 /* Sample #1 */
633 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60
634 },
635 {
636 /* Sample #2 */
637 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b
638 },
639 {
640 /* Sample #3 */
641 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69
642 },
643 {
644 /* Sample #4 */
645 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb
646 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200647 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200648
649/* CMAC-TDES (Generation) - 3 Key Test Data */
650static const unsigned char des3_3key_key[24] = {
651 /* Key1 */
652 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
653 /* Key2 */
654 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
655 /* Key3 */
656 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
657};
658static const unsigned char des3_3key_subkeys[2][8] = {
659 {
660 /* K1 */
661 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0
662 },
663 {
664 /* K2 */
665 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b
666 }
667};
Jens Wiklander32b31802023-10-06 16:59:46 +0200668static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
669 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200670 {
671 /* Sample #1 */
672 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50
673 },
674 {
675 /* Sample #2 */
676 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09
677 },
678 {
679 /* Sample #3 */
680 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2
681 },
682 {
683 /* Sample #4 */
684 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5
685 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200686 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200687
688#endif /* MBEDTLS_DES_C */
689
690#if defined(MBEDTLS_AES_C)
691/* AES AES-CMAC-PRF-128 Test Data */
692static const unsigned char PRFK[] = {
693 /* Key */
694 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
695 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
696 0xed, 0xcb
697};
698
699/* Sizes in bytes */
700static const size_t PRFKlen[NB_PRF_TESTS] = {
701 18,
702 16,
703 10
704};
705
706/* Message */
707static const unsigned char PRFM[] = {
708 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
709 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
710 0x10, 0x11, 0x12, 0x13
711};
712
713static const unsigned char PRFT[NB_PRF_TESTS][16] = {
714 {
715 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
716 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
717 },
718 {
719 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
720 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
721 },
722 {
723 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
724 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
725 }
726};
727#endif /* MBEDTLS_AES_C */
728
Jens Wiklander32b31802023-10-06 16:59:46 +0200729static int cmac_test_subkeys(int verbose,
730 const char *testname,
731 const unsigned char *key,
732 int keybits,
733 const unsigned char *subkeys,
734 mbedtls_cipher_type_t cipher_type,
735 int block_size,
736 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200737{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100738 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200739 mbedtls_cipher_context_t ctx;
740 const mbedtls_cipher_info_t *cipher_info;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200741 unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
742 unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200743
Jens Wiklander32b31802023-10-06 16:59:46 +0200744 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
745 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200746 /* Failing at this point must be due to a build issue */
Jens Wiklander32b31802023-10-06 16:59:46 +0200747 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +0200748 }
749
Jens Wiklander32b31802023-10-06 16:59:46 +0200750 for (i = 0; i < num_tests; i++) {
751 if (verbose != 0) {
752 mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1);
753 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200754
Jens Wiklander32b31802023-10-06 16:59:46 +0200755 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200756
Jens Wiklander32b31802023-10-06 16:59:46 +0200757 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
758 if (verbose != 0) {
759 mbedtls_printf("test execution failed\n");
760 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200761
762 goto cleanup;
763 }
764
Jens Wiklander32b31802023-10-06 16:59:46 +0200765 if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,
766 MBEDTLS_ENCRYPT)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200767 /* When CMAC is implemented by an alternative implementation, or
768 * the underlying primitive itself is implemented alternatively,
769 * AES-192 may be unavailable. This should not cause the selftest
770 * function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200771 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
772 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
773 cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {
774 if (verbose != 0) {
775 mbedtls_printf("skipped\n");
776 }
Jerome Forissier79013242021-07-28 10:24:04 +0200777 goto next_test;
778 }
779
Jens Wiklander32b31802023-10-06 16:59:46 +0200780 if (verbose != 0) {
781 mbedtls_printf("test execution failed\n");
782 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200783
784 goto cleanup;
785 }
786
Jens Wiklander32b31802023-10-06 16:59:46 +0200787 ret = cmac_generate_subkeys(&ctx, K1, K2);
788 if (ret != 0) {
789 if (verbose != 0) {
790 mbedtls_printf("failed\n");
791 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200792
793 goto cleanup;
794 }
795
Jens Wiklander32b31802023-10-06 16:59:46 +0200796 if ((ret = memcmp(K1, subkeys, block_size)) != 0 ||
797 (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {
798 if (verbose != 0) {
799 mbedtls_printf("failed\n");
800 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200801
802 goto cleanup;
803 }
804
Jens Wiklander32b31802023-10-06 16:59:46 +0200805 if (verbose != 0) {
806 mbedtls_printf("passed\n");
807 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200808
Jerome Forissier79013242021-07-28 10:24:04 +0200809next_test:
Jens Wiklander32b31802023-10-06 16:59:46 +0200810 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200811 }
812
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100813 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200814 goto exit;
815
816cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200817 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200818
819exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200820 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200821}
822
Jens Wiklander32b31802023-10-06 16:59:46 +0200823static int cmac_test_wth_cipher(int verbose,
824 const char *testname,
825 const unsigned char *key,
826 int keybits,
827 const unsigned char *messages,
828 const unsigned int message_lengths[4],
829 const unsigned char *expected_result,
830 mbedtls_cipher_type_t cipher_type,
831 int block_size,
832 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200833{
834 const mbedtls_cipher_info_t *cipher_info;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100835 int i, ret = 0;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200836 unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200837
Jens Wiklander32b31802023-10-06 16:59:46 +0200838 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
839 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200840 /* Failing at this point must be due to a build issue */
841 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
842 goto exit;
843 }
844
Jens Wiklander32b31802023-10-06 16:59:46 +0200845 for (i = 0; i < num_tests; i++) {
846 if (verbose != 0) {
847 mbedtls_printf(" %s CMAC #%d: ", testname, i + 1);
848 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200849
Jens Wiklander32b31802023-10-06 16:59:46 +0200850 if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
851 message_lengths[i], output)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200852 /* When CMAC is implemented by an alternative implementation, or
853 * the underlying primitive itself is implemented alternatively,
854 * AES-192 and/or 3DES may be unavailable. This should not cause
855 * the selftest function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200856 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
857 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
858 (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
859 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {
860 if (verbose != 0) {
861 mbedtls_printf("skipped\n");
862 }
Jerome Forissier79013242021-07-28 10:24:04 +0200863 continue;
864 }
865
Jens Wiklander32b31802023-10-06 16:59:46 +0200866 if (verbose != 0) {
867 mbedtls_printf("failed\n");
868 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200869 goto exit;
870 }
871
Jens Wiklander32b31802023-10-06 16:59:46 +0200872 if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) {
873 if (verbose != 0) {
874 mbedtls_printf("failed\n");
875 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200876 goto exit;
877 }
878
Jens Wiklander32b31802023-10-06 16:59:46 +0200879 if (verbose != 0) {
880 mbedtls_printf("passed\n");
881 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200882 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100883 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200884
885exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200886 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200887}
888
889#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200890static int test_aes128_cmac_prf(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200891{
892 int i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200893 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200894 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
895
Jens Wiklander32b31802023-10-06 16:59:46 +0200896 for (i = 0; i < NB_PRF_TESTS; i++) {
897 mbedtls_printf(" AES CMAC 128 PRF #%d: ", i);
898 ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);
899 if (ret != 0 ||
900 memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200901
Jens Wiklander32b31802023-10-06 16:59:46 +0200902 if (verbose != 0) {
903 mbedtls_printf("failed\n");
904 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200905
Jens Wiklander32b31802023-10-06 16:59:46 +0200906 return ret;
907 } else if (verbose != 0) {
908 mbedtls_printf("passed\n");
Jens Wiklander817466c2018-05-22 13:49:31 +0200909 }
910 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200911 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200912}
913#endif /* MBEDTLS_AES_C */
914
Jens Wiklander32b31802023-10-06 16:59:46 +0200915int mbedtls_cmac_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200916{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200917 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200918
919#if defined(MBEDTLS_AES_C)
920 /* AES-128 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200921 if ((ret = cmac_test_subkeys(verbose,
922 "AES 128",
923 aes_128_key,
924 128,
925 (const unsigned char *) aes_128_subkeys,
926 MBEDTLS_CIPHER_AES_128_ECB,
927 MBEDTLS_AES_BLOCK_SIZE,
928 NB_CMAC_TESTS_PER_KEY)) != 0) {
929 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200930 }
931
Jens Wiklander32b31802023-10-06 16:59:46 +0200932 if ((ret = cmac_test_wth_cipher(verbose,
933 "AES 128",
934 aes_128_key,
935 128,
936 test_message,
937 aes_message_lengths,
938 (const unsigned char *) aes_128_expected_result,
939 MBEDTLS_CIPHER_AES_128_ECB,
940 MBEDTLS_AES_BLOCK_SIZE,
941 NB_CMAC_TESTS_PER_KEY)) != 0) {
942 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200943 }
944
945 /* AES-192 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200946#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander32b31802023-10-06 16:59:46 +0200947 if ((ret = cmac_test_subkeys(verbose,
948 "AES 192",
949 aes_192_key,
950 192,
951 (const unsigned char *) aes_192_subkeys,
952 MBEDTLS_CIPHER_AES_192_ECB,
953 MBEDTLS_AES_BLOCK_SIZE,
954 NB_CMAC_TESTS_PER_KEY)) != 0) {
955 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200956 }
957
Jens Wiklander32b31802023-10-06 16:59:46 +0200958 if ((ret = cmac_test_wth_cipher(verbose,
959 "AES 192",
960 aes_192_key,
961 192,
962 test_message,
963 aes_message_lengths,
964 (const unsigned char *) aes_192_expected_result,
965 MBEDTLS_CIPHER_AES_192_ECB,
966 MBEDTLS_AES_BLOCK_SIZE,
967 NB_CMAC_TESTS_PER_KEY)) != 0) {
968 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200969 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200970#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200971
972 /* AES-256 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200973#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander32b31802023-10-06 16:59:46 +0200974 if ((ret = cmac_test_subkeys(verbose,
975 "AES 256",
976 aes_256_key,
977 256,
978 (const unsigned char *) aes_256_subkeys,
979 MBEDTLS_CIPHER_AES_256_ECB,
980 MBEDTLS_AES_BLOCK_SIZE,
981 NB_CMAC_TESTS_PER_KEY)) != 0) {
982 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200983 }
984
Jens Wiklander32b31802023-10-06 16:59:46 +0200985 if ((ret = cmac_test_wth_cipher(verbose,
986 "AES 256",
987 aes_256_key,
988 256,
989 test_message,
990 aes_message_lengths,
991 (const unsigned char *) aes_256_expected_result,
992 MBEDTLS_CIPHER_AES_256_ECB,
993 MBEDTLS_AES_BLOCK_SIZE,
994 NB_CMAC_TESTS_PER_KEY)) != 0) {
995 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200996 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200997#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200998#endif /* MBEDTLS_AES_C */
999
1000#if defined(MBEDTLS_DES_C)
1001 /* 3DES 2 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001002 if ((ret = cmac_test_subkeys(verbose,
1003 "3DES 2 key",
1004 des3_2key_key,
1005 192,
1006 (const unsigned char *) des3_2key_subkeys,
1007 MBEDTLS_CIPHER_DES_EDE3_ECB,
1008 MBEDTLS_DES3_BLOCK_SIZE,
1009 NB_CMAC_TESTS_PER_KEY)) != 0) {
1010 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001011 }
1012
Jens Wiklander32b31802023-10-06 16:59:46 +02001013 if ((ret = cmac_test_wth_cipher(verbose,
1014 "3DES 2 key",
1015 des3_2key_key,
1016 192,
1017 test_message,
1018 des3_message_lengths,
1019 (const unsigned char *) des3_2key_expected_result,
1020 MBEDTLS_CIPHER_DES_EDE3_ECB,
1021 MBEDTLS_DES3_BLOCK_SIZE,
1022 NB_CMAC_TESTS_PER_KEY)) != 0) {
1023 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001024 }
1025
1026 /* 3DES 3 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001027 if ((ret = cmac_test_subkeys(verbose,
1028 "3DES 3 key",
1029 des3_3key_key,
1030 192,
1031 (const unsigned char *) des3_3key_subkeys,
1032 MBEDTLS_CIPHER_DES_EDE3_ECB,
1033 MBEDTLS_DES3_BLOCK_SIZE,
1034 NB_CMAC_TESTS_PER_KEY)) != 0) {
1035 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001036 }
1037
Jens Wiklander32b31802023-10-06 16:59:46 +02001038 if ((ret = cmac_test_wth_cipher(verbose,
1039 "3DES 3 key",
1040 des3_3key_key,
1041 192,
1042 test_message,
1043 des3_message_lengths,
1044 (const unsigned char *) des3_3key_expected_result,
1045 MBEDTLS_CIPHER_DES_EDE3_ECB,
1046 MBEDTLS_DES3_BLOCK_SIZE,
1047 NB_CMAC_TESTS_PER_KEY)) != 0) {
1048 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001049 }
1050#endif /* MBEDTLS_DES_C */
1051
1052#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +02001053 if ((ret = test_aes128_cmac_prf(verbose)) != 0) {
1054 return ret;
1055 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001056#endif /* MBEDTLS_AES_C */
1057
Jens Wiklander32b31802023-10-06 16:59:46 +02001058 if (verbose != 0) {
1059 mbedtls_printf("\n");
1060 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001061
Jens Wiklander32b31802023-10-06 16:59:46 +02001062 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001063}
1064
1065#endif /* MBEDTLS_SELF_TEST */
1066
1067#endif /* MBEDTLS_CMAC_C */