Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/cipher/mac.c
Line
Count
Source (jump to first uncovered line)
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 const gcry_mac_spec_t * const 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
  &_gcry_mac_type_spec_hmac_sha512_256,
44
  &_gcry_mac_type_spec_hmac_sha512_224,
45
#endif
46
#if USE_SHA3
47
  &_gcry_mac_type_spec_hmac_sha3_224,
48
  &_gcry_mac_type_spec_hmac_sha3_256,
49
  &_gcry_mac_type_spec_hmac_sha3_384,
50
  &_gcry_mac_type_spec_hmac_sha3_512,
51
#endif
52
#if USE_GOST_R_3411_94
53
  &_gcry_mac_type_spec_hmac_gost3411_94,
54
  &_gcry_mac_type_spec_hmac_gost3411_cp,
55
#endif
56
#if USE_GOST_R_3411_12
57
  &_gcry_mac_type_spec_hmac_stribog256,
58
  &_gcry_mac_type_spec_hmac_stribog512,
59
#endif
60
#if USE_WHIRLPOOL
61
  &_gcry_mac_type_spec_hmac_whirlpool,
62
#endif
63
#if USE_RMD160
64
  &_gcry_mac_type_spec_hmac_rmd160,
65
#endif
66
#if USE_TIGER
67
  &_gcry_mac_type_spec_hmac_tiger1,
68
#endif
69
#if USE_MD5
70
  &_gcry_mac_type_spec_hmac_md5,
71
#endif
72
#if USE_MD4
73
  &_gcry_mac_type_spec_hmac_md4,
74
#endif
75
#if USE_BLAKE2
76
  &_gcry_mac_type_spec_hmac_blake2b_512,
77
  &_gcry_mac_type_spec_hmac_blake2b_384,
78
  &_gcry_mac_type_spec_hmac_blake2b_256,
79
  &_gcry_mac_type_spec_hmac_blake2b_160,
80
  &_gcry_mac_type_spec_hmac_blake2s_256,
81
  &_gcry_mac_type_spec_hmac_blake2s_224,
82
  &_gcry_mac_type_spec_hmac_blake2s_160,
83
  &_gcry_mac_type_spec_hmac_blake2s_128,
84
#endif
85
#if USE_SM3
86
  &_gcry_mac_type_spec_hmac_sm3,
87
#endif
88
#if USE_BLOWFISH
89
  &_gcry_mac_type_spec_cmac_blowfish,
90
#endif
91
#if USE_DES
92
  &_gcry_mac_type_spec_cmac_tripledes,
93
#endif
94
#if USE_CAST5
95
  &_gcry_mac_type_spec_cmac_cast5,
96
#endif
97
#if USE_AES
98
  &_gcry_mac_type_spec_cmac_aes,
99
  &_gcry_mac_type_spec_gmac_aes,
100
  &_gcry_mac_type_spec_poly1305mac_aes,
101
#endif
102
#if USE_TWOFISH
103
  &_gcry_mac_type_spec_cmac_twofish,
104
  &_gcry_mac_type_spec_gmac_twofish,
105
  &_gcry_mac_type_spec_poly1305mac_twofish,
106
#endif
107
#if USE_SERPENT
108
  &_gcry_mac_type_spec_cmac_serpent,
109
  &_gcry_mac_type_spec_gmac_serpent,
110
  &_gcry_mac_type_spec_poly1305mac_serpent,
111
#endif
112
#if USE_RFC2268
113
  &_gcry_mac_type_spec_cmac_rfc2268,
114
#endif
115
#if USE_SEED
116
  &_gcry_mac_type_spec_cmac_seed,
117
  &_gcry_mac_type_spec_gmac_seed,
118
  &_gcry_mac_type_spec_poly1305mac_seed,
119
#endif
120
#if USE_CAMELLIA
121
  &_gcry_mac_type_spec_cmac_camellia,
122
  &_gcry_mac_type_spec_gmac_camellia,
123
  &_gcry_mac_type_spec_poly1305mac_camellia,
124
#endif
125
#if USE_IDEA
126
  &_gcry_mac_type_spec_cmac_idea,
127
#endif
128
#if USE_GOST28147
129
  &_gcry_mac_type_spec_cmac_gost28147,
