Coverage Report

Created: 2026-05-18 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#ifdef WOLFSSL_QNX_CAAM
25
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
26
#endif
27
#if defined(WOLFSSL_HASH_KEEP)
28
#include <wolfssl/wolfcrypt/hash.h>
29
#endif
30
31
#if defined(WOLFSSL_CMAC)
32
33
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
34
    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
35
    #define FIPS_NO_WRAPPERS
36
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
222
{
84
222
    int i, j, xorRb;
85
222
    int mask = 0, last = 0;
86
222
    byte Rb = 0x87;
87
88
222
    xorRb = (in[0] & 0x80) != 0;
89
90
3.77k
    for (i = 1, j = WC_AES_BLOCK_SIZE - 1; i <= WC_AES_BLOCK_SIZE; i++, j--) {
91
3.55k
        last = (in[j] & 0x80) ? 1 : 0;
92
3.55k
        out[j] = (byte)((in[j] << 1) | mask);
93
3.55k
        mask = last;
94
3.55k
        if (xorRb) {
95
1.42k
            out[j] ^= Rb;
96
1.42k
            Rb = 0;
97
1.42k
        }
98
3.55k
    }
99
222
}
100
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
101
102
111
#define CMAC_AES_INIT_PLAIN  0
103
#ifdef WOLF_PRIVATE_KEY_ID
104
222
#define CMAC_AES_INIT_ID     1
105
222
#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
111
{
114
111
    int ret = 0;
115
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
116
    byte useSW = 0;
117
#endif
118
119
111
    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
111
    XMEMSET(cmac, 0, sizeof(Cmac));
128
129
    /* Store id/label on the Cmac struct so the crypto callback can
130
     * inspect them to determine the hardware key slot. */
131
111
#ifdef WOLF_PRIVATE_KEY_ID
132
111
    cmac->aesInitType = aesInitType;
133
111
    if (aesInitType == CMAC_AES_INIT_ID && id != NULL && idLen > 0) {
134
0
        if (idLen > (int)sizeof(cmac->id)) {
135
0
            return BAD_FUNC_ARG;
136
0
        }
137
0
        XMEMCPY(cmac->id, id, (word32)idLen);
138
0
        cmac->idLen = idLen;
139
0
    }
140
111
    else if (aesInitType == CMAC_AES_INIT_LABEL && label != NULL) {
141
0
        int labelLen = (int)XSTRLEN(label);
142
0
        if (labelLen > 0 && labelLen < (int)sizeof(cmac->label)) {
143
0
            XMEMCPY(cmac->label, label, (word32)labelLen);
144
0
            cmac->labelLen = labelLen;
145
0
        }
146
0
    }
147
111
#endif
148
111
    (void)aesInitType;
149
111
    (void)id;
150
111
    (void)idLen;
151
111
    (void)label;
152
153
111
#ifdef WOLF_CRYPTO_CB
154
    /* Set devId regardless of value (invalid or not) */
155
111
    cmac->devId = devId;
156
111
    #ifndef WOLF_CRYPTO_CB_FIND
157
111
    if (devId != INVALID_DEVID)
158
0
    #endif
159
0
    {
160
0
        cmac->devCtx = NULL;
161
162
0
        ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL,
163
0
                type, unused);
164
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
165
0
            return ret;
166
0
        }
167
        /* fall-through when unavailable, reset ret for software path */
168
0
        ret = 0;
169
0
        (void)ret;
170
0
    }
171
#else
172
    (void)devId;
173
#endif
174
111
    (void)unused;
175
111
    (void)heap;
176
177
111
    if (key == NULL || keySz == 0) {
178
0
        return BAD_FUNC_ARG;
179
0
    }
