blob: 17c7e49c1904d5fc034c9f4680dbf64d76b3bcd8 [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
7 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02008 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
Jens Wiklander817466c2018-05-22 13:49:31 +020020 */
21
22/*
23 * References:
24 *
25 * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
26 * CMAC Mode for Authentication
27 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
28 *
29 * - RFC 4493 - The AES-CMAC Algorithm
30 * https://tools.ietf.org/html/rfc4493
31 *
32 * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
33 * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
34 * Algorithm for the Internet Key Exchange Protocol (IKE)
35 * https://tools.ietf.org/html/rfc4615
36 *
37 * Additional test vectors: ISO/IEC 9797-1
38 *
39 */
40
Jerome Forissier79013242021-07-28 10:24:04 +020041#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020042
43#if defined(MBEDTLS_CMAC_C)
44
45#include "mbedtls/cmac.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010046#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020047#include "mbedtls/error.h"
Jerome Forissier79013242021-07-28 10:24:04 +020048#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020049
50#include <string.h>
51
Jens Wiklander3d3b0592019-03-20 15:30:29 +010052#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
Jens Wiklander817466c2018-05-22 13:49:31 +020053
54/*
55 * Multiplication by u in the Galois field of GF(2^n)
56 *
57 * As explained in NIST SP 800-38B, this can be computed:
58 *
59 * If MSB(p) = 0, then p = (p << 1)
60 * If MSB(p) = 1, then p = (p << 1) ^ R_n
61 * with R_64 = 0x1B and R_128 = 0x87
62 *
63 * Input and output MUST NOT point to the same buffer
64 * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
65 */
Jens Wiklander32b31802023-10-06 16:59:46 +020066static int cmac_multiply_by_u(unsigned char *output,
67 const unsigned char *input,
68 size_t blocksize)
Jens Wiklander817466c2018-05-22 13:49:31 +020069{
70 const unsigned char R_128 = 0x87;
71 const unsigned char R_64 = 0x1B;
72 unsigned char R_n, mask;
73 unsigned char overflow = 0x00;
74 int i;
75
Jens Wiklander32b31802023-10-06 16:59:46 +020076 if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +020077 R_n = R_128;
Jens Wiklander32b31802023-10-06 16:59:46 +020078 } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +020079 R_n = R_64;
Jens Wiklander32b31802023-10-06 16:59:46 +020080 } else {
81 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020082 }
83
Jens Wiklander32b31802023-10-06 16:59:46 +020084 for (i = (int) blocksize - 1; i >= 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +020085 output[i] = input[i] << 1 | overflow;
86 overflow = input[i] >> 7;
87 }
88
89 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
90 * using bit operations to avoid branches */
91
92 /* MSVC has a warning about unary minus on unsigned, but this is
93 * well-defined and precisely what we want to do here */
94#if defined(_MSC_VER)
95#pragma warning( push )
96#pragma warning( disable : 4146 )
97#endif
Jens Wiklander32b31802023-10-06 16:59:46 +020098 mask = -(input[0] >> 7);
Jens Wiklander817466c2018-05-22 13:49:31 +020099#if defined(_MSC_VER)
100#pragma warning( pop )
101#endif
102
Jens Wiklander32b31802023-10-06 16:59:46 +0200103 output[blocksize - 1] ^= R_n & mask;
Jens Wiklander817466c2018-05-22 13:49:31 +0200104
Jens Wiklander32b31802023-10-06 16:59:46 +0200105 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200106}
107
108/*
109 * Generate subkeys
110 *
111 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
112 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200113static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
114 unsigned char *K1, unsigned char *K2)
Jens Wiklander817466c2018-05-22 13:49:31 +0200115{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200116 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200117 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
118 size_t olen, block_size;
119
Jens Wiklander32b31802023-10-06 16:59:46 +0200120 mbedtls_platform_zeroize(L, sizeof(L));
Jens Wiklander817466c2018-05-22 13:49:31 +0200121
122 block_size = ctx->cipher_info->block_size;
123
124 /* Calculate Ek(0) */
Jens Wiklander32b31802023-10-06 16:59:46 +0200125 if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200126 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200127 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200128
129 /*
130 * Generate K1 and K2
131 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200132 if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200133 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200134 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200135
Jens Wiklander32b31802023-10-06 16:59:46 +0200136 if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200137 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200139
140exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200141 mbedtls_platform_zeroize(L, sizeof(L));
Jens Wiklander817466c2018-05-22 13:49:31 +0200142
Jens Wiklander32b31802023-10-06 16:59:46 +0200143 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200144}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100145#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
Jens Wiklander817466c2018-05-22 13:49:31 +0200146
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100147#if !defined(MBEDTLS_CMAC_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200148
149/*
150 * Create padded last block from (partial) last block.
151 *
152 * We can't use the padding option from the cipher layer, as it only works for
153 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
154 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200155static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
156 size_t padded_block_len,
157 const unsigned char *last_block,
158 size_t last_block_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200159{
160 size_t j;
161
Jens Wiklander32b31802023-10-06 16:59:46 +0200162 for (j = 0; j < padded_block_len; j++) {
163 if (j < last_block_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200164 padded_block[j] = last_block[j];
Jens Wiklander32b31802023-10-06 16:59:46 +0200165 } else if (j == last_block_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200166 padded_block[j] = 0x80;
Jens Wiklander32b31802023-10-06 16:59:46 +0200167 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +0200168 padded_block[j] = 0x00;
Jens Wiklander32b31802023-10-06 16:59:46 +0200169 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200170 }
171}
172
Edison Ai12484fc2018-12-19 15:36:28 +0800173int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx)
174{
175 mbedtls_cmac_context_t *cmac_ctx;
176
177 /* Allocated and initialise in the cipher context memory for the CMAC
178 * context */
Jens Wiklander32b31802023-10-06 16:59:46 +0200179 cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));
180 if (cmac_ctx == NULL)
181 return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
Edison Ai12484fc2018-12-19 15:36:28 +0800182
183 ctx->cmac_ctx = cmac_ctx;
184
Jens Wiklander32b31802023-10-06 16:59:46 +0200185 mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
Edison Ai12484fc2018-12-19 15:36:28 +0800186 return 0;
187}
188
Jens Wiklander32b31802023-10-06 16:59:46 +0200189int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
190 const unsigned char *key, size_t keybits)
Jens Wiklander817466c2018-05-22 13:49:31 +0200191{
192 mbedtls_cipher_type_t type;
Jens Wiklander817466c2018-05-22 13:49:31 +0200193 int retval;
194
Jens Wiklander32b31802023-10-06 16:59:46 +0200195 if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) {
196 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
197 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200198
Jens Wiklander32b31802023-10-06 16:59:46 +0200199 if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits,
200 MBEDTLS_ENCRYPT)) != 0) {
201 return retval;
202 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200203
204 type = ctx->cipher_info->type;
205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 switch (type) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200207 case MBEDTLS_CIPHER_AES_128_ECB:
208 case MBEDTLS_CIPHER_AES_192_ECB:
209 case MBEDTLS_CIPHER_AES_256_ECB:
210 case MBEDTLS_CIPHER_DES_EDE3_ECB:
211 break;
212 default:
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200214 }
215
Edison Ai12484fc2018-12-19 15:36:28 +0800216 /* Check if cmac ctx had been allocated by mbedtls_cipher_cmac_setup() */
217 if( ctx->cmac_ctx != NULL )
218 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200219
Edison Ai12484fc2018-12-19 15:36:28 +0800220 return mbedtls_cipher_cmac_setup( ctx );
Jens Wiklander817466c2018-05-22 13:49:31 +0200221}
222
Jens Wiklander32b31802023-10-06 16:59:46 +0200223int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
224 const unsigned char *input, size_t ilen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200225{
Jens Wiklander32b31802023-10-06 16:59:46 +0200226 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200227 unsigned char *state;
228 int ret = 0;
229 size_t n, j, olen, block_size;
230
Jens Wiklander32b31802023-10-06 16:59:46 +0200231 if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
232 ctx->cmac_ctx == NULL) {
233 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
234 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200235
236 cmac_ctx = ctx->cmac_ctx;
237 block_size = ctx->cipher_info->block_size;
238 state = ctx->cmac_ctx->state;
239
240 /* Is there data still to process from the last call, that's greater in
241 * size than a block? */
Jens Wiklander32b31802023-10-06 16:59:46 +0200242 if (cmac_ctx->unprocessed_len > 0 &&
243 ilen > block_size - cmac_ctx->unprocessed_len) {
244 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
245 input,
246 block_size - cmac_ctx->unprocessed_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200247
Jens Wiklander32b31802023-10-06 16:59:46 +0200248 mbedtls_xor(state, cmac_ctx->unprocessed_block, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200249
Jens Wiklander32b31802023-10-06 16:59:46 +0200250 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
251 &olen)) != 0) {
252 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200253 }
254
255 input += block_size - cmac_ctx->unprocessed_len;
256 ilen -= block_size - cmac_ctx->unprocessed_len;
257 cmac_ctx->unprocessed_len = 0;
258 }
259
260 /* n is the number of blocks including any final partial block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200261 n = (ilen + block_size - 1) / block_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200262
263 /* Iterate across the input data in block sized chunks, excluding any
264 * final partial or complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200265 for (j = 1; j < n; j++) {
266 mbedtls_xor(state, input, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200267
Jens Wiklander32b31802023-10-06 16:59:46 +0200268 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
269 &olen)) != 0) {
270 goto exit;
271 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200272
273 ilen -= block_size;
274 input += block_size;
275 }
276
277 /* If there is data left over that wasn't aligned to a block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200278 if (ilen > 0) {
279 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
280 input,
281 ilen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200282 cmac_ctx->unprocessed_len += ilen;
283 }
284
285exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200287}
288
Jens Wiklander32b31802023-10-06 16:59:46 +0200289int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
290 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200291{
Jens Wiklander32b31802023-10-06 16:59:46 +0200292 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200293 unsigned char *state, *last_block;
294 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
295 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
296 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200297 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200298 size_t olen, block_size;
299
Jens Wiklander32b31802023-10-06 16:59:46 +0200300 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
301 output == NULL) {
302 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
303 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200304
305 cmac_ctx = ctx->cmac_ctx;
306 block_size = ctx->cipher_info->block_size;
307 state = cmac_ctx->state;
308
Jens Wiklander32b31802023-10-06 16:59:46 +0200309 mbedtls_platform_zeroize(K1, sizeof(K1));
310 mbedtls_platform_zeroize(K2, sizeof(K2));
311 cmac_generate_subkeys(ctx, K1, K2);
Jens Wiklander817466c2018-05-22 13:49:31 +0200312
313 last_block = cmac_ctx->unprocessed_block;
314
315 /* Calculate last block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200316 if (cmac_ctx->unprocessed_len < block_size) {
317 cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);
318 mbedtls_xor(M_last, M_last, K2, block_size);
319 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +0200320 /* Last block is complete block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200321 mbedtls_xor(M_last, last_block, K1, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200322 }
323
324
Jens Wiklander32b31802023-10-06 16:59:46 +0200325 mbedtls_xor(state, M_last, state, block_size);
326 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
327 &olen)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200328 goto exit;
329 }
330
Jens Wiklander32b31802023-10-06 16:59:46 +0200331 memcpy(output, state, block_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200332
333exit:
334 /* Wipe the generated keys on the stack, and any other transients to avoid
335 * side channel leakage */
Jens Wiklander32b31802023-10-06 16:59:46 +0200336 mbedtls_platform_zeroize(K1, sizeof(K1));
337 mbedtls_platform_zeroize(K2, sizeof(K2));
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
339 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200340 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
341 sizeof(cmac_ctx->unprocessed_block));
Jens Wiklander817466c2018-05-22 13:49:31 +0200342
Jens Wiklander32b31802023-10-06 16:59:46 +0200343 mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX);
344 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200345}
346
Jens Wiklander32b31802023-10-06 16:59:46 +0200347int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200348{
Jens Wiklander32b31802023-10-06 16:59:46 +0200349 mbedtls_cmac_context_t *cmac_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200350
Jens Wiklander32b31802023-10-06 16:59:46 +0200351 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) {
352 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
353 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200354
355 cmac_ctx = ctx->cmac_ctx;
356
357 /* Reset the internal state */
358 cmac_ctx->unprocessed_len = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200359 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
360 sizeof(cmac_ctx->unprocessed_block));
361 mbedtls_platform_zeroize(cmac_ctx->state,
362 sizeof(cmac_ctx->state));
Jens Wiklander817466c2018-05-22 13:49:31 +0200363
Jens Wiklander32b31802023-10-06 16:59:46 +0200364 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200365}
366
Jens Wiklander32b31802023-10-06 16:59:46 +0200367int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
368 const unsigned char *key, size_t keylen,
369 const unsigned char *input, size_t ilen,
370 unsigned char *output)
Jens Wiklander817466c2018-05-22 13:49:31 +0200371{
372 mbedtls_cipher_context_t ctx;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200373 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200374
Jens Wiklander32b31802023-10-06 16:59:46 +0200375 if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) {
376 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
377 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200378
Jens Wiklander32b31802023-10-06 16:59:46 +0200379 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200380
Jens Wiklander32b31802023-10-06 16:59:46 +0200381 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200382 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200383 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200384
Jens Wiklander32b31802023-10-06 16:59:46 +0200385 ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);
386 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200387 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200388 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200389
Jens Wiklander32b31802023-10-06 16:59:46 +0200390 ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);
391 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200392 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200393 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200394
Jens Wiklander32b31802023-10-06 16:59:46 +0200395 ret = mbedtls_cipher_cmac_finish(&ctx, output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200396
397exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200398 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200399
Jens Wiklander32b31802023-10-06 16:59:46 +0200400 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200401}
402
403#if defined(MBEDTLS_AES_C)
404/*
405 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
406 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200407int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
408 const unsigned char *input, size_t in_len,
409 unsigned char output[16])
Jens Wiklander817466c2018-05-22 13:49:31 +0200410{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200411 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200412 const mbedtls_cipher_info_t *cipher_info;
413 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
414 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
415
Jens Wiklander32b31802023-10-06 16:59:46 +0200416 if (key == NULL || input == NULL || output == NULL) {
417 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
418 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200419
Jens Wiklander32b31802023-10-06 16:59:46 +0200420 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
421 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200422 /* Failing at this point must be due to a build issue */
423 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
424 goto exit;
425 }
426
Jens Wiklander32b31802023-10-06 16:59:46 +0200427 if (key_length == MBEDTLS_AES_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200428 /* Use key as is */
Jens Wiklander32b31802023-10-06 16:59:46 +0200429 memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);
430 } else {
431 memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200432
Jens Wiklander32b31802023-10-06 16:59:46 +0200433 ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
434 key_length, int_key);
435 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200436 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200437 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200438 }
439
Jens Wiklander32b31802023-10-06 16:59:46 +0200440 ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
441 output);
Jens Wiklander817466c2018-05-22 13:49:31 +0200442
443exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200444 mbedtls_platform_zeroize(int_key, sizeof(int_key));
Jens Wiklander817466c2018-05-22 13:49:31 +0200445
Jens Wiklander32b31802023-10-06 16:59:46 +0200446 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200447}
448#endif /* MBEDTLS_AES_C */
449
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100450#endif /* !MBEDTLS_CMAC_ALT */
451
Jens Wiklander817466c2018-05-22 13:49:31 +0200452#if defined(MBEDTLS_SELF_TEST)
453/*
454 * CMAC test data for SP800-38B
455 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
456 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
457 *
458 * AES-CMAC-PRF-128 test data from RFC 4615
459 * https://tools.ietf.org/html/rfc4615#page-4
460 */
461
462#define NB_CMAC_TESTS_PER_KEY 4
463#define NB_PRF_TESTS 3
464
465#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
466/* All CMAC test inputs are truncated from the same 64 byte buffer. */
467static const unsigned char test_message[] = {
468 /* PT */
469 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
470 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
471 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
472 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
473 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
474 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
475 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
476 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
477};
478#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
479
480#if defined(MBEDTLS_AES_C)
481/* Truncation point of message for AES CMAC tests */
482static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
483 /* Mlen */
484 0,
485 16,
486 20,
487 64
488};
489
490/* CMAC-AES128 Test Data */
491static const unsigned char aes_128_key[16] = {
492 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
493 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
494};
495static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
496 {
497 /* K1 */
498 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
499 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
500 },
501 {
502 /* K2 */
503 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
504 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
505 }
506};
Jens Wiklander32b31802023-10-06 16:59:46 +0200507static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
508{
Jens Wiklander817466c2018-05-22 13:49:31 +0200509 {
510 /* Example #1 */
511 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
512 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
513 },
514 {
515 /* Example #2 */
516 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
517 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
518 },
519 {
520 /* Example #3 */
521 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
522 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
523 },
524 {
525 /* Example #4 */
526 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
527 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
528 }
529};
530
531/* CMAC-AES192 Test Data */
532static const unsigned char aes_192_key[24] = {
533 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
534 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
535 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
536};
537static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
538 {
539 /* K1 */
540 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
541 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
542 },
543 {
544 /* K2 */
545 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
546 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
547 }
548};
Jens Wiklander32b31802023-10-06 16:59:46 +0200549static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
550{
Jens Wiklander817466c2018-05-22 13:49:31 +0200551 {
552 /* Example #1 */
553 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
554 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
555 },
556 {
557 /* Example #2 */
558 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
559 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
560 },
561 {
562 /* Example #3 */
563 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04,
564 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8
565 },
566 {
567 /* Example #4 */
568 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
569 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
570 }
571};
572
573/* CMAC-AES256 Test Data */
574static const unsigned char aes_256_key[32] = {
575 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
576 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
577 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
578 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
579};
580static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
581 {
582 /* K1 */
583 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
584 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
585 },
586 {
587 /* K2 */
588 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
589 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
590 }
591};
Jens Wiklander32b31802023-10-06 16:59:46 +0200592static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
593{
Jens Wiklander817466c2018-05-22 13:49:31 +0200594 {
595 /* Example #1 */
596 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
597 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
598 },
599 {
600 /* Example #2 */
601 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
602 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
603 },
604 {
605 /* Example #3 */
606 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a,
607 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93
608 },
609 {
610 /* Example #4 */
611 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
612 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
613 }
614};
615#endif /* MBEDTLS_AES_C */
616
617#if defined(MBEDTLS_DES_C)
618/* Truncation point of message for 3DES CMAC tests */
619static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
620 0,
621 16,
622 20,
623 32
624};
625
626/* CMAC-TDES (Generation) - 2 Key Test Data */
627static const unsigned char des3_2key_key[24] = {
628 /* Key1 */
629 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
630 /* Key2 */
631 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
632 /* Key3 */
633 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
634};
635static const unsigned char des3_2key_subkeys[2][8] = {
636 {
637 /* K1 */
638 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9
639 },
640 {
641 /* K2 */
642 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2
643 }
644};
Jens Wiklander32b31802023-10-06 16:59:46 +0200645static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
646 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200647 {
648 /* Sample #1 */
649 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60
650 },
651 {
652 /* Sample #2 */
653 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b
654 },
655 {
656 /* Sample #3 */
657 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69
658 },
659 {
660 /* Sample #4 */
661 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb
662 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200663 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200664
665/* CMAC-TDES (Generation) - 3 Key Test Data */
666static const unsigned char des3_3key_key[24] = {
667 /* Key1 */
668 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
669 /* Key2 */
670 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
671 /* Key3 */
672 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
673};
674static const unsigned char des3_3key_subkeys[2][8] = {
675 {
676 /* K1 */
677 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0
678 },
679 {
680 /* K2 */
681 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b
682 }
683};
Jens Wiklander32b31802023-10-06 16:59:46 +0200684static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
685 = {
Jens Wiklander817466c2018-05-22 13:49:31 +0200686 {
687 /* Sample #1 */
688 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50
689 },
690 {
691 /* Sample #2 */
692 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09
693 },
694 {
695 /* Sample #3 */
696 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2
697 },
698 {
699 /* Sample #4 */
700 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5
701 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200702 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200703
704#endif /* MBEDTLS_DES_C */
705
706#if defined(MBEDTLS_AES_C)
707/* AES AES-CMAC-PRF-128 Test Data */
708static const unsigned char PRFK[] = {
709 /* Key */
710 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
711 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
712 0xed, 0xcb
713};
714
715/* Sizes in bytes */
716static const size_t PRFKlen[NB_PRF_TESTS] = {
717 18,
718 16,
719 10
720};
721
722/* Message */
723static const unsigned char PRFM[] = {
724 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
725 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
726 0x10, 0x11, 0x12, 0x13
727};
728
729static const unsigned char PRFT[NB_PRF_TESTS][16] = {
730 {
731 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
732 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
733 },
734 {
735 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
736 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
737 },
738 {
739 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
740 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
741 }
742};
743#endif /* MBEDTLS_AES_C */
744
Jens Wiklander32b31802023-10-06 16:59:46 +0200745static int cmac_test_subkeys(int verbose,
746 const char *testname,
747 const unsigned char *key,
748 int keybits,
749 const unsigned char *subkeys,
750 mbedtls_cipher_type_t cipher_type,
751 int block_size,
752 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200753{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100754 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200755 mbedtls_cipher_context_t ctx;
756 const mbedtls_cipher_info_t *cipher_info;
757 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
758 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
759
Jens Wiklander32b31802023-10-06 16:59:46 +0200760 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
761 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200762 /* Failing at this point must be due to a build issue */
Jens Wiklander32b31802023-10-06 16:59:46 +0200763 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +0200764 }
765
Jens Wiklander32b31802023-10-06 16:59:46 +0200766 for (i = 0; i < num_tests; i++) {
767 if (verbose != 0) {
768 mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1);
769 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200770
Jens Wiklander32b31802023-10-06 16:59:46 +0200771 mbedtls_cipher_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200772
Jens Wiklander32b31802023-10-06 16:59:46 +0200773 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
774 if (verbose != 0) {
775 mbedtls_printf("test execution failed\n");
776 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200777
778 goto cleanup;
779 }
780
Jens Wiklander32b31802023-10-06 16:59:46 +0200781 if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,
782 MBEDTLS_ENCRYPT)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200783 /* When CMAC is implemented by an alternative implementation, or
784 * the underlying primitive itself is implemented alternatively,
785 * AES-192 may be unavailable. This should not cause the selftest
786 * function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200787 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
788 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
789 cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {
790 if (verbose != 0) {
791 mbedtls_printf("skipped\n");
792 }
Jerome Forissier79013242021-07-28 10:24:04 +0200793 goto next_test;
794 }
795
Jens Wiklander32b31802023-10-06 16:59:46 +0200796 if (verbose != 0) {
797 mbedtls_printf("test execution failed\n");
798 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200799
800 goto cleanup;
801 }
802
Jens Wiklander32b31802023-10-06 16:59:46 +0200803 ret = cmac_generate_subkeys(&ctx, K1, K2);
804 if (ret != 0) {
805 if (verbose != 0) {
806 mbedtls_printf("failed\n");
807 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200808
809 goto cleanup;
810 }
811
Jens Wiklander32b31802023-10-06 16:59:46 +0200812 if ((ret = memcmp(K1, subkeys, block_size)) != 0 ||
813 (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {
814 if (verbose != 0) {
815 mbedtls_printf("failed\n");
816 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200817
818 goto cleanup;
819 }
820
Jens Wiklander32b31802023-10-06 16:59:46 +0200821 if (verbose != 0) {
822 mbedtls_printf("passed\n");
823 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200824
Jerome Forissier79013242021-07-28 10:24:04 +0200825next_test:
Jens Wiklander32b31802023-10-06 16:59:46 +0200826 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200827 }
828
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100829 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200830 goto exit;
831
832cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200833 mbedtls_cipher_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200834
835exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200836 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200837}
838
Jens Wiklander32b31802023-10-06 16:59:46 +0200839static int cmac_test_wth_cipher(int verbose,
840 const char *testname,
841 const unsigned char *key,
842 int keybits,
843 const unsigned char *messages,
844 const unsigned int message_lengths[4],
845 const unsigned char *expected_result,
846 mbedtls_cipher_type_t cipher_type,
847 int block_size,
848 int num_tests)
Jens Wiklander817466c2018-05-22 13:49:31 +0200849{
850 const mbedtls_cipher_info_t *cipher_info;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100851 int i, ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200852 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
853
Jens Wiklander32b31802023-10-06 16:59:46 +0200854 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
855 if (cipher_info == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200856 /* Failing at this point must be due to a build issue */
857 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
858 goto exit;
859 }
860
Jens Wiklander32b31802023-10-06 16:59:46 +0200861 for (i = 0; i < num_tests; i++) {
862 if (verbose != 0) {
863 mbedtls_printf(" %s CMAC #%d: ", testname, i + 1);
864 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200865
Jens Wiklander32b31802023-10-06 16:59:46 +0200866 if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
867 message_lengths[i], output)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200868 /* When CMAC is implemented by an alternative implementation, or
869 * the underlying primitive itself is implemented alternatively,
870 * AES-192 and/or 3DES may be unavailable. This should not cause
871 * the selftest function to fail. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200872 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
873 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
874 (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
875 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {
876 if (verbose != 0) {
877 mbedtls_printf("skipped\n");
878 }
Jerome Forissier79013242021-07-28 10:24:04 +0200879 continue;
880 }
881
Jens Wiklander32b31802023-10-06 16:59:46 +0200882 if (verbose != 0) {
883 mbedtls_printf("failed\n");
884 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200885 goto exit;
886 }
887
Jens Wiklander32b31802023-10-06 16:59:46 +0200888 if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) {
889 if (verbose != 0) {
890 mbedtls_printf("failed\n");
891 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200892 goto exit;
893 }
894
Jens Wiklander32b31802023-10-06 16:59:46 +0200895 if (verbose != 0) {
896 mbedtls_printf("passed\n");
897 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200898 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100899 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200900
901exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200902 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200903}
904
905#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200906static int test_aes128_cmac_prf(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200907{
908 int i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200909 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200910 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
911
Jens Wiklander32b31802023-10-06 16:59:46 +0200912 for (i = 0; i < NB_PRF_TESTS; i++) {
913 mbedtls_printf(" AES CMAC 128 PRF #%d: ", i);
914 ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);
915 if (ret != 0 ||
916 memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200917
Jens Wiklander32b31802023-10-06 16:59:46 +0200918 if (verbose != 0) {
919 mbedtls_printf("failed\n");
920 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200921
Jens Wiklander32b31802023-10-06 16:59:46 +0200922 return ret;
923 } else if (verbose != 0) {
924 mbedtls_printf("passed\n");
Jens Wiklander817466c2018-05-22 13:49:31 +0200925 }
926 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200927 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200928}
929#endif /* MBEDTLS_AES_C */
930
Jens Wiklander32b31802023-10-06 16:59:46 +0200931int mbedtls_cmac_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200932{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200933 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200934
935#if defined(MBEDTLS_AES_C)
936 /* AES-128 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200937 if ((ret = cmac_test_subkeys(verbose,
938 "AES 128",
939 aes_128_key,
940 128,
941 (const unsigned char *) aes_128_subkeys,
942 MBEDTLS_CIPHER_AES_128_ECB,
943 MBEDTLS_AES_BLOCK_SIZE,
944 NB_CMAC_TESTS_PER_KEY)) != 0) {
945 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200946 }
947
Jens Wiklander32b31802023-10-06 16:59:46 +0200948 if ((ret = cmac_test_wth_cipher(verbose,
949 "AES 128",
950 aes_128_key,
951 128,
952 test_message,
953 aes_message_lengths,
954 (const unsigned char *) aes_128_expected_result,
955 MBEDTLS_CIPHER_AES_128_ECB,
956 MBEDTLS_AES_BLOCK_SIZE,
957 NB_CMAC_TESTS_PER_KEY)) != 0) {
958 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200959 }
960
961 /* AES-192 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200962 if ((ret = cmac_test_subkeys(verbose,
963 "AES 192",
964 aes_192_key,
965 192,
966 (const unsigned char *) aes_192_subkeys,
967 MBEDTLS_CIPHER_AES_192_ECB,
968 MBEDTLS_AES_BLOCK_SIZE,
969 NB_CMAC_TESTS_PER_KEY)) != 0) {
970 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200971 }
972
Jens Wiklander32b31802023-10-06 16:59:46 +0200973 if ((ret = cmac_test_wth_cipher(verbose,
974 "AES 192",
975 aes_192_key,
976 192,
977 test_message,
978 aes_message_lengths,
979 (const unsigned char *) aes_192_expected_result,
980 MBEDTLS_CIPHER_AES_192_ECB,
981 MBEDTLS_AES_BLOCK_SIZE,
982 NB_CMAC_TESTS_PER_KEY)) != 0) {
983 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200984 }
985
986 /* AES-256 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200987 if ((ret = cmac_test_subkeys(verbose,
988 "AES 256",
989 aes_256_key,
990 256,
991 (const unsigned char *) aes_256_subkeys,
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 }
997
Jens Wiklander32b31802023-10-06 16:59:46 +0200998 if ((ret = cmac_test_wth_cipher(verbose,
999 "AES 256",
1000 aes_256_key,
1001 256,
1002 test_message,
1003 aes_message_lengths,
1004 (const unsigned char *) aes_256_expected_result,
1005 MBEDTLS_CIPHER_AES_256_ECB,
1006 MBEDTLS_AES_BLOCK_SIZE,
1007 NB_CMAC_TESTS_PER_KEY)) != 0) {
1008 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001009 }
1010#endif /* MBEDTLS_AES_C */
1011
1012#if defined(MBEDTLS_DES_C)
1013 /* 3DES 2 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001014 if ((ret = cmac_test_subkeys(verbose,
1015 "3DES 2 key",
1016 des3_2key_key,
1017 192,
1018 (const unsigned char *) des3_2key_subkeys,
1019 MBEDTLS_CIPHER_DES_EDE3_ECB,
1020 MBEDTLS_DES3_BLOCK_SIZE,
1021 NB_CMAC_TESTS_PER_KEY)) != 0) {
1022 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001023 }
1024
Jens Wiklander32b31802023-10-06 16:59:46 +02001025 if ((ret = cmac_test_wth_cipher(verbose,
1026 "3DES 2 key",
1027 des3_2key_key,
1028 192,
1029 test_message,
1030 des3_message_lengths,
1031 (const unsigned char *) des3_2key_expected_result,
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
1038 /* 3DES 3 key */
Jens Wiklander32b31802023-10-06 16:59:46 +02001039 if ((ret = cmac_test_subkeys(verbose,
1040 "3DES 3 key",
1041 des3_3key_key,
1042 192,
1043 (const unsigned char *) des3_3key_subkeys,
1044 MBEDTLS_CIPHER_DES_EDE3_ECB,
1045 MBEDTLS_DES3_BLOCK_SIZE,
1046 NB_CMAC_TESTS_PER_KEY)) != 0) {
1047 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001048 }
1049
Jens Wiklander32b31802023-10-06 16:59:46 +02001050 if ((ret = cmac_test_wth_cipher(verbose,
1051 "3DES 3 key",
1052 des3_3key_key,
1053 192,
1054 test_message,
1055 des3_message_lengths,
1056 (const unsigned char *) des3_3key_expected_result,
1057 MBEDTLS_CIPHER_DES_EDE3_ECB,
1058 MBEDTLS_DES3_BLOCK_SIZE,
1059 NB_CMAC_TESTS_PER_KEY)) != 0) {
1060 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001061 }
1062#endif /* MBEDTLS_DES_C */
1063
1064#if defined(MBEDTLS_AES_C)
Jens Wiklander32b31802023-10-06 16:59:46 +02001065 if ((ret = test_aes128_cmac_prf(verbose)) != 0) {
1066 return ret;
1067 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001068#endif /* MBEDTLS_AES_C */
1069
Jens Wiklander32b31802023-10-06 16:59:46 +02001070 if (verbose != 0) {
1071 mbedtls_printf("\n");
1072 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001073
Jens Wiklander32b31802023-10-06 16:59:46 +02001074 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001075}
1076
1077#endif /* MBEDTLS_SELF_TEST */
1078
1079#endif /* MBEDTLS_CMAC_C */