130
  &_gcry_mac_type_spec_gost28147_imit,
131
#endif
132
  &_gcry_mac_type_spec_poly1305mac,
133
#if USE_SM4
134
  &_gcry_mac_type_spec_cmac_sm4,
135
#endif
136
  NULL,
137
};
138
139
/* HMAC implementations start with index 101 (enum gcry_mac_algos) */
140
static const gcry_mac_spec_t * const mac_list_algo101[] =
141
  {
142
#if USE_SHA256
143
    &_gcry_mac_type_spec_hmac_sha256,
144
    &_gcry_mac_type_spec_hmac_sha224,
145
#else
146
    NULL,
147
    NULL,
148
#endif
149
#if USE_SHA512
150
    &_gcry_mac_type_spec_hmac_sha512,
151
    &_gcry_mac_type_spec_hmac_sha384,
152
#else
153
    NULL,
154
    NULL,
155
#endif
156
#if USE_SHA1
157
    &_gcry_mac_type_spec_hmac_sha1,
158
#else
159
    NULL,
160
#endif
161
#if USE_MD5
162
    &_gcry_mac_type_spec_hmac_md5,
163
#else
164
    NULL,
165
#endif
166
#if USE_MD4
167
    &_gcry_mac_type_spec_hmac_md4,
168
#else
169
    NULL,
170
#endif
171
#if USE_RMD160
172
    &_gcry_mac_type_spec_hmac_rmd160,
173
#else
174
    NULL,
175
#endif
176
#if USE_TIGER
177
    &_gcry_mac_type_spec_hmac_tiger1,
178
#else
179
    NULL,
180
#endif
181
#if USE_WHIRLPOOL
182
    &_gcry_mac_type_spec_hmac_whirlpool,
183
#else
184
    NULL,
185
#endif
186
#if USE_GOST_R_3411_94
187
    &_gcry_mac_type_spec_hmac_gost3411_94,
188
#else
189
    NULL,
190
#endif
191
#if USE_GOST_R_3411_12
192
    &_gcry_mac_type_spec_hmac_stribog256,
193
    &_gcry_mac_type_spec_hmac_stribog512,
194
#else
195
    NULL,
196
    NULL,
197
#endif
198
#if USE_MD2
199
    &_gcry_mac_type_spec_hmac_md2,
200
#else
201
    NULL,
202
#endif
203
#if USE_SHA3
204
    &_gcry_mac_type_spec_hmac_sha3_224,
205
    &_gcry_mac_type_spec_hmac_sha3_256,
206
    &_gcry_mac_type_spec_hmac_sha3_384,
207
    &_gcry_mac_type_spec_hmac_sha3_512,
208
#else
209
    NULL,
210
    NULL,
211
    NULL,
212
    NULL,
213
#endif
214
#if USE_GOST_R_3411_94
215
    &_gcry_mac_type_spec_hmac_gost3411_cp,
216
#else
217
    NULL,
218
#endif
219
#if USE_BLAKE2
220
    &_gcry_mac_type_spec_hmac_blake2b_512,
221
    &_gcry_mac_type_spec_hmac_blake2b_384,
222
    &_gcry_mac_type_spec_hmac_blake2b_256,
223
    &_gcry_mac_type_spec_hmac_blake2b_160,
224
    &_gcry_mac_type_spec_hmac_blake2s_256,
225
    &_gcry_mac_type_spec_hmac_blake2s_224,
226
    &_gcry_mac_type_spec_hmac_blake2s_160,
227
    &_gcry_mac_type_spec_hmac_blake2s_128,
228
#else
229
    NULL,
230
    NULL,
231
    NULL,
232
    NULL,
233
    NULL,
234
    NULL,
235
    NULL,
236
    NULL,
237
#endif
238
#if USE_SM3
239
    &_gcry_mac_type_spec_hmac_sm3,
240
#else
241
    NULL,
242
#endif
243
#if USE_SHA512
244
    &_gcry_mac_type_spec_hmac_sha512_256,
245
    &_gcry_mac_type_spec_hmac_sha512_224,
246
#else
247
    NULL,
248
    NULL,
249
#endif
250
  };
