Line data Source code
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 0 : _gcry_mac_init (void)
122 : {
123 0 : if (fips_mode())
124 : {
125 : /* disable algorithms that are disallowed in fips */
126 : int idx;
127 : gcry_mac_spec_t *spec;
128 :
129 0 : for (idx = 0; (spec = mac_list[idx]); idx++)
130 0 : if (!spec->flags.fips)
131 0 : spec->flags.disabled = 1;
132 : }
133 :
134 0 : return 0;
135 : }
136 :
137 :
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 0 : spec_from_algo (int algo)
142 : {
143 : gcry_mac_spec_t *spec;
144 : int idx;
145 :
146 0 : for (idx = 0; (spec = mac_list[idx]); idx++)
147 0 : if (algo == spec->algo)
148 0 : return spec;
149 0 : return NULL;
150 : }
151 :
152 :
153 : /* Lookup a mac's spec by its name. */
154 : static gcry_mac_spec_t *
155 0 : spec_from_name (const char *name)
156 : {
157 : gcry_mac_spec_t *spec;
158 : int idx;
159 :
160 0 : for (idx = 0; (spec = mac_list[idx]); idx++)
161 0 : if (!stricmp (name, spec->name))
162 0 : return spec;
163 :
164 0 : return NULL;
165 : }
166 :
167 :
168 : /****************
169 : * Map a string to the mac algo
170 : */
171 : int
172 0 : _gcry_mac_map_name (const char *string)
173 : {
174 : gcry_mac_spec_t *spec;
175 :
176 0 : if (!string)
177 0 : return 0;
178 :
179 : /* Not found, search a matching mac name. */
180 0 : spec = spec_from_name (string);
181 0 : if (spec)
182 0 : return spec->algo;
183 :
184 0 : 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 0 : _gcry_mac_algo_name (int algorithm)
196 : {
197 : gcry_mac_spec_t *spec;
198 :
199 0 : spec = spec_from_algo (algorithm);
200 0 : return spec ? spec->name : "?";
201 : }
202 :
203 :
204 : static gcry_err_code_t
205 0 : check_mac_algo (int algorithm)
206 : {
207 : gcry_mac_spec_t *spec;
208 :
209 0 : spec = spec_from_algo (algorithm);
210 0 : if (spec && !spec->flags.disabled)
211 0 : return 0;
212 :
213 0 : 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 0 : 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 0 : spec = spec_from_algo (algo);
228 0 : if (!spec)
229 0 : return GPG_ERR_MAC_ALGO;
230 0 : else if (spec->flags.disabled)
231 0 : return GPG_ERR_MAC_ALGO;
232 0 : else if (!spec->ops)
233 0 : return GPG_ERR_MAC_ALGO;
234 0 : else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
235 0 : !spec->ops->read || !spec->ops->verify || !spec->ops->reset)
236 0 : return GPG_ERR_MAC_ALGO;
237 :
238 0 : if (secure)
239 0 : h = xtrycalloc_secure (1, sizeof (*h));
240 : else
241 0 : h = xtrycalloc (1, sizeof (*h));
242 :
243 0 : if (!h)
244 0 : return gpg_err_code_from_syserror ();
245 :
246 0 : h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
247 0 : h->spec = spec;
248 0 : h->algo = algo;
249 0 : h->gcry_ctx = ctx;
250 :
251 0 : err = h->spec->ops->open (h);
252 0 : if (err)
253 0 : xfree (h);
254 : else
255 0 : *hd = h;
256 :
257 0 : return err;
258 : }
259 :
260 :
261 : static gcry_err_code_t
262 0 : mac_reset (gcry_mac_hd_t hd)
263 : {
264 0 : if (hd->spec->ops->reset)
265 0 : return hd->spec->ops->reset (hd);
266 :
267 0 : return 0;
268 : }
269 :
270 :
271 : static void
272 0 : mac_close (gcry_mac_hd_t hd)
273 : {
274 0 : if (hd->spec->ops->close)
275 0 : hd->spec->ops->close (hd);
276 :
277 0 : wipememory (hd, sizeof (*hd));
278 :
279 0 : xfree (hd);
280 0 : }
281 :
282 :
283 : static gcry_err_code_t
284 0 : mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
285 : {
286 0 : if (!hd->spec->ops->setkey)
287 0 : return GPG_ERR_INV_ARG;
288 0 : if (keylen > 0 && !key)
289 0 : return GPG_ERR_INV_ARG;
290 :
291 0 : return hd->spec->ops->setkey (hd, key, keylen);
292 : }
293 :
294 :
295 : static gcry_err_code_t
296 0 : mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
297 : {
298 0 : if (!hd->spec->ops->setiv)
299 0 : return GPG_ERR_INV_ARG;
300 0 : if (ivlen > 0 && !iv)
301 0 : return GPG_ERR_INV_ARG;
302 :
303 0 : return hd->spec->ops->setiv (hd, iv, ivlen);
304 : }
305 :
306 :
307 : static gcry_err_code_t
308 0 : mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
309 : {
310 0 : if (!hd->spec->ops->write)
311 0 : return GPG_ERR_INV_ARG;
312 0 : if (inlen > 0 && !inbuf)
313 0 : return GPG_ERR_INV_ARG;
314 :
315 0 : return hd->spec->ops->write (hd, inbuf, inlen);
316 : }
317 :
318 :
319 : static gcry_err_code_t
320 0 : mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
321 : {
322 0 : if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
323 0 : return GPG_ERR_INV_ARG;
324 :
325 0 : return hd->spec->ops->read (hd, outbuf, outlen);
326 : }
327 :
328 :
329 : static gcry_err_code_t
330 0 : mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
331 : {
332 0 : if (!buf || buflen == 0 || !hd->spec->ops->verify)
333 0 : return GPG_ERR_INV_ARG;
334 :
335 0 : 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 0 : _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 0 : gcry_mac_hd_t hd = NULL;
348 :
349 0 : if ((flags & ~GCRY_MAC_FLAG_SECURE))
350 0 : rc = GPG_ERR_INV_ARG;
351 : else
352 0 : rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
353 :
354 0 : *h = rc ? NULL : hd;
355 0 : return rc;
356 : }
357 :
358 :
359 : void
360 0 : _gcry_mac_close (gcry_mac_hd_t hd)
361 : {
362 0 : if (hd)
363 0 : mac_close (hd);
364 0 : }
365 :
366 :
367 : gcry_err_code_t
368 0 : _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
369 : {
370 0 : return mac_setkey (hd, key, keylen);
371 : }
372 :
373 :
374 : gcry_err_code_t
375 0 : _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
376 : {
377 0 : return mac_setiv (hd, iv, ivlen);
378 : }
379 :
380 :
381 : gcry_err_code_t
382 0 : _gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
383 : {
384 0 : return mac_write (hd, inbuf, inlen);
385 : }
386 :
387 :
388 : gcry_err_code_t
389 0 : _gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
390 : {
391 0 : return mac_read (hd, outbuf, outlen);
392 : }
393 :
394 :
395 : gcry_err_code_t
396 0 : _gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
397 : {
398 0 : return mac_verify (hd, buf, buflen);
399 : }
400 :
401 :
402 : int
403 0 : _gcry_mac_get_algo (gcry_mac_hd_t hd)
404 : {
405 0 : return hd->algo;
406 : }
407 :
408 :
409 : unsigned int
410 0 : _gcry_mac_get_algo_maclen (int algo)
411 : {
412 : gcry_mac_spec_t *spec;
413 :
414 0 : spec = spec_from_algo (algo);
415 0 : if (!spec || !spec->ops || !spec->ops->get_maclen)
416 0 : return 0;
417 :
418 0 : return spec->ops->get_maclen (algo);
419 : }
420 :
421 :
422 : unsigned int
423 0 : _gcry_mac_get_algo_keylen (int algo)
424 : {
425 : gcry_mac_spec_t *spec;
426 :
427 0 : spec = spec_from_algo (algo);
428 0 : if (!spec || !spec->ops || !spec->ops->get_keylen)
429 0 : return 0;
430 :
431 0 : return spec->ops->get_keylen (algo);
432 : }
433 :
434 :
435 : gcry_err_code_t
436 0 : _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 0 : switch (cmd)
446 : {
447 : case GCRYCTL_RESET:
448 0 : rc = mac_reset (hd);
449 0 : break;
450 : default:
451 0 : rc = GPG_ERR_INV_OP;
452 : }
453 0 : 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 0 : _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
471 : {
472 0 : gcry_err_code_t rc = 0;
473 : unsigned int ui;
474 :
475 0 : switch (what)
476 : {
477 : case GCRYCTL_GET_KEYLEN:
478 0 : if (buffer || (!nbytes))
479 0 : rc = GPG_ERR_INV_ARG;
480 : else
481 : {
482 0 : ui = _gcry_mac_get_algo_keylen (algo);
483 0 : if (ui > 0)
484 0 : *nbytes = (size_t) ui;
485 : else
486 : /* The only reason for an error is an invalid algo. */
487 0 : rc = GPG_ERR_MAC_ALGO;
488 : }
489 0 : break;
490 : case GCRYCTL_TEST_ALGO:
491 0 : if (buffer || nbytes)
492 0 : rc = GPG_ERR_INV_ARG;
493 : else
494 0 : rc = check_mac_algo (algo);
495 0 : break;
496 :
497 : default:
498 0 : rc = GPG_ERR_INV_OP;
499 : }
500 :
501 0 : return rc;
502 : }
|