cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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