Coverage Report

Created: 2025-07-23 07:18

/src/gnutls/lib/hash_int.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* This file handles all the internal functions that cope with hashes
24
 * and HMACs.
25
 */
26
27
#include "gnutls_int.h"
28
#include "hash_int.h"
29
#include "errors.h"
30
#include "algorithms.h"
31
#include "fips.h"
32
33
#ifdef ENABLE_PKCS11
34
#include "pkcs11/p11_provider.h"
35
#endif
36
37
int _gnutls_hash_init(digest_hd_st *dig, const mac_entry_st *e)
38
0
{
39
0
  int result;
40
0
  const gnutls_crypto_digest_st *cc = NULL;
41
42
0
  FAIL_IF_LIB_ERROR;
43
44
0
  if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
45
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
46
47
0
  dig->e = e;
48
49
  /* check if a digest has been registered 
50
   */
51
0
  cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id);
52
0
  if (
53
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
54
    /* Prioritize crypto from pkcs11 provider */
55
    !_p11_provider_is_initialized() &&
56
#endif
57
0
    cc != NULL && cc->init) {
58
0
    if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) <
59
0
        0) {
60
0
      gnutls_assert();
61
0
      return GNUTLS_E_HASH_FAILED;
62
0
    }
63
64
0
    dig->hash = cc->hash;
65
0
    dig->output = cc->output;
66
0
    dig->deinit = cc->deinit;
67
0
    dig->copy = cc->copy;
68
69
0
    return 0;
70
0
  }
71
72
0
  result = _gnutls_digest_backend()->init(
73
0
    (gnutls_digest_algorithm_t)e->id, &dig->handle);
74
0
  if (result < 0) {
75
0
    gnutls_assert();
76
0
    return result;
77
0
  }
78
79
0
  dig->hash = _gnutls_digest_backend()->hash;
80
0
  dig->output = _gnutls_digest_backend()->output;
81
0
  dig->deinit = _gnutls_digest_backend()->deinit;
82
0
  dig->copy = _gnutls_digest_backend()->copy;
83
84
0
  return 0;
85
0
}
86
87
/* Returns true(non-zero) or false(0) if the 
88
 * provided hash exists
89
 */
90
int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
91
0
{
92
0
  const gnutls_crypto_digest_st *cc = NULL;
93
94
0
  if (!is_mac_algo_allowed(DIG_TO_MAC(algo)))
95
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
96
97
0
  cc = _gnutls_get_crypto_digest(algo);
98
0
  if (
99
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
100
    /* Prioritize crypto from pkcs11 provider */
101
    !_p11_provider_is_initialized() &&
102
#endif
103
0
    cc != NULL)
104
0
    return 1;
105
106
0
  return _gnutls_digest_backend()->exists(algo);
107
0
}
108
109
int _gnutls_hash_copy(const digest_hd_st *handle, digest_hd_st *dst)
110
0
{
111
0
  if (handle->copy == NULL)
112
0
    return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
113
114
0
  *dst = *handle; /* copy data */
115
0
  dst->handle = handle->copy(handle->handle);
116
117
0
  if (dst->handle == NULL)
118
0
    return GNUTLS_E_HASH_FAILED;
119
120
0
  return 0;
121
0
}
122
123
void _gnutls_hash_deinit(digest_hd_st *handle, void *digest)
124
0
{
125
0
  if (handle->handle == NULL) {
126
0
    return;
127
0
  }
128
129
0
  if (digest != NULL)
130
0
    _gnutls_hash_output(handle, digest);
131
132
0
  handle->deinit(handle->handle);
133
0
  handle->handle = NULL;
134
0
}
135
136
int _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm, const void *text,
137
          size_t textlen, void *digest)
138
0
{
139
0
  int ret;
140
0
  const gnutls_crypto_digest_st *cc = NULL;
141
142
0
  FAIL_IF_LIB_ERROR;
143
144
  /* check if a digest has been registered 
145
   */
146
0
  cc = _gnutls_get_crypto_digest(algorithm);
147
0
  if (
148
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
149
    /* Prioritize crypto from pkcs11 provider */
150
    !_p11_provider_is_initialized() &&
151
#endif
152
0
    cc != NULL) {
153
0
    if (cc->fast(algorithm, text, textlen, digest) < 0) {
154
0
      gnutls_assert();
155
0
      return GNUTLS_E_HASH_FAILED;
156
0
    }
157
158
0
    return 0;
159
0
  }
160
161
0
  ret = _gnutls_digest_backend()->fast(algorithm, text, textlen, digest);
162
0
  if (ret < 0) {
163
0
    gnutls_assert();
164
0
    return ret;
165
0
  }
166
167
0
  return 0;
168
0
}
169
170
int _gnutls_hash_squeeze(digest_hd_st *handle, void *output, size_t length)
171
0
{
172
0
  if (handle->output == NULL)
173
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
174
175
0
  if (!(handle->e->flags & GNUTLS_MAC_FLAG_XOF))
176
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
177
178
0
  handle->output(handle->handle, output, length);
179
0
  return 0;
180
0
}
181
182
/* HMAC interface */
183
184
int _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
185
         int keylen, const void *text, size_t textlen, void *digest)