251
252
/* CMAC implementations start with index 201 (enum gcry_mac_algos) */
253
static const gcry_mac_spec_t * const mac_list_algo201[] =
254
  {
255
#if USE_AES
256
    &_gcry_mac_type_spec_cmac_aes,
257
#else
258
    NULL,
259
#endif
260
#if USE_DES
261
    &_gcry_mac_type_spec_cmac_tripledes,
262
#else
263
    NULL,
264
#endif
265
#if USE_CAMELLIA
266
    &_gcry_mac_type_spec_cmac_camellia,
267
#else
268
    NULL,
269
#endif
270
#if USE_CAST5
271
    &_gcry_mac_type_spec_cmac_cast5,
272
#else
273
    NULL,
274
#endif
275
#if USE_BLOWFISH
276
    &_gcry_mac_type_spec_cmac_blowfish,
277
#else
278
    NULL,
279
#endif
280
#if USE_TWOFISH
281
    &_gcry_mac_type_spec_cmac_twofish,
282
#else
283
    NULL,
284
#endif
285
#if USE_SERPENT
286
    &_gcry_mac_type_spec_cmac_serpent,
287
#else
288
    NULL,
289
#endif
290
#if USE_SEED
291
    &_gcry_mac_type_spec_cmac_seed,
292
#else
293
    NULL,
294
#endif
295
#if USE_RFC2268
296
    &_gcry_mac_type_spec_cmac_rfc2268,
297
#else
298
    NULL,
299
#endif
300
#if USE_IDEA
301
    &_gcry_mac_type_spec_cmac_idea,
302
#else
303
    NULL,
304
#endif
305
#if USE_GOST28147
306
    &_gcry_mac_type_spec_cmac_gost28147,
307
#else
308
    NULL,
309
#endif
310
#if USE_SM4
311
    &_gcry_mac_type_spec_cmac_sm4
312
#else
313
    NULL
314
#endif
315
  };
316
317
/* GMAC implementations start with index 401 (enum gcry_mac_algos) */
318
static const gcry_mac_spec_t * const mac_list_algo401[] =
319
  {
320
#if USE_AES
321
    &_gcry_mac_type_spec_gmac_aes,
322
#else
323
    NULL,
324
#endif
325
#if USE_CAMELLIA
326
    &_gcry_mac_type_spec_gmac_camellia,
327
#else
328
    NULL,
329
#endif
330
#if USE_TWOFISH
331
    &_gcry_mac_type_spec_gmac_twofish,
332
#else
333
    NULL,
334
#endif
335
#if USE_SERPENT
336
    &_gcry_mac_type_spec_gmac_serpent,
337
#else
338
    NULL,
339
#endif
340
#if USE_SEED
341
    &_gcry_mac_type_spec_gmac_seed
342
#else
343
    NULL
344
#endif
345
  };
346
347
/* Poly1305-MAC implementations start with index 501 (enum gcry_mac_algos) */
348
static const gcry_mac_spec_t * const mac_list_algo501[] =
349
  {
350
    &_gcry_mac_type_spec_poly1305mac,
351
#if USE_AES
352
    &_gcry_mac_type_spec_poly1305mac_aes,
353
#else
354
    NULL,
355
#endif
356
#if USE_CAMELLIA
357
    &_gcry_mac_type_spec_poly1305mac_camellia,
358
#else
359
    NULL,
360
#endif
361
#if USE_TWOFISH
362
    &_gcry_mac_type_spec_poly1305mac_twofish,
363
#else
364
    NULL,
365
#endif
366
#if USE_SERPENT
367
    &_gcry_mac_type_spec_poly1305mac_serpent,
368
#else
369
    NULL,
370
#endif
371
#if USE_SEED
372
    &_gcry_mac_type_spec_poly1305mac_seed
373
#else
374
    NULL
375
#endif
376
  };
377
378
379
380
381
/* Explicitly initialize this module.  */
382
gcry_err_code_t
383
_gcry_mac_init (void)
384
1
{
385
1
  return 0;
386
1
}
387
388

389
/* Return the spec structure for the MAC algorithm ALGO.  For an
390
   unknown algorithm NULL is returned.  */
