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