Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-math-all/wolfcrypt/src/cmac.c
Line
Count
Source
1
/* cmac.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#define WC_FIPS_LL_CRYPTO
23
#define _WC_BUILDING_CMAC_C
24
25
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
26
27
#ifdef WOLFSSL_QNX_CAAM
28
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
29
#endif
30
#if defined(WOLFSSL_HASH_KEEP)
31
#include <wolfssl/wolfcrypt/hash.h>
32
#endif
33
34
#if defined(WOLFSSL_CMAC)
35
36
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
37
    #ifdef USE_WINDOWS_API
38
        #pragma code_seg(".fipsA$c")
39
        #pragma const_seg(".fipsB$c")
40
    #endif
41
#endif
42
43
#ifdef NO_INLINE
44
    #include <wolfssl/wolfcrypt/misc.h>
45
#else
46
    #define WOLFSSL_MISC_INCLUDED
47
    #include <wolfcrypt/src/misc.c>
48
#endif
49
50
#include <wolfssl/wolfcrypt/aes.h>
51
#include <wolfssl/wolfcrypt/cmac.h>
52
53
#ifdef WOLF_CRYPTO_CB
54
    #include <wolfssl/wolfcrypt/cryptocb.h>
55
#endif
56
57
#if FIPS_VERSION3_GE(6,0,0)
58
    const unsigned int wolfCrypt_FIPS_cmac_ro_sanity[2] =
59
                                                     { 0x1a2b3c4d, 0x00000003 };
60
    int wolfCrypt_FIPS_CMAC_sanity(void)
61
    {
62
        return 0;
63
    }
64
#endif
65
66
#ifdef WOLFSSL_HASH_KEEP
67
/* Some hardware have issues with update, this function stores the data to be
68
 * hashed into an array. Once ready, the Final operation is called on all of the
69
 * data to be hashed at once.
70
 * returns 0 on success
71
 */
72
int wc_CMAC_Grow(Cmac* cmac, const byte* in, int inSz)
73
{
74
    if ((cmac == NULL) || (in == NULL && inSz != 0))
75
        return BAD_FUNC_ARG;
76
    return _wc_Hash_Grow(&cmac->msg, &cmac->used, &cmac->len, in, inSz, cmac->aes.heap);
77
}
78
#endif /* WOLFSSL_HASH_KEEP */
79
80
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
81
/* Used by AES-SIV. See aes.c. */
82
void ShiftAndXorRb(byte* out, byte* in)
83
270
{
84
270
    int i, j, xorRb;
85
270
    int mask = 0, last = 0;
86
270
    byte Rb = 0x87;
87
88
270
    xorRb = (in[0] & 0x80) != 0;
89
90
4.59k
    for (i = 1, j = WC_AES_BLOCK_SIZE - 1; i <= WC_AES_BLOCK_SIZE; i++, j--) {
91
4.32k
        last = (in[j] & 0x80) ? 1 : 0;
92
4.32k
        out[j] = (byte)((in[j] << 1) | mask);
93
4.32k
        mask = last;
94
4.32k
        if (xorRb) {
95
1.72k
            out[j] ^= Rb;
96
1.72k
            Rb = 0;
97
1.72k
        }
98
4.32k
    }
99
270
}
100
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
101
102
135
#define CMAC_AES_INIT_PLAIN  0
103
#ifdef WOLF_PRIVATE_KEY_ID
104
270
#define CMAC_AES_INIT_ID     1
105
270
#define CMAC_AES_INIT_LABEL  2
106
#endif
107
108
109
static int _InitCmac_common(Cmac* cmac, const byte* key, word32 keySz,
110
                            int type, void* unused, void* heap, int devId,
111
                            int aesInitType, unsigned char* id, int idLen,
112
                            const char* label)
