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