Coverage Report

Created: 2026-11-12 06:59

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
#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
    #if defined(USE_WINDOWS_API) && defined(_MSC_VER)
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
258
{
84
258
    int i, j, xorRb;
85
258
    int mask = 0, last = 0;
86
258
    byte Rb = 0x87;
87
88
258
    xorRb = (in[0] & 0x80) != 0;
89
90
4.38k
    for (i = 1, j = WC_AES_BLOCK_SIZE - 1; i <= WC_AES_BLOCK_SIZE; i++, j--) {
91
4.12k
        last = (in[j] & 0x80) ? 1 : 0;
92
4.12k
        out[j] = (byte)((in[j] << 1) | mask);
93
4.12k
        mask = last;
94
4.12k
        if (xorRb) {
95
1.20k
            out[j] ^= Rb;
96
1.20k
            Rb = 0;
97
1.20k
        }
98
4.12k
    }
99
258
}
100
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
101
102
129
#define CMAC_AES_INIT_PLAIN  0
103
#ifdef WOLF_PRIVATE_KEY_ID
104
258
#define CMAC_AES_INIT_ID     1
105
258
#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
129
{
114
129
    int ret = 0;
115
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT)
116
    byte useSW = 0;
117
#endif
118
119
129
    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
129
    XMEMSET(cmac, 0, sizeof(Cmac));
128
129
    /* Stash heap so the cryptocb can read it from the zeroed cmac. */
130
129
#ifndef NO_AES
131
129
    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
129
#ifdef WOLF_PRIVATE_KEY_ID
139
129
    cmac->aesInitType = aesInitType;
140
129
    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
129
    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
129
#endif
155
129
    (void)aesInitType;
156
129
    (void)id;
157
129
    (void)idLen;
158
129
    (void)label;
159
160
129
#ifdef WOLF_CRYPTO_CB
161
    /* Set devId regardless of value (invalid or not) */
162
129
    cmac->devId = devId;
163
    /* Set before the cryptocb early return so wc_CmacFree can clean up. */
164
129
    cmac->type = (CmacType)type;
165
129
    #ifndef WOLF_CRYPTO_CB_FIND
166
129
    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
129
    (void)unused;
184
129
    (void)heap;
185
186
129
    if (key == NULL || keySz == 0) {
187
0
        return BAD_FUNC_ARG;
188
0
    }
189
190
129
    switch (type) {
191
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
192
129
    case WC_CMAC_AES:
193
129
        cmac->type = WC_CMAC_AES;
194
129
        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
129
        default:
214
129
            if (id != NULL || idLen != 0 || label != NULL) {
215
0
                ret = BAD_FUNC_ARG;
216
0
            }
217
129
            else {
218
129
                ret = wc_AesInit(&cmac->aes, heap, devId);
219
129
            }
220
129
            break;
221
129
        }
222
129
        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
129
        if (ret == 0) {
234
129
            ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
235
129
        }
236
237
129
        if (ret == 0) {
238
129
            ALIGN16 byte l[WC_AES_BLOCK_SIZE];
239
240
129
            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
129
#ifndef HAVE_SELFTEST
245
129
            ret = wc_AesEncryptDirect(&cmac->aes, l, l);
246
129
            if (ret == 0) {
247
129
                ShiftAndXorRb(cmac->k1, l);
248
129
                ShiftAndXorRb(cmac->k2, cmac->k1);
249
129
            }
250
#else
251
            wc_AesEncryptDirect(&cmac->aes, l, l);
252
            ShiftAndXorRb(cmac->k1, l);
253
            ShiftAndXorRb(cmac->k2, cmac->k1);
254
#endif
255
129
            ForceZero(l, WC_AES_BLOCK_SIZE);
256
#ifdef WOLFSSL_CHECK_MEM_ZERO
257
            wc_MemZero_Check(l, WC_AES_BLOCK_SIZE);
258
#endif
259
129
        }