180
181
111
    switch (type) {
182
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
183
111
    case WC_CMAC_AES:
184
111
        cmac->type = WC_CMAC_AES;
185
111
        switch (aesInitType) {
186
0
#ifdef WOLF_PRIVATE_KEY_ID
187
0
        case CMAC_AES_INIT_ID:
188
0
            if (id == NULL || idLen == 0 || label != NULL) {
189
0
                ret = BAD_FUNC_ARG;
190
0
            }
191
0
            else {
192
0
                ret = wc_AesInit_Id(&cmac->aes, id, idLen, heap, devId);
193
0
            }
194
0
            break;
195
0
        case CMAC_AES_INIT_LABEL:
196
0
            if (label == NULL || id != NULL || idLen != 0) {
197
0
                ret = BAD_FUNC_ARG;
198
0
            }
199
0
            else {
200
0
                ret = wc_AesInit_Label(&cmac->aes, label, heap, devId);
201
0
            }
202
0
            break;
203
0
#endif
204
111
        default:
205
111
            if (id != NULL || idLen != 0 || label != NULL) {
206
0
                ret = BAD_FUNC_ARG;
207
0
            }
208
111
            else {
209
111
                ret = wc_AesInit(&cmac->aes, heap, devId);
210
111
            }
211
111
            break;
212
111
        }
213
111
        if (ret != 0) {
214
0
            return ret;
215
0
        }
216
217
    #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
218
        cmac->useSWCrypt = useSW;
219
        if (cmac->useSWCrypt == 1) {
220
            cmac->aes.useSWCrypt = 1;
221
        }
222
    #endif
223
224
111
        if (ret == 0) {
225
111
            ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
226
111
        }
227
228
111
        if (ret == 0) {
229
111
            byte l[WC_AES_BLOCK_SIZE];
230
231
111
            XMEMSET(l, 0, WC_AES_BLOCK_SIZE);
232
111
#ifndef HAVE_SELFTEST
233
111
            ret = wc_AesEncryptDirect(&cmac->aes, l, l);
234
111
            if (ret == 0) {
235
111
                ShiftAndXorRb(cmac->k1, l);
236
111
                ShiftAndXorRb(cmac->k2, cmac->k1);
237
111
                ForceZero(l, WC_AES_BLOCK_SIZE);
238
111
            }
239
#else
240
            wc_AesEncryptDirect(&cmac->aes, l, l);
241
            ShiftAndXorRb(cmac->k1, l);
242
            ShiftAndXorRb(cmac->k2, cmac->k1);
243
            ForceZero(l, WC_AES_BLOCK_SIZE);
244
#endif
245
111
        }
246
111
        break;
247
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
248
0
    default:
249
0
        return BAD_FUNC_ARG;
250
111
    }
251
252
111
    return ret;
253
111
}
254
255
256
/* returns 0 on success */
257
int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz,
258
                int type, void* unused, void* heap, int devId)
259
111
{
260
111
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
261
111
                            CMAC_AES_INIT_PLAIN, NULL, 0, NULL);
262
111
}
263
264
265
int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
266
                int type, void* unused)
267
111
{
268
#ifdef WOLFSSL_QNX_CAAM
269
    int devId = WOLFSSL_CAAM_DEVID;
270
#else
271
111
    int devId = INVALID_DEVID;
272
111
#endif
273
111
    return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, devId);
274
111
}
275
276
277
#ifdef WOLF_PRIVATE_KEY_ID
278
/* returns 0 on success */
279
int wc_InitCmac_Id(Cmac* cmac, const byte* key, word32 keySz,
280
                   int type, void* unused, unsigned char* id, int len,
281
                   void* heap, int devId)
282
0
{
283
0
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
284
0
                            CMAC_AES_INIT_ID, id, len, NULL);
285
0
}
286
287
288
/* returns 0 on success */
289
int wc_InitCmac_Label(Cmac* cmac, const byte* key, word32 keySz,
290
                      int type, void* unused, const char* label,
291
                      void* heap, int devId)
292
0
{
293
0
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
294
0
                            CMAC_AES_INIT_LABEL, NULL, 0, label);