113
135
{
114
135
    int ret = 0;
115
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
116
    byte useSW = 0;
117
#endif
118
119
135
    if (cmac == NULL || type != WC_CMAC_AES) {
120
0
        return BAD_FUNC_ARG;
121
0
    }
122
123
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
124
    /* save if we should use SW crypt, restore after memset */
125
    useSW = cmac->useSWCrypt;
126
#endif
127
135
    XMEMSET(cmac, 0, sizeof(Cmac));
128
129
    /* Stash heap so the cryptocb can read it from the zeroed cmac. */
130
135
#ifndef NO_AES
131
135
    cmac->aes.heap = heap;
132
#else
133
    cmac->heap = heap;
134
#endif
135
136
    /* Store id/label on the Cmac struct so the crypto callback can
137
     * inspect them to determine the hardware key slot. */
138
135
#ifdef WOLF_PRIVATE_KEY_ID
139
135
    cmac->aesInitType = aesInitType;
140
135
    if (aesInitType == CMAC_AES_INIT_ID && id != NULL && idLen > 0) {
141
0
        if (idLen > (int)sizeof(cmac->id)) {
142
0
            return BAD_FUNC_ARG;
143
0
        }
144
0
        XMEMCPY(cmac->id, id, (word32)idLen);
145
0
        cmac->idLen = idLen;
146
0
    }
147
135
    else if (aesInitType == CMAC_AES_INIT_LABEL && label != NULL) {
148
0
        int labelLen = (int)XSTRLEN(label);
149
0
        if (labelLen > 0 && labelLen < (int)sizeof(cmac->label)) {
150
0
            XMEMCPY(cmac->label, label, (word32)labelLen);
151
0
            cmac->labelLen = labelLen;
152
0
        }
153
0
    }
154
135
#endif
155
135
    (void)aesInitType;
156
135
    (void)id;
157
135
    (void)idLen;
158
135
    (void)label;
159
160
135
#ifdef WOLF_CRYPTO_CB
161
    /* Set devId regardless of value (invalid or not) */
162
135
    cmac->devId = devId;
163
    /* Set before the cryptocb early return so wc_CmacFree can clean up. */
164
135
    cmac->type = (CmacType)type;
165
135
    #ifndef WOLF_CRYPTO_CB_FIND
166
135
    if (devId != INVALID_DEVID)
167
0
    #endif
168
0
    {
169
0
        cmac->devCtx = NULL;
170
171
0
        ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL,
172
0
                type, unused);
173
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
174
0
            return ret;
175
0
        }
176
        /* fall-through when unavailable, reset ret for software path */
177
0
        ret = 0;
178
0
        (void)ret;
179
0
    }
180
#else
181
    (void)devId;
182
#endif
183
135
    (void)unused;
184
135
    (void)heap;
185
186
135
    if (key == NULL || keySz == 0) {
187
0
        return BAD_FUNC_ARG;
188
0
    }
