Coverage Report

Created: 2023-03-26 07:33

/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
int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
34
0
{
35
0
  int result;
36
0
  const gnutls_crypto_digest_st *cc = NULL;
37
38
0
  FAIL_IF_LIB_ERROR;
39
40
0
  if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
41
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
42
43
0
  dig->e = e;
44
45
  /* check if a digest has been registered 
46
   */
47
0
  cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t) e->id);
48
0
  if (cc != NULL && cc->init) {
49
0
    if (cc->init((gnutls_digest_algorithm_t) e->id, &dig->handle) <
50
0
        0) {
51
0
      gnutls_assert();
52
0
      return GNUTLS_E_HASH_FAILED;
53
0
    }
54
55
0
    dig->hash = cc->hash;
56
0
    dig->output = cc->output;
57
0
    dig->deinit = cc->deinit;
58
0
    dig->copy = cc->copy;
59
60
0
    return 0;
61
0
  }
62
63
0
  result =
64
0
      _gnutls_digest_ops.init((gnutls_digest_algorithm_t) e->id,
65
0
            &dig->handle);
66
0
  if (result < 0) {
67
0
    gnutls_assert();
68
0
    return result;
69
0
  }
70
71
0
  dig->hash = _gnutls_digest_ops.hash;
72
0
  dig->output = _gnutls_digest_ops.output;
73
0
  dig->deinit = _gnutls_digest_ops.deinit;
74
0
  dig->copy = _gnutls_digest_ops.copy;
75
76
0
  return 0;
77
0
}
78
79
/* Returns true(non-zero) or false(0) if the 
80
 * provided hash exists
81
 */
82
int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
83
0
{
84
0
  const gnutls_crypto_digest_st *cc = NULL;
85
86
0
  if (!is_mac_algo_allowed(DIG_TO_MAC(algo)))
87
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
88
89
0
  cc = _gnutls_get_crypto_digest(algo);
90
0
  if (cc != NULL)
91
0
    return 1;
92
93
0
  return _gnutls_digest_ops.exists(algo);
94
0
}
95
96
int _gnutls_hash_copy(const digest_hd_st * handle, digest_hd_st * dst)
97
0
{
98
0
  if (handle->copy == NULL)
99
0
    return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
100
101
0
  *dst = *handle;   /* copy data */
102
0
  dst->handle = handle->copy(handle->handle);
103
104
0
  if (dst->handle == NULL)
105
0
    return GNUTLS_E_HASH_FAILED;
106
107
0
  return 0;
108
0
}
109
110
void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
111
0
{
112
0
  if (handle->handle == NULL) {
113
0
    return;
114
0
  }
115
116
0
  if (digest != NULL)
117
0
    _gnutls_hash_output(handle, digest);
118
119
0
  handle->deinit(handle->handle);
120
0
  handle->handle = NULL;
121
0
}
122
123
int
124
_gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
125
      const void *text, size_t textlen, void *digest)
126
0
{
127
0
  int ret;
128
0
  const gnutls_crypto_digest_st *cc = NULL;
129
130
0
  FAIL_IF_LIB_ERROR;
131
132
  /* check if a digest has been registered 
133
   */
134
0
  cc = _gnutls_get_crypto_digest(algorithm);
135
0
  if (cc != NULL) {
136
0
    if (cc->fast(algorithm, text, textlen, digest) < 0) {
137
0
      gnutls_assert();
138
0
      return GNUTLS_E_HASH_FAILED;
139
0
    }
140
141
0
    return 0;
142
0
  }
143
144
0
  ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest);
145
0
  if (ret < 0) {
146
0
    gnutls_assert();
147
0
    return ret;
148
0
  }
149
150
0
  return 0;
151
0
}
152
153
/* HMAC interface */
154
155
int
156
_gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
157
     int keylen, const void *text, size_t textlen, void *digest)
