blob: 16ef1ca295a5663aa25c38203f01a88ef3620973 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelleyad9c6f02017-10-27 22:13:49 +01002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_DNSSEC
20
21#include <nettle/rsa.h>
22#include <nettle/dsa.h>
23#ifndef NO_NETTLE_ECC
24# include <nettle/ecdsa.h>
25# include <nettle/ecc-curve.h>
26# include <nettle/eddsa.h>
27#endif
28#include <nettle/nettle-meta.h>
29#include <nettle/bignum.h>
30
31/* Nettle-3.0 moved to a new API for DSA. We use a name that's defined in the new API
32 to detect Nettle-3, and invoke the backwards compatibility mode. */
33#ifdef dsa_params_init
34#include <nettle/dsa-compat.h>
35#endif
36
37/* Implement a "hash-function" to the nettle API, which simply returns
38 the input data, concatenated into a single, statically maintained, buffer.
39
40 Used for the EdDSA sigs, which operate on the whole message, rather
41 than a digest. */
42
43struct null_hash_digest
44{
45 uint8_t *buff;
46 size_t len;
47};
48
49struct null_hash_ctx
50{
51 size_t len;
52};
53
54static size_t null_hash_buff_sz = 0;
55static uint8_t *null_hash_buff = NULL;
56#define BUFF_INCR 128
57
58static void null_hash_init(void *ctx)
59{
60 ((struct null_hash_ctx *)ctx)->len = 0;
61}
62
63static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
64{
65 struct null_hash_ctx *ctx = ctxv;
66 size_t new_len = ctx->len + length;
67
68 if (new_len > null_hash_buff_sz)
69 {
70 uint8_t *new;
71
72 if (!(new = whine_malloc(new_len + BUFF_INCR)))
73 return;
74
75 if (null_hash_buff)
76 {
77 if (ctx->len != 0)
78 memcpy(new, null_hash_buff, ctx->len);
79 free(null_hash_buff);
80 }
81
82 null_hash_buff_sz = new_len + BUFF_INCR;
83 null_hash_buff = new;
84 }
85
86 memcpy(null_hash_buff + ctx->len, src, length);
87 ctx->len += length;
88}
89
90
91static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
92{
93 (void)length;
94
95 ((struct null_hash_digest *)dst)->buff = null_hash_buff;
96 ((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
97}
98
99static struct nettle_hash null_hash = {
100 "null_hash",
101 sizeof(struct null_hash_ctx),
102 sizeof(struct null_hash_digest),
103 0,
104 (nettle_hash_init_func *) null_hash_init,
105 (nettle_hash_update_func *) null_hash_update,
106 (nettle_hash_digest_func *) null_hash_digest
107};
108
109/* Find pointer to correct hash function in nettle library */
110const struct nettle_hash *hash_find(char *name)
111{
112 int i;
113
114 if (!name)
115 return NULL;
116
117 for (i = 0; nettle_hashes[i]; i++)
118 {
119 if (strcmp(nettle_hashes[i]->name, name) == 0)
120 return nettle_hashes[i];
121 }
122
123 /* We provide a "null" hash which returns the input data as digest. */
124 if (strcmp(null_hash.name, name) == 0)
125 return &null_hash;
126
127 return NULL;
128}
129
130/* expand ctx and digest memory allocations if necessary and init hash function */
131int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
132{
133 static void *ctx = NULL;
134 static unsigned char *digest = NULL;
135 static unsigned int ctx_sz = 0;
136 static unsigned int digest_sz = 0;
137
138 void *new;
139
140 if (ctx_sz < hash->context_size)
141 {
142 if (!(new = whine_malloc(hash->context_size)))
143 return 0;
144 if (ctx)
145 free(ctx);
146 ctx = new;
147 ctx_sz = hash->context_size;
148 }
149
150 if (digest_sz < hash->digest_size)
151 {
152 if (!(new = whine_malloc(hash->digest_size)))
153 return 0;
154 if (digest)
155 free(digest);
156 digest = new;
157 digest_sz = hash->digest_size;
158 }
159
160 *ctxp = ctx;
161 *digestp = digest;
162
163 hash->init(ctx);
164
165 return 1;
166}
167
168static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
169 unsigned char *digest, size_t digest_len, int algo)
170{
171 unsigned char *p;
172 size_t exp_len;
173
174 static struct rsa_public_key *key = NULL;
175 static mpz_t sig_mpz;
176
177 (void)digest_len;
178
179 if (key == NULL)
180 {
181 if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
182 return 0;
183
184 nettle_rsa_public_key_init(key);
185 mpz_init(sig_mpz);
186 }
187
188 if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
189 return 0;
190
191 key_len--;
192 if ((exp_len = *p++) == 0)
193 {
194 GETSHORT(exp_len, p);
195 key_len -= 2;
196 }
197
198 if (exp_len >= key_len)
199 return 0;
200
201 key->size = key_len - exp_len;
202 mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
203 mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
204
205 mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
206
207 switch (algo)
208 {
209 case 1:
210 return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
211 case 5: case 7:
212 return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
213 case 8:
214 return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
215 case 10:
216 return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
217 }
218
219 return 0;
220}
221
222static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
223 unsigned char *digest, size_t digest_len, int algo)
224{
225 unsigned char *p;
226 unsigned int t;
227
228 static struct dsa_public_key *key = NULL;
229 static struct dsa_signature *sig_struct;
230
231 (void)digest_len;
232
233 if (key == NULL)
234 {
235 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
236 !(key = whine_malloc(sizeof(struct dsa_public_key))))
237 return 0;
238
239 nettle_dsa_public_key_init(key);
240 nettle_dsa_signature_init(sig_struct);
241 }
242
243 if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
244 return 0;
245
246 t = *p++;
247
248 if (key_len < (213 + (t * 24)))
249 return 0;
250
251 mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
252 mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
253 mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
254 mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
255
256 mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
257 mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
258
259 (void)algo;
260
261 return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
262}
263
264#ifndef NO_NETTLE_ECC
265static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
266 unsigned char *sig, size_t sig_len,
267 unsigned char *digest, size_t digest_len, int algo)
268{
269 unsigned char *p;
270 unsigned int t;
271 struct ecc_point *key;
272
273 static struct ecc_point *key_256 = NULL, *key_384 = NULL;
274 static mpz_t x, y;
275 static struct dsa_signature *sig_struct;
276
277 if (!sig_struct)
278 {
279 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
280 return 0;
281
282 nettle_dsa_signature_init(sig_struct);
283 mpz_init(x);
284 mpz_init(y);
285 }
286
287 switch (algo)
288 {
289 case 13:
290 if (!key_256)
291 {
292 if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
293 return 0;
294
295 nettle_ecc_point_init(key_256, &nettle_secp_256r1);
296 }
297
298 key = key_256;
299 t = 32;
300 break;
301
302 case 14:
303 if (!key_384)
304 {
305 if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
306 return 0;
307
308 nettle_ecc_point_init(key_384, &nettle_secp_384r1);
309 }
310
311 key = key_384;
312 t = 48;
313 break;
314
315 default:
316 return 0;
317 }
318
319 if (sig_len != 2*t || key_len != 2*t ||
320 !(p = blockdata_retrieve(key_data, key_len, NULL)))
321 return 0;
322
323 mpz_import(x, t , 1, 1, 0, 0, p);
324 mpz_import(y, t , 1, 1, 0, 0, p + t);
325
326 if (!ecc_point_set(key, x, y))
327 return 0;
328
329 mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
330 mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
331
332 return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
333}
334
335static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
336 unsigned char *sig, size_t sig_len,
337 unsigned char *digest, size_t digest_len, int algo)
338{
339 unsigned char *p;
340
341 if (key_len != ED25519_KEY_SIZE ||
342 sig_len != ED25519_SIGNATURE_SIZE ||
343 digest_len != sizeof(struct null_hash_digest) ||
344 !(p = blockdata_retrieve(key_data, key_len, NULL)))
345 return 0;
346
347 /* The "digest" returned by the null_hash function is simply a struct null_hash_digest
348 which has a pointer to the actual data and a length, because the buffer
349 may need to be extended during "hashing". */
350
351 switch (algo)
352 {
353 case 15:
354 return ed25519_sha512_verify(p,
355 ((struct null_hash_digest *)digest)->len,
356 ((struct null_hash_digest *)digest)->buff,
357 sig);
358 case 16:
359 /* Ed448 when available */
360 return 0;
361 }
362
363 return 0;
364}
365
366#endif
367
Simon Kelleyb77efc12017-10-27 23:23:53 +0100368static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
Simon Kelleyad9c6f02017-10-27 22:13:49 +0100369 unsigned char *digest, size_t digest_len, int algo)
370{
371
372 /* Enure at runtime that we have support for this digest */
373 if (!hash_find(algo_digest_name(algo)))
374 return NULL;
375
376 /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
377 switch (algo)
378 {
379 case 1: case 5: case 7: case 8: case 10:
380 return dnsmasq_rsa_verify;
381
382 case 3: case 6:
383 return dnsmasq_dsa_verify;
384
385#ifndef NO_NETTLE_ECC
386 case 13: case 14:
387 return dnsmasq_ecdsa_verify;
388
389 case 15: case 16:
390 return dnsmasq_eddsa_verify;
391#endif
392 }
393
394 return NULL;
395}
396
397int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
398 unsigned char *digest, size_t digest_len, int algo)
399{
400
401 int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
402 unsigned char *digest, size_t digest_len, int algo);
403
404 func = verify_func(algo);
405
406 if (!func)
407 return 0;
408
409 return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
410}
411
Simon Kelleyb77efc12017-10-27 23:23:53 +0100412/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
413 define which algo numbers we support. If algo_digest_name() returns
Simon Kelley0954a972017-10-27 23:26:51 +0100414 non-NULL for an algorithm number, we assume that algorithm is
Simon Kelleyb77efc12017-10-27 23:23:53 +0100415 supported by verify(). */
416
Simon Kelleyad9c6f02017-10-27 22:13:49 +0100417/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
418char *ds_digest_name(int digest)
419{
420 switch (digest)
421 {
422 case 1: return "sha1";
423 case 2: return "sha256";
424 case 3: return "gosthash94";
425 case 4: return "sha384";
426 default: return NULL;
427 }
428}
429
430/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
431char *algo_digest_name(int algo)
432{
433 switch (algo)
434 {
Simon Kelley0954a972017-10-27 23:26:51 +0100435 case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
Simon Kelleyb77efc12017-10-27 23:23:53 +0100436 case 2: return NULL; /* Diffie-Hellman */
437 case 3: return "sha1"; /* DSA/SHA1 */
438 case 5: return "sha1"; /* RSA/SHA1 */
439 case 6: return "sha1"; /* DSA-NSEC3-SHA1 */
440 case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
441 case 8: return "sha256"; /* RSA/SHA-256 */
442 case 10: return "sha512"; /* RSA/SHA-512 */
443 case 12: return NULL; /* ECC-GOST */
444 case 13: return "sha256"; /* ECDSAP256SHA256 */
445 case 14: return "sha384"; /* ECDSAP384SHA384 */
446 case 15: return "null_hash"; /* ED25519 */
447 case 16: return NULL; /* ED448 */
Simon Kelleyad9c6f02017-10-27 22:13:49 +0100448 default: return NULL;
449 }
450}
451
452/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
453char *nsec3_digest_name(int digest)
454{
455 switch (digest)
456 {
457 case 1: return "sha1";
458 default: return NULL;
459 }
460}
461
462#endif