260
261
129
        if (ret != 0) {
262
0
            wc_AesFree(&cmac->aes);
263
0
            cmac->type = WC_CMAC_NONE;
264
0
        }
265
266
129
        break;
267
0
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
268
0
    default:
269
0
        return BAD_FUNC_ARG;
270
129
    }
271
272
129
    return ret;
273
129
}
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
129
{
280
129
    return _InitCmac_common(cmac, key, keySz, type, unused, heap, devId,
281
129
                            CMAC_AES_INIT_PLAIN, NULL, 0, NULL);
282
129
}
283
284
285
int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
286
                int type, void* unused)
287
129
{
288
#ifdef WOLFSSL_QNX_CAAM
289
    int devId = WOLFSSL_CAAM_DEVID;
290
#else
291
129
    int devId = INVALID_DEVID;
292
129
#endif
293
129
    return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, devId);
294
129
}
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
1.75k
{
321
1.75k
    int ret = 0;
322
323
1.75k
    if ((cmac == NULL) || (in == NULL && inSz != 0)) {
324
0
        return BAD_FUNC_ARG;
325
0
    }
326
327
1.75k
#ifdef WOLF_CRYPTO_CB
328
1.75k
    #ifndef WOLF_CRYPTO_CB_FIND
329
1.75k
    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
1.75k
#endif
339
340
    /* Clear CRYPTOCB_UNAVAILABLE return code */
341
1.75k
    ret = 0;
342
343
1.75k
    switch (cmac->type) {
344
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
345
1.75k
    case WC_CMAC_AES:
346
1.75k
    {
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
1.75k
        (void)ret;
366
1.75k
        ret = wc_local_CmacUpdateAes(cmac, in, inSz);
367
1.75k
#endif
368
1.75k
    }; 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
1.75k
    }
374
1.75k
    return ret;
375
1.75k
}
376
377
int wc_CmacFree(Cmac* cmac)
378
129
{
379
129
    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
129
    switch (cmac->type) {
399
0
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
400
129
    case WC_CMAC_AES:
401
129
        wc_AesFree(&cmac->aes);
402
129
        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
129
    }
409
129
    ForceZero(cmac, sizeof(Cmac));
410
129
    return 0;
411
129
}
412
413
#ifdef WOLFSSL_CMAC_TAG_ASSOCIATION
414
/* first use of the key fixes the length, per SP 800-38B 5.4
415
 */
416
static int CmacAssociateTagSz(Cmac* cmac, word32 tagSz)
417
129
{
418
129
    if (cmac == NULL) {
419
0
        return BAD_FUNC_ARG;
420
0
    }
421
422
129
    if (cmac->aes.tagLen == WC_NO_TAG_ASSOCIATION) {
423
129
        cmac->aes.tagLen = tagSz;
424
129
        return 0;
425
129
    }
426
427
0
    if (tagSz != cmac->aes.tagLen) {
428
0
        WOLFSSL_MSG("CMAC tag size is not the one associated with the key");
429
0
        return BAD_FUNC_ARG;
430
0
    }
431
432
0
    return 0;
433
0
}
434
435
/* One tag length per key, per SP 800-38B 5.4, which gives a range not a
436
 * list. Once set, only a new key changes it.
437
 */
438
int wc_CmacSetTagLen(Cmac* cmac, word32 tagLen)
439
0
{
440
0
    if (cmac == NULL) {
441
0
        return BAD_FUNC_ARG;
442
0
    }
443
444
0
    if (tagLen < WC_CMAC_TAG_MIN_SZ || tagLen > WC_CMAC_TAG_MAX_SZ) {
445
0
        return BAD_FUNC_ARG;
446
0
    }
447
448
0
    return wc_AesSetTagLen(&cmac->aes, tagLen);
449
0
}
450
#endif
451
452
453
int wc_CmacFinalNoFree(Cmac* cmac, byte* out, word32* outSz)
454
129
{
455
129
    int ret = 0;
456
457
129
    if (cmac == NULL || out == NULL || outSz == NULL) {
458
0
        return BAD_FUNC_ARG;
459
0
    }
460
129
    if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) {
461
0
        return BUFFER_E;
462
0
    }