158
0
{
159
0
  int ret;
160
0
  const gnutls_crypto_mac_st *cc = NULL;
161
162
0
  FAIL_IF_LIB_ERROR;
163
164
  /* check if a digest has been registered 
165
   */
166
0
  cc = _gnutls_get_crypto_mac(algorithm);
167
0
  if (cc != NULL) {
168
0
    if (cc->fast(algorithm, NULL, 0, key, keylen, text, textlen,
169
0
           digest) < 0) {
170
0
      gnutls_assert();
171
0
      return GNUTLS_E_HASH_FAILED;
172
0
    }
173
174
0
    return 0;
175
0
  }
176
177
0
  ret =
178
0
      _gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text,
179
0
         textlen, digest);
180
0
  if (ret < 0) {
181
0
    gnutls_assert();
182
0
    return ret;
183
0
  }
184
185
0
  return 0;
186
187
0
}
188
189
/* Returns true(non-zero) or false(0) if the 
190
 * provided hash exists
191
 */
192
int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
193
0
{
194
0
  const gnutls_crypto_mac_st *cc = NULL;
195
196
  /* exceptionally it exists, as it is not a real MAC */
197
0
  if (algo == GNUTLS_MAC_AEAD)
198
0
    return 1;
199
200
0
  if (!is_mac_algo_allowed(algo))
201
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
202
203
0
  cc = _gnutls_get_crypto_mac(algo);
204
0
  if (cc != NULL)
205
0
    return 1;
206
207
0
  return _gnutls_mac_ops.exists(algo);
208
0
}
209
210
int
211
_gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
212
     const void *key, int keylen)
213
0
{
214
0
  int result;
215
0
  const gnutls_crypto_mac_st *cc = NULL;
216
217
0
  FAIL_IF_LIB_ERROR;
218
219
0
  if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
220
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
221
222
0
  mac->e = e;
223
0
  mac->mac_len = _gnutls_mac_get_algo_len(e);
224
225
  /* check if a digest has been registered 
226
   */
227
0
  cc = _gnutls_get_crypto_mac(e->id);
228
0
  if (cc != NULL && cc->init != NULL) {
229
0
    if (cc->init(e->id, &mac->handle) < 0) {
230
0
      gnutls_assert();
231
0
      return GNUTLS_E_HASH_FAILED;
232
0
    }
233
234
0
    if (cc->setkey(mac->handle, key, keylen) < 0) {
235
0
      gnutls_assert();
236
0
      cc->deinit(mac->handle);
237
0
      return GNUTLS_E_HASH_FAILED;
238
0
    }
239
240
0
    mac->hash = cc->hash;
241
0
    mac->setnonce = cc->setnonce;
242
0
    mac->output = cc->output;
243
0
    mac->deinit = cc->deinit;
244
0
    mac->copy = cc->copy;
245
0
    mac->setkey = cc->setkey;
246
247
0
    return 0;
248
0
  }
249
250
0
  result = _gnutls_mac_ops.init(e->id, &mac->handle);
251
0
  if (result < 0) {
252
0
    gnutls_assert();
253
0
    return result;
254
0
  }
255
256
0
  mac->hash = _gnutls_mac_ops.hash;
257
0
  mac->setnonce = _gnutls_mac_ops.setnonce;
258
0
  mac->output = _gnutls_mac_ops.output;
259
0
  mac->deinit = _gnutls_mac_ops.deinit;
260
0
  mac->copy = _gnutls_mac_ops.copy;
261
0
  mac->setkey = _gnutls_mac_ops.setkey;
262
263
0
  if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
264
0
    gnutls_assert();
265
0
    mac->deinit(mac->handle);
266
0
    return GNUTLS_E_HASH_FAILED;
267
0
  }
268
269
0
  return 0;
