This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

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 #include <cyassl/ctaocrypt/hmac.h>
00031 #include <cyassl/ctaocrypt/ctaoerror2.h>
00032 
00033 
00034 #ifdef HAVE_CAVIUM
00035     static void HmacCaviumFinal(Hmac* hmac, byte* hash);
00036     static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length);
00037     static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key,
00038                                  word32 length);
00039 #endif
00040 
00041 static int InitHmac(Hmac* hmac, int type)
00042 {
00043     hmac->innerHashKeyed = 0;
00044     hmac->macType = (byte)type;
00045 
00046     if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384
00047                       || type == SHA512))
00048         return BAD_FUNC_ARG;
00049 
00050     switch (type) {
00051         #ifndef NO_MD5
00052         case MD5:
00053             InitMd5(&hmac->hash.md5);
00054         break;
00055         #endif
00056 
00057         #ifndef NO_SHA
00058         case SHA:
00059             InitSha(&hmac->hash.sha);
00060         break;
00061         #endif
00062         
00063         #ifndef NO_SHA256
00064         case SHA256:
00065             InitSha256(&hmac->hash.sha256);
00066         break;
00067         #endif
00068         
00069         #ifdef CYASSL_SHA384
00070         case SHA384:
00071             InitSha384(&hmac->hash.sha384);
00072         break;
00073         #endif
00074         
00075         #ifdef CYASSL_SHA512
00076         case SHA512:
00077             InitSha512(&hmac->hash.sha512);
00078         break;
00079         #endif
00080         
00081         default:
00082         break;
00083     }
00084 
00085     return 0;
00086 }
00087 
00088 
00089 void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
00090 {
00091     byte*  ip = (byte*) hmac->ipad;
00092     byte*  op = (byte*) hmac->opad;
00093     word32 i, hmac_block_size = 0;
00094 
00095 #ifdef HAVE_CAVIUM
00096     if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC)
00097         return HmacCaviumSetKey(hmac, type, key, length);
00098 #endif
00099 
00100     InitHmac(hmac, type);
00101 
00102     switch (hmac->macType) {
00103         #ifndef NO_MD5
00104         case MD5:
00105         {
00106             hmac_block_size = MD5_BLOCK_SIZE;
00107             if (length <= MD5_BLOCK_SIZE) {
00108                 XMEMCPY(ip, key, length);
00109             }
00110             else {
00111                 Md5Update(&hmac->hash.md5, key, length);
00112                 Md5Final(&hmac->hash.md5, ip);
00113                 length = MD5_DIGEST_SIZE;
00114             }
00115         }
00116         break;
00117         #endif
00118 
00119         #ifndef NO_SHA
00120         case SHA:
00121         {
00122             hmac_block_size = SHA_BLOCK_SIZE;
00123             if (length <= SHA_BLOCK_SIZE) {
00124                 XMEMCPY(ip, key, length);
00125             }
00126             else {
00127                 ShaUpdate(&hmac->hash.sha, key, length);
00128                 ShaFinal(&hmac->hash.sha, ip);
00129                 length = SHA_DIGEST_SIZE;
00130             }
00131         }
00132         break;
00133         #endif
00134 
00135         #ifndef NO_SHA256
00136         case SHA256:
00137         {
00138             hmac_block_size = SHA256_BLOCK_SIZE;
00139             if (length <= SHA256_BLOCK_SIZE) {
00140                 XMEMCPY(ip, key, length);
00141             }
00142             else {
00143                 Sha256Update(&hmac->hash.sha256, key, length);
00144                 Sha256Final(&hmac->hash.sha256, ip);
00145                 length = SHA256_DIGEST_SIZE;
00146             }
00147         }
00148         break;
00149         #endif
00150 
00151         #ifdef CYASSL_SHA384
00152         case SHA384:
00153         {
00154             hmac_block_size = SHA384_BLOCK_SIZE;
00155             if (length <= SHA384_BLOCK_SIZE) {
00156                 XMEMCPY(ip, key, length);
00157             }
00158             else {
00159                 Sha384Update(&hmac->hash.sha384, key, length);
00160                 Sha384Final(&hmac->hash.sha384, ip);
00161                 length = SHA384_DIGEST_SIZE;
00162             }
00163         }
00164         break;
00165         #endif
00166 
00167         #ifdef CYASSL_SHA512
00168         case SHA512:
00169         {
00170             hmac_block_size = SHA512_BLOCK_SIZE;
00171             if (length <= SHA512_BLOCK_SIZE) {
00172                 XMEMCPY(ip, key, length);
00173             }
00174             else {
00175                 Sha512Update(&hmac->hash.sha512, key, length);
00176                 Sha512Final(&hmac->hash.sha512, ip);
00177                 length = SHA512_DIGEST_SIZE;
00178             }
00179         }
00180         break;
00181         #endif
00182 
00183         default:
00184         break;
00185     }
00186     if (length < hmac_block_size)
00187         XMEMSET(ip + length, 0, hmac_block_size - length);
00188 
00189     for(i = 0; i < hmac_block_size; i++) {
00190         op[i] = ip[i] ^ OPAD;
00191         ip[i] ^= IPAD;
00192     }
00193 }
00194 
00195 
00196 static void HmacKeyInnerHash(Hmac* hmac)
00197 {
00198     switch (hmac->macType) {
00199         #ifndef NO_MD5
00200         case MD5:
00201             Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE);
00202         break;
00203         #endif
00204 
00205         #ifndef NO_SHA
00206         case SHA:
00207             ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE);
00208         break;
00209         #endif
00210 
00211         #ifndef NO_SHA256
00212         case SHA256:
00213             Sha256Update(&hmac->hash.sha256,
00214                                          (byte*) hmac->ipad, SHA256_BLOCK_SIZE);
00215         break;
00216         #endif
00217 
00218         #ifdef CYASSL_SHA384
00219         case SHA384:
00220             Sha384Update(&hmac->hash.sha384,
00221                                          (byte*) hmac->ipad, SHA384_BLOCK_SIZE);
00222         break;
00223         #endif
00224 
00225         #ifdef CYASSL_SHA512
00226         case SHA512:
00227             Sha512Update(&hmac->hash.sha512,
00228                                          (byte*) hmac->ipad, SHA512_BLOCK_SIZE);
00229         break;
00230         #endif
00231 
00232         default:
00233         break;
00234     }
00235 
00236     hmac->innerHashKeyed = 1;
00237 }
00238 
00239 
00240 void HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
00241 {
00242 #ifdef HAVE_CAVIUM
00243     if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC)
00244         return HmacCaviumUpdate(hmac, msg, length);
00245 #endif
00246 
00247     if (!hmac->innerHashKeyed)
00248         HmacKeyInnerHash(hmac);
00249 
00250     switch (hmac->macType) {
00251         #ifndef NO_MD5
00252         case MD5:
00253             Md5Update(&hmac->hash.md5, msg, length);
00254         break;
00255         #endif
00256 
00257         #ifndef NO_SHA
00258         case SHA:
00259             ShaUpdate(&hmac->hash.sha, msg, length);
00260         break;
00261         #endif
00262 
00263         #ifndef NO_SHA256
00264         case SHA256:
00265             Sha256Update(&hmac->hash.sha256, msg, length);
00266         break;
00267         #endif
00268 
00269         #ifdef CYASSL_SHA384
00270         case SHA384:
00271             Sha384Update(&hmac->hash.sha384, msg, length);
00272         break;
00273         #endif
00274 
00275         #ifdef CYASSL_SHA512
00276         case SHA512:
00277             Sha512Update(&hmac->hash.sha512, msg, length);
00278         break;
00279         #endif
00280 
00281         default:
00282         break;
00283     }
00284 
00285 }
00286 
00287 
00288 void HmacFinal(Hmac* hmac, byte* hash)
00289 {
00290 #ifdef HAVE_CAVIUM
00291     if (hmac->magic == CYASSL_HMAC_CAVIUM_MAGIC)
00292         return HmacCaviumFinal(hmac, hash);
00293 #endif
00294 
00295     if (!hmac->innerHashKeyed)
00296         HmacKeyInnerHash(hmac);
00297 
00298     switch (hmac->macType) {
00299         #ifndef NO_MD5
00300         case MD5:
00301         {
00302             Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
00303 
00304             Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE);
00305             Md5Update(&hmac->hash.md5,
00306                                      (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
00307 
00308             Md5Final(&hmac->hash.md5, hash);
00309         }
00310         break;
00311         #endif
00312 
00313         #ifndef NO_SHA
00314         case SHA:
00315         {
00316             ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
00317 
00318             ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE);
00319             ShaUpdate(&hmac->hash.sha,
00320                                      (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
00321 
00322             ShaFinal(&hmac->hash.sha, hash);
00323         }
00324         break;
00325         #endif
00326 
00327         #ifndef NO_SHA256
00328         case SHA256:
00329         {
00330             Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
00331 
00332             Sha256Update(&hmac->hash.sha256,
00333                                 (byte*) hmac->opad, SHA256_BLOCK_SIZE);
00334             Sha256Update(&hmac->hash.sha256,
00335                                 (byte*) hmac->innerHash, SHA256_DIGEST_SIZE);
00336 
00337             Sha256Final(&hmac->hash.sha256, hash);
00338         }
00339         break;
00340         #endif
00341 
00342         #ifdef CYASSL_SHA384
00343         case SHA384:
00344         {
00345             Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash);
00346 
00347             Sha384Update(&hmac->hash.sha384,
00348                                  (byte*) hmac->opad, SHA384_BLOCK_SIZE);
00349             Sha384Update(&hmac->hash.sha384,
00350                                  (byte*) hmac->innerHash, SHA384_DIGEST_SIZE);
00351 
00352             Sha384Final(&hmac->hash.sha384, hash);
00353         }
00354         break;
00355         #endif
00356 
00357         #ifdef CYASSL_SHA512
00358         case SHA512:
00359         {
00360             Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash);
00361 
00362             Sha512Update(&hmac->hash.sha512,
00363                                  (byte*) hmac->opad, SHA512_BLOCK_SIZE);
00364             Sha512Update(&hmac->hash.sha512,
00365                                  (byte*) hmac->innerHash, SHA512_DIGEST_SIZE);
00366 
00367             Sha512Final(&hmac->hash.sha512, hash);
00368         }
00369         break;
00370         #endif
00371 
00372         default:
00373         break;
00374     }
00375 
00376     hmac->innerHashKeyed = 0;
00377 }
00378 
00379 
00380 #ifdef HAVE_CAVIUM
00381 
00382 /* Initiliaze Hmac for use with Nitrox device */
00383 int HmacInitCavium(Hmac* hmac, int devId)
00384 {
00385     if (hmac == NULL)
00386         return -1;
00387 
00388     if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0)
00389         return -1;
00390 
00391     hmac->keyLen  = 0;
00392     hmac->dataLen = 0;
00393     hmac->type    = 0;
00394     hmac->devId   = devId;
00395     hmac->magic   = CYASSL_HMAC_CAVIUM_MAGIC;
00396     hmac->data    = NULL;        /* buffered input data */
00397    
00398     hmac->innerHashKeyed = 0;
00399 
00400     return 0;
00401 }
00402 
00403 
00404 /* Free Hmac from use with Nitrox device */
00405 void HmacFreeCavium(Hmac* hmac)
00406 {
00407     if (hmac == NULL)
00408         return;
00409 
00410     CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId);
00411     hmac->magic = 0;
00412     XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP);
00413     hmac->data = NULL;
00414 }
00415 
00416 
00417 static void HmacCaviumFinal(Hmac* hmac, byte* hash)
00418 {
00419     word32 requestId;
00420 
00421     if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen,
00422                 (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId,
00423                 hmac->devId) != 0) {
00424         CYASSL_MSG("Cavium Hmac failed");
00425     } 
00426     hmac->innerHashKeyed = 0;  /* tell update to start over if used again */
00427 }
00428 
00429 
00430 static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length)
00431 {
00432     word16 add = (word16)length;
00433     word32 total;
00434     byte*  tmp;
00435 
00436     if (length > CYASSL_MAX_16BIT) {
00437         CYASSL_MSG("Too big msg for cavium hmac");
00438         return;
00439     }
00440 
00441     if (hmac->innerHashKeyed == 0) {  /* starting new */
00442         hmac->dataLen        = 0;
00443         hmac->innerHashKeyed = 1;
00444     }
00445 
00446     total = add + hmac->dataLen;
00447     if (total > CYASSL_MAX_16BIT) {
00448         CYASSL_MSG("Too big msg for cavium hmac");
00449         return;
00450     }
00451 
00452     tmp = XMALLOC(hmac->dataLen + add, NULL,DYNAMIC_TYPE_CAVIUM_TMP);
00453     if (tmp == NULL) {
00454         CYASSL_MSG("Out of memory for cavium update");
00455         return;
00456     }
00457     if (hmac->dataLen)
00458         XMEMCPY(tmp, hmac->data,  hmac->dataLen);
00459     XMEMCPY(tmp + hmac->dataLen, msg, add);
00460         
00461     hmac->dataLen += add;
00462     XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP);
00463     hmac->data = tmp;
00464 }
00465 
00466 
00467 static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key,
00468                              word32 length)
00469 {
00470     hmac->macType = (byte)type;
00471     if (type == MD5)
00472         hmac->type = MD5_TYPE;
00473     else if (type == SHA)
00474         hmac->type = SHA1_TYPE;
00475     else if (type == SHA256)
00476         hmac->type = SHA256_TYPE;
00477     else  {
00478         CYASSL_MSG("unsupported cavium hmac type");
00479     }
00480 
00481     hmac->innerHashKeyed = 0;  /* should we key Startup flag */
00482 
00483     hmac->keyLen = (word16)length;
00484     /* store key in ipad */
00485     XMEMCPY(hmac->ipad, key, length);
00486 }
00487 
00488 #endif /* HAVE_CAVIUM */
00489 
00490 #endif /* NO_HMAC */
00491