Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/algorithms/mac.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2017 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include <algorithms.h>
26
#include "errors.h"
27
#include <x509/common.h>
28
#include "c-strcase.h"
29
30
#define MAC_OID_SHA1 "1.2.840.113549.2.7"
31
#define MAC_OID_SHA224 "1.2.840.113549.2.8"
32
#define MAC_OID_SHA256 "1.2.840.113549.2.9"
33
#define MAC_OID_SHA384 "1.2.840.113549.2.10"
34
#define MAC_OID_SHA512 "1.2.840.113549.2.11"
35
#define MAC_OID_GOST_R_3411_94 "1.2.643.2.2.10"
36
#define MAC_OID_STREEBOG_256 "1.2.643.7.1.1.4.1"
37
#define MAC_OID_STREEBOG_512 "1.2.643.7.1.1.4.2"
38
39
static SYSTEM_CONFIG_OR_CONST mac_entry_st hash_algorithms[] = {
40
  {.name = "SHA1",
41
   .oid = HASH_OID_SHA1,
42
   .mac_oid = MAC_OID_SHA1,
43
   .id = GNUTLS_MAC_SHA1,
44
   .output_size = 20,
45
   .key_size = 20,
46
   .block_size = 64},
47
  {.name = "MD5+SHA1",
48
   .id = GNUTLS_MAC_MD5_SHA1,
49
   .output_size = 36,
50
   .key_size = 36,
51
   .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE,
52
   .block_size = 64},
53
  {.name = "SHA256",
54
   .oid = HASH_OID_SHA256,
55
   .mac_oid = MAC_OID_SHA256,
56
   .id = GNUTLS_MAC_SHA256,
57
   .output_size = 32,
58
   .key_size = 32,
59
   .block_size = 64},
60
  {.name = "SHA384",
61
   .oid = HASH_OID_SHA384,
62
   .mac_oid = MAC_OID_SHA384,
63
   .id = GNUTLS_MAC_SHA384,
64
   .output_size = 48,
65
   .key_size = 48,
66
   .block_size = 128},
67
  {.name = "SHA512",
68
   .oid = HASH_OID_SHA512,
69
   .mac_oid = MAC_OID_SHA512,
70
   .id = GNUTLS_MAC_SHA512,
71
   .output_size = 64,
72
   .key_size = 64,
73
   .block_size = 128},
74
  {.name = "SHA224",
75
   .oid = HASH_OID_SHA224,
76
   .mac_oid = MAC_OID_SHA224,
77
   .id = GNUTLS_MAC_SHA224,
78
   .output_size = 28,
79
   .key_size = 28,
80
   .block_size = 64},
81
  {.name = "SHA3-256",
82
   .oid = HASH_OID_SHA3_256,
83
   .id = GNUTLS_MAC_SHA3_256,
84
   .output_size = 32,
85
   .key_size = 32,
86
   .block_size = 136},
87
  {.name = "SHA3-384",
88
   .oid = HASH_OID_SHA3_384,
89
   .id = GNUTLS_MAC_SHA3_384,
90
   .output_size = 48,
91
   .key_size = 48,
92
   .block_size = 104},
93
  {.name = "SHA3-512",
94
   .oid = HASH_OID_SHA3_512,
95
   .id = GNUTLS_MAC_SHA3_512,
96
   .output_size = 64,
97
   .key_size = 64,
98
   .block_size = 72},
99
  {.name = "SHA3-224",
100
   .oid = HASH_OID_SHA3_224,
101
   .id = GNUTLS_MAC_SHA3_224,
102
   .output_size = 28,
103
   .key_size = 28,
104
   .block_size = 144},
105
  {.name = "UMAC-96",
106
   .id = GNUTLS_MAC_UMAC_96,
107
   .output_size = 12,
108
   .key_size = 16,
109
   .nonce_size = 8},
110
  {.name = "UMAC-128",
111
   .id = GNUTLS_MAC_UMAC_128,
112
   .output_size = 16,
113
   .key_size = 16,
114
   .nonce_size = 8},
115
  {.name = "AEAD",
116
   .id = GNUTLS_MAC_AEAD,
117
   .placeholder = 1},
118
  {.name = "MD5",
119
   .oid = HASH_OID_MD5,
120
   .id = GNUTLS_MAC_MD5,
121
   .output_size = 16,
122
   .key_size = 16,
123
   .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE,
124
   .block_size = 64},
125
  {.name = "MD2",
126
   .oid = HASH_OID_MD2,
127
   .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE,
128
   .id = GNUTLS_MAC_MD2},
129
  {.name = "RIPEMD160",
130
   .oid = HASH_OID_RMD160,
131
   .id = GNUTLS_MAC_RMD160,
132
   .output_size = 20,
133
   .key_size = 20,
134
   .block_size = 64},
135
  {.name = "GOSTR341194",
136
   .oid = HASH_OID_GOST_R_3411_94,
137
   .mac_oid = MAC_OID_GOST_R_3411_94,
138
   .id = GNUTLS_MAC_GOSTR_94,
139
   .output_size = 32,
140
   .key_size = 32,
141
   .block_size = 32,
142
   .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE},
143
  {.name = "STREEBOG-256",
144
   .oid = HASH_OID_STREEBOG_256,
145
   .mac_oid = MAC_OID_STREEBOG_256,
146
   .id = GNUTLS_MAC_STREEBOG_256,
147
   .output_size = 32,
148
   .key_size = 32,
149
   .block_size = 64},
150
  {.name = "STREEBOG-512",
151
   .oid = HASH_OID_STREEBOG_512,
152
   .mac_oid = MAC_OID_STREEBOG_512,
153
   .id = GNUTLS_MAC_STREEBOG_512,
154
   .output_size = 64,
155
   .key_size = 64,
156
   .block_size = 64},
157
  {.name = "AES-CMAC-128",
158
   .id = GNUTLS_MAC_AES_CMAC_128,
159
   .output_size = 16,
160
   .key_size = 16,},
161
  {.name = "AES-CMAC-256",
162
   .id = GNUTLS_MAC_AES_CMAC_256,
163
   .output_size = 16,
164
   .key_size = 32},
165
  {.name = "AES-GMAC-128",
166
   .id = GNUTLS_MAC_AES_GMAC_128,
167
   .output_size = 16,
168
   .key_size = 16,
169
   .nonce_size = 12},
170
  {.name = "AES-GMAC-192",
171
   .id = GNUTLS_MAC_AES_GMAC_192,
172
   .output_size = 16,
173
   .key_size = 24,
174
   .nonce_size = 12},
175
  {.name = "AES-GMAC-256",
176
   .id = GNUTLS_MAC_AES_GMAC_256,
177
   .output_size = 16,
178
   .key_size = 32,
179
   .nonce_size = 12},
180
  {.name = "GOST28147-TC26Z-IMIT",
181
   .id = GNUTLS_MAC_GOST28147_TC26Z_IMIT,
182
   .output_size = 4,
183
   .key_size = 32,
184
   .block_size = 8,
185
   .flags = GNUTLS_MAC_FLAG_CONTINUOUS_MAC},
186
  {.name = "SHAKE-128",
187
   .oid = HASH_OID_SHAKE_128,
188
   .id = GNUTLS_MAC_SHAKE_128,
189
   .block_size = 168},
190
  {.name = "SHAKE-256",
191
   .oid = HASH_OID_SHAKE_256,
192
   .id = GNUTLS_MAC_SHAKE_256,
193
   .block_size = 136},
194
  {.name = "OMAC-MAGMA",
195
   .id = GNUTLS_MAC_MAGMA_OMAC,
196
   .output_size = 8,
197
   .key_size = 32,
198
   .block_size = 8},
199
  {.name = "OMAC-KUZNYECHIK",
200
   .id = GNUTLS_MAC_KUZNYECHIK_OMAC,
201
   .output_size = 16,
202
   .key_size = 32,
203
   .block_size = 16},
204
  {.name = "MAC-NULL",
205
   .id = GNUTLS_MAC_NULL},
206
  {0, 0, 0, 0, 0, 0, 0, 0, 0}
207
};
208
209
#define GNUTLS_HASH_LOOP(b) \
210
0
  const mac_entry_st *p; \
