mac: Fix gcry_mac_close to allow for a NULL handle.
[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 #ifdef USE_GOST_R_3411_94
45   &_gcry_mac_type_spec_hmac_gost3411_94,
46 #endif
47 #ifdef USE_GOST_R_3411_12
48   &_gcry_mac_type_spec_hmac_stribog256,
49   &_gcry_mac_type_spec_hmac_stribog512,
50 #endif
51 #if USE_WHIRLPOOL
52   &_gcry_mac_type_spec_hmac_whirlpool,
53 #endif
54 #if USE_RMD160
55   &_gcry_mac_type_spec_hmac_rmd160,
56 #endif
57 #if USE_TIGER
58   &_gcry_mac_type_spec_hmac_tiger1,
59 #endif
60 #if USE_MD5
61   &_gcry_mac_type_spec_hmac_md5,
62 #endif
63 #if USE_MD4
64   &_gcry_mac_type_spec_hmac_md4,
65 #endif
66 #if USE_BLOWFISH
67   &_gcry_mac_type_spec_cmac_blowfish,
68 #endif
69 #if USE_DES
70   &_gcry_mac_type_spec_cmac_tripledes,
71 #endif
72 #if USE_CAST5
73   &_gcry_mac_type_spec_cmac_cast5,
74 #endif
75 #if USE_AES
76   &_gcry_mac_type_spec_cmac_aes,
77   &_gcry_mac_type_spec_gmac_aes,
78   &_gcry_mac_type_spec_poly1305mac_aes,
79 #endif
80 #if USE_TWOFISH
81   &_gcry_mac_type_spec_cmac_twofish,
82   &_gcry_mac_type_spec_gmac_twofish,
83   &_gcry_mac_type_spec_poly1305mac_twofish,
84 #endif
85 #if USE_SERPENT
86   &_gcry_mac_type_spec_cmac_serpent,
87   &_gcry_mac_type_spec_gmac_serpent,
88   &_gcry_mac_type_spec_poly1305mac_serpent,
89 #endif
90 #if USE_RFC2268
91   &_gcry_mac_type_spec_cmac_rfc2268,
92 #endif
93 #if USE_SEED
94   &_gcry_mac_type_spec_cmac_seed,
95   &_gcry_mac_type_spec_gmac_seed,
96   &_gcry_mac_type_spec_poly1305mac_seed,
97 #endif
98 #if USE_CAMELLIA
99   &_gcry_mac_type_spec_cmac_camellia,
100   &_gcry_mac_type_spec_gmac_camellia,
101   &_gcry_mac_type_spec_poly1305mac_camellia,
102 #endif
103 #ifdef USE_IDEA
104   &_gcry_mac_type_spec_cmac_idea,
105 #endif
106 #if USE_GOST28147
107   &_gcry_mac_type_spec_cmac_gost28147,
108 #endif
109   &_gcry_mac_type_spec_poly1305mac,
110   NULL,
111 };
112
113
114 \f
115 /* Return the spec structure for the MAC algorithm ALGO.  For an
116    unknown algorithm NULL is returned.  */
117 static gcry_mac_spec_t *
118 spec_from_algo (int algo)
119 {
120   gcry_mac_spec_t *spec;
121   int idx;
122
123   for (idx = 0; (spec = mac_list[idx]); idx++)
124     if (algo == spec->algo)
125       return spec;
126   return NULL;
127 }
128
129
130 /* Lookup a mac's spec by its name.  */
131 static gcry_mac_spec_t *
132 spec_from_name (const char *name)
133 {
134   gcry_mac_spec_t *spec;
135   int idx;
136
137   for (idx = 0; (spec = mac_list[idx]); idx++)
138     if (!stricmp (name, spec->name))
139       return spec;
140
141   return NULL;
142 }
143
144
145 /****************
146  * Map a string to the mac algo
147  */
148 int
149 _gcry_mac_map_name (const char *string)
150 {
151   gcry_mac_spec_t *spec;
152
153   if (!string)
154     return 0;
155
156   /* Not found, search a matching mac name.  */
157   spec = spec_from_name (string);
158   if (spec)
159     return spec->algo;
160
161   return 0;
162 }
163
164
165 /****************
166  * This function simply returns the name of the algorithm or some constant
167  * string when there is no algo.  It will never return NULL.
168  * Use the macro gcry_mac_test_algo() to check whether the algorithm
169  * is valid.
170  */
171 const char *
172 _gcry_mac_algo_name (int algorithm)
173 {
174   gcry_mac_spec_t *spec;
175
176   spec = spec_from_algo (algorithm);
177   return spec ? spec->name : "?";
178 }
179
180
181 static gcry_err_code_t
182 check_mac_algo (int algorithm)
183 {
184   gcry_mac_spec_t *spec;
185
186   spec = spec_from_algo (algorithm);
187   if (spec && !spec->flags.disabled)
188     return 0;
189
190   return GPG_ERR_MAC_ALGO;
191 }
192
193
194 /****************
195  * Open a message digest handle for use with algorithm ALGO.
196  */
197 static gcry_err_code_t
198 mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
199 {
200   gcry_mac_spec_t *spec;
201   gcry_err_code_t err;
202   gcry_mac_hd_t h;
203
204   spec = spec_from_algo (algo);
205   if (!spec)
206     return GPG_ERR_MAC_ALGO;
207   else if (spec->flags.disabled)
208     return GPG_ERR_MAC_ALGO;
209   else if (!spec->ops)
210     return GPG_ERR_MAC_ALGO;
211   else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
212            !spec->ops->read || !spec->ops->verify || !spec->ops->reset)
213     return GPG_ERR_MAC_ALGO;
214
215   if (secure)
216     h = xtrycalloc_secure (1, sizeof (*h));
217   else
218     h = xtrycalloc (1, sizeof (*h));
219
220   if (!h)
221     return gpg_err_code_from_syserror ();
222
223   h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
224   h->spec = spec;
225   h->algo = algo;
226   h->gcry_ctx = ctx;
227
228   err = h->spec->ops->open (h);
229   if (err)
230     xfree (h);
231   else
232     *hd = h;
233
234   return err;
235 }
236
237
238 static gcry_error_t
239 mac_reset (gcry_mac_hd_t hd)
240 {
241   if (hd->spec->ops->reset)
242     return hd->spec->ops->reset (hd);
243
244   return 0;
245 }
246
247
248 static void
249 mac_close (gcry_mac_hd_t hd)
250 {
251   if (hd->spec->ops->close)
252     hd->spec->ops->close (hd);
253
254   wipememory (hd, sizeof (*hd));
255
256   xfree (hd);
257 }
258
259
260 static gcry_error_t
261 mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
262 {
263   if (!hd->spec->ops->setkey)
264     return GPG_ERR_INV_ARG;
265   if (keylen > 0 && !key)
266     return GPG_ERR_INV_ARG;
267
268   return hd->spec->ops->setkey (hd, key, keylen);
269 }
270
271
272 static gcry_error_t
273 mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
274 {
275   if (!hd->spec->ops->setiv)
276     return GPG_ERR_INV_ARG;
277   if (ivlen > 0 && !iv)
278     return GPG_ERR_INV_ARG;
279
280   return hd->spec->ops->setiv (hd, iv, ivlen);
281 }
282
283
284 static gcry_error_t
285 mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
286 {
287   if (!hd->spec->ops->write)
288     return GPG_ERR_INV_ARG;
289   if (inlen > 0 && !inbuf)
290     return GPG_ERR_INV_ARG;
291
292   return hd->spec->ops->write (hd, inbuf, inlen);
293 }
294
295
296 static gcry_error_t
297 mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
298 {
299   if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
300     return GPG_ERR_INV_ARG;
301
302   return hd->spec->ops->read (hd, outbuf, outlen);
303 }
304
305
306 static gcry_error_t
307 mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
308 {
309   if (!buf || buflen == 0 || !hd->spec->ops->verify)
310     return GPG_ERR_INV_ARG;
311
312   return hd->spec->ops->verify (hd, buf, buflen);
313 }
314
315
316 /* Create a MAC object for algorithm ALGO.  FLAGS may be
317    given as an bitwise OR of the gcry_mac_flags values.
318    H is guaranteed to be a valid handle or NULL on error.  */
319 gpg_err_code_t
320 _gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags,
321                 gcry_ctx_t ctx)
322 {
323   gcry_err_code_t rc;
324   gcry_mac_hd_t hd = NULL;
325
326   if ((flags & ~GCRY_MAC_FLAG_SECURE))
327     rc = GPG_ERR_INV_ARG;
328   else
329     rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
330
331   *h = rc ? NULL : hd;
332   return rc;
333 }
334
335
336 void
337 _gcry_mac_close (gcry_mac_hd_t hd)
338 {
339   if (hd)
340     mac_close (hd);
341 }
342
343
344 gcry_err_code_t
345 _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
346 {
347   return mac_setkey (hd, key, keylen);
348 }
349
350
351 gcry_err_code_t
352 _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
353 {
354   return mac_setiv (hd, iv, ivlen);
355 }
356
357
358 gcry_err_code_t
359 _gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
360 {
361   return mac_write (hd, inbuf, inlen);
362 }
363
364
365 gcry_err_code_t
366 _gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
367 {
368   return mac_read (hd, outbuf, outlen);
369 }
370
371
372 gcry_err_code_t
373 _gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
374 {
375   return mac_verify (hd, buf, buflen);
376 }
377
378
379 int
380 _gcry_mac_get_algo (gcry_mac_hd_t hd)
381 {
382   return hd->algo;
383 }
384
385
386 unsigned int
387 _gcry_mac_get_algo_maclen (int algo)
388 {
389   gcry_mac_spec_t *spec;
390
391   spec = spec_from_algo (algo);
392   if (!spec || !spec->ops || !spec->ops->get_maclen)
393     return 0;
394
395   return spec->ops->get_maclen (algo);
396 }
397
398
399 unsigned int
400 _gcry_mac_get_algo_keylen (int algo)
401 {
402   gcry_mac_spec_t *spec;
403
404   spec = spec_from_algo (algo);
405   if (!spec || !spec->ops || !spec->ops->get_keylen)
406     return 0;
407
408   return spec->ops->get_keylen (algo);
409 }
410
411
412 gcry_err_code_t
413 _gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
414 {
415   gcry_err_code_t rc;
416
417   /* Currently not used.  */
418   (void) hd;
419   (void) buffer;
420   (void) buflen;
421
422   switch (cmd)
423     {
424     case GCRYCTL_RESET:
425       rc = mac_reset (hd);
426       break;
427     default:
428       rc = GPG_ERR_INV_OP;
429     }
430   return rc;
431 }
432
433
434 /* Return information about the given MAC algorithm ALGO.
435
436     GCRYCTL_TEST_ALGO:
437         Returns 0 if the specified algorithm ALGO is available for use.
438         BUFFER and NBYTES must be zero.
439
440    Note: Because this function is in most cases used to return an
441    integer value, we can make it easier for the caller to just look at
442    the return value.  The caller will in all cases consult the value
443    and thereby detecting whether a error occurred or not (i.e. while
444    checking the block size)
445  */
446 gcry_err_code_t
447 _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
448 {
449   gcry_err_code_t rc = 0;
450   unsigned int ui;
451
452   switch (what)
453     {
454     case GCRYCTL_GET_KEYLEN:
455       if (buffer || (!nbytes))
456         rc = GPG_ERR_INV_ARG;
457       else
458         {
459           ui = _gcry_mac_get_algo_keylen (algo);
460           if (ui > 0)
461             *nbytes = (size_t) ui;
462           else
463             /* The only reason for an error is an invalid algo.  */
464             rc = GPG_ERR_MAC_ALGO;
465         }
466       break;
467     case GCRYCTL_TEST_ALGO:
468       if (buffer || nbytes)
469         rc = GPG_ERR_INV_ARG;
470       else
471         rc = check_mac_algo (algo);
472       break;
473
474     default:
475       rc = GPG_ERR_INV_OP;
476     }
477
478   return rc;
479 }