295
0
}
296
#endif /* WOLF_PRIVATE_KEY_ID */
297
298
299
int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
300
628
{
301
628
    int ret = 0;
302
303
628
    if ((cmac == NULL) || (in == NULL && inSz != 0)) {
304
0
        return BAD_FUNC_ARG;
305
0
    }
306
307
628
#ifdef WOLF_CRYPTO_CB
308
628
    #ifndef WOLF_CRYPTO_CB_FIND
309
628
    if (cmac->devId != INVALID_DEVID)
310
0
    #endif
311
0
    {
312
0
        ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz,
313
0
            NULL, NULL, (int)cmac->type, NULL);
314
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
315
0
            return ret;
316
        /* fall-through when unavailable */
317
0
    }
318
628
#endif
319
320
    /* Clear CRYPTOCB_UNAVAILABLE return code */
321
628
    ret = 0;
322
323
628
    switch (cmac->type) {
324
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
325
628
    case WC_CMAC_AES:
326
628
    {
327
#ifdef HAVE_SELFTEST
328
        while ((ret == 0) && (inSz != 0)) {
329
            word32 add = min(inSz, WC_AES_BLOCK_SIZE - cmac->bufferSz);
330
            XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
331
332
            cmac->bufferSz += add;
333
            in += add;
334
            inSz -= add;
335
336
            if (cmac->bufferSz == WC_AES_BLOCK_SIZE && inSz != 0) {
337
                xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
338
                wc_AesEncryptDirect(&cmac->aes, cmac->digest,
339
                        cmac->buffer);
340
                cmac->totalSz += WC_AES_BLOCK_SIZE;
341
                cmac->bufferSz = 0;
342
            }
343
        }
344
#else
345
628
        (void)ret;
346
628
        ret = wc_local_CmacUpdateAes(cmac, in, inSz);
347
628
#endif
348
628
    }; break;
349
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
350
0
    default:
351
0
        ret = BAD_FUNC_ARG;
352
628
    }
353
628
    return ret;
354
628
}
355
356
int wc_CmacFree(Cmac* cmac)
357
111
{
358
111
    if (cmac == NULL)
359
0
        return BAD_FUNC_ARG;
360
#if defined(WOLFSSL_HASH_KEEP)
361
    /* TODO: msg is leaked if wc_CmacFinal() is not called
362
     * e.g. when multiple calls to wc_CmacUpdate() and one fails but
363
     * wc_CmacFinal() not called. */
364
    XFREE(cmac->msg, cmac->aes.heap, DYNAMIC_TYPE_TMP_BUFFER);
365
#endif
366
111
    switch (cmac->type) {
367
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
368
111
    case WC_CMAC_AES:
369
111
        wc_AesFree(&cmac->aes);
370
111
        break;
371
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
372
0
    default:
373
        /* Nothing to do */
374
0
        (void)cmac;
375
111
    }
376
111
    ForceZero(cmac, sizeof(Cmac));
377
111
    return 0;
378
111
}
379
380
int wc_CmacFinalNoFree(Cmac* cmac, byte* out, word32* outSz)
381
111
{
382
111
    int ret = 0;
383
384
111
    if (cmac == NULL || out == NULL || outSz == NULL) {
385
0
        return BAD_FUNC_ARG;
386
0
    }
387
111
    if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) {
388
0
        return BUFFER_E;
389
0
    }
390
391
111
#ifdef WOLF_CRYPTO_CB
392
111
    #ifndef WOLF_CRYPTO_CB_FIND
393
111
    if (cmac->devId != INVALID_DEVID)
394
0
    #endif
395
0
    {
396
0
        ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz,
397
0
            (int)cmac->type, NULL);
398
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
399
0
            return ret;
400
401
        /* Clear CRYPTOCB_UNAVAILABLE return code */
402
0
       ret = 0;
403
404
        /* fall-through when unavailable */
405
0
    }
