blob: 38028a372ea1bc5bd2237ef697ec0d4aa80d7a27 [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2 Copyright (C) 2012 Werner Dittmann
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 * In addition, as a special exception, the copyright holders give
19 * permission to link the code of portions of this program with the
20 * OpenSSL library under certain conditions as described in each
21 * individual source file, and distribute linked combinations
22 * including the two.
23 * You must obey the GNU General Public License in all respects
24 * for all of the code used other than OpenSSL. If you modify
25 * file(s) with this exception, you may extend this exception to your
26 * version of the file(s), but you are not obligated to do so. If you
27 * do not wish to do so, delete this exception statement from your
28 * version. If you delete this exception statement from all source
29 * files in the program, then also delete it here.
30 */
31
32/*
33 * Authors: Werner Dittmann
34 */
35
36#include <stdint.h>
37#include <string.h>
38#include <stdio.h>
39#include "crypto/sha1.h"
40#include "crypto/hmac.h"
41
42typedef struct _hmacSha1Context {
43 sha1_ctx ctx;
44 sha1_ctx innerCtx;
45 sha1_ctx outerCtx;
46} hmacSha1Context;
47
48static int32_t hmacSha1Init(hmacSha1Context *ctx, const uint8_t *key, uint32_t kLength)
49{
50 int32_t i;
51 uint8_t localPad[SHA1_BLOCK_SIZE] = {0};
52 uint8_t localKey[SHA1_BLOCK_SIZE] = {0};
53
54 if (key == NULL)
55 return 0;
56
57 memset(ctx, 0, sizeof(hmacSha1Context));
58
59 /* check key length and reduce it if necessary */
60 if (kLength > SHA1_BLOCK_SIZE) {
61 sha1_begin(&ctx->ctx);
62 sha1_hash(key, kLength, &ctx->ctx);
63 sha1_end(localKey, &ctx->ctx);
64 }
65 else {
66 memcpy(localKey, key, kLength);
67 }
68 /* prepare inner hash and hold the context */
69 for (i = 0; i < SHA1_BLOCK_SIZE; i++)
70 localPad[i] = localKey[i] ^ 0x36;
71
72 sha1_begin(&ctx->innerCtx);
73 sha1_hash(localPad, SHA1_BLOCK_SIZE, &ctx->innerCtx);
74
75 /* prepare outer hash and hold the context */
76 for (i = 0; i < SHA1_BLOCK_SIZE; i++)
77 localPad[i] = localKey[i] ^ 0x5c;
78
79 sha1_begin(&ctx->outerCtx);
80 sha1_hash(localPad, SHA1_BLOCK_SIZE, &ctx->outerCtx);
81
82 /* copy prepared inner hash to work hash - ready to process data */
83 memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha1_ctx));
84
85 memset(localKey, 0, sizeof(localKey));
86
87 return 1;
88}
89
90static void hmacSha1Reset(hmacSha1Context *ctx)
91{
92 /* copy prepared inner hash to work hash context */
93 memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha1_ctx));
94}
95
96static void hmacSha1Update(hmacSha1Context *ctx, const uint8_t *data, uint32_t dLength)
97{
98 /* hash new data to work hash context */
99 sha1_hash(data, dLength, &ctx->ctx);
100}
101
102static void hmacSha1Final(hmacSha1Context *ctx, uint8_t *mac)
103{
104 uint8_t tmpDigest[SHA1_DIGEST_SIZE];
105
106 /* finalize work hash context */
107 sha1_end(tmpDigest, &ctx->ctx);
108
109 /* copy prepared outer hash to work hash */
110 memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha1_ctx));
111
112 /* hash inner digest to work (outer) hash context */
113 sha1_hash(tmpDigest, SHA1_DIGEST_SIZE, &ctx->ctx);
114
115 /* finalize work hash context to get the hmac*/
116 sha1_end(mac, &ctx->ctx);
117}
118
119
120void hmac_sha1(uint8_t *key, int32_t keyLength, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength)
121{
122 hmacSha1Context ctx;
123
124 hmacSha1Init(&ctx, key, keyLength);
125 hmacSha1Update(&ctx, data, dataLength);
126 hmacSha1Final(&ctx, mac);
127 *macLength = SHA1_BLOCK_SIZE;
128}
129
130void hmac_sha1( uint8_t* key, int32_t keyLength, const uint8_t* dataChunks[], uint32_t dataChunckLength[],
131 uint8_t* mac, int32_t* macLength )
132{
133 hmacSha1Context ctx;
134
135 hmacSha1Init(&ctx, key, keyLength);
136
137 while (*dataChunks) {
138 hmacSha1Update(&ctx, *dataChunks, *dataChunckLength);
139 dataChunks ++;
140 dataChunckLength ++;
141 }
142 hmacSha1Final(&ctx, mac);
143 *macLength = SHA1_BLOCK_SIZE;
144}
145
146void* createSha1HmacContext(uint8_t* key, int32_t keyLength)
147{
148 hmacSha1Context *ctx = reinterpret_cast<hmacSha1Context*>(malloc(sizeof(hmacSha1Context)));
149
150 hmacSha1Init(ctx, key, keyLength);
151 return ctx;
152}
153
154void hmacSha1Ctx(void* ctx, const uint8_t* data, uint32_t dataLength,
155 uint8_t* mac, int32_t* macLength)
156{
157 hmacSha1Context *pctx = (hmacSha1Context*)ctx;
158
159 hmacSha1Reset(pctx);
160 hmacSha1Update(pctx, data, dataLength);
161 hmacSha1Final(pctx, mac);
162 *macLength = SHA1_BLOCK_SIZE;
163}
164
165void hmacSha1Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[],
166 uint8_t* mac, int32_t* macLength )
167{
168 hmacSha1Context *pctx = (hmacSha1Context*)ctx;
169
170 hmacSha1Reset(pctx);
171 while (*data) {
172 hmacSha1Update(pctx, *data, *dataLength);
173 data++;
174 dataLength++;
175 }
176 hmacSha1Final(pctx, mac);
177 *macLength = SHA1_BLOCK_SIZE;
178}
179
180void freeSha1HmacContext(void* ctx)
181{
182 if (ctx) {
183 memset(ctx, 0, sizeof(hmacSha1Context));
184 free(ctx);
185 }
186}