211
0
    for(p = hash_algorithms; p->name != NULL; p++) { b ; }
212
213
#define GNUTLS_HASH_ALG_LOOP(a) \
214
0
      GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } )
215
216
const mac_entry_st *_gnutls_mac_to_entry(gnutls_mac_algorithm_t c)
217
0
{
218
0
  GNUTLS_HASH_LOOP(if (c == p->id) return p) ;
219
220
0
  return NULL;
221
0
}
222
223
/**
224
 * gnutls_mac_get_name:
225
 * @algorithm: is a MAC algorithm
226
 *
227
 * Convert a #gnutls_mac_algorithm_t value to a string.
228
 *
229
 * Returns: a string that contains the name of the specified MAC
230
 *   algorithm, or %NULL.
231
 **/
232
const char *gnutls_mac_get_name(gnutls_mac_algorithm_t algorithm)
233
0
{
234
0
  const char *ret = NULL;
235
236
  /* avoid prefix */
237
0
  GNUTLS_HASH_ALG_LOOP(ret = p->name);
238
239
0
  return ret;
240
0
}
241
242
/**
243
 * gnutls_digest_get_name:
244
 * @algorithm: is a digest algorithm
245
 *
246
 * Convert a #gnutls_digest_algorithm_t value to a string.
247
 *
248
 * Returns: a string that contains the name of the specified digest
249
 *   algorithm, or %NULL.
250
 **/