406
111
#endif
407
111
    if (ret == 0) {
408
111
        switch (cmac->type) {
409
0
    #if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
410
111
        case WC_CMAC_AES:
411
111
        {
412
111
            const byte* subKey;
413
111
            word32 remainder;
414
415
111
            if (cmac->bufferSz == WC_AES_BLOCK_SIZE) {
416
0
                subKey = cmac->k1;
417
0
            }
418
111
            else {
419
                /* ensure we will have a valid remainder value */
420
111
                if (cmac->bufferSz > WC_AES_BLOCK_SIZE) {
421
0
                    ret = BAD_STATE_E;
422
0
                    break;
423
0
                }
424
111
                remainder = WC_AES_BLOCK_SIZE - cmac->bufferSz;
425
426
111
                if (remainder == 0) {
427
0
                    remainder = WC_AES_BLOCK_SIZE;
428
0
                }
429
111
                if (remainder > 1) {
430
76
                    XMEMSET(cmac->buffer + WC_AES_BLOCK_SIZE - remainder, 0,
431
76
                            remainder);
432
76
                }
433
434
111
                cmac->buffer[WC_AES_BLOCK_SIZE - remainder] = 0x80;
435
111
                subKey = cmac->k2;
436
111
            }
437
111
            xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
438
111
            xorbuf(cmac->buffer, subKey, WC_AES_BLOCK_SIZE);
439
111
#ifndef HAVE_SELFTEST
440
111
            ret = wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
441
111
            if (ret == 0) {
442
111
                XMEMCPY(out, cmac->digest, *outSz);
443
111
            }
444
#else
445
            wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
446
            XMEMCPY(out, cmac->digest, *outSz);
447
#endif
448
111
        }; break;
449
0
    #endif /* !NO_AES && WOLFSSL_AES_DIRECT */
450
0
        default:
451
0
            ret = BAD_FUNC_ARG;
452
111
        }
453
111
    }
454
111
    return ret;
455
111
}
456
457
int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
458
111
{
459
111
    int ret = 0;
460
461
111
    if (cmac == NULL)
462
0
        return BAD_FUNC_ARG;
463
111
    ret = wc_CmacFinalNoFree(cmac, out, outSz);
464
111
    (void)wc_CmacFree(cmac);
465
111
    return ret;
466
111
}
467
468
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
469
int wc_AesCmacGenerate_ex(Cmac* cmac,
470
                          byte* out, word32* outSz,
471
                          const byte* in, word32 inSz,
472
                          const byte* key, word32 keySz,
473
                          void* heap, int devId)
474
0
{
475
0
    int ret = 0;
476
477
0
    if (cmac == NULL) {
478
0
        return BAD_FUNC_ARG;
479
0
    }
480
481
0
#ifdef WOLF_CRYPTO_CB
482
    /* Set devId regardless of value (invalid or not) */
483
0
    cmac->devId = devId;
484
0
    #ifndef WOLF_CRYPTO_CB_FIND
485
0
    if (devId != INVALID_DEVID)
486
0
    #endif
487
0
    {
488
0
        ret = wc_CryptoCb_Cmac(cmac, key, keySz, in, inSz, out, outSz,
489
0
                WC_CMAC_AES, NULL);
490
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
491
0
            return ret;
492
493
         /* Clear CRYPTOCB_UNAVAILABLE return code */
494
0
        ret = 0;
495
496
        /* fall-through when unavailable */
497
0
    }
498
0
#endif
499
500
0
    if ( ((out == NULL) && (outSz != NULL) && (*outSz > 0))
501
0
         || (in == NULL && inSz > 0)
502
0
         || (key == NULL && keySz > 0))  {
503
0
        return BAD_FUNC_ARG;
504
0
    }
505
506
    /* Init step is optional */
507
0
    if (key != NULL) {
508
0
        ret = wc_InitCmac_ex(cmac, key, keySz, WC_CMAC_AES, NULL, heap, devId);
509
0
    }
510
0
    if (ret == 0) {
511
0
        ret = wc_CmacUpdate(cmac, in, inSz);
512
        /* Ensure we are freed and zeroed if not calling wc_CmacFinal */
513
0
        if (ret != 0) {
514
0
            (void)wc_CmacFree(cmac);
515
0
        }
516
0
    }
517
0
    if (ret == 0) {
518
0
        ret = wc_CmacFinal(cmac, out, outSz);
519
0
    }
520
521
0
    return ret;
522
0
}
523
524
525
int wc_AesCmacGenerate(byte* out, word32* outSz,
526
                       const byte* in, word32 inSz,
527
                       const byte* key, word32 keySz)
