Prototype implementation of IKE key exchange via NTRU encryption
[strongswan.git] / src / libstrongswan / plugins / ntru / ntru_crypto / ntru_crypto_hmac.c
1 /******************************************************************************
2 * NTRU Cryptography Reference Source Code
3 * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
4 *
5 * ntru_crypto_hmac.c is a component of ntru-crypto.
6 *
7 * Copyright (C) 2009-2013 Security Innovation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *****************************************************************************/
24
25 /******************************************************************************
26 *
27 * File: ntru_crypto_hmac.c
28 *
29 * Contents: Routines implementing the HMAC hash calculation.
30 *
31 *****************************************************************************/
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include "ntru_crypto_hmac.h"
37
38
39 /* HMAC context */
40
41 struct _NTRU_CRYPTO_HMAC_CTX {
42 NTRU_CRYPTO_HASH_CTX hash_ctx;
43 uint8_t *k0;
44 uint16_t blk_len;
45 uint16_t md_len;
46 };
47
48
49 /* ntru_crypto_hmac_create_ctx
50 *
51 * This routine creates an HMAC context, setting the hash algorithm and
52 * the key to be used.
53 *
54 * Returns NTRU_CRYPTO_HMAC_OK if successful.
55 * Returns NTRU_CRYPTO_HMAC_BAD_ALG if the specified algorithm is not supported.
56 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
57 * passed.
58 * Returns NTRU_CRYPTO_HMAC_OUT_OF_MEMORY if memory cannot be allocated.
59 */
60
61 uint32_t
62 ntru_crypto_hmac_create_ctx(
63 NTRU_CRYPTO_HASH_ALGID algid, /* in - the hash algorithm to be used */
64 uint8_t const *key, /* in - pointer to the HMAC key */
65 uint32_t key_len, /* in - number of bytes in HMAC key */
66 NTRU_CRYPTO_HMAC_CTX **c) /* out - address for pointer to HMAC
67 context */
68 {
69 NTRU_CRYPTO_HMAC_CTX *ctx = NULL;
70 uint32_t result;
71
72 /* check parameters */
73
74 if (!c || !key)
75 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
76
77 *c = NULL;
78
79 /* allocate memory for an HMAC context */
80
81 if ((ctx = (NTRU_CRYPTO_HMAC_CTX*) malloc(sizeof(NTRU_CRYPTO_HMAC_CTX))) ==
82 NULL)
83 HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
84
85 /* set the algorithm */
86
87 if (result = ntru_crypto_hash_set_alg(algid, &ctx->hash_ctx)) {
88 free(ctx);
89 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_ALG);
90 }
91
92 /* set block length and digest length */
93
94 if ((result = ntru_crypto_hash_block_length(&ctx->hash_ctx,
95 &ctx->blk_len)) ||
96 (result = ntru_crypto_hash_digest_length(&ctx->hash_ctx,
97 &ctx->md_len))) {
98 free(ctx);
99 return result;
100 }
101
102 /* allocate memory for K0 */
103
104 if ((ctx->k0 = (uint8_t*) malloc(ctx->blk_len)) == NULL) {
105 free(ctx);
106 HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
107 }
108
109 /* calculate K0 and store in HMAC context */
110
111 memset(ctx->k0, 0, ctx->blk_len);
112
113 /* check if key is too large */
114
115 if (key_len > ctx->blk_len) {
116
117 if (result = ntru_crypto_hash_digest(algid, key, key_len, ctx->k0)) {
118 memset(ctx->k0, 0, ctx->blk_len);
119 free(ctx->k0);
120 free(ctx);
121 return result;
122 }
123
124 } else
125 memcpy(ctx->k0, key, key_len);
126
127 /* return pointer to HMAC context */
128
129 *c = ctx;
130 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
131 }
132
133
134 /* ntru_crypto_hmac_destroy_ctx
135 *
136 * Destroys an HMAC context.
137 *
138 * Returns NTRU_CRYPTO_HMAC_OK if successful.
139 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
140 * passed.
141 */
142
143 uint32_t
144 ntru_crypto_hmac_destroy_ctx(
145 NTRU_CRYPTO_HMAC_CTX *c) /* in/out - pointer to HMAC context */
146 {
147 if (!c || !c->k0)
148 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
149
150 /* clear key and release memory */
151
152 memset(c->k0, 0, c->blk_len);
153 free(c->k0);
154 free(c);
155
156 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
157 }
158
159
160 /* ntru_crypto_hmac_get_md_len
161 *
162 * This routine gets the digest length of the HMAC.
163 *
164 * Returns NTRU_CRYPTO_HMAC_OK on success.
165 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
166 * passed.
167 */
168
169 uint32_t
170 ntru_crypto_hmac_get_md_len(
171 NTRU_CRYPTO_HMAC_CTX const *c, /* in - pointer to HMAC context */
172 uint16_t *md_len) /* out - address for digest length */
173 {
174 /* check parameters */
175
176 if (!c || !md_len)
177 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
178
179 /* get digest length */
180
181 *md_len = c->md_len;
182 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
183 }
184
185
186 /* ntru_crypto_hmac_set_key
187 *
188 * This routine sets a digest-length key into the HMAC context.
189 *
190 * Returns NTRU_CRYPTO_HMAC_OK on success.
191 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
192 * passed.
193 */
194
195 uint32_t
196 ntru_crypto_hmac_set_key(
197 NTRU_CRYPTO_HMAC_CTX *c, /* in - pointer to HMAC context */
198 uint8_t const *key) /* in - pointer to new HMAC key */
199 {
200 /* check parameters */
201
202 if (!c || !key)
203 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
204
205 /* copy key */
206
207 memcpy(c->k0, key, c->md_len);
208 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
209 }
210
211
212 /* ntru_crypto_hmac_init
213 *
214 * This routine performs standard initialization of the HMAC state.
215 *
216 * Returns NTRU_CRYPTO_HMAC_OK on success.
217 * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
218 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
219 * passed.
220 */
221
222 uint32_t
223 ntru_crypto_hmac_init(
224 NTRU_CRYPTO_HMAC_CTX *c) /* in/out - pointer to HMAC context */
225 {
226 uint32_t result;
227 int i;
228
229 /* check parameters */
230
231 if (!c)
232 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
233
234 /* init hash context and compute H(K0 ^ ipad) */
235
236 for (i = 0; i < c->blk_len; i++)
237 c->k0[i] ^= 0x36; /* K0 ^ ipad */
238 if ((result = ntru_crypto_hash_init(&c->hash_ctx)) ||
239 (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len)))
240 return result;
241
242 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
243 }
244
245
246 /* ntru_crypto_hmac_update
247 *
248 * This routine processes input data and updates the HMAC hash calculation.
249 *
250 * Returns NTRU_CRYPTO_HMAC_OK on success.
251 * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
252 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
253 * passed.
254 * Returns NTRU_CRYPTO_HASH_OVERFLOW if more than bytes are hashed than the
255 * underlying hash algorithm can handle.
256 */
257
258 uint32_t
259 ntru_crypto_hmac_update(
260 NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
261 const uint8_t *data, /* in - pointer to input data */
262 uint32_t data_len) /* in - no. of bytes of input data */
263 {
264 uint32_t result;
265
266 /* check parameters */
267
268 if (!c || (data_len && !data))
269 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
270
271 if (result = ntru_crypto_hash_update(&c->hash_ctx, data, data_len))
272 return result;
273
274 HMAC_RET(NTRU_CRYPTO_HMAC_OK);
275 }
276
277
278 /* ntru_crypto_hmac_final
279 *
280 * This routine completes the HMAC hash calculation and returns the
281 * message digest.
282 *
283 * Returns NTRU_CRYPTO_HMAC_OK on success.
284 * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
285 * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
286 * passed.
287 */
288
289 uint32_t
290 ntru_crypto_hmac_final(
291 NTRU_CRYPTO_HMAC_CTX *c, /* in/out - pointer to HMAC context */
292 uint8_t *md) /* out - address for message digest */
293 {
294 uint32_t result = NTRU_CRYPTO_HMAC_OK;
295 int i;
296
297 /* check parameters */
298
299 if (!c || !md)
300 HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
301
302 /* form K0 ^ opad
303 * complete md = H((K0 ^ ipad) || data)
304 * compute md = H((K0 ^ opad) || md)
305 * re-form K0
306 */
307
308 for (i = 0; i < c->blk_len; i++)
309 c->k0[i] ^= (0x36^0x5c);
310 if ((result = ntru_crypto_hash_final(&c->hash_ctx, md)) ||
311 (result = ntru_crypto_hash_init(&c->hash_ctx)) ||
312 (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len)) ||
313 (result = ntru_crypto_hash_update(&c->hash_ctx, md, c->md_len)) ||
314 (result = ntru_crypto_hash_final(&c->hash_ctx, md))) {
315 }
316 for (i = 0; i < c->blk_len; i++)
317 c->k0[i] ^= 0x5c;
318 return result;
319 }
320