186
0
{
187
0
  int ret;
188
0
  const gnutls_crypto_mac_st *cc = NULL;
189
190
0
  FAIL_IF_LIB_ERROR;
191
192
  /* check if a digest has been registered 
193
   */
194
0
  cc = _gnutls_get_crypto_mac(algorithm);
195
0
  if (
196
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
197
    /* Prioritize crypto from pkcs11 provider */
198
    !_p11_provider_is_initialized() &&
199
#endif
200
0
    cc != NULL) {
201
0
    if (cc->fast(algorithm, NULL, 0, key, keylen, text, textlen,
202
0
           digest) < 0) {
203
0
      gnutls_assert();
204
0
      return GNUTLS_E_HASH_FAILED;
205
0
    }
206
207
0
    return 0;
208
0
  }
209
210
0
  ret = _gnutls_mac_backend()->fast(algorithm, NULL, 0, key, keylen, text,
211
0
            textlen, digest);
212
0
  if (ret < 0) {
213
0
    gnutls_assert();
214
0
    return ret;
215
0
  }
216
217
0
  return 0;
218
0
}
219
220
/* Returns true(non-zero) or false(0) if the 
221
 * provided hash exists
222
 */
223
int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
224
0
{
225
0
  const gnutls_crypto_mac_st *cc = NULL;
226
227
  /* exceptionally it exists, as it is not a real MAC */
228
0
  if (algo == GNUTLS_MAC_AEAD)
229
0
    return 1;
230
231
0
  if (!is_mac_algo_allowed(algo))
232
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
233
234
0
  cc = _gnutls_get_crypto_mac(algo);
235
0
  if (
236
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
237
    /* Prioritize crypto from pkcs11 provider */
238
    !_p11_provider_is_initialized() &&
239
#endif
240
0
    cc != NULL)
241
0
    return 1;
242
243
0
  return _gnutls_mac_backend()->exists(algo);
244
0
}
245
246
int _gnutls_mac_init(mac_hd_st *mac, const mac_entry_st *e, const void *key,
247
         int keylen)
