Coverage Report

Created: 2024-06-20 06:28

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