CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

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-2009 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 
00023 #ifndef NO_HMAC
00024 
00025 #include "ctc_hmac.h"
00026 
00027 
00028 
00029 static int InitHmac(Hmac* hmac, int type)
00030 {
00031     hmac->innerHashKeyed = 0;
00032     hmac->macType = type;
00033 
00034     if (!(type == MD5 || type == SHA || type == SHA256))
00035         return -1;
00036 
00037     if (type == MD5)
00038         InitMd5(&hmac->hash.md5);
00039     else if (type == SHA)
00040         InitSha(&hmac->hash.sha);
00041 #ifndef NO_SHA256
00042     else if (type == SHA256)
00043         InitSha256(&hmac->hash.sha256);
00044 #endif
00045 
00046     return 0;
00047 }
00048 
00049 
00050 void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
00051 {
00052     byte*  ip = (byte*) hmac->ipad;
00053     byte*  op = (byte*) hmac->opad;
00054     word32 i;
00055 
00056     InitHmac(hmac, type);
00057 
00058     if (length <= HMAC_BLOCK_SIZE)
00059         XMEMCPY(ip, key, length);
00060     else {
00061         if (hmac->macType == MD5) {
00062             Md5Update(&hmac->hash.md5, key, length);
00063             Md5Final(&hmac->hash.md5, ip);
00064             length = MD5_DIGEST_SIZE;
00065         }
00066         else if (hmac->macType == SHA) {
00067             ShaUpdate(&hmac->hash.sha, key, length);
00068             ShaFinal(&hmac->hash.sha, ip);
00069             length = SHA_DIGEST_SIZE;
00070         }
00071 #ifndef NO_SHA256
00072         else if (hmac->macType == SHA256) {
00073             Sha256Update(&hmac->hash.sha256, key, length);
00074             Sha256Final(&hmac->hash.sha256, ip);
00075             length = SHA256_DIGEST_SIZE;
00076         }
00077 #endif
00078     }
00079     XMEMSET(ip + length, 0, HMAC_BLOCK_SIZE - length);
00080 
00081     for(i = 0; i < HMAC_BLOCK_SIZE; i++) {
00082         op[i] = ip[i] ^ OPAD;
00083         ip[i] ^= IPAD;
00084     }
00085 }
00086 
00087 
00088 static void HmacKeyInnerHash(Hmac* hmac)
00089 {
00090     if (hmac->macType == MD5)
00091         Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
00092     else if (hmac->macType == SHA)
00093         ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
00094 #ifndef NO_SHA256
00095     else if (hmac->macType == SHA256)
00096         Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
00097 #endif
00098 
00099     hmac->innerHashKeyed = 1;
00100 }
00101 
00102 
00103 void HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
00104 {
00105     if (!hmac->innerHashKeyed)
00106         HmacKeyInnerHash(hmac);
00107 
00108     if (hmac->macType == MD5)
00109         Md5Update(&hmac->hash.md5, msg, length);
00110     else if (hmac->macType == SHA)
00111         ShaUpdate(&hmac->hash.sha, msg, length);
00112 #ifndef NO_SHA256
00113     else if (hmac->macType == SHA256)
00114         Sha256Update(&hmac->hash.sha256, msg, length);
00115 #endif
00116 
00117 }
00118 
00119 
00120 void HmacFinal(Hmac* hmac, byte* hash)
00121 {
00122     if (!hmac->innerHashKeyed)
00123         HmacKeyInnerHash(hmac);
00124 
00125     if (hmac->macType == MD5) {
00126         Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
00127 
00128         Md5Update(&hmac->hash.md5, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
00129         Md5Update(&hmac->hash.md5, (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
00130 
00131         Md5Final(&hmac->hash.md5, hash);
00132     }
00133     else if (hmac->macType ==SHA) {
00134         ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
00135 
00136         ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
00137         ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
00138 
00139         ShaFinal(&hmac->hash.sha, hash);
00140     }
00141 #ifndef NO_SHA256
00142     else if (hmac->macType ==SHA256) {
00143         Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
00144 
00145         Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
00146         Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash,
00147                      SHA256_DIGEST_SIZE);
00148 
00149         Sha256Final(&hmac->hash.sha256, hash);
00150     }
00151 #endif
00152 
00153     hmac->innerHashKeyed = 0;
00154 }
00155 
00156 
00157 #endif /* NO_HMAC */
00158