463
129
#ifdef WOLFSSL_CMAC_TAG_ASSOCIATION
464
129
    if (CmacAssociateTagSz(cmac, *outSz) != 0) {
465
0
        return BAD_FUNC_ARG;
466
0
    }
467
129
#endif
468
469
129
#ifdef WOLF_CRYPTO_CB
470
129
    #ifndef WOLF_CRYPTO_CB_FIND
471
129
    if (cmac->devId != INVALID_DEVID)
472
0
    #endif
473
0
    {
474
0
        ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz,
475
0
            (int)cmac->type, NULL);
476
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
477
0
            return ret;
478
479
        /* Clear CRYPTOCB_UNAVAILABLE return code */
480
0
       ret = 0;
481
482
        /* fall-through when unavailable */
483
0
    }
484
129
#endif
485
129
    if (ret == 0) {
486
129
        switch (cmac->type) {
487
0
    #if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
488
129
        case WC_CMAC_AES:
489
129
        {
490
129
            const byte* subKey;
491
129
            word32 remainder;
492
493
129
            if (cmac->bufferSz == WC_AES_BLOCK_SIZE) {
494
0
                subKey = cmac->k1;
495
0
            }
496
129
            else {
497
                /* ensure we will have a valid remainder value */
498
129
                if (cmac->bufferSz > WC_AES_BLOCK_SIZE) {
499
0
                    ret = BAD_STATE_E;
500
0
                    break;
501
0
                }
502
129
                remainder = WC_AES_BLOCK_SIZE - cmac->bufferSz;
503
504
129
                if (remainder == 0) {
505
0
                    remainder = WC_AES_BLOCK_SIZE;
506
0
                }
507
129
                if (remainder > 1) {
508
94
                    XMEMSET(cmac->buffer + WC_AES_BLOCK_SIZE - remainder, 0,
509
94
                            remainder);
510
94
                }
511
512
129
                cmac->buffer[WC_AES_BLOCK_SIZE - remainder] = 0x80;
513
129
                subKey = cmac->k2;
514
129
            }
515
129
            xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
516
129
            xorbuf(cmac->buffer, subKey, WC_AES_BLOCK_SIZE);
517
129
#ifndef HAVE_SELFTEST
518
129
            ret = wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
519
129
            if (ret == 0) {
520
129
                XMEMCPY(out, cmac->digest, *outSz);
521
129
            }
522
#else
523
            wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
524
            XMEMCPY(out, cmac->digest, *outSz);
525
#endif
526
129
        }; break;
527
0
    #endif /* !NO_AES && WOLFSSL_AES_DIRECT */
528
0
        case WC_CMAC_NONE:
529
0
        default:
530
0
            ret = BAD_FUNC_ARG;
531
129
        }
532
129
    }
533
129
    return ret;
534
129
}
535
536
int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
537
129
{
538
129
    int ret = 0;
539
540
129
    if (cmac == NULL)
541
0
        return BAD_FUNC_ARG;
542
129
    ret = wc_CmacFinalNoFree(cmac, out, outSz);
543
129
    (void)wc_CmacFree(cmac);
544
129
    return ret;
545
129
}
546
547
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
548
int wc_AesCmacGenerate_ex(Cmac* cmac,
549
                          byte* out, word32* outSz,
550
                          const byte* in, word32 inSz,
551
                          const byte* key, word32 keySz,
552
                          void* heap, int devId)