270
0
}
271
272
int _gnutls_mac_copy(const mac_hd_st * handle, mac_hd_st * dst)
273
0
{
274
0
  if (handle->copy == NULL)
275
0
    return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
276
277
0
  *dst = *handle;   /* copy data */
278
0
  dst->handle = handle->copy(handle->handle);
279
280
0
  if (dst->handle == NULL)
281
0
    return GNUTLS_E_HASH_FAILED;
282
283
0
  return 0;
284
0
}
285
286
void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
287
0
{
288
0
  if (handle->handle == NULL) {
289
0
    return;
290
0
  }
291
292
0
  if (digest)
293
0
    _gnutls_mac_output(handle, digest);
294
295
0
  handle->deinit(handle->handle);
296
0
  handle->handle = NULL;
297
0
}
298
299
#ifdef ENABLE_SSL3
300
inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
301
{
302
  switch (algorithm) {
303
  case GNUTLS_MAC_MD5:
304
    return 48;
305
  case GNUTLS_MAC_SHA1:
306
    return 40;
307
  default:
308
    return 0;
309
  }
310
}
311
312
/* Special functions for SSL3 MAC
313
 */
314
315
int
316
_gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
317
          void *key, int keylen)
318
{
319
  uint8_t ipad[48];
320
  int padsize, result;
321
322
  FAIL_IF_LIB_ERROR;
323
324
  padsize = get_padsize(e->id);
325
  if (padsize == 0) {
326
    gnutls_assert();
327
    return GNUTLS_E_HASH_FAILED;
328
  }
329
330
  memset(ipad, 0x36, padsize);
331
332
  result = _gnutls_hash_init(ret, e);
333
  if (result < 0) {
334
    gnutls_assert();
335
    return result;
336
  }
337
338
  ret->key = key;
339
  ret->keysize = keylen;
340
341
  if (keylen > 0)
342
    _gnutls_hash(ret, key, keylen);
343
  _gnutls_hash(ret, ipad, padsize);
344
345
  return 0;
346
}
347
348
int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
349
{
350
  uint8_t ret[MAX_HASH_SIZE];
351
  digest_hd_st td;
352
  uint8_t opad[48];
353
  int padsize;
354
  int block, rc;
355
356
  padsize = get_padsize(handle->e->id);
357
  if (padsize == 0) {
358
    gnutls_assert();
359
    return GNUTLS_E_INTERNAL_ERROR;
360
  }
361
362
  memset(opad, 0x5C, padsize);
363
364
  rc = _gnutls_hash_init(&td, handle->e);
365
  if (rc < 0) {
366
    gnutls_assert();
367
    return rc;
368
  }
369
370
  if (handle->keysize > 0)
371
    _gnutls_hash(&td, handle->key, handle->keysize);
372
373
  _gnutls_hash(&td, opad, padsize);
374
  block = _gnutls_mac_get_algo_len(handle->e);
375
  _gnutls_hash_output(handle, ret); /* get the previous hash */
376
  _gnutls_hash(&td, ret, block);
377
378
  _gnutls_hash_deinit(&td, digest);
379
380
  /* reset handle */
381
  memset(opad, 0x36, padsize);
382
383
  if (handle->keysize > 0)
384
    _gnutls_hash(handle, handle->key, handle->keysize);
385
  _gnutls_hash(handle, opad, padsize);
386
387
  return 0;
388
}
389
390
int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
391
{
392
  int ret = 0;
393
394
  if (digest != NULL)
395
    ret = _gnutls_mac_output_ssl3(handle, digest);
396
  _gnutls_hash_deinit(handle, NULL);
397
398
  return ret;
399
}
400
401
int
402
_gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
403
          void *digest, uint8_t * key,
404
          uint32_t key_size)
