blob: 1e3ceb7d6ea4ee70aaca1d364d9c4117d03fd51f [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2 Copyright (C) 2012-2013 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 "zrtp/crypto/sha2.h"
40#include "zrtp/crypto/hmac256.h"
41
42typedef struct _hmacSha256Context {
43 sha256_ctx ctx;
44 sha256_ctx innerCtx;
45 sha256_ctx outerCtx;
46} hmacSha256Context;
47
48static int32_t hmacSha256Init(hmacSha256Context *ctx, const uint8_t *key, uint32_t kLength)
49{
50 int32_t i;
51 uint8_t localPad[SHA256_BLOCK_SIZE] = {0};
52 uint8_t localKey[SHA256_BLOCK_SIZE] = {0};
53
54 if (key == NULL)
55 return 0;
56
57 memset(ctx, 0, sizeof(hmacSha256Context));
58
59 /* check key length and reduce it if necessary */
60 if (kLength > SHA256_BLOCK_SIZE) {
61 sha256_begin(&ctx->ctx);
62 sha256_hash(key, kLength, &ctx->ctx);
63 sha256_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 < SHA256_BLOCK_SIZE; i++)
70 localPad[i] = localKey[i] ^ 0x36;
71
72 sha256_begin(&ctx->innerCtx);
73 sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->innerCtx);
74
75 /* prepare outer hash and hold the context */
76 for (i = 0; i < SHA256_BLOCK_SIZE; i++)
77 localPad[i] = localKey[i] ^ 0x5c;
78
79 sha256_begin(&ctx->outerCtx);
80 sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->outerCtx);
81
82 /* copy prepared inner hash to work hash - ready to process data */
83 memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx));
84
85 memset(localKey, 0, sizeof(localKey));
86
87 return 1;
88}
89
90static void hmacSha256Reset(hmacSha256Context *ctx)
91{
92 /* copy prepared inner hash to work hash context */
93 memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx));
94}
95
96static void hmacSha256Update(hmacSha256Context *ctx, const uint8_t *data, uint32_t dLength)
97{
98 /* hash new data to work hash context */
99 sha256_hash(data, dLength, &ctx->ctx);
100}
101
102static void hmacSha256Final(hmacSha256Context *ctx, uint8_t *mac)
103{
104 uint8_t tmpDigest[SHA256_DIGEST_SIZE];
105
106 /* finalize work hash context */
107 sha256_end(tmpDigest, &ctx->ctx);
108
109 /* copy prepared outer hash to work hash */
110 memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha256_ctx));
111
112 /* hash inner digest to work (outer) hash context */
113 sha256_hash(tmpDigest, SHA256_DIGEST_SIZE, &ctx->ctx);
114
115 /* finalize work hash context to get the hmac*/
116 sha256_end(mac, &ctx->ctx);
117}
118
119
120void hmac_sha256(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength)
121{
122 hmacSha256Context ctx;
123
124 hmacSha256Init(&ctx, key, keyLength);
125 hmacSha256Update(&ctx, data, dataLength);
126 hmacSha256Final(&ctx, mac);
127 *macLength = SHA256_DIGEST_SIZE;
128}
129
130void hmac_sha256(uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[],
131 uint8_t* mac, uint32_t* macLength )
132{
133 hmacSha256Context ctx;
134
135 hmacSha256Init(&ctx, key, keyLength);
136
137 while (*dataChunks) {
138 hmacSha256Update(&ctx, *dataChunks, *dataChunckLength);
139 dataChunks ++;
140 dataChunckLength ++;
141 }
142 hmacSha256Final(&ctx, mac);
143 *macLength = SHA256_DIGEST_SIZE;
144}
145
146void* createSha256HmacContext(uint8_t* key, int32_t keyLength)
147{
148 hmacSha256Context *ctx = reinterpret_cast<hmacSha256Context*>(malloc(sizeof(hmacSha256Context)));
149
150 hmacSha256Init(ctx, key, keyLength);
151 return ctx;
152}
153
154void hmacSha256Ctx(void* ctx, const uint8_t* data, uint32_t dataLength,
155 uint8_t* mac, int32_t* macLength)
156{
157 hmacSha256Context *pctx = (hmacSha256Context*)ctx;
158
159 hmacSha256Reset(pctx);
160 hmacSha256Update(pctx, data, dataLength);
161 hmacSha256Final(pctx, mac);
162 *macLength = SHA256_DIGEST_SIZE;
163}
164
165void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[],
166 uint8_t* mac, int32_t* macLength )
167{
168 hmacSha256Context *pctx = (hmacSha256Context*)ctx;
169
170 hmacSha256Reset(pctx);
171 while (*data) {
172 hmacSha256Update(pctx, *data, *dataLength);
173 data++;
174 dataLength++;
175 }
176 hmacSha256Final(pctx, mac);
177 *macLength = SHA256_DIGEST_SIZE;
178}
179
180void freeSha256HmacContext(void* ctx)
181{
182 if (ctx) {
183 memset(ctx, 0, sizeof(hmacSha256Context));
184 free(ctx);
185 }
186}