248
0
{
249
0
  int result;
250
0
  const gnutls_crypto_mac_st *cc = NULL;
251
252
0
  FAIL_IF_LIB_ERROR;
253
254
0
  if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
255
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
256
257
0
  mac->e = e;
258
0
  mac->mac_len = _gnutls_mac_get_algo_len(e);
259
260
  /* check if a digest has been registered 
261
   */
262
0
  cc = _gnutls_get_crypto_mac(e->id);
263
0
  if (
264
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
265
    /* Prioritize crypto from pkcs11 provider */
266
    !_p11_provider_is_initialized() &&
267
#endif
268
0
    cc != NULL && cc->init != NULL) {
269
270
0
    if (cc->init(e->id, &mac->handle) < 0) {
271
0
      gnutls_assert();
272
0
      return GNUTLS_E_HASH_FAILED;
273
0
    }
274
275
0
    if (cc->setkey(mac->handle, key, keylen) < 0) {
276
0
      gnutls_assert();
277
0
      cc->deinit(mac->handle);
278
0
      return GNUTLS_E_HASH_FAILED;
279
0
    }
280
281
0
    mac->hash = cc->hash;
282
0
    mac->setnonce = cc->setnonce;
283
0
    mac->output = cc->output;
284
0
    mac->deinit = cc->deinit;
285
0
    mac->copy = cc->copy;
286
0
    mac->setkey = cc->setkey;
287
288
0
    return 0;
289
0
  }
290
291
0
  result = _gnutls_mac_backend()->init(e->id, &mac->handle);
292
0
  if (result < 0) {
293
0
    gnutls_assert();
294
0
    return result;
295
0
  }
296
297
0
  mac->hash = _gnutls_mac_backend()->hash;
298
0
  mac->setnonce = _gnutls_mac_backend()->setnonce;
299
0
  mac->output = _gnutls_mac_backend()->output;
300
0
  mac->deinit = _gnutls_mac_backend()->deinit;
301
0
  mac->copy = _gnutls_mac_backend()->copy;
302
0
  mac->setkey = _gnutls_mac_backend()->setkey;
303
304
0
  if (_gnutls_mac_backend()->setkey(mac->handle, key, keylen) < 0) {
305
0
    gnutls_assert();
306
0
    mac->deinit(mac->handle);
307
0
    return GNUTLS_E_HASH_FAILED;
308
0
  }
309
310
0
  return 0;
311
0
}
312
313
int _gnutls_mac_copy(const mac_hd_st *handle, mac_hd_st *dst)
314
0
{
315
0
  if (handle->copy == NULL)
316
0
    return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
317
318
0
  *dst = *handle; /* copy data */
319
0
  dst->handle = handle->copy(handle->handle);
320
321
0
  if (dst->handle == NULL)
322
0
    return GNUTLS_E_HASH_FAILED;
323
324
0
  return 0;
325
0
}
326
327
void _gnutls_mac_deinit(mac_hd_st *handle, void *digest)
328
0
{
329
0
  if (handle->handle == NULL) {
330
0
    return;
331
0
  }
332
333
0
  if (digest)
334
0
    _gnutls_mac_output(handle, digest);
335
336
0
  handle->deinit(handle->handle);
337
0
  handle->handle = NULL;
338
0
}
339
340
#ifdef ENABLE_SSL3
341
inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
342
{
343
  switch (algorithm) {
344
  case GNUTLS_MAC_MD5:
345
    return 48;
346
  case GNUTLS_MAC_SHA1:
347
    return 40;
348
  default:
349
    return 0;
350
  }
351
}
352
353
/* Special functions for SSL3 MAC
354
 */
355
356
int _gnutls_mac_init_ssl3(digest_hd_st *ret, const mac_entry_st *e, void *key,
357
        int keylen)
358
{
359
  uint8_t ipad[48];
360
  int padsize, result;
361
362
  FAIL_IF_LIB_ERROR;
363
364
  padsize = get_padsize(e->id);
365
  if (padsize == 0) {
366
    gnutls_assert();
367
    return GNUTLS_E_HASH_FAILED;
368
  }
369
370
  memset(ipad, 0x36, padsize);
371
372
  result = _gnutls_hash_init(ret, e);
373
  if (result < 0) {
374
    gnutls_assert();
375
    return result;
376
  }
377
378
  ret->key = key;
379
  ret->keysize = keylen;
380
381
  if (keylen > 0)
382
    _gnutls_hash(ret, key, keylen);
383
  _gnutls_hash(ret, ipad, padsize);
384
385
  return 0;
386
}
387
388
int _gnutls_mac_output_ssl3(digest_hd_st *handle, void *digest)
389
{
390
  uint8_t ret[MAX_HASH_SIZE];
391
  digest_hd_st td;
392
  uint8_t opad[48];
393
  int padsize;
394
  int block, rc;
395
396
  padsize = get_padsize(handle->e->id);
397
  if (padsize == 0) {
398
    gnutls_assert();
399
    return GNUTLS_E_INTERNAL_ERROR;
400
  }
401
402
  memset(opad, 0x5C, padsize);
403
404
  rc = _gnutls_hash_init(&td, handle->e);
405
  if (rc < 0) {
406
    gnutls_assert();
407
    return rc;
408
  }
409
410
  if (handle->keysize > 0)
411
    _gnutls_hash(&td, handle->key, handle->keysize);
412
413
  _gnutls_hash(&td, opad, padsize);
414
  block = _gnutls_mac_get_algo_len(handle->e);
415
  _gnutls_hash_output(handle, ret); /* get the previous hash */
416
  _gnutls_hash(&td, ret, block);
417
418
  _gnutls_hash_deinit(&td, digest);
419
420
  /* reset handle */
421
  memset(opad, 0x36, padsize);
422
423
  if (handle->keysize > 0)
424
    _gnutls_hash(handle, handle->key, handle->keysize);
425
  _gnutls_hash(handle, opad, padsize);
426
427
  return 0;
428
}
429
430
int _gnutls_mac_deinit_ssl3(digest_hd_st *handle, void *digest)
431
{
432
  int ret = 0;
433
434
  if (digest != NULL)
435
    ret = _gnutls_mac_output_ssl3(handle, digest);
436
  _gnutls_hash_deinit(handle, NULL);
437
438
  return ret;
439
}
440
441
int _gnutls_mac_deinit_ssl3_handshake(digest_hd_st *handle, void *digest,
442
              uint8_t *key, uint32_t key_size)
