Annotation of embedaddon/dnsmasq/src/crypto.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1.1 misho 2:
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:
1.1.1.2 ! misho 19: #if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
! 20:
! 21: /* Minimal version of nettle */
! 22:
! 23: /* bignum.h includes version.h and works on
! 24: earlier releases of nettle which don't have version.h */
! 25: #include <nettle/bignum.h>
! 26: #if !defined(NETTLE_VERSION_MAJOR)
! 27: # define NETTLE_VERSION_MAJOR 2
! 28: # define NETTLE_VERSION_MINOR 0
! 29: #endif
! 30: #define MIN_VERSION(major, minor) ((NETTLE_VERSION_MAJOR == (major) && NETTLE_VERSION_MINOR >= (minor)) || \
! 31: (NETTLE_VERSION_MAJOR > (major)))
1.1 misho 32:
1.1.1.2 ! misho 33: #endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
! 34:
! 35: #if defined(HAVE_DNSSEC)
1.1 misho 36: #include <nettle/rsa.h>
37: #include <nettle/ecdsa.h>
38: #include <nettle/ecc-curve.h>
1.1.1.2 ! misho 39: #if MIN_VERSION(3, 1)
1.1 misho 40: #include <nettle/eddsa.h>
41: #endif
1.1.1.2 ! misho 42: #if MIN_VERSION(3, 6)
! 43: # include <nettle/gostdsa.h>
1.1 misho 44: #endif
45:
1.1.1.2 ! misho 46: #if MIN_VERSION(3, 1)
1.1 misho 47: /* Implement a "hash-function" to the nettle API, which simply returns
48: the input data, concatenated into a single, statically maintained, buffer.
49:
50: Used for the EdDSA sigs, which operate on the whole message, rather
51: than a digest. */
52:
53: struct null_hash_digest
54: {
55: uint8_t *buff;
56: size_t len;
57: };
58:
59: struct null_hash_ctx
60: {
61: size_t len;
62: };
63:
64: static size_t null_hash_buff_sz = 0;
65: static uint8_t *null_hash_buff = NULL;
66: #define BUFF_INCR 128
67:
68: static void null_hash_init(void *ctx)
69: {
70: ((struct null_hash_ctx *)ctx)->len = 0;
71: }
72:
73: static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
74: {
75: struct null_hash_ctx *ctx = ctxv;
76: size_t new_len = ctx->len + length;
77:
78: if (new_len > null_hash_buff_sz)
79: {
80: uint8_t *new;
81:
82: if (!(new = whine_malloc(new_len + BUFF_INCR)))
83: return;
84:
85: if (null_hash_buff)
86: {
87: if (ctx->len != 0)
88: memcpy(new, null_hash_buff, ctx->len);
89: free(null_hash_buff);
90: }
91:
92: null_hash_buff_sz = new_len + BUFF_INCR;
93: null_hash_buff = new;
94: }
95:
96: memcpy(null_hash_buff + ctx->len, src, length);
97: ctx->len += length;
98: }
99:
100: static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
101: {
102: (void)length;
103:
104: ((struct null_hash_digest *)dst)->buff = null_hash_buff;
105: ((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
106: }
107:
108: static struct nettle_hash null_hash = {
109: "null_hash",
110: sizeof(struct null_hash_ctx),
111: sizeof(struct null_hash_digest),
112: 0,
113: (nettle_hash_init_func *) null_hash_init,
114: (nettle_hash_update_func *) null_hash_update,
115: (nettle_hash_digest_func *) null_hash_digest
116: };
117:
1.1.1.2 ! misho 118: #endif /* MIN_VERSION(3, 1) */
1.1 misho 119:
120: /* expand ctx and digest memory allocations if necessary and init hash function */
121: int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
122: {
123: static void *ctx = NULL;
124: static unsigned char *digest = NULL;
125: static unsigned int ctx_sz = 0;
126: static unsigned int digest_sz = 0;
127:
128: void *new;
129:
130: if (ctx_sz < hash->context_size)
131: {
132: if (!(new = whine_malloc(hash->context_size)))
133: return 0;
134: if (ctx)
135: free(ctx);
136: ctx = new;
137: ctx_sz = hash->context_size;
138: }
139:
140: if (digest_sz < hash->digest_size)
141: {
142: if (!(new = whine_malloc(hash->digest_size)))
143: return 0;
144: if (digest)
145: free(digest);
146: digest = new;
147: digest_sz = hash->digest_size;
148: }
149:
150: *ctxp = ctx;
151: *digestp = digest;
152:
153: hash->init(ctx);
154:
155: return 1;
156: }
157:
158: static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
159: unsigned char *digest, size_t digest_len, int algo)
160: {
161: unsigned char *p;
162: size_t exp_len;
163:
164: static struct rsa_public_key *key = NULL;
165: static mpz_t sig_mpz;
166:
167: (void)digest_len;
168:
169: if (key == NULL)
170: {
171: if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
172: return 0;
173:
174: nettle_rsa_public_key_init(key);
175: mpz_init(sig_mpz);
176: }
177:
178: if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
179: return 0;
180:
181: key_len--;
182: if ((exp_len = *p++) == 0)
183: {
184: GETSHORT(exp_len, p);
185: key_len -= 2;
186: }
187:
188: if (exp_len >= key_len)
189: return 0;
190:
191: key->size = key_len - exp_len;
192: mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
193: mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
194:
195: mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
196:
197: switch (algo)
198: {
199: case 5: case 7:
200: return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
201: case 8:
202: return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
203: case 10:
204: return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
205: }
206:
207: return 0;
208: }
209:
210: static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
211: unsigned char *sig, size_t sig_len,
212: unsigned char *digest, size_t digest_len, int algo)
213: {
214: unsigned char *p;
215: unsigned int t;
216: struct ecc_point *key;
217:
218: static struct ecc_point *key_256 = NULL, *key_384 = NULL;
219: static mpz_t x, y;
220: static struct dsa_signature *sig_struct;
1.1.1.2 ! misho 221: #if !MIN_VERSION(3, 4)
1.1 misho 222: #define nettle_get_secp_256r1() (&nettle_secp_256r1)
223: #define nettle_get_secp_384r1() (&nettle_secp_384r1)
224: #endif
225:
226: if (!sig_struct)
227: {
228: if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
229: return 0;
230:
231: nettle_dsa_signature_init(sig_struct);
232: mpz_init(x);
233: mpz_init(y);
234: }
235:
236: switch (algo)
237: {
238: case 13:
239: if (!key_256)
240: {
241: if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
242: return 0;
243:
244: nettle_ecc_point_init(key_256, nettle_get_secp_256r1());
245: }
246:
247: key = key_256;
248: t = 32;
249: break;
250:
251: case 14:
252: if (!key_384)
253: {
254: if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
255: return 0;
256:
257: nettle_ecc_point_init(key_384, nettle_get_secp_384r1());
258: }
259:
260: key = key_384;
261: t = 48;
262: break;
263:
264: default:
265: return 0;
266: }
267:
268: if (sig_len != 2*t || key_len != 2*t ||
269: !(p = blockdata_retrieve(key_data, key_len, NULL)))
270: return 0;
271:
272: mpz_import(x, t , 1, 1, 0, 0, p);
273: mpz_import(y, t , 1, 1, 0, 0, p + t);
274:
275: if (!ecc_point_set(key, x, y))
276: return 0;
277:
278: mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
279: mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
280:
281: return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
282: }
283:
1.1.1.2 ! misho 284: #if MIN_VERSION(3, 6)
1.1 misho 285: static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_len,
286: unsigned char *sig, size_t sig_len,
287: unsigned char *digest, size_t digest_len, int algo)
288: {
289: unsigned char *p;
290:
291: static struct ecc_point *gost_key = NULL;
292: static mpz_t x, y;
293: static struct dsa_signature *sig_struct;
294:
295: if (algo != 12 ||
296: sig_len != 64 || key_len != 64 ||
297: !(p = blockdata_retrieve(key_data, key_len, NULL)))
298: return 0;
299:
300: if (!sig_struct)
301: {
302: if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
303: !(gost_key = whine_malloc(sizeof(struct ecc_point))))
304: return 0;
305:
306: nettle_dsa_signature_init(sig_struct);
307: nettle_ecc_point_init(gost_key, nettle_get_gost_gc256b());
308: mpz_init(x);
309: mpz_init(y);
310: }
311:
1.1.1.2 ! misho 312: mpz_import(x, 32, -1, 1, 0, 0, p);
! 313: mpz_import(y, 32, -1, 1, 0, 0, p + 32);
1.1 misho 314:
315: if (!ecc_point_set(gost_key, x, y))
1.1.1.2 ! misho 316: return 0;
1.1 misho 317:
1.1.1.2 ! misho 318: mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig);
! 319: mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig + 32);
1.1 misho 320:
321: return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
322: }
323: #endif
324:
1.1.1.2 ! misho 325: #if MIN_VERSION(3, 1)
1.1 misho 326: static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
327: unsigned char *sig, size_t sig_len,
328: unsigned char *digest, size_t digest_len, int algo)
329: {
330: unsigned char *p;
331:
332: if (digest_len != sizeof(struct null_hash_digest) ||
333: !(p = blockdata_retrieve(key_data, key_len, NULL)))
334: return 0;
335:
336: /* The "digest" returned by the null_hash function is simply a struct null_hash_digest
337: which has a pointer to the actual data and a length, because the buffer
338: may need to be extended during "hashing". */
339:
340: switch (algo)
341: {
342: case 15:
343: if (key_len != ED25519_KEY_SIZE ||
344: sig_len != ED25519_SIGNATURE_SIZE)
345: return 0;
346:
347: return ed25519_sha512_verify(p,
348: ((struct null_hash_digest *)digest)->len,
349: ((struct null_hash_digest *)digest)->buff,
350: sig);
351:
1.1.1.2 ! misho 352: #if MIN_VERSION(3, 6)
1.1 misho 353: case 16:
354: if (key_len != ED448_KEY_SIZE ||
355: sig_len != ED448_SIGNATURE_SIZE)
356: return 0;
357:
358: return ed448_shake256_verify(p,
359: ((struct null_hash_digest *)digest)->len,
360: ((struct null_hash_digest *)digest)->buff,
361: sig);
362: #endif
363:
364: }
365:
366: return 0;
367: }
1.1.1.2 ! misho 368: #endif
1.1 misho 369:
370: static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
371: unsigned char *digest, size_t digest_len, int algo)
372: {
373:
374: /* Ensure at runtime that we have support for this digest */
375: if (!hash_find(algo_digest_name(algo)))
376: return NULL;
377:
378: /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
379: switch (algo)
380: {
381: case 5: case 7: case 8: case 10:
382: return dnsmasq_rsa_verify;
383:
1.1.1.2 ! misho 384: #if MIN_VERSION(3, 6)
1.1 misho 385: case 12:
386: return dnsmasq_gostdsa_verify;
387: #endif
388:
389: case 13: case 14:
390: return dnsmasq_ecdsa_verify;
1.1.1.2 ! misho 391:
! 392: #if MIN_VERSION(3, 1)
! 393: case 15:
! 394: return dnsmasq_eddsa_verify;
! 395: #endif
1.1 misho 396:
1.1.1.2 ! misho 397: #if MIN_VERSION(3, 6)
! 398: case 16:
1.1 misho 399: return dnsmasq_eddsa_verify;
1.1.1.2 ! misho 400: #endif
1.1 misho 401: }
402:
403: return NULL;
404: }
405:
406: int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
407: unsigned char *digest, size_t digest_len, int algo)
408: {
409:
410: int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
411: unsigned char *digest, size_t digest_len, int algo);
412:
413: func = verify_func(algo);
414:
415: if (!func)
416: return 0;
417:
418: return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
419: }
420:
421: /* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
422: define which algo numbers we support. If algo_digest_name() returns
423: non-NULL for an algorithm number, we assume that algorithm is
424: supported by verify(). */
425:
426: /* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
427: char *ds_digest_name(int digest)
428: {
429: switch (digest)
430: {
431: case 1: return "sha1";
432: case 2: return "sha256";
1.1.1.2 ! misho 433: #if MIN_VERSION(3, 6)
! 434: case 3: return "gosthash94cp";
! 435: #endif
1.1 misho 436: case 4: return "sha384";
437: default: return NULL;
438: }
439: }
440:
441: /* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
442: char *algo_digest_name(int algo)
443: {
444: switch (algo)
445: {
446: case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
447: case 2: return NULL; /* Diffie-Hellman */
448: case 3: return NULL; ; /* DSA/SHA1 - Must Not Implement. RFC 8624 section 3.1 */
449: case 5: return "sha1"; /* RSA/SHA1 */
450: case 6: return NULL; /* DSA-NSEC3-SHA1 - Must Not Implement. RFC 8624 section 3.1 */
451: case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
452: case 8: return "sha256"; /* RSA/SHA-256 */
453: case 10: return "sha512"; /* RSA/SHA-512 */
1.1.1.2 ! misho 454: #if MIN_VERSION(3, 6)
! 455: case 12: return "gosthash94cp"; /* ECC-GOST */
! 456: #endif
1.1 misho 457: case 13: return "sha256"; /* ECDSAP256SHA256 */
458: case 14: return "sha384"; /* ECDSAP384SHA384 */
1.1.1.2 ! misho 459: #if MIN_VERSION(3, 1)
1.1 misho 460: case 15: return "null_hash"; /* ED25519 */
1.1.1.2 ! misho 461: # if MIN_VERSION(3, 6)
1.1 misho 462: case 16: return "null_hash"; /* ED448 */
1.1.1.2 ! misho 463: # endif
! 464: #endif
1.1 misho 465: default: return NULL;
466: }
467: }
468:
469: /* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
470: char *nsec3_digest_name(int digest)
471: {
472: switch (digest)
473: {
474: case 1: return "sha1";
475: default: return NULL;
476: }
477: }
478:
1.1.1.2 ! misho 479: #endif /* defined(HAVE_DNSSEC) */
! 480:
! 481: #if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
! 482: /* Find pointer to correct hash function in nettle library */
! 483: const struct nettle_hash *hash_find(char *name)
! 484: {
! 485: if (!name)
! 486: return NULL;
! 487:
! 488: #if MIN_VERSION(3,1) && defined(HAVE_DNSSEC)
! 489: /* We provide a "null" hash which returns the input data as digest. */
! 490: if (strcmp(null_hash.name, name) == 0)
! 491: return &null_hash;
! 492: #endif
! 493:
! 494: /* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
! 495: incompatibilities if sizeof(nettle_hashes) changes between library
! 496: versions. */
! 497: #if MIN_VERSION(3, 4)
! 498: return nettle_lookup_hash(name);
! 499: #else
! 500: {
! 501: int i;
! 502:
! 503: for (i = 0; nettle_hashes[i]; i++)
! 504: if (strcmp(nettle_hashes[i]->name, name) == 0)
! 505: return nettle_hashes[i];
! 506: }
! 507:
! 508: return NULL;
1.1 misho 509: #endif
1.1.1.2 ! misho 510: }
! 511:
! 512: #endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>