528
0
{
529
0
    int ret = 0;
530
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
531
532
0
    if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) {
533
0
        return BAD_FUNC_ARG;
534
0
    }
535
536
0
#ifdef WOLFSSL_SMALL_STACK
537
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
538
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
539
0
        return MEMORY_E;
540
0
    }
541
0
#endif
542
543
#ifdef WOLFSSL_CHECK_MEM_ZERO
544
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
545
        sizeof(Cmac) - sizeof(Aes));
546
    /* Aes part is checked by wc_AesFree. */
547
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
548
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
549
#endif
550
551
0
    ret = wc_AesCmacGenerate_ex(cmac,
552
0
                                out, outSz,
553
0
                                in, inSz,
554
0
                                key, keySz,
555
0
                                NULL,
556
0
                                INVALID_DEVID);
557
558
559
0
#ifdef WOLFSSL_SMALL_STACK
560
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
561
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
562
    wc_MemZero_Check(cmac, sizeof(Cmac));
563
#endif
564
565
0
    return ret;
566
0
}
567
568
569
int wc_AesCmacVerify_ex(Cmac* cmac,
570
                        const byte* check, word32 checkSz,
571
                        const byte* in, word32 inSz,
572
                        const byte* key, word32 keySz,
573
                        void* heap, int devId)
574
0
{
575
0
    int ret = 0;
576
0
    byte a[WC_AES_BLOCK_SIZE];
577
0
    word32 aSz;
578
0
    int compareRet;
579
580
0
    if (cmac == NULL || check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
581
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz != 0)) {
582
0
        return BAD_FUNC_ARG;
583
0
    }
584
585
0
    aSz = checkSz;
586
0
    XMEMSET(a, 0, sizeof(a));
587
0
    ret = wc_AesCmacGenerate_ex(cmac,
588
0
                                a, &aSz,
589
0
                                in, inSz,
590
0
                                key, keySz,
591
0
                                heap,
592
0
                                devId);
593
    /* aSz is passed by reference to wc_AesCmacGenerate_ex, which on the
594
     * WOLF_CRYPTO_CB path forwards it to a user-supplied callback that may
595
     * write back any value. Reject anything that does not match the user
596
     * provided length. */
597
0
    if (ret == 0 && aSz != checkSz) {
598
0
        ret = BAD_STATE_E;
599
0
    }
600
0
    if (ret == 0) {
601
0
        compareRet = ConstantCompare(check, a, (int)aSz);
602
0
        ret = compareRet ? MAC_CMP_FAILED_E : 0;
603
0
    }
604
605
0
    return ret;
606
0
}
607
608
609
int wc_AesCmacVerify(const byte* check, word32 checkSz,
610
                     const byte* in, word32 inSz,
611
                     const byte* key, word32 keySz)
612
0
{
613
0
    int ret = 0;
614
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
615
616
0
    if (check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
617
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz > 0) ||
618
0
            key == NULL || keySz == 0) {
619
0
        return BAD_FUNC_ARG;
620
0
    }
621
622
0
#ifdef WOLFSSL_SMALL_STACK
623
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
624
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
625
0
        return MEMORY_E;
626
0
    }
627
0
#endif
628
629
#ifdef WOLFSSL_CHECK_MEM_ZERO
630
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
631
        sizeof(Cmac) - sizeof(Aes));
632
    /* Aes part is checked by wc_AesFree. */
633
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
634
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
635
#endif
636
637
0
    ret = wc_AesCmacVerify_ex(cmac,
638
0
                              check, checkSz,
639
0
                              in, inSz,
640
0
                              key, keySz,
641
0
                              NULL,
642
0
                              INVALID_DEVID);
643
644
0
#ifdef WOLFSSL_SMALL_STACK
645
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
646
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
647
    wc_MemZero_Check(cmac, sizeof(Cmac));
648
#endif
649
650
0
    return ret;
651
0
}
652
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
653
654
#endif /* WOLFSSL_CMAC */