391
static const gcry_mac_spec_t *
392
spec_from_algo (int algo)
393
0
{
394
0
  const gcry_mac_spec_t *spec = NULL;
395
396
0
  if (algo >= 101 && algo < 101 + DIM(mac_list_algo101))
397
0
    spec = mac_list_algo101[algo - 101];
398
0
  else if (algo >= 201 && algo < 201 + DIM(mac_list_algo201))
399
0
    spec = mac_list_algo201[algo - 201];
400
0
  else if (algo >= 401 && algo < 401 + DIM(mac_list_algo401))
401
0
    spec = mac_list_algo401[algo - 401];
402
0
  else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501))
403
0
    spec = mac_list_algo501[algo - 501];
404
0
#if USE_GOST28147
405
0
  else if (algo == GCRY_MAC_GOST28147_IMIT)
406
0
    spec = &_gcry_mac_type_spec_gost28147_imit;
407
0
#endif
408
409
0
  if (spec)
410
0
    gcry_assert (spec->algo == algo);
411
412
0
  return spec;
413
0
}
414
415
416
/* Lookup a mac's spec by its name.  */
417
static const gcry_mac_spec_t *
418
spec_from_name (const char *name)
419
0
{
420
0
  const gcry_mac_spec_t *spec;
421
0
  int idx;
422
423
0
  for (idx = 0; (spec = mac_list[idx]); idx++)
424
0
    if (!stricmp (name, spec->name))
425
0
      return spec;
426
427
0
  return NULL;
428
0
}
429
430
431
/****************
432
 * Map a string to the mac algo
433
 */
434
int
435
_gcry_mac_map_name (const char *string)
436
0
{
437
0
  const gcry_mac_spec_t *spec;
438
439
0
  if (!string)
440
0
    return 0;
441
442
  /* Not found, search a matching mac name.  */
443
0
  spec = spec_from_name (string);
444
0
  if (spec)
445
0
    return spec->algo;
446
447
0
  return 0;
448
0
}
449
450
451
/****************
452
 * This function simply returns the name of the algorithm or some constant
453
 * string when there is no algo.  It will never return NULL.
454
 * Use the macro gcry_mac_test_algo() to check whether the algorithm
455
 * is valid.
456
 */
457
const char *
458
_gcry_mac_algo_name (int algorithm)
459
0
{
460
0
  const gcry_mac_spec_t *spec;
461
462
0
  spec = spec_from_algo (algorithm);
463
0
  return spec ? spec->name : "?";
464
0
}
465
466
467
static gcry_err_code_t
468
check_mac_algo (int algorithm)
469
0
{
470
0
  const gcry_mac_spec_t *spec;
471
472
0
  spec = spec_from_algo (algorithm);
473
0
  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
474
0
    return 0;
475
476
0
  return GPG_ERR_MAC_ALGO;
477
0
}
478
479
480
/****************
481
 * Open a message digest handle for use with algorithm ALGO.
482
 */
483
static gcry_err_code_t
484
mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
485
0
{
486
0
  const gcry_mac_spec_t *spec;
487
0
  gcry_err_code_t err;
488
0
  gcry_mac_hd_t h;
489
490
0
  spec = spec_from_algo (algo);
491
0
  if (!spec)
492
0
    return GPG_ERR_MAC_ALGO;
493
0
  else if (spec->flags.disabled)
494
0
    return GPG_ERR_MAC_ALGO;
495
0
  else if (!spec->flags.fips && fips_mode ())
496
0
    return GPG_ERR_MAC_ALGO;
497
0
  else if (!spec->ops)
498
0
    return GPG_ERR_MAC_ALGO;
499
0
  else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
500
0
           !spec->ops->read || !spec->ops->verify || !spec->ops->reset)
501
0
    return GPG_ERR_MAC_ALGO;
502
503
0
  if (secure)
504
0
    h = xtrycalloc_secure (1, sizeof (*h));
505
0
  else
506
0
    h = xtrycalloc (1, sizeof (*h));
507
508
0
  if (!h)
509
0
    return gpg_err_code_from_syserror ();
510
511
0
  h->magic = secure ? CTX_MAC_MAGIC_SECURE : CTX_MAC_MAGIC_NORMAL;
512
0
  h->spec = spec;
513
0
  h->algo = algo;
514
0
  h->gcry_ctx = ctx;
515
516
0
  err = h->spec->ops->open (h);
517
0
  if (err)
518
0
    xfree (h);
519
0
  else
520
0
    *hd = h;
521
522
0
  return err;