189
190
135
    switch (type) {
191
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
192
135
    case WC_CMAC_AES:
193
135
        cmac->type = WC_CMAC_AES;
194
135
        switch (aesInitType) {
195
0
#ifdef WOLF_PRIVATE_KEY_ID
196
0
        case CMAC_AES_INIT_ID:
197
0
            if (id == NULL || idLen == 0 || label != NULL) {
198
0
                ret = BAD_FUNC_ARG;
199
0
            }
200
0
            else {
201
0
                ret = wc_AesInit_Id(&cmac->aes, id, idLen, heap, devId);
202
0
            }
203
0
            break;
204
0
        case CMAC_AES_INIT_LABEL:
205
0
            if (label == NULL || id != NULL || idLen != 0) {
206
0
                ret = BAD_FUNC_ARG;
207
0
            }
208
0
            else {
209
0
                ret = wc_AesInit_Label(&cmac->aes, label, heap, devId);
210
0
            }
211
0
            break;
212
0
#endif
213
135
        default:
214
135
            if (id != NULL || idLen != 0 || label != NULL) {
215
0
                ret = BAD_FUNC_ARG;
216
0
            }
217
135
            else {
218
135
                ret = wc_AesInit(&cmac->aes, heap, devId);
219
135
            }
220
135
            break;
221
135
        }
222
135
        if (ret != 0) {
223
0
            return ret;
224
0
        }
225
226
    #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
227
        cmac->useSWCrypt = useSW;
228
        if (cmac->useSWCrypt == 1) {
229
            cmac->aes.useSWCrypt = 1;
230
        }
231
    #endif
232
233
135
        if (ret == 0) {
234
135
            ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
235
135
        }
236
237
135
        if (ret == 0) {
238
135
            byte l[WC_AES_BLOCK_SIZE];
239
240
135
            XMEMSET(l, 0, WC_AES_BLOCK_SIZE);
241
#ifdef WOLFSSL_CHECK_MEM_ZERO
242
            wc_MemZero_Add("InitInternal l", l, WC_AES_BLOCK_SIZE);
243
#endif
244
135
#ifndef HAVE_SELFTEST
245
135
            ret = wc_AesEncryptDirect(&cmac->aes, l, l);
246
135
            if (ret == 0) {
247
135
                ShiftAndXorRb(cmac->k1, l);
248
135
                ShiftAndXorRb(cmac->k2, cmac->k1);
249
135
            }
250
#else
251
            wc_AesEncryptDirect(&cmac->aes, l, l);
252
            ShiftAndXorRb(cmac->k1, l);
253
            ShiftAndXorRb(cmac->k2, cmac->k1);
254
#endif
255
135
            ForceZero(l, WC_AES_BLOCK_SIZE);
256
#ifdef WOLFSSL_CHECK_MEM_ZERO
257
            wc_MemZero_Check(l, WC_AES_BLOCK_SIZE);
258
#endif
259
135
        }
260
261
135
        if (ret != 0) {
262
0
            wc_AesFree(&cmac->aes);
263
0
            cmac->type = WC_CMAC_NONE;
264
0
        }
265
266
135
        break;
267
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
268
0
    default:
269
0
        return BAD_FUNC_ARG;
270
135
    }
271
272
135
    return ret;
273
135
}
274
275
276
/* returns 0 on success */
277
int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz,
278
                int type, void* unused, void* heap, int devId)
279
135
{
280
135
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
281
135
                            CMAC_AES_INIT_PLAIN, NULL, 0, NULL);
282
135
}
283
284
285
int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
286
                int type, void* unused)
287
135
{
288
#ifdef WOLFSSL_QNX_CAAM
289
    int devId = WOLFSSL_CAAM_DEVID;
290
#else
291
135
    int devId = INVALID_DEVID;
292
135
#endif
293
135
    return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, devId);
294
135
}
295
296
297
#ifdef WOLF_PRIVATE_KEY_ID
298
/* returns 0 on success */
299
int wc_InitCmac_Id(Cmac* cmac, const byte* key, word32 keySz,
300
                   int type, void* unused, unsigned char* id, int len,
301
                   void* heap, int devId)
302
0
{
303
0
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
304
0
                            CMAC_AES_INIT_ID, id, len, NULL);
305
0
}
306
307
308
/* returns 0 on success */
309
int wc_InitCmac_Label(Cmac* cmac, const byte* key, word32 keySz,
310
                      int type, void* unused, const char* label,
311
                      void* heap, int devId)
312
0
{
313
0
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
314
0
                            CMAC_AES_INIT_LABEL, NULL, 0, label);
315
0
}
316
#endif /* WOLF_PRIVATE_KEY_ID */
317
318
319
int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
320
725
{
321
725
    int ret = 0;
322
323
725
    if ((cmac == NULL) || (in == NULL && inSz != 0)) {
324
0
        return BAD_FUNC_ARG;
325
0
    }
326
327
725
#ifdef WOLF_CRYPTO_CB
328
725
    #ifndef WOLF_CRYPTO_CB_FIND
329
725
    if (cmac->devId != INVALID_DEVID)
330
0
    #endif
331
0
    {
332
0
        ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz,
333
0
            NULL, NULL, (int)cmac->type, NULL);
334
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
335
0
            return ret;
336
        /* fall-through when unavailable */
337
0
    }
338
725
#endif
339
340
    /* Clear CRYPTOCB_UNAVAILABLE return code */
341
725
    ret = 0;