251
const char *gnutls_digest_get_name(gnutls_digest_algorithm_t algorithm)
252
0
{
253
0
  const char *ret = NULL;
254
255
0
  GNUTLS_HASH_LOOP(if (algorithm == (unsigned)p->id && p->oid != NULL) {
256
0
       ret = p->name; break;}
257
0
  ) ;
258
259
0
  return ret;
260
0
}
261
262
/**
263
 * gnutls_digest_get_id:
264
 * @name: is a digest algorithm name
265
 *
266
 * Convert a string to a #gnutls_digest_algorithm_t value.  The names are
267
 * compared in a case insensitive way.
268
 *
269
 * Returns: a #gnutls_digest_algorithm_t id of the specified MAC
270
 *   algorithm string, or %GNUTLS_DIG_UNKNOWN on failure.
271
 **/
272
gnutls_digest_algorithm_t gnutls_digest_get_id(const char *name)
273
0
{
274
0
  gnutls_digest_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
275
276
0
  GNUTLS_HASH_LOOP(if (p->oid != NULL && c_strcasecmp(p->name, name) == 0) {
277
0
       if (_gnutls_digest_exists
278
0
           ((gnutls_digest_algorithm_t) p->id))
279
0
       ret = (gnutls_digest_algorithm_t) p->id; break;}
280
0
  ) ;
281
282
0
  return ret;
283
0
}
284
285
/* This is only called by cfg_apply in priority.c, in blocklisting mode. */
286
int _gnutls_digest_mark_insecure(gnutls_digest_algorithm_t dig)
287
0
{
288
0
#ifndef DISABLE_SYSTEM_CONFIG
289
0
  mac_entry_st *p;
290
291
0
  for (p = hash_algorithms; p->name != NULL; p++) {
292
0
    if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t) dig) {
293
0
      p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE;
294
0
      return 0;
295
0
    }
296
0
  }
297
298
0
#endif
299
0
  return GNUTLS_E_INVALID_REQUEST;
300
0
}
301
302
/* This is only called by cfg_apply in priority.c, in allowlisting mode. */
303
void _gnutls_digest_mark_insecure_all(void)
304
0
{
305
0
#ifndef DISABLE_SYSTEM_CONFIG
306
0
  mac_entry_st *p;
307
308
0
  for (p = hash_algorithms; p->name != NULL; p++) {
309
0
    p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE |
310
0
        GNUTLS_MAC_FLAG_PREIMAGE_INSECURE;
311
0
  }
312
313
0
#endif
314
0
}
315
316
int
317
_gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure)
318
0
{
319
0
#ifndef DISABLE_SYSTEM_CONFIG
320
0
  mac_entry_st *p;
321
322
0
  for (p = hash_algorithms; p->name != NULL; p++) {
323
0
    if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t) dig) {
324
0
      if (!
325
0
          (p->flags &
326
0
           GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE)) {
327
0
        return
328
0
            gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
329
0
      }
330
0
      if (secure) {
331
0
        p->flags &= ~GNUTLS_MAC_FLAG_PREIMAGE_INSECURE;
332
0
      } else {
333
0
        p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE;
334
0
      }
335
0
      return 0;
336
0
    }
337
0
  }
338
339
0
#endif
340
0
  return GNUTLS_E_INVALID_REQUEST;
