wolf SSL / CyaSSL-2.9.4

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac.c Source File

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