1 /* cmac.c
2 *
3 * Copyright (C) 2006-2021 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 2 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
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <wolfssl/wolfcrypt/settings.h>
28 #ifdef WOLFSSL_QNX_CAAM
29 #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
30 #endif
31
32 #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
33
34 #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
35 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
36 #define FIPS_NO_WRAPPERS
37
38 #ifdef USE_WINDOWS_API
39 #pragma code_seg(".fipsA$n")
40 #pragma const_seg(".fipsB$n")
41 #endif
42 #endif
43
44 #ifdef NO_INLINE
45 #include <wolfssl/wolfcrypt/misc.h>
46 #else
47 #define WOLFSSL_MISC_INCLUDED
48 #include <wolfcrypt/src/misc.c>
49 #endif
50
51 #include <wolfssl/wolfcrypt/error-crypt.h>
52 #include <wolfssl/wolfcrypt/aes.h>
53 #include <wolfssl/wolfcrypt/cmac.h>
54
55 #ifdef WOLF_CRYPTO_CB
56 #include <wolfssl/wolfcrypt/cryptocb.h>
57 #endif
58
59
ShiftAndXorRb(byte * out,byte * in)60 static void ShiftAndXorRb(byte* out, byte* in)
61 {
62 int i, j, xorRb;
63 int mask = 0, last = 0;
64 byte Rb = 0x87;
65
66 xorRb = (in[0] & 0x80) != 0;
67
68 for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) {
69 last = (in[j] & 0x80) ? 1 : 0;
70 out[j] = (byte)((in[j] << 1) | mask);
71 mask = last;
72 if (xorRb) {
73 out[j] ^= Rb;
74 Rb = 0;
75 }
76 }
77 }
78
79
80
81 /* returns 0 on success */
wc_InitCmac_ex(Cmac * cmac,const byte * key,word32 keySz,int type,void * unused,void * heap,int devId)82 int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz,
83 int type, void* unused, void* heap, int devId)
84 {
85 int ret;
86
87 (void)unused;
88 (void)heap;
89
90 if (cmac == NULL || keySz == 0 || type != WC_CMAC_AES) {
91 return BAD_FUNC_ARG;
92 }
93
94 XMEMSET(cmac, 0, sizeof(Cmac));
95
96 #ifdef WOLF_CRYPTO_CB
97 if (devId != INVALID_DEVID) {
98 cmac->devId = devId;
99 cmac->devCtx = NULL;
100
101 ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL,
102 type, unused);
103 if (ret != CRYPTOCB_UNAVAILABLE)
104 return ret;
105 /* fall-through when unavailable */
106 }
107 #else
108 (void)devId;
109 #endif
110
111 if (key == NULL) {
112 return BAD_FUNC_ARG;
113 }
114
115 ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
116 if (ret == 0) {
117 byte l[AES_BLOCK_SIZE];
118
119 XMEMSET(l, 0, AES_BLOCK_SIZE);
120 #ifdef WOLFSSL_LINUXKM
121 ret =
122 #endif
123 wc_AesEncryptDirect(&cmac->aes, l, l);
124 #ifdef WOLFSSL_LINUXKM
125 if (ret == 0) {
126 #endif
127 ShiftAndXorRb(cmac->k1, l);
128 ShiftAndXorRb(cmac->k2, cmac->k1);
129 ForceZero(l, AES_BLOCK_SIZE);
130 #ifdef WOLFSSL_LINUXKM
131 }
132 #endif
133 }
134 return ret;
135 }
136
137
wc_InitCmac(Cmac * cmac,const byte * key,word32 keySz,int type,void * unused)138 int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
139 int type, void* unused)
140 {
141 #ifdef WOLFSSL_QNX_CAAM
142 int devId = WOLFSSL_CAAM_DEVID;
143 #else
144 int devId = INVALID_DEVID;
145 #endif
146 return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, devId);
147 }
148
149
150
wc_CmacUpdate(Cmac * cmac,const byte * in,word32 inSz)151 int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
152 {
153 int ret = 0;
154
155 if ((cmac == NULL) || (in == NULL && inSz != 0)) {
156 return BAD_FUNC_ARG;
157 }
158
159 #ifdef WOLF_CRYPTO_CB
160 if (cmac->devId != INVALID_DEVID) {
161 ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz,
162 NULL, NULL, 0, NULL);
163 if (ret != CRYPTOCB_UNAVAILABLE)
164 return ret;
165 /* fall-through when unavailable */
166 ret = 0; /* reset error code */
167 }
168 #endif
169
170 while (inSz != 0) {
171 word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz);
172 XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
173
174 cmac->bufferSz += add;
175 in += add;
176 inSz -= add;
177
178 if (cmac->bufferSz == AES_BLOCK_SIZE && inSz != 0) {
179 if (cmac->totalSz != 0) {
180 xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
181 }
182 #ifdef WOLFSSL_LINUXKM
183 ret =
184 #endif
185 wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
186 #ifdef WOLFSSL_LINUXKM
187 if (ret == 0) {
188 #endif
189 cmac->totalSz += AES_BLOCK_SIZE;
190 cmac->bufferSz = 0;
191 #ifdef WOLFSSL_LINUXKM
192 }
193 #endif
194 }
195 }
196
197 return ret;
198 }
199
200
wc_CmacFinal(Cmac * cmac,byte * out,word32 * outSz)201 int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
202 {
203 int ret = 0;
204 const byte* subKey;
205
206 if (cmac == NULL || out == NULL || outSz == NULL) {
207 return BAD_FUNC_ARG;
208 }
209 if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) {
210 return BUFFER_E;
211 }
212
213 #ifdef WOLF_CRYPTO_CB
214 if (cmac->devId != INVALID_DEVID) {
215 ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz, 0, NULL);
216 if (ret != CRYPTOCB_UNAVAILABLE)
217 return ret;
218 /* fall-through when unavailable */
219 ret = 0; /* reset error code */
220 }
221 #endif
222
223 if (cmac->bufferSz == AES_BLOCK_SIZE) {
224 subKey = cmac->k1;
225 }
226 else {
227 word32 remainder = AES_BLOCK_SIZE - cmac->bufferSz;
228
229 if (remainder == 0) {
230 remainder = AES_BLOCK_SIZE;
231 }
232 if (remainder > 1) {
233 XMEMSET(cmac->buffer + AES_BLOCK_SIZE - remainder, 0, remainder);
234 }
235 cmac->buffer[AES_BLOCK_SIZE - remainder] = 0x80;
236 subKey = cmac->k2;
237 }
238 xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
239 xorbuf(cmac->buffer, subKey, AES_BLOCK_SIZE);
240 #ifdef WOLFSSL_LINUXKM
241 ret =
242 #endif
243 wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
244 #ifdef WOLFSSL_LINUXKM
245 if (ret == 0) {
246 #endif
247 XMEMCPY(out, cmac->digest, *outSz);
248 #ifdef WOLFSSL_LINUXKM
249 }
250 #endif
251
252 ForceZero(cmac, sizeof(Cmac));
253
254 return ret;
255 }
256
257
wc_AesCmacGenerate(byte * out,word32 * outSz,const byte * in,word32 inSz,const byte * key,word32 keySz)258 int wc_AesCmacGenerate(byte* out, word32* outSz,
259 const byte* in, word32 inSz,
260 const byte* key, word32 keySz)
261 {
262 int ret;
263 #ifdef WOLFSSL_SMALL_STACK
264 Cmac *cmac;
265 #else
266 Cmac cmac[1];
267 #endif
268
269 if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) {
270 return BAD_FUNC_ARG;
271 }
272
273 #ifdef WOLFSSL_SMALL_STACK
274 if ((cmac = (Cmac *)XMALLOC(sizeof *cmac, NULL,
275 DYNAMIC_TYPE_CMAC)) == NULL) {
276 return MEMORY_E;
277 }
278 #endif
279
280 ret = wc_InitCmac(cmac, key, keySz, WC_CMAC_AES, NULL);
281 if (ret == 0) {
282 ret = wc_CmacUpdate(cmac, in, inSz);
283 }
284 if (ret == 0) {
285 ret = wc_CmacFinal(cmac, out, outSz);
286 }
287
288 #ifdef WOLFSSL_SMALL_STACK
289 if (cmac) {
290 XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
291 }
292 #endif
293
294 return ret;
295 }
296
297
wc_AesCmacVerify(const byte * check,word32 checkSz,const byte * in,word32 inSz,const byte * key,word32 keySz)298 int wc_AesCmacVerify(const byte* check, word32 checkSz,
299 const byte* in, word32 inSz,
300 const byte* key, word32 keySz)
301 {
302 int ret;
303 byte a[AES_BLOCK_SIZE];
304 word32 aSz = sizeof(a);
305 int compareRet;
306
307 if (check == NULL || checkSz == 0 || (in == NULL && inSz != 0) ||
308 key == NULL || keySz == 0) {
309 return BAD_FUNC_ARG;
310 }
311
312 XMEMSET(a, 0, aSz);
313 ret = wc_AesCmacGenerate(a, &aSz, in, inSz, key, keySz);
314 compareRet = ConstantCompare(check, a, min(checkSz, aSz));
315
316 if (ret == 0)
317 ret = compareRet ? 1 : 0;
318
319 return ret;
320 }
321
322
323 #endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */
324