341
0
}
342
343
unsigned _gnutls_digest_is_insecure(gnutls_digest_algorithm_t dig)
344
0
{
345
0
  const mac_entry_st *p;
346
347
0
  for (p = hash_algorithms; p->name != NULL; p++) {
348
0
    if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t) dig) {
349
0
      return p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE;
350
0
    }
351
0
  }
352
353
0
  return 1;
354
0
}
355
356
bool _gnutls_digest_is_insecure2(gnutls_digest_algorithm_t dig, unsigned flags)
357
0
{
358
0
  const mac_entry_st *p;
359
360
0
  for (p = hash_algorithms; p->name != NULL; p++) {
361
0
    if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t) dig) {
362
0
      return (p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE &&
363
0
        !(flags &
364
0
          GNUTLS_MAC_FLAG_ALLOW_INSECURE_REVERTIBLE
365
0
          && p->flags &
366
0
          GNUTLS_MAC_FLAG_PREIMAGE_INSECURE_REVERTIBLE));
367
0
    }
368
0
  }
369
370
0
  return true;
371
0
}
372
373
/**
374
 * gnutls_mac_get_id:
375
 * @name: is a MAC algorithm name
376
 *
377
 * Convert a string to a #gnutls_mac_algorithm_t value.  The names are
378
 * compared in a case insensitive way.
379
 *
380
 * Returns: a #gnutls_mac_algorithm_t id of the specified MAC
381
 *   algorithm string, or %GNUTLS_MAC_UNKNOWN on failure.
382
 **/
383
gnutls_mac_algorithm_t gnutls_mac_get_id(const char *name)
384
0
{
385
0
  gnutls_mac_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
386
387
0
  GNUTLS_HASH_LOOP(if (c_strcasecmp(p->name, name) == 0) {
388
0
       if (p->placeholder != 0 || _gnutls_mac_exists(p->id))
389
0
       ret = p->id; break;}
390
0
  ) ;
391
392
0
  return ret;
393
0
}
394
395
/**
396
 * gnutls_mac_get_key_size:
397
 * @algorithm: is an encryption algorithm
398
 *
399
 * Returns the size of the MAC key used in TLS.
400
 *
401
 * Returns: length (in bytes) of the given MAC key size, or 0 if the
402
 *   given MAC algorithm is invalid.
403
 **/
404
size_t gnutls_mac_get_key_size(gnutls_mac_algorithm_t algorithm)
405
0
{
406
0
  size_t ret = 0;
407
408
  /* avoid prefix */
409
0
  GNUTLS_HASH_ALG_LOOP(ret = p->key_size);
410
411
0
  return ret;
412
0
}
413
414
/**
415
 * gnutls_mac_get_nonce_size:
416
 * @algorithm: is an encryption algorithm
417
 *
418
 * Returns the size of the nonce used by the MAC in TLS.
419
 *
420
 * Returns: length (in bytes) of the given MAC nonce size, or 0.
421
 *
422
 * Since: 3.2.0
423
 **/
424
size_t gnutls_mac_get_nonce_size(gnutls_mac_algorithm_t algorithm)
425
0
{
426
0
  size_t ret = 0;
427
428
  /* avoid prefix */
429
0
  GNUTLS_HASH_ALG_LOOP(ret = p->nonce_size);
430
431
0
  return ret;
432
0
}
433
434
/**
435
 * gnutls_mac_list:
436
 *
437
 * Get a list of hash algorithms for use as MACs.  Note that not
438
 * necessarily all MACs are supported in TLS cipher suites.
439
 * This function is not thread safe.
440
 *
441
 * Returns: Return a (0)-terminated list of #gnutls_mac_algorithm_t
442
 *   integers indicating the available MACs.
443
 **/
444
const gnutls_mac_algorithm_t *gnutls_mac_list(void)
445
0
{
446
0
  static gnutls_mac_algorithm_t supported_macs[MAX_ALGOS] = { 0 };
447
448
0
  if (supported_macs[0] == 0) {
449
0
    int i = 0;
450
451
0
    GNUTLS_HASH_LOOP(if
452
0
         (p->placeholder != 0
453
0
          || _gnutls_mac_exists(p->id))
454
0
         supported_macs[i++] = p->id;) ;
455
0
    supported_macs[i++] = 0;
456
0
  }
457
458
0
  return supported_macs;
459
0
}
460
461
/**
462
 * gnutls_digest_list:
463
 *
464
 * Get a list of hash (digest) algorithms supported by GnuTLS.
465
 *
466
 * This function is not thread safe.
467
 *
468
 * Returns: Return a (0)-terminated list of #gnutls_digest_algorithm_t
469
 *   integers indicating the available digests.
470
 **/