523
0
}
524
525
526
static gcry_err_code_t
527
mac_reset (gcry_mac_hd_t hd)
528
0
{
529
0
  if (hd->spec->ops->reset)
530
0
    return hd->spec->ops->reset (hd);
531
532
0
  return 0;
533
0
}
534
535
536
static void
537
mac_close (gcry_mac_hd_t hd)
538
0
{
539
0
  if (hd->spec->ops->close)
540
0
    hd->spec->ops->close (hd);
541
542
0
  wipememory (hd, sizeof (*hd));
543
544
0
  xfree (hd);
545
0
}
546
547
548
static gcry_err_code_t
549
mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
550
0
{
551
0
  if (!hd->spec->ops->setkey)
552
0
    return GPG_ERR_INV_ARG;
553
0
  if (keylen > 0 && !key)
554
0
    return GPG_ERR_INV_ARG;
555
556
0
  return hd->spec->ops->setkey (hd, key, keylen);
557
0
}
558
559
560
static gcry_err_code_t
561
mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
562
0
{
563
0
  if (!hd->spec->ops->setiv)
564
0
    return GPG_ERR_INV_ARG;
565
0
  if (ivlen > 0 && !iv)
566
0
    return GPG_ERR_INV_ARG;
567
568
0
  return hd->spec->ops->setiv (hd, iv, ivlen);
569
0
}
570
571
572
static gcry_err_code_t
573
mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
574
0
{
575
0
  if (!hd->spec->ops->write)
576
0
    return GPG_ERR_INV_ARG;
577
0
  if (inlen > 0 && !inbuf)
578
0
    return GPG_ERR_INV_ARG;
579
580
0
  return hd->spec->ops->write (hd, inbuf, inlen);
581
0
}
582
583
584
static gcry_err_code_t
585
mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
586
0
{
587
0
  if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
588
0
    return GPG_ERR_INV_ARG;
589
590
0
  return hd->spec->ops->read (hd, outbuf, outlen);
591
0
}
592
593
594
static gcry_err_code_t
595
mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
596
0
{
597
0
  if (!buf || buflen == 0 || !hd->spec->ops->verify)
598
0
    return GPG_ERR_INV_ARG;
599
600
0
  return hd->spec->ops->verify (hd, buf, buflen);
601
0
}
602
603
604
/* Create a MAC object for algorithm ALGO.  FLAGS may be
605
   given as an bitwise OR of the gcry_mac_flags values.
606
   H is guaranteed to be a valid handle or NULL on error.  */
607
gpg_err_code_t
608
_gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags,
609
                gcry_ctx_t ctx)
