Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cmac.c Source File

cmac.c

00001 /* cmac.c
00002  *
00003  * Copyright (C) 2006-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfcrypt/settings.h>
00028 
00029 #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
00030 
00031 #if defined(HAVE_FIPS) && \
00032     defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
00033 
00034     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00035     #define FIPS_NO_WRAPPERS
00036 
00037     #ifdef USE_WINDOWS_API
00038         #pragma code_seg(".fipsA$n")
00039         #pragma const_seg(".fipsB$n")
00040     #endif
00041 #endif
00042 
00043 #ifdef NO_INLINE
00044     #include <wolfcrypt/misc.h>
00045 #else
00046     #define WOLFSSL_MISC_INCLUDED
00047     #include <wolfcrypt/src/misc.c>
00048 #endif
00049 
00050 #include <wolfcrypt/error-crypt.h>
00051 #include <wolfcrypt/aes.h>
00052 #include <wolfcrypt/cmac.h>
00053 
00054 
00055 static void ShiftAndXorRb(byte* out, byte* in)
00056 {
00057     int i, j, xorRb;
00058     int mask = 0, last = 0;
00059     byte Rb = 0x87;
00060 
00061     xorRb = (in[0] & 0x80) != 0;
00062 
00063     for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) {
00064         last = (in[j] & 0x80) ? 1 : 0;
00065         out[j] = (byte)((in[j] << 1) | mask);
00066         mask = last;
00067         if (xorRb) {
00068             out[j] ^= Rb;
00069             Rb = 0;
00070         }
00071     }
00072 }
00073 
00074 
00075 int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
00076                 int type, void* unused)
00077 {
00078     int ret;
00079 
00080     (void)unused;
00081 
00082     if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES)
00083         return BAD_FUNC_ARG;
00084 
00085     XMEMSET(cmac, 0, sizeof(Cmac));
00086     ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
00087     if (ret == 0) {
00088         byte l[AES_BLOCK_SIZE];
00089 
00090         XMEMSET(l, 0, AES_BLOCK_SIZE);
00091         wc_AesEncryptDirect(&cmac->aes, l, l);
00092         ShiftAndXorRb(cmac->k1, l);
00093         ShiftAndXorRb(cmac->k2, cmac->k1);
00094         ForceZero(l, AES_BLOCK_SIZE);
00095     }
00096     return ret;
00097 }
00098 
00099 
00100 int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
00101 {
00102     if ((cmac == NULL) || (in == NULL && inSz != 0))
00103         return BAD_FUNC_ARG;
00104 
00105     while (inSz != 0) {
00106         word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz);
00107         XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
00108 
00109         cmac->bufferSz += add;
00110         in += add;
00111         inSz -= add;
00112 
00113         if (cmac->bufferSz == AES_BLOCK_SIZE && inSz != 0) {
00114             if (cmac->totalSz != 0)
00115                 xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
00116             wc_AesEncryptDirect(&cmac->aes,
00117                                 cmac->digest,
00118                                 cmac->buffer);
00119             cmac->totalSz += AES_BLOCK_SIZE;
00120             cmac->bufferSz = 0;
00121         }
00122     }
00123 
00124     return 0;
00125 }
00126 
00127 
00128 int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
00129 {
00130     const byte* subKey;
00131 
00132     if (cmac == NULL || out == NULL || outSz == NULL)
00133         return BAD_FUNC_ARG;
00134 
00135     if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ)
00136         return BUFFER_E;
00137 
00138     if (cmac->bufferSz == AES_BLOCK_SIZE) {
00139         subKey = cmac->k1;
00140     }
00141     else {
00142         word32 remainder = AES_BLOCK_SIZE - cmac->bufferSz;
00143 
00144         if (remainder == 0)
00145             remainder = AES_BLOCK_SIZE;
00146 
00147         if (remainder > 1)
00148             XMEMSET(cmac->buffer + AES_BLOCK_SIZE - remainder, 0, remainder);
00149         cmac->buffer[AES_BLOCK_SIZE - remainder] = 0x80;
00150         subKey = cmac->k2;
00151     }
00152     xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
00153     xorbuf(cmac->buffer, subKey, AES_BLOCK_SIZE);
00154     wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
00155 
00156     XMEMCPY(out, cmac->digest, *outSz);
00157 
00158     ForceZero(cmac, sizeof(Cmac));
00159 
00160     return 0;
00161 }
00162 
00163 
00164 int wc_AesCmacGenerate(byte* out, word32* outSz,
00165                        const byte* in, word32 inSz,
00166                        const byte* key, word32 keySz)
00167 {
00168     Cmac cmac;
00169     int ret;
00170 
00171     if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0)
00172         return BAD_FUNC_ARG;
00173 
00174     ret = wc_InitCmac(&cmac, key, keySz, WC_CMAC_AES, NULL);
00175     if (ret != 0)
00176         return ret;
00177 
00178     ret = wc_CmacUpdate(&cmac, in, inSz);
00179     if (ret != 0)
00180         return ret;
00181 
00182     ret = wc_CmacFinal(&cmac, out, outSz);
00183     if (ret != 0)
00184         return ret;
00185 
00186     return 0;
00187 }
00188 
00189 
00190 int wc_AesCmacVerify(const byte* check, word32 checkSz,
00191                      const byte* in, word32 inSz,
00192                      const byte* key, word32 keySz)
00193 {
00194     byte a[AES_BLOCK_SIZE];
00195     word32 aSz = sizeof(a);
00196     int result;
00197     int compareRet;
00198 
00199     if (check == NULL || checkSz == 0 || (in == NULL && inSz != 0) ||
00200         key == NULL || keySz == 0)
00201 
00202         return BAD_FUNC_ARG;
00203 
00204     XMEMSET(a, 0, aSz);
00205     result = wc_AesCmacGenerate(a, &aSz, in, inSz, key, keySz);
00206     compareRet = ConstantCompare(check, a, min(checkSz, aSz));
00207 
00208     if (result == 0)
00209         result = compareRet ? 1 : 0;
00210 
00211     return result;
00212 }
00213 
00214 
00215 #endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */
00216