Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2