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