342
343
725
    switch (cmac->type) {
344
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
345
725
    case WC_CMAC_AES:
346
725
    {
347
#ifdef HAVE_SELFTEST
348
        while ((ret == 0) && (inSz != 0)) {
349
            word32 add = min(inSz, WC_AES_BLOCK_SIZE - cmac->bufferSz);
350
            XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
351
352
            cmac->bufferSz += add;
353
            in += add;
354
            inSz -= add;
355
356
            if (cmac->bufferSz == WC_AES_BLOCK_SIZE && inSz != 0) {
357
                xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
358
                wc_AesEncryptDirect(&cmac->aes, cmac->digest,
359
                        cmac->buffer);
360
                cmac->totalSz += WC_AES_BLOCK_SIZE;
361
                cmac->bufferSz = 0;
362
            }
363
        }
364
#else
365
725
        (void)ret;
366
725
        ret = wc_local_CmacUpdateAes(cmac, in, inSz);
367
725
#endif
368
725
    }; break;
369
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
370
0
    case WC_CMAC_NONE:
371
0
    default:
372
0
        ret = BAD_FUNC_ARG;
373
725
    }
374
725
    return ret;
375
725
}
376
377
int wc_CmacFree(Cmac* cmac)
378
135
{
379
135
    if (cmac == NULL)
380
0
        return BAD_FUNC_ARG;
381
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE)
382
    /* Let the device release any per-context state it hung off cmac->devCtx
383
     * before the struct is zeroed (e.g. an offload context never finalized). */
384
    #ifndef WOLF_CRYPTO_CB_FIND
385
    if (cmac->devId != INVALID_DEVID)
386
    #endif
387
    {
388
        (void)wc_CryptoCb_Free(cmac->devId, WC_ALGO_TYPE_CMAC, (int)cmac->type,
389
            0, cmac);
390
    }
391
#endif
392
#if defined(WOLFSSL_HASH_KEEP)
393
    /* TODO: msg is leaked if wc_CmacFinal() is not called
394
     * e.g. when multiple calls to wc_CmacUpdate() and one fails but
395
     * wc_CmacFinal() not called. */
396
    XFREE(cmac->msg, cmac->aes.heap, DYNAMIC_TYPE_TMP_BUFFER);
397
#endif
398
135
    switch (cmac->type) {
399
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
400
135
    case WC_CMAC_AES:
401
135
        wc_AesFree(&cmac->aes);
402
135
        break;
403
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
404
0
    case WC_CMAC_NONE:
405
0
    default:
406
        /* Nothing to do */
407
0
        (void)cmac;
408
135
    }
409
135
    ForceZero(cmac, sizeof(Cmac));
410
135
    return 0;
411
135
}
412
413
int wc_CmacFinalNoFree(Cmac* cmac, byte* out, word32* outSz)
414
135
{
415
135
    int ret = 0;
416
417
135
    if (cmac == NULL || out == NULL || outSz == NULL) {
418
0
        return BAD_FUNC_ARG;
419
0
    }
420
135
    if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) {
421
0
        return BUFFER_E;
422
0
    }
423
424
135
#ifdef WOLF_CRYPTO_CB
425
135
    #ifndef WOLF_CRYPTO_CB_FIND
426
135
    if (cmac->devId != INVALID_DEVID)
427
0
    #endif
428
0
    {
429
0
        ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz,
430
0
            (int)cmac->type, NULL);
431
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
432
0
            return ret;
433
434
        /* Clear CRYPTOCB_UNAVAILABLE return code */
435
0
       ret = 0;
436
437
        /* fall-through when unavailable */
438
0
    }
