Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/cipher/hash-common.c
Line
Count
Source (jump to first uncovered line)
1
/* hash-common.c - Common code for hash algorithms
2
 * Copyright (C) 2008 Free Software Foundation, Inc.
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
#ifdef HAVE_STDINT_H
25
# include <stdint.h>
26
#endif
27
28
#include "g10lib.h"
29
#include "bufhelp.h"
30
#include "hash-common.h"
31
32
33
/* Run a selftest for hash algorithm ALGO.  If the resulting digest
34
   matches EXPECT/EXPECTLEN and everything else is fine as well,
35
   return NULL.  If an error occurs, return a static text string
36
   describing the error.
37
38
   DATAMODE controls what will be hashed according to this table:
39
40
     0 - Hash the supplied DATA of DATALEN.
41
     1 - Hash one million times a 'a'.  DATA and DATALEN are ignored.
42
43
*/
44
const char *
45
_gcry_hash_selftest_check_one (int algo,
46
                               int datamode, const void *data, size_t datalen,
47
                               const void *expect, size_t expectlen)
48
0
{
49
0
  const char *result = NULL;
50
0
  gcry_error_t err = 0;
51
0
  gcry_md_hd_t hd;
52
0
  unsigned char *digest;
53
0
  char aaa[1000];
54
0
  int xof = 0;
55
56
0
  if (_gcry_md_get_algo_dlen (algo) == 0)
57
0
    xof = 1;
58
0
  else if (_gcry_md_get_algo_dlen (algo) != expectlen)
59
0
    return "digest size does not match expected size";
60
61
0
  err = _gcry_md_open (&hd, algo, 0);
62
0
  if (err)
63
0
    return "gcry_md_open failed";
64
65
0
  switch (datamode)
66
0
    {
67
0
    case 0:
68
0
      _gcry_md_write (hd, data, datalen);
69
0
      break;
70
71
0
    case 1: /* Hash one million times an "a". */
72
0
      {
73
0
        int i;
74
75
        /* Write in odd size chunks so that we test the buffering.  */
76
0
        memset (aaa, 'a', 1000);
77
0
        for (i = 0; i < 1000; i++)
78
0
          _gcry_md_write (hd, aaa, 1000);
79
0
      }
80
0
      break;
81
82
0
    default:
83
0
      result = "invalid DATAMODE";
84
0
    }
85
86
0
  if (!result)
87
0
    {
88
0
      if (!xof)
89
0
  {
90
0
    digest = _gcry_md_read (hd, algo);
91
92
0
    if ( memcmp (digest, expect, expectlen) )
93
0
      result = "digest mismatch";
94
0
  }
95
0
      else
96
0
  {
97
0
    gcry_assert(expectlen <= sizeof(aaa));
98
99
0
    err = _gcry_md_extract (hd, algo, aaa, expectlen);
100
0
    if (err)
101
0
      result = "error extracting output from XOF";
102
0
    else if ( memcmp (aaa, expect, expectlen) )
103
0
      result = "digest mismatch";
104
0
  }
105
0
    }
106
107
0
  _gcry_md_close (hd);
108
109
0
  return result;
110
0
}
111
112
113
/* Common function to write a chunk of data to the transform function
114
   of a hash algorithm.  Note that the use of the term "block" does
115
   not imply a fixed size block.  Note that we explicitly allow to use
116
   this function after the context has been finalized; the result does
117
   not have any meaning but writing after finalize is sometimes
118
   helpful to mitigate timing attacks. */
119
void
120
_gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
121
3.18k
{
122
3.18k
  const unsigned char *inbuf = inbuf_arg;
123
3.18k
  gcry_md_block_ctx_t *hd = context;
124
3.18k
  unsigned int stack_burn = 0;
125
3.18k
  unsigned int nburn;
126
3.18k
  const unsigned int blocksize_shift = hd->blocksize_shift;
127
3.18k
  const unsigned int blocksize = 1 << blocksize_shift;
128
3.18k
  size_t inblocks;
129
3.18k
  size_t copylen;
130
131
3.18k
  if (sizeof(hd->buf) < blocksize)
132
0
    BUG();
133
134
3.18k
  if (!hd->bwrite)
135
0
    return;
136
137
3.18k
  if (hd->count > blocksize)
138
0
    {
139
      /* This happens only when gcry_md_write is called after final.
140
       * Writing after final is used for mitigating timing attacks. */
141
0
      hd->count = 0;
142
0
    }
143
144
5.07k
  while (hd->count)
145
3.68k
    {
146
3.68k
      if (hd->count == blocksize)  /* Flush the buffer. */
147
179
  {
148
179
    nburn = hd->bwrite (hd, hd->buf, 1);
149
179
    stack_burn = nburn > stack_burn ? nburn : stack_burn;
150
179
    hd->count = 0;
151
179
    if (!++hd->nblocks)
152
0
      hd->nblocks_high++;
153
179
  }
154
3.50k
      else
155
3.50k
  {
156
3.50k
    copylen = inlen;
157
3.50k
    if (copylen > blocksize - hd->count)
158
179
      copylen = blocksize - hd->count;
159
160
3.50k
    if (copylen == 0)
161
1.78k
      break;
162
163
1.71k
    buf_cpy (&hd->buf[hd->count], inbuf, copylen);
164
1.71k
    hd->count += copylen;
165
1.71k
    inbuf += copylen;
166
1.71k
    inlen -= copylen;
167
1.71k
  }
168
3.68k
    }
169
170
3.18k
  if (inlen == 0)
171
1.78k
    return;
172
173
1.39k
  if (inlen >= blocksize)
174
74
    {
175
74
      inblocks = inlen >> blocksize_shift;
176
74
      nburn = hd->bwrite (hd, inbuf, inblocks);
177
74
      stack_burn = nburn > stack_burn ? nburn : stack_burn;
178
74
      hd->count = 0;
179
74
      hd->nblocks_high += (hd->nblocks + inblocks < inblocks);
180
74
      hd->nblocks += inblocks;
181
74
      inlen -= inblocks << blocksize_shift;
182
74
      inbuf += inblocks << blocksize_shift;
183
74
    }
184
185
1.39k
  if (inlen)
186
1.38k
    {
187
1.38k
      buf_cpy (hd->buf, inbuf, inlen);
188
1.38k
      hd->count = inlen;
189
1.38k
    }
190
191
1.39k
  if (stack_burn > 0)
192
0
    _gcry_burn_stack (stack_burn);
193
1.39k
}