553
0
{
554
0
    int ret = 0;
555
556
0
    if (cmac == NULL) {
557
0
        return BAD_FUNC_ARG;
558
0
    }
559
560
0
#ifdef WOLF_CRYPTO_CB
561
    /* Set devId regardless of value (invalid or not) */
562
0
    cmac->devId = devId;
563
0
    #ifndef WOLF_CRYPTO_CB_FIND
564
0
    if (devId != INVALID_DEVID)
565
0
    #endif
566
0
    {
567
0
    #ifdef WOLFSSL_CMAC_TAG_ASSOCIATION
568
        /* this path runs before the argument checks below, so associate
569
         * only when the call would pass them */
570
0
        if (key == NULL && keySz == 0 && out != NULL && outSz != NULL &&
571
0
                (in != NULL || inSz == 0)) {
572
0
            if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) {
573
0
                return BUFFER_E;
574
0
            }
575
0
            if (CmacAssociateTagSz(cmac, *outSz) != 0) {
576
0
                return BAD_FUNC_ARG;
577
0
            }
578
0
        }
579
0
    #endif
580
0
        ret = wc_CryptoCb_Cmac(cmac, key, keySz, in, inSz, out, outSz,
581
0
                WC_CMAC_AES, NULL);
582
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
583
0
    #ifdef WOLFSSL_CMAC_TAG_ASSOCIATION
584
            /* a key sets the key, so the length this call used becomes the
585
             * one that key carries */
586
0
            if (ret == 0 && key != NULL && outSz != NULL) {
587
0
                cmac->aes.tagLen = *outSz;
588
0
            }
589
0
    #endif
590
0
            return ret;
591
0
        }
592
593
         /* Clear CRYPTOCB_UNAVAILABLE return code */
594
0
        ret = 0;
595
596
        /* fall-through when unavailable */
597
0
    }
598
0
#endif
599
600
0
    if ( ((out == NULL) && (outSz != NULL) && (*outSz > 0))
601
0
         || (in == NULL && inSz > 0)
602
0
         || (key == NULL && keySz > 0))  {
603
0
        return BAD_FUNC_ARG;
604
0
    }
605
606
    /* Init step is optional */
607
0
    if (key != NULL) {
608
0
        ret = wc_InitCmac_ex(cmac, key, keySz, WC_CMAC_AES, NULL, heap, devId);
609
0
    }
610
0
    if (ret == 0) {
611
0
        ret = wc_CmacUpdate(cmac, in, inSz);
612
        /* Ensure we are freed and zeroed if not calling wc_CmacFinal */
613
0
        if (ret != 0) {
614
0
            (void)wc_CmacFree(cmac);
615
0
        }
616
0
    }
617
0
    if (ret == 0) {
618
0
        ret = wc_CmacFinal(cmac, out, outSz);
619
0
    }
620
621
0
    return ret;
622
0
}
623
624
625
int wc_AesCmacGenerate(byte* out, word32* outSz,
626
                       const byte* in, word32 inSz,
627
                       const byte* key, word32 keySz)
628
0
{
629
0
    int ret = 0;
630
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
631
632
0
    if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) {
633
0
        return BAD_FUNC_ARG;
634
0
    }
635
636
0
#ifdef WOLFSSL_SMALL_STACK
637
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
638
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
639
0
        return MEMORY_E;
640
0
    }
641
0
#endif
642
643
#ifdef WOLFSSL_CHECK_MEM_ZERO
644
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
645
        sizeof(Cmac) - sizeof(Aes));
646
    /* Aes part is checked by wc_AesFree. */
647
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
648
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
649
#endif
650
651
0
    ret = wc_AesCmacGenerate_ex(cmac,
652
0
                                out, outSz,
653
0
                                in, inSz,
654
0
                                key, keySz,
655
0
                                NULL,
656
0
                                INVALID_DEVID);
657
658
659
0
#ifdef WOLFSSL_SMALL_STACK
660
0
    ForceZero(cmac, sizeof(Cmac));
661
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
662
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
663
    wc_MemZero_Check(cmac, sizeof(Cmac));
664
#endif
665
666
0
    return ret;
667
0
}
668
669
670
int wc_AesCmacVerify_ex(Cmac* cmac,
671
                        const byte* check, word32 checkSz,
672
                        const byte* in, word32 inSz,
673
                        const byte* key, word32 keySz,
674
                        void* heap, int devId)