471
const gnutls_digest_algorithm_t *gnutls_digest_list(void)
472
0
{
473
0
  static gnutls_digest_algorithm_t supported_digests[MAX_ALGOS] = { 0 };
474
475
0
  if (supported_digests[0] == 0) {
476
0
    int i = 0;
477
478
0
    GNUTLS_HASH_LOOP(if (p->oid != NULL && (p->placeholder != 0 ||
479
0
              _gnutls_mac_exists
480
0
              (p->id))) {
481
482
0
         supported_digests[i++] =
483
0
         (gnutls_digest_algorithm_t) p->id;}
484
0
    ) ;
485
0
    supported_digests[i++] = 0;
486
0
  }
487
488
0
  return supported_digests;
489
0
}
490
491
/**
492
 * gnutls_oid_to_digest:
493
 * @oid: is an object identifier
494
 *
495
 * Converts a textual object identifier to a #gnutls_digest_algorithm_t value.
496
 *
497
 * Returns: a #gnutls_digest_algorithm_t id of the specified digest
498
 *   algorithm, or %GNUTLS_DIG_UNKNOWN on failure.
499
 *
500
 * Since: 3.4.3
501
 **/
502
gnutls_digest_algorithm_t gnutls_oid_to_digest(const char *oid)
503
0
{
504
0
  GNUTLS_HASH_LOOP(if (p->oid && strcmp(oid, p->oid) == 0) {
505
0
       if (_gnutls_digest_exists
506
0
           ((gnutls_digest_algorithm_t) p->id)) {
507
0
       return (gnutls_digest_algorithm_t) p->id;}
508
0
       break;}
509
0
  ) ;
510
511
0
  return GNUTLS_DIG_UNKNOWN;
512
0
}
513
514
/**
515
 * gnutls_oid_to_mac:
516
 * @oid: is an object identifier
517
 *
518
 * Converts a textual object identifier typically from PKCS#5 values to a #gnutls_mac_algorithm_t value.
519
 *
520
 * Returns: a #gnutls_mac_algorithm_t id of the specified digest
521
 *   algorithm, or %GNUTLS_MAC_UNKNOWN on failure.
522
 *
523
 * Since: 3.5.4
524
 **/
525
gnutls_mac_algorithm_t gnutls_oid_to_mac(const char *oid)
526
0
{
527
0
  GNUTLS_HASH_LOOP(if (p->mac_oid && strcmp(oid, p->mac_oid) == 0) {
528
0
       if (_gnutls_mac_exists(p->id)) {
529
0
       return p->id;}
530
0
       break;}
531
0
  ) ;
532
533
0
  return GNUTLS_MAC_UNKNOWN;
534
0
}
535
536
/**
537
 * gnutls_digest_get_oid:
538
 * @algorithm: is a digest algorithm
539
 *
540
 * Convert a #gnutls_digest_algorithm_t value to its object identifier.
541
 *
542
 * Returns: a string that contains the object identifier of the specified digest
543
 *   algorithm, or %NULL.
544
 *
545
 * Since: 3.4.3
546
 **/
547
const char *gnutls_digest_get_oid(gnutls_digest_algorithm_t algorithm)
548
0
{
549
0
  GNUTLS_HASH_LOOP(if (algorithm == (unsigned)p->id && p->oid != NULL) {
550
0
       return p->oid;}
551
0
  ) ;
552
553
0
  return NULL;
554
0
}
555
556
gnutls_digest_algorithm_t _gnutls_hash_size_to_sha_hash(unsigned int size)
557
0
{
558
0
  if (size == 20)
559
0
    return GNUTLS_DIG_SHA1;
560
0
  else if (size == 28)
561
0
    return GNUTLS_DIG_SHA224;
562
0
  else if (size == 32)
563
0
    return GNUTLS_DIG_SHA256;
564
0
  else if (size == 48)
565
0
    return GNUTLS_DIG_SHA384;
566
0
  else if (size == 64)
567
0
    return GNUTLS_DIG_SHA512;
568
569
0
  return GNUTLS_DIG_UNKNOWN;
570
0
}