ecc: Fix ec_mulm_25519.
[libgcrypt.git] / cipher / mac.c
1 /* mac.c  -  message authentication code dispatcher
2  * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include "g10lib.h"
27 #include "mac-internal.h"
28
29
30 /* This is the list of the digest implementations included in
31    libgcrypt.  */
32 static gcry_mac_spec_t *mac_list[] = {
33 #if USE_SHA1
34   &_gcry_mac_type_spec_hmac_sha1,
35 #endif
36 #if USE_SHA256
37   &_gcry_mac_type_spec_hmac_sha256,
38   &_gcry_mac_type_spec_hmac_sha224,
39 #endif
40 #if USE_SHA512
41   &_gcry_mac_type_spec_hmac_sha512,
42   &_gcry_mac_type_spec_hmac_sha384,
43 #endif
44 #if USE_SHA3
45   &_gcry_mac_type_spec_hmac_sha3_224,
46   &_gcry_mac_type_spec_hmac_sha3_256,
47   &_gcry_mac_type_spec_hmac_sha3_384,
48   &_gcry_mac_type_spec_hmac_sha3_512,
49 #endif
50 #ifdef USE_GOST_R_3411_94
51   &_gcry_mac_type_spec_hmac_gost3411_94,
52 #endif
53 #ifdef USE_GOST_R_3411_12
54   &_gcry_mac_type_spec_hmac_stribog256,
55   &_gcry_mac_type_spec_hmac_stribog512,
56 #endif
57 #if USE_WHIRLPOOL
58   &_gcry_mac_type_spec_hmac_whirlpool,
59 #endif
60 #if USE_RMD160
61   &_gcry_mac_type_spec_hmac_rmd160,
62 #endif
63 #if USE_TIGER
64   &_gcry_mac_type_spec_hmac_tiger1,
65 #endif
66 #if USE_MD5
67   &_gcry_mac_type_spec_hmac_md5,
68 #endif
69 #if USE_MD4
70   &_gcry_mac_type_spec_hmac_md4,
71 #endif
72 #if USE_BLOWFISH
73   &_gcry_mac_type_spec_cmac_blowfish,
74 #endif
75 #if USE_DES
76   &_gcry_mac_type_spec_cmac_tripledes,
77 #endif
78 #if USE_CAST5
79   &_gcry_mac_type_spec_cmac_cast5,
80 #endif
81 #if USE_AES
82   &_gcry_mac_type_spec_cmac_aes,
83   &_gcry_mac_type_spec_gmac_aes,
84   &_gcry_mac_type_spec_poly1305mac_aes,
85 #endif
86 #if USE_TWOFISH
87   &_gcry_mac_type_spec_cmac_twofish,
88   &_gcry_mac_type_spec_gmac_twofish,
89   &_gcry_mac_type_spec_poly1305mac_twofish,
90 #endif
91 #if USE_SERPENT
92   &_gcry_mac_type_spec_cmac_serpent,
93   &_gcry_mac_type_spec_gmac_serpent,
94   &_gcry_mac_type_spec_poly1305mac_serpent,
95 #endif
96 #if USE_RFC2268
97   &_gcry_mac_type_spec_cmac_rfc2268,
98 #endif
99 #if USE_SEED
100   &_gcry_mac_type_spec_cmac_seed,
101   &_gcry_mac_type_spec_gmac_seed,
102   &_gcry_mac_type_spec_poly1305mac_seed,
103 #endif
104 #if USE_CAMELLIA
105   &_gcry_mac_type_spec_cmac_camellia,
106   &_gcry_mac_type_spec_gmac_camellia,
107   &_gcry_mac_type_spec_poly1305mac_camellia,
108 #endif
109 #ifdef USE_IDEA
110   &_gcry_mac_type_spec_cmac_idea,
111 #endif
112 #if USE_GOST28147
113   &_gcry_mac_type_spec_cmac_gost28147,
114 #endif
115   &_gcry_mac_type_spec_poly1305mac,
116   NULL,
117 };
118
119 /* Explicitly initialize this module.  */
120 gcry_err_code_t
121 _gcry_mac_init (void)
122 {
123   if (fips_mode())
124     {
125       /* disable algorithms that are disallowed in fips */
126       int idx;
127       gcry_mac_spec_t *spec;
128
129       for (idx = 0; (spec = mac_list[idx]); idx++)
130         if (!spec->flags.fips)
131           spec->flags.disabled = 1;
132     }
133
134   return 0;
135 }
136
137 \f
138 /* Return the spec structure for the MAC algorithm ALGO.  For an
139    unknown algorithm NULL is returned.  */
140 static gcry_mac_spec_t *
141 spec_from_algo (int algo)
142 {
143   gcry_mac_spec_t *spec;
144   int idx;
145
146   for (idx = 0; (spec = mac_list[idx]); idx++)
147     if (algo == spec->algo)
148       return spec;
149   return NULL;
150 }
151
152
153 /* Lookup a mac's spec by its name.  */
154 static gcry_mac_spec_t *
155 spec_from_name (const char *name)
156 {
157   gcry_mac_spec_t *spec;
158   int idx;
159
160   for (idx = 0; (spec = mac_list[idx]); idx++)
161     if (!stricmp (name, spec->name))
162       return spec;
163
164   return NULL;
165 }
166
167
168 /****************
169  * Map a string to the mac algo
170  */
171 int
172 _gcry_mac_map_name (const char *string)
173 {
174   gcry_mac_spec_t *spec;
175
176   if (!string)
177     return 0;
178
179   /* Not found, search a matching mac name.  */
180   spec = spec_from_name (string);
181   if (spec)
182     return spec->algo;
183
184   return 0;
185 }
186
187
188 /****************
189  * This function simply returns the name of the algorithm or some constant
190  * string when there is no algo.  It will never return NULL.
191  * Use the macro gcry_mac_test_algo() to check whether the algorithm
192  * is valid.
193  */
194 const char *
195 _gcry_mac_algo_name (int algorithm)
196 {
197   gcry_mac_spec_t *spec;
198
199   spec = spec_from_algo (algorithm);
200   return spec ? spec->name : "?";
201 }
202
203
204 static gcry_err_code_t
205 check_mac_algo (int algorithm)
206 {
207   gcry_mac_spec_t *spec;
208
209   spec = spec_from_algo (algorithm);
210   if (spec && !spec->flags.disabled)
211     return 0;
212
213   return GPG_ERR_MAC_ALGO;
214 }
215
216
217 /****************
218  * Open a message digest handle for use with algorithm ALGO.
219  */
220 static gcry_err_code_t
221 mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
222 {
223   gcry_mac_spec_t *spec;
224   gcry_err_code_t err;
225   gcry_mac_hd_t h;
226
227   spec = spec_from_algo (algo);
228   if (!spec)
229     return GPG_ERR_MAC_ALGO;
230   else if (spec->flags.disabled)
231     return GPG_ERR_MAC_ALGO;
232   else if (!spec->ops)
233     return GPG_ERR_MAC_ALGO;
234   else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
235            !spec->ops->read || !spec->ops->verify || !spec->ops->reset)
236     return GPG_ERR_MAC_ALGO;
237
238   if (secure)
239     h = xtrycalloc_secure (1, sizeof (*h));
240   else
241     h = xtrycalloc (1, sizeof (*h));
242
243   if (!h)
244     return gpg_err_code_from_syserror ();
245
246   h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
247   h->spec = spec;
248   h->algo = algo;
249   h->gcry_ctx = ctx;
250
251   err = h->spec->ops->open (h);
252   if (err)
253     xfree (h);
254   else
255     *hd = h;
256
257   return err;
258 }
259
260
261 static gcry_err_code_t
262 mac_reset (gcry_mac_hd_t hd)
263 {
264   if (hd->spec->ops->reset)
265     return hd->spec->ops->reset (hd);
266
267   return 0;
268 }
269
270
271 static void
272 mac_close (gcry_mac_hd_t hd)
273 {
274   if (hd->spec->ops->close)
275     hd->spec->ops->close (hd);
276
277   wipememory (hd, sizeof (*hd));
278
279   xfree (hd);
280 }
281
282
283 static gcry_err_code_t
284 mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
285 {
286   if (!hd->spec->ops->setkey)
287     return GPG_ERR_INV_ARG;
288   if (keylen > 0 && !key)
289     return GPG_ERR_INV_ARG;
290
291   return hd->spec->ops->setkey (hd, key, keylen);
292 }
293
294
295 static gcry_err_code_t
296 mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
297 {
298   if (!hd->spec->ops->setiv)
299     return GPG_ERR_INV_ARG;
300   if (ivlen > 0 && !iv)
301     return GPG_ERR_INV_ARG;
302
303   return hd->spec->ops->setiv (hd, iv, ivlen);
304 }
305
306
307 static gcry_err_code_t
308 mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
309 {
310   if (!hd->spec->ops->write)
311     return GPG_ERR_INV_ARG;
312   if (inlen > 0 && !inbuf)
313     return GPG_ERR_INV_ARG;
314
315   return hd->spec->ops->write (hd, inbuf, inlen);
316 }
317
318
319 static gcry_err_code_t
320 mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
321 {
322   if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
323     return GPG_ERR_INV_ARG;
324
325   return hd->spec->ops->read (hd, outbuf, outlen);
326 }
327
328
329 static gcry_err_code_t
330 mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
331 {
332   if (!buf || buflen == 0 || !hd->spec->ops->verify)
333     return GPG_ERR_INV_ARG;
334
335   return hd->spec->ops->verify (hd, buf, buflen);
336 }
337
338
339 /* Create a MAC object for algorithm ALGO.  FLAGS may be
340    given as an bitwise OR of the gcry_mac_flags values.
341    H is guaranteed to be a valid handle or NULL on error.  */
342 gpg_err_code_t
343 _gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags,
344                 gcry_ctx_t ctx)
345 {
346   gcry_err_code_t rc;
347   gcry_mac_hd_t hd = NULL;
348
349   if ((flags & ~GCRY_MAC_FLAG_SECURE))
350     rc = GPG_ERR_INV_ARG;
351   else
352     rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
353
354   *h = rc ? NULL : hd;
355   return rc;
356 }
357
358
359 void
360 _gcry_mac_close (gcry_mac_hd_t hd)
361 {
362   if (hd)
363     mac_close (hd);
364 }
365
366
367 gcry_err_code_t
368 _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
369 {
370   return mac_setkey (hd, key, keylen);
371 }
372
373
374 gcry_err_code_t
375 _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
376 {
377   return mac_setiv (hd, iv, ivlen);
378 }
379
380
381 gcry_err_code_t
382 _gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
383 {
384   return mac_write (hd, inbuf, inlen);
385 }
386
387
388 gcry_err_code_t
389 _gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
390 {
391   return mac_read (hd, outbuf, outlen);
392 }
393
394
395 gcry_err_code_t
396 _gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
397 {
398   return mac_verify (hd, buf, buflen);
399 }
400
401
402 int
403 _gcry_mac_get_algo (gcry_mac_hd_t hd)
404 {
405   return hd->algo;
406 }
407
408
409 unsigned int
410 _gcry_mac_get_algo_maclen (int algo)
411 {
412   gcry_mac_spec_t *spec;
413
414   spec = spec_from_algo (algo);
415   if (!spec || !spec->ops || !spec->ops->get_maclen)
416     return 0;
417
418   return spec->ops->get_maclen (algo);
419 }
420
421
422 unsigned int
423 _gcry_mac_get_algo_keylen (int algo)
424 {
425   gcry_mac_spec_t *spec;
426
427   spec = spec_from_algo (algo);
428   if (!spec || !spec->ops || !spec->ops->get_keylen)
429     return 0;
430
431   return spec->ops->get_keylen (algo);
432 }
433
434
435 gcry_err_code_t
436 _gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
437 {
438   gcry_err_code_t rc;
439
440   /* Currently not used.  */
441   (void) hd;
442   (void) buffer;
443   (void) buflen;
444
445   switch (cmd)
446     {
447     case GCRYCTL_RESET:
448       rc = mac_reset (hd);
449       break;
450     default:
451       rc = GPG_ERR_INV_OP;
452     }
453   return rc;
454 }
455
456
457 /* Return information about the given MAC algorithm ALGO.
458
459     GCRYCTL_TEST_ALGO:
460         Returns 0 if the specified algorithm ALGO is available for use.
461         BUFFER and NBYTES must be zero.
462
463    Note: Because this function is in most cases used to return an
464    integer value, we can make it easier for the caller to just look at
465    the return value.  The caller will in all cases consult the value
466    and thereby detecting whether a error occurred or not (i.e. while
467    checking the block size)
468  */
469 gcry_err_code_t
470 _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
471 {
472   gcry_err_code_t rc = 0;
473   unsigned int ui;
474
475   switch (what)
476     {
477     case GCRYCTL_GET_KEYLEN:
478       if (buffer || (!nbytes))
479         rc = GPG_ERR_INV_ARG;
480       else
481         {
482           ui = _gcry_mac_get_algo_keylen (algo);
483           if (ui > 0)
484             *nbytes = (size_t) ui;
485           else
486             /* The only reason for an error is an invalid algo.  */
487             rc = GPG_ERR_MAC_ALGO;
488         }
489       break;
490     case GCRYCTL_TEST_ALGO:
491       if (buffer || nbytes)
492         rc = GPG_ERR_INV_ARG;
493       else
494         rc = check_mac_algo (algo);
495       break;
496
497     default:
498       rc = GPG_ERR_INV_OP;
499     }
500
501   return rc;
502 }