405
{
406
  uint8_t ret[MAX_HASH_SIZE];
407
  digest_hd_st td;
408
  uint8_t opad[48];
409
  uint8_t ipad[48];
410
  int padsize;
411
  int block, rc;
412
413
  padsize = get_padsize(handle->e->id);
414
  if (padsize == 0) {
415
    gnutls_assert();
416
    rc = GNUTLS_E_INTERNAL_ERROR;
417
    goto cleanup;
418
  }
419
420
  memset(opad, 0x5C, padsize);
421
  memset(ipad, 0x36, padsize);
422
423
  rc = _gnutls_hash_init(&td, handle->e);
424
  if (rc < 0) {
425
    gnutls_assert();
426
    goto cleanup;
427
  }
428
429
  if (key_size > 0)
430
    _gnutls_hash(&td, key, key_size);
431
432
  _gnutls_hash(&td, opad, padsize);
433
  block = _gnutls_mac_get_algo_len(handle->e);
434
435
  if (key_size > 0)
436
    _gnutls_hash(handle, key, key_size);
437
  _gnutls_hash(handle, ipad, padsize);
438
  _gnutls_hash_deinit(handle, ret); /* get the previous hash */
439
440
  _gnutls_hash(&td, ret, block);
441
442
  _gnutls_hash_deinit(&td, digest);
443
444
  return 0;
445
446
 cleanup:
447
  _gnutls_hash_deinit(handle, NULL);
448
  return rc;
449
}
450
451
static int
452
ssl3_sha(int i, uint8_t * secret, int secret_len,
453
   uint8_t * rnd, int rnd_len, void *digest)
454
{
455
  int j, ret;
456
  uint8_t text1[26];
457
458
  digest_hd_st td;
459
460
  for (j = 0; j < i + 1; j++) {
461
    text1[j] = 65 + i;  /* A==65 */
462
  }
463
464
  ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
465
  if (ret < 0) {
466
    gnutls_assert();
467
    return ret;
468
  }
469
470
  _gnutls_hash(&td, text1, i + 1);
471
  _gnutls_hash(&td, secret, secret_len);
472
  _gnutls_hash(&td, rnd, rnd_len);
473
474
  _gnutls_hash_deinit(&td, digest);
475
  return 0;
476
}
477
478
# define SHA1_DIGEST_OUTPUT 20
479
# define MD5_DIGEST_OUTPUT 16
480
481
static int
482
ssl3_md5(int i, uint8_t * secret, int secret_len,
483
   uint8_t * rnd, int rnd_len, void *digest)
484
{
485
  uint8_t tmp[MAX_HASH_SIZE];
486
  digest_hd_st td;
487
  int ret;
488
489
  ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
490
  if (ret < 0) {
491
    gnutls_assert();
492
    return ret;
493
  }
494
495
  _gnutls_hash(&td, secret, secret_len);
496
497
  ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
498
  if (ret < 0) {
499
    gnutls_assert();
500
    _gnutls_hash_deinit(&td, digest);
501
    return ret;
502
  }
503
504
  _gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
505
506
  _gnutls_hash_deinit(&td, digest);
507
  return 0;
508
}
509
510
int
511
_gnutls_ssl3_generate_random(void *secret, int secret_len,
512
           void *rnd, int rnd_len,
513
           int ret_bytes, uint8_t * ret)
514
{
515
  int i = 0, copy, output_bytes;
516
  uint8_t digest[MAX_HASH_SIZE];
517
  int block = MD5_DIGEST_OUTPUT;
518
  int result, times;
519
520
  output_bytes = 0;
521
  do {
522
    output_bytes += block;
523
  }
524
  while (output_bytes < ret_bytes);
525
526
  times = output_bytes / block;
527
528
  for (i = 0; i < times; i++) {
529
530
    result = ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
531
    if (result < 0) {
532
      gnutls_assert();
533
      return result;
534
    }
535
536
    if ((1 + i) * block < ret_bytes) {
537
      copy = block;
538
    } else {
539
      copy = ret_bytes - (i) * block;
540
    }
541
542
    memcpy(&ret[i * block], digest, copy);
543
  }
544
545
  return 0;
546
}
547
548
#endif