610
0
{
611
0
  gcry_err_code_t rc;
612
0
  gcry_mac_hd_t hd = NULL;
613
614
0
  if ((flags & ~GCRY_MAC_FLAG_SECURE))
615
0
    rc = GPG_ERR_INV_ARG;
616
0
  else
617
0
    rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
618
619
0
  *h = rc ? NULL : hd;
620
0
  return rc;
621
0
}
622
623
624
void
625
_gcry_mac_close (gcry_mac_hd_t hd)
626
0
{
627
0
  if (hd)
628
0
    mac_close (hd);
629
0
}
630
631
632
gcry_err_code_t
633
_gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
634
0
{
635
0
  return mac_setkey (hd, key, keylen);
636
0
}
637
638
639
gcry_err_code_t
640
_gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
641
0
{
642
0
  return mac_setiv (hd, iv, ivlen);
643
0
}
644
645
646
gcry_err_code_t
647
_gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
648
0
{
649
0
  return mac_write (hd, inbuf, inlen);
650
0
}
651
652
653
gcry_err_code_t
654
_gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
655
0
{
656
0
  return mac_read (hd, outbuf, outlen);
657
0
}
658
659
660
gcry_err_code_t
661
_gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
662
0
{
663
0
  return mac_verify (hd, buf, buflen);
664
0
}
665
666
667
int
668
_gcry_mac_get_algo (gcry_mac_hd_t hd)
669
0
{
670
0
  return hd->algo;
671
0
}
672
673
674
unsigned int
675
_gcry_mac_get_algo_maclen (int algo)
676
0
{
677
0
  const gcry_mac_spec_t *spec;
678
679
0
  spec = spec_from_algo (algo);
680
0
  if (!spec || !spec->ops || !spec->ops->get_maclen)
681
0
    return 0;
682
683
0
  return spec->ops->get_maclen (algo);
684
0
}
685
686
687
unsigned int
688
_gcry_mac_get_algo_keylen (int algo)
689
0
{
690
0
  const gcry_mac_spec_t *spec;
691
692
0
  spec = spec_from_algo (algo);
693
0
  if (!spec || !spec->ops || !spec->ops->get_keylen)
694
0
    return 0;
695
696
0
  return spec->ops->get_keylen (algo);
697
0
}
698
699
700
gcry_err_code_t
701
_gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
702
0
{
703
0
  gcry_err_code_t rc;
704
705
  /* Currently not used.  */
706
0
  (void) hd;
707
0
  (void) buffer;
708
0
  (void) buflen;
709
710
0
  switch (cmd)
711
0
    {
712
0
    case GCRYCTL_RESET:
713
0
      rc = mac_reset (hd);
714
0
      break;
715
0
    case GCRYCTL_SET_SBOX:
716
0
      if (hd->spec->ops->set_extra_info)
717
0
        rc = hd->spec->ops->set_extra_info
718
0
          (hd, GCRYCTL_SET_SBOX, buffer, buflen);
719
0
      else
720
0
        rc = GPG_ERR_NOT_SUPPORTED;
721
0
      break;
722
0
    default:
723
0
      rc = GPG_ERR_INV_OP;
724
0
    }
725
0
  return rc;
726
0
}
727
728
729
/* Return information about the given MAC algorithm ALGO.
730
731
    GCRYCTL_TEST_ALGO:
732
        Returns 0 if the specified algorithm ALGO is available for use.
733
        BUFFER and NBYTES must be zero.
734
735
   Note: Because this function is in most cases used to return an
736
   integer value, we can make it easier for the caller to just look at
737
   the return value.  The caller will in all cases consult the value
738
   and thereby detecting whether a error occurred or not (i.e. while
739
   checking the block size)
740
 */
741
gcry_err_code_t
742
_gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
743
0
{
744
0
  gcry_err_code_t rc = 0;
745
0
  unsigned int ui;
746
747
0
  switch (what)
748
0
    {
749
0
    case GCRYCTL_GET_KEYLEN:
750
0
      if (buffer || (!nbytes))
751
0
        rc = GPG_ERR_INV_ARG;
752
0
      else
753
0
        {
754
0
          ui = _gcry_mac_get_algo_keylen (algo);
755
0
          if (ui > 0)
756
0
            *nbytes = (size_t) ui;
757
0
          else
758
            /* The only reason for an error is an invalid algo.  */
759
0
            rc = GPG_ERR_MAC_ALGO;
760
0
        }
761
0
      break;
762
0
    case GCRYCTL_TEST_ALGO:
763
0
      if (buffer || nbytes)
764
0
        rc = GPG_ERR_INV_ARG;
765
0
      else
766
0
        rc = check_mac_algo (algo);
767
0
      break;
768
769
0
    default:
770
0
      rc = GPG_ERR_INV_OP;
771
0
    }
772
773
0
  return rc;
774
0
}
775
776
777
/* Run the self-tests for the MAC.  */
778
gpg_error_t
779
_gcry_mac_selftest (int algo, int extended, selftest_report_func_t report)
780
0
{
781
0
  gcry_err_code_t ec;
782
0
  const gcry_mac_spec_t *spec;
783
784
0
  spec = spec_from_algo (algo);
785
0
  if (spec && !spec->flags.disabled
786
0
      && (spec->flags.fips || !fips_mode ())
787
0
      && spec->ops && spec->ops->selftest)
788
0
    ec = spec->ops->selftest (algo, extended, report);
789
0
  else
790
0
    {
791
0
      ec = GPG_ERR_MAC_ALGO;
792
0
      if (report)
793
0
        report ("mac", algo, "module",
794
0
                spec && !spec->flags.disabled
795
0
                && (spec->flags.fips || !fips_mode ())?
796
0
                "no selftest available" :
797
0
                spec? "algorithm disabled" :
798
0
                "algorithm not found");
799
0
    }
800
801
0
  return gpg_error (ec);
802
0
}