3 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28 #include <cyassl/ctaocrypt/hmac.h>
29 #include <cyassl/ctaocrypt/error.h>
32 static int InitHmac(Hmac* hmac, int type)
34 hmac->innerHashKeyed = 0;
35 hmac->macType = (byte)type;
37 if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384))
41 InitMd5(&hmac->hash.md5);
43 InitSha(&hmac->hash.sha);
45 else if (type == SHA256)
46 InitSha256(&hmac->hash.sha256);
49 else if (type == SHA384)
50 InitSha384(&hmac->hash.sha384);
57 void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
59 byte* ip = (byte*) hmac->ipad;
60 byte* op = (byte*) hmac->opad;
61 word32 i, hmac_block_size = MD5_BLOCK_SIZE;
65 if (hmac->macType == MD5) {
66 if (length <= MD5_BLOCK_SIZE) {
67 XMEMCPY(ip, key, length);
70 Md5Update(&hmac->hash.md5, key, length);
71 Md5Final(&hmac->hash.md5, ip);
72 length = MD5_DIGEST_SIZE;
75 else if (hmac->macType == SHA) {
76 hmac_block_size = SHA_BLOCK_SIZE;
77 if (length <= SHA_BLOCK_SIZE) {
78 XMEMCPY(ip, key, length);
81 ShaUpdate(&hmac->hash.sha, key, length);
82 ShaFinal(&hmac->hash.sha, ip);
83 length = SHA_DIGEST_SIZE;
87 else if (hmac->macType == SHA256) {
88 hmac_block_size = SHA256_BLOCK_SIZE;
89 if (length <= SHA256_BLOCK_SIZE) {
90 XMEMCPY(ip, key, length);
93 Sha256Update(&hmac->hash.sha256, key, length);
94 Sha256Final(&hmac->hash.sha256, ip);
95 length = SHA256_DIGEST_SIZE;
100 else if (hmac->macType == SHA384) {
101 hmac_block_size = SHA384_BLOCK_SIZE;
102 if (length <= SHA384_BLOCK_SIZE) {
103 XMEMCPY(ip, key, length);
106 Sha384Update(&hmac->hash.sha384, key, length);
107 Sha384Final(&hmac->hash.sha384, ip);
108 length = SHA384_DIGEST_SIZE;
112 XMEMSET(ip + length, 0, hmac_block_size - length);
114 for(i = 0; i < hmac_block_size; i++) {
115 op[i] = ip[i] ^ OPAD;
121 static void HmacKeyInnerHash(Hmac* hmac)
123 if (hmac->macType == MD5)
124 Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE);
125 else if (hmac->macType == SHA)
126 ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE);
128 else if (hmac->macType == SHA256)
129 Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, SHA256_BLOCK_SIZE);
132 else if (hmac->macType == SHA384)
133 Sha384Update(&hmac->hash.sha384, (byte*) hmac->ipad, SHA384_BLOCK_SIZE);
136 hmac->innerHashKeyed = 1;
140 void HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
142 if (!hmac->innerHashKeyed)
143 HmacKeyInnerHash(hmac);
145 if (hmac->macType == MD5)
146 Md5Update(&hmac->hash.md5, msg, length);
147 else if (hmac->macType == SHA)
148 ShaUpdate(&hmac->hash.sha, msg, length);
150 else if (hmac->macType == SHA256)
151 Sha256Update(&hmac->hash.sha256, msg, length);
154 else if (hmac->macType == SHA384)
155 Sha384Update(&hmac->hash.sha384, msg, length);
161 void HmacFinal(Hmac* hmac, byte* hash)
163 if (!hmac->innerHashKeyed)
164 HmacKeyInnerHash(hmac);
166 if (hmac->macType == MD5) {
167 Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
169 Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE);
170 Md5Update(&hmac->hash.md5, (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
172 Md5Final(&hmac->hash.md5, hash);
174 else if (hmac->macType == SHA) {
175 ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
177 ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE);
178 ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
180 ShaFinal(&hmac->hash.sha, hash);
183 else if (hmac->macType == SHA256) {
184 Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
186 Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, SHA256_BLOCK_SIZE);
187 Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash,
190 Sha256Final(&hmac->hash.sha256, hash);
194 else if (hmac->macType == SHA384) {
195 Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash);
197 Sha384Update(&hmac->hash.sha384, (byte*) hmac->opad, SHA384_BLOCK_SIZE);
198 Sha384Update(&hmac->hash.sha384, (byte*) hmac->innerHash,
201 Sha384Final(&hmac->hash.sha384, hash);
205 hmac->innerHashKeyed = 0;