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