443
{
444
  uint8_t ret[MAX_HASH_SIZE];
445
  digest_hd_st td;
446
  uint8_t opad[48];
447
  uint8_t ipad[48];
448
  int padsize;
449
  int block, rc;
450
451
  padsize = get_padsize(handle->e->id);
452
  if (padsize == 0) {
453
    gnutls_assert();
454
    rc = GNUTLS_E_INTERNAL_ERROR;
455
    goto cleanup;
456
  }
457
458
  memset(opad, 0x5C, padsize);
459
  memset(ipad, 0x36, padsize);
460
461
  rc = _gnutls_hash_init(&td, handle->e);
462
  if (rc < 0) {
463
    gnutls_assert();
464
    goto cleanup;
465
  }
466
467
  if (key_size > 0)
468
    _gnutls_hash(&td, key, key_size);
469
470
  _gnutls_hash(&td, opad, padsize);
471
  block = _gnutls_mac_get_algo_len(handle->e);
472
473
  if (key_size > 0)
474
    _gnutls_hash(handle, key, key_size);
475
  _gnutls_hash(handle, ipad, padsize);
476
  _gnutls_hash_deinit(handle, ret); /* get the previous hash */
477
478
  _gnutls_hash(&td, ret, block);
479
480
  _gnutls_hash_deinit(&td, digest);
481
482
  return 0;
483
484
cleanup:
485
  _gnutls_hash_deinit(handle, NULL);
486
  return rc;
487
}
488
489
static int ssl3_sha(int i, uint8_t *secret, int secret_len, uint8_t *rnd,
490
        int rnd_len, void *digest)
491
{
492
  int j, ret;
493
  uint8_t text1[26];
494
495
  digest_hd_st td;
496
497
  for (j = 0; j < i + 1; j++) {
498
    text1[j] = 65 + i; /* A==65 */
499
  }
500
501
  ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
502
  if (ret < 0) {
503
    gnutls_assert();
504
    return ret;
505
  }
506
507
  _gnutls_hash(&td, text1, i + 1);
508
  _gnutls_hash(&td, secret, secret_len);
509
  _gnutls_hash(&td, rnd, rnd_len);
510
511
  _gnutls_hash_deinit(&td, digest);
512
  return 0;
513
}
514
515
#define SHA1_DIGEST_OUTPUT 20
516
#define MD5_DIGEST_OUTPUT 16
517
518
static int ssl3_md5(int i, uint8_t *secret, int secret_len, uint8_t *rnd,
519
        int rnd_len, void *digest)
520
{
521
  uint8_t tmp[MAX_HASH_SIZE];
522
  digest_hd_st td;
523
  int ret;
524
525
  ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
526
  if (ret < 0) {
527
    gnutls_assert();
528
    return ret;
529
  }
530
531
  _gnutls_hash(&td, secret, secret_len);
532
533
  ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
534
  if (ret < 0) {
535
    gnutls_assert();
536
    _gnutls_hash_deinit(&td, digest);
537
    return ret;
538
  }
539
540
  _gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
541
542
  _gnutls_hash_deinit(&td, digest);
543
  return 0;
544
}
545
546
int _gnutls_ssl3_generate_random(void *secret, int secret_len, void *rnd,
547
         int rnd_len, int ret_bytes, uint8_t *ret)
548
{
549
  int i = 0, copy, output_bytes;
550
  uint8_t digest[MAX_HASH_SIZE];
551
  int block = MD5_DIGEST_OUTPUT;
552
  int result, times;
553
554
  output_bytes = 0;
555
  do {
556
    output_bytes += block;
557
  } while (output_bytes < ret_bytes);
558
559
  times = output_bytes / block;
560
561
  for (i = 0; i < times; i++) {
562
    result = ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
563
    if (result < 0) {
564
      gnutls_assert();
565
      return result;
566
    }
567
568
    if ((1 + i) * block < ret_bytes) {
569
      copy = block;
570
    } else {
571
      copy = ret_bytes - (i)*block;
572
    }
573
574
    memcpy(&ret[i * block], digest, copy);
575
  }
576
577
  return 0;
578
}
579
580
#endif