439
135
#endif
440
135
    if (ret == 0) {
441
135
        switch (cmac->type) {
442
0
    #if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
443
135
        case WC_CMAC_AES:
444
135
        {
445
135
            const byte* subKey;
446
135
            word32 remainder;
447
448
135
            if (cmac->bufferSz == WC_AES_BLOCK_SIZE) {
449
0
                subKey = cmac->k1;
450
0
            }
451
135
            else {
452
                /* ensure we will have a valid remainder value */
453
135
                if (cmac->bufferSz > WC_AES_BLOCK_SIZE) {
454
0
                    ret = BAD_STATE_E;
455
0
                    break;
456
0
                }
457
135
                remainder = WC_AES_BLOCK_SIZE - cmac->bufferSz;
458
459
135
                if (remainder == 0) {
460
0
                    remainder = WC_AES_BLOCK_SIZE;
461
0
                }
462
135
                if (remainder > 1) {
463
98
                    XMEMSET(cmac->buffer + WC_AES_BLOCK_SIZE - remainder, 0,
464
98
                            remainder);
465
98
                }
466
467
135
                cmac->buffer[WC_AES_BLOCK_SIZE - remainder] = 0x80;
468
135
                subKey = cmac->k2;
469
135
            }
470
135
            xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
471
135
            xorbuf(cmac->buffer, subKey, WC_AES_BLOCK_SIZE);
472
135
#ifndef HAVE_SELFTEST
473
135
            ret = wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
474
135
            if (ret == 0) {
475
135
                XMEMCPY(out, cmac->digest, *outSz);
476
135
            }
477
#else
478
            wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
479
            XMEMCPY(out, cmac->digest, *outSz);
480
#endif
481
135
        }; break;
482
0
    #endif /* !NO_AES && WOLFSSL_AES_DIRECT */
483
0
        case WC_CMAC_NONE:
484
0
        default:
485
0
            ret = BAD_FUNC_ARG;
486
135
        }
487
135
    }
488
135
    return ret;
489
135
}
490
491
int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
492
135
{
493
135
    int ret = 0;
494
495
135
    if (cmac == NULL)
496
0
        return BAD_FUNC_ARG;
497
135
    ret = wc_CmacFinalNoFree(cmac, out, outSz);
498
135
    (void)wc_CmacFree(cmac);
499
135
    return ret;
500
135
}
501
502
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
503
int wc_AesCmacGenerate_ex(Cmac* cmac,
504
                          byte* out, word32* outSz,
505
                          const byte* in, word32 inSz,
506
                          const byte* key, word32 keySz,
507
                          void* heap, int devId)
508
0
{
509
0
    int ret = 0;
510
511
0
    if (cmac == NULL) {
512
0
        return BAD_FUNC_ARG;
513
0
    }
514
515
0
#ifdef WOLF_CRYPTO_CB
516
    /* Set devId regardless of value (invalid or not) */
517
0
    cmac->devId = devId;
518
0
    #ifndef WOLF_CRYPTO_CB_FIND
519
0
    if (devId != INVALID_DEVID)
520
0
    #endif
521
0
    {
522
0
        ret = wc_CryptoCb_Cmac(cmac, key, keySz, in, inSz, out, outSz,
523
0
                WC_CMAC_AES, NULL);
524
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
525
0
            return ret;
526
527
         /* Clear CRYPTOCB_UNAVAILABLE return code */
528
0
        ret = 0;
529
530
        /* fall-through when unavailable */
531
0
    }
532
0
#endif
533
534
0
    if ( ((out == NULL) && (outSz != NULL) && (*outSz > 0))
535
0
         || (in == NULL && inSz > 0)
536
0
         || (key == NULL && keySz > 0))  {
537
0
        return BAD_FUNC_ARG;
538
0
    }
539
540
    /* Init step is optional */
541
0
    if (key != NULL) {
542
0
        ret = wc_InitCmac_ex(cmac, key, keySz, WC_CMAC_AES, NULL, heap, devId);
543
0
    }
544
0
    if (ret == 0) {
545
0
        ret = wc_CmacUpdate(cmac, in, inSz);
546
        /* Ensure we are freed and zeroed if not calling wc_CmacFinal */
547
0
        if (ret != 0) {
548
0
            (void)wc_CmacFree(cmac);
549
0
        }
550
0
    }
551
0
    if (ret == 0) {
552
0
        ret = wc_CmacFinal(cmac, out, outSz);
553
0
    }
554
555
0
    return ret;
556
0
}
557
558
559
int wc_AesCmacGenerate(byte* out, word32* outSz,
560
                       const byte* in, word32 inSz,
561
                       const byte* key, word32 keySz)