675
0
{
676
0
    int ret = 0;
677
0
    byte a[WC_AES_BLOCK_SIZE];
678
0
    word32 aSz;
679
0
    int compareRet;
680
681
0
    if (cmac == NULL || check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
682
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz != 0)) {
683
0
        return BAD_FUNC_ARG;
684
0
    }
685
686
0
#ifdef WOLFSSL_CMAC_TAG_ASSOCIATION
687
    /* only associate a length for a keyed cmac, a key here means this call
688
     * sets both the key and the length that goes with it */
689
0
    if (key == NULL && CmacAssociateTagSz(cmac, checkSz) != 0) {
690
0
        return BAD_FUNC_ARG;
691
0
    }
692
0
#endif
693
694
0
    aSz = checkSz;
695
0
    XMEMSET(a, 0, sizeof(a));
696
#ifdef WOLFSSL_CHECK_MEM_ZERO
697
    wc_MemZero_Add("wc_AesCmacVerify_ex a", a, sizeof(a));
698
#endif
699
0
    ret = wc_AesCmacGenerate_ex(cmac,
700
0
                                a, &aSz,
701
0
                                in, inSz,
702
0
                                key, keySz,
703
0
                                heap,
704
0
                                devId);
705
    /* aSz is passed by reference to wc_AesCmacGenerate_ex, which on the
706
     * WOLF_CRYPTO_CB path forwards it to a user-supplied callback that may
707
     * write back any value. Reject anything that does not match the user
708
     * provided length. */
709
0
    if (ret == 0 && aSz != checkSz) {
710
0
        ret = BAD_STATE_E;
711
0
    }
712
0
    if (ret == 0) {
713
0
        compareRet = ConstantCompare(check, a, (int)aSz);
714
0
        ret = compareRet ? MAC_CMP_FAILED_E : 0;
715
0
    }
716
    /* On a mismatch this is a valid tag for the message. */
717
0
    ForceZero(a, sizeof(a));
718
#ifdef WOLFSSL_CHECK_MEM_ZERO
719
    wc_MemZero_Check(a, sizeof(a));
720
#endif
721
722
0
    return ret;
723
0
}
724
725
726
int wc_AesCmacVerify(const byte* check, word32 checkSz,
727
                     const byte* in, word32 inSz,
728
                     const byte* key, word32 keySz)
729
0
{
730
0
    int ret = 0;
731
0
    WC_DECLARE_VAR(cmac, Cmac, 1, 0);
732
733
0
    if (check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
734
0
            checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz > 0) ||
735
0
            key == NULL || keySz == 0) {
736
0
        return BAD_FUNC_ARG;
737
0
    }
738
739
0
#ifdef WOLFSSL_SMALL_STACK
740
0
    if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
741
0
                                DYNAMIC_TYPE_CMAC)) == NULL) {
742
0
        return MEMORY_E;
743
0
    }
744
0
#endif
745
746
#ifdef WOLFSSL_CHECK_MEM_ZERO
747
    XMEMSET(((unsigned char *)cmac) + sizeof(Aes), 0xff,
748
        sizeof(Cmac) - sizeof(Aes));
749
    /* Aes part is checked by wc_AesFree. */
750
    wc_MemZero_Add("wc_AesCmacGenerate_ex cmac",
751
        ((unsigned char *)cmac) + sizeof(Aes), sizeof(Cmac) - sizeof(Aes));
752
#endif
753
754
0
    ret = wc_AesCmacVerify_ex(cmac,
755
0
                              check, checkSz,
756
0
                              in, inSz,
757
0
                              key, keySz,
758
0
                              NULL,
759
0
                              INVALID_DEVID);
760
761
0
#ifdef WOLFSSL_SMALL_STACK
762
0
    ForceZero(cmac, sizeof(Cmac));
763
0
    XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
764
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
765
    wc_MemZero_Check(cmac, sizeof(Cmac));
766
#endif
767
768
0
    return ret;
769
0
}
770
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
771
772
#endif /* WOLFSSL_CMAC */