wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac.c Source File

hmac.c

00001 /* hmac.h
00002  *
00003  * Copyright (C) 2006-2016 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 <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifndef NO_HMAC
00030 
00031 #include <wolfssl/wolfcrypt/hmac.h>
00032 
00033 #ifdef NO_INLINE
00034     #include <wolfssl/wolfcrypt/misc.h>
00035 #else
00036     #define WOLFSSL_MISC_INCLUDED
00037     #include <wolfcrypt/src/misc.c>
00038 #endif
00039 
00040 
00041 /* fips wrapper calls, user can call direct */
00042 #ifdef HAVE_FIPS
00043     /* does init */
00044     int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz)
00045     {
00046         return HmacSetKey_fips(hmac, type, key, keySz);
00047     }
00048     int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz)
00049     {
00050         return HmacUpdate_fips(hmac, in, sz);
00051     }
00052     int wc_HmacFinal(Hmac* hmac, byte* out)
00053     {
00054         return HmacFinal_fips(hmac, out);
00055     }
00056     int wolfSSL_GetHmacMaxSize(void)
00057     {
00058         return CyaSSL_GetHmacMaxSize();
00059     }
00060 
00061     int wc_HmacInit(Hmac* hmac, void* heap, int devId)
00062     {
00063         (void)hmac;
00064         (void)heap;
00065         (void)devId;
00066         /* FIPS doesn't support:
00067             return HmacInit(hmac, heap, devId); */
00068         return 0;
00069     }
00070     void wc_HmacFree(Hmac* hmac)
00071     {
00072         (void)hmac;
00073         /* FIPS doesn't support:
00074             HmacFree(hmac); */
00075     }
00076 
00077     #ifdef HAVE_HKDF
00078         int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
00079                     const byte* salt, word32 saltSz,
00080                     const byte* info, word32 infoSz,
00081                     byte* out, word32 outSz)
00082         {
00083             return HKDF(type, inKey, inKeySz, salt, saltSz,
00084                 info, infoSz, out, outSz);
00085         }
00086     #endif /* HAVE_HKDF */
00087 
00088 #else /* else build without fips */
00089 
00090 
00091 #include <wolfssl/wolfcrypt/error-crypt.h>
00092 
00093 
00094 #ifdef WOLFSSL_PIC32MZ_HASH
00095     #define wc_InitMd5   wc_InitMd5_sw
00096     #define wc_Md5Update wc_Md5Update_sw
00097     #define wc_Md5Final  wc_Md5Final_sw
00098 
00099     #define wc_InitSha   wc_InitSha_sw
00100     #define wc_ShaUpdate wc_ShaUpdate_sw
00101     #define wc_ShaFinal  wc_ShaFinal_sw
00102 
00103     #define wc_InitSha256   wc_InitSha256_sw
00104     #define wc_Sha256Update wc_Sha256Update_sw
00105     #define wc_Sha256Final  wc_Sha256Final_sw
00106 #endif /* WOLFSSL_PIC32MZ_HASH */
00107 
00108 
00109 
00110 int wc_HmacSizeByType(int type)
00111 {
00112     int ret;
00113 
00114     if (!(type == MD5 || type == SHA    || type == SHA256 || type == SHA384
00115                       || type == SHA512 || type == BLAKE2B_ID
00116                       || type == SHA224)) {
00117         return BAD_FUNC_ARG;
00118     }
00119 
00120     switch (type) {
00121     #ifndef NO_MD5
00122         case MD5:
00123             ret = MD5_DIGEST_SIZE;
00124             break;
00125     #endif /* !NO_MD5 */
00126 
00127     #ifndef NO_SHA
00128         case SHA:
00129             ret = SHA_DIGEST_SIZE;
00130             break;
00131     #endif /* !NO_SHA */
00132 
00133     #ifdef WOLFSSL_SHA224
00134         case SHA224:
00135             ret = SHA224_DIGEST_SIZE;
00136             break;
00137     #endif /* WOLFSSL_SHA224 */
00138 
00139     #ifndef NO_SHA256
00140         case SHA256:
00141             ret = SHA256_DIGEST_SIZE;
00142             break;
00143     #endif /* !NO_SHA256 */
00144 
00145     #ifdef WOLFSSL_SHA512
00146     #ifdef WOLFSSL_SHA384
00147         case SHA384:
00148             ret = SHA384_DIGEST_SIZE;
00149             break;
00150     #endif /* WOLFSSL_SHA384 */
00151         case SHA512:
00152             ret = SHA512_DIGEST_SIZE;
00153             break;
00154     #endif /* WOLFSSL_SHA512 */
00155 
00156     #ifdef HAVE_BLAKE2
00157         case BLAKE2B_ID:
00158             ret = BLAKE2B_OUTBYTES;
00159             break;
00160     #endif /* HAVE_BLAKE2 */
00161 
00162         default:
00163             ret = BAD_FUNC_ARG;
00164             break;
00165     }
00166 
00167     return ret;
00168 }
00169 
00170 static int _InitHmac(Hmac* hmac, int type, void* heap)
00171 {
00172     int ret = 0;
00173 
00174     switch (type) {
00175     #ifndef NO_MD5
00176         case MD5:
00177             ret = wc_InitMd5(&hmac->hash.md5);
00178             break;
00179     #endif /* !NO_MD5 */
00180 
00181     #ifndef NO_SHA
00182         case SHA:
00183             ret = wc_InitSha(&hmac->hash.sha);
00184             break;
00185     #endif /* !NO_SHA */
00186 
00187     #ifdef WOLFSSL_SHA224
00188         case SHA224:
00189             ret = wc_InitSha224(&hmac->hash.sha224);
00190             break;
00191     #endif /* WOLFSSL_SHA224 */
00192 
00193     #ifndef NO_SHA256
00194         case SHA256:
00195             ret = wc_InitSha256(&hmac->hash.sha256);
00196             break;
00197     #endif /* !NO_SHA256 */
00198 
00199     #ifdef WOLFSSL_SHA512
00200     #ifdef WOLFSSL_SHA384
00201         case SHA384:
00202             ret = wc_InitSha384(&hmac->hash.sha384);
00203             break;
00204     #endif /* WOLFSSL_SHA384 */
00205         case SHA512:
00206             ret = wc_InitSha512(&hmac->hash.sha512);
00207             break;
00208     #endif /* WOLFSSL_SHA512 */
00209 
00210     #ifdef HAVE_BLAKE2
00211         case BLAKE2B_ID:
00212             ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256);
00213             break;
00214     #endif /* HAVE_BLAKE2 */
00215 
00216         default:
00217             ret = BAD_FUNC_ARG;
00218             break;
00219     }
00220 
00221     /* default to NULL heap hint or test value */
00222 #ifdef WOLFSSL_HEAP_TEST
00223     hmac->heap = (void)WOLFSSL_HEAP_TEST;
00224 #else
00225     hmac->heap = heap;
00226 #endif /* WOLFSSL_HEAP_TEST */
00227 
00228     return ret;
00229 }
00230 
00231 
00232 int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
00233 {
00234     byte*  ip;
00235     byte*  op;
00236     word32 i, hmac_block_size = 0;
00237     int    ret = 0;
00238     void*  heap = NULL;
00239 
00240     if (hmac == NULL || (key == NULL && length != 0) ||
00241         !(type == MD5 || type == SHA    || type == SHA256 || type == SHA384
00242                       || type == SHA512 || type == BLAKE2B_ID
00243                       || type == SHA224)) {
00244         return BAD_FUNC_ARG;
00245     }
00246 
00247     hmac->innerHashKeyed = 0;
00248     hmac->macType = (byte)type;
00249 
00250 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
00251     if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
00252     #if defined(HAVE_CAVIUM) || defined(HAVE_INTEL_QA)
00253         if (length > HMAC_BLOCK_SIZE) {
00254             return WC_KEY_SIZE_E;
00255         }
00256 
00257         if (key != NULL) {
00258             XMEMCPY(hmac->keyRaw, key, length);
00259         }
00260         hmac->keyLen = (word16)length;
00261 
00262         return 0; /* nothing to do here */
00263     #endif /* HAVE_CAVIUM || HAVE_INTEL_QA */
00264     }
00265 #endif /* WOLFSSL_ASYNC_CRYPT */
00266 
00267     ret = _InitHmac(hmac, type, heap);
00268     if (ret != 0)
00269         return ret;
00270 
00271 #ifdef HAVE_FIPS
00272     if (length < HMAC_FIPS_MIN_KEY)
00273         return HMAC_MIN_KEYLEN_E;
00274 #endif
00275 
00276     ip = (byte*)hmac->ipad;
00277     op = (byte*)hmac->opad;
00278 
00279     switch (hmac->macType) {
00280     #ifndef NO_MD5
00281         case MD5:
00282             hmac_block_size = MD5_BLOCK_SIZE;
00283             if (length <= MD5_BLOCK_SIZE) {
00284                 if (key != NULL) {
00285                     XMEMCPY(ip, key, length);
00286                 }
00287             }
00288             else {
00289                 ret = wc_Md5Update(&hmac->hash.md5, key, length);
00290                 if (ret != 0)
00291                     break;
00292                 ret = wc_Md5Final(&hmac->hash.md5, ip);
00293                 if (ret != 0)
00294                     break;
00295                 length = MD5_DIGEST_SIZE;
00296             }
00297             break;
00298     #endif /* !NO_MD5 */
00299 
00300     #ifndef NO_SHA
00301         case SHA:
00302             hmac_block_size = SHA_BLOCK_SIZE;
00303             if (length <= SHA_BLOCK_SIZE) {
00304                 if (key != NULL) {
00305                     XMEMCPY(ip, key, length);
00306                 }
00307             }
00308             else {
00309                 ret = wc_ShaUpdate(&hmac->hash.sha, key, length);
00310                 if (ret != 0)
00311                     break;
00312                 ret = wc_ShaFinal(&hmac->hash.sha, ip);
00313                 if (ret != 0)
00314                     break;
00315 
00316                 length = SHA_DIGEST_SIZE;
00317             }
00318             break;
00319     #endif /* !NO_SHA */
00320 
00321     #ifdef WOLFSSL_SHA224
00322         case SHA224:
00323         {
00324             hmac_block_size = SHA224_BLOCK_SIZE;
00325             if (length <= SHA224_BLOCK_SIZE) {
00326                 if (key != NULL) {
00327                     XMEMCPY(ip, key, length);
00328                 }
00329             }
00330             else {
00331                 ret = wc_Sha224Update(&hmac->hash.sha224, key, length);
00332                 if (ret != 0)
00333                     break;
00334                 ret = wc_Sha224Final(&hmac->hash.sha224, ip);
00335                 if (ret != 0)
00336                     break;
00337 
00338                 length = SHA224_DIGEST_SIZE;
00339             }
00340         }
00341         break;
00342     #endif /* WOLFSSL_SHA224 */
00343 
00344     #ifndef NO_SHA256
00345         case SHA256:
00346             hmac_block_size = SHA256_BLOCK_SIZE;
00347             if (length <= SHA256_BLOCK_SIZE) {
00348                 if (key != NULL) {
00349                     XMEMCPY(ip, key, length);
00350                 }
00351             }
00352             else {
00353                 ret = wc_Sha256Update(&hmac->hash.sha256, key, length);
00354                 if (ret != 0)
00355                     break;
00356                 ret = wc_Sha256Final(&hmac->hash.sha256, ip);
00357                 if (ret != 0)
00358                     break;
00359 
00360                 length = SHA256_DIGEST_SIZE;
00361             }
00362             break;
00363     #endif /* !NO_SHA256 */
00364 
00365     #ifdef WOLFSSL_SHA512
00366     #ifdef WOLFSSL_SHA384
00367         case SHA384:
00368             hmac_block_size = SHA384_BLOCK_SIZE;
00369             if (length <= SHA384_BLOCK_SIZE) {
00370                 if (key != NULL) {
00371                     XMEMCPY(ip, key, length);
00372                 }
00373             }
00374             else {
00375                 ret = wc_Sha384Update(&hmac->hash.sha384, key, length);
00376                 if (ret != 0)
00377                     break;
00378                 ret = wc_Sha384Final(&hmac->hash.sha384, ip);
00379                 if (ret != 0)
00380                     break;
00381 
00382                 length = SHA384_DIGEST_SIZE;
00383             }
00384             break;
00385     #endif /* WOLFSSL_SHA384 */
00386         case SHA512:
00387             hmac_block_size = SHA512_BLOCK_SIZE;
00388             if (length <= SHA512_BLOCK_SIZE) {
00389                 if (key != NULL) {
00390                     XMEMCPY(ip, key, length);
00391                 }
00392             }
00393             else {
00394                 ret = wc_Sha512Update(&hmac->hash.sha512, key, length);
00395                 if (ret != 0)
00396                     break;
00397                 ret = wc_Sha512Final(&hmac->hash.sha512, ip);
00398                 if (ret != 0)
00399                     break;
00400 
00401                 length = SHA512_DIGEST_SIZE;
00402             }
00403             break;
00404     #endif /* WOLFSSL_SHA512 */
00405 
00406     #ifdef HAVE_BLAKE2
00407         case BLAKE2B_ID:
00408             hmac_block_size = BLAKE2B_BLOCKBYTES;
00409             if (length <= BLAKE2B_BLOCKBYTES) {
00410                 if (key != NULL) {
00411                     XMEMCPY(ip, key, length);
00412                 }
00413             }
00414             else {
00415                 ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length);
00416                 if (ret != 0)
00417                     break;
00418                 ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256);
00419                 if (ret != 0)
00420                     break;
00421 
00422                 length = BLAKE2B_256;
00423             }
00424             break;
00425     #endif /* HAVE_BLAKE2 */
00426 
00427         default:
00428             return BAD_FUNC_ARG;
00429     }
00430 
00431     if (ret == 0) {
00432         if (length < hmac_block_size)
00433             XMEMSET(ip + length, 0, hmac_block_size - length);
00434 
00435         for(i = 0; i < hmac_block_size; i++) {
00436             op[i] = ip[i] ^ OPAD;
00437             ip[i] ^= IPAD;
00438         }
00439     }
00440 
00441     return ret;
00442 }
00443 
00444 
00445 static int HmacKeyInnerHash(Hmac* hmac)
00446 {
00447     int ret = 0;
00448 
00449     switch (hmac->macType) {
00450     #ifndef NO_MD5
00451         case MD5:
00452             ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad,
00453                                                                 MD5_BLOCK_SIZE);
00454             break;
00455     #endif /* !NO_MD5 */
00456 
00457     #ifndef NO_SHA
00458         case SHA:
00459             ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad,
00460                                                                 SHA_BLOCK_SIZE);
00461             break;
00462     #endif /* !NO_SHA */
00463 
00464     #ifdef WOLFSSL_SHA224
00465         case SHA224:
00466             ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad,
00467                                                              SHA224_BLOCK_SIZE);
00468             break;
00469     #endif /* WOLFSSL_SHA224 */
00470 
00471     #ifndef NO_SHA256
00472         case SHA256:
00473             ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad,
00474                                                              SHA256_BLOCK_SIZE);
00475             break;
00476     #endif /* !NO_SHA256 */
00477 
00478     #ifdef WOLFSSL_SHA512
00479     #ifdef WOLFSSL_SHA384
00480         case SHA384:
00481             ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad,
00482                                                              SHA384_BLOCK_SIZE);
00483             break;
00484     #endif /* WOLFSSL_SHA384 */
00485         case SHA512:
00486             ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad,
00487                                                              SHA512_BLOCK_SIZE);
00488             break;
00489     #endif /* WOLFSSL_SHA512 */
00490 
00491     #ifdef HAVE_BLAKE2
00492         case BLAKE2B_ID:
00493             ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad,
00494                                                             BLAKE2B_BLOCKBYTES);
00495             break;
00496     #endif /* HAVE_BLAKE2 */
00497 
00498         default:
00499             break;
00500     }
00501 
00502     if (ret == 0)
00503         hmac->innerHashKeyed = 1;
00504 
00505     return ret;
00506 }
00507 
00508 
00509 int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
00510 {
00511     int ret = 0;
00512 
00513 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
00514     if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
00515     #if defined(HAVE_CAVIUM)
00516         return NitroxHmacUpdate(hmac, msg, length);
00517     #elif defined(HAVE_INTEL_QA)
00518         return IntelQaHmac(&hmac->asyncDev, hmac->macType,
00519             hmac->keyRaw, hmac->keyLen, NULL, msg, length);
00520     #endif
00521     }
00522 #endif /* WOLFSSL_ASYNC_CRYPT */
00523 
00524     if (!hmac->innerHashKeyed) {
00525         ret = HmacKeyInnerHash(hmac);
00526         if (ret != 0)
00527             return ret;
00528     }
00529 
00530     switch (hmac->macType) {
00531     #ifndef NO_MD5
00532         case MD5:
00533             ret = wc_Md5Update(&hmac->hash.md5, msg, length);
00534             break;
00535     #endif /* !NO_MD5 */
00536 
00537     #ifndef NO_SHA
00538         case SHA:
00539             ret = wc_ShaUpdate(&hmac->hash.sha, msg, length);
00540             break;
00541     #endif /* !NO_SHA */
00542 
00543     #ifdef WOLFSSL_SHA224
00544         case SHA224:
00545             ret = wc_Sha224Update(&hmac->hash.sha224, msg, length);
00546             break;
00547     #endif /* WOLFSSL_SHA224 */
00548 
00549     #ifndef NO_SHA256
00550         case SHA256:
00551             ret = wc_Sha256Update(&hmac->hash.sha256, msg, length);
00552             break;
00553     #endif /* !NO_SHA256 */
00554 
00555     #ifdef WOLFSSL_SHA512
00556     #ifdef WOLFSSL_SHA384
00557         case SHA384:
00558             ret = wc_Sha384Update(&hmac->hash.sha384, msg, length);
00559             break;
00560     #endif /* WOLFSSL_SHA384 */
00561         case SHA512:
00562             ret = wc_Sha512Update(&hmac->hash.sha512, msg, length);
00563             break;
00564     #endif /* WOLFSSL_SHA512 */
00565 
00566     #ifdef HAVE_BLAKE2
00567         case BLAKE2B_ID:
00568             ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length);
00569             break;
00570     #endif /* HAVE_BLAKE2 */
00571 
00572         default:
00573             break;
00574     }
00575 
00576     return ret;
00577 }
00578 
00579 
00580 int wc_HmacFinal(Hmac* hmac, byte* hash)
00581 {
00582     int ret;
00583 
00584 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
00585     if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
00586         int hashLen = wc_HmacSizeByType(hmac->macType);
00587         if (hashLen <= 0)
00588             return hashLen;
00589 
00590     #if defined(HAVE_CAVIUM)
00591         return NitroxHmacFinal(hmac, hmac->macType, hash, hashLen);
00592     #elif defined(HAVE_INTEL_QA)
00593         return IntelQaHmac(&hmac->asyncDev, hmac->macType,
00594             hmac->keyRaw, hmac->keyLen, hash, NULL, hashLen);
00595     #endif
00596     }
00597 #endif /* WOLFSSL_ASYNC_CRYPT */
00598 
00599     if (!hmac->innerHashKeyed) {
00600         ret = HmacKeyInnerHash(hmac);
00601         if (ret != 0)
00602             return ret;
00603     }
00604 
00605     switch (hmac->macType) {
00606     #ifndef NO_MD5
00607         case MD5:
00608             ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash);
00609             if (ret != 0)
00610                 break;
00611             ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad,
00612                                                                 MD5_BLOCK_SIZE);
00613             if (ret != 0)
00614                 break;
00615             ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash,
00616                                                                MD5_DIGEST_SIZE);
00617             if (ret != 0)
00618                 break;
00619             ret = wc_Md5Final(&hmac->hash.md5, hash);
00620             break;
00621     #endif /* !NO_MD5 */
00622 
00623     #ifndef NO_SHA
00624         case SHA:
00625             ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash);
00626             if (ret != 0)
00627                 break;
00628             ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad,
00629                                                                 SHA_BLOCK_SIZE);
00630             if (ret != 0)
00631                 break;
00632             ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash,
00633                                                                SHA_DIGEST_SIZE);
00634             if (ret != 0)
00635                 break;
00636             ret = wc_ShaFinal(&hmac->hash.sha, hash);
00637             break;
00638     #endif /* !NO_SHA */
00639 
00640     #ifdef WOLFSSL_SHA224
00641         case SHA224:
00642         {
00643             ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash);
00644             if (ret != 0)
00645                 break;
00646             ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad,
00647                                                              SHA224_BLOCK_SIZE);
00648             if (ret != 0)
00649                 break;
00650             ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash,
00651                                                             SHA224_DIGEST_SIZE);
00652             if (ret != 0)
00653                 break;
00654             ret = wc_Sha224Final(&hmac->hash.sha224, hash);
00655             if (ret != 0)
00656                 break;
00657         }
00658         break;
00659     #endif /* WOLFSSL_SHA224 */
00660 
00661     #ifndef NO_SHA256
00662         case SHA256:
00663             ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash);
00664             if (ret != 0)
00665                 break;
00666             ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad,
00667                                                              SHA256_BLOCK_SIZE);
00668             if (ret != 0)
00669                 break;
00670             ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash,
00671                                                             SHA256_DIGEST_SIZE);
00672             if (ret != 0)
00673                 break;
00674             ret = wc_Sha256Final(&hmac->hash.sha256, hash);
00675             break;
00676     #endif /* !NO_SHA256 */
00677 
00678     #ifdef WOLFSSL_SHA512
00679     #ifdef WOLFSSL_SHA384
00680         case SHA384:
00681             ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash);
00682             if (ret != 0)
00683                 break;
00684             ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad,
00685                                                              SHA384_BLOCK_SIZE);
00686             if (ret != 0)
00687                 break;
00688             ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash,
00689                                                             SHA384_DIGEST_SIZE);
00690             if (ret != 0)
00691                 break;
00692             ret = wc_Sha384Final(&hmac->hash.sha384, hash);
00693             break;
00694     #endif /* WOLFSSL_SHA384 */
00695         case SHA512:
00696             ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash);
00697             if (ret != 0)
00698                 break;
00699             ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad,
00700                                                              SHA512_BLOCK_SIZE);
00701             if (ret != 0)
00702                 break;
00703             ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash,
00704                                                             SHA512_DIGEST_SIZE);
00705             if (ret != 0)
00706                 break;
00707             ret = wc_Sha512Final(&hmac->hash.sha512, hash);
00708             break;
00709     #endif /* WOLFSSL_SHA512 */
00710 
00711     #ifdef HAVE_BLAKE2
00712         case BLAKE2B_ID:
00713             ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash,
00714                                                                    BLAKE2B_256);
00715             if (ret != 0)
00716                 break;
00717             ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad,
00718                                                             BLAKE2B_BLOCKBYTES);
00719             if (ret != 0)
00720                 break;
00721             ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash,
00722                                                                    BLAKE2B_256);
00723             if (ret != 0)
00724                 break;
00725             ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256);
00726             break;
00727     #endif /* HAVE_BLAKE2 */
00728 
00729         default:
00730             ret = BAD_FUNC_ARG;
00731             break;
00732     }
00733 
00734     if (ret == 0) {
00735         hmac->innerHashKeyed = 0;
00736     }
00737 
00738     return ret;
00739 }
00740 
00741 
00742 /* Initialize Hmac for use with async device */
00743 int wc_HmacInit(Hmac* hmac, void* heap, int devId)
00744 {
00745     int ret = 0;
00746 
00747     if (hmac == NULL)
00748         return BAD_FUNC_ARG;
00749 
00750     XMEMSET(hmac, 0, sizeof(Hmac));
00751     hmac->heap = heap;
00752 
00753 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
00754     hmac->keyLen = 0;
00755     #ifdef HAVE_CAVIUM
00756         hmac->dataLen = 0;
00757         hmac->data    = NULL;        /* buffered input data */
00758     #endif /* HAVE_CAVIUM */
00759 
00760     ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC,
00761                                                          hmac->heap, devId);
00762 #else
00763     (void)devId;
00764 #endif /* WOLFSSL_ASYNC_CRYPT */
00765 
00766     return ret;
00767 }
00768 
00769 /* Free Hmac from use with async device */
00770 void wc_HmacFree(Hmac* hmac)
00771 {
00772     if (hmac == NULL)
00773         return;
00774 
00775 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
00776     wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC);
00777 
00778 #ifdef HAVE_CAVIUM
00779     XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_HMAC);
00780     hmac->data = NULL;
00781 #endif /* HAVE_CAVIUM */
00782 #endif /* WOLFSSL_ASYNC_CRYPT */
00783 }
00784 
00785 int wolfSSL_GetHmacMaxSize(void)
00786 {
00787     return MAX_DIGEST_SIZE;
00788 }
00789 
00790 #ifdef HAVE_HKDF
00791     /* HMAC-KDF-Extract.
00792      * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
00793      *
00794      * type     The hash algorithm type.
00795      * salt     The optional salt value.
00796      * saltSz   The size of the salt.
00797      * inKey    The input keying material.
00798      * inKeySz  The size of the input keying material.
00799      * out      The pseudorandom key with the length that of the hash.
00800      * returns 0 on success, otherwise failure.
00801      */
00802     int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz,
00803                         const byte* inKey, word32 inKeySz, byte* out)
00804     {
00805         byte   tmp[MAX_DIGEST_SIZE]; /* localSalt helper */
00806         Hmac   myHmac;
00807         int    ret;
00808         const  byte* localSalt;  /* either points to user input or tmp */
00809         int    hashSz = wc_HmacSizeByType(type);
00810 
00811         localSalt = salt;
00812         if (localSalt == NULL) {
00813             XMEMSET(tmp, 0, hashSz);
00814             localSalt = tmp;
00815             saltSz    = hashSz;
00816         }
00817 
00818         ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz);
00819         if (ret == 0)
00820             ret = wc_HmacUpdate(&myHmac, inKey, inKeySz);
00821         if (ret == 0)
00822             ret = wc_HmacFinal(&myHmac,  out);
00823 
00824         return ret;
00825     }
00826 
00827     /* HMAC-KDF-Expand.
00828      * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
00829      *
00830      * type     The hash algorithm type.
00831      * inKey    The input key.
00832      * inKeySz  The size of the input key.
00833      * info     The application specific information.
00834      * infoSz   The size of the application specific information.
00835      * out      The output keying material.
00836      * returns 0 on success, otherwise failure.
00837      */
00838     int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz,
00839                        const byte* info, word32 infoSz, byte* out, word32 outSz)
00840     {
00841         byte   tmp[MAX_DIGEST_SIZE];
00842         Hmac   myHmac;
00843         int    ret = 0;
00844         word32 outIdx = 0;
00845         word32 hashSz = wc_HmacSizeByType(type);
00846         byte   n = 0x1;
00847 
00848         while (outIdx < outSz) {
00849             int    tmpSz = (n == 1) ? 0 : hashSz;
00850             word32 left = outSz - outIdx;
00851 
00852             ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz);
00853             if (ret != 0)
00854                 break;
00855             ret = wc_HmacUpdate(&myHmac, tmp, tmpSz);
00856             if (ret != 0)
00857                 break;
00858             ret = wc_HmacUpdate(&myHmac, info, infoSz);
00859             if (ret != 0)
00860                 break;
00861             ret = wc_HmacUpdate(&myHmac, &n, 1);
00862             if (ret != 0)
00863                 break;
00864             ret = wc_HmacFinal(&myHmac, tmp);
00865             if (ret != 0)
00866                 break;
00867 
00868             left = min(left, hashSz);
00869             XMEMCPY(out+outIdx, tmp, left);
00870 
00871             outIdx += hashSz;
00872             n++;
00873         }
00874 
00875         return ret;
00876     }
00877 
00878     /* HMAC-KDF.
00879      * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
00880      *
00881      * type     The hash algorithm type.
00882      * inKey    The input keying material.
00883      * inKeySz  The size of the input keying material.
00884      * salt     The optional salt value.
00885      * saltSz   The size of the salt.
00886      * info     The application specific information.
00887      * infoSz   The size of the application specific information.
00888      * out      The output keying material.
00889      * returns 0 on success, otherwise failure.
00890      */
00891     int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
00892                        const byte* salt,  word32 saltSz,
00893                        const byte* info,  word32 infoSz,
00894                        byte* out,         word32 outSz)
00895     {
00896         byte   prk[MAX_DIGEST_SIZE];
00897         int    hashSz = wc_HmacSizeByType(type);
00898         int    ret;
00899 
00900         if (hashSz < 0)
00901             return BAD_FUNC_ARG;
00902 
00903         ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk);
00904         if (ret != 0)
00905             return ret;
00906 
00907         return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz);
00908     }
00909 
00910 #endif /* HAVE_HKDF */
00911 
00912 #endif /* HAVE_FIPS */
00913 #endif /* NO_HMAC */
00914