blob: 40c15a8877b2dced9e3837ad500f9d916ba0fb5b [file] [log] [blame]
Andres Amaya Garciaaf610a02016-12-14 10:13:43 +00001/**
Brian Murray53e23b62016-09-13 14:00:15 -07002 * \file cmac.c
Simon Butcher327398a2016-10-05 14:09:11 +01003 *
Simon Butcher69283e52016-10-06 12:49:58 +01004 * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
Robert Cragie3d23b1d2015-12-15 07:38:11 +00005 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02006 * Copyright The Mbed TLS Contributors
Robert Cragie3d23b1d2015-12-15 07:38:11 +00007 * SPDX-License-Identifier: Apache-2.0
8 *
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.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000020 */
21
22/*
Brian Murray53e23b62016-09-13 14:00:15 -070023 * References:
Simon Butcher327398a2016-10-05 14:09:11 +010024 *
25 * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
26 * CMAC Mode for Authentication
Janos Follathcd13bd22016-12-13 11:51:04 +000027 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
Simon Butcher327398a2016-10-05 14:09:11 +010028 *
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 *
Robert Cragie3d23b1d2015-12-15 07:38:11 +000039 */
40
Gilles Peskinedb09ef62020-06-03 01:43:33 +020041#include "common.h"
Robert Cragie3d23b1d2015-12-15 07:38:11 +000042
43#if defined(MBEDTLS_CMAC_C)
44
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020045# include "mbedtls/cmac.h"
46# include "mbedtls/platform_util.h"
47# include "mbedtls/error.h"
48# include "mbedtls/platform.h"
Robert Cragie3d23b1d2015-12-15 07:38:11 +000049
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020050# include <string.h>
Robert Cragie3d23b1d2015-12-15 07:38:11 +000051
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020052# if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
Steven Cooreman63342772017-04-04 11:47:16 +020053
Robert Cragie3d23b1d2015-12-15 07:38:11 +000054/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070055 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000056 *
Brian Murray72b69e32016-09-13 14:21:01 -070057 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000058 *
Simon Butcher327398a2016-10-05 14:09:11 +010059 * 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
Brian J Murray2adecba2016-11-06 04:45:15 -080064 * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000065 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020066static int cmac_multiply_by_u(unsigned char *output,
67 const unsigned char *input,
68 size_t blocksize)
Robert Cragie3d23b1d2015-12-15 07:38:11 +000069{
Brian Murrayb0c3c432016-05-18 14:29:51 -070070 const unsigned char R_128 = 0x87;
71 const unsigned char R_64 = 0x1B;
72 unsigned char R_n, mask;
73 unsigned char overflow = 0x00;
Simon Butcher327398a2016-10-05 14:09:11 +010074 int i;
Brian Murrayb0c3c432016-05-18 14:29:51 -070075
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020076 if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
Brian Murrayb0c3c432016-05-18 14:29:51 -070077 R_n = R_128;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020078 } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
Brian Murrayb0c3c432016-05-18 14:29:51 -070079 R_n = R_64;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020080 } else {
81 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Brian Murrayb0c3c432016-05-18 14:29:51 -070082 }
83
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020084 for (i = (int)blocksize - 1; i >= 0; i--) {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000085 output[i] = input[i] << 1 | overflow;
86 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000087 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000088
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000089 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
90 * using bit operations to avoid branches */
Simon Butcher327398a2016-10-05 14:09:11 +010091
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000092 /* MSVC has a warning about unary minus on unsigned, but this is
93 * well-defined and precisely what we want to do here */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020094# if defined(_MSC_VER)
95# pragma warning(push)
96# pragma warning(disable : 4146)
97# endif
98 mask = -(input[0] >> 7);
99# if defined(_MSC_VER)
100# pragma warning(pop)
101# endif
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000102
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200103 output[blocksize - 1] ^= R_n & mask;
Simon Butcher327398a2016-10-05 14:09:11 +0100104
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200105 return 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000106}
107
108/*
109 * Generate subkeys
Simon Butcher327398a2016-10-05 14:09:11 +0100110 *
111 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000112 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200113static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
114 unsigned char *K1,
115 unsigned char *K2)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000116{
Janos Follath24eed8d2019-11-22 13:21:35 +0000117 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher69283e52016-10-06 12:49:58 +0100118 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700119 size_t olen, block_size;
120
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200121 mbedtls_platform_zeroize(L, sizeof(L));
Brian Murrayb0c3c432016-05-18 14:29:51 -0700122
Simon Butcher327398a2016-10-05 14:09:11 +0100123 block_size = ctx->cipher_info->block_size;
124
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000125 /* Calculate Ek(0) */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0)
Brian Murrayb0c3c432016-05-18 14:29:51 -0700127 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000128
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000129 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000130 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000131 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200132 if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0)
Brian Murrayb0c3c432016-05-18 14:29:51 -0700133 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000134
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200135 if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0)
Simon Butcher327398a2016-10-05 14:09:11 +0100136 goto exit;
137
138exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139 mbedtls_platform_zeroize(L, sizeof(L));
Simon Butcher327398a2016-10-05 14:09:11 +0100140
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200141 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000142}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200143# endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000144
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200145# if !defined(MBEDTLS_CMAC_ALT)
146static void cmac_xor_block(unsigned char *output,
147 const unsigned char *input1,
148 const unsigned char *input2,
149 const size_t block_size)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000150{
Hanno Becker61937d42017-04-26 15:01:23 +0100151 size_t idx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200153 for (idx = 0; idx < block_size; idx++)
154 output[idx] = input1[idx] ^ input2[idx];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000155}
156
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000157/*
158 * Create padded last block from (partial) last block.
159 *
160 * We can't use the padding option from the cipher layer, as it only works for
161 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
162 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200163static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
164 size_t padded_block_len,
165 const unsigned char *last_block,
166 size_t last_block_len)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000167{
168 size_t j;
169
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170 for (j = 0; j < padded_block_len; j++) {
171 if (j < last_block_len)
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000172 padded_block[j] = last_block[j];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200173 else if (j == last_block_len)
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000174 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000175 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000176 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000177 }
178}
179
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200180int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
181 const unsigned char *key,
182 size_t keybits)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000183{
Simon Butcher327398a2016-10-05 14:09:11 +0100184 mbedtls_cipher_type_t type;
185 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher327398a2016-10-05 14:09:11 +0100186 int retval;
187
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200188 if (ctx == NULL || ctx->cipher_info == NULL || key == NULL)
189 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Simon Butcher327398a2016-10-05 14:09:11 +0100190
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200191 if ((retval = mbedtls_cipher_setkey(ctx, key, (int)keybits,
192 MBEDTLS_ENCRYPT)) != 0)
193 return retval;
Simon Butcher327398a2016-10-05 14:09:11 +0100194
Simon Butcher327398a2016-10-05 14:09:11 +0100195 type = ctx->cipher_info->type;
196
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200197 switch (type) {
Simon Butcher327398a2016-10-05 14:09:11 +0100198 case MBEDTLS_CIPHER_AES_128_ECB:
199 case MBEDTLS_CIPHER_AES_192_ECB:
200 case MBEDTLS_CIPHER_AES_256_ECB:
201 case MBEDTLS_CIPHER_DES_EDE3_ECB:
202 break;
203 default:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200204 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Simon Butcher327398a2016-10-05 14:09:11 +0100205 }
206
207 /* Allocated and initialise in the cipher context memory for the CMAC
208 * context */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200209 cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));
210 if (cmac_ctx == NULL)
211 return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
Simon Butcher327398a2016-10-05 14:09:11 +0100212
213 ctx->cmac_ctx = cmac_ctx;
214
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200215 mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
Simon Butcher327398a2016-10-05 14:09:11 +0100216
217 return 0;
218}
219
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200220int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
221 const unsigned char *input,
222 size_t ilen)
Simon Butcher327398a2016-10-05 14:09:11 +0100223{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200224 mbedtls_cmac_context_t *cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700225 unsigned char *state;
Simon B3249cb72016-11-03 01:11:37 +0000226 int ret = 0;
227 size_t n, j, olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700228
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200229 if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
230 ctx->cmac_ctx == NULL)
231 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700232
Simon Butcher327398a2016-10-05 14:09:11 +0100233 cmac_ctx = ctx->cmac_ctx;
234 block_size = ctx->cipher_info->block_size;
235 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000236
Simon Butcher6b0774a2016-10-10 21:37:42 +0100237 /* Is there data still to process from the last call, that's greater in
238 * size than a block? */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200239 if (cmac_ctx->unprocessed_len > 0 &&
240 ilen > block_size - cmac_ctx->unprocessed_len) {
241 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input,
242 block_size - cmac_ctx->unprocessed_len);
Simon Butcher327398a2016-10-05 14:09:11 +0100243
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200244 cmac_xor_block(state, cmac_ctx->unprocessed_block, state, block_size);
Simon Butcher327398a2016-10-05 14:09:11 +0100245
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200246 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
247 &olen)) != 0) {
248 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100249 }
250
Simon Butcher6b0774a2016-10-10 21:37:42 +0100251 input += block_size - cmac_ctx->unprocessed_len;
252 ilen -= block_size - cmac_ctx->unprocessed_len;
Simon Butcher327398a2016-10-05 14:09:11 +0100253 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700254 }
255
Simon Butcher327398a2016-10-05 14:09:11 +0100256 /* n is the number of blocks including any final partial block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200257 n = (ilen + block_size - 1) / block_size;
Simon Butcher327398a2016-10-05 14:09:11 +0100258
Simon B3249cb72016-11-03 01:11:37 +0000259 /* Iterate across the input data in block sized chunks, excluding any
260 * final partial or complete block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200261 for (j = 1; j < n; j++) {
262 cmac_xor_block(state, input, state, block_size);
Simon Butcher327398a2016-10-05 14:09:11 +0100263
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200264 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
265 &olen)) != 0)
266 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100267
268 ilen -= block_size;
269 input += block_size;
Brian Murray57863ad2016-05-19 16:38:36 -0700270 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000271
Simon Butcher327398a2016-10-05 14:09:11 +0100272 /* If there is data left over that wasn't aligned to a block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200273 if (ilen > 0) {
274 memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input,
275 ilen);
Simon Butcher6b0774a2016-10-10 21:37:42 +0100276 cmac_ctx->unprocessed_len += ilen;
Simon Butcher327398a2016-10-05 14:09:11 +0100277 }
278
279exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200280 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100281}
282
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200283int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
284 unsigned char *output)
Simon Butcher327398a2016-10-05 14:09:11 +0100285{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200286 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100287 unsigned char *state, *last_block;
288 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
289 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
290 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Janos Follath24eed8d2019-11-22 13:21:35 +0000291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher327398a2016-10-05 14:09:11 +0100292 size_t olen, block_size;
293
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200294 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
295 output == NULL)
296 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Simon Butcher327398a2016-10-05 14:09:11 +0100297
298 cmac_ctx = ctx->cmac_ctx;
299 block_size = ctx->cipher_info->block_size;
300 state = cmac_ctx->state;
301
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200302 mbedtls_platform_zeroize(K1, sizeof(K1));
303 mbedtls_platform_zeroize(K2, sizeof(K2));
304 cmac_generate_subkeys(ctx, K1, K2);
Simon Butcher327398a2016-10-05 14:09:11 +0100305
Simon Butcher69283e52016-10-06 12:49:58 +0100306 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000307
308 /* Calculate last block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200309 if (cmac_ctx->unprocessed_len < block_size) {
310 cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);
311 cmac_xor_block(M_last, M_last, K2, block_size);
312 } else {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000313 /* Last block is complete block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200314 cmac_xor_block(M_last, last_block, K1, block_size);
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000315 }
316
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200317 cmac_xor_block(state, M_last, state, block_size);
318 if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) !=
319 0) {
Simon Butcher327398a2016-10-05 14:09:11 +0100320 goto exit;
321 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200323 memcpy(output, state, block_size);
Simon Butcher327398a2016-10-05 14:09:11 +0100324
325exit:
326 /* Wipe the generated keys on the stack, and any other transients to avoid
327 * side channel leakage */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200328 mbedtls_platform_zeroize(K1, sizeof(K1));
329 mbedtls_platform_zeroize(K2, sizeof(K2));
Simon Butcher327398a2016-10-05 14:09:11 +0100330
331 cmac_ctx->unprocessed_len = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200332 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
333 sizeof(cmac_ctx->unprocessed_block));
Simon Butcher327398a2016-10-05 14:09:11 +0100334
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200335 mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX);
336 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337}
338
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200339int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200341 mbedtls_cmac_context_t *cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000342
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200343 if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL)
344 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700345
Simon Butcher327398a2016-10-05 14:09:11 +0100346 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347
Simon Butcher327398a2016-10-05 14:09:11 +0100348 /* Reset the internal state */
349 cmac_ctx->unprocessed_len = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200350 mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
351 sizeof(cmac_ctx->unprocessed_block));
352 mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000353
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200354 return 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000355}
356
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200357int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
358 const unsigned char *key,
359 size_t keylen,
360 const unsigned char *input,
361 size_t ilen,
362 unsigned char *output)
Simon Butcher327398a2016-10-05 14:09:11 +0100363{
364 mbedtls_cipher_context_t ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000365 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher327398a2016-10-05 14:09:11 +0100366
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200367 if (cipher_info == NULL || key == NULL || input == NULL || output == NULL)
368 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Simon Butcher327398a2016-10-05 14:09:11 +0100369
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200370 mbedtls_cipher_init(&ctx);
Simon Butcher327398a2016-10-05 14:09:11 +0100371
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200372 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0)
Simon Butcher327398a2016-10-05 14:09:11 +0100373 goto exit;
374
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200375 ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);
376 if (ret != 0)
Simon Butcher327398a2016-10-05 14:09:11 +0100377 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100378
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200379 ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);
380 if (ret != 0)
Simon Butcher327398a2016-10-05 14:09:11 +0100381 goto exit;
382
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200383 ret = mbedtls_cipher_cmac_finish(&ctx, output);
Simon Butcher327398a2016-10-05 14:09:11 +0100384
385exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200386 mbedtls_cipher_free(&ctx);
Simon Butcher69283e52016-10-06 12:49:58 +0100387
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200388 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100389}
Simon Butcher327398a2016-10-05 14:09:11 +0100390
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200391# if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000392/*
Simon Butcher69283e52016-10-06 12:49:58 +0100393 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000394 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200395int mbedtls_aes_cmac_prf_128(const unsigned char *key,
396 size_t key_length,
397 const unsigned char *input,
398 size_t in_len,
399 unsigned char output[16])
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000400{
Janos Follath24eed8d2019-11-22 13:21:35 +0000401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher327398a2016-10-05 14:09:11 +0100402 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100403 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
404 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
405
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200406 if (key == NULL || input == NULL || output == NULL)
407 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000408
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200409 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
410 if (cipher_info == NULL) {
Simon Butcher327398a2016-10-05 14:09:11 +0100411 /* Failing at this point must be due to a build issue */
412 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
413 goto exit;
414 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700415
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200416 if (key_length == MBEDTLS_AES_BLOCK_SIZE) {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000417 /* Use key as is */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200418 memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);
419 } else {
420 memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000421
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200422 ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key, key_length,
423 int_key);
424 if (ret != 0)
Brian Murrayb0c3c432016-05-18 14:29:51 -0700425 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000426 }
427
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200428 ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len, output);
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000429
Simon Butcher327398a2016-10-05 14:09:11 +0100430exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200431 mbedtls_platform_zeroize(int_key, sizeof(int_key));
Brian Murrayb0c3c432016-05-18 14:29:51 -0700432
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200433 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000434}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200435# endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000436
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200437# endif /* !MBEDTLS_CMAC_ALT */
Steven Cooreman63342772017-04-04 11:47:16 +0200438
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200439# if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000440/*
Janos Follathcd13bd22016-12-13 11:51:04 +0000441 * CMAC test data for SP800-38B
442 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
443 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700444 *
445 * AES-CMAC-PRF-128 test data from RFC 4615
446 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000447 */
448
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200449# define NB_CMAC_TESTS_PER_KEY 4
450# define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100451
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452# if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700453/* All CMAC test inputs are truncated from the same 64 byte buffer. */
454static const unsigned char test_message[] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000455 /* PT */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200456 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e,
457 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03,
458 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30,
459 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19,
460 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b,
461 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000462};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463# endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700464
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200465# if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700466/* Truncation point of message for AES CMAC tests */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200467static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000468 /* Mlen */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200469 0, 16, 20, 64
Brian Murray0f6af732016-05-19 15:59:23 -0700470};
471
Janos Follathcd13bd22016-12-13 11:51:04 +0000472/* CMAC-AES128 Test Data */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200473static const unsigned char aes_128_key[16] = { 0x2b, 0x7e, 0x15, 0x16,
474 0x28, 0xae, 0xd2, 0xa6,
475 0xab, 0xf7, 0x15, 0x88,
476 0x09, 0xcf, 0x4f, 0x3c };
Simon Butcher69283e52016-10-06 12:49:58 +0100477static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200478 { /* K1 */
479 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 0x7c, 0x85, 0xe0, 0x8f,
480 0x72, 0x36, 0xa8, 0xde },
481 { /* K2 */
482 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 0xf9, 0x0b, 0xc1, 0x1e,
483 0xe4, 0x6d, 0x51, 0x3b }
Brian Murray0f6af732016-05-19 15:59:23 -0700484};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200485static const unsigned char
486 aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
487 { /* Example #1 */
488 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d,
489 0x12, 0x9b, 0x75, 0x67, 0x46 },
490 { /* Example #2 */
491 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd,
492 0x9d, 0xd0, 0x4a, 0x28, 0x7c },
493 { /* Example #3 */
494 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, 0x23, 0xa7, 0xbf,
495 0x78, 0x83, 0x7d, 0xfa, 0xde },
496 { /* Example #4 */
497 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74,
498 0x17, 0x79, 0x36, 0x3c, 0xfe }
499 };
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000500
Janos Follathcd13bd22016-12-13 11:51:04 +0000501/* CMAC-AES192 Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700502static const unsigned char aes_192_key[24] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200503 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b,
504 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000505};
Simon Butcher69283e52016-10-06 12:49:58 +0100506static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200507 { /* K1 */
508 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, 0x3e, 0xe6, 0x43, 0x9d,
509 0xd4, 0xda, 0xa2, 0x96 },
510 { /* K2 */
511 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, 0x7d, 0xcc, 0x87, 0x3b,
512 0xa9, 0xb5, 0x45, 0x2c }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700513};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200514static const unsigned char
515 aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
516 { /* Example #1 */
517 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4,
518 0x83, 0xde, 0x7a, 0x93, 0x67 },
519 { /* Example #2 */
520 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6,
521 0x5e, 0x61, 0x7c, 0x51, 0x84 },
522 { /* Example #3 */
523 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, 0x44, 0xa9, 0xfa,
524 0x7e, 0xc7, 0x40, 0xec, 0xf8 },
525 { /* Example #4 */
526 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58,
527 0x96, 0x59, 0xf3, 0x9a, 0x11 }
528 };
Brian Murrayb0c3c432016-05-18 14:29:51 -0700529
Janos Follathcd13bd22016-12-13 11:51:04 +0000530/* CMAC-AES256 Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700531static const unsigned char aes_256_key[32] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200532 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae,
533 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61,
534 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700535};
Simon Butcher69283e52016-10-06 12:49:58 +0100536static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200537 { /* K1 */
538 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, 0x2e, 0x9a, 0x99, 0x80,
539 0x86, 0x21, 0x50, 0x2f },
540 { /* K2 */
541 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, 0x5d, 0x35, 0x33, 0x01,
542 0x0c, 0x42, 0xa0, 0xd9 }
Brian Murray0f6af732016-05-19 15:59:23 -0700543};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200544static const unsigned char
545 aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
546 { /* Example #1 */
547 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55,
548 0x1f, 0x46, 0x67, 0xd9, 0x83 },
549 { /* Example #2 */
550 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2,
551 0x8d, 0x8c, 0x37, 0xc3, 0x5c },
552 { /* Example #3 */
553 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, 0x02, 0x3c, 0x1f,
554 0xe0, 0x3b, 0xad, 0x6d, 0x93 },
555 { /* Example #4 */
556 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c,
557 0x05, 0x6c, 0x31, 0x54, 0x10 }
558 };
559# endif /* MBEDTLS_AES_C */
Brian Murray0f6af732016-05-19 15:59:23 -0700560
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200561# if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700562/* Truncation point of message for 3DES CMAC tests */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200563static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 0, 16,
564 20,
565 32 };
Brian Murray0f6af732016-05-19 15:59:23 -0700566
Janos Follathcd13bd22016-12-13 11:51:04 +0000567/* CMAC-TDES (Generation) - 2 Key Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700568static const unsigned char des3_2key_key[24] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000569 /* Key1 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200570 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
Janos Follathcd13bd22016-12-13 11:51:04 +0000571 /* Key2 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200572 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
Janos Follathcd13bd22016-12-13 11:51:04 +0000573 /* Key3 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200574 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
Brian Murray0f6af732016-05-19 15:59:23 -0700575};
576static const unsigned char des3_2key_subkeys[2][8] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200577 { /* K1 */
578 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 },
579 { /* K2 */
580 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 }
Brian Murray0f6af732016-05-19 15:59:23 -0700581};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200582static const unsigned char
583 des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
584 { /* Sample #1 */
585 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 },
586 { /* Sample #2 */
587 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b },
588 { /* Sample #3 */
589 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 },
590 { /* Sample #4 */
591 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb }
592 };
Brian Murrayb0c3c432016-05-18 14:29:51 -0700593
Janos Follathcd13bd22016-12-13 11:51:04 +0000594/* CMAC-TDES (Generation) - 3 Key Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700595static const unsigned char des3_3key_key[24] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000596 /* Key1 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200597 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
Janos Follathcd13bd22016-12-13 11:51:04 +0000598 /* Key2 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200599 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
Janos Follathcd13bd22016-12-13 11:51:04 +0000600 /* Key3 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200601 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
Brian Murray0f6af732016-05-19 15:59:23 -0700602};
603static const unsigned char des3_3key_subkeys[2][8] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200604 { /* K1 */
605 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 },
606 { /* K2 */
607 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b }
Brian Murray0f6af732016-05-19 15:59:23 -0700608};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200609static const unsigned char
610 des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
611 { /* Sample #1 */
612 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 },
613 { /* Sample #2 */
614 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 },
615 { /* Sample #3 */
616 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 },
617 { /* Sample #4 */
618 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 }
619 };
Brian Murrayb0c3c432016-05-18 14:29:51 -0700620
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200621# endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700622
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200623# if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700624/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000625static const unsigned char PRFK[] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000626 /* Key */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200627 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
628 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xed, 0xcb
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000629};
630
631/* Sizes in bytes */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200632static const size_t PRFKlen[NB_PRF_TESTS] = { 18, 16, 10 };
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000633
Janos Follathcd13bd22016-12-13 11:51:04 +0000634/* Message */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200635static const unsigned char PRFM[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
636 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
637 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 };
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000638
639static const unsigned char PRFT[NB_PRF_TESTS][16] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200640 { 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, 0xab, 0xff, 0xfc, 0x0d,
641 0x2b, 0x4d, 0xa0, 0x9a },
642 { 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, 0x14, 0xf5, 0xb6, 0xa8,
643 0x45, 0x5e, 0x4c, 0x2d },
644 { 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, 0x14, 0x1f, 0xcf, 0x64,
645 0xc0, 0xb7, 0x2f, 0x3d }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000646};
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200647# endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000648
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200649static int cmac_test_subkeys(int verbose,
650 const char *testname,
651 const unsigned char *key,
652 int keybits,
653 const unsigned char *subkeys,
654 mbedtls_cipher_type_t cipher_type,
655 int block_size,
656 int num_tests)
Simon Butcher327398a2016-10-05 14:09:11 +0100657{
Brian Murray2fab5c92016-12-15 18:51:13 -0800658 int i, ret = 0;
Simon Butcher327398a2016-10-05 14:09:11 +0100659 mbedtls_cipher_context_t ctx;
660 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100661 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
662 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100663
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200664 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
665 if (cipher_info == NULL) {
Simon Butcher327398a2016-10-05 14:09:11 +0100666 /* Failing at this point must be due to a build issue */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200667 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Simon Butcher327398a2016-10-05 14:09:11 +0100668 }
669
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200670 for (i = 0; i < num_tests; i++) {
671 if (verbose != 0)
672 mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1);
Simon Butcher327398a2016-10-05 14:09:11 +0100673
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200674 mbedtls_cipher_init(&ctx);
Janos Follathd4443582016-10-12 10:00:42 +0100675
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200676 if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
677 if (verbose != 0)
678 mbedtls_printf("test execution failed\n");
Simon Butcher327398a2016-10-05 14:09:11 +0100679
Janos Follathd4443582016-10-12 10:00:42 +0100680 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100681 }
682
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200683 if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,
684 MBEDTLS_ENCRYPT)) != 0) {
Steven Cooreman830d5af2021-01-08 18:01:46 +0100685 /* When CMAC is implemented by an alternative implementation, or
686 * the underlying primitive itself is implemented alternatively,
Steven Cooremanc7da6a42021-01-29 11:09:50 +0100687 * AES-192 may be unavailable. This should not cause the selftest
688 * function to fail. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200689 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
690 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
691 cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {
692 if (verbose != 0)
693 mbedtls_printf("skipped\n");
Steven Cooreman830d5af2021-01-08 18:01:46 +0100694 goto next_test;
695 }
696
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200697 if (verbose != 0)
698 mbedtls_printf("test execution failed\n");
Simon Butcher327398a2016-10-05 14:09:11 +0100699
Janos Follathd4443582016-10-12 10:00:42 +0100700 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100701 }
702
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200703 ret = cmac_generate_subkeys(&ctx, K1, K2);
704 if (ret != 0) {
705 if (verbose != 0)
706 mbedtls_printf("failed\n");
Janos Follathd4443582016-10-12 10:00:42 +0100707
708 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100709 }
710
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200711 if ((ret = memcmp(K1, subkeys, block_size)) != 0 ||
712 (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {
713 if (verbose != 0)
714 mbedtls_printf("failed\n");
Janos Follathd4443582016-10-12 10:00:42 +0100715
716 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100717 }
718
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200719 if (verbose != 0)
720 mbedtls_printf("passed\n");
Janos Follathd4443582016-10-12 10:00:42 +0100721
Steven Cooreman830d5af2021-01-08 18:01:46 +0100722next_test:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200723 mbedtls_cipher_free(&ctx);
Simon Butcher327398a2016-10-05 14:09:11 +0100724 }
725
Gilles Peskinedf761d52018-03-01 22:18:14 +0100726 ret = 0;
Janos Follathd4443582016-10-12 10:00:42 +0100727 goto exit;
728
729cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200730 mbedtls_cipher_free(&ctx);
Simon Butcher69283e52016-10-06 12:49:58 +0100731
Janos Follathd4443582016-10-12 10:00:42 +0100732exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200733 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100734}
735
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200736static int cmac_test_wth_cipher(int verbose,
737 const char *testname,
738 const unsigned char *key,
739 int keybits,
740 const unsigned char *messages,
741 const unsigned int message_lengths[4],
742 const unsigned char *expected_result,
743 mbedtls_cipher_type_t cipher_type,
744 int block_size,
745 int num_tests)
Brian Murray00dc5f02016-05-19 14:23:50 -0700746{
Simon Butcher327398a2016-10-05 14:09:11 +0100747 const mbedtls_cipher_info_t *cipher_info;
Brian Murray2fab5c92016-12-15 18:51:13 -0800748 int i, ret = 0;
Simon Butcher69283e52016-10-06 12:49:58 +0100749 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700750
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200751 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
752 if (cipher_info == NULL) {
Simon Butcher327398a2016-10-05 14:09:11 +0100753 /* Failing at this point must be due to a build issue */
754 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700755 goto exit;
756 }
757
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200758 for (i = 0; i < num_tests; i++) {
759 if (verbose != 0)
760 mbedtls_printf(" %s CMAC #%d: ", testname, i + 1);
Brian Murray00dc5f02016-05-19 14:23:50 -0700761
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200762 if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
763 message_lengths[i], output)) != 0) {
Steven Cooreman830d5af2021-01-08 18:01:46 +0100764 /* When CMAC is implemented by an alternative implementation, or
765 * the underlying primitive itself is implemented alternatively,
Steven Cooremand3679902021-02-15 13:42:35 +0100766 * AES-192 and/or 3DES may be unavailable. This should not cause
767 * the selftest function to fail. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200768 if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
769 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
770 (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
771 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {
772 if (verbose != 0)
773 mbedtls_printf("skipped\n");
Steven Cooreman830d5af2021-01-08 18:01:46 +0100774 continue;
775 }
776
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200777 if (verbose != 0)
778 mbedtls_printf("failed\n");
Brian Murray00dc5f02016-05-19 14:23:50 -0700779 goto exit;
780 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700781
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200782 if ((ret = memcmp(output, &expected_result[i * block_size],
783 block_size)) != 0) {
784 if (verbose != 0)
785 mbedtls_printf("failed\n");
Brian Murray00dc5f02016-05-19 14:23:50 -0700786 goto exit;
787 }
788
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200789 if (verbose != 0)
790 mbedtls_printf("passed\n");
Brian Murray00dc5f02016-05-19 14:23:50 -0700791 }
Gilles Peskinedf761d52018-03-01 22:18:14 +0100792 ret = 0;
Simon Butcher327398a2016-10-05 14:09:11 +0100793
Simon Butcher69283e52016-10-06 12:49:58 +0100794exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200795 return ret;
Brian Murray00dc5f02016-05-19 14:23:50 -0700796}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000797
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200798# if defined(MBEDTLS_AES_C)
799static int test_aes128_cmac_prf(int verbose)
Brian Murray6a3c0d22016-05-20 18:25:43 -0700800{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000801 int i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000802 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher69283e52016-10-06 12:49:58 +0100803 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100804
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200805 for (i = 0; i < NB_PRF_TESTS; i++) {
806 mbedtls_printf(" AES CMAC 128 PRF #%d: ", i);
807 ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);
808 if (ret != 0 || memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {
809 if (verbose != 0)
810 mbedtls_printf("failed\n");
Simon Butcher327398a2016-10-05 14:09:11 +0100811
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200812 return ret;
813 } else if (verbose != 0) {
814 mbedtls_printf("passed\n");
Brian Murrayb0c3c432016-05-18 14:29:51 -0700815 }
816 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200817 return ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700818}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200819# endif /* MBEDTLS_AES_C */
Brian Murray0f6af732016-05-19 15:59:23 -0700820
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200821int mbedtls_cmac_self_test(int verbose)
Brian Murray0f6af732016-05-19 15:59:23 -0700822{
Janos Follath24eed8d2019-11-22 13:21:35 +0000823 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Simon Butcher327398a2016-10-05 14:09:11 +0100824
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200825# if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100826 /* AES-128 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200827 if ((ret = cmac_test_subkeys(
828 verbose, "AES 128", aes_128_key, 128,
829 (const unsigned char *)aes_128_subkeys, MBEDTLS_CIPHER_AES_128_ECB,
830 MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) {
831 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100832 }
833
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200834 if ((ret = cmac_test_wth_cipher(
835 verbose, "AES 128", aes_128_key, 128, test_message,
836 aes_message_lengths,
837 (const unsigned char *)aes_128_expected_result,
838 MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE,
839 NB_CMAC_TESTS_PER_KEY)) != 0) {
840 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100841 }
842
843 /* AES-192 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200844 if ((ret = cmac_test_subkeys(
845 verbose, "AES 192", aes_192_key, 192,
846 (const unsigned char *)aes_192_subkeys, MBEDTLS_CIPHER_AES_192_ECB,
847 MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) {
848 return ret;
Brian Murray9044b022016-05-19 16:36:56 -0700849 }
Brian Murray0f6af732016-05-19 15:59:23 -0700850
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200851 if ((ret = cmac_test_wth_cipher(
852 verbose, "AES 192", aes_192_key, 192, test_message,
853 aes_message_lengths,
854 (const unsigned char *)aes_192_expected_result,
855 MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE,
856 NB_CMAC_TESTS_PER_KEY)) != 0) {
857 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100858 }
859
860 /* AES-256 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200861 if ((ret = cmac_test_subkeys(
862 verbose, "AES 256", aes_256_key, 256,
863 (const unsigned char *)aes_256_subkeys, MBEDTLS_CIPHER_AES_256_ECB,
864 MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) {
865 return ret;
Brian Murray9044b022016-05-19 16:36:56 -0700866 }
Brian Murray0f6af732016-05-19 15:59:23 -0700867
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200868 if ((ret = cmac_test_wth_cipher(
869 verbose, "AES 256", aes_256_key, 256, test_message,
870 aes_message_lengths,
871 (const unsigned char *)aes_256_expected_result,
872 MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE,
873 NB_CMAC_TESTS_PER_KEY)) != 0) {
874 return ret;
Brian Murray9044b022016-05-19 16:36:56 -0700875 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200876# endif /* MBEDTLS_AES_C */
Brian Murray0f6af732016-05-19 15:59:23 -0700877
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200878# if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100879 /* 3DES 2 key */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200880 if ((ret = cmac_test_subkeys(verbose, "3DES 2 key", des3_2key_key, 192,
881 (const unsigned char *)des3_2key_subkeys,
882 MBEDTLS_CIPHER_DES_EDE3_ECB,
883 MBEDTLS_DES3_BLOCK_SIZE,
884 NB_CMAC_TESTS_PER_KEY)) != 0) {
885 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100886 }
887
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200888 if ((ret = cmac_test_wth_cipher(
889 verbose, "3DES 2 key", des3_2key_key, 192, test_message,
890 des3_message_lengths,
891 (const unsigned char *)des3_2key_expected_result,
892 MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE,
893 NB_CMAC_TESTS_PER_KEY)) != 0) {
894 return ret;
Brian Murray9044b022016-05-19 16:36:56 -0700895 }
Brian Murray0f6af732016-05-19 15:59:23 -0700896
Simon Butcher327398a2016-10-05 14:09:11 +0100897 /* 3DES 3 key */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200898 if ((ret = cmac_test_subkeys(verbose, "3DES 3 key", des3_3key_key, 192,
899 (const unsigned char *)des3_3key_subkeys,
900 MBEDTLS_CIPHER_DES_EDE3_ECB,
901 MBEDTLS_DES3_BLOCK_SIZE,
902 NB_CMAC_TESTS_PER_KEY)) != 0) {
903 return ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100904 }
905
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200906 if ((ret = cmac_test_wth_cipher(
907 verbose, "3DES 3 key", des3_3key_key, 192, test_message,
908 des3_message_lengths,
909 (const unsigned char *)des3_3key_expected_result,
910 MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE,
911 NB_CMAC_TESTS_PER_KEY)) != 0) {
912 return ret;
Brian Murray9044b022016-05-19 16:36:56 -0700913 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200914# endif /* MBEDTLS_DES_C */
Brian Murray0f6af732016-05-19 15:59:23 -0700915
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200916# if defined(MBEDTLS_AES_C)
917 if ((ret = test_aes128_cmac_prf(verbose)) != 0)
918 return ret;
919# endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700920
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200921 if (verbose != 0)
922 mbedtls_printf("\n");
Brian Murray0f6af732016-05-19 15:59:23 -0700923
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200924 return 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000925}
926
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200927# endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000928
929#endif /* MBEDTLS_CMAC_C */