Greenbone Vulnerability Management Libraries 22.32.0
streamvalidator.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6#include "streamvalidator.h"
7
8#include "authutils.h"
9
10#include <assert.h>
11#include <gcrypt.h>
12#include <glib.h>
13#include <stdint.h>
14#include <string.h>
15
20
34
43const char *
45{
46 switch (value)
47 {
49 return "internal error";
51 return NULL;
53 return "too short";
55 return "too long";
57 return "invalid hash syntax";
59 return "invalid or unsupported hash algorithm";
61 return "invalid hash value";
63 return "hash does not match";
64 default:
65 return "unknown error";
66 }
67}
68
87gvm_stream_validator_new (const char *expected_hash_str,
88 gvm_stream_validator_t *validator_out)
89{
91 expected_hash_str, GVM_STREAM_VALIDATOR_NO_SIZE, validator_out);
92}
93
117gvm_stream_validator_with_size_new (const char *expected_hash_str,
118 size_t expected_size,
119 gvm_stream_validator_t *validator_out)
120{
121 assert (validator_out);
122
123 static GRegex *hex_regex = NULL;
124 gchar **parts = NULL;
125 const char *algo_str = NULL;
126 const char *hex_str = NULL;
127 int algo;
128 unsigned int expected_hex_len;
129 gcry_md_hd_t gcrypt_md_hd;
130 gboolean size_enforced = FALSE;
131 size_t final_expected_size = 0;
132
133 if (expected_hash_str == NULL)
135
136 if (hex_regex == NULL)
137 hex_regex = g_regex_new ("^(?:[0-9A-Fa-f][0-9A-Fa-f])+$", 0, 0, NULL);
138
139 *validator_out = NULL;
140
141 parts = g_strsplit (expected_hash_str, ":", 2);
142 guint n = g_strv_length (parts);
143 if (n != 2)
144 {
145 g_strfreev (parts);
147 }
148 algo_str = parts[0];
149 hex_str = parts[1];
150
151 if (expected_size != GVM_STREAM_VALIDATOR_NO_SIZE)
152 {
153 final_expected_size = expected_size;
154 size_enforced = TRUE;
155 }
156 else
157 {
158 final_expected_size = 0;
159 size_enforced = FALSE;
160 }
161
162 algo = gcry_md_map_name (algo_str);
163 if (algo == GCRY_MD_NONE || gcry_md_test_algo (algo))
164 {
165 g_strfreev (parts);
167 }
168
169 expected_hex_len = gcry_md_get_algo_dlen (algo) * 2;
170 if (strlen (hex_str) != expected_hex_len
171 || g_regex_match (hex_regex, hex_str, 0, NULL) == FALSE)
172 {
173 g_strfreev (parts);
175 }
176
177 gcrypt_md_hd = NULL;
178 if (gcry_md_open (&gcrypt_md_hd, algo, 0))
179 {
180 g_strfreev (parts);
182 }
183
184 *validator_out = g_malloc0 (sizeof (struct gvm_stream_validator));
185 (*validator_out)->algorithm = algo;
186 (*validator_out)->expected_size = final_expected_size;
187 (*validator_out)->size_enforced = size_enforced;
188 (*validator_out)->expected_hash_str = g_strdup (expected_hash_str);
189 (*validator_out)->expected_hash_hex = g_strdup (hex_str);
190 (*validator_out)->gcrypt_md_hd = gcrypt_md_hd;
191 (*validator_out)->current_size = 0;
192
193 g_strfreev (parts);
195}
196
203void
205{
206 gcry_md_reset (validator->gcrypt_md_hd);
207 validator->current_size = 0;
208}
209
215void
217{
218 gcry_md_close (validator->gcrypt_md_hd);
219 g_free (validator->expected_hash_str);
220 g_free (validator->expected_hash_hex);
221 g_free (validator);
222}
223
237 size_t length)
238{
239 if (validator->size_enforced)
240 {
241 if (length > validator->expected_size - validator->current_size)
243 }
244
245 gcry_md_write (validator->gcrypt_md_hd, data, length);
246 validator->current_size += length;
247
249}
250
261{
262 unsigned char *actual_hash_bin;
263 gchar *actual_hash_hex;
264
265 if (validator->size_enforced)
266 {
267 if (validator->current_size < validator->expected_size)
269
270 if (validator->current_size > validator->expected_size)
272 }
273
274 actual_hash_bin =
275 gcry_md_read (validator->gcrypt_md_hd, validator->algorithm);
276 actual_hash_hex = digest_hex (validator->algorithm, actual_hash_bin);
277 if (strcasecmp (validator->expected_hash_hex, actual_hash_hex))
278 {
279 g_free (actual_hash_hex);
281 }
282 g_free (actual_hash_hex);
283
285}
gchar * digest_hex(int gcrypt_algorithm, const guchar *digest)
Generate a hexadecimal representation of a message digest.
Definition authutils.c:175
Authentication mechanism(s).
void gvm_stream_validator_rewind(gvm_stream_validator_t validator)
Rewind the validation state of a stream validator while keeping the expected hash and data size.
void gvm_stream_validator_free(gvm_stream_validator_t validator)
Free a stream validator and all of its fields.
gvm_stream_validator_return_t gvm_stream_validator_new(const char *expected_hash_str, gvm_stream_validator_t *validator_out)
Allocate and initialize a checksum-only stream validator.
const char * gvm_stream_validator_return_str(gvm_stream_validator_return_t value)
Gets a string representation of a gvm_stream_validator_return_t.
gvm_stream_validator_return_t gvm_stream_validator_with_size_new(const char *expected_hash_str, size_t expected_size, gvm_stream_validator_t *validator_out)
Allocate and initialize a new data stream validator.
gvm_stream_validator_return_t gvm_stream_validator_write(gvm_stream_validator_t validator, const char *data, size_t length)
Write data to a validator, updating the hash state and current size.
gvm_stream_validator_return_t gvm_stream_validator_end(gvm_stream_validator_t validator)
Signal the end of data input into a validator and produce the result of the validation.
Data stream validation headers.
#define GVM_STREAM_VALIDATOR_NO_SIZE
struct gvm_stream_validator * gvm_stream_validator_t
Pointer to an opaque stream validator data structure.
gvm_stream_validator_return_t
@ GVM_STREAM_VALIDATOR_INVALID_HASH_ALGORITHM
@ GVM_STREAM_VALIDATOR_HASH_MISMATCH
@ GVM_STREAM_VALIDATOR_DATA_TOO_SHORT
@ GVM_STREAM_VALIDATOR_DATA_TOO_LONG
@ GVM_STREAM_VALIDATOR_INTERNAL_ERROR
@ GVM_STREAM_VALIDATOR_OK
@ GVM_STREAM_VALIDATOR_INVALID_HASH_SYNTAX
@ GVM_STREAM_VALIDATOR_INVALID_HASH_VALUE
Data stream validator structure.
int algorithm
The hash algorithm used.
gchar * expected_hash_hex
Expected hash value as hexadecimal string.
size_t current_size
Current total amount of data received.
gcry_md_hd_t gcrypt_md_hd
gcrypt message digest handle.
gboolean size_enforced
TRUE enforce size checks; FALSE hash-only.
gchar * expected_hash_str
Expected hash algorithm and hex string.
size_t expected_size
Expected amount of data to validate.