Line data Source code
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 "hash-common.h"
30 :
31 :
32 : /* Run a selftest for hash algorithm ALGO. If the resulting digest
33 : matches EXPECT/EXPECTLEN and everything else is fine as well,
34 : return NULL. If an error occurs, return a static text string
35 : describing the error.
36 :
37 : DATAMODE controls what will be hashed according to this table:
38 :
39 : 0 - Hash the supplied DATA of DATALEN.
40 : 1 - Hash one million times a 'a'. DATA and DATALEN are ignored.
41 :
42 : */
43 : const char *
44 0 : _gcry_hash_selftest_check_one (int algo,
45 : int datamode, const void *data, size_t datalen,
46 : const void *expect, size_t expectlen)
47 : {
48 0 : const char *result = NULL;
49 0 : gcry_error_t err = 0;
50 : gcry_md_hd_t hd;
51 : unsigned char *digest;
52 : char aaa[1000];
53 0 : int xof = 0;
54 :
55 0 : if (_gcry_md_get_algo_dlen (algo) == 0)
56 0 : xof = 1;
57 0 : else if (_gcry_md_get_algo_dlen (algo) != expectlen)
58 0 : return "digest size does not match expected size";
59 :
60 0 : err = _gcry_md_open (&hd, algo, 0);
61 0 : if (err)
62 0 : return "gcry_md_open failed";
63 :
64 0 : switch (datamode)
65 : {
66 : case 0:
67 0 : _gcry_md_write (hd, data, datalen);
68 0 : break;
69 :
70 : case 1: /* Hash one million times an "a". */
71 : {
72 : int i;
73 :
74 : /* Write in odd size chunks so that we test the buffering. */
75 0 : memset (aaa, 'a', 1000);
76 0 : for (i = 0; i < 1000; i++)
77 0 : _gcry_md_write (hd, aaa, 1000);
78 : }
79 0 : break;
80 :
81 : default:
82 0 : result = "invalid DATAMODE";
83 : }
84 :
85 0 : if (!result)
86 : {
87 0 : if (!xof)
88 : {
89 0 : digest = _gcry_md_read (hd, algo);
90 :
91 0 : if ( memcmp (digest, expect, expectlen) )
92 0 : result = "digest mismatch";
93 : }
94 : else
95 : {
96 0 : gcry_assert(expectlen <= sizeof(aaa));
97 :
98 0 : err = _gcry_md_extract (hd, algo, aaa, expectlen);
99 0 : if (err)
100 0 : result = "error extracting output from XOF";
101 0 : else if ( memcmp (aaa, expect, expectlen) )
102 0 : result = "digest mismatch";
103 : }
104 : }
105 :
106 0 : _gcry_md_close (hd);
107 :
108 0 : return result;
109 : }
110 :
111 :
112 : /* Common function to write a chunk of data to the transform function
113 : of a hash algorithm. Note that the use of the term "block" does
114 : not imply a fixed size block. Note that we explicitly allow to use
115 : this function after the context has been finalized; the result does
116 : not have any meaning but writing after finalize is sometimes
117 : helpful to mitigate timing attacks. */
118 : void
119 0 : _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
120 : {
121 0 : const unsigned char *inbuf = inbuf_arg;
122 0 : gcry_md_block_ctx_t *hd = context;
123 0 : unsigned int stack_burn = 0;
124 0 : const unsigned int blocksize = hd->blocksize;
125 : size_t inblocks;
126 :
127 0 : if (sizeof(hd->buf) < blocksize)
128 0 : BUG();
129 :
130 0 : if (!hd->bwrite)
131 0 : return;
132 :
133 0 : if (hd->count == blocksize) /* Flush the buffer. */
134 : {
135 0 : stack_burn = hd->bwrite (hd, hd->buf, 1);
136 0 : _gcry_burn_stack (stack_burn);
137 0 : stack_burn = 0;
138 0 : hd->count = 0;
139 0 : if (!++hd->nblocks)
140 0 : hd->nblocks_high++;
141 : }
142 0 : if (!inbuf)
143 0 : return;
144 :
145 0 : if (hd->count)
146 : {
147 0 : for (; inlen && hd->count < blocksize; inlen--)
148 0 : hd->buf[hd->count++] = *inbuf++;
149 0 : _gcry_md_block_write (hd, NULL, 0);
150 0 : if (!inlen)
151 0 : return;
152 : }
153 :
154 0 : if (inlen >= blocksize)
155 : {
156 0 : inblocks = inlen / blocksize;
157 0 : stack_burn = hd->bwrite (hd, inbuf, inblocks);
158 0 : hd->count = 0;
159 0 : hd->nblocks_high += (hd->nblocks + inblocks < inblocks);
160 0 : hd->nblocks += inblocks;
161 0 : inlen -= inblocks * blocksize;
162 0 : inbuf += inblocks * blocksize;
163 : }
164 0 : _gcry_burn_stack (stack_burn);
165 0 : for (; inlen && hd->count < blocksize; inlen--)
166 0 : hd->buf[hd->count++] = *inbuf++;
167 : }
|