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.c 00002 * 00003 * Copyright (C) 2006-2013 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL 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 * CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ctaocrypt/settings.h> 00027 00028 #ifndef NO_HMAC 00029 00030 #ifdef CYASSL_PIC32MZ_HASH 00031 00032 #define InitMd5 InitMd5_sw 00033 #define Md5Update Md5Update_sw 00034 #define Md5Final Md5Final_sw 00035 00036 #define InitSha InitSha_sw 00037 #define ShaUpdate ShaUpdate_sw 00038 #define ShaFinal ShaFinal_sw 00039 00040 #define InitSha256 InitSha256_sw 00041 #define Sha256Update Sha256Update_sw 00042 #define Sha256Final Sha256Final_sw 00043 00044 #endif 00045 00046 #ifdef HAVE_FIPS 00047 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ 00048 #define FIPS_NO_WRAPPERS 00049 #endif 00050 00051 #include <cyassl/ctaocrypt/hmac.h> 00052 #include <cyassl/ctaocrypt/error-crypt.h> 00053 00054 00055 #ifdef HAVE_CAVIUM 00056 static void HmacCaviumFinal(Hmac* hmac, byte* hash); 00057 static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length); 00058 static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, 00059 word32 length); 00060 #endif 00061 00062 static int InitHmac(Hmac* hmac, int type) 00063 { 00064 int ret = 0; 00065 00066 hmac->innerHashKeyed = 0; 00067 hmac->macType = (byte)type; 00068 00069 if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 00070 || type == SHA512 || type == BLAKE2B_ID)) 00071 return BAD_FUNC_ARG; 00072 00073 switch (type) { 00074 #ifndef NO_MD5 00075 case MD5: 00076 InitMd5(&hmac->hash.md5); 00077 break; 00078 #endif 00079 00080 #ifndef NO_SHA 00081 case SHA: 00082 ret = InitSha(&hmac->hash.sha); 00083 break; 00084 #endif 00085 00086 #ifndef NO_SHA256 00087 case SHA256: 00088 ret = InitSha256(&hmac->hash.sha256); 00089 break; 00090 #endif 00091 00092 #ifdef CYASSL_SHA384 00093 case SHA384: 00094 ret = InitSha384(&hmac->hash.sha384); 00095 break; 00096 #endif 00097 00098 #ifdef CYASSL_SHA512 00099 case SHA512: 00100 ret = InitSha512(&hmac->hash.sha512); 00101 break; 00102 #endif 00103 00104 #ifdef HAVE_BLAKE2 00105 case BLAKE2B_ID: 00106 InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); 00107 break; 00108 #endif 00109 00110 default: 00111 return BAD_FUNC_ARG; 00112 } 00113 00114 return ret; 00115 } 00116 00117 00118 int HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) 00119 { 00120 byte* ip = (byte*) hmac->ipad; 00121 byte* op = (byte*) hmac->opad; 00122 word32 i, hmac_block_size = 0; 00123 int ret; 00124 00125 #ifdef HAVE_CAVIUM 00126 if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC) 00127 return HmacCaviumSetKey(hmac, type, key, length); 00128 #endif 00129 00130 ret = InitHmac(hmac, type); 00131 if (ret != 0) 00132 return ret; 00133 00134 switch (hmac->macType) { 00135 #ifndef NO_MD5 00136 case MD5: 00137 { 00138 hmac_block_size = MD5_BLOCK_SIZE; 00139 if (length <= MD5_BLOCK_SIZE) { 00140 XMEMCPY(ip, key, length); 00141 } 00142 else { 00143 Md5Update(&hmac->hash.md5, key, length); 00144 Md5Final(&hmac->hash.md5, ip); 00145 length = MD5_DIGEST_SIZE; 00146 } 00147 } 00148 break; 00149 #endif 00150 00151 #ifndef NO_SHA 00152 case SHA: 00153 { 00154 hmac_block_size = SHA_BLOCK_SIZE; 00155 if (length <= SHA_BLOCK_SIZE) { 00156 XMEMCPY(ip, key, length); 00157 } 00158 else { 00159 ShaUpdate(&hmac->hash.sha, key, length); 00160 ShaFinal(&hmac->hash.sha, ip); 00161 length = SHA_DIGEST_SIZE; 00162 } 00163 } 00164 break; 00165 #endif 00166 00167 #ifndef NO_SHA256 00168 case SHA256: 00169 { 00170 hmac_block_size = SHA256_BLOCK_SIZE; 00171 if (length <= SHA256_BLOCK_SIZE) { 00172 XMEMCPY(ip, key, length); 00173 } 00174 else { 00175 Sha256Update(&hmac->hash.sha256, key, length); 00176 Sha256Final(&hmac->hash.sha256, ip); 00177 length = SHA256_DIGEST_SIZE; 00178 } 00179 } 00180 break; 00181 #endif 00182 00183 #ifdef CYASSL_SHA384 00184 case SHA384: 00185 { 00186 hmac_block_size = SHA384_BLOCK_SIZE; 00187 if (length <= SHA384_BLOCK_SIZE) { 00188 XMEMCPY(ip, key, length); 00189 } 00190 else { 00191 Sha384Update(&hmac->hash.sha384, key, length); 00192 Sha384Final(&hmac->hash.sha384, ip); 00193 length = SHA384_DIGEST_SIZE; 00194 } 00195 } 00196 break; 00197 #endif 00198 00199 #ifdef CYASSL_SHA512 00200 case SHA512: 00201 { 00202 hmac_block_size = SHA512_BLOCK_SIZE; 00203 if (length <= SHA512_BLOCK_SIZE) { 00204 XMEMCPY(ip, key, length); 00205 } 00206 else { 00207 Sha512Update(&hmac->hash.sha512, key, length); 00208 Sha512Final(&hmac->hash.sha512, ip); 00209 length = SHA512_DIGEST_SIZE; 00210 } 00211 } 00212 break; 00213 #endif 00214 00215 #ifdef HAVE_BLAKE2 00216 case BLAKE2B_ID: 00217 { 00218 hmac_block_size = BLAKE2B_BLOCKBYTES; 00219 if (length <= BLAKE2B_BLOCKBYTES) { 00220 XMEMCPY(ip, key, length); 00221 } 00222 else { 00223 Blake2bUpdate(&hmac->hash.blake2b, key, length); 00224 Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); 00225 length = BLAKE2B_256; 00226 } 00227 } 00228 break; 00229 #endif 00230 00231 default: 00232 return BAD_FUNC_ARG; 00233 } 00234 if (length < hmac_block_size) 00235 XMEMSET(ip + length, 0, hmac_block_size - length); 00236 00237 for(i = 0; i < hmac_block_size; i++) { 00238 op[i] = ip[i] ^ OPAD; 00239 ip[i] ^= IPAD; 00240 } 00241 return 0; 00242 } 00243 00244 00245 static void HmacKeyInnerHash(Hmac* hmac) 00246 { 00247 switch (hmac->macType) { 00248 #ifndef NO_MD5 00249 case MD5: 00250 Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); 00251 break; 00252 #endif 00253 00254 #ifndef NO_SHA 00255 case SHA: 00256 ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); 00257 break; 00258 #endif 00259 00260 #ifndef NO_SHA256 00261 case SHA256: 00262 Sha256Update(&hmac->hash.sha256, 00263 (byte*) hmac->ipad, SHA256_BLOCK_SIZE); 00264 break; 00265 #endif 00266 00267 #ifdef CYASSL_SHA384 00268 case SHA384: 00269 Sha384Update(&hmac->hash.sha384, 00270 (byte*) hmac->ipad, SHA384_BLOCK_SIZE); 00271 break; 00272 #endif 00273 00274 #ifdef CYASSL_SHA512 00275 case SHA512: 00276 Sha512Update(&hmac->hash.sha512, 00277 (byte*) hmac->ipad, SHA512_BLOCK_SIZE); 00278 break; 00279 #endif 00280 00281 #ifdef HAVE_BLAKE2 00282 case BLAKE2B_ID: 00283 Blake2bUpdate(&hmac->hash.blake2b, 00284 (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); 00285 break; 00286 #endif 00287 00288 default: 00289 break; 00290 } 00291 00292 hmac->innerHashKeyed = 1; 00293 } 00294 00295 00296 int HmacUpdate(Hmac* hmac, const byte* msg, word32 length) 00297 { 00298 #ifdef HAVE_CAVIUM 00299 if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC) 00300 return HmacCaviumUpdate(hmac, msg, length); 00301 #endif 00302 00303 if (!hmac->innerHashKeyed) 00304 HmacKeyInnerHash(hmac); 00305 00306 switch (hmac->macType) { 00307 #ifndef NO_MD5 00308 case MD5: 00309 Md5Update(&hmac->hash.md5, msg, length); 00310 break; 00311 #endif 00312 00313 #ifndef NO_SHA 00314 case SHA: 00315 ShaUpdate(&hmac->hash.sha, msg, length); 00316 break; 00317 #endif 00318 00319 #ifndef NO_SHA256 00320 case SHA256: 00321 Sha256Update(&hmac->hash.sha256, msg, length); 00322 break; 00323 #endif 00324 00325 #ifdef CYASSL_SHA384 00326 case SHA384: 00327 Sha384Update(&hmac->hash.sha384, msg, length); 00328 break; 00329 #endif 00330 00331 #ifdef CYASSL_SHA512 00332 case SHA512: 00333 Sha512Update(&hmac->hash.sha512, msg, length); 00334 break; 00335 #endif 00336 00337 #ifdef HAVE_BLAKE2 00338 case BLAKE2B_ID: 00339 Blake2bUpdate(&hmac->hash.blake2b, msg, length); 00340 break; 00341 #endif 00342 00343 default: 00344 break; 00345 } 00346 00347 return 0; 00348 } 00349 00350 00351 int HmacFinal(Hmac* hmac, byte* hash) 00352 { 00353 #ifdef HAVE_CAVIUM 00354 if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC) 00355 return HmacCaviumFinal(hmac, hash); 00356 #endif 00357 00358 if (!hmac->innerHashKeyed) 00359 HmacKeyInnerHash(hmac); 00360 00361 switch (hmac->macType) { 00362 #ifndef NO_MD5 00363 case MD5: 00364 { 00365 Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); 00366 00367 Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); 00368 Md5Update(&hmac->hash.md5, 00369 (byte*) hmac->innerHash, MD5_DIGEST_SIZE); 00370 00371 Md5Final(&hmac->hash.md5, hash); 00372 } 00373 break; 00374 #endif 00375 00376 #ifndef NO_SHA 00377 case SHA: 00378 { 00379 ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); 00380 00381 ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); 00382 ShaUpdate(&hmac->hash.sha, 00383 (byte*) hmac->innerHash, SHA_DIGEST_SIZE); 00384 00385 ShaFinal(&hmac->hash.sha, hash); 00386 } 00387 break; 00388 #endif 00389 00390 #ifndef NO_SHA256 00391 case SHA256: 00392 { 00393 Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); 00394 00395 Sha256Update(&hmac->hash.sha256, 00396 (byte*) hmac->opad, SHA256_BLOCK_SIZE); 00397 Sha256Update(&hmac->hash.sha256, 00398 (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); 00399 00400 Sha256Final(&hmac->hash.sha256, hash); 00401 } 00402 break; 00403 #endif 00404 00405 #ifdef CYASSL_SHA384 00406 case SHA384: 00407 { 00408 Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); 00409 00410 Sha384Update(&hmac->hash.sha384, 00411 (byte*) hmac->opad, SHA384_BLOCK_SIZE); 00412 Sha384Update(&hmac->hash.sha384, 00413 (byte*) hmac->innerHash, SHA384_DIGEST_SIZE); 00414 00415 Sha384Final(&hmac->hash.sha384, hash); 00416 } 00417 break; 00418 #endif 00419 00420 #ifdef CYASSL_SHA512 00421 case SHA512: 00422 { 00423 Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash); 00424 00425 Sha512Update(&hmac->hash.sha512, 00426 (byte*) hmac->opad, SHA512_BLOCK_SIZE); 00427 Sha512Update(&hmac->hash.sha512, 00428 (byte*) hmac->innerHash, SHA512_DIGEST_SIZE); 00429 00430 Sha512Final(&hmac->hash.sha512, hash); 00431 } 00432 break; 00433 #endif 00434 00435 #ifdef HAVE_BLAKE2 00436 case BLAKE2B_ID: 00437 { 00438 Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, 00439 BLAKE2B_256); 00440 Blake2bUpdate(&hmac->hash.blake2b, 00441 (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); 00442 Blake2bUpdate(&hmac->hash.blake2b, 00443 (byte*) hmac->innerHash, BLAKE2B_256); 00444 Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); 00445 } 00446 break; 00447 #endif 00448 00449 default: 00450 break; 00451 } 00452 00453 hmac->innerHashKeyed = 0; 00454 00455 return 0; 00456 } 00457 00458 00459 #ifdef HAVE_CAVIUM 00460 00461 /* Initiliaze Hmac for use with Nitrox device */ 00462 int HmacInitCavium(Hmac* hmac, int devId) 00463 { 00464 if (hmac == NULL) 00465 return -1; 00466 00467 if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0) 00468 return -1; 00469 00470 hmac->keyLen = 0; 00471 hmac->dataLen = 0; 00472 hmac->type = 0; 00473 hmac->devId = devId; 00474 hmac->magic = CYASSL_HMAC_CAVIUM_MAGIC; 00475 hmac->data = NULL; /* buffered input data */ 00476 00477 hmac->innerHashKeyed = 0; 00478 00479 return 0; 00480 } 00481 00482 00483 /* Free Hmac from use with Nitrox device */ 00484 void HmacFreeCavium(Hmac* hmac) 00485 { 00486 if (hmac == NULL) 00487 return; 00488 00489 CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId); 00490 hmac->magic = 0; 00491 XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); 00492 hmac->data = NULL; 00493 } 00494 00495 00496 static void HmacCaviumFinal(Hmac* hmac, byte* hash) 00497 { 00498 word32 requestId; 00499 00500 if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, 00501 (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId, 00502 hmac->devId) != 0) { 00503 CYASSL_MSG("Cavium Hmac failed"); 00504 } 00505 hmac->innerHashKeyed = 0; /* tell update to start over if used again */ 00506 } 00507 00508 00509 static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length) 00510 { 00511 word16 add = (word16)length; 00512 word32 total; 00513 byte* tmp; 00514 00515 if (length > CYASSL_MAX_16BIT) { 00516 CYASSL_MSG("Too big msg for cavium hmac"); 00517 return; 00518 } 00519 00520 if (hmac->innerHashKeyed == 0) { /* starting new */ 00521 hmac->dataLen = 0; 00522 hmac->innerHashKeyed = 1; 00523 } 00524 00525 total = add + hmac->dataLen; 00526 if (total > CYASSL_MAX_16BIT) { 00527 CYASSL_MSG("Too big msg for cavium hmac"); 00528 return; 00529 } 00530 00531 tmp = XMALLOC(hmac->dataLen + add, NULL,DYNAMIC_TYPE_CAVIUM_TMP); 00532 if (tmp == NULL) { 00533 CYASSL_MSG("Out of memory for cavium update"); 00534 return; 00535 } 00536 if (hmac->dataLen) 00537 XMEMCPY(tmp, hmac->data, hmac->dataLen); 00538 XMEMCPY(tmp + hmac->dataLen, msg, add); 00539 00540 hmac->dataLen += add; 00541 XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); 00542 hmac->data = tmp; 00543 } 00544 00545 00546 static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, 00547 word32 length) 00548 { 00549 hmac->macType = (byte)type; 00550 if (type == MD5) 00551 hmac->type = MD5_TYPE; 00552 else if (type == SHA) 00553 hmac->type = SHA1_TYPE; 00554 else if (type == SHA256) 00555 hmac->type = SHA256_TYPE; 00556 else { 00557 CYASSL_MSG("unsupported cavium hmac type"); 00558 } 00559 00560 hmac->innerHashKeyed = 0; /* should we key Startup flag */ 00561 00562 hmac->keyLen = (word16)length; 00563 /* store key in ipad */ 00564 XMEMCPY(hmac->ipad, key, length); 00565 } 00566 00567 #endif /* HAVE_CAVIUM */ 00568 00569 int CyaSSL_GetHmacMaxSize(void) 00570 { 00571 return MAX_DIGEST_SIZE; 00572 } 00573 00574 #ifdef HAVE_HKDF 00575 00576 #ifndef min 00577 00578 static INLINE word32 min(word32 a, word32 b) 00579 { 00580 return a > b ? b : a; 00581 } 00582 00583 #endif /* min */ 00584 00585 00586 static INLINE int GetHashSizeByType(int type) 00587 { 00588 if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 00589 || type == SHA512 || type == BLAKE2B_ID)) 00590 return BAD_FUNC_ARG; 00591 00592 switch (type) { 00593 #ifndef NO_MD5 00594 case MD5: 00595 return MD5_DIGEST_SIZE; 00596 break; 00597 #endif 00598 00599 #ifndef NO_SHA 00600 case SHA: 00601 return SHA_DIGEST_SIZE; 00602 break; 00603 #endif 00604 00605 #ifndef NO_SHA256 00606 case SHA256: 00607 return SHA256_DIGEST_SIZE; 00608 break; 00609 #endif 00610 00611 #ifdef CYASSL_SHA384 00612 case SHA384: 00613 return SHA384_DIGEST_SIZE; 00614 break; 00615 #endif 00616 00617 #ifdef CYASSL_SHA512 00618 case SHA512: 00619 return SHA512_DIGEST_SIZE; 00620 break; 00621 #endif 00622 00623 #ifdef HAVE_BLAKE2 00624 case BLAKE2B_ID: 00625 return BLAKE2B_OUTBYTES; 00626 break; 00627 #endif 00628 00629 default: 00630 return BAD_FUNC_ARG; 00631 break; 00632 } 00633 } 00634 00635 00636 /* HMAC-KDF with hash type, optional salt and info, return 0 on success */ 00637 int HKDF(int type, const byte* inKey, word32 inKeySz, 00638 const byte* salt, word32 saltSz, 00639 const byte* info, word32 infoSz, 00640 byte* out, word32 outSz) 00641 { 00642 Hmac myHmac; 00643 byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ 00644 byte prk[MAX_DIGEST_SIZE]; 00645 const byte* localSalt; /* either points to user input or tmp */ 00646 int hashSz = GetHashSizeByType(type); 00647 word32 outIdx = 0; 00648 byte n = 0x1; 00649 00650 if (hashSz < 0) 00651 return BAD_FUNC_ARG; 00652 00653 localSalt = salt; 00654 if (localSalt == NULL) { 00655 XMEMSET(tmp, 0, hashSz); 00656 localSalt = tmp; 00657 saltSz = hashSz; 00658 } 00659 00660 if (HmacSetKey(&myHmac, type, localSalt, saltSz) != 0) 00661 return BAD_FUNC_ARG; 00662 00663 HmacUpdate(&myHmac, inKey, inKeySz); 00664 HmacFinal(&myHmac, prk); 00665 00666 while (outIdx < outSz) { 00667 int tmpSz = (n == 1) ? 0 : hashSz; 00668 word32 left = outSz - outIdx; 00669 00670 if (HmacSetKey(&myHmac, type, prk, hashSz) != 0) 00671 return BAD_FUNC_ARG; 00672 00673 HmacUpdate(&myHmac, tmp, tmpSz); 00674 HmacUpdate(&myHmac, info, infoSz); 00675 HmacUpdate(&myHmac, &n, 1); 00676 HmacFinal(&myHmac, tmp); 00677 00678 left = min(left, (word32)hashSz); 00679 XMEMCPY(out+outIdx, tmp, left); 00680 00681 outIdx += hashSz; 00682 n++; 00683 } 00684 00685 return 0; 00686 } 00687 00688 #endif /* HAVE_HKDF */ 00689 00690 #endif /* NO_HMAC */ 00691
Generated on Tue Jul 12 2022 20:12:50 by