562
0
{
563
0
    int ret = 0;
564
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
565
566
0
    if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) {
567
0
        return BAD_FUNC_ARG;
568
0
    }
569
570
0
#ifdef WOLFSSL_SMALL_STACK
571
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
572
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
573
0
        return MEMORY_E;
574
0
    }
575
0
#endif
576
577
#ifdef WOLFSSL_CHECK_MEM_ZERO
578
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
579
        sizeof(Cmac) - sizeof(Aes));
580
    /* Aes part is checked by wc_AesFree. */
581
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
582
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
583
#endif
584
585
0
    ret = wc_AesCmacGenerate_ex(cmac,
586
0
                                out, outSz,
587
0
                                in, inSz,
588
0
                                key, keySz,
589
0
                                NULL,
590
0
                                INVALID_DEVID);
591
592
593
0
#ifdef WOLFSSL_SMALL_STACK
594
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
595
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
596
    wc_MemZero_Check(cmac, sizeof(Cmac));
597
#endif
598
599
0
    return ret;
600
0
}
601
602
603
int wc_AesCmacVerify_ex(Cmac* cmac,
604
                        const byte* check, word32 checkSz,
605
                        const byte* in, word32 inSz,
606
                        const byte* key, word32 keySz,
607
                        void* heap, int devId)
608
0
{
609
0
    int ret = 0;
610
0
    byte a[WC_AES_BLOCK_SIZE];
611
0
    word32 aSz;
612
0
    int compareRet;
613
614
0
    if (cmac == NULL || check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
615
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz != 0)) {
616
0
        return BAD_FUNC_ARG;
617
0
    }
618
619
0
    aSz = checkSz;
620
0
    XMEMSET(a, 0, sizeof(a));
621
0
    ret = wc_AesCmacGenerate_ex(cmac,
622
0
                                a, &aSz,
623
0
                                in, inSz,
624
0
                                key, keySz,
625
0
                                heap,
626
0
                                devId);
627
    /* aSz is passed by reference to wc_AesCmacGenerate_ex, which on the
628
     * WOLF_CRYPTO_CB path forwards it to a user-supplied callback that may
629
     * write back any value. Reject anything that does not match the user
630
     * provided length. */
631
0
    if (ret == 0 && aSz != checkSz) {
632
0
        ret = BAD_STATE_E;
633
0
    }
634
0
    if (ret == 0) {
635
0
        compareRet = ConstantCompare(check, a, (int)aSz);
636
0
        ret = compareRet ? MAC_CMP_FAILED_E : 0;
637
0
    }
638
639
0
    return ret;
640
0
}
641
642
643
int wc_AesCmacVerify(const byte* check, word32 checkSz,
644
                     const byte* in, word32 inSz,
645
                     const byte* key, word32 keySz)
646
0
{
647
0
    int ret = 0;
648
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
649
650
0
    if (check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
651
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz > 0) ||
652
0
            key == NULL || keySz == 0) {
653
0
        return BAD_FUNC_ARG;
654
0
    }
655
656
0
#ifdef WOLFSSL_SMALL_STACK
657
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
658
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
659
0
        return MEMORY_E;
660
0
    }
661
0
#endif
662
663
#ifdef WOLFSSL_CHECK_MEM_ZERO
664
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
665
        sizeof(Cmac) - sizeof(Aes));
666
    /* Aes part is checked by wc_AesFree. */
667
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
668
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
669
#endif
670
671
0
    ret = wc_AesCmacVerify_ex(cmac,
672
0
                              check, checkSz,
673
0
                              in, inSz,
674
0
                              key, keySz,
675
0
                              NULL,
676
0
                              INVALID_DEVID);
677
678
0
#ifdef WOLFSSL_SMALL_STACK
679
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
680
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
681
    wc_MemZero_Check(cmac, sizeof(Cmac));
682
#endif
683
684
0
    return ret;
685
0
}
686
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
687
688
#endif /* WOLFSSL_CMAC */