FIPS140 mode is detected on run-time.
[gnutls:gnutls.git] / lib / nettle / mac.c
1 /*
2  * Copyright (C) 2008-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GNUTLS.
7  *
8  * The GNUTLS library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* This file provides the backend hash/mac API for nettle.
24  */
25
26 #include <gnutls_int.h>
27 #include <gnutls_hash_int.h>
28 #include <gnutls_errors.h>
29 #include <nettle/md5.h>
30 #include <nettle/md2.h>
31 #include <nettle/sha.h>
32 #include <nettle/hmac.h>
33 #include <nettle/umac.h>
34 #include <fips.h>
35
36 typedef void (*update_func) (void *, unsigned, const uint8_t *);
37 typedef void (*digest_func) (void *, unsigned, uint8_t *);
38 typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
39 typedef void (*set_nonce_func) (void *, unsigned, const uint8_t *);
40
41 static int wrap_nettle_hash_init(gnutls_digest_algorithm_t algo,
42                                  void **_ctx);
43
44 struct nettle_hash_ctx {
45         union {
46                 struct md5_ctx md5;
47                 struct sha224_ctx sha224;
48                 struct sha256_ctx sha256;
49                 struct sha384_ctx sha384;
50                 struct sha512_ctx sha512;
51                 struct sha1_ctx sha1;
52                 struct md2_ctx md2;
53         } ctx;
54         void *ctx_ptr;
55         gnutls_digest_algorithm_t algo;
56         size_t length;
57         update_func update;
58         digest_func digest;
59 };
60
61 struct nettle_mac_ctx {
62         union {
63                 struct hmac_md5_ctx md5;
64                 struct hmac_sha224_ctx sha224;
65                 struct hmac_sha256_ctx sha256;
66                 struct hmac_sha384_ctx sha384;
67                 struct hmac_sha512_ctx sha512;
68                 struct hmac_sha1_ctx sha1;
69                 struct umac96_ctx umac96;
70                 struct umac128_ctx umac128;
71         } ctx;
72
73         void *ctx_ptr;
74         gnutls_mac_algorithm_t algo;
75         size_t length;
76         update_func update;
77         digest_func digest;
78         set_key_func set_key;
79         set_nonce_func set_nonce;
80 };
81
82 static void
83 _wrap_umac96_set_key(void *ctx, unsigned len, const uint8_t * key)
84 {
85         if (unlikely(len != 16))
86                 abort();
87         umac96_set_key(ctx, key);
88 }
89
90 static void
91 _wrap_umac128_set_key(void *ctx, unsigned len, const uint8_t * key)
92 {
93         if (unlikely(len != 16))
94                 abort();
95         umac128_set_key(ctx, key);
96 }
97
98 static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
99                          struct nettle_mac_ctx *ctx)
100 {
101         ctx->set_nonce = NULL;
102         switch (algo) {
103         case GNUTLS_MAC_MD5:
104                 ctx->update = (update_func) hmac_md5_update;
105                 ctx->digest = (digest_func) hmac_md5_digest;
106                 ctx->set_key = (set_key_func) hmac_md5_set_key;
107                 ctx->ctx_ptr = &ctx->ctx.md5;
108                 ctx->length = MD5_DIGEST_SIZE;
109                 break;
110         case GNUTLS_MAC_SHA1:
111                 ctx->update = (update_func) hmac_sha1_update;
112                 ctx->digest = (digest_func) hmac_sha1_digest;
113                 ctx->set_key = (set_key_func) hmac_sha1_set_key;
114                 ctx->ctx_ptr = &ctx->ctx.sha1;
115                 ctx->length = SHA1_DIGEST_SIZE;
116                 break;
117         case GNUTLS_MAC_SHA224:
118                 ctx->update = (update_func) hmac_sha224_update;
119                 ctx->digest = (digest_func) hmac_sha224_digest;
120                 ctx->set_key = (set_key_func) hmac_sha224_set_key;
121                 ctx->ctx_ptr = &ctx->ctx.sha224;
122                 ctx->length = SHA224_DIGEST_SIZE;
123                 break;
124         case GNUTLS_MAC_SHA256:
125                 ctx->update = (update_func) hmac_sha256_update;
126                 ctx->digest = (digest_func) hmac_sha256_digest;
127                 ctx->set_key = (set_key_func) hmac_sha256_set_key;
128                 ctx->ctx_ptr = &ctx->ctx.sha256;
129                 ctx->length = SHA256_DIGEST_SIZE;
130                 break;
131         case GNUTLS_MAC_SHA384:
132                 ctx->update = (update_func) hmac_sha384_update;
133                 ctx->digest = (digest_func) hmac_sha384_digest;
134                 ctx->set_key = (set_key_func) hmac_sha384_set_key;
135                 ctx->ctx_ptr = &ctx->ctx.sha384;
136                 ctx->length = SHA384_DIGEST_SIZE;
137                 break;
138         case GNUTLS_MAC_SHA512:
139                 ctx->update = (update_func) hmac_sha512_update;
140                 ctx->digest = (digest_func) hmac_sha512_digest;
141                 ctx->set_key = (set_key_func) hmac_sha512_set_key;
142                 ctx->ctx_ptr = &ctx->ctx.sha512;
143                 ctx->length = SHA512_DIGEST_SIZE;
144                 break;
145         case GNUTLS_MAC_UMAC_96:
146                 if (_gnutls_fips_mode_enabled() != 0)
147                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
148         
149                 ctx->update = (update_func) umac96_update;
150                 ctx->digest = (digest_func) umac96_digest;
151                 ctx->set_key = _wrap_umac96_set_key;
152                 ctx->set_nonce = (set_nonce_func) umac96_set_nonce;
153                 ctx->ctx_ptr = &ctx->ctx.umac96;
154                 ctx->length = 12;
155                 break;
156         case GNUTLS_MAC_UMAC_128:
157                 if (_gnutls_fips_mode_enabled() != 0)
158                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
159
160                 ctx->update = (update_func) umac128_update;
161                 ctx->digest = (digest_func) umac128_digest;
162                 ctx->set_key = _wrap_umac128_set_key;
163                 ctx->set_nonce = (set_nonce_func) umac128_set_nonce;
164                 ctx->ctx_ptr = &ctx->ctx.umac128;
165                 ctx->length = 16;
166                 break;
167         default:
168                 gnutls_assert();
169                 return GNUTLS_E_INVALID_REQUEST;
170         }
171
172         return 0;
173 }
174
175 static int wrap_nettle_mac_fast(gnutls_mac_algorithm_t algo,
176                                 const void *nonce, size_t nonce_size,
177                                 const void *key, size_t key_size,
178                                 const void *text, size_t text_size,
179                                 void *digest)
180 {
181         struct nettle_mac_ctx ctx;
182         int ret;
183
184         ret = _mac_ctx_init(algo, &ctx);
185         if (ret < 0)
186                 return gnutls_assert_val(ret);
187
188         if (ctx.set_nonce)
189                 ctx.set_nonce(&ctx, nonce_size, nonce);
190         ctx.set_key(&ctx, key_size, key);
191         ctx.update(&ctx, text_size, text);
192         ctx.digest(&ctx, ctx.length, digest);
193         
194         zeroize_temp_key(&ctx, sizeof(ctx));
195
196         return 0;
197 }
198
199 static int wrap_nettle_mac_exists(gnutls_mac_algorithm_t algo)
200 {
201         switch (algo) {
202         case GNUTLS_MAC_MD5:
203         case GNUTLS_MAC_SHA1:
204         case GNUTLS_MAC_SHA224:
205         case GNUTLS_MAC_SHA256:
206         case GNUTLS_MAC_SHA384:
207         case GNUTLS_MAC_SHA512:
208                 return 1;
209
210         case GNUTLS_MAC_UMAC_96:
211         case GNUTLS_MAC_UMAC_128:
212                 if (_gnutls_fips_mode_enabled() != 0)
213                         return 0;
214                 else
215                         return 1;
216         default:
217                 return 0;
218         }
219 }
220
221 static int wrap_nettle_mac_init(gnutls_mac_algorithm_t algo, void **_ctx)
222 {
223         struct nettle_mac_ctx *ctx;
224         int ret;
225
226         ctx = gnutls_calloc(1, sizeof(struct nettle_mac_ctx));
227         if (ctx == NULL) {
228                 gnutls_assert();
229                 return GNUTLS_E_MEMORY_ERROR;
230         }
231
232         ctx->algo = algo;
233
234         ret = _mac_ctx_init(algo, ctx);
235         if (ret < 0) {
236                 gnutls_free(ctx);
237                 return gnutls_assert_val(ret);
238         }
239
240         *_ctx = ctx;
241
242         return 0;
243 }
244
245 static int
246 wrap_nettle_mac_set_key(void *_ctx, const void *key, size_t keylen)
247 {
248         struct nettle_mac_ctx *ctx = _ctx;
249
250         ctx->set_key(ctx->ctx_ptr, keylen, key);
251         return 0;
252 }
253
254 static int
255 wrap_nettle_mac_set_nonce(void *_ctx, const void *nonce, size_t noncelen)
256 {
257         struct nettle_mac_ctx *ctx = _ctx;
258
259         if (ctx->set_nonce == NULL)
260                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
261
262         ctx->set_nonce(ctx->ctx_ptr, noncelen, nonce);
263
264         return GNUTLS_E_SUCCESS;
265 }
266
267 static int
268 wrap_nettle_mac_update(void *_ctx, const void *text, size_t textsize)
269 {
270         struct nettle_mac_ctx *ctx = _ctx;
271
272         ctx->update(ctx->ctx_ptr, textsize, text);
273
274         return GNUTLS_E_SUCCESS;
275 }
276
277 static int
278 wrap_nettle_mac_output(void *src_ctx, void *digest, size_t digestsize)
279 {
280         struct nettle_mac_ctx *ctx;
281         ctx = src_ctx;
282
283         if (digestsize < ctx->length) {
284                 gnutls_assert();
285                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
286         }
287
288         ctx->digest(ctx->ctx_ptr, digestsize, digest);
289
290         return 0;
291 }
292
293 static void wrap_nettle_mac_deinit(void *hd)
294 {
295         struct nettle_mac_ctx *ctx = hd;
296         
297         zeroize_temp_key(ctx, sizeof(*ctx));
298         gnutls_free(ctx);
299 }
300
301 /* Hash functions 
302  */
303 static int
304 wrap_nettle_hash_update(void *_ctx, const void *text, size_t textsize)
305 {
306         struct nettle_hash_ctx *ctx = _ctx;
307
308         ctx->update(ctx->ctx_ptr, textsize, text);
309
310         return GNUTLS_E_SUCCESS;
311 }
312
313 static void wrap_nettle_hash_deinit(void *hd)
314 {
315         gnutls_free(hd);
316 }
317
318 static int wrap_nettle_hash_exists(gnutls_digest_algorithm_t algo)
319 {
320         switch (algo) {
321         case GNUTLS_DIG_MD5:
322         case GNUTLS_DIG_SHA1:
323
324         case GNUTLS_DIG_SHA224:
325         case GNUTLS_DIG_SHA256:
326         case GNUTLS_DIG_SHA384:
327         case GNUTLS_DIG_SHA512:
328                 return 1;
329         case GNUTLS_DIG_MD2:
330                 if (_gnutls_fips_mode_enabled() != 0)
331                         return 0;
332                 else
333                         return 1;
334         default:
335                 return 0;
336         }
337 }
338
339 static int _ctx_init(gnutls_digest_algorithm_t algo,
340                      struct nettle_hash_ctx *ctx)
341 {
342         switch (algo) {
343         case GNUTLS_DIG_MD5:
344                 md5_init(&ctx->ctx.md5);
345                 ctx->update = (update_func) md5_update;
346                 ctx->digest = (digest_func) md5_digest;
347                 ctx->ctx_ptr = &ctx->ctx.md5;
348                 ctx->length = MD5_DIGEST_SIZE;
349                 break;
350         case GNUTLS_DIG_SHA1:
351                 sha1_init(&ctx->ctx.sha1);
352                 ctx->update = (update_func) sha1_update;
353                 ctx->digest = (digest_func) sha1_digest;
354                 ctx->ctx_ptr = &ctx->ctx.sha1;
355                 ctx->length = SHA1_DIGEST_SIZE;
356                 break;
357         case GNUTLS_DIG_SHA224:
358                 sha224_init(&ctx->ctx.sha224);
359                 ctx->update = (update_func) sha224_update;
360                 ctx->digest = (digest_func) sha224_digest;
361                 ctx->ctx_ptr = &ctx->ctx.sha224;
362                 ctx->length = SHA224_DIGEST_SIZE;
363                 break;
364         case GNUTLS_DIG_SHA256:
365                 sha256_init(&ctx->ctx.sha256);
366                 ctx->update = (update_func) sha256_update;
367                 ctx->digest = (digest_func) sha256_digest;
368                 ctx->ctx_ptr = &ctx->ctx.sha256;
369                 ctx->length = SHA256_DIGEST_SIZE;
370                 break;
371         case GNUTLS_DIG_SHA384:
372                 sha384_init(&ctx->ctx.sha384);
373                 ctx->update = (update_func) sha384_update;
374                 ctx->digest = (digest_func) sha384_digest;
375                 ctx->ctx_ptr = &ctx->ctx.sha384;
376                 ctx->length = SHA384_DIGEST_SIZE;
377                 break;
378         case GNUTLS_DIG_SHA512:
379                 sha512_init(&ctx->ctx.sha512);
380                 ctx->update = (update_func) sha512_update;
381                 ctx->digest = (digest_func) sha512_digest;
382                 ctx->ctx_ptr = &ctx->ctx.sha512;
383                 ctx->length = SHA512_DIGEST_SIZE;
384                 break;
385         case GNUTLS_DIG_MD2:
386                 if (_gnutls_fips_mode_enabled() != 0)
387                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
388
389                 md2_init(&ctx->ctx.md2);
390                 ctx->update = (update_func) md2_update;
391                 ctx->digest = (digest_func) md2_digest;
392                 ctx->ctx_ptr = &ctx->ctx.md2;
393                 ctx->length = MD2_DIGEST_SIZE;
394                 break;
395         default:
396                 gnutls_assert();
397                 return GNUTLS_E_INVALID_REQUEST;
398         }
399
400         return 0;
401 }
402
403 static int wrap_nettle_hash_fast(gnutls_digest_algorithm_t algo,
404                                  const void *text, size_t text_size,
405                                  void *digest)
406 {
407         struct nettle_hash_ctx ctx;
408         int ret;
409
410         ret = _ctx_init(algo, &ctx);
411         if (ret < 0)
412                 return gnutls_assert_val(ret);
413
414         ctx.update(&ctx, text_size, text);
415         ctx.digest(&ctx, ctx.length, digest);
416
417         return 0;
418 }
419
420 static int
421 wrap_nettle_hash_init(gnutls_digest_algorithm_t algo, void **_ctx)
422 {
423         struct nettle_hash_ctx *ctx;
424         int ret;
425
426         ctx = gnutls_malloc(sizeof(struct nettle_hash_ctx));
427         if (ctx == NULL) {
428                 gnutls_assert();
429                 return GNUTLS_E_MEMORY_ERROR;
430         }
431
432         ctx->algo = algo;
433
434         if ((ret = _ctx_init(algo, ctx)) < 0) {
435                 gnutls_assert();
436                 gnutls_free(ctx);
437                 return ret;
438         }
439
440         *_ctx = ctx;
441
442         return 0;
443 }
444
445 static int
446 wrap_nettle_hash_output(void *src_ctx, void *digest, size_t digestsize)
447 {
448         struct nettle_hash_ctx *ctx;
449         ctx = src_ctx;
450
451         if (digestsize < ctx->length) {
452                 gnutls_assert();
453                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
454         }
455
456         ctx->digest(ctx->ctx_ptr, digestsize, digest);
457
458         return 0;
459 }
460
461 gnutls_crypto_mac_st _gnutls_mac_ops = {
462         .init = wrap_nettle_mac_init,
463         .setkey = wrap_nettle_mac_set_key,
464         .setnonce = wrap_nettle_mac_set_nonce,
465         .hash = wrap_nettle_mac_update,
466         .output = wrap_nettle_mac_output,
467         .deinit = wrap_nettle_mac_deinit,
468         .fast = wrap_nettle_mac_fast,
469         .exists = wrap_nettle_mac_exists,
470 };
471
472 gnutls_crypto_digest_st _gnutls_digest_ops = {
473         .init = wrap_nettle_hash_init,
474         .hash = wrap_nettle_hash_update,
475         .output = wrap_nettle_hash_output,
476         .deinit = wrap_nettle_hash_deinit,
477         .fast = wrap_nettle_hash_fast,
478         .exists = wrap_nettle_hash_exists,
479 };